Compare commits
122 Commits
2.1.0-beta
...
2.1.7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
809e8ef45b | ||
|
|
0a091a99e8 | ||
|
|
e299fbe665 | ||
|
|
67e8b622d8 | ||
|
|
ce509273d4 | ||
|
|
bcf588a2e4 | ||
|
|
f08d540e66 | ||
|
|
e06db3d8c5 | ||
|
|
c5c04ebe9c | ||
|
|
c9faa38f6c | ||
|
|
c188f047dc | ||
|
|
775d50306c | ||
|
|
3821144c3b | ||
|
|
a1da70c221 | ||
|
|
bb2db0fed0 | ||
|
|
9680f24640 | ||
|
|
c732fbd81b | ||
|
|
7980b8d14d | ||
|
|
13e88f5b47 | ||
|
|
031596301b | ||
|
|
b34ab45746 | ||
|
|
dbf83c6f24 | ||
|
|
4cb974839c | ||
|
|
1fa714ef2c | ||
|
|
63bbcd4e00 | ||
|
|
49d67d7c27 | ||
|
|
7cc4c9fedb | ||
|
|
afd110a6ed | ||
|
|
7cdf6c8d64 | ||
|
|
60621da243 | ||
|
|
96ccdda304 | ||
|
|
4073984fd7 | ||
|
|
ea31c8a64d | ||
|
|
832ee07e0e | ||
|
|
b542b140c6 | ||
|
|
ac89fc7120 | ||
|
|
150858485d | ||
|
|
e7810e2066 | ||
|
|
4879446567 | ||
|
|
43eff78088 | ||
|
|
55a2ae3801 | ||
|
|
a3b0332d13 | ||
|
|
4b1846883d | ||
|
|
778fd3ba65 | ||
|
|
00456a35e5 | ||
|
|
5958f0516b | ||
|
|
166ffedf04 | ||
|
|
36dfee1263 | ||
|
|
ec0026ecfd | ||
|
|
a721bb3f21 | ||
|
|
83de3dd719 | ||
|
|
5615decd96 | ||
|
|
0348b1ec7e | ||
|
|
1467dab58f | ||
|
|
3a8f48de35 | ||
|
|
46391c06ec | ||
|
|
7103f7dd51 | ||
|
|
9fc1dfee41 | ||
|
|
82dc76fdc6 | ||
|
|
02ae52e3df | ||
|
|
5c06683e27 | ||
|
|
2684372156 | ||
|
|
d80c6d5714 | ||
|
|
1ae5311b81 | ||
|
|
e1e7555cce | ||
|
|
4f79d7cf4b | ||
|
|
b13b1e8ac7 | ||
|
|
6a1e7cc539 | ||
|
|
2e87633ef7 | ||
|
|
8a23d0b72c | ||
|
|
735ef85088 | ||
|
|
75cf44a6d2 | ||
|
|
7e0073f4a3 | ||
|
|
c9291df345 | ||
|
|
fd5e97d48c | ||
|
|
64a9fb163a | ||
|
|
b0256ffb7d | ||
|
|
e606bdc97f | ||
|
|
b53b3a924a | ||
|
|
539ea7c8fc | ||
|
|
5e8763e160 | ||
|
|
d52f33a50c | ||
|
|
287ad84b18 | ||
|
|
3f1b792f60 | ||
|
|
d94317421d | ||
|
|
7717a82d5c | ||
|
|
ace1651ceb | ||
|
|
1f74bf059c | ||
|
|
c98e912fc5 | ||
|
|
d04a8e7bbf | ||
|
|
d4a940b723 | ||
|
|
0dd20bc29a | ||
|
|
f71ee9f1f2 | ||
|
|
dd61302445 | ||
|
|
0bee1f03de | ||
|
|
a59aaa3dc9 | ||
|
|
1debe9d939 | ||
|
|
3d2e81b457 | ||
|
|
ac759cd9a4 | ||
|
|
05c77929e4 | ||
|
|
cefd9226bd | ||
|
|
762f295d3d | ||
|
|
d3e6063027 | ||
|
|
f18c14e119 | ||
|
|
77bcd10729 | ||
|
|
6ee990af0a | ||
|
|
a3fe37b69b | ||
|
|
56388ede54 | ||
|
|
b98035bf3a | ||
|
|
95abe465ef | ||
|
|
780f607332 | ||
|
|
a11d26522a | ||
|
|
462a798cb6 | ||
|
|
7556685881 | ||
|
|
965e2dfd95 | ||
|
|
1f2cce6195 | ||
|
|
f4f84aa397 | ||
|
|
0f37dfb1eb | ||
|
|
7438786a24 | ||
|
|
041c2d176c | ||
|
|
597e765677 | ||
|
|
f757233d61 |
5
.github/workflows/build-docs.yml
vendored
5
.github/workflows/build-docs.yml
vendored
@@ -2,7 +2,8 @@ name: build-documentation
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [published]
|
# only run for stable releases
|
||||||
|
types: [released]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build_docs:
|
build_docs:
|
||||||
@@ -11,4 +12,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-and-deploy.yml -f type=tags ref=${{github.ref_name}}
|
gh workflow run --repo Froxlor/Documentation build-and-deploy.yml -f type=tags -f ref=${{github.ref_name}}
|
||||||
|
|||||||
108
.github/workflows/build-mariadb.yml
vendored
108
.github/workflows/build-mariadb.yml
vendored
@@ -8,8 +8,8 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
php-versions: ['7.4', '8.1']
|
php-versions: [ '7.4', '8.2' ]
|
||||||
mariadb-version: [10.5, 10.4]
|
mariadb-version: [ 10.11, 10.5 ]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
@@ -49,33 +49,81 @@ jobs:
|
|||||||
- name: Run testing
|
- name: Run testing
|
||||||
run: ant quick-build
|
run: ant quick-build
|
||||||
|
|
||||||
# - name: irc push
|
nightly:
|
||||||
# uses: rectalogic/notify-irc@v1
|
name: Create nightly/testing tarball
|
||||||
# if: github.event_name == 'push'
|
runs-on: ubuntu-latest
|
||||||
# with:
|
needs: froxlor
|
||||||
# channel: "#froxlor"
|
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||||
# server: "irc.libera.chat"
|
|
||||||
# nickname: froxlor-ci
|
|
||||||
# message: |
|
|
||||||
# ${{ github.actor }} pushed ${{ github.event.ref }} ${{ github.event.compare }}
|
|
||||||
# ${{ join(github.event.commits.*.message) }}
|
|
||||||
|
|
||||||
# - name: irc pull request
|
steps:
|
||||||
# uses: rectalogic/notify-irc@v1
|
- name: Checkout
|
||||||
# if: github.event_name == 'pull_request'
|
uses: actions/checkout@v3
|
||||||
# with:
|
|
||||||
# channel: "#froxlor"
|
|
||||||
# server: "irc.libera.chat"
|
|
||||||
# nickname: froxlor-ci
|
|
||||||
# message: |
|
|
||||||
# ${{ github.actor }} opened PR ${{ github.event.pull_request.html_url }}
|
|
||||||
|
|
||||||
# - name: irc tag created
|
- name: Setup PHP with PECL extension
|
||||||
# uses: rectalogic/notify-irc@v1
|
uses: shivammathur/setup-php@v2
|
||||||
# if: github.event_name == 'create' && github.event.ref_type == 'tag'
|
with:
|
||||||
# with:
|
php-version: '7.4'
|
||||||
# channel: "#froxlor"
|
tools: composer:v2
|
||||||
# server: "irc.libera.chat"
|
extensions: mbstring, xml, ctype, pdo_mysql, mysql, curl, json, zip, session, filter, posix, openssl, fileinfo, bcmath, gmp, gnupg
|
||||||
# nickname: froxlor-ci
|
|
||||||
# message: |
|
- name: Install composer dependencies
|
||||||
# ${{ github.actor }} tagged ${{ github.repository }} ${{ github.event.ref }}
|
run: composer install --no-dev
|
||||||
|
|
||||||
|
- name: Install Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: '20.x'
|
||||||
|
|
||||||
|
- name: Install npm dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Build assets
|
||||||
|
run: npm run build
|
||||||
|
working-directory: .
|
||||||
|
|
||||||
|
- name: Setting file/directory permissions
|
||||||
|
run: |
|
||||||
|
find -exec chmod ugo+r,u+w,go-w {} \;
|
||||||
|
find -type f -exec chmod ugo-x {} \;
|
||||||
|
find -type d -exec chmod ugo+x {} \;
|
||||||
|
chmod 0755 bin/froxlor-cli
|
||||||
|
|
||||||
|
- name: Remove vcs and unneeded files
|
||||||
|
run: |
|
||||||
|
rm .gitignore
|
||||||
|
rm .editorconfig
|
||||||
|
rm -rf node_modules
|
||||||
|
rm composer.json
|
||||||
|
rm composer.lock
|
||||||
|
rm package.json
|
||||||
|
rm package-lock.json
|
||||||
|
rm *.xml
|
||||||
|
rm vite.config.js
|
||||||
|
|
||||||
|
- name: Create empty index.html in built assets directory
|
||||||
|
run: |
|
||||||
|
touch templates/Froxlor/build/index.html
|
||||||
|
touch templates/Froxlor/build/assets/index.html
|
||||||
|
|
||||||
|
- name: Set outputs
|
||||||
|
id: vars
|
||||||
|
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Set nightly branding
|
||||||
|
run: |
|
||||||
|
sed -i "s/const BRANDING = '';/const BRANDING = '+nightly.${{steps.vars.outputs.sha_short}}';/" lib/Froxlor/Froxlor.php
|
||||||
|
zip -r froxlor-nightly.${{steps.vars.outputs.sha_short}}.zip . -x "*.git*"
|
||||||
|
sha256sum froxlor-nightly.${{steps.vars.outputs.sha_short}}.zip > froxlor-nightly.${{steps.vars.outputs.sha_short}}.zip.sha256
|
||||||
|
mkdir dist
|
||||||
|
mv froxlor-nightly.${{steps.vars.outputs.sha_short}}.zip dist/
|
||||||
|
mv froxlor-nightly.${{steps.vars.outputs.sha_short}}.zip.sha256 dist/
|
||||||
|
|
||||||
|
- name: Deploy nightly to server
|
||||||
|
uses: easingthemes/ssh-deploy@v3.4.3
|
||||||
|
env:
|
||||||
|
ARGS: "-rltDzvO --chown=${{ secrets.WEB_USER }}:${{ secrets.WEB_USER }}"
|
||||||
|
SOURCE: "dist/"
|
||||||
|
SSH_PRIVATE_KEY: ${{ secrets.SERVER_SSH_KEY }}
|
||||||
|
REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
|
||||||
|
REMOTE_USER: ${{ secrets.REMOTE_USER }}
|
||||||
|
TARGET: "${{ secrets.REMOTE_TARGET }}"
|
||||||
|
|||||||
2
.github/workflows/build-mysql.yml
vendored
2
.github/workflows/build-mysql.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
php-versions: ['7.4', '8.1']
|
php-versions: ['7.4', '8.2']
|
||||||
mysql-version: [8.0, 5.7]
|
mysql-version: [8.0, 5.7]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -22,8 +22,5 @@ fonts/
|
|||||||
templates/*
|
templates/*
|
||||||
!templates/index.html
|
!templates/index.html
|
||||||
!templates/Froxlor/
|
!templates/Froxlor/
|
||||||
templates/Froxlor/assets/mix-manifest.json
|
templates/Froxlor/build/
|
||||||
templates/Froxlor/assets/css/
|
|
||||||
templates/Froxlor/assets/js/
|
|
||||||
templates/Froxlor/assets/webfonts/
|
|
||||||
!templates/misc/
|
!templates/misc/
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -34,19 +34,13 @@ You may find help in the following places:
|
|||||||
|
|
||||||
The froxlor community discord server can be found here: https://discord.froxlor.org
|
The froxlor community discord server can be found here: https://discord.froxlor.org
|
||||||
|
|
||||||
### IRC
|
|
||||||
|
|
||||||
froxlor may be found on libera.chat, channel #froxlor:
|
|
||||||
irc://irc.libera.chat/froxlor
|
|
||||||
|
|
||||||
### Forum
|
### Forum
|
||||||
|
|
||||||
The community is located on https://forum.froxlor.org/
|
The community is located on https://forum.froxlor.org/
|
||||||
|
|
||||||
### Wiki
|
### Documentation
|
||||||
|
|
||||||
More documentation may be found in the froxlor - documentation:
|
The documentation may be found at https://docs.froxlor.org/
|
||||||
https://docs.froxlor.org/
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
14
SECURITY.md
14
SECURITY.md
@@ -10,9 +10,11 @@ With that, good luck hacking us ;)
|
|||||||
|
|
||||||
## Supported versions
|
## Supported versions
|
||||||
|
|
||||||
- ️✅ **2.x** (`main` git-branch)
|
- ️✅ **2.2.x** (`main` git-branch)
|
||||||
- ❌ 0.10.x (`0.10.x` git-branch)
|
- ️✅ **2.1.x** (`v2.1` git-branch)
|
||||||
- ❌ 0.9.x (`0.9.x`git-branch)
|
- ❌ 2.0.x (`2.0.x`-tags)
|
||||||
|
- ❌ 0.10.x (`0.10.x`-tags)
|
||||||
|
- ❌ other git-branches
|
||||||
|
|
||||||
## Qualifying Vulnerabilities
|
## Qualifying Vulnerabilities
|
||||||
|
|
||||||
@@ -26,7 +28,7 @@ With that, good luck hacking us ;)
|
|||||||
|
|
||||||
### Vulnerabilities we accept
|
### Vulnerabilities we accept
|
||||||
|
|
||||||
Only reproducable issues on a default/clean setup from the latest stable release of a supported version will be accepted.
|
Only reproducible issues on a default/clean setup from the latest stable release of a supported version will be accepted.
|
||||||
|
|
||||||
## Non-Qualifying Vulnerabilities
|
## Non-Qualifying Vulnerabilities
|
||||||
|
|
||||||
@@ -34,6 +36,8 @@ Only reproducable issues on a default/clean setup from the latest stable release
|
|||||||
- Theoretical attacks without proof of exploitability
|
- Theoretical attacks without proof of exploitability
|
||||||
- Attacks that are the result of a third party library should be reported to the library maintainers
|
- Attacks that are the result of a third party library should be reported to the library maintainers
|
||||||
- Social engineering
|
- Social engineering
|
||||||
|
- Attacks that require disabling security features or reducing the security level of the environment
|
||||||
|
- Exploits by an admin user itself (privileged user and implicitly trusted)
|
||||||
- Reflected file download
|
- Reflected file download
|
||||||
- Physical attacks
|
- Physical attacks
|
||||||
- Weak SSL/TLS/SSH algorithms or protocols
|
- Weak SSL/TLS/SSH algorithms or protocols
|
||||||
@@ -44,4 +48,4 @@ Only reproducable issues on a default/clean setup from the latest stable release
|
|||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
If you think you have found a vulnerability in froxlor, please head over to [https://huntr.dev/repos/froxlor/froxlor](https://huntr.dev/repos/froxlor/froxlor) and use the reporting possibilities there as we are funding the prize-pot for froxlor on this platform. Also, please give us appropriate time to fix the issue and build update-packages before publishing anything into the wild. Alternatively you can send us an email to [team@froxlor.org](team@froxlor.org).
|
If you think you have found a vulnerability in froxlor, please head over to [https://github.com/Froxlor/Froxlor/security/advisories](https://github.com/Froxlor/Froxlor/security/advisories/new) and use the reporting possibilities there. Also, please give us appropriate time to fix the issue and build update-packages before publishing anything into the wild. Alternatively you can email us to [team@froxlor.org](team@froxlor.org).
|
||||||
|
|||||||
@@ -130,7 +130,8 @@ return [
|
|||||||
'default' => 'stable',
|
'default' => 'stable',
|
||||||
'select_var' => [
|
'select_var' => [
|
||||||
'stable' => lng('serversettings.uc_stable'),
|
'stable' => lng('serversettings.uc_stable'),
|
||||||
'testing' => lng('serversettings.uc_testing')
|
'testing' => lng('serversettings.uc_testing'),
|
||||||
|
'nightly' => lng('serversettings.uc_nightly')
|
||||||
],
|
],
|
||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'advanced_mode' => true
|
'advanced_mode' => true
|
||||||
@@ -171,16 +172,6 @@ return [
|
|||||||
'default' => false,
|
'default' => false,
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
],
|
],
|
||||||
'system_index_file_extension' => [
|
|
||||||
'label' => lng('serversettings.index_file_extension'),
|
|
||||||
'settinggroup' => 'system',
|
|
||||||
'varname' => 'index_file_extension',
|
|
||||||
'type' => 'text',
|
|
||||||
'string_regexp' => '/^[a-zA-Z0-9]{1,6}$/',
|
|
||||||
'default' => 'html',
|
|
||||||
'save_method' => 'storeSettingField',
|
|
||||||
'advanced_mode' => true
|
|
||||||
],
|
|
||||||
'system_store_index_file_subs' => [
|
'system_store_index_file_subs' => [
|
||||||
'label' => lng('serversettings.system_store_index_file_subs'),
|
'label' => lng('serversettings.system_store_index_file_subs'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ return [
|
|||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
'varname' => 'le_domain_dnscheck_resolver',
|
'varname' => 'le_domain_dnscheck_resolver',
|
||||||
'type' => 'text',
|
'type' => 'text',
|
||||||
'string_regexp' => '/^(([0-9]+ [a-z0-9\-\._]+, ?)*[0-9]+ [a-z0-9\-\._]+)?$/i',
|
'string_type' => 'validate_ip',
|
||||||
'string_emptyallowed' => true,
|
'string_emptyallowed' => true,
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ return [
|
|||||||
'settinggroup' => 'spf',
|
'settinggroup' => 'spf',
|
||||||
'varname' => 'spf_entry',
|
'varname' => 'spf_entry',
|
||||||
'type' => 'text',
|
'type' => 'text',
|
||||||
'default' => '"v=spf1 a mx -all"',
|
'string_regexp' => '/^v=spf[a-z0-9:~?\s.-]+$/i',
|
||||||
|
'default' => 'v=spf1 a mx -all',
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -60,7 +60,9 @@ if ($userinfo['change_serversettings'] == '1') {
|
|||||||
|
|
||||||
if (!empty($distribution)) {
|
if (!empty($distribution)) {
|
||||||
if (!file_exists($config_dir . '/' . $distribution . ".xml")) {
|
if (!file_exists($config_dir . '/' . $distribution . ".xml")) {
|
||||||
Response::dynamicError("Unknown distribution");
|
// unknown distribution -> redirect to select a valid distribution for config-templates
|
||||||
|
Settings::Set('system.distribution', '');
|
||||||
|
Response::redirectTo('admin_configfiles.php', ['reselect' => 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update setting if different
|
// update setting if different
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ if (Settings::Get('panel.sendalternativemail') == 1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$file_templates = [
|
$file_templates = [
|
||||||
'index_html'
|
'index_html',
|
||||||
|
'unconfigured_html'
|
||||||
];
|
];
|
||||||
|
|
||||||
$languages = Language::getLanguages();
|
$languages = Language::getLanguages();
|
||||||
|
|||||||
@@ -24,20 +24,8 @@
|
|||||||
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
use Froxlor\Cli\ConfigDiff;
|
|
||||||
use Symfony\Component\Console\Application;
|
|
||||||
use Froxlor\Cli\RunApiCommand;
|
|
||||||
use Froxlor\Cli\ConfigServices;
|
|
||||||
use Froxlor\Cli\PhpSessionclean;
|
|
||||||
use Froxlor\Cli\SwitchServerIp;
|
|
||||||
use Froxlor\Cli\UpdateCommand;
|
|
||||||
use Froxlor\Cli\InstallCommand;
|
|
||||||
use Froxlor\Cli\MasterCron;
|
|
||||||
use Froxlor\Cli\UserCommand;
|
|
||||||
use Froxlor\Cli\ValidateAcmeWebroot;
|
|
||||||
use Froxlor\Froxlor;
|
use Froxlor\Froxlor;
|
||||||
|
use Symfony\Component\Console\Application;
|
||||||
|
|
||||||
// validate correct php version
|
// validate correct php version
|
||||||
if (version_compare("7.4.0", PHP_VERSION, ">=")) {
|
if (version_compare("7.4.0", PHP_VERSION, ">=")) {
|
||||||
@@ -53,14 +41,31 @@ require dirname(__DIR__) . '/vendor/autoload.php';
|
|||||||
require dirname(__DIR__) . '/lib/tables.inc.php';
|
require dirname(__DIR__) . '/lib/tables.inc.php';
|
||||||
|
|
||||||
$application = new Application('froxlor-cli', Froxlor::getFullVersion());
|
$application = new Application('froxlor-cli', Froxlor::getFullVersion());
|
||||||
$application->add(new RunApiCommand());
|
|
||||||
$application->add(new ConfigServices());
|
// files that are no commands
|
||||||
$application->add(new PhpSessionclean());
|
$fileIgnoreList = [
|
||||||
$application->add(new SwitchServerIp());
|
// Current non-command files
|
||||||
$application->add(new UpdateCommand());
|
'CliCommand.php',
|
||||||
$application->add(new InstallCommand());
|
'index.html',
|
||||||
$application->add(new MasterCron());
|
'install.functions.php',
|
||||||
$application->add(new UserCommand());
|
];
|
||||||
$application->add(new ValidateAcmeWebroot());
|
// directory of commands to include
|
||||||
$application->add(new ConfigDiff());
|
$cmd_files = glob(Froxlor::getInstallDir() . '/lib/Froxlor/Cli/*.php');
|
||||||
|
|
||||||
|
// include and add commands
|
||||||
|
foreach ($cmd_files as $cmdFile) {
|
||||||
|
// check ignore-list
|
||||||
|
if (!in_array(basename($cmdFile), $fileIgnoreList)) {
|
||||||
|
// include class-file
|
||||||
|
require $cmdFile;
|
||||||
|
// create class-name including namespace
|
||||||
|
$cmdClass = "\\Froxlor\\Cli\\" . substr(basename($cmdFile), 0, -4);
|
||||||
|
// check whether it exists
|
||||||
|
if (class_exists($cmdClass) && is_subclass_of($cmdClass, '\Symfony\Component\Console\Command\Command')) {
|
||||||
|
// add to cli application
|
||||||
|
$application->add(new $cmdClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$application->run();
|
$application->run();
|
||||||
|
|||||||
144
composer.lock
generated
144
composer.lock
generated
@@ -8,16 +8,16 @@
|
|||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "amnuts/opcache-gui",
|
"name": "amnuts/opcache-gui",
|
||||||
"version": "3.5.2",
|
"version": "3.5.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/amnuts/opcache-gui.git",
|
"url": "https://github.com/amnuts/opcache-gui.git",
|
||||||
"reference": "db9df06889067f99d95bb9f226ec99e663aed196"
|
"reference": "f3a8fe44c0a4c69dd69b9999d68f9097ee362946"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/amnuts/opcache-gui/zipball/db9df06889067f99d95bb9f226ec99e663aed196",
|
"url": "https://api.github.com/repos/amnuts/opcache-gui/zipball/f3a8fe44c0a4c69dd69b9999d68f9097ee362946",
|
||||||
"reference": "db9df06889067f99d95bb9f226ec99e663aed196",
|
"reference": "f3a8fe44c0a4c69dd69b9999d68f9097ee362946",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
"support": {
|
"support": {
|
||||||
"email": "andy@amnuts.com",
|
"email": "andy@amnuts.com",
|
||||||
"issues": "https://github.com/amnuts/opcache-gui/issues",
|
"issues": "https://github.com/amnuts/opcache-gui/issues",
|
||||||
"source": "https://github.com/amnuts/opcache-gui/tree/3.5.2"
|
"source": "https://github.com/amnuts/opcache-gui/tree/3.5.4"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-10-02T10:23:26+00:00"
|
"time": "2023-10-25T19:09:56+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "dflydev/dot-access-data",
|
"name": "dflydev/dot-access-data",
|
||||||
@@ -674,16 +674,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpmailer/phpmailer",
|
"name": "phpmailer/phpmailer",
|
||||||
"version": "v6.8.1",
|
"version": "v6.9.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/PHPMailer/PHPMailer.git",
|
"url": "https://github.com/PHPMailer/PHPMailer.git",
|
||||||
"reference": "e88da8d679acc3824ff231fdc553565b802ac016"
|
"reference": "039de174cd9c17a8389754d3b877a2ed22743e18"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/e88da8d679acc3824ff231fdc553565b802ac016",
|
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/039de174cd9c17a8389754d3b877a2ed22743e18",
|
||||||
"reference": "e88da8d679acc3824ff231fdc553565b802ac016",
|
"reference": "039de174cd9c17a8389754d3b877a2ed22743e18",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -703,6 +703,7 @@
|
|||||||
"yoast/phpunit-polyfills": "^1.0.4"
|
"yoast/phpunit-polyfills": "^1.0.4"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
|
"decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication",
|
||||||
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
|
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
|
||||||
"ext-openssl": "Needed for secure SMTP sending and DKIM signing",
|
"ext-openssl": "Needed for secure SMTP sending and DKIM signing",
|
||||||
"greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication",
|
"greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication",
|
||||||
@@ -742,7 +743,7 @@
|
|||||||
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
|
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
|
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
|
||||||
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.8.1"
|
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.9.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -750,7 +751,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-08-29T08:26:30+00:00"
|
"time": "2023-11-25T22:23:28+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/container",
|
"name": "psr/container",
|
||||||
@@ -972,16 +973,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v5.4.28",
|
"version": "v5.4.32",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/console.git",
|
"url": "https://github.com/symfony/console.git",
|
||||||
"reference": "f4f71842f24c2023b91237c72a365306f3c58827"
|
"reference": "c70df1ffaf23a8d340bded3cfab1b86752ad6ed7"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/console/zipball/f4f71842f24c2023b91237c72a365306f3c58827",
|
"url": "https://api.github.com/repos/symfony/console/zipball/c70df1ffaf23a8d340bded3cfab1b86752ad6ed7",
|
||||||
"reference": "f4f71842f24c2023b91237c72a365306f3c58827",
|
"reference": "c70df1ffaf23a8d340bded3cfab1b86752ad6ed7",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1051,7 +1052,7 @@
|
|||||||
"terminal"
|
"terminal"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/console/tree/v5.4.28"
|
"source": "https://github.com/symfony/console/tree/v5.4.32"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1067,7 +1068,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-08-07T06:12:30+00:00"
|
"time": "2023-11-18T18:23:04+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/deprecation-contracts",
|
"name": "symfony/deprecation-contracts",
|
||||||
@@ -1872,16 +1873,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/string",
|
"name": "symfony/string",
|
||||||
"version": "v5.4.29",
|
"version": "v5.4.32",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/string.git",
|
"url": "https://github.com/symfony/string.git",
|
||||||
"reference": "e41bdc93def20eaf3bfc1537c4e0a2b0680a152d"
|
"reference": "91bf4453d65d8231688a04376c3a40efe0770f04"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/string/zipball/e41bdc93def20eaf3bfc1537c4e0a2b0680a152d",
|
"url": "https://api.github.com/repos/symfony/string/zipball/91bf4453d65d8231688a04376c3a40efe0770f04",
|
||||||
"reference": "e41bdc93def20eaf3bfc1537c4e0a2b0680a152d",
|
"reference": "91bf4453d65d8231688a04376c3a40efe0770f04",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1938,7 +1939,7 @@
|
|||||||
"utf8"
|
"utf8"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/string/tree/v5.4.29"
|
"source": "https://github.com/symfony/string/tree/v5.4.32"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1954,30 +1955,31 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-09-13T11:47:41+00:00"
|
"time": "2023-11-26T13:43:46+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "twig/twig",
|
"name": "twig/twig",
|
||||||
"version": "v3.7.1",
|
"version": "v3.8.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/twigphp/Twig.git",
|
"url": "https://github.com/twigphp/Twig.git",
|
||||||
"reference": "a0ce373a0ca3bf6c64b9e3e2124aca502ba39554"
|
"reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/a0ce373a0ca3bf6c64b9e3e2124aca502ba39554",
|
"url": "https://api.github.com/repos/twigphp/Twig/zipball/9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
|
||||||
"reference": "a0ce373a0ca3bf6c64b9e3e2124aca502ba39554",
|
"reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.2.5",
|
"php": ">=7.2.5",
|
||||||
"symfony/polyfill-ctype": "^1.8",
|
"symfony/polyfill-ctype": "^1.8",
|
||||||
"symfony/polyfill-mbstring": "^1.3"
|
"symfony/polyfill-mbstring": "^1.3",
|
||||||
|
"symfony/polyfill-php80": "^1.22"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"psr/container": "^1.0|^2.0",
|
"psr/container": "^1.0|^2.0",
|
||||||
"symfony/phpunit-bridge": "^5.4.9|^6.3"
|
"symfony/phpunit-bridge": "^5.4.9|^6.3|^7.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -2013,7 +2015,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/twigphp/Twig/issues",
|
"issues": "https://github.com/twigphp/Twig/issues",
|
||||||
"source": "https://github.com/twigphp/Twig/tree/v3.7.1"
|
"source": "https://github.com/twigphp/Twig/tree/v3.8.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -2025,7 +2027,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-08-28T11:09:02+00:00"
|
"time": "2023-11-21T18:54:41+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "voku/anti-xss",
|
"name": "voku/anti-xss",
|
||||||
@@ -2291,16 +2293,16 @@
|
|||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
{
|
{
|
||||||
"name": "composer/pcre",
|
"name": "composer/pcre",
|
||||||
"version": "3.1.0",
|
"version": "3.1.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/composer/pcre.git",
|
"url": "https://github.com/composer/pcre.git",
|
||||||
"reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2"
|
"reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/composer/pcre/zipball/4bff79ddd77851fe3cdd11616ed3f92841ba5bd2",
|
"url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9",
|
||||||
"reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2",
|
"reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -2342,7 +2344,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/composer/pcre/issues",
|
"issues": "https://github.com/composer/pcre/issues",
|
||||||
"source": "https://github.com/composer/pcre/tree/3.1.0"
|
"source": "https://github.com/composer/pcre/tree/3.1.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -2358,7 +2360,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-11-17T09:50:14+00:00"
|
"time": "2023-10-11T07:11:09+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "composer/xdebug-handler",
|
"name": "composer/xdebug-handler",
|
||||||
@@ -2613,23 +2615,24 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pdepend/pdepend",
|
"name": "pdepend/pdepend",
|
||||||
"version": "2.15.1",
|
"version": "2.16.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/pdepend/pdepend.git",
|
"url": "https://github.com/pdepend/pdepend.git",
|
||||||
"reference": "d12f25bcdfb7754bea458a4a5cb159d55e9950d0"
|
"reference": "8dfc0c46529e2073fa97986552f80646eedac562"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/pdepend/pdepend/zipball/d12f25bcdfb7754bea458a4a5cb159d55e9950d0",
|
"url": "https://api.github.com/repos/pdepend/pdepend/zipball/8dfc0c46529e2073fa97986552f80646eedac562",
|
||||||
"reference": "d12f25bcdfb7754bea458a4a5cb159d55e9950d0",
|
"reference": "8dfc0c46529e2073fa97986552f80646eedac562",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.7",
|
"php": ">=5.3.7",
|
||||||
"symfony/config": "^2.3.0|^3|^4|^5|^6.0",
|
"symfony/config": "^2.3.0|^3|^4|^5|^6.0|^7.0",
|
||||||
"symfony/dependency-injection": "^2.3.0|^3|^4|^5|^6.0",
|
"symfony/dependency-injection": "^2.3.0|^3|^4|^5|^6.0|^7.0",
|
||||||
"symfony/filesystem": "^2.3.0|^3|^4|^5|^6.0"
|
"symfony/filesystem": "^2.3.0|^3|^4|^5|^6.0|^7.0",
|
||||||
|
"symfony/polyfill-mbstring": "^1.19"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"easy-doc/easy-doc": "0.0.0|^1.2.3",
|
"easy-doc/easy-doc": "0.0.0|^1.2.3",
|
||||||
@@ -2664,7 +2667,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/pdepend/pdepend/issues",
|
"issues": "https://github.com/pdepend/pdepend/issues",
|
||||||
"source": "https://github.com/pdepend/pdepend/tree/2.15.1"
|
"source": "https://github.com/pdepend/pdepend/tree/2.16.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -2672,7 +2675,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-09-28T12:00:56+00:00"
|
"time": "2023-11-29T08:52:35+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phar-io/manifest",
|
"name": "phar-io/manifest",
|
||||||
@@ -2906,7 +2909,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"abandoned": true,
|
|
||||||
"time": "2020-12-07T05:51:20+00:00"
|
"time": "2020-12-07T05:51:20+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2995,16 +2997,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpstan/phpstan",
|
"name": "phpstan/phpstan",
|
||||||
"version": "1.10.38",
|
"version": "1.10.46",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpstan/phpstan.git",
|
"url": "https://github.com/phpstan/phpstan.git",
|
||||||
"reference": "5302bb402c57f00fb3c2c015bac86e0827e4b691"
|
"reference": "90d3d25c5b98b8068916bbf08ce42d5cb6c54e70"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/5302bb402c57f00fb3c2c015bac86e0827e4b691",
|
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/90d3d25c5b98b8068916bbf08ce42d5cb6c54e70",
|
||||||
"reference": "5302bb402c57f00fb3c2c015bac86e0827e4b691",
|
"reference": "90d3d25c5b98b8068916bbf08ce42d5cb6c54e70",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3053,7 +3055,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-10-06T14:19:14+00:00"
|
"time": "2023-11-28T14:57:26+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/php-code-coverage",
|
"name": "phpunit/php-code-coverage",
|
||||||
@@ -4562,16 +4564,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/config",
|
"name": "symfony/config",
|
||||||
"version": "v5.4.26",
|
"version": "v5.4.31",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/config.git",
|
"url": "https://github.com/symfony/config.git",
|
||||||
"reference": "8109892f27beed9252bd1f1c1880aeb4ad842650"
|
"reference": "dd5ea39de228813aba0c23c3a4153da2a4cf3cd9"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/config/zipball/8109892f27beed9252bd1f1c1880aeb4ad842650",
|
"url": "https://api.github.com/repos/symfony/config/zipball/dd5ea39de228813aba0c23c3a4153da2a4cf3cd9",
|
||||||
"reference": "8109892f27beed9252bd1f1c1880aeb4ad842650",
|
"reference": "dd5ea39de228813aba0c23c3a4153da2a4cf3cd9",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -4621,7 +4623,7 @@
|
|||||||
"description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
|
"description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/config/tree/v5.4.26"
|
"source": "https://github.com/symfony/config/tree/v5.4.31"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -4637,20 +4639,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-07-19T20:21:11+00:00"
|
"time": "2023-11-09T08:22:43+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/dependency-injection",
|
"name": "symfony/dependency-injection",
|
||||||
"version": "v5.4.29",
|
"version": "v5.4.32",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/dependency-injection.git",
|
"url": "https://github.com/symfony/dependency-injection.git",
|
||||||
"reference": "338638ed8c9d5c7fcb136a73f5c7043465ae2f05"
|
"reference": "d5d48f215ed73f7973d01256b9a2fac729bef759"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/338638ed8c9d5c7fcb136a73f5c7043465ae2f05",
|
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/d5d48f215ed73f7973d01256b9a2fac729bef759",
|
||||||
"reference": "338638ed8c9d5c7fcb136a73f5c7043465ae2f05",
|
"reference": "d5d48f215ed73f7973d01256b9a2fac729bef759",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -4710,7 +4712,7 @@
|
|||||||
"description": "Allows you to standardize and centralize the way objects are constructed in your application",
|
"description": "Allows you to standardize and centralize the way objects are constructed in your application",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/dependency-injection/tree/v5.4.29"
|
"source": "https://github.com/symfony/dependency-injection/tree/v5.4.32"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -4726,7 +4728,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-09-20T06:23:43+00:00"
|
"time": "2023-11-29T06:58:28+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/filesystem",
|
"name": "symfony/filesystem",
|
||||||
@@ -4873,16 +4875,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "theseer/tokenizer",
|
"name": "theseer/tokenizer",
|
||||||
"version": "1.2.1",
|
"version": "1.2.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/theseer/tokenizer.git",
|
"url": "https://github.com/theseer/tokenizer.git",
|
||||||
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
|
"reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
|
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
|
||||||
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
|
"reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -4911,7 +4913,7 @@
|
|||||||
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
|
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/theseer/tokenizer/issues",
|
"issues": "https://github.com/theseer/tokenizer/issues",
|
||||||
"source": "https://github.com/theseer/tokenizer/tree/1.2.1"
|
"source": "https://github.com/theseer/tokenizer/tree/1.2.2"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -4919,7 +4921,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-07-28T10:34:58+00:00"
|
"time": "2023-11-20T00:12:19+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ if ($page == 'overview' || $page == 'domains') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$actions_links[] = [
|
$actions_links[] = [
|
||||||
'href' => 'https://docs.froxlor.org/v2/user-guide/domains/',
|
'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/domains/',
|
||||||
'target' => '_blank',
|
'target' => '_blank',
|
||||||
'icon' => 'fa-solid fa-circle-info',
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
'class' => 'btn-outline-secondary'
|
'class' => 'btn-outline-secondary'
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$actions_links[] = [
|
$actions_links[] = [
|
||||||
'href' => 'https://docs.froxlor.org/v2/user-guide/emails/',
|
'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/emails/',
|
||||||
'target' => '_blank',
|
'target' => '_blank',
|
||||||
'icon' => 'fa-solid fa-circle-info',
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
'class' => 'btn-outline-secondary'
|
'class' => 'btn-outline-secondary'
|
||||||
@@ -138,7 +138,7 @@ if ($page == 'email_domain') {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
$actions_links[] = [
|
$actions_links[] = [
|
||||||
'href' => 'https://docs.froxlor.org/v2/user-guide/emails/',
|
'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/emails/',
|
||||||
'target' => '_blank',
|
'target' => '_blank',
|
||||||
'icon' => 'fa-solid fa-circle-info',
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
'class' => 'btn-outline-secondary'
|
'class' => 'btn-outline-secondary'
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ if ($page == 'overview' || $page == 'htpasswds') {
|
|||||||
];
|
];
|
||||||
|
|
||||||
$actions_links[] = [
|
$actions_links[] = [
|
||||||
'href' => 'https://docs.froxlor.org/v2/user-guide/extras/',
|
'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/extras/',
|
||||||
'target' => '_blank',
|
'target' => '_blank',
|
||||||
'icon' => 'fa-solid fa-circle-info',
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
'class' => 'btn-outline-secondary'
|
'class' => 'btn-outline-secondary'
|
||||||
@@ -200,7 +200,7 @@ if ($page == 'overview' || $page == 'htpasswds') {
|
|||||||
];
|
];
|
||||||
|
|
||||||
$actions_links[] = [
|
$actions_links[] = [
|
||||||
'href' => 'https://docs.froxlor.org/v2/user-guide/extras/',
|
'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/extras/',
|
||||||
'target' => '_blank',
|
'target' => '_blank',
|
||||||
'icon' => 'fa-solid fa-circle-info',
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
'class' => 'btn-outline-secondary'
|
'class' => 'btn-outline-secondary'
|
||||||
@@ -349,7 +349,7 @@ if ($page == 'overview' || $page == 'htpasswds') {
|
|||||||
|
|
||||||
$actions_links = [
|
$actions_links = [
|
||||||
[
|
[
|
||||||
'href' => 'https://docs.froxlor.org/v2/user-guide/extras/',
|
'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/extras/',
|
||||||
'target' => '_blank',
|
'target' => '_blank',
|
||||||
'icon' => 'fa-solid fa-circle-info',
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
'class' => 'btn-outline-secondary'
|
'class' => 'btn-outline-secondary'
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ if ($page == 'overview' || $page == 'accounts') {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
$actions_links[] = [
|
$actions_links[] = [
|
||||||
'href' => 'https://docs.froxlor.org/v2/user-guide/ftp-accounts/',
|
'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/ftp-accounts/',
|
||||||
'target' => '_blank',
|
'target' => '_blank',
|
||||||
'icon' => 'fa-solid fa-circle-info',
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
'class' => 'btn-outline-secondary'
|
'class' => 'btn-outline-secondary'
|
||||||
|
|||||||
@@ -115,8 +115,8 @@ if ($page == 'overview') {
|
|||||||
$userinfo['traffic_bytes_used'] = $userinfo['traffic_used'] * 1024;
|
$userinfo['traffic_bytes_used'] = $userinfo['traffic_used'] * 1024;
|
||||||
|
|
||||||
if (Settings::Get('system.mail_quota_enabled')) {
|
if (Settings::Get('system.mail_quota_enabled')) {
|
||||||
$userinfo['email_quota_bytes'] = ($userinfo['email_quota'] > -1) ? $userinfo['email_quota'] * 1024 : -1;
|
$userinfo['email_quota_bytes'] = ($userinfo['email_quota'] > -1) ? $userinfo['email_quota'] * 1024 * 1024 : -1;
|
||||||
$userinfo['email_quota_bytes_used'] = $userinfo['email_quota_used'] * 1024;
|
$userinfo['email_quota_bytes_used'] = $userinfo['email_quota_used'] * 1024 * 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($usages) {
|
if ($usages) {
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ if ($page == 'overview' || $page == 'mysqls') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$actions_links[] = [
|
$actions_links[] = [
|
||||||
'href' => 'https://docs.froxlor.org/v2/user-guide/databases/',
|
'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/databases/',
|
||||||
'target' => '_blank',
|
'target' => '_blank',
|
||||||
'icon' => 'fa-solid fa-circle-info',
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
'class' => 'btn-outline-secondary'
|
'class' => 'btn-outline-secondary'
|
||||||
|
|||||||
22
index.php
22
index.php
@@ -74,27 +74,26 @@ if ($action == '2fa_entercode') {
|
|||||||
$code = isset($_POST['2fa_code']) ? $_POST['2fa_code'] : null;
|
$code = isset($_POST['2fa_code']) ? $_POST['2fa_code'] : null;
|
||||||
// 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));
|
|
||||||
// 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'];
|
||||||
|
if ($_SESSION['secret_2fa'] == 'email') {
|
||||||
|
// verify code set to user's data_2fa field
|
||||||
|
$sel_stmt = Database::prepare("SELECT `data_2fa` FROM " . $table . " WHERE `" . $field . "` = :uid");
|
||||||
|
$userinfo_code = Database::pexecute_first($sel_stmt, ['uid' => $uid]);
|
||||||
|
$result = $tfa->verifyCode($userinfo_code['data_2fa'], $code);
|
||||||
|
} else {
|
||||||
|
$result = $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
|
// 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
|
// which is temporarily stored for the customer when using email-2fa
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$sel_param = [
|
$sel_param = [
|
||||||
'uid' => $uid
|
'uid' => $uid
|
||||||
];
|
];
|
||||||
if ($_SESSION['secret_2fa'] == 'email') {
|
|
||||||
// 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
|
|
||||||
$sel_stmt = Database::prepare("SELECT * FROM " . $table . " WHERE `" . $field . "` = :uid AND `data_2fa` = :code");
|
|
||||||
$sel_param['code'] = $code;
|
|
||||||
} else {
|
|
||||||
// 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
|
||||||
if (empty($userinfo)) {
|
if (empty($userinfo)) {
|
||||||
@@ -327,11 +326,12 @@ if ($action == '2fa_entercode') {
|
|||||||
if ($userinfo['type_2fa'] == 1) {
|
if ($userinfo['type_2fa'] == 1) {
|
||||||
// generate code
|
// generate code
|
||||||
$tfa = new FroxlorTwoFactorAuth('Froxlor ' . Settings::Get('system.hostname'));
|
$tfa = new FroxlorTwoFactorAuth('Froxlor ' . Settings::Get('system.hostname'));
|
||||||
$code = $tfa->getCode($tfa->createSecret());
|
$secret = $tfa->createSecret();
|
||||||
|
$code = $tfa->getCode($secret);
|
||||||
// set code for user
|
// set code for user
|
||||||
$stmt = Database::prepare("UPDATE $table SET `data_2fa` = :d2fa WHERE `$uid` = :uid");
|
$stmt = Database::prepare("UPDATE $table SET `data_2fa` = :d2fa WHERE `$uid` = :uid");
|
||||||
Database::pexecute($stmt, [
|
Database::pexecute($stmt, [
|
||||||
"d2fa" => $code,
|
"d2fa" => $secret,
|
||||||
"uid" => $userinfo[$uid]
|
"uid" => $userinfo[$uid]
|
||||||
]);
|
]);
|
||||||
// build up & send email
|
// build up & send email
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ CREATE TABLE `panel_admins` (
|
|||||||
`api_allowed` tinyint(1) NOT NULL default '1',
|
`api_allowed` tinyint(1) NOT NULL default '1',
|
||||||
PRIMARY KEY (`adminid`),
|
PRIMARY KEY (`adminid`),
|
||||||
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_customers`;
|
DROP TABLE IF EXISTS `panel_customers`;
|
||||||
@@ -299,7 +299,7 @@ CREATE TABLE `panel_domains` (
|
|||||||
KEY `customerid` (`customerid`),
|
KEY `customerid` (`customerid`),
|
||||||
KEY `parentdomain` (`parentdomainid`),
|
KEY `parentdomain` (`parentdomainid`),
|
||||||
KEY `domain` (`domain`)
|
KEY `domain` (`domain`)
|
||||||
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
|
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=DYNAMIC;
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `panel_ipsandports`;
|
DROP TABLE IF EXISTS `panel_ipsandports`;
|
||||||
@@ -356,23 +356,6 @@ CREATE TABLE `panel_htpasswds` (
|
|||||||
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
|
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `panel_sessions`;
|
|
||||||
CREATE TABLE `panel_sessions` (
|
|
||||||
`hash` varchar(32) NOT NULL default '',
|
|
||||||
`userid` int(11) unsigned NOT NULL default '0',
|
|
||||||
`ipaddress` varchar(255) NOT NULL default '',
|
|
||||||
`useragent` varchar(255) NOT NULL default '',
|
|
||||||
`lastactivity` int(11) unsigned NOT NULL default '0',
|
|
||||||
`lastpaging` varchar(255) NOT NULL default '',
|
|
||||||
`formtoken` char(32) NOT NULL default '',
|
|
||||||
`language` varchar(64) NOT NULL default '',
|
|
||||||
`adminsession` tinyint(1) unsigned NOT NULL default '0',
|
|
||||||
`theme` varchar(255) NOT NULL default '',
|
|
||||||
PRIMARY KEY (`hash`),
|
|
||||||
KEY `userid` (`userid`)
|
|
||||||
) ENGINE=HEAP;
|
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `panel_settings`;
|
DROP TABLE IF EXISTS `panel_settings`;
|
||||||
CREATE TABLE `panel_settings` (
|
CREATE TABLE `panel_settings` (
|
||||||
`settingid` int(11) unsigned NOT NULL auto_increment,
|
`settingid` int(11) unsigned NOT NULL auto_increment,
|
||||||
@@ -408,7 +391,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
|
|||||||
('admin', 'show_version_footer', '0'),
|
('admin', 'show_version_footer', '0'),
|
||||||
('caa', 'caa_entry', ''),
|
('caa', 'caa_entry', ''),
|
||||||
('spf', 'use_spf', '0'),
|
('spf', 'use_spf', '0'),
|
||||||
('spf', 'spf_entry', '"v=spf1 a mx -all"'),
|
('spf', 'spf_entry', 'v=spf1 a mx -all'),
|
||||||
('dkim', 'dkim_algorithm', 'all'),
|
('dkim', 'dkim_algorithm', 'all'),
|
||||||
('dkim', 'dkim_keylength', '1024'),
|
('dkim', 'dkim_keylength', '1024'),
|
||||||
('dkim', 'dkim_servicetype', '0'),
|
('dkim', 'dkim_servicetype', '0'),
|
||||||
@@ -579,7 +562,6 @@ opcache.validate_timestamps'),
|
|||||||
('system', 'mod_fcgid_wrapper', '1'),
|
('system', 'mod_fcgid_wrapper', '1'),
|
||||||
('system', 'mod_fcgid_starter', '0'),
|
('system', 'mod_fcgid_starter', '0'),
|
||||||
('system', 'mod_fcgid_peardir', '/usr/share/php/:/usr/share/php5/'),
|
('system', 'mod_fcgid_peardir', '/usr/share/php/:/usr/share/php5/'),
|
||||||
('system', 'index_file_extension', 'html'),
|
|
||||||
('system', 'mod_fcgid_maxrequests', '250'),
|
('system', 'mod_fcgid_maxrequests', '250'),
|
||||||
('system', 'ssl_key_file','/etc/ssl/froxlor_selfsigned.key'),
|
('system', 'ssl_key_file','/etc/ssl/froxlor_selfsigned.key'),
|
||||||
('system', 'ssl_ca_file', ''),
|
('system', 'ssl_ca_file', ''),
|
||||||
@@ -696,7 +678,7 @@ 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.1.0-beta1'),
|
('system', 'update_notify_last', ''),
|
||||||
('system', 'traffictool', 'goaccess'),
|
('system', 'traffictool', 'goaccess'),
|
||||||
('system', 'req_limit_per_interval', 60),
|
('system', 'req_limit_per_interval', 60),
|
||||||
('system', 'req_limit_interval', 60),
|
('system', 'req_limit_interval', 60),
|
||||||
@@ -704,7 +686,7 @@ opcache.validate_timestamps'),
|
|||||||
('api', 'customer_default', '1'),
|
('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_MAIL'),
|
||||||
('panel', 'phpmyadmin_url', ''),
|
('panel', 'phpmyadmin_url', ''),
|
||||||
('panel', 'webmail_url', ''),
|
('panel', 'webmail_url', ''),
|
||||||
('panel', 'webftp_url', ''),
|
('panel', 'webftp_url', ''),
|
||||||
@@ -744,8 +726,8 @@ opcache.validate_timestamps'),
|
|||||||
('panel', 'logo_overridecustom', '0'),
|
('panel', 'logo_overridecustom', '0'),
|
||||||
('panel', 'settings_mode', '0'),
|
('panel', 'settings_mode', '0'),
|
||||||
('panel', 'menu_collapsed', '1'),
|
('panel', 'menu_collapsed', '1'),
|
||||||
('panel', 'version', '2.1.0-beta1'),
|
('panel', 'version', '2.1.7'),
|
||||||
('panel', 'db_version', '202305240');
|
('panel', 'db_version', '202312120');
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `panel_tasks`;
|
DROP TABLE IF EXISTS `panel_tasks`;
|
||||||
@@ -768,6 +750,7 @@ CREATE TABLE `panel_templates` (
|
|||||||
`templategroup` varchar(255) NOT NULL default '',
|
`templategroup` varchar(255) NOT NULL default '',
|
||||||
`varname` varchar(255) NOT NULL default '',
|
`varname` varchar(255) NOT NULL default '',
|
||||||
`value` longtext NOT NULL,
|
`value` longtext NOT NULL,
|
||||||
|
`file_extension` varchar(50) NOT NULL default 'html',
|
||||||
PRIMARY KEY (id),
|
PRIMARY KEY (id),
|
||||||
KEY adminid (adminid)
|
KEY adminid (adminid)
|
||||||
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
|
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ if (!defined('_CRON_UPDATE')) {
|
|||||||
|
|
||||||
if (Froxlor::isFroxlorVersion('2.0.24')) {
|
if (Froxlor::isFroxlorVersion('2.0.24')) {
|
||||||
Update::showUpdateStep("Cleaning domains table");
|
Update::showUpdateStep("Cleaning domains table");
|
||||||
|
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ROW_FORMAT=DYNAMIC;");
|
||||||
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` DROP COLUMN `ismainbutsubto`;");
|
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` DROP COLUMN `ismainbutsubto`;");
|
||||||
Update::lastStepStatus(0);
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
@@ -67,15 +68,18 @@ if (Froxlor::isFroxlorVersion('2.0.24')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Update::showUpdateStep("Adjusting cronjobs");
|
Update::showUpdateStep("Adjusting cronjobs");
|
||||||
Database::query("
|
$cfupd_stmt = Database::prepare("
|
||||||
UPDATE `" . TABLE_PANEL_CRONRUNS . "` SET
|
UPDATE `" . TABLE_PANEL_CRONRUNS . "` SET
|
||||||
`module`= 'froxlor/export',
|
`module`= 'froxlor/export',
|
||||||
`cronfile` = 'export',
|
`cronfile` = 'export',
|
||||||
`cronclass` = '\\Froxlor\\Cron\\System\\ExportCron',
|
`cronclass` = :cc,
|
||||||
`interval` = '1 HOUR',
|
`interval` = '1 HOUR',
|
||||||
`desc_lng_key` = 'cron_export'
|
`desc_lng_key` = 'cron_export'
|
||||||
WHERE `module` = 'froxlor/backup'
|
WHERE `module` = 'froxlor/backup'
|
||||||
");
|
");
|
||||||
|
Database::pexecute($cfupd_stmt, [
|
||||||
|
'cc' => '\\Froxlor\\Cron\\System\\ExportCron'
|
||||||
|
]);
|
||||||
Update::lastStepStatus(0);
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
Update::showUpdateStep("Adjusting system for data-export function");
|
Update::showUpdateStep("Adjusting system for data-export function");
|
||||||
@@ -93,3 +97,200 @@ if (Froxlor::isFroxlorVersion('2.1.0-dev1')) {
|
|||||||
Update::showUpdateStep("Updating from 2.1.0-dev1 to 2.1.0-beta1", false);
|
Update::showUpdateStep("Updating from 2.1.0-dev1 to 2.1.0-beta1", false);
|
||||||
Froxlor::updateToVersion('2.1.0-beta1');
|
Froxlor::updateToVersion('2.1.0-beta1');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.0-beta1')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.1.0-beta1 to 2.1.0-beta2", false);
|
||||||
|
|
||||||
|
Update::showUpdateStep("Removing unused table");
|
||||||
|
Database::query("DROP TABLE IF EXISTS `panel_sessions`;");
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Froxlor::updateToVersion('2.1.0-beta2');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.0-beta2')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.1.0-beta2 to 2.1.0-rc1", false);
|
||||||
|
Froxlor::updateToVersion('2.1.0-rc1');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.0-rc1')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.1.0-rc1 to 2.1.0-rc2", false);
|
||||||
|
|
||||||
|
Update::showUpdateStep("Adjusting setting spf_entry");
|
||||||
|
$spf_entry = Settings::Get('spf.spf_entry');
|
||||||
|
if (!preg_match('/^v=spf[a-z0-9:~?\s.-]+$/i', $spf_entry)) {
|
||||||
|
Settings::Set('spf.spf_entry', 'v=spf1 a mx -all');
|
||||||
|
Update::lastStepStatus(1, 'corrected');
|
||||||
|
} else {
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Froxlor::updateToVersion('2.1.0-rc2');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isDatabaseVersion('202305240')) {
|
||||||
|
|
||||||
|
Update::showUpdateStep("Adjusting file-template file extension setttings");
|
||||||
|
$current_fileextension = Settings::Get('system.index_file_extension');
|
||||||
|
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup`= 'system' AND `varname`= 'index_file_extension'");
|
||||||
|
Database::query("ALTER TABLE `" . TABLE_PANEL_TEMPLATES . "` ADD `file_extension` varchar(50) NOT NULL default 'html';");
|
||||||
|
if (!empty(trim($current_fileextension)) && strtolower(trim($current_fileextension)) != 'html') {
|
||||||
|
$stmt = Database::prepare("UPDATE `" . TABLE_PANEL_TEMPLATES . "` SET `file_extension` = :ext WHERE `templategroup` = 'files'");
|
||||||
|
Database::pexecute($stmt, ['ext' => strtolower(trim($current_fileextension))]);
|
||||||
|
}
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Froxlor::updateToDbVersion('202311260');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.0-rc2')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.1.0-rc2 to 2.1.0-rc3", false);
|
||||||
|
Froxlor::updateToVersion('2.1.0-rc3');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isDatabaseVersion('202311260')) {
|
||||||
|
Update::showUpdateStep("Cleaning up old files");
|
||||||
|
$to_clean = array(
|
||||||
|
"install/updates/froxlor/update_2.x.inc.php",
|
||||||
|
"install/updates/preconfig/preconfig_2.x.inc.php",
|
||||||
|
"lib/Froxlor/Api/Commands/CustomerBackups.php",
|
||||||
|
"lib/Froxlor/Cli/Action",
|
||||||
|
"lib/Froxlor/Cli/Action.php",
|
||||||
|
"lib/Froxlor/Cli/CmdLineHandler.php",
|
||||||
|
"lib/Froxlor/Cli/ConfigServicesCmd.php",
|
||||||
|
"lib/Froxlor/Cli/PhpSessioncleanCmd.php",
|
||||||
|
"lib/Froxlor/Cli/SwitchServerIpCmd.php",
|
||||||
|
"lib/Froxlor/Cli/UpdateCliCmd.php",
|
||||||
|
"lib/Froxlor/Cron/System/BackupCron.php",
|
||||||
|
"lib/formfields/customer/extras/formfield.backup.php",
|
||||||
|
"lib/tablelisting/customer/tablelisting.backups.php",
|
||||||
|
"templates/Froxlor/assets/mix-manifest.json",
|
||||||
|
"templates/Froxlor/assets/css",
|
||||||
|
"templates/Froxlor/assets/webfonts",
|
||||||
|
"templates/Froxlor/assets/js/main.js",
|
||||||
|
"templates/Froxlor/assets/js/main.js.LICENSE.txt",
|
||||||
|
"templates/Froxlor/src",
|
||||||
|
"templates/Froxlor/user/change_language.html.twig",
|
||||||
|
"templates/Froxlor/user/change_password.html.twig",
|
||||||
|
"templates/Froxlor/user/change_theme.html.twig",
|
||||||
|
"tests/Backup/CustomerBackupsTest.php"
|
||||||
|
);
|
||||||
|
$disabled = explode(',', ini_get('disable_functions'));
|
||||||
|
$exec_allowed = !in_array('exec', $disabled);
|
||||||
|
$del_list = "";
|
||||||
|
foreach ($to_clean as $filedir) {
|
||||||
|
$complete_filedir = Froxlor::getInstallDir() . $filedir;
|
||||||
|
if (file_exists($complete_filedir)) {
|
||||||
|
if ($exec_allowed) {
|
||||||
|
FileDir::safe_exec("rm -rf " . escapeshellarg($complete_filedir));
|
||||||
|
} else {
|
||||||
|
$del_list .= "rm -rf " . escapeshellarg($complete_filedir) . PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($exec_allowed) {
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
} else {
|
||||||
|
if (empty($del_list)) {
|
||||||
|
// none of the files existed
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
} else {
|
||||||
|
Update::lastStepStatus(
|
||||||
|
1,
|
||||||
|
'manual commands needed',
|
||||||
|
'Please run the following commands manually:<br><pre>' . $del_list . '</pre>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Froxlor::updateToDbVersion('202312050');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.0-rc3')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.1.0-rc3 to 2.1.0 stable", false);
|
||||||
|
Froxlor::updateToVersion('2.1.0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.0')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.1.0 to 2.1.1", false);
|
||||||
|
Froxlor::updateToVersion('2.1.1');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isDatabaseVersion('202312050')) {
|
||||||
|
Update::showUpdateStep("Cleaning up old files");
|
||||||
|
$to_clean = array(
|
||||||
|
"lib/configfiles/centos7.xml",
|
||||||
|
"lib/configfiles/centos8.xml",
|
||||||
|
"lib/configfiles/stretch.xml",
|
||||||
|
"lib/configfiles/xenial.xml",
|
||||||
|
"lib/configfiles/buster.xml",
|
||||||
|
"lib/configfiles/bionic.xml",
|
||||||
|
);
|
||||||
|
$disabled = explode(',', ini_get('disable_functions'));
|
||||||
|
$exec_allowed = !in_array('exec', $disabled);
|
||||||
|
$del_list = "";
|
||||||
|
foreach ($to_clean as $filedir) {
|
||||||
|
$complete_filedir = Froxlor::getInstallDir() . $filedir;
|
||||||
|
if (file_exists($complete_filedir)) {
|
||||||
|
if ($exec_allowed) {
|
||||||
|
FileDir::safe_exec("rm -rf " . escapeshellarg($complete_filedir));
|
||||||
|
} else {
|
||||||
|
$del_list .= "rm -rf " . escapeshellarg($complete_filedir) . PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($exec_allowed) {
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
} else {
|
||||||
|
if (empty($del_list)) {
|
||||||
|
// none of the files existed
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
} else {
|
||||||
|
Update::lastStepStatus(
|
||||||
|
1,
|
||||||
|
'manual commands needed',
|
||||||
|
'Please run the following commands manually:<br><pre>' . $del_list . '</pre>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Froxlor::updateToDbVersion('202312100');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isDatabaseVersion('202312100')) {
|
||||||
|
|
||||||
|
Update::showUpdateStep("Adjusting table row format of larger tables");
|
||||||
|
Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` ROW_FORMAT=DYNAMIC;");
|
||||||
|
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ROW_FORMAT=DYNAMIC;");
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Froxlor::updateToDbVersion('202312120');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.1')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.1.1 to 2.1.2", false);
|
||||||
|
Froxlor::updateToVersion('2.1.2');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.2')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.1.2 to 2.1.3", false);
|
||||||
|
Froxlor::updateToVersion('2.1.3');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.3')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.1.3 to 2.1.4", false);
|
||||||
|
Froxlor::updateToVersion('2.1.4');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.4')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.1.4 to 2.1.5", false);
|
||||||
|
Froxlor::updateToVersion('2.1.5');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.5')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.1.5 to 2.1.6", false);
|
||||||
|
Froxlor::updateToVersion('2.1.6');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.6')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.1.6 to 2.1.7", false);
|
||||||
|
Froxlor::updateToVersion('2.1.7');
|
||||||
|
}
|
||||||
|
|||||||
@@ -400,8 +400,11 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
$allowed_phpconfigs = array_map('intval', $allowed_phpconfigs);
|
$allowed_phpconfigs = array_map('intval', $allowed_phpconfigs);
|
||||||
|
|
||||||
if (empty($allowed_phpconfigs) && $phpenabled == 1) {
|
if (empty($allowed_phpconfigs) && $phpenabled == 1) {
|
||||||
|
// only required if not using mod_php
|
||||||
|
if ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) {
|
||||||
Response::standardError('customerphpenabledbutnoconfig', '', true);
|
Response::standardError('customerphpenabledbutnoconfig', '', true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$allowed_mysqlserver = array();
|
$allowed_mysqlserver = array();
|
||||||
if (! empty($p_allowed_mysqlserver) && is_array($p_allowed_mysqlserver)) {
|
if (! empty($p_allowed_mysqlserver) && is_array($p_allowed_mysqlserver)) {
|
||||||
@@ -1053,7 +1056,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
$email = $this->getParam('email', true, $idna_convert->decode($result['email']));
|
$email = $this->getParam('email', true, $idna_convert->decode($result['email']));
|
||||||
$name = $this->getParam('name', true, $result['name']);
|
$name = $this->getParam('name', true, $result['name']);
|
||||||
$firstname = $this->getParam('firstname', true, $result['firstname']);
|
$firstname = $this->getParam('firstname', true, $result['firstname']);
|
||||||
$company_required = empty($result['company']) && ((!empty($name) && empty($firstname)) || (empty($name) && !empty($firstname)) || (empty($name) && empty($firstname)));
|
$company_required = (!empty($name) && empty($firstname)) || (empty($name) && !empty($firstname)) || (empty($name) && empty($firstname));
|
||||||
$company = $this->getParam('company', !$company_required, $result['company']);
|
$company = $this->getParam('company', !$company_required, $result['company']);
|
||||||
$street = $this->getParam('street', true, $result['street']);
|
$street = $this->getParam('street', true, $result['street']);
|
||||||
$zipcode = $this->getParam('zipcode', true, $result['zipcode']);
|
$zipcode = $this->getParam('zipcode', true, $result['zipcode']);
|
||||||
@@ -1114,8 +1117,11 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
$allowed_phpconfigs = array_map('intval', $allowed_phpconfigs);
|
$allowed_phpconfigs = array_map('intval', $allowed_phpconfigs);
|
||||||
}
|
}
|
||||||
if (empty($allowed_phpconfigs) && $phpenabled == 1) {
|
if (empty($allowed_phpconfigs) && $phpenabled == 1) {
|
||||||
|
// only required if not using mod_php
|
||||||
|
if ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) {
|
||||||
Response::standardError('customerphpenabledbutnoconfig', '', true);
|
Response::standardError('customerphpenabledbutnoconfig', '', true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// add permission for allowed mysql usage if customer was not allowed to use mysql prior
|
// add permission for allowed mysql usage if customer was not allowed to use mysql prior
|
||||||
if ($result['mysqls'] == 0 && ($mysqls == -1 || $mysqls > 0)) {
|
if ($result['mysqls'] == 0 && ($mysqls == -1 || $mysqls > 0)) {
|
||||||
|
|||||||
@@ -349,6 +349,8 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
if (substr($p_domain, 0, 4) == 'xn--') {
|
if (substr($p_domain, 0, 4) == 'xn--') {
|
||||||
Response::standardError('domain_nopunycode', '', true);
|
Response::standardError('domain_nopunycode', '', true);
|
||||||
|
} elseif (Validate::validate_ip2($p_domain, true, '', true, true)) {
|
||||||
|
Response::standardError('domain_noipaddress', '', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$idna_convert = new IdnaWrapper();
|
$idna_convert = new IdnaWrapper();
|
||||||
@@ -517,7 +519,8 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$mod_fcgid_maxrequests = '-1';
|
$mod_fcgid_maxrequests = '-1';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$phpenabled = '1';
|
// set default to whether the customer has php enabled or not
|
||||||
|
$phpenabled = $customer['phpenabled'];
|
||||||
$openbasedir = '1';
|
$openbasedir = '1';
|
||||||
|
|
||||||
if ((int)Settings::Get('phpfpm.enabled') == 1) {
|
if ((int)Settings::Get('phpfpm.enabled') == 1) {
|
||||||
@@ -1525,13 +1528,12 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
// enabled ssl for the domain but no ssl ip/port is selected
|
// enabled ssl for the domain but no ssl ip/port is selected
|
||||||
Response::standardError('nosslippportgiven', '', true);
|
Response::standardError('nosslippportgiven', '', true);
|
||||||
}
|
}
|
||||||
if (Settings::Get('system.use_ssl') == "0" || empty($ssl_ipandports)) {
|
if (Settings::Get('system.use_ssl') == "0" || empty($ssl_ipandports) || !$sslenabled) {
|
||||||
$ssl_redirect = 0;
|
$ssl_redirect = 0;
|
||||||
$letsencrypt = 0;
|
$letsencrypt = 0;
|
||||||
$http2 = 0;
|
$http2 = 0;
|
||||||
// we need this for the json_encode
|
// act like $remove_ssl_ipandport
|
||||||
// if ssl is disabled or no ssl-ip/port exists
|
$ssl_ipandports = [];
|
||||||
$ssl_ipandports[] = -1;
|
|
||||||
|
|
||||||
// HSTS
|
// HSTS
|
||||||
$hsts_maxage = 0;
|
$hsts_maxage = 0;
|
||||||
@@ -1650,6 +1652,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
|| $iswildcarddomain != $result['iswildcarddomain']
|
|| $iswildcarddomain != $result['iswildcarddomain']
|
||||||
|| $phpenabled != $result['phpenabled']
|
|| $phpenabled != $result['phpenabled']
|
||||||
|| $openbasedir != $result['openbasedir']
|
|| $openbasedir != $result['openbasedir']
|
||||||
|
|| $openbasedir_path != $result['openbasedir_path']
|
||||||
|| $phpsettingid != $result['phpsettingid']
|
|| $phpsettingid != $result['phpsettingid']
|
||||||
|| $mod_fcgid_starter != $result['mod_fcgid_starter']
|
|| $mod_fcgid_starter != $result['mod_fcgid_starter']
|
||||||
|| $mod_fcgid_maxrequests != $result['mod_fcgid_maxrequests']
|
|| $mod_fcgid_maxrequests != $result['mod_fcgid_maxrequests']
|
||||||
@@ -1667,6 +1670,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
|| $hsts_sub != $result['hsts_sub']
|
|| $hsts_sub != $result['hsts_sub']
|
||||||
|| $hsts_preload != $result['hsts_preload']
|
|| $hsts_preload != $result['hsts_preload']
|
||||||
|| $ocsp_stapling != $result['ocsp_stapling']
|
|| $ocsp_stapling != $result['ocsp_stapling']
|
||||||
|
|| $sslenabled != $result['ssl_enabled']
|
||||||
) {
|
) {
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
}
|
}
|
||||||
@@ -1815,7 +1819,7 @@ 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['openbasedir_path'] = $openbasedir_path;
|
||||||
$update_data['speciallogfile'] = $speciallogfile;
|
$update_data['speciallogfile'] = $speciallogfile;
|
||||||
$update_data['phpsettingid'] = $phpsettingid;
|
$update_data['phpsettingid'] = $phpsettingid;
|
||||||
|
|||||||
@@ -157,10 +157,10 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
// prefix hash-algo
|
// prefix hash-algo
|
||||||
switch (Settings::Get('system.passwordcryptfunc')) {
|
switch (Settings::Get('system.passwordcryptfunc')) {
|
||||||
case PASSWORD_ARGON2I:
|
case 'argon2i':
|
||||||
$cpPrefix = '{ARGON2I}';
|
$cpPrefix = '{ARGON2I}';
|
||||||
break;
|
break;
|
||||||
case PASSWORD_ARGON2ID:
|
case 'argon2id':
|
||||||
$cpPrefix = '{ARGON2ID}';
|
$cpPrefix = '{ARGON2ID}';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -404,10 +404,10 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
|
|||||||
$password = Crypt::validatePassword($password, true);
|
$password = Crypt::validatePassword($password, true);
|
||||||
// prefix hash-algo
|
// prefix hash-algo
|
||||||
switch (Settings::Get('system.passwordcryptfunc')) {
|
switch (Settings::Get('system.passwordcryptfunc')) {
|
||||||
case PASSWORD_ARGON2I:
|
case 'argon2i':
|
||||||
$cpPrefix = '{ARGON2I}';
|
$cpPrefix = '{ARGON2I}';
|
||||||
break;
|
break;
|
||||||
case PASSWORD_ARGON2ID:
|
case 'argon2id':
|
||||||
$cpPrefix = '{ARGON2ID}';
|
$cpPrefix = '{ARGON2ID}';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class Froxlor extends ApiCommand
|
|||||||
if ($aucheck == 1) {
|
if ($aucheck == 1) {
|
||||||
// anzeige über version-status mit ggfls. formular
|
// anzeige über version-status mit ggfls. formular
|
||||||
// zum update schritt #1 -> download
|
// zum update schritt #1 -> download
|
||||||
$text = lng('update.uc_newinfo', [(Settings::Get('system.update_channel') == 'testing' ? 'testing ' : ''), AutoUpdate::getFromResult('version'), $this->version]);
|
$text = lng('update.uc_newinfo', [(Settings::Get('system.update_channel') != 'stable' ? Settings::Get('system.update_channel').' ' : ''), AutoUpdate::getFromResult('version'), $this->version]);
|
||||||
$response = [
|
$response = [
|
||||||
'isnewerversion' => (int) !AutoUpdate::getFromResult('has_latest'),
|
'isnewerversion' => (int) !AutoUpdate::getFromResult('has_latest'),
|
||||||
'version' => $this->version,
|
'version' => $this->version,
|
||||||
@@ -259,14 +259,15 @@ class Froxlor extends ApiCommand
|
|||||||
* returns a random password based on froxlor settings for min-length, included characters, etc.
|
* returns a random password based on froxlor settings for min-length, included characters, etc.
|
||||||
*
|
*
|
||||||
* @param int $length
|
* @param int $length
|
||||||
* optional length of password, defaults to 10
|
* optional length of password, defaults to 0 (panel.password_min_length)
|
||||||
*
|
*
|
||||||
* @access admin, customer
|
* @access admin, customer
|
||||||
* @return string
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function generatePassword()
|
public function generatePassword(): string
|
||||||
{
|
{
|
||||||
$length = $this->getParam('length', true, 10);
|
$length = $this->getParam('length', true, 0);
|
||||||
return $this->response(Crypt::generatePassword($length));
|
return $this->response(Crypt::generatePassword($length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -176,8 +176,9 @@ class IpsAndPorts extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
if ((int)Settings::Get('system.use_ssl') == 1) {
|
if ((int)Settings::Get('system.use_ssl') == 1) {
|
||||||
$ssl = (bool)$this->getBoolParam('ssl', true, 0);
|
$ssl = (bool)$this->getBoolParam('ssl', true, 0);
|
||||||
$ssl_cert_file = Validate::validate($this->getParam('ssl_cert_file', !$ssl, ''), 'ssl_cert_file', '', '', [], true);
|
$cert_optional = !($ssl && empty(Settings::Get('system.ssl_cert_file')));
|
||||||
$ssl_key_file = Validate::validate($this->getParam('ssl_key_file', !$ssl, ''), 'ssl_key_file', '', '', [], true);
|
$ssl_cert_file = Validate::validate($this->getParam('ssl_cert_file', $cert_optional, ''), 'ssl_cert_file', '', '', [], true);
|
||||||
|
$ssl_key_file = Validate::validate($this->getParam('ssl_key_file', $cert_optional, ''), '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, '');
|
||||||
@@ -415,8 +416,9 @@ class IpsAndPorts extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
if ((int)Settings::Get('system.use_ssl') == 1) {
|
if ((int)Settings::Get('system.use_ssl') == 1) {
|
||||||
$ssl = (bool)$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);
|
$cert_optional = !($ssl && empty(Settings::Get('system.ssl_cert_file')));
|
||||||
$ssl_key_file = Validate::validate($this->getParam('ssl_key_file', !$ssl, $result['ssl_key_file']), 'ssl_key_file', '', '', [], true);
|
$ssl_cert_file = Validate::validate($this->getParam('ssl_cert_file', $cert_optional, $result['ssl_cert_file']), 'ssl_cert_file', '', '', [], true);
|
||||||
|
$ssl_key_file = Validate::validate($this->getParam('ssl_key_file', $cert_optional, $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']);
|
||||||
|
|||||||
@@ -222,8 +222,8 @@ class PhpSettings extends ApiCommand implements ResourceEntity
|
|||||||
* optional request terminate timeout if FPM is used, default is '60s'
|
* optional request terminate timeout if FPM is used, default is '60s'
|
||||||
* @param string $phpfpm_reqslowtimeout
|
* @param string $phpfpm_reqslowtimeout
|
||||||
* optional request slowlog timeout if FPM is used, default is '5s'
|
* optional request slowlog timeout if FPM is used, default is '5s'
|
||||||
* @param bool $phpfpm_pass_authorizationheader
|
* @param bool $pass_authorizationheader
|
||||||
* optional whether to pass authorization header to webserver if FPM is used, default is 0 (false)
|
* optional whether to pass authorization header to webserver if FPM/FCGID is used, default is 0 (false)
|
||||||
* @param bool $override_fpmconfig
|
* @param bool $override_fpmconfig
|
||||||
* optional whether to override fpm-daemon-config value for the following settings if FPM is used,
|
* optional whether to override fpm-daemon-config value for the following settings if FPM is used,
|
||||||
* default is 0 (false)
|
* default is 0 (false)
|
||||||
@@ -276,7 +276,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
|
|||||||
$fpm_enableslowlog = $this->getBoolParam('phpfpm_enable_slowlog', true, 0);
|
$fpm_enableslowlog = $this->getBoolParam('phpfpm_enable_slowlog', true, 0);
|
||||||
$fpm_reqtermtimeout = $this->getParam('phpfpm_reqtermtimeout', true, "60s");
|
$fpm_reqtermtimeout = $this->getParam('phpfpm_reqtermtimeout', true, "60s");
|
||||||
$fpm_reqslowtimeout = $this->getParam('phpfpm_reqslowtimeout', true, "5s");
|
$fpm_reqslowtimeout = $this->getParam('phpfpm_reqslowtimeout', true, "5s");
|
||||||
$fpm_pass_authorizationheader = $this->getBoolParam('phpfpm_pass_authorizationheader', true, 0);
|
$pass_authorizationheader = $this->getBoolParam('pass_authorizationheader', true, 0);
|
||||||
|
|
||||||
$override_fpmconfig = $this->getBoolParam('override_fpmconfig', true, 0);
|
$override_fpmconfig = $this->getBoolParam('override_fpmconfig', true, 0);
|
||||||
$def_fpmconfig = $this->apiCall('FpmDaemons.get', [
|
$def_fpmconfig = $this->apiCall('FpmDaemons.get', [
|
||||||
@@ -312,7 +312,6 @@ class PhpSettings extends ApiCommand implements ResourceEntity
|
|||||||
$fpm_enableslowlog = 0;
|
$fpm_enableslowlog = 0;
|
||||||
$fpm_reqtermtimeout = 0;
|
$fpm_reqtermtimeout = 0;
|
||||||
$fpm_reqslowtimeout = 0;
|
$fpm_reqslowtimeout = 0;
|
||||||
$fpm_pass_authorizationheader = 0;
|
|
||||||
$override_fpmconfig = 0;
|
$override_fpmconfig = 0;
|
||||||
} elseif (Settings::Get('phpfpm.enabled') == 1) {
|
} elseif (Settings::Get('phpfpm.enabled') == 1) {
|
||||||
$fpm_reqtermtimeout = Validate::validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true);
|
$fpm_reqtermtimeout = Validate::validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true);
|
||||||
@@ -377,7 +376,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
|
|||||||
'fpmreqslow' => $fpm_reqslowtimeout,
|
'fpmreqslow' => $fpm_reqslowtimeout,
|
||||||
'phpsettings' => $phpsettings,
|
'phpsettings' => $phpsettings,
|
||||||
'fpmsettingid' => $fpm_config_id,
|
'fpmsettingid' => $fpm_config_id,
|
||||||
'fpmpassauth' => $fpm_pass_authorizationheader,
|
'fpmpassauth' => $pass_authorizationheader,
|
||||||
'ofc' => $override_fpmconfig,
|
'ofc' => $override_fpmconfig,
|
||||||
'pm' => $pmanager,
|
'pm' => $pmanager,
|
||||||
'max_children' => $max_children,
|
'max_children' => $max_children,
|
||||||
@@ -464,7 +463,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
|
|||||||
* optional request terminate timeout if FPM is used, default is '60s'
|
* optional request terminate timeout if FPM is used, default is '60s'
|
||||||
* @param string $phpfpm_reqslowtimeout
|
* @param string $phpfpm_reqslowtimeout
|
||||||
* optional request slowlog timeout if FPM is used, default is '5s'
|
* optional request slowlog timeout if FPM is used, default is '5s'
|
||||||
* @param bool $phpfpm_pass_authorizationheader
|
* @param bool $pass_authorizationheader
|
||||||
* optional whether to pass authorization header to webserver if FPM is used, default is 0 (false)
|
* optional whether to pass authorization header to webserver if FPM is used, default is 0 (false)
|
||||||
* @param bool $override_fpmconfig
|
* @param bool $override_fpmconfig
|
||||||
* optional whether to override fpm-daemon-config value for the following settings if FPM is used,
|
* optional whether to override fpm-daemon-config value for the following settings if FPM is used,
|
||||||
@@ -516,7 +515,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
|
|||||||
$fpm_enableslowlog = $this->getBoolParam('phpfpm_enable_slowlog', true, $result['fpm_slowlog']);
|
$fpm_enableslowlog = $this->getBoolParam('phpfpm_enable_slowlog', true, $result['fpm_slowlog']);
|
||||||
$fpm_reqtermtimeout = $this->getParam('phpfpm_reqtermtimeout', true, $result['fpm_reqterm']);
|
$fpm_reqtermtimeout = $this->getParam('phpfpm_reqtermtimeout', true, $result['fpm_reqterm']);
|
||||||
$fpm_reqslowtimeout = $this->getParam('phpfpm_reqslowtimeout', true, $result['fpm_reqslow']);
|
$fpm_reqslowtimeout = $this->getParam('phpfpm_reqslowtimeout', true, $result['fpm_reqslow']);
|
||||||
$fpm_pass_authorizationheader = $this->getBoolParam('phpfpm_pass_authorizationheader', true, $result['pass_authorizationheader']);
|
$pass_authorizationheader = $this->getBoolParam('pass_authorizationheader', true, $result['pass_authorizationheader']);
|
||||||
$override_fpmconfig = $this->getBoolParam('override_fpmconfig', true, $result['override_fpmconfig']);
|
$override_fpmconfig = $this->getBoolParam('override_fpmconfig', true, $result['override_fpmconfig']);
|
||||||
$pmanager = $this->getParam('pm', true, $result['pm']);
|
$pmanager = $this->getParam('pm', true, $result['pm']);
|
||||||
$max_children = $this->getParam('max_children', true, $result['max_children']);
|
$max_children = $this->getParam('max_children', true, $result['max_children']);
|
||||||
@@ -548,7 +547,6 @@ class PhpSettings extends ApiCommand implements ResourceEntity
|
|||||||
$fpm_enableslowlog = 0;
|
$fpm_enableslowlog = 0;
|
||||||
$fpm_reqtermtimeout = 0;
|
$fpm_reqtermtimeout = 0;
|
||||||
$fpm_reqslowtimeout = 0;
|
$fpm_reqslowtimeout = 0;
|
||||||
$fpm_pass_authorizationheader = 0;
|
|
||||||
$override_fpmconfig = 0;
|
$override_fpmconfig = 0;
|
||||||
} elseif (Settings::Get('phpfpm.enabled') == 1) {
|
} elseif (Settings::Get('phpfpm.enabled') == 1) {
|
||||||
$fpm_reqtermtimeout = Validate::validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true);
|
$fpm_reqtermtimeout = Validate::validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true);
|
||||||
@@ -614,7 +612,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
|
|||||||
'fpmreqslow' => $fpm_reqslowtimeout,
|
'fpmreqslow' => $fpm_reqslowtimeout,
|
||||||
'phpsettings' => $phpsettings,
|
'phpsettings' => $phpsettings,
|
||||||
'fpmsettingid' => $fpm_config_id,
|
'fpmsettingid' => $fpm_config_id,
|
||||||
'fpmpassauth' => $fpm_pass_authorizationheader,
|
'fpmpassauth' => $pass_authorizationheader,
|
||||||
'ofc' => $override_fpmconfig,
|
'ofc' => $override_fpmconfig,
|
||||||
'pm' => $pmanager,
|
'pm' => $pmanager,
|
||||||
'max_children' => $max_children,
|
'max_children' => $max_children,
|
||||||
|
|||||||
@@ -296,6 +296,8 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
// assign default config
|
// assign default config
|
||||||
$phpsid_result['phpsettingid'] = 1;
|
$phpsid_result['phpsettingid'] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($domain_check['phpenabled'] == 1) {
|
||||||
// check whether the customer has chosen its own php-config
|
// check whether the customer has chosen its own php-config
|
||||||
if ($phpsettingid > 0 && $phpsettingid != $phpsid_result['phpsettingid']) {
|
if ($phpsettingid > 0 && $phpsettingid != $phpsid_result['phpsettingid']) {
|
||||||
$phpsid_result['phpsettingid'] = intval($phpsettingid);
|
$phpsid_result['phpsettingid'] = intval($phpsettingid);
|
||||||
@@ -313,6 +315,7 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
Response::standardError('notallowedphpconfigused', '', true);
|
Response::standardError('notallowedphpconfigused', '', true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// actually insert domain
|
// actually insert domain
|
||||||
$stmt = Database::prepare("
|
$stmt = Database::prepare("
|
||||||
@@ -797,7 +800,7 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
$allowed_phpconfigs = [];
|
$allowed_phpconfigs = [];
|
||||||
}
|
}
|
||||||
// only with fcgid/fpm enabled will it be possible to select a php-setting
|
// only with fcgid/fpm enabled will it be possible to select a php-setting
|
||||||
if ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) {
|
if ((int)$result['phpenabled'] == 1 && ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1)) {
|
||||||
if (!in_array($phpsettingid, $allowed_phpconfigs)) {
|
if (!in_array($phpsettingid, $allowed_phpconfigs)) {
|
||||||
Response::standardError('notallowedphpconfigused', '', true);
|
Response::standardError('notallowedphpconfigused', '', true);
|
||||||
}
|
}
|
||||||
@@ -1078,10 +1081,8 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
$custom_list_result = $_custom_list_result['list'];
|
$custom_list_result = $_custom_list_result['list'];
|
||||||
}
|
}
|
||||||
$customer_ids = [];
|
$customer_ids = [];
|
||||||
$customer_stdsubs = [];
|
|
||||||
foreach ($custom_list_result as $customer) {
|
foreach ($custom_list_result as $customer) {
|
||||||
$customer_ids[] = $customer['customerid'];
|
$customer_ids[] = $customer['customerid'];
|
||||||
$customer_stdsubs[$customer['customerid']] = $customer['standardsubdomain'];
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Settings::IsInList('panel.customer_hide_options', 'domains')) {
|
if (Settings::IsInList('panel.customer_hide_options', 'domains')) {
|
||||||
@@ -1090,9 +1091,6 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
$customer_ids = [
|
$customer_ids = [
|
||||||
$this->getUserDetail('customerid')
|
$this->getUserDetail('customerid')
|
||||||
];
|
];
|
||||||
$customer_stdsubs = [
|
|
||||||
$this->getUserDetail('customerid') => $this->getUserDetail('standardsubdomain')
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
if (!empty($customer_ids)) {
|
if (!empty($customer_ids)) {
|
||||||
// prepare select statement
|
// prepare select statement
|
||||||
@@ -1101,7 +1099,6 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
FROM `" . TABLE_PANEL_DOMAINS . "` `d`
|
FROM `" . TABLE_PANEL_DOMAINS . "` `d`
|
||||||
WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ")
|
WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ")
|
||||||
AND `d`.`email_only` = '0'
|
AND `d`.`email_only` = '0'
|
||||||
AND `d`.`id` NOT IN (" . implode(', ', $customer_stdsubs) . ")
|
|
||||||
");
|
");
|
||||||
$result = Database::pexecute_first($domains_stmt, null, true, true);
|
$result = Database::pexecute_first($domains_stmt, null, true, true);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
|
|||||||
@@ -402,7 +402,7 @@ final class ConfigServices extends CliCommand
|
|||||||
case "file":
|
case "file":
|
||||||
if (array_key_exists('content', $action)) {
|
if (array_key_exists('content', $action)) {
|
||||||
$output->writeln('<comment>Creating file "' . $action['name'] . '"</>');
|
$output->writeln('<comment>Creating file "' . $action['name'] . '"</>');
|
||||||
file_put_contents($action['name'], trim(strtr($action['content'], $replace_arr)));
|
file_put_contents($action['name'], trim(strtr($action['content'], $replace_arr)) . PHP_EOL);
|
||||||
} elseif (array_key_exists('subcommands', $action)) {
|
} elseif (array_key_exists('subcommands', $action)) {
|
||||||
foreach ($action['subcommands'] as $fileaction) {
|
foreach ($action['subcommands'] as $fileaction) {
|
||||||
if (array_key_exists('execute', $fileaction) && $fileaction['execute'] == "pre") {
|
if (array_key_exists('execute', $fileaction) && $fileaction['execute'] == "pre") {
|
||||||
@@ -411,7 +411,7 @@ final class ConfigServices extends CliCommand
|
|||||||
exec(strtr($fileaction['content'], $replace_arr));
|
exec(strtr($fileaction['content'], $replace_arr));
|
||||||
} elseif ($fileaction['type'] == 'file') {
|
} elseif ($fileaction['type'] == 'file') {
|
||||||
$output->writeln('<comment>Creating file "' . $fileaction['name'] . '"</>');
|
$output->writeln('<comment>Creating file "' . $fileaction['name'] . '"</>');
|
||||||
file_put_contents($fileaction['name'], trim(strtr($fileaction['content'], $replace_arr)));
|
file_put_contents($fileaction['name'], trim(strtr($fileaction['content'], $replace_arr)) . PHP_EOL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -514,6 +514,7 @@ final class ConfigServices extends CliCommand
|
|||||||
'<WEBSERVER_GROUP>' => Settings::Get('system.httpgroup'),
|
'<WEBSERVER_GROUP>' => Settings::Get('system.httpgroup'),
|
||||||
'<SSL_CERT_FILE>' => Settings::Get('system.ssl_cert_file'),
|
'<SSL_CERT_FILE>' => Settings::Get('system.ssl_cert_file'),
|
||||||
'<SSL_KEY_FILE>' => Settings::Get('system.ssl_key_file'),
|
'<SSL_KEY_FILE>' => Settings::Get('system.ssl_key_file'),
|
||||||
|
'<ADMIN_MAIL>' => Settings::Get('panel.adminmail'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ final class InstallCommand extends Command
|
|||||||
$ask_field = false;
|
$ask_field = false;
|
||||||
}
|
}
|
||||||
$fielddata['value'] = $this->formfielddata[$fieldname] ?? ($fielddata['value'] ?? null);
|
$fielddata['value'] = $this->formfielddata[$fieldname] ?? ($fielddata['value'] ?? null);
|
||||||
$fielddata['label'] = strip_tags(str_replace("<br>", " ", $fielddata['label']));
|
$fielddata['label'] = $this->cliTextFormat($fielddata['label'], " ");
|
||||||
if ($ask_field) {
|
if ($ask_field) {
|
||||||
if ($fielddata['type'] == 'password') {
|
if ($fielddata['type'] == 'password') {
|
||||||
$this->formfielddata[$fieldname] = $this->io->askHidden($fielddata['label'], function ($value) use ($fielddata) {
|
$this->formfielddata[$fieldname] = $this->io->askHidden($fielddata['label'], function ($value) use ($fielddata) {
|
||||||
@@ -267,15 +267,17 @@ final class InstallCommand extends Command
|
|||||||
case 4:
|
case 4:
|
||||||
$section = $inst->formfield['install']['sections']['step' . $step] ?? [];
|
$section = $inst->formfield['install']['sections']['step' . $step] ?? [];
|
||||||
$this->io->section($section['title']);
|
$this->io->section($section['title']);
|
||||||
$this->io->note($section['description']);
|
$this->io->note($this->cliTextFormat($section['description']));
|
||||||
$cmdfield = $section['fields']['system'];
|
$cmdfield = $section['fields']['system'];
|
||||||
$this->io->success([
|
$this->io->success([
|
||||||
$cmdfield['label'],
|
$cmdfield['label'],
|
||||||
$cmdfield['value']
|
$cmdfield['value']
|
||||||
]);
|
]);
|
||||||
|
if (!isset($decoded_input['manual_config']) || (bool)$decoded_input['manual_config'] === false) {
|
||||||
if (!empty($decoded_input) || $this->io->confirm('Execute command now?', false)) {
|
if (!empty($decoded_input) || $this->io->confirm('Execute command now?', false)) {
|
||||||
passthru($cmdfield['value']);
|
passthru($cmdfield['value']);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
@@ -305,7 +307,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' || $name == 'target_servername') {
|
if ($name == 'system' || $name == 'target_servername') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($field['type'] == 'text' || $field['type'] == 'email') {
|
if ($field['type'] == 'text' || $field['type'] == 'email') {
|
||||||
@@ -346,4 +348,10 @@ final class InstallCommand extends Command
|
|||||||
curl_close($ch);
|
curl_close($ch);
|
||||||
fclose($fp);
|
fclose($fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function cliTextFormat(string $text, string $nl_char = "\n"): string
|
||||||
|
{
|
||||||
|
$text = str_replace(['<br>', '<br/>', '<br />'], [$nl_char, $nl_char, $nl_char], $text);
|
||||||
|
return strip_tags($text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,6 +263,8 @@ final class MasterCron extends CliCommand
|
|||||||
if ($jobcount > 0) {
|
if ($jobcount > 0) {
|
||||||
if (Settings::Get('system.nssextrausers') == 1) {
|
if (Settings::Get('system.nssextrausers') == 1) {
|
||||||
Extrausers::generateFiles($this->cronLog);
|
Extrausers::generateFiles($this->cronLog);
|
||||||
|
// reload crond as shell users might use crontab and the user is only known to crond if reloaded
|
||||||
|
FileDir::safe_exec(escapeshellcmd(Settings::Get('system.crondreload')));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,6 +277,8 @@ final class MasterCron extends CliCommand
|
|||||||
FileDir::safe_exec('nscd -i group 1> /dev/null', $false_val, [
|
FileDir::safe_exec('nscd -i group 1> /dev/null', $false_val, [
|
||||||
'>'
|
'>'
|
||||||
]);
|
]);
|
||||||
|
// reload crond as shell users might use crontab and the user is only known to crond if reloaded
|
||||||
|
FileDir::safe_exec(escapeshellcmd(Settings::Get('system.crondreload')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ final class UpdateCommand extends CliCommand
|
|||||||
|
|
||||||
// database update only
|
// database update only
|
||||||
if ($input->getOption('database')) {
|
if ($input->getOption('database')) {
|
||||||
$result = $this->validateRequirements($input, $output, true);
|
$result = $this->validateRequirements($output, true);
|
||||||
if ($result == self::SUCCESS) {
|
if ($result == self::SUCCESS) {
|
||||||
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
|
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
|
||||||
$output->writeln('<info>' . lng('updates.dbupdate_required') . '</>');
|
$output->writeln('<info>' . lng('updates.dbupdate_required') . '</>');
|
||||||
@@ -77,7 +77,7 @@ final class UpdateCommand extends CliCommand
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->validateRequirements($input, $output);
|
$result = $this->validateRequirements($output);
|
||||||
|
|
||||||
if ($result != self::SUCCESS) {
|
if ($result != self::SUCCESS) {
|
||||||
// requirements failed, exit
|
// requirements failed, exit
|
||||||
@@ -100,7 +100,7 @@ final class UpdateCommand extends CliCommand
|
|||||||
}
|
}
|
||||||
// there is a new version
|
// there is a new version
|
||||||
if ($input->getOption('check-only')) {
|
if ($input->getOption('check-only')) {
|
||||||
$text = lng('update.uc_newinfo', [(Settings::Get('system.update_channel') == 'testing' ? 'testing ' : ''), AutoUpdate::getFromResult('version'), Froxlor::VERSION]);
|
$text = lng('update.uc_newinfo', [(Settings::Get('system.update_channel') != 'stable' ? Settings::Get('system.update_channel').' ' : ''), AutoUpdate::getFromResult('version'), Froxlor::VERSION]);
|
||||||
} else {
|
} else {
|
||||||
$text = lng('admin.newerversionavailable') . ' ' . lng('admin.newerversiondetails', [AutoUpdate::getFromResult('version'), Froxlor::VERSION]);
|
$text = lng('admin.newerversionavailable') . ' ' . lng('admin.newerversiondetails', [AutoUpdate::getFromResult('version'), Froxlor::VERSION]);
|
||||||
}
|
}
|
||||||
@@ -175,7 +175,7 @@ final class UpdateCommand extends CliCommand
|
|||||||
$result = self::SUCCESS;
|
$result = self::SUCCESS;
|
||||||
$question = new ConfirmationQuestion('Update database? [no] ', false, '/^(y|j)/i');
|
$question = new ConfirmationQuestion('Update database? [no] ', false, '/^(y|j)/i');
|
||||||
if ($yestoall || $helper->ask($input, $output, $question)) {
|
if ($yestoall || $helper->ask($input, $output, $question)) {
|
||||||
$result = $this->updateDatabase();
|
$result = $this->runUpdate($output, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$errmsg = 'error.autoupdate_' . $auex;
|
$errmsg = 'error.autoupdate_' . $auex;
|
||||||
@@ -199,7 +199,7 @@ final class UpdateCommand extends CliCommand
|
|||||||
if ($input->getOption('mail-notify')) {
|
if ($input->getOption('mail-notify')) {
|
||||||
$last_check_version = Settings::Get('system.update_notify_last');
|
$last_check_version = Settings::Get('system.update_notify_last');
|
||||||
if (Update::versionInUpdate($last_check_version, AutoUpdate::getFromResult('version'))) {
|
if (Update::versionInUpdate($last_check_version, AutoUpdate::getFromResult('version'))) {
|
||||||
$text = lng('update.uc_newinfo', [(Settings::Get('system.update_channel') == 'testing' ? 'testing ' : ''), AutoUpdate::getFromResult('version'), Froxlor::VERSION]);
|
$text = lng('update.uc_newinfo', [(Settings::Get('system.update_channel') != 'stable' ? Settings::Get('system.update_channel').' ' : ''), AutoUpdate::getFromResult('version'), Froxlor::VERSION]);
|
||||||
$mail = new Mailer(true);
|
$mail = new Mailer(true);
|
||||||
$mail->Body = $text;
|
$mail->Body = $text;
|
||||||
$mail->Subject = "[froxlor] " . lng('update.notify_subject');
|
$mail->Subject = "[froxlor] " . lng('update.notify_subject');
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ class ConfigDisplay
|
|||||||
'<SQL_UNPRIVILEGED_PASSWORD>' => 'FROXLOR_MYSQL_PASSWORD',
|
'<SQL_UNPRIVILEGED_PASSWORD>' => 'FROXLOR_MYSQL_PASSWORD',
|
||||||
'<SQL_DB>' => $sql['db'],
|
'<SQL_DB>' => $sql['db'],
|
||||||
'<SQL_HOST>' => $sql['host'],
|
'<SQL_HOST>' => $sql['host'],
|
||||||
'<SQL_SOCKET>' => isset($sql['socket']) ? $sql['socket'] : null,
|
'<SQL_SOCKET>' => $sql['socket'] ?? null,
|
||||||
'<SERVERNAME>' => Settings::Get('system.hostname'),
|
'<SERVERNAME>' => Settings::Get('system.hostname'),
|
||||||
'<SERVERIP>' => Settings::Get('system.ipaddress'),
|
'<SERVERIP>' => Settings::Get('system.ipaddress'),
|
||||||
'<NAMESERVERS>' => Settings::Get('system.nameservers'),
|
'<NAMESERVERS>' => Settings::Get('system.nameservers'),
|
||||||
@@ -127,12 +127,15 @@ class ConfigDisplay
|
|||||||
'<VIRTUAL_GID_MAPS>' => Settings::Get('system.vmail_gid'),
|
'<VIRTUAL_GID_MAPS>' => Settings::Get('system.vmail_gid'),
|
||||||
'<SSLPROTOCOLS>' => (Settings::Get('system.use_ssl') == '1') ? 'imaps pop3s' : '',
|
'<SSLPROTOCOLS>' => (Settings::Get('system.use_ssl') == '1') ? 'imaps pop3s' : '',
|
||||||
'<CUSTOMER_TMP>' => FileDir::makeCorrectDir($customer_tmpdir),
|
'<CUSTOMER_TMP>' => FileDir::makeCorrectDir($customer_tmpdir),
|
||||||
'<BASE_PATH>' => FileDir::makeCorrectDir(Froxlor::getInstallDir()),
|
'<BASE_PATH>' => Froxlor::getInstallDir(),
|
||||||
'<BIND_CONFIG_PATH>' => FileDir::makeCorrectDir(Settings::Get('system.bindconf_directory')),
|
'<BIND_CONFIG_PATH>' => FileDir::makeCorrectDir(Settings::Get('system.bindconf_directory')),
|
||||||
'<WEBSERVER_RELOAD_CMD>' => Settings::Get('system.apachereload_command'),
|
'<WEBSERVER_RELOAD_CMD>' => Settings::Get('system.apachereload_command'),
|
||||||
'<CUSTOMER_LOGS>' => FileDir::makeCorrectDir(Settings::Get('system.logfiles_directory')),
|
'<CUSTOMER_LOGS>' => FileDir::makeCorrectDir(Settings::Get('system.logfiles_directory')),
|
||||||
'<FPM_IPCDIR>' => FileDir::makeCorrectDir(Settings::Get('phpfpm.fastcgi_ipcdir')),
|
'<FPM_IPCDIR>' => FileDir::makeCorrectDir(Settings::Get('phpfpm.fastcgi_ipcdir')),
|
||||||
'<WEBSERVER_GROUP>' => Settings::Get('system.httpgroup')
|
'<WEBSERVER_GROUP>' => Settings::Get('system.httpgroup'),
|
||||||
|
'<SSL_CERT_FILE>' => Settings::Get('system.ssl_cert_file'),
|
||||||
|
'<SSL_KEY_FILE>' => Settings::Get('system.ssl_key_file'),
|
||||||
|
'<ADMIN_MAIL>' => Settings::Get('panel.adminmail'),
|
||||||
];
|
];
|
||||||
|
|
||||||
$commands_pre = "";
|
$commands_pre = "";
|
||||||
|
|||||||
@@ -55,12 +55,10 @@ class Bind extends DnsBase
|
|||||||
$domains = $this->getDomainList();
|
$domains = $this->getDomainList();
|
||||||
|
|
||||||
if (empty($domains)) {
|
if (empty($domains)) {
|
||||||
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, skipping...');
|
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, not creating any zones...');
|
||||||
return;
|
$this->bindconf_file = '';
|
||||||
}
|
} else {
|
||||||
|
|
||||||
$this->bindconf_file = '# ' . Settings::Get('system.bindconf_directory') . 'froxlor_bind.conf' . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n\n";
|
$this->bindconf_file = '# ' . Settings::Get('system.bindconf_directory') . 'froxlor_bind.conf' . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n\n";
|
||||||
|
|
||||||
foreach ($domains as $domain) {
|
foreach ($domains as $domain) {
|
||||||
if ($domain['is_child']) {
|
if ($domain['is_child']) {
|
||||||
// domains that are subdomains to other main domains are handled by recursion within walkDomainList()
|
// domains that are subdomains to other main domains are handled by recursion within walkDomainList()
|
||||||
@@ -68,6 +66,7 @@ class Bind extends DnsBase
|
|||||||
}
|
}
|
||||||
$this->walkDomainList($domain, $domains);
|
$this->walkDomainList($domain, $domains);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$bindconf_file_handler = fopen(FileDir::makeCorrectFile(Settings::Get('system.bindconf_directory') . '/froxlor_bind.conf'), 'w');
|
$bindconf_file_handler = fopen(FileDir::makeCorrectFile(Settings::Get('system.bindconf_directory') . '/froxlor_bind.conf'), 'w');
|
||||||
fwrite($bindconf_file_handler, $this->bindconf_file);
|
fwrite($bindconf_file_handler, $this->bindconf_file);
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ abstract class DnsBase
|
|||||||
'zonefile' => '',
|
'zonefile' => '',
|
||||||
'froxlorhost' => '1'
|
'froxlorhost' => '1'
|
||||||
];
|
];
|
||||||
$domains['none'] = $hostname_arr;
|
$domains[0] = $hostname_arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($domains)) {
|
if (empty($domains)) {
|
||||||
|
|||||||
@@ -45,10 +45,8 @@ class PowerDNS extends DnsBase
|
|||||||
$this->clearZoneTables($domains);
|
$this->clearZoneTables($domains);
|
||||||
|
|
||||||
if (empty($domains)) {
|
if (empty($domains)) {
|
||||||
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, skipping...');
|
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, not creating any zones...');
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($domains as $domain) {
|
foreach ($domains as $domain) {
|
||||||
if ($domain['is_child']) {
|
if ($domain['is_child']) {
|
||||||
// domains that are subdomains to other main domains are handled by recursion within walkDomainList()
|
// domains that are subdomains to other main domains are handled by recursion within walkDomainList()
|
||||||
@@ -56,7 +54,7 @@ class PowerDNS extends DnsBase
|
|||||||
}
|
}
|
||||||
$this->walkDomainList($domain, $domains);
|
$this->walkDomainList($domain, $domains);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'PowerDNS database updated');
|
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'PowerDNS database updated');
|
||||||
$this->reloadDaemon();
|
$this->reloadDaemon();
|
||||||
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Task4 finished');
|
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Task4 finished');
|
||||||
|
|||||||
@@ -25,19 +25,21 @@
|
|||||||
|
|
||||||
namespace Froxlor\Cron\Http;
|
namespace Froxlor\Cron\Http;
|
||||||
|
|
||||||
use Froxlor\Froxlor;
|
|
||||||
use Froxlor\Cron\Http\Php\PhpInterface;
|
use Froxlor\Cron\Http\Php\PhpInterface;
|
||||||
|
use Froxlor\Cron\TaskId;
|
||||||
use Froxlor\Customer\Customer;
|
use Froxlor\Customer\Customer;
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
use Froxlor\Domain\Domain;
|
use Froxlor\Domain\Domain;
|
||||||
use Froxlor\FileDir;
|
use Froxlor\FileDir;
|
||||||
|
use Froxlor\Froxlor;
|
||||||
use Froxlor\FroxlorLogger;
|
use Froxlor\FroxlorLogger;
|
||||||
use Froxlor\Http\Directory;
|
use Froxlor\Http\Directory;
|
||||||
use Froxlor\Http\Statistics;
|
use Froxlor\Http\Statistics;
|
||||||
use Froxlor\PhpHelper;
|
use Froxlor\PhpHelper;
|
||||||
use Froxlor\Settings;
|
use Froxlor\Settings;
|
||||||
use Froxlor\Validate\Validate;
|
use Froxlor\System\Cronjob;
|
||||||
use Froxlor\System\Crypt;
|
use Froxlor\System\Crypt;
|
||||||
|
use Froxlor\Validate\Validate;
|
||||||
use PDO;
|
use PDO;
|
||||||
|
|
||||||
class Apache extends HttpConfigBase
|
class Apache extends HttpConfigBase
|
||||||
@@ -133,6 +135,7 @@ class Apache extends HttpConfigBase
|
|||||||
if (Settings::Get('system.le_froxlor_enabled') && ($this->froxlorVhostHasLetsEncryptCert() == false || $this->froxlorVhostLetsEncryptNeedsRenew())) {
|
if (Settings::Get('system.le_froxlor_enabled') && ($this->froxlorVhostHasLetsEncryptCert() == false || $this->froxlorVhostLetsEncryptNeedsRenew())) {
|
||||||
$this->virtualhosts_data[$vhosts_filename] .= '# temp. disabled ssl-redirect due to Let\'s Encrypt certificate generation.' . PHP_EOL;
|
$this->virtualhosts_data[$vhosts_filename] .= '# temp. disabled ssl-redirect due to Let\'s Encrypt certificate generation.' . PHP_EOL;
|
||||||
$is_redirect = false;
|
$is_redirect = false;
|
||||||
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
} else {
|
} else {
|
||||||
$_sslport = $this->checkAlternativeSslPort();
|
$_sslport = $this->checkAlternativeSslPort();
|
||||||
|
|
||||||
@@ -205,7 +208,9 @@ class Apache extends HttpConfigBase
|
|||||||
];
|
];
|
||||||
$php = new PhpInterface($domain);
|
$php = new PhpInterface($domain);
|
||||||
$phpconfig = $php->getPhpConfig(Settings::Get('system.mod_fcgid_defaultini_ownvhost'));
|
$phpconfig = $php->getPhpConfig(Settings::Get('system.mod_fcgid_defaultini_ownvhost'));
|
||||||
|
if ($phpconfig['pass_authorizationheader'] == '1') {
|
||||||
|
$this->virtualhosts_data[$vhosts_filename] .= ' FcgidPassHeader Authorization' . "\n";
|
||||||
|
}
|
||||||
$starter_filename = FileDir::makeCorrectFile($configdir . '/php-fcgi-starter');
|
$starter_filename = FileDir::makeCorrectFile($configdir . '/php-fcgi-starter');
|
||||||
$this->virtualhosts_data[$vhosts_filename] .= ' SuexecUserGroup "' . Settings::Get('system.mod_fcgid_httpuser') . '" "' . Settings::Get('system.mod_fcgid_httpgroup') . '"' . "\n";
|
$this->virtualhosts_data[$vhosts_filename] .= ' SuexecUserGroup "' . Settings::Get('system.mod_fcgid_httpuser') . '" "' . Settings::Get('system.mod_fcgid_httpgroup') . '"' . "\n";
|
||||||
$this->virtualhosts_data[$vhosts_filename] .= ' <Directory "' . $mypath . '">' . "\n";
|
$this->virtualhosts_data[$vhosts_filename] .= ' <Directory "' . $mypath . '">' . "\n";
|
||||||
@@ -276,7 +281,9 @@ class Apache extends HttpConfigBase
|
|||||||
// start block, cut off last pipe and close block
|
// start block, cut off last pipe and close block
|
||||||
$filesmatch = '(' . str_replace(".", "\.", substr($filesmatch, 0, -1)) . ')';
|
$filesmatch = '(' . str_replace(".", "\.", substr($filesmatch, 0, -1)) . ')';
|
||||||
$this->virtualhosts_data[$vhosts_filename] .= ' <FilesMatch \.' . $filesmatch . '$>' . "\n";
|
$this->virtualhosts_data[$vhosts_filename] .= ' <FilesMatch \.' . $filesmatch . '$>' . "\n";
|
||||||
|
$this->virtualhosts_data[$vhosts_filename] .= ' <If "-f %{SCRIPT_FILENAME}">' . "\n";
|
||||||
$this->virtualhosts_data[$vhosts_filename] .= ' SetHandler proxy:unix:' . $php->getInterface()->getSocketFile() . '|fcgi://localhost' . "\n";
|
$this->virtualhosts_data[$vhosts_filename] .= ' SetHandler proxy:unix:' . $php->getInterface()->getSocketFile() . '|fcgi://localhost' . "\n";
|
||||||
|
$this->virtualhosts_data[$vhosts_filename] .= ' </If>' . "\n";
|
||||||
$this->virtualhosts_data[$vhosts_filename] .= ' </FilesMatch>' . "\n";
|
$this->virtualhosts_data[$vhosts_filename] .= ' </FilesMatch>' . "\n";
|
||||||
if ($phpconfig['pass_authorizationheader'] == '1') {
|
if ($phpconfig['pass_authorizationheader'] == '1') {
|
||||||
$this->virtualhosts_data[$vhosts_filename] .= ' <Directory "' . $mypath . '">' . "\n";
|
$this->virtualhosts_data[$vhosts_filename] .= ' <Directory "' . $mypath . '">' . "\n";
|
||||||
@@ -515,13 +522,7 @@ class Apache extends HttpConfigBase
|
|||||||
*/
|
*/
|
||||||
private function createStandardDirectoryEntry()
|
private function createStandardDirectoryEntry()
|
||||||
{
|
{
|
||||||
$vhosts_folder = '';
|
$vhosts_filename = $this->getCustomVhostFilename('05_froxlor_dirfix_nofcgid.conf');
|
||||||
if (is_dir(Settings::Get('system.apacheconf_vhost'))) {
|
|
||||||
$vhosts_folder = FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost'));
|
|
||||||
} else {
|
|
||||||
$vhosts_folder = FileDir::makeCorrectDir(dirname(Settings::Get('system.apacheconf_vhost')));
|
|
||||||
}
|
|
||||||
$vhosts_filename = FileDir::makeCorrectFile($vhosts_folder . '/05_froxlor_dirfix_nofcgid.conf');
|
|
||||||
|
|
||||||
if (!isset($this->virtualhosts_data[$vhosts_filename])) {
|
if (!isset($this->virtualhosts_data[$vhosts_filename])) {
|
||||||
$this->virtualhosts_data[$vhosts_filename] = '';
|
$this->virtualhosts_data[$vhosts_filename] = '';
|
||||||
@@ -545,7 +546,7 @@ class Apache extends HttpConfigBase
|
|||||||
}
|
}
|
||||||
$this->virtualhosts_data[$vhosts_filename] .= ' </Directory>' . "\n";
|
$this->virtualhosts_data[$vhosts_filename] .= ' </Directory>' . "\n";
|
||||||
|
|
||||||
$ocsp_cache_filename = FileDir::makeCorrectFile($vhosts_folder . '/03_froxlor_ocsp_cache.conf');
|
$ocsp_cache_filename = $this->getCustomVhostFilename('03_froxlor_ocsp_cache.conf');
|
||||||
if (Settings::Get('system.use_ssl') == '1' && Settings::Get('system.apache24') == 1) {
|
if (Settings::Get('system.use_ssl') == '1' && Settings::Get('system.apache24') == 1) {
|
||||||
$this->virtualhosts_data[$ocsp_cache_filename] = 'SSLStaplingCache ' . Settings::Get('system.apache24_ocsp_cache_path') . "\n";
|
$this->virtualhosts_data[$ocsp_cache_filename] = 'SSLStaplingCache ' . Settings::Get('system.apache24_ocsp_cache_path') . "\n";
|
||||||
} else {
|
} else {
|
||||||
@@ -562,14 +563,7 @@ class Apache extends HttpConfigBase
|
|||||||
private function createStandardErrorHandler()
|
private function createStandardErrorHandler()
|
||||||
{
|
{
|
||||||
if (Settings::Get('defaultwebsrverrhandler.enabled') == '1' && (Settings::Get('defaultwebsrverrhandler.err401') != '' || Settings::Get('defaultwebsrverrhandler.err403') != '' || Settings::Get('defaultwebsrverrhandler.err404') != '' || Settings::Get('defaultwebsrverrhandler.err500') != '')) {
|
if (Settings::Get('defaultwebsrverrhandler.enabled') == '1' && (Settings::Get('defaultwebsrverrhandler.err401') != '' || Settings::Get('defaultwebsrverrhandler.err403') != '' || Settings::Get('defaultwebsrverrhandler.err404') != '' || Settings::Get('defaultwebsrverrhandler.err500') != '')) {
|
||||||
$vhosts_folder = '';
|
$vhosts_filename = $this->getCustomVhostFilename('05_froxlor_default_errorhandler.conf');
|
||||||
if (is_dir(Settings::Get('system.apacheconf_vhost'))) {
|
|
||||||
$vhosts_folder = FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost'));
|
|
||||||
} else {
|
|
||||||
$vhosts_folder = FileDir::makeCorrectDir(dirname(Settings::Get('system.apacheconf_vhost')));
|
|
||||||
}
|
|
||||||
|
|
||||||
$vhosts_filename = FileDir::makeCorrectFile($vhosts_folder . '/05_froxlor_default_errorhandler.conf');
|
|
||||||
|
|
||||||
if (!isset($this->virtualhosts_data[$vhosts_filename])) {
|
if (!isset($this->virtualhosts_data[$vhosts_filename])) {
|
||||||
$this->virtualhosts_data[$vhosts_filename] = '';
|
$this->virtualhosts_data[$vhosts_filename] = '';
|
||||||
@@ -855,6 +849,7 @@ class Apache extends HttpConfigBase
|
|||||||
}
|
}
|
||||||
$vhost_content .= $this->getLogfiles($domain);
|
$vhost_content .= $this->getLogfiles($domain);
|
||||||
|
|
||||||
|
if ($this->deactivated == false) {
|
||||||
if ($domain['specialsettings'] != '' && ($ssl_vhost == false || ($ssl_vhost == true && $domain['include_specialsettings'] == 1))) {
|
if ($domain['specialsettings'] != '' && ($ssl_vhost == false || ($ssl_vhost == true && $domain['include_specialsettings'] == 1))) {
|
||||||
$vhost_content .= $this->processSpecialConfigTemplate($domain['specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
|
$vhost_content .= $this->processSpecialConfigTemplate($domain['specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
|
||||||
}
|
}
|
||||||
@@ -875,6 +870,7 @@ class Apache extends HttpConfigBase
|
|||||||
$vhost_content .= $this->processSpecialConfigTemplate(Settings::Get('system.default_sslvhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
|
$vhost_content .= $this->processSpecialConfigTemplate(Settings::Get('system.default_sslvhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$vhost_content .= '</VirtualHost>' . "\n";
|
$vhost_content .= '</VirtualHost>' . "\n";
|
||||||
|
|
||||||
|
|||||||
@@ -43,23 +43,29 @@ class DomainSSL
|
|||||||
* domain-array as reference so we can set the corresponding array-indices
|
* domain-array as reference so we can set the corresponding array-indices
|
||||||
*
|
*
|
||||||
* @return null
|
* @return null
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function setDomainSSLFilesArray(array &$domain = null)
|
public function setDomainSSLFilesArray(array &$domain = null)
|
||||||
{
|
{
|
||||||
// check if the domain itself has a certificate defined
|
// check if the domain itself has a certificate defined
|
||||||
$dom_certs_stmt = Database::prepare("
|
$dom_certs_stmt = Database::prepare("
|
||||||
SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :domid
|
SELECT s.*, d.domain
|
||||||
|
FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s
|
||||||
|
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON d.id = s.domainid
|
||||||
|
WHERE s.`domainid` = :domid
|
||||||
");
|
");
|
||||||
$dom_certs = Database::pexecute_first($dom_certs_stmt, [
|
$dom_certs = Database::pexecute_first($dom_certs_stmt, [
|
||||||
'domid' => $domain['id']
|
'domid' => $domain['id']
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$parent_certificate = false;
|
||||||
if (!is_array($dom_certs) || !isset($dom_certs['ssl_cert_file']) || $dom_certs['ssl_cert_file'] == '') {
|
if (!is_array($dom_certs) || !isset($dom_certs['ssl_cert_file']) || $dom_certs['ssl_cert_file'] == '') {
|
||||||
// maybe its parent?
|
// maybe its parent?
|
||||||
if (isset($domain['parentdomainid']) && $domain['parentdomainid'] != 0) {
|
if (isset($domain['parentdomainid']) && $domain['parentdomainid'] != 0) {
|
||||||
$dom_certs = Database::pexecute_first($dom_certs_stmt, [
|
$dom_certs = Database::pexecute_first($dom_certs_stmt, [
|
||||||
'domid' => $domain['parentdomainid']
|
'domid' => $domain['parentdomainid']
|
||||||
]);
|
]);
|
||||||
|
$parent_certificate = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,8 +79,8 @@ class DomainSSL
|
|||||||
}
|
}
|
||||||
// make correct files for the certificates
|
// make correct files for the certificates
|
||||||
$ssl_files = [
|
$ssl_files = [
|
||||||
'ssl_cert_file' => FileDir::makeCorrectFile($sslcertpath . '/' . $domain['domain'] . '.crt'),
|
'ssl_cert_file' => FileDir::makeCorrectFile($sslcertpath . '/' . ($parent_certificate ? $dom_certs['domain'] : $domain['domain']) . '.crt'),
|
||||||
'ssl_key_file' => FileDir::makeCorrectFile($sslcertpath . '/' . $domain['domain'] . '.key')
|
'ssl_key_file' => FileDir::makeCorrectFile($sslcertpath . '/' . ($parent_certificate ? $dom_certs['domain'] : $domain['domain']) . '.key')
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!$this->validateCertificate($dom_certs)) {
|
if (!$this->validateCertificate($dom_certs)) {
|
||||||
@@ -93,19 +99,19 @@ class DomainSSL
|
|||||||
$ssl_files['ssl_cert_chainfile'] = '';
|
$ssl_files['ssl_cert_chainfile'] = '';
|
||||||
// set them if they are != empty
|
// set them if they are != empty
|
||||||
if ($dom_certs['ssl_ca_file'] != '') {
|
if ($dom_certs['ssl_ca_file'] != '') {
|
||||||
$ssl_files['ssl_ca_file'] = FileDir::makeCorrectFile($sslcertpath . '/' . $domain['domain'] . '_CA.pem');
|
$ssl_files['ssl_ca_file'] = FileDir::makeCorrectFile($sslcertpath . '/' . ($parent_certificate ? $dom_certs['domain'] : $domain['domain']) . '_CA.pem');
|
||||||
}
|
}
|
||||||
if ($dom_certs['ssl_cert_chainfile'] != '') {
|
if ($dom_certs['ssl_cert_chainfile'] != '') {
|
||||||
if (Settings::Get('system.webserver') == 'nginx') {
|
if (Settings::Get('system.webserver') == 'nginx') {
|
||||||
// put ca.crt in my.crt, as nginx does not support a separate chain file.
|
// put ca.crt in my.crt, as nginx does not support a separate chain file.
|
||||||
$dom_certs['ssl_cert_file'] = trim($dom_certs['ssl_cert_file']) . "\n" . trim($dom_certs['ssl_cert_chainfile']) . "\n";
|
$dom_certs['ssl_cert_file'] = trim($dom_certs['ssl_cert_file']) . "\n" . trim($dom_certs['ssl_cert_chainfile']) . "\n";
|
||||||
} else {
|
} else {
|
||||||
$ssl_files['ssl_cert_chainfile'] = FileDir::makeCorrectFile($sslcertpath . '/' . $domain['domain'] . '_chain.pem');
|
$ssl_files['ssl_cert_chainfile'] = FileDir::makeCorrectFile($sslcertpath . '/' . ($parent_certificate ? $dom_certs['domain'] : $domain['domain']) . '_chain.pem');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// will only be generated to be used externally, froxlor does not need this
|
// will only be generated to be used externally, froxlor does not need this
|
||||||
if ($dom_certs['ssl_fullchain_file'] != '') {
|
if ($dom_certs['ssl_fullchain_file'] != '') {
|
||||||
$ssl_files['ssl_fullchain_file'] = FileDir::makeCorrectFile($sslcertpath . '/' . $domain['domain'] . '_fullchain.pem');
|
$ssl_files['ssl_fullchain_file'] = FileDir::makeCorrectFile($sslcertpath . '/' . ($parent_certificate ? $dom_certs['domain'] : $domain['domain']) . '_fullchain.pem');
|
||||||
}
|
}
|
||||||
// create them on the filesystem
|
// create them on the filesystem
|
||||||
foreach ($ssl_files as $type => $filename) {
|
foreach ($ssl_files as $type => $filename) {
|
||||||
@@ -131,7 +137,7 @@ class DomainSSL
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function validateCertificate($dom_certs = [])
|
private function validateCertificate($dom_certs = []): bool
|
||||||
{
|
{
|
||||||
return openssl_x509_check_private_key($dom_certs['ssl_cert_file'], $dom_certs['ssl_key_file']);
|
return openssl_x509_check_private_key($dom_certs['ssl_cert_file'], $dom_certs['ssl_key_file']);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,4 +202,13 @@ class HttpConfigBase
|
|||||||
}
|
}
|
||||||
return FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/' . $filename);
|
return FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/' . $filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getCustomVhostFilename(string $name)
|
||||||
|
{
|
||||||
|
$vhosts_folder = FileDir::makeCorrectDir(dirname(Settings::Get('system.apacheconf_vhost')));
|
||||||
|
if (is_dir(Settings::Get('system.apacheconf_vhost'))) {
|
||||||
|
$vhosts_folder = FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost'));
|
||||||
|
}
|
||||||
|
return FileDir::makeCorrectFile($vhosts_folder . '/' . $name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
namespace Froxlor\Cron\Http\LetsEncrypt;
|
namespace Froxlor\Cron\Http\LetsEncrypt;
|
||||||
|
|
||||||
use Froxlor\Cron\FroxlorCron;
|
use Froxlor\Cron\FroxlorCron;
|
||||||
|
use Froxlor\Cron\TaskId;
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
use Froxlor\Domain\Domain;
|
use Froxlor\Domain\Domain;
|
||||||
use Froxlor\FileDir;
|
use Froxlor\FileDir;
|
||||||
@@ -83,7 +84,7 @@ class AcmeSh extends FroxlorCron
|
|||||||
$renew_domains = self::renewDomains(true);
|
$renew_domains = self::renewDomains(true);
|
||||||
if ($issue_froxlor || !empty($issue_domains) || !empty($renew_froxlor) || $renew_domains) {
|
if ($issue_froxlor || !empty($issue_domains) || !empty($renew_froxlor) || $renew_domains) {
|
||||||
// insert task to generate certificates and vhost-configs
|
// insert task to generate certificates and vhost-configs
|
||||||
Cronjob::inserttask(1);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -203,7 +204,7 @@ class AcmeSh extends FroxlorCron
|
|||||||
// This is easiest done by just creating a new task ;)
|
// This is easiest done by just creating a new task ;)
|
||||||
if ($changedetected) {
|
if ($changedetected) {
|
||||||
if (self::$no_inserttask == false) {
|
if (self::$no_inserttask == false) {
|
||||||
Cronjob::inserttask(1);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
}
|
}
|
||||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Let's Encrypt certificates have been updated");
|
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Let's Encrypt certificates have been updated");
|
||||||
} else {
|
} else {
|
||||||
@@ -520,6 +521,8 @@ EOC;
|
|||||||
self::runAcmeSh($certrow, $domains, $cronlog, $do_force);
|
self::runAcmeSh($certrow, $domains, $cronlog, $do_force);
|
||||||
} else {
|
} else {
|
||||||
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect");
|
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect");
|
||||||
|
// we need another reconfigure in order to get the certificate
|
||||||
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1161,14 +1161,7 @@ class Nginx extends HttpConfigBase
|
|||||||
private function createStandardErrorHandler()
|
private function createStandardErrorHandler()
|
||||||
{
|
{
|
||||||
if (Settings::Get('defaultwebsrverrhandler.enabled') == '1' && (Settings::Get('defaultwebsrverrhandler.err401') != '' || Settings::Get('defaultwebsrverrhandler.err403') != '' || Settings::Get('defaultwebsrverrhandler.err404') != '' || Settings::Get('defaultwebsrverrhandler.err500') != '')) {
|
if (Settings::Get('defaultwebsrverrhandler.enabled') == '1' && (Settings::Get('defaultwebsrverrhandler.err401') != '' || Settings::Get('defaultwebsrverrhandler.err403') != '' || Settings::Get('defaultwebsrverrhandler.err404') != '' || Settings::Get('defaultwebsrverrhandler.err500') != '')) {
|
||||||
$vhosts_folder = '';
|
$vhosts_filename = $this->getCustomVhostFilename('05_froxlor_default_errorhandler.conf');
|
||||||
if (is_dir(Settings::Get('system.apacheconf_vhost'))) {
|
|
||||||
$vhosts_folder = FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost'));
|
|
||||||
} else {
|
|
||||||
$vhosts_folder = FileDir::makeCorrectDir(dirname(Settings::Get('system.apacheconf_vhost')));
|
|
||||||
}
|
|
||||||
|
|
||||||
$vhosts_filename = FileDir::makeCorrectFile($vhosts_folder . '/05_froxlor_default_errorhandler.conf');
|
|
||||||
|
|
||||||
if (!isset($this->nginx_data[$vhosts_filename])) {
|
if (!isset($this->nginx_data[$vhosts_filename])) {
|
||||||
$this->nginx_data[$vhosts_filename] = '';
|
$this->nginx_data[$vhosts_filename] = '';
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class TrafficCron extends FroxlorCron
|
|||||||
|
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
self::runFork([self::class, 'handle']);
|
self::runFork([self::class, 'handle'], [true]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function handle()
|
public static function handle()
|
||||||
@@ -163,14 +163,14 @@ class TrafficCron extends FroxlorCron
|
|||||||
|
|
||||||
if (isset($domainlist[$row['customerid']]) && is_array($domainlist[$row['customerid']]) && count($domainlist[$row['customerid']]) != 0) {
|
if (isset($domainlist[$row['customerid']]) && is_array($domainlist[$row['customerid']]) && count($domainlist[$row['customerid']]) != 0) {
|
||||||
// Examining which caption to use for default webalizer stats...
|
// Examining which caption to use for default webalizer stats...
|
||||||
if ($row['standardsubdomain'] != '0') {
|
if ($row['standardsubdomain'] != '0' && isset($domainlist[$row['customerid']][$row['standardsubdomain']])) {
|
||||||
// ... of course we'd prefer to use the standardsubdomain ...
|
// ... of course we'd prefer to use the standardsubdomain ...
|
||||||
$caption = $domainlist[$row['customerid']][$row['standardsubdomain']];
|
$caption = $domainlist[$row['customerid']][$row['standardsubdomain']];
|
||||||
} else {
|
} else {
|
||||||
// ... but if there is no standardsubdomain, we have to use the loginname ...
|
// ... but if there is no standardsubdomain, we have to use the loginname ...
|
||||||
$caption = $row['loginname'];
|
$caption = $row['loginname'];
|
||||||
|
|
||||||
// ... which results in non-usable links to files in the stats, so lets have a look if we find a domain which is not speciallogfiledomain
|
// ... which results in non-usable links to files in the stats, so let's have a look if we find a domain which is not speciallogfiledomain
|
||||||
foreach ($domainlist[$row['customerid']] as $domainid => $domain) {
|
foreach ($domainlist[$row['customerid']] as $domainid => $domain) {
|
||||||
if (!isset($speciallogfile_domainlist[$row['customerid']]) || !isset($speciallogfile_domainlist[$row['customerid']][$domainid])) {
|
if (!isset($speciallogfile_domainlist[$row['customerid']]) || !isset($speciallogfile_domainlist[$row['customerid']][$domainid])) {
|
||||||
$caption = $domain;
|
$caption = $domain;
|
||||||
@@ -193,6 +193,8 @@ class TrafficCron extends FroxlorCron
|
|||||||
} else {
|
} else {
|
||||||
$httptraffic += floatval(self::callWebalizerGetTraffic($row['loginname'] . '-' . $domain, $row['documentroot'] . '/webalizer/' . $domain . '/', $domain, $domainlist[$row['customerid']]));
|
$httptraffic += floatval(self::callWebalizerGetTraffic($row['loginname'] . '-' . $domain, $row['documentroot'] . '/webalizer/' . $domain . '/', $domain, $domainlist[$row['customerid']]));
|
||||||
}
|
}
|
||||||
|
// kind of a keep-alive-call as this unsets the link which leads to a new connection to the database
|
||||||
|
Database::needRoot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,6 +212,8 @@ class TrafficCron extends FroxlorCron
|
|||||||
} else {
|
} else {
|
||||||
$httptraffic += floatval(self::callWebalizerGetTraffic($row['loginname'], $row['documentroot'] . '/webalizer/', $caption, $domainlist[$row['customerid']]));
|
$httptraffic += floatval(self::callWebalizerGetTraffic($row['loginname'], $row['documentroot'] . '/webalizer/', $caption, $domainlist[$row['customerid']]));
|
||||||
}
|
}
|
||||||
|
// kind of a keep-alive-call as this unsets the link which leads to a new connection to the database
|
||||||
|
Database::needRoot();
|
||||||
|
|
||||||
// make the stuff readable for the customer, #258
|
// make the stuff readable for the customer, #258
|
||||||
Statistics::makeChownWithNewStats($row);
|
Statistics::makeChownWithNewStats($row);
|
||||||
@@ -618,7 +622,7 @@ class TrafficCron extends FroxlorCron
|
|||||||
$format = Settings::Get('system.logfiles_type') == '2' ? 'VCOMBINED' : 'COMBINED';
|
$format = Settings::Get('system.logfiles_type') == '2' ? 'VCOMBINED' : 'COMBINED';
|
||||||
$monthyear = $monthyear_arr['month'] . '/' . $monthyear_arr['year'];
|
$monthyear = $monthyear_arr['month'] . '/' . $monthyear_arr['year'];
|
||||||
$return_value = false;
|
$return_value = false;
|
||||||
FileDir::safe_exec("grep '" . $monthyear . "' " . escapeshellarg($logfile) . " | goaccess " . $keep_params . " --db-path=" . escapeshellarg($outputdir) . " -o " . escapeshellarg($outputdir . '.tmp.json') . " -o " . escapeshellarg($outputdir . 'index.html') . " --html-report-title=" . escapeshellarg($caption) . " --log-format=" . $format . " - ", $return_value, ['|']);
|
FileDir::safe_exec("grep '" . $monthyear . "' " . escapeshellarg($logfile) . " | goaccess " . $keep_params . " --db-path=" . escapeshellarg($outputdir) . " -o " . escapeshellarg($outputdir . '.tmp.json') . " -o " . escapeshellarg($outputdir . 'index.html') . " --html-report-title=" . escapeshellarg($caption) . " --log-format=" . $format . " --no-parsing-spinner --no-progress - ", $return_value, ['|']);
|
||||||
|
|
||||||
if (file_exists($outputdir . '.tmp.json')) {
|
if (file_exists($outputdir . '.tmp.json')) {
|
||||||
// need jq here because of potentially LARGE json files
|
// need jq here because of potentially LARGE json files
|
||||||
@@ -787,6 +791,8 @@ class TrafficCron extends FroxlorCron
|
|||||||
// 'real' domains and no subdomains which are aliases in the
|
// 'real' domains and no subdomains which are aliases in the
|
||||||
// model-config-file.
|
// model-config-file.
|
||||||
$returnval += self::awstatsDoSingleDomain($singledomain, $outputdir, $current_stamp);
|
$returnval += self::awstatsDoSingleDomain($singledomain, $outputdir, $current_stamp);
|
||||||
|
// kind of a keep-alive-call as this unsets the link which leads to a new connection to the database
|
||||||
|
Database::needRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -187,7 +187,8 @@ class CurrentUser
|
|||||||
if (self::getField('type_2fa') == 1) {
|
if (self::getField('type_2fa') == 1) {
|
||||||
// generate code
|
// generate code
|
||||||
$tfa = new FroxlorTwoFactorAuth('Froxlor ' . Settings::Get('system.hostname'));
|
$tfa = new FroxlorTwoFactorAuth('Froxlor ' . Settings::Get('system.hostname'));
|
||||||
$code = $tfa->getCode($tfa->createSecret());
|
$secret = $tfa->createSecret();
|
||||||
|
$code = $tfa->getCode($secret);
|
||||||
// set code for user
|
// set code for user
|
||||||
$table = TABLE_PANEL_CUSTOMERS;
|
$table = TABLE_PANEL_CUSTOMERS;
|
||||||
$uid = 'customerid';
|
$uid = 'customerid';
|
||||||
@@ -197,7 +198,7 @@ class CurrentUser
|
|||||||
}
|
}
|
||||||
$stmt = Database::prepare("UPDATE $table SET `data_2fa` = :d2fa WHERE `$uid` = :uid");
|
$stmt = Database::prepare("UPDATE $table SET `data_2fa` = :d2fa WHERE `$uid` = :uid");
|
||||||
Database::pexecute($stmt, [
|
Database::pexecute($stmt, [
|
||||||
"d2fa" => $code,
|
"d2fa" => $secret,
|
||||||
"uid" => self::getField($uid)
|
"uid" => self::getField($uid)
|
||||||
]);
|
]);
|
||||||
// build up & send email
|
// build up & send email
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ class Domain
|
|||||||
]);
|
]);
|
||||||
$result = [];
|
$result = [];
|
||||||
while ($entry = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($entry = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
$result = $entry['id'];
|
$result[] = $entry['id'];
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
@@ -324,8 +324,11 @@ class Domain
|
|||||||
FroxlorLogger $log
|
FroxlorLogger $log
|
||||||
) {
|
) {
|
||||||
if ($aliasDestinationDomainID > 0) {
|
if ($aliasDestinationDomainID > 0) {
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO,
|
$log->logAction(
|
||||||
"LetsEncrypt CSR triggered for domain ID " . $aliasDestinationDomainID);
|
FroxlorLogger::ADM_ACTION,
|
||||||
|
LOG_INFO,
|
||||||
|
"LetsEncrypt CSR triggered for domain ID " . $aliasDestinationDomainID
|
||||||
|
);
|
||||||
$upd_stmt = Database::prepare("UPDATE
|
$upd_stmt = Database::prepare("UPDATE
|
||||||
`" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
|
`" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
|
||||||
SET
|
SET
|
||||||
@@ -349,15 +352,20 @@ class Domain
|
|||||||
$acmesh = AcmeSh::getAcmeSh();
|
$acmesh = AcmeSh::getAcmeSh();
|
||||||
if (file_exists($acmesh)) {
|
if (file_exists($acmesh)) {
|
||||||
$certificate_folder = AcmeSh::getWorkingDirFromEnv($domainname);
|
$certificate_folder = AcmeSh::getWorkingDirFromEnv($domainname);
|
||||||
if (file_exists($certificate_folder)) {
|
$certificate_ecc_folder = AcmeSh::getWorkingDirFromEnv($domainname, true);
|
||||||
|
if (file_exists($certificate_folder) || file_exists($certificate_ecc_folder)) {
|
||||||
$params = " --remove -d " . $domainname;
|
$params = " --remove -d " . $domainname;
|
||||||
if (Settings::Get('system.leecc') > 0) {
|
if (file_exists($certificate_ecc_folder)) {
|
||||||
$params .= " --ecc";
|
$params .= " --ecc";
|
||||||
}
|
}
|
||||||
// run remove command
|
// run remove command
|
||||||
FileDir::safe_exec($acmesh . $params);
|
FileDir::safe_exec($acmesh . $params);
|
||||||
// remove certificates directory
|
// remove certificates directory
|
||||||
|
if (file_exists($certificate_folder)) {
|
||||||
FileDir::safe_exec('rm -rf ' . $certificate_folder);
|
FileDir::safe_exec('rm -rf ' . $certificate_folder);
|
||||||
|
} elseif (file_exists($certificate_ecc_folder)) {
|
||||||
|
FileDir::safe_exec('rm -rf ' . $certificate_ecc_folder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -43,9 +43,6 @@ class IpAddr
|
|||||||
|
|
||||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
if (!isset($system_ipaddress_array[$row['ip']]) && !in_array($row['ip'], $system_ipaddress_array)) {
|
if (!isset($system_ipaddress_array[$row['ip']]) && !in_array($row['ip'], $system_ipaddress_array)) {
|
||||||
if (filter_var($row['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
|
||||||
$row['ip'] = '[' . $row['ip'] . ']';
|
|
||||||
}
|
|
||||||
$system_ipaddress_array[$row['ip']] = $row['ip'];
|
$system_ipaddress_array[$row['ip']] = $row['ip'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,6 +140,12 @@ class FileDir
|
|||||||
if (is_link($check_dir)) {
|
if (is_link($check_dir)) {
|
||||||
$original_target = $check_dir;
|
$original_target = $check_dir;
|
||||||
$check_dir = readlink($check_dir);
|
$check_dir = readlink($check_dir);
|
||||||
|
$link_dir = dirname($original_target);
|
||||||
|
// check whether the link is relative or absolute
|
||||||
|
if (substr($check_dir, 0, 1) != '/') {
|
||||||
|
// relative directory, prepend link_dir
|
||||||
|
$check_dir = $link_dir . '/' . $check_dir;
|
||||||
|
}
|
||||||
if (substr($check_dir, 0, strlen($fixed_homedir)) != $fixed_homedir) {
|
if (substr($check_dir, 0, strlen($fixed_homedir)) != $fixed_homedir) {
|
||||||
throw new Exception("Found symlink pointing outside of customer home directory: " . substr($original_target, strlen($fixed_homedir)));
|
throw new Exception("Found symlink pointing outside of customer home directory: " . substr($original_target, strlen($fixed_homedir)));
|
||||||
}
|
}
|
||||||
@@ -257,6 +263,41 @@ class FileDir
|
|||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read unconfigured-domain template from database if exists or fallback to default
|
||||||
|
*
|
||||||
|
* @param string $servername
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function getUnknownDomainTemplate(string $servername = "")
|
||||||
|
{
|
||||||
|
$result_stmt = Database::prepare("
|
||||||
|
SELECT * FROM `" . TABLE_PANEL_TEMPLATES . "` WHERE `templategroup` = 'files' AND `varname` = 'unconfigured_html'
|
||||||
|
");
|
||||||
|
Database::pexecute($result_stmt);
|
||||||
|
if (Database::num_rows() > 0) {
|
||||||
|
$template = $result_stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
$replace_arr = [
|
||||||
|
'SERVERNAME' => $servername,
|
||||||
|
];
|
||||||
|
$tpl_content = PhpHelper::replaceVariables($template['value'], $replace_arr);
|
||||||
|
$tpl_ext = $template['file_extension'];
|
||||||
|
} else {
|
||||||
|
$tpl_ext = 'html';
|
||||||
|
$unconfiguredPath = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/templates/misc/unconfigured/index.html');
|
||||||
|
if (file_exists($unconfiguredPath)) {
|
||||||
|
$tpl_content = file_get_contents($unconfiguredPath);
|
||||||
|
} else {
|
||||||
|
$tpl_content = lng('admin.templates.unconfigured_content_fallback');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$redirect_file = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/notice.' . $tpl_ext);
|
||||||
|
file_put_contents($redirect_file, $tpl_content);
|
||||||
|
return basename($redirect_file);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* store the default index-file in a given destination folder
|
* store the default index-file in a given destination folder
|
||||||
*
|
*
|
||||||
@@ -277,7 +318,7 @@ class FileDir
|
|||||||
{
|
{
|
||||||
if ($force || (int)Settings::Get('system.store_index_file_subs') == 1) {
|
if ($force || (int)Settings::Get('system.store_index_file_subs') == 1) {
|
||||||
$result_stmt = Database::prepare("
|
$result_stmt = Database::prepare("
|
||||||
SELECT `t`.`value`, `c`.`email` AS `customer_email`, `a`.`email` AS `admin_email`, `c`.`loginname` AS `customer_login`, `a`.`loginname` AS `admin_login`
|
SELECT `t`.`value`, `t`.`file_extension`, `c`.`email` AS `customer_email`, `a`.`email` AS `admin_email`, `c`.`loginname` AS `customer_login`, `a`.`loginname` AS `admin_login`
|
||||||
FROM `" . TABLE_PANEL_CUSTOMERS . "` AS `c` INNER JOIN `" . TABLE_PANEL_ADMINS . "` AS `a`
|
FROM `" . TABLE_PANEL_CUSTOMERS . "` AS `c` INNER JOIN `" . TABLE_PANEL_ADMINS . "` AS `a`
|
||||||
ON `c`.`adminid` = `a`.`adminid`
|
ON `c`.`adminid` = `a`.`adminid`
|
||||||
INNER JOIN `" . TABLE_PANEL_TEMPLATES . "` AS `t`
|
INNER JOIN `" . TABLE_PANEL_TEMPLATES . "` AS `t`
|
||||||
@@ -300,7 +341,7 @@ class FileDir
|
|||||||
|
|
||||||
// replaceVariables
|
// replaceVariables
|
||||||
$htmlcontent = PhpHelper::replaceVariables($template['value'], $replace_arr);
|
$htmlcontent = PhpHelper::replaceVariables($template['value'], $replace_arr);
|
||||||
$indexhtmlpath = self::makeCorrectFile($destination . '/index.' . Settings::Get('system.index_file_extension'));
|
$indexhtmlpath = self::makeCorrectFile($destination . '/index.' . $template['file_extension']);
|
||||||
$index_html_handler = fopen($indexhtmlpath, 'w');
|
$index_html_handler = fopen($indexhtmlpath, 'w');
|
||||||
fwrite($index_html_handler, $htmlcontent);
|
fwrite($index_html_handler, $htmlcontent);
|
||||||
fclose($index_html_handler);
|
fclose($index_html_handler);
|
||||||
@@ -308,7 +349,7 @@ class FileDir
|
|||||||
$logger->logAction(
|
$logger->logAction(
|
||||||
FroxlorLogger::CRON_ACTION,
|
FroxlorLogger::CRON_ACTION,
|
||||||
LOG_NOTICE,
|
LOG_NOTICE,
|
||||||
'Creating \'index.' . Settings::Get('system.index_file_extension') . '\' for Customer \'' . $template['customer_login'] . '\' based on template in directory ' . escapeshellarg($indexhtmlpath)
|
'Creating \'index.' . $template['file_extension'] . '\' for Customer \'' . $template['customer_login'] . '\' based on template in directory ' . escapeshellarg($indexhtmlpath)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -31,14 +31,16 @@ final class Froxlor
|
|||||||
{
|
{
|
||||||
|
|
||||||
// Main version variable
|
// Main version variable
|
||||||
const VERSION = '2.1.0-beta1';
|
const VERSION = '2.1.7';
|
||||||
|
|
||||||
// Database version (YYYYMMDDC where C is a daily counter)
|
// Database version (YYYYMMDDC where C is a daily counter)
|
||||||
const DBVERSION = '202305240';
|
const DBVERSION = '202312120';
|
||||||
|
|
||||||
// Distribution branding-tag (used for Debian etc.)
|
// Distribution branding-tag (used for Debian etc.)
|
||||||
const BRANDING = '';
|
const BRANDING = '';
|
||||||
|
|
||||||
|
const DOCS_URL = 'https://docs.froxlor.org/v2.1/';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return path to where froxlor is installed, e.g.
|
* return path to where froxlor is installed, e.g.
|
||||||
* /var/www/froxlor/
|
* /var/www/froxlor/
|
||||||
|
|||||||
@@ -104,18 +104,16 @@ class FroxlorLogger
|
|||||||
self::$ml->pushHandler(new SyslogHandler('froxlor', LOG_USER, Logger::DEBUG));
|
self::$ml->pushHandler(new SyslogHandler('froxlor', LOG_USER, Logger::DEBUG));
|
||||||
break;
|
break;
|
||||||
case 'file':
|
case 'file':
|
||||||
|
$setings_logfile = Settings::Get('logger.logfile');
|
||||||
|
if (empty($setings_logfile)) {
|
||||||
|
Settings::Set('logger.logfile', 'froxlor.log');
|
||||||
|
}
|
||||||
$logger_logfile = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/logs/' . Settings::Get('logger.logfile'));
|
$logger_logfile = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/logs/' . Settings::Get('logger.logfile'));
|
||||||
// is_writable needs an existing file to check if it's actually writable
|
// is_writable needs an existing file to check if it's actually writable
|
||||||
@touch($logger_logfile);
|
if (!@touch($logger_logfile) || !is_writable($logger_logfile)) {
|
||||||
if (empty($logger_logfile) || !is_writable($logger_logfile)) {
|
|
||||||
Settings::Set('logger.logfile', 'froxlor.log');
|
|
||||||
$logger_logfile = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/logs/froxlor.log');
|
|
||||||
@touch($logger_logfile);
|
|
||||||
if (empty($logger_logfile) || !is_writable($logger_logfile)) {
|
|
||||||
// not writable in our own directory? Skip
|
// not writable in our own directory? Skip
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
self::$ml->pushHandler(new StreamHandler($logger_logfile, Logger::DEBUG));
|
self::$ml->pushHandler(new StreamHandler($logger_logfile, Logger::DEBUG));
|
||||||
break;
|
break;
|
||||||
case 'mysql':
|
case 'mysql':
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class IdnaWrapper
|
|||||||
*/
|
*/
|
||||||
public function encode(string $to_encode): string
|
public function encode(string $to_encode): string
|
||||||
{
|
{
|
||||||
$to_encode = $this->isUtf8($to_encode) ? $to_encode : utf8_encode($to_encode);
|
$to_encode = $this->isUtf8($to_encode) ? $to_encode : mb_convert_encoding($to_encode, 'UTF-8');
|
||||||
try {
|
try {
|
||||||
return $this->idna_converter->encode($to_encode);
|
return $this->idna_converter->encode($to_encode);
|
||||||
} catch (InvalidArgumentException $iae) {
|
} catch (InvalidArgumentException $iae) {
|
||||||
|
|||||||
@@ -68,6 +68,12 @@ class AutoUpdate
|
|||||||
$channel = '';
|
$channel = '';
|
||||||
if (Settings::Get('system.update_channel') == 'testing') {
|
if (Settings::Get('system.update_channel') == 'testing') {
|
||||||
$channel = '/testing';
|
$channel = '/testing';
|
||||||
|
} elseif (Settings::Get('system.update_channel') == 'nightly') {
|
||||||
|
if (empty(Froxlor::BRANDING) || substr(Froxlor::BRANDING, 0, 1) == '-') {
|
||||||
|
$channel = '/nightly.0000000';
|
||||||
|
} else {
|
||||||
|
$channel = '/' . substr(Froxlor::BRANDING, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$latestversion = HttpClient::urlGet(self::UPDATE_URI . Froxlor::VERSION . $channel, true, 3);
|
$latestversion = HttpClient::urlGet(self::UPDATE_URI . Froxlor::VERSION . $channel, true, 3);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
@@ -145,6 +151,8 @@ class AutoUpdate
|
|||||||
$zip->close();
|
$zip->close();
|
||||||
// success - remove unused archive
|
// success - remove unused archive
|
||||||
@unlink($localArchive);
|
@unlink($localArchive);
|
||||||
|
// reset cached version check
|
||||||
|
Settings::Set('system.updatecheck_data', '');
|
||||||
// wait a bit before we redirect to be sure
|
// wait a bit before we redirect to be sure
|
||||||
sleep(3);
|
sleep(3);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -26,13 +26,14 @@
|
|||||||
namespace Froxlor\Install;
|
namespace Froxlor\Install;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use PDO;
|
use Froxlor\Config\ConfigParser;
|
||||||
|
use Froxlor\Froxlor;
|
||||||
use Froxlor\Install\Install\Core;
|
use Froxlor\Install\Install\Core;
|
||||||
|
use Froxlor\System\IPTools;
|
||||||
use Froxlor\UI\Panel\UI;
|
use Froxlor\UI\Panel\UI;
|
||||||
use Froxlor\UI\Request;
|
use Froxlor\UI\Request;
|
||||||
use Froxlor\Config\ConfigParser;
|
|
||||||
use Froxlor\Validate\Validate;
|
use Froxlor\Validate\Validate;
|
||||||
use Froxlor\System\IPTools;
|
use PDO;
|
||||||
|
|
||||||
class Install
|
class Install
|
||||||
{
|
{
|
||||||
@@ -41,25 +42,27 @@ class Install
|
|||||||
public $maxSteps;
|
public $maxSteps;
|
||||||
public $phpVersion;
|
public $phpVersion;
|
||||||
public $formfield;
|
public $formfield;
|
||||||
public string $requiredVersion = '7.4.0';
|
|
||||||
public array $requiredExtensions = ['session', 'ctype', 'xml', 'filter', 'posix', 'mbstring', 'curl', 'gmp', 'json', 'gd'];
|
|
||||||
public array $suggestedExtensions = ['bcmath', 'zip', 'gnupg'];
|
|
||||||
public array $suggestions = [];
|
public array $suggestions = [];
|
||||||
public array $criticals = [];
|
public array $criticals = [];
|
||||||
public array $loadedExtensions;
|
public array $loadedExtensions;
|
||||||
public array $supportedOS = [];
|
public array $supportedOS = [];
|
||||||
public array $webserverBackend = [
|
public array $webserverBackend = [
|
||||||
'php-fpm' => 'PHP-FPM',
|
'php-fpm' => 'PHP-FPM',
|
||||||
'fcgid' => 'FCGID',
|
'fcgid' => 'FCGID (apache2 only)',
|
||||||
'mod_php' => 'mod_php (not recommended)',
|
'mod_php' => 'mod_php (not recommended)',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct(array $cliData = [])
|
public function __construct(array $cliData = [])
|
||||||
{
|
{
|
||||||
|
// set actual php version and extensions
|
||||||
|
$this->phpVersion = phpversion();
|
||||||
|
$this->loadedExtensions = get_loaded_extensions();
|
||||||
|
|
||||||
// get all supported OS
|
// get all supported OS
|
||||||
// show list of available distro's
|
// show list of available distro's
|
||||||
$distros = glob(dirname(__DIR__, 3) . '/lib/configfiles/*.xml');
|
$distros = glob(dirname(__DIR__, 3) . '/lib/configfiles/*.xml');
|
||||||
$distributions_select[''] = '-';
|
$distributions_select[''] = '-';
|
||||||
|
if (in_array('xml', $this->loadedExtensions)) {
|
||||||
// read in all the distros
|
// read in all the distros
|
||||||
foreach ($distros as $distribution) {
|
foreach ($distros as $distribution) {
|
||||||
// get configparser object
|
// get configparser object
|
||||||
@@ -69,6 +72,7 @@ class Install
|
|||||||
}
|
}
|
||||||
// sort by distribution name
|
// sort by distribution name
|
||||||
asort($this->supportedOS);
|
asort($this->supportedOS);
|
||||||
|
}
|
||||||
|
|
||||||
// guess distribution and webserver to preselect in formfield
|
// guess distribution and webserver to preselect in formfield
|
||||||
$webserverBackend = $this->webserverBackend;
|
$webserverBackend = $this->webserverBackend;
|
||||||
@@ -84,10 +88,6 @@ class Install
|
|||||||
$this->extendedView = $cliData['extended'] ?? Request::any('extended', 0);
|
$this->extendedView = $cliData['extended'] ?? Request::any('extended', 0);
|
||||||
$this->maxSteps = count($this->formfield['install']['sections']);
|
$this->maxSteps = count($this->formfield['install']['sections']);
|
||||||
|
|
||||||
// set actual php version and extensions
|
|
||||||
$this->phpVersion = phpversion();
|
|
||||||
$this->loadedExtensions = get_loaded_extensions();
|
|
||||||
|
|
||||||
if (empty($cliData)) {
|
if (empty($cliData)) {
|
||||||
// set global variables
|
// set global variables
|
||||||
UI::twig()->addGlobal('install_mode', true);
|
UI::twig()->addGlobal('install_mode', true);
|
||||||
@@ -99,7 +99,7 @@ class Install
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check for url manipulation or wrong step
|
// check for url manipulation or wrong step
|
||||||
if ((isset($_SESSION['installation']['stepCompleted']) && ($this->currentStep + 1) > ($_SESSION['installation']['stepCompleted'] ?? 0))
|
if ((isset($_SESSION['installation']['stepCompleted']) && $this->currentStep > $_SESSION['installation']['stepCompleted'])
|
||||||
|| (!isset($_SESSION['installation']['stepCompleted']) && $this->currentStep > 0)
|
|| (!isset($_SESSION['installation']['stepCompleted']) && $this->currentStep > 0)
|
||||||
) {
|
) {
|
||||||
$this->currentStep = isset($_SESSION['installation']['stepCompleted']) ? $_SESSION['installation']['stepCompleted'] + 1 : 1;
|
$this->currentStep = isset($_SESSION['installation']['stepCompleted']) ? $_SESSION['installation']['stepCompleted'] + 1 : 1;
|
||||||
@@ -136,6 +136,7 @@ class Install
|
|||||||
'section' => $this->formfield['install']['sections']['step' . $this->currentStep] ?? [],
|
'section' => $this->formfield['install']['sections']['step' . $this->currentStep] ?? [],
|
||||||
'error' => $error ?? null,
|
'error' => $error ?? null,
|
||||||
'extended' => $this->extendedView,
|
'extended' => $this->extendedView,
|
||||||
|
'csrf_token' => Froxlor::genSessionId(20),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// output view
|
// output view
|
||||||
@@ -151,16 +152,14 @@ class Install
|
|||||||
if ($this->currentStep <= $this->maxSteps) {
|
if ($this->currentStep <= $this->maxSteps) {
|
||||||
// Validate user data
|
// Validate user data
|
||||||
$validatedData = $this->validateRequest($formfield['sections']['step' . $this->currentStep]['fields']);
|
$validatedData = $this->validateRequest($formfield['sections']['step' . $this->currentStep]['fields']);
|
||||||
// Check database connection (
|
|
||||||
if ($this->currentStep == 1) {
|
if ($this->currentStep == 1) {
|
||||||
|
// Check database connection
|
||||||
$this->checkDatabase($validatedData);
|
$this->checkDatabase($validatedData);
|
||||||
}
|
} elseif ($this->currentStep == 2) {
|
||||||
// Check validity of admin user data
|
// Check validity of admin user data
|
||||||
elseif ($this->currentStep == 2) {
|
|
||||||
$this->checkAdminUser($validatedData);
|
$this->checkAdminUser($validatedData);
|
||||||
}
|
} elseif ($this->currentStep == 3) {
|
||||||
// Check validity of system data
|
// Check validity of system data
|
||||||
elseif ($this->currentStep == 3) {
|
|
||||||
$this->checkSystem($validatedData);
|
$this->checkSystem($validatedData);
|
||||||
}
|
}
|
||||||
$validatedData['stepCompleted'] = ($this->currentStep < $this->maxSteps) ? $this->currentStep : ($this->maxSteps - 1);
|
$validatedData['stepCompleted'] = ($this->currentStep < $this->maxSteps) ? $this->currentStep : ($this->maxSteps - 1);
|
||||||
@@ -223,7 +222,7 @@ class Install
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check for required extensions
|
// check for required extensions
|
||||||
foreach ($this->requiredExtensions as $requiredExtension) {
|
foreach (Requirements::REQUIRED_EXTENSIONS as $requiredExtension) {
|
||||||
if (in_array($requiredExtension, $this->loadedExtensions)) {
|
if (in_array($requiredExtension, $this->loadedExtensions)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -231,7 +230,7 @@ class Install
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check for suggested extensions
|
// check for suggested extensions
|
||||||
foreach ($this->suggestedExtensions as $suggestedExtension) {
|
foreach (Requirements::SUGGESTED_EXTENSIONS as $suggestedExtension) {
|
||||||
if (in_array($suggestedExtension, $this->loadedExtensions)) {
|
if (in_array($suggestedExtension, $this->loadedExtensions)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -250,11 +249,11 @@ class Install
|
|||||||
*/
|
*/
|
||||||
private function getInformationText(): string
|
private function getInformationText(): string
|
||||||
{
|
{
|
||||||
if (version_compare($this->requiredVersion, PHP_VERSION, "<")) {
|
if (version_compare(Requirements::REQUIRED_VERSION, PHP_VERSION, "<")) {
|
||||||
$text = lng('install.phpinfosuccess', [$this->phpVersion]);
|
$text = lng('install.phpinfosuccess', [$this->phpVersion]);
|
||||||
} else {
|
} else {
|
||||||
$text = lng('install.phpinfowarn', [$this->requiredVersion]);
|
$text = lng('install.phpinfowarn', [Requirements::REQUIRED_VERSION]);
|
||||||
$this->criticals[] = lng('install.phpinfoupdate', [$this->phpVersion, $this->requiredVersion]);
|
$this->criticals[] = lng('install.phpinfoupdate', [$this->phpVersion, Requirements::REQUIRED_VERSION]);
|
||||||
}
|
}
|
||||||
return $text;
|
return $text;
|
||||||
}
|
}
|
||||||
@@ -302,9 +301,9 @@ class Install
|
|||||||
throw new Exception(lng('install.errors.nov4andnov6ip'));
|
throw new Exception(lng('install.errors.nov4andnov6ip'));
|
||||||
} elseif (!empty($serveripv4) && (!Validate::validate_ip2($serveripv4, true, '', false, true) || IPTools::is_ipv6($serveripv4))) {
|
} elseif (!empty($serveripv4) && (!Validate::validate_ip2($serveripv4, true, '', false, true) || IPTools::is_ipv6($serveripv4))) {
|
||||||
throw new Exception(lng('error.invalidip', [$serveripv4]));
|
throw new Exception(lng('error.invalidip', [$serveripv4]));
|
||||||
} elseif (!empty($serveripv6) && (!Validate::validate_ip2($serveripv6, true, '', false, true) || IPTools::is_ipv6($serveripv6) == false)) {
|
} elseif (!empty($serveripv6) && (!Validate::validate_ip2($serveripv6, true, '', false, true) || !IPTools::is_ipv6($serveripv6))) {
|
||||||
throw new Exception(lng('error.invalidip', [$serveripv6]));
|
throw new Exception(lng('error.invalidip', [$serveripv6]));
|
||||||
} elseif (!Validate::validateDomain($servername) && !Validate::validateLocalHostname($servername)) {
|
} elseif (!Validate::validateDomain($servername)) {
|
||||||
throw new Exception(lng('install.errors.servernameneedstobevalid'));
|
throw new Exception(lng('install.errors.servernameneedstobevalid'));
|
||||||
} elseif (posix_getpwnam($httpuser) === false) {
|
} elseif (posix_getpwnam($httpuser) === false) {
|
||||||
throw new Exception(lng('install.errors.websrvuserdoesnotexist'));
|
throw new Exception(lng('install.errors.websrvuserdoesnotexist'));
|
||||||
@@ -323,6 +322,8 @@ class Install
|
|||||||
$email = $validatedData['admin_email'] ?? '';
|
$email = $validatedData['admin_email'] ?? '';
|
||||||
$password = $validatedData['admin_pass'] ?? '';
|
$password = $validatedData['admin_pass'] ?? '';
|
||||||
$password_confirm = $validatedData['admin_pass_confirm'] ?? '';
|
$password_confirm = $validatedData['admin_pass_confirm'] ?? '';
|
||||||
|
$useadminmailassender = $validatedData['use_admin_email_as_sender'] ?? '1';
|
||||||
|
$senderemail = $validatedData['sender_email'] ?? '';
|
||||||
|
|
||||||
if (!preg_match('/^[^\r\n\t\f\0]*$/D', $name)) {
|
if (!preg_match('/^[^\r\n\t\f\0]*$/D', $name)) {
|
||||||
throw new Exception(lng('error.stringformaterror', ['admin_name']));
|
throw new Exception(lng('error.stringformaterror', ['admin_name']));
|
||||||
@@ -330,6 +331,8 @@ class Install
|
|||||||
throw new Exception(lng('error.loginnameiswrong', [$loginname]));
|
throw new Exception(lng('error.loginnameiswrong', [$loginname]));
|
||||||
} elseif (empty(trim($email)) || !Validate::validateEmail($email)) {
|
} elseif (empty(trim($email)) || !Validate::validateEmail($email)) {
|
||||||
throw new Exception(lng('error.emailiswrong', [$email]));
|
throw new Exception(lng('error.emailiswrong', [$email]));
|
||||||
|
} elseif ((int)$useadminmailassender == 0 && !empty(trim($senderemail)) && !Validate::validateEmail($senderemail)) {
|
||||||
|
throw new Exception(lng('error.emailiswrong', [$senderemail]));
|
||||||
} elseif (empty($password) || $password != $password_confirm) {
|
} elseif (empty($password) || $password != $password_confirm) {
|
||||||
throw new Exception(lng('error.newpasswordconfirmerror'));
|
throw new Exception(lng('error.newpasswordconfirmerror'));
|
||||||
} elseif ($password == $loginname) {
|
} elseif ($password == $loginname) {
|
||||||
@@ -410,7 +413,7 @@ class Install
|
|||||||
} else {
|
} else {
|
||||||
$osrf = explode("\n", file_get_contents('/etc/os-release'));
|
$osrf = explode("\n", file_get_contents('/etc/os-release'));
|
||||||
foreach ($osrf as $line) {
|
foreach ($osrf as $line) {
|
||||||
$osrfline = explode("\n", $line);
|
$osrfline = explode("=", $line);
|
||||||
if ($osrfline[0] == 'VERSION_CODENAME') {
|
if ($osrfline[0] == 'VERSION_CODENAME') {
|
||||||
$os_dist['VERSION_CODENAME'] = $osrfline[1];
|
$os_dist['VERSION_CODENAME'] = $osrfline[1];
|
||||||
} else if ($osrfline[0] == 'ID') {
|
} else if ($osrfline[0] == 'ID') {
|
||||||
|
|||||||
@@ -301,8 +301,8 @@ class Core
|
|||||||
/* continue */
|
/* continue */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (version_compare($db_root->getAttribute(PDO::ATTR_SERVER_VERSION), '10.0.0', '>=')) {
|
if (version_compare($db_root->getAttribute(PDO::ATTR_SERVER_VERSION), '8.0.11', '>=')) {
|
||||||
// mariadb compatibility
|
// mariadb & mysql8
|
||||||
// create user
|
// create user
|
||||||
$stmt = $db_root->prepare("CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY :password");
|
$stmt = $db_root->prepare("CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY :password");
|
||||||
$stmt->execute([
|
$stmt->execute([
|
||||||
@@ -314,19 +314,6 @@ class Core
|
|||||||
"username" => $username,
|
"username" => $username,
|
||||||
"host" => $access_host
|
"host" => $access_host
|
||||||
]);
|
]);
|
||||||
} elseif (version_compare($db_root->getAttribute(PDO::ATTR_SERVER_VERSION), '8.0.11', '>=')) {
|
|
||||||
// mysql8 compatibility
|
|
||||||
// create user
|
|
||||||
$stmt = $db_root->prepare("CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED WITH mysql_native_password BY :password");
|
|
||||||
$stmt->execute([
|
|
||||||
"password" => $password
|
|
||||||
]);
|
|
||||||
// grant privileges
|
|
||||||
$stmt = $db_root->prepare("GRANT ALL ON `" . $database . "`.* TO :username@:host");
|
|
||||||
$stmt->execute([
|
|
||||||
"username" => $username,
|
|
||||||
"host" => $access_host
|
|
||||||
]);
|
|
||||||
} else {
|
} else {
|
||||||
// grant privileges
|
// grant privileges
|
||||||
$stmt = $db_root->prepare("GRANT ALL PRIVILEGES ON `" . $database . "`.* TO :username@:host IDENTIFIED BY :password");
|
$stmt = $db_root->prepare("GRANT ALL PRIVILEGES ON `" . $database . "`.* TO :username@:host IDENTIFIED BY :password");
|
||||||
@@ -378,7 +365,14 @@ class Core
|
|||||||
|
|
||||||
$mainip = !empty($this->validatedData['serveripv6']) ? $this->validatedData['serveripv6'] : $this->validatedData['serveripv4'];
|
$mainip = !empty($this->validatedData['serveripv6']) ? $this->validatedData['serveripv6'] : $this->validatedData['serveripv4'];
|
||||||
|
|
||||||
$this->updateSetting($upd_stmt, 'admin@' . $this->validatedData['servername'], 'panel', 'adminmail');
|
if ($this->validatedData['use_admin_email_as_sender'] == '1') {
|
||||||
|
$adminmail_value = $this->validatedData['admin_email'];
|
||||||
|
} elseif ($this->validatedData['use_admin_email_as_sender'] == '0' && !empty($this->validatedData['sender_email'])) {
|
||||||
|
$adminmail_value = $this->validatedData['sender_email'];
|
||||||
|
} else {
|
||||||
|
$adminmail_value = 'admin@' . $this->validatedData['servername'];
|
||||||
|
}
|
||||||
|
$this->updateSetting($upd_stmt, $adminmail_value, 'panel', 'adminmail');
|
||||||
$this->updateSetting($upd_stmt, $mainip, 'system', 'ipaddress');
|
$this->updateSetting($upd_stmt, $mainip, 'system', 'ipaddress');
|
||||||
if ($this->validatedData['use_ssl']) {
|
if ($this->validatedData['use_ssl']) {
|
||||||
$this->updateSetting($upd_stmt, 1, 'system', 'use_ssl');
|
$this->updateSetting($upd_stmt, 1, 'system', 'use_ssl');
|
||||||
@@ -576,7 +570,7 @@ class Core
|
|||||||
'password' => password_hash($this->validatedData['admin_pass'], PASSWORD_DEFAULT),
|
'password' => password_hash($this->validatedData['admin_pass'], PASSWORD_DEFAULT),
|
||||||
'adminname' => $this->validatedData['admin_name'],
|
'adminname' => $this->validatedData['admin_name'],
|
||||||
'email' => $this->validatedData['admin_email'],
|
'email' => $this->validatedData['admin_email'],
|
||||||
'deflang' => 'en' // TODO: set lanuage
|
'deflang' => 'en' // TODO: set language
|
||||||
];
|
];
|
||||||
$ins_stmt = $db_user->prepare("
|
$ins_stmt = $db_user->prepare("
|
||||||
INSERT INTO `" . TABLE_PANEL_ADMINS . "` SET
|
INSERT INTO `" . TABLE_PANEL_ADMINS . "` SET
|
||||||
|
|||||||
10
lib/Froxlor/Install/Requirements.php
Normal file
10
lib/Froxlor/Install/Requirements.php
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Froxlor\Install;
|
||||||
|
|
||||||
|
class Requirements
|
||||||
|
{
|
||||||
|
const REQUIRED_VERSION = '7.4.0';
|
||||||
|
const REQUIRED_EXTENSIONS = ['session', 'ctype', 'xml', 'filter', 'posix', 'mbstring', 'pdo_mysql', 'curl', 'gmp', 'json', 'gd'];
|
||||||
|
const SUGGESTED_EXTENSIONS = ['bcmath', 'zip', 'gnupg'];
|
||||||
|
}
|
||||||
@@ -220,8 +220,11 @@ class PhpHelper
|
|||||||
if (is_dir($data_dirname)) {
|
if (is_dir($data_dirname)) {
|
||||||
$data_dirhandle = opendir($data_dirname);
|
$data_dirhandle = opendir($data_dirname);
|
||||||
while (false !== ($data_filename = readdir($data_dirhandle))) {
|
while (false !== ($data_filename = readdir($data_dirhandle))) {
|
||||||
if ($data_filename != '.' && $data_filename != '..' && $data_filename != '' && substr($data_filename,
|
if ($data_filename != '.'
|
||||||
-4) == '.php') {
|
&& $data_filename != '..'
|
||||||
|
&& $data_filename != ''
|
||||||
|
&& substr($data_filename, -4) == '.php'
|
||||||
|
) {
|
||||||
$data_files[] = $data_dirname . $data_filename;
|
$data_files[] = $data_dirname . $data_filename;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -458,6 +461,11 @@ class PhpHelper
|
|||||||
'directory_password',
|
'directory_password',
|
||||||
'ftp_password',
|
'ftp_password',
|
||||||
'mysql_password',
|
'mysql_password',
|
||||||
|
'mysql_root_pass',
|
||||||
|
'mysql_unprivileged_pass',
|
||||||
|
'admin_pass',
|
||||||
|
'admin_pass_confirm',
|
||||||
|
'panel_password_special_char',
|
||||||
];
|
];
|
||||||
if (!empty($global)) {
|
if (!empty($global)) {
|
||||||
$tmp = $global;
|
$tmp = $global;
|
||||||
@@ -557,4 +565,17 @@ class PhpHelper
|
|||||||
}
|
}
|
||||||
return $tab . $str;
|
return $tab . $str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function array_merge_recursive_distinct(array &$array1, array &$array2)
|
||||||
|
{
|
||||||
|
$merged = $array1;
|
||||||
|
foreach ($array2 as $key => &$value) {
|
||||||
|
if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
|
||||||
|
$merged[$key] = self::array_merge_recursive_distinct($merged[$key], $value);
|
||||||
|
} else {
|
||||||
|
$merged[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $merged;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ class SImExporter
|
|||||||
public static function export()
|
public static function export()
|
||||||
{
|
{
|
||||||
$settings_definitions = [];
|
$settings_definitions = [];
|
||||||
foreach (PhpHelper::loadConfigArrayDir('./actions/admin/settings/')['groups'] as $group) {
|
foreach (PhpHelper::loadConfigArrayDir(Froxlor::getInstallDir() . '/actions/admin/settings/')['groups'] as $group) {
|
||||||
foreach ($group['fields'] as $field) {
|
foreach ($group['fields'] as $field) {
|
||||||
$settings_definitions[$field['settinggroup']][$field['varname']] = $field;
|
$settings_definitions[$field['settinggroup']][$field['varname']] = $field;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,6 +102,14 @@ class Traffic
|
|||||||
$years_avail = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC);
|
$years_avail = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sort users by total traffic
|
||||||
|
uasort($users, function ($user_a, $user_b) {
|
||||||
|
if ($user_a['total'] == $user_b['total']) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ($user_a['total'] < $user_b['total']) ? 1 : -1;
|
||||||
|
});
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'metrics' => $metrics,
|
'metrics' => $metrics,
|
||||||
'users' => $users,
|
'users' => $users,
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
namespace Froxlor\UI\Callbacks;
|
namespace Froxlor\UI\Callbacks;
|
||||||
|
|
||||||
|
use Froxlor\CurrentUser;
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
use Froxlor\Domain\Domain as DDomain;
|
use Froxlor\Domain\Domain as DDomain;
|
||||||
use Froxlor\FileDir;
|
use Froxlor\FileDir;
|
||||||
@@ -33,6 +34,11 @@ use Froxlor\UI\Panel\UI;
|
|||||||
|
|
||||||
class Domain
|
class Domain
|
||||||
{
|
{
|
||||||
|
public static function domainLink(array $attributes)
|
||||||
|
{
|
||||||
|
return '<a href="https://' . $attributes['data'] . '" target="_blank">' . $attributes['data'] . '</a>';
|
||||||
|
}
|
||||||
|
|
||||||
public static function domainWithCustomerLink(array $attributes)
|
public static function domainWithCustomerLink(array $attributes)
|
||||||
{
|
{
|
||||||
$linker = UI::getLinker();
|
$linker = UI::getLinker();
|
||||||
@@ -76,7 +82,7 @@ class Domain
|
|||||||
return lng('domains.aliasdomain') . ' ' . $attributes['fields']['aliasdomain'];
|
return lng('domains.aliasdomain') . ' ' . $attributes['fields']['aliasdomain'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function domainExternalLinkInfo(array $attributes)
|
public static function domainExternalLinkInfo(array $attributes): string
|
||||||
{
|
{
|
||||||
$result = '';
|
$result = '';
|
||||||
if ($attributes['fields']['parentdomainid'] != 0) {
|
if ($attributes['fields']['parentdomainid'] != 0) {
|
||||||
@@ -84,7 +90,11 @@ class Domain
|
|||||||
}
|
}
|
||||||
$result .= '<a href="http://' . $attributes['data'] . '" target="_blank">' . $attributes['data'] . '</a>';
|
$result .= '<a href="http://' . $attributes['data'] . '" target="_blank">' . $attributes['data'] . '</a>';
|
||||||
// check for statistics if parentdomainid==0 to show stats-link for customers
|
// check for statistics if parentdomainid==0 to show stats-link for customers
|
||||||
if ((int)UI::getCurrentUser()['adminsession'] == 0 && $attributes['fields']['parentdomainid'] == 0 && $attributes['fields']['deactivated'] == 0) {
|
if ((int)UI::getCurrentUser()['adminsession'] == 0
|
||||||
|
&& $attributes['fields']['parentdomainid'] == 0
|
||||||
|
&& $attributes['fields']['deactivated'] == 0
|
||||||
|
&& preg_match('/^https?:\/\/(.*)/i', $attributes['fields']['documentroot']) == false
|
||||||
|
) {
|
||||||
$statsapp = Settings::Get('system.traffictool');
|
$statsapp = Settings::Get('system.traffictool');
|
||||||
$result .= ' <a href="http://' . $attributes['data'] . '/' . $statsapp . '" rel="external" target="_blank" title="' . lng('domains.statstics') . '"><i class="fa-solid fa-chart-line text-secondary"></i></a>';
|
$result .= ' <a href="http://' . $attributes['data'] . '/' . $statsapp . '" rel="external" target="_blank" title="' . lng('domains.statstics') . '"><i class="fa-solid fa-chart-line text-secondary"></i></a>';
|
||||||
}
|
}
|
||||||
@@ -104,7 +114,7 @@ class Domain
|
|||||||
|
|
||||||
public static function canViewLogs(array $attributes): bool
|
public static function canViewLogs(array $attributes): bool
|
||||||
{
|
{
|
||||||
if ((int)$attributes['fields']['email_only'] == 0 && !$attributes['fields']['deactivated']) {
|
if ((!CurrentUser::isAdmin() || (CurrentUser::isAdmin() && (int)$attributes['fields']['email_only'] == 0)) && !$attributes['fields']['deactivated']) {
|
||||||
if ((int)UI::getCurrentUser()['adminsession'] == 0 && (bool)UI::getCurrentUser()['logviewenabled']) {
|
if ((int)UI::getCurrentUser()['adminsession'] == 0 && (bool)UI::getCurrentUser()['logviewenabled']) {
|
||||||
return true;
|
return true;
|
||||||
} elseif ((int)UI::getCurrentUser()['adminsession'] == 1) {
|
} elseif ((int)UI::getCurrentUser()['adminsession'] == 1) {
|
||||||
@@ -146,7 +156,7 @@ class Domain
|
|||||||
|
|
||||||
public static function hasLetsEncryptActivated(array $attributes): bool
|
public static function hasLetsEncryptActivated(array $attributes): bool
|
||||||
{
|
{
|
||||||
return ((bool)$attributes['fields']['letsencrypt'] && (int)$attributes['fields']['email_only'] == 0);
|
return ((bool)$attributes['fields']['letsencrypt'] && (!CurrentUser::isAdmin() || (CurrentUser::isAdmin() && (int)$attributes['fields']['email_only'] == 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function canEditSSL(array $attributes): bool
|
public static function canEditSSL(array $attributes): bool
|
||||||
@@ -156,7 +166,7 @@ class Domain
|
|||||||
&& DDomain::domainHasSslIpPort($attributes['fields']['id'])
|
&& DDomain::domainHasSslIpPort($attributes['fields']['id'])
|
||||||
&& (int)$attributes['fields']['caneditdomain'] == 1
|
&& (int)$attributes['fields']['caneditdomain'] == 1
|
||||||
&& (int)$attributes['fields']['letsencrypt'] == 0
|
&& (int)$attributes['fields']['letsencrypt'] == 0
|
||||||
&& (int)$attributes['fields']['email_only'] == 0
|
&& (!CurrentUser::isAdmin() || (CurrentUser::isAdmin() && (int)$attributes['fields']['email_only'] == 0))
|
||||||
&& !$attributes['fields']['deactivated']
|
&& !$attributes['fields']['deactivated']
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -25,23 +25,24 @@
|
|||||||
|
|
||||||
namespace Froxlor\UI\Callbacks;
|
namespace Froxlor\UI\Callbacks;
|
||||||
|
|
||||||
|
use Froxlor\CurrentUser;
|
||||||
use Froxlor\Settings;
|
use Froxlor\Settings;
|
||||||
|
|
||||||
class Style
|
class Style
|
||||||
{
|
{
|
||||||
public static function deactivated(array $attributes): string
|
public static function deactivated(array $attributes): string
|
||||||
{
|
{
|
||||||
return $attributes['fields']['deactivated'] ? 'bg-danger' : '';
|
return $attributes['fields']['deactivated'] ? 'table-danger' : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function loginDisabled(array $attributes): string
|
public static function loginDisabled(array $attributes): string
|
||||||
{
|
{
|
||||||
return $attributes['fields']['login_enabled'] == 'N' ? 'bg-danger' : '';
|
return $attributes['fields']['login_enabled'] == 'N' ? 'table-danger' : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function resultIntegrityBad(array $attributes): string
|
public static function resultIntegrityBad(array $attributes): string
|
||||||
{
|
{
|
||||||
return $attributes['fields']['result'] ? '' : 'bg-warning';
|
return $attributes['fields']['result'] ? '' : 'table-warning';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function invalidApiKey(array $attributes): string
|
public static function invalidApiKey(array $attributes): string
|
||||||
@@ -53,7 +54,7 @@ class Style
|
|||||||
$isValid = false;
|
$isValid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $isValid ? '' : 'bg-danger';
|
return $isValid ? '' : 'table-danger';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function resultDomainTerminatedOrDeactivated(array $attributes): string
|
public static function resultDomainTerminatedOrDeactivated(array $attributes): string
|
||||||
@@ -63,25 +64,24 @@ class Style
|
|||||||
if (!empty($termination_date)) {
|
if (!empty($termination_date)) {
|
||||||
$cdate = strtotime($termination_date . " 23:59:59");
|
$cdate = strtotime($termination_date . " 23:59:59");
|
||||||
$today = time();
|
$today = time();
|
||||||
$termination_css = 'bg-warning';
|
$termination_css = 'table-warning';
|
||||||
if ($cdate < $today) {
|
if ($cdate < $today) {
|
||||||
$termination_css = 'bg-danger text-light';
|
$termination_css = 'table-danger';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$deactivated = $attributes['fields']['deactivated'] || $attributes['fields']['customer_deactivated'];
|
$deactivated = $attributes['fields']['deactivated'] || (CurrentUser::isAdmin() && $attributes['fields']['customer_deactivated']);
|
||||||
return $deactivated ? 'bg-info text-light' : $termination_css;
|
return $deactivated ? 'table-info' : $termination_css;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function resultCustomerLockedOrDeactivated(array $attributes): string
|
public static function resultCustomerLockedOrDeactivated(array $attributes): string
|
||||||
{
|
{
|
||||||
$row_css = '';
|
$row_css = '';
|
||||||
if ((int)$attributes['fields']['deactivated'] == 1) {
|
if ((int)$attributes['fields']['deactivated'] == 1) {
|
||||||
$row_css = 'bg-info text-light';
|
$row_css = 'table-info';
|
||||||
} elseif (
|
} elseif ($attributes['fields']['loginfail_count'] >= Settings::Get('login.maxloginattempts')
|
||||||
$attributes['fields']['loginfail_count'] >= Settings::Get('login.maxloginattempts')
|
|
||||||
&& $attributes['fields']['lastlogin_fail'] > (time() - Settings::Get('login.deactivatetime'))
|
&& $attributes['fields']['lastlogin_fail'] > (time() - Settings::Get('login.deactivatetime'))
|
||||||
) {
|
) {
|
||||||
$row_css = 'bg-warning';
|
$row_css = 'table-warning';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $row_css;
|
return $row_css;
|
||||||
@@ -97,9 +97,9 @@ class Style
|
|||||||
$style = '';
|
$style = '';
|
||||||
if ((int)$attributes[$field] >= 0) {
|
if ((int)$attributes[$field] >= 0) {
|
||||||
if (($attributes[$field] / 100) * $report_max < $attributes[$field . '_used']) {
|
if (($attributes[$field] / 100) * $report_max < $attributes[$field . '_used']) {
|
||||||
$style = 'bg-danger';
|
$style = 'table-danger';
|
||||||
} elseif (($attributes[$field] / 100) * ($report_max - 15) < $attributes[$field . '_used']) {
|
} elseif (($attributes[$field] / 100) * ($report_max - 15) < $attributes[$field . '_used']) {
|
||||||
$style = 'bg-warning';
|
$style = 'table-warning';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $style;
|
return $style;
|
||||||
|
|||||||
@@ -90,9 +90,10 @@ class Text
|
|||||||
public static function customerNoteDetailModal(array $attributes): array
|
public static function customerNoteDetailModal(array $attributes): array
|
||||||
{
|
{
|
||||||
$note = $attributes['fields']['custom_notes'] ?? '';
|
$note = $attributes['fields']['custom_notes'] ?? '';
|
||||||
|
$key = $attributes['fields']['customerid'] ?? $attributes['fields']['adminid'];
|
||||||
return [
|
return [
|
||||||
'entry' => $attributes['fields']['id'],
|
'entry' => $key,
|
||||||
'id' => 'cnModal' . $attributes['fields']['id'],
|
'id' => 'cnModal' . $key,
|
||||||
'title' => lng('usersettings.custom_notes.title') . ': ' . ($attributes['fields']['loginname'] ?? $attributes['fields']['adminname']),
|
'title' => lng('usersettings.custom_notes.title') . ': ' . ($attributes['fields']['loginname'] ?? $attributes['fields']['adminname']),
|
||||||
'body' => nl2br(Markdown::cleanCustomNotes($note))
|
'body' => nl2br(Markdown::cleanCustomNotes($note))
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -193,10 +193,14 @@ class Form
|
|||||||
if (!$do_show) {
|
if (!$do_show) {
|
||||||
$fielddata['note'] = lng('serversettings.option_requires_otp');
|
$fielddata['note'] = lng('serversettings.option_requires_otp');
|
||||||
if (!$otp_enabled_system) {
|
if (!$otp_enabled_system) {
|
||||||
|
$fielddata['disabled'] = true;
|
||||||
$fielddata['note'] .= '<br>' . lng('2fa.2fa_not_activated');
|
$fielddata['note'] .= '<br>' . lng('2fa.2fa_not_activated');
|
||||||
} elseif (!$otp_enabled_user) {
|
} elseif (!$otp_enabled_user) {
|
||||||
|
$fielddata['disabled'] = true;
|
||||||
$fielddata['note'] .= '<br>' . lng('2fa.2fa_not_activated_for_user');
|
$fielddata['note'] .= '<br>' . lng('2fa.2fa_not_activated_for_user');
|
||||||
}
|
}
|
||||||
|
// show field in any case
|
||||||
|
$do_show = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +217,8 @@ class Form
|
|||||||
{
|
{
|
||||||
$returnvalue = [];
|
$returnvalue = [];
|
||||||
if (is_array($fielddata) && isset($fielddata['type']) && $fielddata['type'] == 'select') {
|
if (is_array($fielddata) && isset($fielddata['type']) && $fielddata['type'] == 'select') {
|
||||||
if ((!isset($fielddata['select_var']) || !is_array($fielddata['select_var']) || empty($fielddata['select_var'])) && (isset($fielddata['option_options_method']))) {
|
if ((empty($fielddata['select_var']) || !is_array($fielddata['select_var'])) && (isset($fielddata['option_options_method']))
|
||||||
|
) {
|
||||||
$returnvalue['select_var'] = call_user_func($fielddata['option_options_method']);
|
$returnvalue['select_var'] = call_user_func($fielddata['option_options_method']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -232,8 +237,8 @@ class Form
|
|||||||
if (\Froxlor\Validate\Form::validateFieldDefinition($groupdetails)) {
|
if (\Froxlor\Validate\Form::validateFieldDefinition($groupdetails)) {
|
||||||
// Prefetch form fields
|
// Prefetch form fields
|
||||||
foreach ($groupdetails['fields'] as $fieldname => $fielddetails) {
|
foreach ($groupdetails['fields'] as $fieldname => $fielddetails) {
|
||||||
if (!$only_enabledisable || ($only_enabledisable && isset($fielddetails['overview_option']))) {
|
if (!$only_enabledisable || isset($fielddetails['overview_option'])) {
|
||||||
$groupdetails['fields'][$fieldname] = self::arrayMergePrefix($fielddetails, $fielddetails['type'], self::prefetchFormFieldData($fieldname, $fielddetails));
|
$groupdetails['fields'][$fieldname] = array_merge($fielddetails, self::prefetchFormFieldData($fieldname, $fielddetails));
|
||||||
$form['groups'][$groupname]['fields'][$fieldname] = $groupdetails['fields'][$fieldname];
|
$form['groups'][$groupname]['fields'][$fieldname] = $groupdetails['fields'][$fieldname];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -343,7 +348,7 @@ class Form
|
|||||||
if (\Froxlor\Validate\Form::validateFieldDefinition($groupdetails)) {
|
if (\Froxlor\Validate\Form::validateFieldDefinition($groupdetails)) {
|
||||||
// Save fields
|
// Save fields
|
||||||
foreach ($groupdetails['fields'] as $fieldname => $fielddetails) {
|
foreach ($groupdetails['fields'] as $fieldname => $fielddetails) {
|
||||||
if (!$only_enabledisable || ($only_enabledisable && isset($fielddetails['overview_option']))) {
|
if (!$only_enabledisable || (isset($fielddetails['overview_option']))) {
|
||||||
if (isset($changed_fields[$fieldname])) {
|
if (isset($changed_fields[$fieldname])) {
|
||||||
if (($saved_field = self::saveFormField($fieldname, $fielddetails, self::manipulateFormFieldData($fieldname, $fielddetails, $changed_fields[$fieldname]))) !== false) {
|
if (($saved_field = self::saveFormField($fieldname, $fielddetails, self::manipulateFormFieldData($fieldname, $fielddetails, $changed_fields[$fieldname]))) !== false) {
|
||||||
$saved_fields = array_merge($saved_fields, $saved_field);
|
$saved_fields = array_merge($saved_fields, $saved_field);
|
||||||
@@ -360,24 +365,7 @@ class Form
|
|||||||
// Save form
|
// Save form
|
||||||
return self::saveForm($form, $saved_fields);
|
return self::saveForm($form, $saved_fields);
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
|
|
||||||
private static function arrayMergePrefix($array1, $key_prefix, $array2)
|
|
||||||
{
|
|
||||||
if (is_array($array1) && is_array($array2)) {
|
|
||||||
if ($key_prefix != '') {
|
|
||||||
foreach ($array2 as $key => $value) {
|
|
||||||
$array1[$key_prefix . '_' . $key] = $value;
|
|
||||||
unset($array2[$key]);
|
|
||||||
}
|
|
||||||
unset($array2);
|
|
||||||
return $array1;
|
|
||||||
} else {
|
|
||||||
return array_merge($array1, $array2);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return $array1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getFormFieldData($fieldname, $fielddata, &$input)
|
public static function getFormFieldData($fieldname, $fielddata, &$input)
|
||||||
|
|||||||
@@ -92,6 +92,10 @@ class FroxlorTwig extends AbstractExtension
|
|||||||
new TwigFunction('mix', [
|
new TwigFunction('mix', [
|
||||||
$this,
|
$this,
|
||||||
'getMix'
|
'getMix'
|
||||||
|
]),
|
||||||
|
new TwigFunction('vite', [
|
||||||
|
$this,
|
||||||
|
'getVite'
|
||||||
])
|
])
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -167,4 +171,9 @@ class FroxlorTwig extends AbstractExtension
|
|||||||
{
|
{
|
||||||
return mix($mix);
|
return mix($mix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getVite($basehref = '', $vite = [], $defaults = [])
|
||||||
|
{
|
||||||
|
return vite($basehref, $vite ?? $defaults);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,8 +142,6 @@ class UI
|
|||||||
header("X-Content-Security-Policy: " . $csp_content);
|
header("X-Content-Security-Policy: " . $csp_content);
|
||||||
header("X-WebKit-CSP: " . $csp_content);
|
header("X-WebKit-CSP: " . $csp_content);
|
||||||
|
|
||||||
header("X-XSS-Protection: 1; mode=block");
|
|
||||||
|
|
||||||
// Don't allow to load Froxlor in an iframe to prevent i.e. clickjacking
|
// Don't allow to load Froxlor in an iframe to prevent i.e. clickjacking
|
||||||
header("X-Frame-Options: DENY");
|
header("X-Frame-Options: DENY");
|
||||||
|
|
||||||
@@ -323,6 +321,10 @@ class UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// check for template-variant
|
||||||
|
if (preg_match("/([a-z0-9.\-]+)_([a-z0-9.\-]+)/i", $theme, $matches)) {
|
||||||
|
$theme = $matches[1];
|
||||||
|
}
|
||||||
if (!file_exists(Froxlor::getInstallDir() . '/templates/' . $theme)) {
|
if (!file_exists(Froxlor::getInstallDir() . '/templates/' . $theme)) {
|
||||||
PhpHelper::phpErrHandler(E_USER_WARNING, "Theme '" . $theme . "' could not be found.", __FILE__, __LINE__);
|
PhpHelper::phpErrHandler(E_USER_WARNING, "Theme '" . $theme . "' could not be found.", __FILE__, __LINE__);
|
||||||
$theme = self::$default_theme;
|
$theme = self::$default_theme;
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ class Data
|
|||||||
return self::validateFormFieldString($fieldname, $fielddata, $newfieldvalue);
|
return self::validateFormFieldString($fieldname, $fielddata, $newfieldvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function validateFormFieldPassword($fieldname, $fielddata, $newfieldvalue)
|
||||||
|
{
|
||||||
|
return self::validateFormFieldString($fieldname, $fielddata, $newfieldvalue);
|
||||||
|
}
|
||||||
|
|
||||||
public static function validateFormFieldString($fieldname, $fielddata, $newfieldvalue)
|
public static function validateFormFieldString($fieldname, $fielddata, $newfieldvalue)
|
||||||
{
|
{
|
||||||
if (isset($fielddata['string_delimiter']) && $fielddata['string_delimiter'] != '') {
|
if (isset($fielddata['string_delimiter']) && $fielddata['string_delimiter'] != '') {
|
||||||
@@ -210,75 +215,6 @@ class Data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function validateFormFieldHiddenString($fieldname, $fielddata, $newfieldvalue)
|
|
||||||
{
|
|
||||||
if (isset($fielddata['string_delimiter']) && $fielddata['string_delimiter'] != '') {
|
|
||||||
$newfieldvalues = explode($fielddata['string_delimiter'], $newfieldvalue);
|
|
||||||
unset($fielddata['string_delimiter']);
|
|
||||||
|
|
||||||
$returnvalue = true;
|
|
||||||
foreach ($newfieldvalues as $single_newfieldvalue) {
|
|
||||||
/**
|
|
||||||
* don't use tabs in value-fields, #81
|
|
||||||
*/
|
|
||||||
$single_newfieldvalue = str_replace("\t", " ", $single_newfieldvalue);
|
|
||||||
$single_returnvalue = Data::validateFormFieldString($fieldname, $fielddata, $single_newfieldvalue);
|
|
||||||
if ($single_returnvalue !== true) {
|
|
||||||
$returnvalue = $single_returnvalue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$returnvalue = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* don't use tabs in value-fields, #81
|
|
||||||
*/
|
|
||||||
$newfieldvalue = str_replace("\t", " ", $newfieldvalue);
|
|
||||||
|
|
||||||
if (isset($fielddata['string_type']) && $fielddata['string_type'] == 'mail') {
|
|
||||||
$returnvalue = Validate::validateEmail($newfieldvalue);
|
|
||||||
} elseif (isset($fielddata['string_type']) && $fielddata['string_type'] == 'url') {
|
|
||||||
$returnvalue = Validate::validateUrl($newfieldvalue);
|
|
||||||
} elseif (isset($fielddata['string_type']) && $fielddata['string_type'] == 'dir') {
|
|
||||||
// add trailing slash to validate path if needed
|
|
||||||
// refs #331
|
|
||||||
if (substr($newfieldvalue, -1) != '/') {
|
|
||||||
$newfieldvalue .= '/';
|
|
||||||
}
|
|
||||||
$returnvalue = ($newfieldvalue == FileDir::makeCorrectDir($newfieldvalue));
|
|
||||||
} elseif (isset($fielddata['string_type']) && $fielddata['string_type'] == 'file') {
|
|
||||||
$returnvalue = ($newfieldvalue == FileDir::makeCorrectFile($newfieldvalue));
|
|
||||||
} elseif (isset($fielddata['string_type']) && $fielddata['string_type'] == 'filedir') {
|
|
||||||
$returnvalue = (($newfieldvalue == FileDir::makeCorrectDir($newfieldvalue)) || ($newfieldvalue == FileDir::makeCorrectFile($newfieldvalue)));
|
|
||||||
} elseif (preg_match('/^[^\r\n\t\f\0]*$/D', $newfieldvalue)) {
|
|
||||||
$returnvalue = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($fielddata['string_regexp']) && $fielddata['string_regexp'] != '') {
|
|
||||||
if (preg_match($fielddata['string_regexp'], $newfieldvalue)) {
|
|
||||||
$returnvalue = true;
|
|
||||||
} else {
|
|
||||||
$returnvalue = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($fielddata['string_emptyallowed']) && $fielddata['string_emptyallowed'] === true && $newfieldvalue === '') {
|
|
||||||
$returnvalue = true;
|
|
||||||
} elseif (isset($fielddata['string_emptyallowed']) && $fielddata['string_emptyallowed'] === false && $newfieldvalue === '') {
|
|
||||||
$returnvalue = 'stringmustntbeempty';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($returnvalue === true) {
|
|
||||||
return true;
|
|
||||||
} elseif ($returnvalue === false) {
|
|
||||||
return 'stringformaterror';
|
|
||||||
} else {
|
|
||||||
return $returnvalue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function validateFormFieldNumber($fieldname, $fielddata, $newfieldvalue)
|
public static function validateFormFieldNumber($fieldname, $fielddata, $newfieldvalue)
|
||||||
{
|
{
|
||||||
if (isset($fielddata['min']) && (int)$newfieldvalue < (int)$fielddata['min']) {
|
if (isset($fielddata['min']) && (int)$newfieldvalue < (int)$fielddata['min']) {
|
||||||
@@ -329,4 +265,10 @@ class Data
|
|||||||
|
|
||||||
return $returnvalue;
|
return $returnvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function validateFormFieldImage($fieldname, $fielddata, $newfieldvalue)
|
||||||
|
{
|
||||||
|
// validation is handled in \Froxlor\Settings\Store::storeSettingImage()
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ class Validate
|
|||||||
}
|
}
|
||||||
|
|
||||||
// special case where localhost ip is allowed (mysql-access-hosts for example)
|
// special case where localhost ip is allowed (mysql-access-hosts for example)
|
||||||
if ($allow_localhost && $ip == '127.0.0.1') {
|
if ($allow_localhost && ($ip == '127.0.0.1' || $ip == '::1')) {
|
||||||
return $ip . $cidr;
|
return $ip . $cidr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +224,7 @@ class Validate
|
|||||||
* Check if the submitted string is a valid domainname
|
* Check if the submitted string is a valid domainname
|
||||||
*
|
*
|
||||||
* @param string $domainname The domainname which should be checked.
|
* @param string $domainname The domainname which should be checked.
|
||||||
* @param bool $allow_underscore optional if true, allowes the underscore character in a domain label (DKIM etc.)
|
* @param bool $allow_underscore optional if true, allows the underscore character in a domain label (DKIM etc.)
|
||||||
*
|
*
|
||||||
* @return string|boolean the domain-name if the domain is valid, false otherwise
|
* @return string|boolean the domain-name if the domain is valid, false otherwise
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -9,11 +9,18 @@ return [
|
|||||||
* recommended value for debian/ubuntu package users is false to rely on apt and not have version mixup.
|
* recommended value for debian/ubuntu package users is false to rely on apt and not have version mixup.
|
||||||
* This is also useful for providers that manage the servers but give admin access to froxlor to handle
|
* This is also useful for providers that manage the servers but give admin access to froxlor to handle
|
||||||
* updates the way the providers does it (e.g. automation, etc.)
|
* updates the way the providers does it (e.g. automation, etc.)
|
||||||
|
*
|
||||||
|
* Default: false
|
||||||
*/
|
*/
|
||||||
'enable_webupdate' => false,
|
'enable_webupdate' => false,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @todo description
|
* settings that have a major impact on the system or which values are used to be executed with high
|
||||||
|
* privileges on the system require the admin-user to have set up and enabled OTP for the corresponding
|
||||||
|
* account to change these values.
|
||||||
|
* To disable this extra security validation, set the value of this to true
|
||||||
|
*
|
||||||
|
* Default: false
|
||||||
*/
|
*/
|
||||||
'disable_otp_security_check' => false,
|
'disable_otp_security_check' => false,
|
||||||
];
|
];
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -92,7 +92,7 @@ Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}
|
|||||||
<command><![CDATA[{{settings.system.apachereload_command}}]]></command>
|
<command><![CDATA[{{settings.system.apachereload_command}}]]></command>
|
||||||
</daemon>
|
</daemon>
|
||||||
<!-- HTTP Lighttpd -->
|
<!-- HTTP Lighttpd -->
|
||||||
<daemon name="lighttpd" title="LigHTTPd">
|
<daemon name="lighttpd" title="LigHTTPd (deprecated)">
|
||||||
<install><![CDATA[apt-get install lighttpd]]></install>
|
<install><![CDATA[apt-get install lighttpd]]></install>
|
||||||
<file name="/etc/lighttpd/lighttpd.conf">
|
<file name="/etc/lighttpd/lighttpd.conf">
|
||||||
<content><![CDATA[
|
<content><![CDATA[
|
||||||
@@ -1556,7 +1556,7 @@ noc: root
|
|||||||
security: root
|
security: root
|
||||||
|
|
||||||
# change this to a valid e-mail address you can access
|
# change this to a valid e-mail address you can access
|
||||||
root: root@<SERVERNAME>
|
root: <ADMIN_MAIL>
|
||||||
]]>
|
]]>
|
||||||
</content>
|
</content>
|
||||||
</file>
|
</file>
|
||||||
@@ -2547,6 +2547,7 @@ plugin {
|
|||||||
</file>
|
</file>
|
||||||
</files>
|
</files>
|
||||||
<commands index="1">
|
<commands index="1">
|
||||||
|
<command><![CDATA[sed -i.bak 's/^!include auth-system.conf.ext/#!include auth-system.conf.ext/' /etc/dovecot/conf.d/10-auth.conf]]></command>
|
||||||
<command><![CDATA[service dovecot restart]]></command>
|
<command><![CDATA[service dovecot restart]]></command>
|
||||||
</commands>
|
</commands>
|
||||||
</general>
|
</general>
|
||||||
@@ -3383,6 +3384,11 @@ aliases: files
|
|||||||
</visibility>
|
</visibility>
|
||||||
<command><![CDATA[a2dismod php8.2]]></command>
|
<command><![CDATA[a2dismod php8.2]]></command>
|
||||||
</commands>
|
</commands>
|
||||||
|
<commands index="5">
|
||||||
|
<visibility mode="equals" value="apache2">{{settings.system.webserver}}
|
||||||
|
</visibility>
|
||||||
|
<command><![CDATA[a2disconf php8.2-fpm]]></command>
|
||||||
|
</commands>
|
||||||
<!-- instead of just restarting apache, we let the cronjob do all the
|
<!-- instead of just restarting apache, we let the cronjob do all the
|
||||||
dirty work -->
|
dirty work -->
|
||||||
<command><![CDATA[php {{const.install_dir}}bin/froxlor-cli froxlor:cron --force]]></command>
|
<command><![CDATA[php {{const.install_dir}}bin/froxlor-cli froxlor:cron --force]]></command>
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}
|
|||||||
<command><![CDATA[{{settings.system.apachereload_command}}]]></command>
|
<command><![CDATA[{{settings.system.apachereload_command}}]]></command>
|
||||||
</daemon>
|
</daemon>
|
||||||
<!-- HTTP Lighttpd -->
|
<!-- HTTP Lighttpd -->
|
||||||
<daemon name="lighttpd" title="LigHTTPd">
|
<daemon name="lighttpd" title="LigHTTPd (deprecated)">
|
||||||
<install><![CDATA[apt-get install lighttpd]]></install>
|
<install><![CDATA[apt-get install lighttpd]]></install>
|
||||||
<file name="/etc/lighttpd/lighttpd.conf">
|
<file name="/etc/lighttpd/lighttpd.conf">
|
||||||
<content><![CDATA[
|
<content><![CDATA[
|
||||||
@@ -1556,7 +1556,7 @@ noc: root
|
|||||||
security: root
|
security: root
|
||||||
|
|
||||||
# change this to a valid e-mail address you can access
|
# change this to a valid e-mail address you can access
|
||||||
root: root@<SERVERNAME>
|
root: <ADMIN_MAIL>
|
||||||
]]>
|
]]>
|
||||||
</content>
|
</content>
|
||||||
</file>
|
</file>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -91,7 +91,7 @@ Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}
|
|||||||
<command><![CDATA[{{settings.system.apachereload_command}}]]></command>
|
<command><![CDATA[{{settings.system.apachereload_command}}]]></command>
|
||||||
</daemon>
|
</daemon>
|
||||||
<!-- HTTP Lighttpd -->
|
<!-- HTTP Lighttpd -->
|
||||||
<daemon name="lighttpd" title="LigHTTPd">
|
<daemon name="lighttpd" title="LigHTTPd (deprecated)">
|
||||||
<install><![CDATA[apt-get install lighttpd]]></install>
|
<install><![CDATA[apt-get install lighttpd]]></install>
|
||||||
<file name="/etc/lighttpd/lighttpd.conf">
|
<file name="/etc/lighttpd/lighttpd.conf">
|
||||||
<content><![CDATA[
|
<content><![CDATA[
|
||||||
@@ -1585,7 +1585,7 @@ noc: root
|
|||||||
security: root
|
security: root
|
||||||
|
|
||||||
# change this to a valid e-mail address you can access
|
# change this to a valid e-mail address you can access
|
||||||
root: root@<SERVERNAME>
|
root: <ADMIN_MAIL>
|
||||||
]]>
|
]]>
|
||||||
</content>
|
</content>
|
||||||
</file>
|
</file>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<froxlor>
|
<froxlor>
|
||||||
<distribution name="Gentoo" version="3.0"
|
<distribution name="Gentoo" version="3.0"
|
||||||
defaulteditor="/usr/bin/nano">
|
defaulteditor="/usr/bin/nano" deprecated="true">
|
||||||
<!-- OS defaults to be loaded on installation -->
|
<!-- OS defaults to be loaded on installation -->
|
||||||
<defaults>
|
<defaults>
|
||||||
<default settinggroup="system" varname="nssextrausers" value="1"></default>
|
<default settinggroup="system" varname="nssextrausers" value="1"></default>
|
||||||
@@ -100,7 +100,7 @@ Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}
|
|||||||
<command><![CDATA[{{settings.system.apachereload_command}}]]></command>
|
<command><![CDATA[{{settings.system.apachereload_command}}]]></command>
|
||||||
</daemon>
|
</daemon>
|
||||||
<!-- HTTP Lighttpd -->
|
<!-- HTTP Lighttpd -->
|
||||||
<daemon name="lighttpd" title="LigHTTPd">
|
<daemon name="lighttpd" title="LigHTTPd (deprecated)">
|
||||||
<install><![CDATA[emerge www-servers/lighttpd]]></install>
|
<install><![CDATA[emerge www-servers/lighttpd]]></install>
|
||||||
<file name="/etc/lighttpd/lighttpd.conf">
|
<file name="/etc/lighttpd/lighttpd.conf">
|
||||||
<content><![CDATA[
|
<content><![CDATA[
|
||||||
@@ -1541,7 +1541,7 @@ noc: root
|
|||||||
security: root
|
security: root
|
||||||
|
|
||||||
# change this to a valid e-mail address you can access
|
# change this to a valid e-mail address you can access
|
||||||
root: root@<SERVERNAME>
|
root: <ADMIN_MAIL>
|
||||||
]]>
|
]]>
|
||||||
</content>
|
</content>
|
||||||
</file>
|
</file>
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}
|
|||||||
<command><![CDATA[{{settings.system.apachereload_command}}]]></command>
|
<command><![CDATA[{{settings.system.apachereload_command}}]]></command>
|
||||||
</daemon>
|
</daemon>
|
||||||
<!-- HTTP Lighttpd -->
|
<!-- HTTP Lighttpd -->
|
||||||
<daemon name="lighttpd" title="LigHTTPd">
|
<daemon name="lighttpd" title="LigHTTPd (deprecated)">
|
||||||
<install><![CDATA[apt-get install lighttpd]]></install>
|
<install><![CDATA[apt-get install lighttpd]]></install>
|
||||||
<file name="/etc/lighttpd/lighttpd.conf">
|
<file name="/etc/lighttpd/lighttpd.conf">
|
||||||
<content><![CDATA[
|
<content><![CDATA[
|
||||||
@@ -1585,7 +1585,7 @@ noc: root
|
|||||||
security: root
|
security: root
|
||||||
|
|
||||||
# change this to a valid e-mail address you can access
|
# change this to a valid e-mail address you can access
|
||||||
root: root@<SERVERNAME>
|
root: <ADMIN_MAIL>
|
||||||
]]>
|
]]>
|
||||||
</content>
|
</content>
|
||||||
</file>
|
</file>
|
||||||
@@ -4172,6 +4172,11 @@ aliases: files
|
|||||||
</visibility>
|
</visibility>
|
||||||
<command><![CDATA[a2dismod php8.1]]></command>
|
<command><![CDATA[a2dismod php8.1]]></command>
|
||||||
</commands>
|
</commands>
|
||||||
|
<commands index="5">
|
||||||
|
<visibility mode="equals" value="apache2">{{settings.system.webserver}}
|
||||||
|
</visibility>
|
||||||
|
<command><![CDATA[a2disconf php8.1-fpm]]></command>
|
||||||
|
</commands>
|
||||||
<!-- instead of just restarting apache, we let the cronjob do all the
|
<!-- instead of just restarting apache, we let the cronjob do all the
|
||||||
dirty work -->
|
dirty work -->
|
||||||
<command><![CDATA[php {{const.install_dir}}bin/froxlor-cli froxlor:cron --force]]></command>
|
<command><![CDATA[php {{const.install_dir}}bin/froxlor-cli froxlor:cron --force]]></command>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ return [
|
|||||||
'label' => lng('login.password'),
|
'label' => lng('login.password'),
|
||||||
'type' => 'password',
|
'type' => 'password',
|
||||||
'autocomplete' => 'off',
|
'autocomplete' => 'off',
|
||||||
'placeholder' => lng('admin.username_default_msg'),
|
'placeholder' => lng('admin.password_default_msg'),
|
||||||
'next_to' => [
|
'next_to' => [
|
||||||
'new_customer_password_suggestion' => [
|
'new_customer_password_suggestion' => [
|
||||||
'next_to_prefix' => lng('customer.generated_pwd') . ':',
|
'next_to_prefix' => lng('customer.generated_pwd') . ':',
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ return [
|
|||||||
'maxlength' => 10,
|
'maxlength' => 10,
|
||||||
'value' => '5s'
|
'value' => '5s'
|
||||||
],
|
],
|
||||||
'phpfpm_pass_authorizationheader' => [
|
'pass_authorizationheader' => [
|
||||||
'visible' => Settings::Get('system.webserver') == "apache2",
|
'visible' => Settings::Get('system.webserver') == "apache2",
|
||||||
'label' => lng('admin.phpsettings.pass_authorizationheader'),
|
'label' => lng('admin.phpsettings.pass_authorizationheader'),
|
||||||
'type' => 'checkbox',
|
'type' => 'checkbox',
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ return [
|
|||||||
'maxlength' => 10,
|
'maxlength' => 10,
|
||||||
'value' => $result['fpm_reqslow']
|
'value' => $result['fpm_reqslow']
|
||||||
],
|
],
|
||||||
'phpfpm_pass_authorizationheader' => [
|
'pass_authorizationheader' => [
|
||||||
'visible' => Settings::Get('system.webserver') == "apache2",
|
'visible' => Settings::Get('system.webserver') == "apache2",
|
||||||
'label' => lng('admin.phpsettings.pass_authorizationheader'),
|
'label' => lng('admin.phpsettings.pass_authorizationheader'),
|
||||||
'type' => 'checkbox',
|
'type' => 'checkbox',
|
||||||
|
|||||||
@@ -38,11 +38,20 @@ return [
|
|||||||
'type' => 'select',
|
'type' => 'select',
|
||||||
'select_var' => $free_templates
|
'select_var' => $free_templates
|
||||||
],
|
],
|
||||||
|
'file_extension' => [
|
||||||
|
'label' => lng('admin.templates.file_extension'),
|
||||||
|
'type' => 'text',
|
||||||
|
'string_regexp' => '/^[a-zA-Z0-9]{1,6}$/',
|
||||||
|
'default' => 'html',
|
||||||
|
'value' => 'html',
|
||||||
|
'mandatory' => true
|
||||||
|
],
|
||||||
'filecontent' => [
|
'filecontent' => [
|
||||||
'label' => lng('admin.templates.filecontent'),
|
'label' => lng('admin.templates.filecontent'),
|
||||||
'type' => 'textarea',
|
'type' => 'textarea',
|
||||||
'cols' => 60,
|
'cols' => 60,
|
||||||
'rows' => 12
|
'rows' => 12,
|
||||||
|
'mandatory' => true
|
||||||
],
|
],
|
||||||
'filesend' => [
|
'filesend' => [
|
||||||
'type' => 'hidden',
|
'type' => 'hidden',
|
||||||
|
|||||||
@@ -39,12 +39,21 @@ return [
|
|||||||
'value' => lng('admin.templates.' . $row['varname']),
|
'value' => lng('admin.templates.' . $row['varname']),
|
||||||
'display' => lng('admin.templates.' . $row['varname'])
|
'display' => lng('admin.templates.' . $row['varname'])
|
||||||
],
|
],
|
||||||
|
'file_extension' => [
|
||||||
|
'label' => lng('admin.templates.file_extension'),
|
||||||
|
'type' => 'text',
|
||||||
|
'string_regexp' => '/^[a-zA-Z0-9]{1,6}$/',
|
||||||
|
'value' => $row['file_extension'],
|
||||||
|
'default' => 'html',
|
||||||
|
'mandatory' => true
|
||||||
|
],
|
||||||
'filecontent' => [
|
'filecontent' => [
|
||||||
'label' => lng('admin.templates.filecontent'),
|
'label' => lng('admin.templates.filecontent'),
|
||||||
'type' => 'textarea',
|
'type' => 'textarea',
|
||||||
'cols' => 60,
|
'cols' => 60,
|
||||||
'rows' => 12,
|
'rows' => 12,
|
||||||
'value' => $row['value']
|
'value' => $row['value'],
|
||||||
|
'mandatory' => true
|
||||||
],
|
],
|
||||||
'filesend' => [
|
'filesend' => [
|
||||||
'type' => 'hidden',
|
'type' => 'hidden',
|
||||||
|
|||||||
@@ -55,13 +55,16 @@ return [
|
|||||||
'label' => lng('login.password'),
|
'label' => lng('login.password'),
|
||||||
'type' => 'password',
|
'type' => 'password',
|
||||||
'autocomplete' => 'off',
|
'autocomplete' => 'off',
|
||||||
'mandatory' => true
|
'mandatory' => true,
|
||||||
],
|
'next_to' => [
|
||||||
'directory_password_suggestion' => [
|
'directory_password_suggestion' => [
|
||||||
'label' => lng('customer.generated_pwd'),
|
'next_to_prefix' => lng('customer.generated_pwd') . ':',
|
||||||
'type' => 'text',
|
'type' => 'text',
|
||||||
'visible' => (Settings::Get('panel.password_regex') == ''),
|
'visible' => (Settings::Get('panel.password_regex') == ''),
|
||||||
'value' => Crypt::generatePassword()
|
'value' => Crypt::generatePassword(),
|
||||||
|
'readonly' => true
|
||||||
|
]
|
||||||
|
]
|
||||||
],
|
],
|
||||||
'directory_authname' => [
|
'directory_authname' => [
|
||||||
'label' => lng('extras.htpasswdauthname'),
|
'label' => lng('extras.htpasswdauthname'),
|
||||||
|
|||||||
@@ -49,13 +49,16 @@ return [
|
|||||||
'directory_password' => [
|
'directory_password' => [
|
||||||
'label' => lng('login.password'),
|
'label' => lng('login.password'),
|
||||||
'type' => 'password',
|
'type' => 'password',
|
||||||
'autocomplete' => 'off'
|
'autocomplete' => 'off',
|
||||||
],
|
'next_to' => [
|
||||||
'directory_password_suggestion' => [
|
'directory_password_suggestion' => [
|
||||||
'label' => lng('customer.generated_pwd'),
|
'next_to_prefix' => lng('customer.generated_pwd') . ':',
|
||||||
'type' => 'text',
|
'type' => 'text',
|
||||||
'visible' => (Settings::Get('panel.password_regex') == ''),
|
'visible' => (Settings::Get('panel.password_regex') == ''),
|
||||||
'value' => Crypt::generatePassword()
|
'value' => Crypt::generatePassword(),
|
||||||
|
'readonly' => true
|
||||||
|
]
|
||||||
|
]
|
||||||
],
|
],
|
||||||
'directory_authname' => [
|
'directory_authname' => [
|
||||||
'label' => lng('extras.htpasswdauthname'),
|
'label' => lng('extras.htpasswdauthname'),
|
||||||
|
|||||||
@@ -46,14 +46,16 @@ return [
|
|||||||
'label' => lng('login.password'),
|
'label' => lng('login.password'),
|
||||||
'type' => 'password',
|
'type' => 'password',
|
||||||
'autocomplete' => 'off',
|
'autocomplete' => 'off',
|
||||||
'mandatory' => true
|
'mandatory' => true,
|
||||||
],
|
'next_to' => [
|
||||||
'mysql_password_suggestion' => [
|
'mysql_password_suggestion' => [
|
||||||
'label' => lng('customer.generated_pwd'),
|
'next_to_prefix' => lng('customer.generated_pwd') . ':',
|
||||||
'type' => 'text',
|
'type' => 'text',
|
||||||
'visible' => (Settings::Get('panel.password_regex') == ''),
|
'visible' => (Settings::Get('panel.password_regex') == ''),
|
||||||
'value' => Crypt::generatePassword(),
|
'value' => Crypt::generatePassword(),
|
||||||
'readonly' => true
|
'readonly' => true
|
||||||
|
]
|
||||||
|
]
|
||||||
],
|
],
|
||||||
'sendinfomail' => [
|
'sendinfomail' => [
|
||||||
'label' => lng('customer.sendinfomail'),
|
'label' => lng('customer.sendinfomail'),
|
||||||
|
|||||||
@@ -52,10 +52,10 @@ return [
|
|||||||
'mysql_password' => [
|
'mysql_password' => [
|
||||||
'label' => lng('changepassword.new_password_ifnotempty'),
|
'label' => lng('changepassword.new_password_ifnotempty'),
|
||||||
'type' => 'password',
|
'type' => 'password',
|
||||||
'autocomplete' => 'off'
|
'autocomplete' => 'off',
|
||||||
],
|
'next_to' => [
|
||||||
'mysql_password_suggestion' => [
|
'mysql_password_suggestion' => [
|
||||||
'label' => lng('customer.generated_pwd'),
|
'next_to_prefix' => lng('customer.generated_pwd') . ':',
|
||||||
'type' => 'text',
|
'type' => 'text',
|
||||||
'visible' => (Settings::Get('panel.password_regex') == ''),
|
'visible' => (Settings::Get('panel.password_regex') == ''),
|
||||||
'value' => Crypt::generatePassword(),
|
'value' => Crypt::generatePassword(),
|
||||||
@@ -65,4 +65,6 @@ return [
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ return [
|
|||||||
'cols' => 100,
|
'cols' => 100,
|
||||||
'rows' => 15,
|
'rows' => 15,
|
||||||
'value' => $result['ssl_cert_file'],
|
'value' => $result['ssl_cert_file'],
|
||||||
'placeholder' => lng('domain.ssl_certificate_placeholder')
|
'placeholder' => lng('domain.ssl_certificate_placeholder'),
|
||||||
|
'mandatory' => true
|
||||||
],
|
],
|
||||||
'ssl_key_file' => [
|
'ssl_key_file' => [
|
||||||
'label' => lng('admin.ipsandports.ssl_key_file_content'),
|
'label' => lng('admin.ipsandports.ssl_key_file_content'),
|
||||||
@@ -53,7 +54,8 @@ return [
|
|||||||
'cols' => 100,
|
'cols' => 100,
|
||||||
'rows' => 15,
|
'rows' => 15,
|
||||||
'value' => $result['ssl_key_file'],
|
'value' => $result['ssl_key_file'],
|
||||||
'placeholder' => lng('domain.ssl_key_placeholder')
|
'placeholder' => lng('domain.ssl_key_placeholder'),
|
||||||
|
'mandatory' => true
|
||||||
],
|
],
|
||||||
'ssl_cert_chainfile' => [
|
'ssl_cert_chainfile' => [
|
||||||
'label' => lng('admin.ipsandports.ssl_cert_chainfile_content'),
|
'label' => lng('admin.ipsandports.ssl_cert_chainfile_content'),
|
||||||
|
|||||||
@@ -143,6 +143,18 @@ return [
|
|||||||
'mandatory' => true,
|
'mandatory' => true,
|
||||||
'value' => old('admin_email', null, 'installation'),
|
'value' => old('admin_email', null, 'installation'),
|
||||||
],
|
],
|
||||||
|
'use_admin_email_as_sender' => [
|
||||||
|
'label' => lng('install.admin.use_admin_email_as_sender'),
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'value' => '1',
|
||||||
|
'checked' => old('use_admin_email_as_sender', '1', 'installation'),
|
||||||
|
],
|
||||||
|
'sender_email' => [
|
||||||
|
'label' => lng('serversettings.adminmail.title'),
|
||||||
|
'placeholder' => lng('install.admin.use_autogenerated_email_as_sender'),
|
||||||
|
'type' => 'email',
|
||||||
|
'value' => old('sender_email', null, 'installation'),
|
||||||
|
],
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'step3' => [
|
'step3' => [
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ function old(string $identifier, string $default = null, string $session = null)
|
|||||||
* This file contains the hashed filenames of the assets.
|
* This file contains the hashed filenames of the assets.
|
||||||
* It must be always placed in the theme assets folder.
|
* It must be always placed in the theme assets folder.
|
||||||
*
|
*
|
||||||
|
* @deprecated since 2.1.x no longer in use
|
||||||
* @param $filename
|
* @param $filename
|
||||||
* @return mixed|string
|
* @return mixed|string
|
||||||
*/
|
*/
|
||||||
@@ -91,3 +92,50 @@ function mix($filename)
|
|||||||
}
|
}
|
||||||
return $filename;
|
return $filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loading the vite manifest file from given theme.
|
||||||
|
* This file contains the hashed filenames of the assets.
|
||||||
|
* It must be always placed in the theme assets folder.
|
||||||
|
*
|
||||||
|
* @param string|null $basehref
|
||||||
|
* @param array $filenames
|
||||||
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
function vite($basehref, array $filenames): string
|
||||||
|
{
|
||||||
|
// Get the hashed filenames from the manifest file
|
||||||
|
$links = [];
|
||||||
|
foreach ($filenames as $filename) {
|
||||||
|
if (preg_match("/templates\/([^\/]+)(.*)/", $filename, $matches)) {
|
||||||
|
$assetDirectory = '/templates/' . $matches[1] . '/build/';
|
||||||
|
$viteManifest = dirname(__DIR__) . $assetDirectory . '/manifest.json';
|
||||||
|
$manifest = json_decode(file_get_contents($viteManifest), true);
|
||||||
|
if (!empty($manifest[$filename]['file'])) {
|
||||||
|
$links[] = $basehref . ltrim($assetDirectory, '/') . $manifest[$filename]['file'];
|
||||||
|
} else {
|
||||||
|
// additional asset from config.json that was not prebuilt on release (e.g. custom.css)
|
||||||
|
$links[] = $filename;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$links[] = $filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the links to the correct html tags
|
||||||
|
foreach ($links as $key => $link) {
|
||||||
|
switch (pathinfo($link, PATHINFO_EXTENSION)) {
|
||||||
|
case 'css':
|
||||||
|
$links[$key] = '<link rel="stylesheet" href="'. $link . '">';
|
||||||
|
break;
|
||||||
|
case 'js':
|
||||||
|
$links[$key] = '<script src="' . $link . '" type="module"></script>';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception('Unknown file extension for file '. $link .' from manifest.json');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode("\n", $links);
|
||||||
|
}
|
||||||
|
|||||||
78
lib/init.php
78
lib/init.php
@@ -50,10 +50,12 @@ if (!file_exists(dirname(__DIR__) . '/vendor/autoload.php')) {
|
|||||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
use Froxlor\CurrentUser;
|
use Froxlor\CurrentUser;
|
||||||
|
use Froxlor\FileDir;
|
||||||
use Froxlor\Froxlor;
|
use Froxlor\Froxlor;
|
||||||
use Froxlor\FroxlorLogger;
|
use Froxlor\FroxlorLogger;
|
||||||
use Froxlor\Http\RateLimiter;
|
use Froxlor\Http\RateLimiter;
|
||||||
use Froxlor\Idna\IdnaWrapper;
|
use Froxlor\Idna\IdnaWrapper;
|
||||||
|
use Froxlor\Install\Update;
|
||||||
use Froxlor\Language;
|
use Froxlor\Language;
|
||||||
use Froxlor\PhpHelper;
|
use Froxlor\PhpHelper;
|
||||||
use Froxlor\Settings;
|
use Froxlor\Settings;
|
||||||
@@ -63,7 +65,7 @@ use Froxlor\UI\Linker;
|
|||||||
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\Install\Update;
|
use Froxlor\Install\Requirements;
|
||||||
|
|
||||||
// include MySQL-tabledefinitions
|
// include MySQL-tabledefinitions
|
||||||
require Froxlor::getInstallDir() . '/lib/tables.inc.php';
|
require Froxlor::getInstallDir() . '/lib/tables.inc.php';
|
||||||
@@ -110,6 +112,40 @@ if (!isset($sql) || !is_array($sql)) {
|
|||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show nice note if requested domain is "unknown" to froxlor and thus is being lead to its vhost
|
||||||
|
*/
|
||||||
|
$req_host = UI::getCookieHost();
|
||||||
|
if ($req_host != Settings::Get('system.hostname') &&
|
||||||
|
Settings::Get('panel.is_configured') == 1 &&
|
||||||
|
!filter_var($req_host, FILTER_VALIDATE_IP) && (
|
||||||
|
empty(Settings::Get('system.froxloraliases')) ||
|
||||||
|
(!empty(Settings::Get('system.froxloraliases')) && !in_array($req_host, array_map('trim', explode(',', Settings::Get('system.froxloraliases')))))
|
||||||
|
)) {
|
||||||
|
// not the froxlor system-hostname, show info page for domains not configured in froxlor
|
||||||
|
$redirect_file = FileDir::getUnknownDomainTemplate($req_host ?? "non-detectable http-host");
|
||||||
|
header('Location: '.$redirect_file);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate php-extensions requirements
|
||||||
|
$loadedExtensions = get_loaded_extensions();
|
||||||
|
$missingExtensions = [];
|
||||||
|
foreach (Requirements::REQUIRED_EXTENSIONS as $requiredExtension) {
|
||||||
|
if (in_array($requiredExtension, $loadedExtensions)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$missingExtensions[] = $requiredExtension;
|
||||||
|
}
|
||||||
|
if (!empty($missingExtensions)) {
|
||||||
|
UI::twig()->addGlobal('install_mode', '1');
|
||||||
|
echo UI::twig()->render($_deftheme . '/misc/missingextensionhint.html.twig', [
|
||||||
|
'phpversion' => phpversion(),
|
||||||
|
'missing_extensions' => implode(", ", $missingExtensions),
|
||||||
|
]);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
// set error-handler
|
// set error-handler
|
||||||
@set_error_handler([
|
@set_error_handler([
|
||||||
'\\Froxlor\\PhpHelper',
|
'\\Froxlor\\PhpHelper',
|
||||||
@@ -168,7 +204,7 @@ if (Update::versionInUpdate(Settings::Get('panel.version'), '2.0.0-beta1')) {
|
|||||||
|
|
||||||
// Check if a different variant of the theme is used
|
// Check if a different variant of the theme is used
|
||||||
$themevariant = "default";
|
$themevariant = "default";
|
||||||
if (preg_match("/([a-z0-9\.\-]+)_([a-z0-9\.\-]+)/i", $theme, $matches)) {
|
if (preg_match("/([a-z0-9.\-]+)_([a-z0-9.\-]+)/i", $theme, $matches)) {
|
||||||
$theme = $matches[1];
|
$theme = $matches[1];
|
||||||
$themevariant = $matches[2];
|
$themevariant = $matches[2];
|
||||||
}
|
}
|
||||||
@@ -188,6 +224,10 @@ if (is_array($_themeoptions) && (!array_key_exists('variants', $_themeoptions) |
|
|||||||
$themevariant = "default";
|
$themevariant = "default";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('global', $_themeoptions)) {
|
||||||
|
$_themeoptions['variants'][$themevariant] = PhpHelper::array_merge_recursive_distinct($_themeoptions['global'], $_themeoptions['variants'][$themevariant]);
|
||||||
|
}
|
||||||
|
|
||||||
// check for custom header-graphic
|
// check for custom header-graphic
|
||||||
$hl_path = 'templates/' . $theme . '/assets/img';
|
$hl_path = 'templates/' . $theme . '/assets/img';
|
||||||
|
|
||||||
@@ -209,8 +249,11 @@ if (Settings::Get('panel.logo_overridecustom') == 0 && file_exists($hl_path . '/
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$color_scheme = $_themeoptions['variants'][$themevariant]['color-scheme'] ?? 'auto';
|
||||||
|
|
||||||
UI::twig()->addGlobal('header_logo_login', $header_logo_login);
|
UI::twig()->addGlobal('header_logo_login', $header_logo_login);
|
||||||
UI::twig()->addGlobal('header_logo', $header_logo);
|
UI::twig()->addGlobal('header_logo', $header_logo);
|
||||||
|
UI::twig()->addGlobal('color_scheme', $color_scheme);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirects to index.php (login page) if no session exists
|
* Redirects to index.php (login page) if no session exists
|
||||||
@@ -235,7 +278,7 @@ if (CurrentUser::hasSession()) {
|
|||||||
$log = FroxlorLogger::getInstanceOf($userinfo);
|
$log = FroxlorLogger::getInstanceOf($userinfo);
|
||||||
if ((CurrentUser::isAdmin() && AREA != 'admin') || (!CurrentUser::isAdmin() && AREA != 'customer')) {
|
if ((CurrentUser::isAdmin() && AREA != 'admin') || (!CurrentUser::isAdmin() && AREA != 'customer')) {
|
||||||
// user tries to access an area not meant for him -> redirect to corresponding index
|
// user tries to access an area not meant for him -> redirect to corresponding index
|
||||||
Response::redirectTo((CurrentUser::isAdmin() ? 'admin' : 'customer') . '_index.php', $params);
|
Response::redirectTo((CurrentUser::isAdmin() ? 'admin' : 'customer') . '_index.php');
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -274,29 +317,21 @@ if (AREA == 'admin' || AREA == 'customer') {
|
|||||||
}
|
}
|
||||||
UI::twig()->addGlobal('nav_entries', $navigation);
|
UI::twig()->addGlobal('nav_entries', $navigation);
|
||||||
|
|
||||||
$js = "";
|
$theme_assets = [];
|
||||||
$css = "";
|
foreach (['css', 'js'] as $asset) {
|
||||||
if (is_array($_themeoptions) && array_key_exists('js', $_themeoptions['variants'][$themevariant])) {
|
if (is_array($_themeoptions) && array_key_exists($asset, $_themeoptions['variants'][$themevariant])) {
|
||||||
if (is_array($_themeoptions['variants'][$themevariant]['js'])) {
|
if (is_array($_themeoptions['variants'][$themevariant][$asset])) {
|
||||||
foreach ($_themeoptions['variants'][$themevariant]['js'] as $jsfile) {
|
foreach ($_themeoptions['variants'][$themevariant][$asset] as $assetfile) {
|
||||||
if (file_exists('templates/' . $theme . '/assets/js/' . $jsfile)) {
|
if (file_exists('templates/' . $theme . '/' . $assetfile)) {
|
||||||
$js .= '<script type="text/javascript" src="' . mix('templates/' . $theme . '/assets/js/' . $jsfile) . '"></script>' . "\n";
|
$theme_assets[] .= 'templates/' . $theme . '/' . $assetfile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is_array($_themeoptions['variants'][$themevariant]['css'])) {
|
|
||||||
foreach ($_themeoptions['variants'][$themevariant]['css'] as $cssfile) {
|
|
||||||
if (file_exists('templates/' . $theme . '/assets/css/' . $cssfile)) {
|
|
||||||
$css .= '<link href="' . mix('templates/' . $theme . '/assets/css/' . $cssfile) . '" rel="stylesheet" type="text/css" />' . "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UI::twig()->addGlobal('theme_js', $js);
|
UI::twig()->addGlobal('theme_assets', $theme_assets);
|
||||||
UI::twig()->addGlobal('theme_css', $css);
|
unset($theme_assets);
|
||||||
unset($js);
|
|
||||||
unset($css);
|
|
||||||
|
|
||||||
$action = Request::any('action');
|
$action = Request::any('action');
|
||||||
$page = Request::any('page', 'overview');
|
$page = Request::any('page', 'overview');
|
||||||
@@ -328,6 +363,7 @@ if (CurrentUser::hasSession()) {
|
|||||||
if (in_array($_SERVER['REQUEST_METHOD'], ['POST', 'PUT', 'PATCH', 'DELETE'])) {
|
if (in_array($_SERVER['REQUEST_METHOD'], ['POST', 'PUT', 'PATCH', 'DELETE'])) {
|
||||||
$current_token = $_POST['csrf_token'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? null;
|
$current_token = $_POST['csrf_token'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? null;
|
||||||
if ($current_token != CurrentUser::getField('csrf_token')) {
|
if ($current_token != CurrentUser::getField('csrf_token')) {
|
||||||
|
http_response_code(403);
|
||||||
Response::dynamicError('CSRF validation failed');
|
Response::dynamicError('CSRF validation failed');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -341,4 +377,6 @@ if (CurrentUser::hasSession()) {
|
|||||||
'samesite' => 'Strict'
|
'samesite' => 'Strict'
|
||||||
];
|
];
|
||||||
setcookie(session_name(), $_COOKIE[session_name()], $cookie_params);
|
setcookie(session_name(), $_COOKIE[session_name()], $cookie_params);
|
||||||
|
} else {
|
||||||
|
UI::twig()->addGlobal('csrf_token', Froxlor::genSessionId(20));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,13 +161,13 @@ return [
|
|||||||
'show_element' => (!Settings::IsInList('panel.customer_hide_options', 'misc.documentation')),
|
'show_element' => (!Settings::IsInList('panel.customer_hide_options', 'misc.documentation')),
|
||||||
'elements' => [
|
'elements' => [
|
||||||
[
|
[
|
||||||
'url' => 'https://docs.froxlor.org/v2/user-guide/',
|
'url' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/',
|
||||||
'label' => lng('admin.userguide'),
|
'label' => lng('admin.userguide'),
|
||||||
'new_window' => true,
|
'new_window' => true,
|
||||||
'is_external' => true,
|
'is_external' => true,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'url' => 'https://docs.froxlor.org/v2/api-guide/',
|
'url' => \Froxlor\Froxlor::DOCS_URL . 'api-guide/',
|
||||||
'label' => lng('admin.apiguide'),
|
'label' => lng('admin.apiguide'),
|
||||||
'new_window' => true,
|
'new_window' => true,
|
||||||
'show_element' => Settings::Get('api.enabled') == 1 && CurrentUser::getField('api_allowed') == 1,
|
'show_element' => Settings::Get('api.enabled') == 1 && CurrentUser::getField('api_allowed') == 1,
|
||||||
@@ -348,13 +348,13 @@ return [
|
|||||||
'icon' => 'fa-solid fa-circle-info',
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
'elements' => [
|
'elements' => [
|
||||||
[
|
[
|
||||||
'url' => 'https://docs.froxlor.org/v2/admin-guide/',
|
'url' => \Froxlor\Froxlor::DOCS_URL . 'admin-guide/',
|
||||||
'label' => lng('admin.adminguide'),
|
'label' => lng('admin.adminguide'),
|
||||||
'new_window' => true,
|
'new_window' => true,
|
||||||
'is_external' => true,
|
'is_external' => true,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'url' => 'https://docs.froxlor.org/v2/api-guide/',
|
'url' => \Froxlor\Froxlor::DOCS_URL . 'api-guide/',
|
||||||
'label' => lng('admin.apiguide'),
|
'label' => lng('admin.apiguide'),
|
||||||
'new_window' => true,
|
'new_window' => true,
|
||||||
'show_element' => Settings::Get('api.enabled') == 1,
|
'show_element' => Settings::Get('api.enabled') == 1,
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ return [
|
|||||||
'label' => lng('domains.domainname'),
|
'label' => lng('domains.domainname'),
|
||||||
'field' => 'domain_ace',
|
'field' => 'domain_ace',
|
||||||
'isdefaultsearchfield' => true,
|
'isdefaultsearchfield' => true,
|
||||||
|
'callback' => [Domain::class, 'domainLink'],
|
||||||
],
|
],
|
||||||
'ipsandports' => [
|
'ipsandports' => [
|
||||||
'label' => lng('admin.ipsandports.ipsandports'),
|
'label' => lng('admin.ipsandports.ipsandports'),
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ return [
|
|||||||
'field' => 'domains',
|
'field' => 'domains',
|
||||||
'callback' => [PHPConf::class, 'domainList'],
|
'callback' => [PHPConf::class, 'domainList'],
|
||||||
'searchable' => false,
|
'searchable' => false,
|
||||||
|
'sortable' => false,
|
||||||
],
|
],
|
||||||
'fpmdesc' => [
|
'fpmdesc' => [
|
||||||
'label' => lng('admin.phpsettings.fpmdesc'),
|
'label' => lng('admin.phpsettings.fpmdesc'),
|
||||||
|
|||||||
@@ -2324,7 +2324,7 @@ Atentament, el vostre administrador'
|
|||||||
]
|
]
|
||||||
],
|
],
|
||||||
'install' => [
|
'install' => [
|
||||||
'slogal' => 'Panell de gestió del servidor froxlor',
|
'slogan' => 'Panell de gestió del servidor froxlor',
|
||||||
'preflight' => 'Comprovació del sistema',
|
'preflight' => 'Comprovació del sistema',
|
||||||
'critical_error' => 'Error crític',
|
'critical_error' => 'Error crític',
|
||||||
'suggestions' => 'No requerit però recomanat',
|
'suggestions' => 'No requerit però recomanat',
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ return [
|
|||||||
'customer_add' => 'Kunden anlegen',
|
'customer_add' => 'Kunden anlegen',
|
||||||
'customer_edit' => 'Kunden bearbeiten',
|
'customer_edit' => 'Kunden bearbeiten',
|
||||||
'username_default_msg' => 'Leer lassen für automatische Benutzername-Vergabe',
|
'username_default_msg' => 'Leer lassen für automatische Benutzername-Vergabe',
|
||||||
|
'password_default_msg' => 'Leer lassen für Passwortgenerierung',
|
||||||
'domains' => 'Domains',
|
'domains' => 'Domains',
|
||||||
'domain_add' => 'Domain anlegen',
|
'domain_add' => 'Domain anlegen',
|
||||||
'domain_edit' => 'Domain bearbeiten',
|
'domain_edit' => 'Domain bearbeiten',
|
||||||
@@ -140,12 +141,18 @@ return [
|
|||||||
'TRAFFICUSED' => 'Wird mit Traffic, der vom Kunden bereits verbraucht wurde, ersetzt.',
|
'TRAFFICUSED' => 'Wird mit Traffic, der vom Kunden bereits verbraucht wurde, ersetzt.',
|
||||||
'pop_success_alternative' => 'Willkommensmail für neue E-Mail-Konten für die alternative E-Mail-Adresse',
|
'pop_success_alternative' => 'Willkommensmail für neue E-Mail-Konten für die alternative E-Mail-Adresse',
|
||||||
'EMAIL_PASSWORD' => 'Wird mit dem Passwort des neuen POP3/IMAP Kontos ersetzt.',
|
'EMAIL_PASSWORD' => 'Wird mit dem Passwort des neuen POP3/IMAP Kontos ersetzt.',
|
||||||
'index_html' => 'index.html Datei für neu erzeugte Kundenverzeichnisse',
|
'index_html' => 'index Datei für neu erzeugte Kundenverzeichnisse',
|
||||||
|
'unconfigured_html' => 'index Datei für unkonfigurierte/unbekannte Domains',
|
||||||
|
'unconfigured_content_fallback' => 'Diese Domain muss über das Froxlor-Serververwaltungspanel konfiguriert werden, da sie derzeit keinem Kunden zugewiesen ist.',
|
||||||
|
'file_extension' => [
|
||||||
|
'description' => 'Die Dateiendung für die index Datei muss zwischen 1 und 6 Zeichen lang sein und darf nur aus den Zeichen a-z, A-Z und 0-9 bestehen<br><br>Standard: html',
|
||||||
|
'title' => 'Dateiendung für Datei Vorlage',
|
||||||
|
],
|
||||||
'SERVERNAME' => 'Wird mit dem Servernamen ersetzt.',
|
'SERVERNAME' => 'Wird mit dem Servernamen ersetzt.',
|
||||||
'CUSTOMER' => 'Wird mit dem Loginnamen des Kunden ersetzt.',
|
'CUSTOMER' => 'Wird mit dem Loginnamen des Kunden ersetzt. Nur für "index Datei für neu erzeugte Kundenverzeichnisse".',
|
||||||
'ADMIN' => 'Wird mit dem Loginnamen des Admins ersetzt.',
|
'ADMIN' => 'Wird mit dem Loginnamen des Admins ersetzt. Nur für "index Datei für neu erzeugte Kundenverzeichnisse".',
|
||||||
'CUSTOMER_EMAIL' => 'Wird mit der E-Mail-Adresse des Kunden ersetzt.',
|
'CUSTOMER_EMAIL' => 'Wird mit der E-Mail-Adresse des Kunden ersetzt. Nur für "index Datei für neu erzeugte Kundenverzeichnisse".',
|
||||||
'ADMIN_EMAIL' => 'Wird mit der E-Mail-Adresse des Admin ersetzt.',
|
'ADMIN_EMAIL' => 'Wird mit der E-Mail-Adresse des Admin ersetzt. Nur für "index Datei für neu erzeugte Kundenverzeichnisse".',
|
||||||
'filetemplates' => 'Dateivorlagen',
|
'filetemplates' => 'Dateivorlagen',
|
||||||
'filecontent' => 'Dateiinhalt',
|
'filecontent' => 'Dateiinhalt',
|
||||||
'new_database_by_customer' => 'Kunden-Benachrichtigungs nach Erstellung einer neuen Datenbank',
|
'new_database_by_customer' => 'Kunden-Benachrichtigungs nach Erstellung einer neuen Datenbank',
|
||||||
@@ -831,7 +838,6 @@ return [
|
|||||||
'descriptioninvalid' => 'Der Beschreibungstext ist zu kurz, zu lang oder enthält ungültige Zeichen',
|
'descriptioninvalid' => 'Der Beschreibungstext ist zu kurz, zu lang oder enthält ungültige Zeichen',
|
||||||
'info' => 'Info',
|
'info' => 'Info',
|
||||||
'filecontentnotset' => 'Diese Datei darf nicht leer sein!',
|
'filecontentnotset' => 'Diese Datei darf nicht leer sein!',
|
||||||
'index_file_extension' => 'Die Dateiendung für die index Datei muss zwischen 1 und 6 Zeichen lang sein und darf nur aus den Zeichen a-z, A-Z und 0-9 bestehen',
|
|
||||||
'customerdoesntexist' => 'Der ausgewählte Kunde existiert nicht.',
|
'customerdoesntexist' => 'Der ausgewählte Kunde existiert nicht.',
|
||||||
'admindoesntexist' => 'Der ausgewählte Admin existiert nicht.',
|
'admindoesntexist' => 'Der ausgewählte Admin existiert nicht.',
|
||||||
'ipportdoesntexist' => 'Die gewählte IP/Port-Kombination existiert nicht.',
|
'ipportdoesntexist' => 'Die gewählte IP/Port-Kombination existiert nicht.',
|
||||||
@@ -920,6 +926,7 @@ return [
|
|||||||
'dns_duplicate_entry' => 'Eintrag existiert bereits',
|
'dns_duplicate_entry' => 'Eintrag existiert bereits',
|
||||||
'dns_notfoundorallowed' => 'Domain nicht gefunden oder keine Berechtigung',
|
'dns_notfoundorallowed' => 'Domain nicht gefunden oder keine Berechtigung',
|
||||||
'domain_nopunycode' => 'Die Eingabe von Punycode (IDNA) ist nicht notwendig. Die Domain wird automatisch konvertiert.',
|
'domain_nopunycode' => 'Die Eingabe von Punycode (IDNA) ist nicht notwendig. Die Domain wird automatisch konvertiert.',
|
||||||
|
'domain_noipaddress' => 'Eine IP-Adresse kann nicht als Domain angelegt werden',
|
||||||
'dns_record_toolong' => 'Records/Labels können maximal 63 Zeichen lang sein',
|
'dns_record_toolong' => 'Records/Labels können maximal 63 Zeichen lang sein',
|
||||||
'noipportgiven' => 'Keine IP/Port angegeben',
|
'noipportgiven' => 'Keine IP/Port angegeben',
|
||||||
'nosslippportgiven' => 'Wenn SSL aktiviert ist, muss eine SSL IP/Port angegeben werden',
|
'nosslippportgiven' => 'Wenn SSL aktiviert ist, muss eine SSL IP/Port angegeben werden',
|
||||||
@@ -1308,6 +1315,8 @@ Vielen Dank, Ihr Administrator',
|
|||||||
'dnsentry_reallydelete' => 'Wollen Sie den DNS-Eintrag wirklich löschen?',
|
'dnsentry_reallydelete' => 'Wollen Sie den DNS-Eintrag wirklich löschen?',
|
||||||
'certificate_reallydelete' => 'Wollen Sie diese Zertifikat wirklich löschen?',
|
'certificate_reallydelete' => 'Wollen Sie diese Zertifikat wirklich löschen?',
|
||||||
'cache_reallydelete' => 'Wollen Sie den Cache wirklich leeren?',
|
'cache_reallydelete' => 'Wollen Sie den Cache wirklich leeren?',
|
||||||
|
'please_enter_otp' => 'Bitte 2FA Code eingeben',
|
||||||
|
'admin_mysqlserver_reallydelete' => 'Wollen Sie wirklich diesen MySQL-Server löschen?',
|
||||||
],
|
],
|
||||||
'serversettings' => [
|
'serversettings' => [
|
||||||
'session_timeout' => [
|
'session_timeout' => [
|
||||||
@@ -1608,10 +1617,6 @@ Vielen Dank, Ihr Administrator',
|
|||||||
'removelink' => 'Hier klicken, um alle E-Mail-Kontingente zu entfernen',
|
'removelink' => 'Hier klicken, um alle E-Mail-Kontingente zu entfernen',
|
||||||
'enforcelink' => 'Hier klicken, um allen Benutzern das Standard-Kontingent zu zuweisen.',
|
'enforcelink' => 'Hier klicken, um allen Benutzern das Standard-Kontingent zu zuweisen.',
|
||||||
],
|
],
|
||||||
'index_file_extension' => [
|
|
||||||
'description' => 'Welche Dateiendung soll die index Datei in neu erstellten Kundenverzeichnissen haben? Diese Dateiendung wird dann verwendet, wenn Sie bzw. einer Ihrer Admins eigene index Dateivorlagen erstellt haben.',
|
|
||||||
'title' => 'Dateiendung für index Datei in neu erstellen Kundenverzeichnissen',
|
|
||||||
],
|
|
||||||
'session_allow_multiple_login' => [
|
'session_allow_multiple_login' => [
|
||||||
'title' => 'Erlaube gleichzeitigen Login',
|
'title' => 'Erlaube gleichzeitigen Login',
|
||||||
'description' => 'Wenn diese Option aktiviert ist, können sich Nutzer mehrmals gleichzeitig anmelden.',
|
'description' => 'Wenn diese Option aktiviert ist, können sich Nutzer mehrmals gleichzeitig anmelden.',
|
||||||
@@ -2240,7 +2245,7 @@ Vielen Dank, Ihr Administrator',
|
|||||||
'database' => [
|
'database' => [
|
||||||
'top' => 'Datenbank',
|
'top' => 'Datenbank',
|
||||||
'title' => 'Datenbank und Benutzer erstellen',
|
'title' => 'Datenbank und Benutzer erstellen',
|
||||||
'description' => 'Froxlor benötigt eine Datenbank und zusätzlich einen Benutzer mit privilegierten Rechten, welcher Benutzer und Datenbanken erstellen darf (GRANT Option). Die angegebene Datenbank und der unprivilegierte Benutzer werden automatisch in diesem Prozess erstellt. Der privilegierte Benutzer muss existieren.',
|
'description' => 'Froxlor benötigt eine Datenbank und zusätzlich <a href="https://docs.froxlor.org/latest/general/installation/tarball.html#_3-create-privileged-database-user" target="_blank">einen Benutzer mit privilegierten Rechten</a>, welcher Benutzer und Datenbanken erstellen darf (GRANT Option). Die angegebene Datenbank und der unprivilegierte Benutzer werden automatisch in diesem Prozess erstellt. Der privilegierte Benutzer muss existieren.',
|
||||||
'user' => 'Unprivilegierter Datenbank Benutzer',
|
'user' => 'Unprivilegierter Datenbank Benutzer',
|
||||||
'dbname' => 'Datenbank Name',
|
'dbname' => 'Datenbank Name',
|
||||||
'force_create' => 'Sichern und überschreiben, sofern Datenbank existiert?',
|
'force_create' => 'Sichern und überschreiben, sofern Datenbank existiert?',
|
||||||
@@ -2249,6 +2254,8 @@ Vielen Dank, Ihr Administrator',
|
|||||||
'top' => 'Admin Konto',
|
'top' => 'Admin Konto',
|
||||||
'title' => 'Erstellen des Haupt-Administrators.',
|
'title' => 'Erstellen des Haupt-Administrators.',
|
||||||
'description' => 'Dieser Benutzer erhält alle Berechtigungen zur Anpassungen von Einstellungen und Erstellen/Bearbeiten/Löschen von Resourcen wie Kunden, Domains, etc.',
|
'description' => 'Dieser Benutzer erhält alle Berechtigungen zur Anpassungen von Einstellungen und Erstellen/Bearbeiten/Löschen von Resourcen wie Kunden, Domains, etc.',
|
||||||
|
'use_admin_email_as_sender' => 'Verwende die oben angegebene E-Mail-Adresse als Absenderadresse. Wenn die Option deaktiviert ist, geben Sie unten bitte eine Absenderadresse an.',
|
||||||
|
'use_autogenerated_email_as_sender' => 'Leer lassen für Standard: admin@servername',
|
||||||
],
|
],
|
||||||
'system' => [
|
'system' => [
|
||||||
'top' => 'System Setup',
|
'top' => 'System Setup',
|
||||||
@@ -2263,7 +2270,7 @@ Vielen Dank, Ihr Administrator',
|
|||||||
'install' => [
|
'install' => [
|
||||||
'top' => 'Abschluss',
|
'top' => 'Abschluss',
|
||||||
'title' => 'Ein letzter Schritt...',
|
'title' => 'Ein letzter Schritt...',
|
||||||
'description' => 'Der untenstehende Befehl lädt, installiert und konfiguriert die benötigten Dienste auf dem System aufgrund der Angaben die während des Installationsprozessen gesammelt wurden.<br><br><span class="text-danger">Führe die gezeigten Befehle als <b>root</b> in der Shell/Konsole des Servers aus.</span>',
|
'description' => 'Der untenstehende Befehl lädt, installiert und konfiguriert die benötigten Dienste auf dem System aufgrund der Angaben die während des Installationsprozessen gesammelt wurden.<br><br><span class="text-danger">Führe die gezeigten Befehle als <b>root</b> in der Shell/Konsole des Servers aus. <b>Beachte bitte</b> das dieser Befehl vorhandene Konfigurationen <b>überschreibt</b> (Sicherungsdateien werden erstellt)!<br>Sollte dies nicht gewünscht sein, wähle <i>Ich werden die Dienste manuell konfigurieren</i> am Ende dieser Seite.</span>',
|
||||||
'runcmd' => 'Folgende Befehle ausführen, um die Installation abzuschließen:',
|
'runcmd' => 'Folgende Befehle ausführen, um die Installation abzuschließen:',
|
||||||
'manual_config' => 'Ich werden die Dienste manuell konfigurieren, direkt zum Login umleiten',
|
'manual_config' => 'Ich werden die Dienste manuell konfigurieren, direkt zum Login umleiten',
|
||||||
'waitforconfig' => 'Warte auf Abschluss der Dienstkonfiguration...',
|
'waitforconfig' => 'Warte auf Abschluss der Dienstkonfiguration...',
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ return [
|
|||||||
'customer_add' => 'Create customer',
|
'customer_add' => 'Create customer',
|
||||||
'customer_edit' => 'Edit customer',
|
'customer_edit' => 'Edit customer',
|
||||||
'username_default_msg' => 'Leave empty for autogenerated value',
|
'username_default_msg' => 'Leave empty for autogenerated value',
|
||||||
|
'password_default_msg' => 'Autogenerated if empty',
|
||||||
'domains' => 'Domains',
|
'domains' => 'Domains',
|
||||||
'domain_add' => 'Create domain',
|
'domain_add' => 'Create domain',
|
||||||
'domain_edit' => 'Edit domain',
|
'domain_edit' => 'Edit domain',
|
||||||
@@ -144,11 +145,17 @@ return [
|
|||||||
'pop_success_alternative' => 'Welcome mail for new email accounts sent to alternative address',
|
'pop_success_alternative' => 'Welcome mail for new email accounts sent to alternative address',
|
||||||
'EMAIL_PASSWORD' => 'Replaced with the POP3/IMAP account password.',
|
'EMAIL_PASSWORD' => 'Replaced with the POP3/IMAP account password.',
|
||||||
'index_html' => 'index file for newly created customer directories',
|
'index_html' => 'index file for newly created customer directories',
|
||||||
|
'unconfigured_html' => 'index file for unconfigured/unknown domains',
|
||||||
|
'unconfigured_content_fallback' => 'This domain requires configuration via the froxlor server management panel, as it is currently not assigned to any customer.',
|
||||||
|
'file_extension' => [
|
||||||
|
'description' => 'The file extension for the index file must be between 1 and 6 characters long. The extension can only contain characters like a-z, A-Z and 0-9<br><br>Default: html',
|
||||||
|
'title' => 'File extension for the file template',
|
||||||
|
],
|
||||||
'SERVERNAME' => 'Replaced with the servername.',
|
'SERVERNAME' => 'Replaced with the servername.',
|
||||||
'CUSTOMER' => 'Replaced with the loginname of the customer.',
|
'CUSTOMER' => 'Replaced with the loginname of the customer. Only for "index file for newly created customer directories"',
|
||||||
'ADMIN' => 'Replaced with the loginname of the admin.',
|
'ADMIN' => 'Replaced with the loginname of the admin. Only for "index file for newly created customer directories"',
|
||||||
'CUSTOMER_EMAIL' => 'Replaced with the e-mail address of the customer.',
|
'CUSTOMER_EMAIL' => 'Replaced with the e-mail address of the customer. Only for "index file for newly created customer directories"',
|
||||||
'ADMIN_EMAIL' => 'Replaced with the e-mail address of the admin.',
|
'ADMIN_EMAIL' => 'Replaced with the e-mail address of the admin. Only for "index file for newly created customer directories"',
|
||||||
'filetemplates' => 'File templates',
|
'filetemplates' => 'File templates',
|
||||||
'filecontent' => 'File content',
|
'filecontent' => 'File content',
|
||||||
'new_database_by_customer' => 'Customer-notification when a database has been created',
|
'new_database_by_customer' => 'Customer-notification when a database has been created',
|
||||||
@@ -903,7 +910,6 @@ return [
|
|||||||
'descriptioninvalid' => 'The description is too short, too long or contains illegal characters.',
|
'descriptioninvalid' => 'The description is too short, too long or contains illegal characters.',
|
||||||
'info' => 'Info',
|
'info' => 'Info',
|
||||||
'filecontentnotset' => 'The file cannot be empty!',
|
'filecontentnotset' => 'The file cannot be empty!',
|
||||||
'index_file_extension' => 'The file extension for the index file must be between 1 and 6 characters long. The extension can only contain characters like a-z, A-Z and 0-9',
|
|
||||||
'customerdoesntexist' => 'The customer you have chosen doesn\'t exist.',
|
'customerdoesntexist' => 'The customer you have chosen doesn\'t exist.',
|
||||||
'admindoesntexist' => 'The admin you have chosen doesn\'t exist.',
|
'admindoesntexist' => 'The admin you have chosen doesn\'t exist.',
|
||||||
'ipportdoesntexist' => 'The ip/port combination you have chosen doesn\'t exist.',
|
'ipportdoesntexist' => 'The ip/port combination you have chosen doesn\'t exist.',
|
||||||
@@ -992,6 +998,7 @@ return [
|
|||||||
'dns_duplicate_entry' => 'Record already exists',
|
'dns_duplicate_entry' => 'Record already exists',
|
||||||
'dns_notfoundorallowed' => 'Domain not found or no permission',
|
'dns_notfoundorallowed' => 'Domain not found or no permission',
|
||||||
'domain_nopunycode' => 'You must not specify punycode (IDNA). The domain will automatically be converted',
|
'domain_nopunycode' => 'You must not specify punycode (IDNA). The domain will automatically be converted',
|
||||||
|
'domain_noipaddress' => 'Cannot add an IP address as domain',
|
||||||
'dns_record_toolong' => 'Records/labels can only be up to 63 characters',
|
'dns_record_toolong' => 'Records/labels can only be up to 63 characters',
|
||||||
'noipportgiven' => 'No IP/port given',
|
'noipportgiven' => 'No IP/port given',
|
||||||
'nosslippportgiven' => 'When enabling SSL you need to select a SSL IP/port',
|
'nosslippportgiven' => 'When enabling SSL you need to select a SSL IP/port',
|
||||||
@@ -1423,6 +1430,8 @@ Yours sincerely, your administrator',
|
|||||||
'dnsentry_reallydelete' => 'Do you really want to delete this zone entry?',
|
'dnsentry_reallydelete' => 'Do you really want to delete this zone entry?',
|
||||||
'certificate_reallydelete' => 'Do you really want to delete this certificate?',
|
'certificate_reallydelete' => 'Do you really want to delete this certificate?',
|
||||||
'cache_reallydelete' => 'Do you really want to clear the cache?',
|
'cache_reallydelete' => 'Do you really want to clear the cache?',
|
||||||
|
'please_enter_otp' => 'Please enter 2FA code',
|
||||||
|
'admin_mysqlserver_reallydelete' => 'Do you really want to delete this MySQL-server?',
|
||||||
],
|
],
|
||||||
'redirect_desc' => [
|
'redirect_desc' => [
|
||||||
'rc_default' => 'default',
|
'rc_default' => 'default',
|
||||||
@@ -1730,10 +1739,6 @@ Yours sincerely, your administrator',
|
|||||||
'removelink' => 'Click here to wipe all quotas for mail accounts.',
|
'removelink' => 'Click here to wipe all quotas for mail accounts.',
|
||||||
'enforcelink' => 'Click here to enforce default quota to all User mail accounts.',
|
'enforcelink' => 'Click here to enforce default quota to all User mail accounts.',
|
||||||
],
|
],
|
||||||
'index_file_extension' => [
|
|
||||||
'description' => 'Which file extension should be used for the index file in newly created customer directories? This file extension will be used, if you or one of your admins has created its own index file template.',
|
|
||||||
'title' => 'File extension for index file in newly created customer directories',
|
|
||||||
],
|
|
||||||
'session_allow_multiple_login' => [
|
'session_allow_multiple_login' => [
|
||||||
'title' => 'Allow multiple login',
|
'title' => 'Allow multiple login',
|
||||||
'description' => 'If activated a user could login multiple times.',
|
'description' => 'If activated a user could login multiple times.',
|
||||||
@@ -2208,6 +2213,7 @@ Yours sincerely, your administrator',
|
|||||||
],
|
],
|
||||||
'uc_stable' => 'stable',
|
'uc_stable' => 'stable',
|
||||||
'uc_testing' => 'testing',
|
'uc_testing' => 'testing',
|
||||||
|
'uc_nightly' => 'nightly',
|
||||||
'traffictool' => [
|
'traffictool' => [
|
||||||
'toolselect' => 'Traffic analyzer',
|
'toolselect' => 'Traffic analyzer',
|
||||||
'webalizer' => 'Webalizer',
|
'webalizer' => 'Webalizer',
|
||||||
@@ -2357,7 +2363,7 @@ Yours sincerely, your administrator',
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
'install' => [
|
'install' => [
|
||||||
'slogal' => 'froxlor Server Management Panel',
|
'slogan' => 'froxlor Server Management Panel',
|
||||||
'preflight' => 'System check',
|
'preflight' => 'System check',
|
||||||
'critical_error' => 'Critical error',
|
'critical_error' => 'Critical error',
|
||||||
'suggestions' => 'Not required but recommended',
|
'suggestions' => 'Not required but recommended',
|
||||||
@@ -2375,7 +2381,7 @@ Yours sincerely, your administrator',
|
|||||||
'database' => [
|
'database' => [
|
||||||
'top' => 'Database',
|
'top' => 'Database',
|
||||||
'title' => 'Create database and user',
|
'title' => 'Create database and user',
|
||||||
'description' => 'Froxlor requires a database and additionally a privileged user to be able to create users and databases (GRANT option). The given database and unprivileged database-user will be created in this process. The privileged user must exist.',
|
'description' => 'Froxlor requires a database and additionally <a href="https://docs.froxlor.org/latest/general/installation/tarball.html#_3-create-privileged-database-user" target="_blank">a privileged user</a> to be able to create users and databases (GRANT option). The given database and unprivileged database-user will be created in this process. The privileged user must exist.',
|
||||||
'user' => 'Unprivileged database user',
|
'user' => 'Unprivileged database user',
|
||||||
'dbname' => 'Database name',
|
'dbname' => 'Database name',
|
||||||
'force_create' => 'Backup and overwrite database if exists?',
|
'force_create' => 'Backup and overwrite database if exists?',
|
||||||
@@ -2384,6 +2390,8 @@ Yours sincerely, your administrator',
|
|||||||
'top' => 'Admin user',
|
'top' => 'Admin user',
|
||||||
'title' => 'Let\'s create the main administrator user.',
|
'title' => 'Let\'s create the main administrator user.',
|
||||||
'description' => 'This user will be granted all privileges to adjust settings and add/update/delete resources like customers, domains, etc.',
|
'description' => 'This user will be granted all privileges to adjust settings and add/update/delete resources like customers, domains, etc.',
|
||||||
|
'use_admin_email_as_sender' => 'Use the email address above as sender address. If unchecked, please specify a sender address below.',
|
||||||
|
'use_autogenerated_email_as_sender' => 'Leave empty for default: admin@servername',
|
||||||
],
|
],
|
||||||
'system' => [
|
'system' => [
|
||||||
'top' => 'System setup',
|
'top' => 'System setup',
|
||||||
@@ -2398,7 +2406,7 @@ Yours sincerely, your administrator',
|
|||||||
'install' => [
|
'install' => [
|
||||||
'top' => 'Finish setup',
|
'top' => 'Finish setup',
|
||||||
'title' => 'One last step...',
|
'title' => 'One last step...',
|
||||||
'description' => 'The command below will download, install and configure required services on your system according to the data you have given in this installation process.<br><br><span class="text-danger">Be sure to run the following command as <b>root</b> on the server\'s shell/terminal.</span>',
|
'description' => 'The command below will download, install and configure required services on your system according to the data you have given in this installation process.<br><br><span class="text-danger">Be sure to run the following command as <b>root</b> on the server\'s shell/terminal and <b>be aware</b> that this command will <b>overwrite</b> any existing configuration for the used services (backups will be created)!.<br>If you do not want to overwrite any configurations, select <i>I will manually configure the services</i> at the bottom of this page!</span>',
|
||||||
'runcmd' => 'Run the following command to finish the installation:',
|
'runcmd' => 'Run the following command to finish the installation:',
|
||||||
'manual_config' => 'I will manually configure the services, just take me to the login',
|
'manual_config' => 'I will manually configure the services, just take me to the login',
|
||||||
'waitforconfig' => 'Waiting for services to be configured...',
|
'waitforconfig' => 'Waiting for services to be configured...',
|
||||||
|
|||||||
@@ -2304,7 +2304,7 @@ Atentamente, su administrador'
|
|||||||
]
|
]
|
||||||
],
|
],
|
||||||
'install' => [
|
'install' => [
|
||||||
'slogal' => 'Panel de gestión del servidor froxlor',
|
'slogan' => 'Panel de gestión del servidor froxlor',
|
||||||
'preflight' => 'Comprobación del sistema',
|
'preflight' => 'Comprobación del sistema',
|
||||||
'critical_error' => 'Error crítico',
|
'critical_error' => 'Error crítico',
|
||||||
'suggestions' => 'No requerido pero recomendado',
|
'suggestions' => 'No requerido pero recomendado',
|
||||||
|
|||||||
9379
package-lock.json
generated
9379
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
28
package.json
28
package.json
@@ -2,19 +2,27 @@
|
|||||||
"name": "froxlor",
|
"name": "froxlor",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "mix watch",
|
"dev": "vite",
|
||||||
"build": "mix --production"
|
"build": "vite build"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^6.2.0",
|
"@fortawesome/fontawesome-free": "^6.4.2",
|
||||||
"@popperjs/core": "^2.11.6",
|
"@popperjs/core": "^2.11.8",
|
||||||
"bootstrap": "^5.2.1",
|
"@vitejs/plugin-vue": "^4.0.0",
|
||||||
"chart.js": "^3.9.1",
|
"axios": "^1.6.0",
|
||||||
|
"bootstrap": "^5.3.2",
|
||||||
|
"chart.js": "^4.4.0",
|
||||||
"jquery": "^3.6.1",
|
"jquery": "^3.6.1",
|
||||||
"jquery-validation": "^1.19.5",
|
"jquery-validation": "^1.20.0",
|
||||||
"laravel-mix": "^6.0.42",
|
"laravel-vite-plugin": "^0.8.0",
|
||||||
|
"lodash": "^4.17.19",
|
||||||
|
"postcss": "^8.1.14",
|
||||||
"resolve-url-loader": "^5.0.0",
|
"resolve-url-loader": "^5.0.0",
|
||||||
"sass": "^1.49.7",
|
"sass": "^1.69.3",
|
||||||
"sass-loader": "^12.5.0"
|
"vite": "^4.4.12",
|
||||||
|
"vue": "^3.2.37"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
14
templates/Froxlor/assets/js/app.js
Normal file
14
templates/Froxlor/assets/js/app.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import '@fortawesome/fontawesome-free';
|
||||||
|
import './bootstrap';
|
||||||
|
|
||||||
|
// Vue
|
||||||
|
import {createApp} from 'vue';
|
||||||
|
|
||||||
|
const app = createApp({});
|
||||||
|
|
||||||
|
// Load jquery components
|
||||||
|
Object.entries(import.meta.glob('./jquery/*.js', {eager: true})).forEach(([path, definition]) => {
|
||||||
|
definition.default();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.mount('#app');
|
||||||
21
templates/Froxlor/assets/js/bootstrap.js
vendored
Normal file
21
templates/Froxlor/assets/js/bootstrap.js
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
|
window._ = _;
|
||||||
|
|
||||||
|
// jQuery
|
||||||
|
import jQuery from 'jquery';
|
||||||
|
window.$ = jQuery;
|
||||||
|
import 'jquery-validation';
|
||||||
|
|
||||||
|
// Bootstrap
|
||||||
|
import * as bootstrap from 'bootstrap';
|
||||||
|
window.bootstrap = bootstrap;
|
||||||
|
|
||||||
|
// ChartJS
|
||||||
|
import Chart from 'chart.js/auto';
|
||||||
|
window.Chart = Chart;
|
||||||
|
|
||||||
|
// Axios
|
||||||
|
import axios from 'axios';
|
||||||
|
window.axios = axios;
|
||||||
|
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||||
|
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
||||||
68
templates/Froxlor/assets/js/jquery/apikeys.js
vendored
Normal file
68
templates/Froxlor/assets/js/jquery/apikeys.js
vendored
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
export default function () {
|
||||||
|
$(function () {
|
||||||
|
var timer, delay = 500;
|
||||||
|
$('div[data-action="apikeys"] #allowed_from').on('keyup change', function () {
|
||||||
|
var _this = $(this);
|
||||||
|
clearTimeout(timer);
|
||||||
|
timer = setTimeout(function () {
|
||||||
|
var akid = _this.closest('div[data-action="apikeys"]').data('entry');
|
||||||
|
$.ajax({
|
||||||
|
url: "lib/ajax.php?action=editapikey",
|
||||||
|
type: "POST",
|
||||||
|
dataType: "json",
|
||||||
|
data: {
|
||||||
|
id: akid,
|
||||||
|
allowed_from: _this.val(),
|
||||||
|
valid_until: $('div[data-entry="' + akid + '"] #valid_until').val()
|
||||||
|
},
|
||||||
|
success: function (data) {
|
||||||
|
if (data.message) {
|
||||||
|
_this.removeClass('is-valid');
|
||||||
|
_this.addClass('is-invalid');
|
||||||
|
} else {
|
||||||
|
_this.removeClass('is-invalid');
|
||||||
|
_this.addClass('is-valid');
|
||||||
|
_this.val(data.allowed_from);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (request, status, error) {
|
||||||
|
_this.removeClass('is-valid');
|
||||||
|
_this.addClass('is-invalid');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, delay);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('div[data-action="apikeys"] #valid_until').on('keyup change', function () {
|
||||||
|
var _this = $(this);
|
||||||
|
clearTimeout(timer);
|
||||||
|
timer = setTimeout(function () {
|
||||||
|
var akid = _this.closest('div[data-action="apikeys"]').data('entry');
|
||||||
|
$.ajax({
|
||||||
|
url: "lib/ajax.php?action=editapikey",
|
||||||
|
type: "POST",
|
||||||
|
dataType: "json",
|
||||||
|
data: {
|
||||||
|
id: akid,
|
||||||
|
valid_until: _this.val(),
|
||||||
|
allowed_from: $('div[data-entry="' + akid + '"] #allowed_from').val()
|
||||||
|
},
|
||||||
|
success: function (data) {
|
||||||
|
if (data.message) {
|
||||||
|
_this.removeClass('is-valid');
|
||||||
|
_this.addClass('is-invalid');
|
||||||
|
} else {
|
||||||
|
_this.removeClass('is-invalid');
|
||||||
|
_this.addClass('is-valid');
|
||||||
|
_this.val(data.valid_until);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (request, status, error) {
|
||||||
|
_this.removeClass('is-valid');
|
||||||
|
_this.addClass('is-invalid');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, delay);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
54
templates/Froxlor/assets/js/jquery/configfiles.js
vendored
Normal file
54
templates/Froxlor/assets/js/jquery/configfiles.js
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
export default function () {
|
||||||
|
$(function () {
|
||||||
|
/*
|
||||||
|
* config files - select all recommended
|
||||||
|
*/
|
||||||
|
$('#selectRecommendedConfig').on('click', function () {
|
||||||
|
$('input[data-recommended]').each(function () {
|
||||||
|
if ($(this).data('recommended') == 1) {
|
||||||
|
$(this).prop('checked', true);
|
||||||
|
} else {
|
||||||
|
$(this).prop('checked', false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* export/download JSON file (e.g. for usage with config-services)
|
||||||
|
*/
|
||||||
|
$('#downloadSelectionAsJson').on('click', function () {
|
||||||
|
var formData = $(this).closest('form').serialize();
|
||||||
|
window.location = "lib/ajax.php?action=getConfigJsonExport&" + formData;
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* open modal window to show selected config-commands/files
|
||||||
|
* for selected daemon
|
||||||
|
*/
|
||||||
|
$('.show-config').on('click', function () {
|
||||||
|
const distro = $(this).data('dist');
|
||||||
|
const section = $(this).data('section');
|
||||||
|
const daemon = $(this).data('daemon');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "lib/ajax.php?action=getConfigDetails",
|
||||||
|
type: "POST",
|
||||||
|
dataType: "json",
|
||||||
|
data: {distro: distro, section: section, daemon: daemon},
|
||||||
|
success: function (data) {
|
||||||
|
$('#configTplShowLabel').html(data.title);
|
||||||
|
$('#configTplShow .modal-body').html(data.content);
|
||||||
|
const myModal = new bootstrap.Modal(document.getElementById('configTplShow'));
|
||||||
|
myModal.show();
|
||||||
|
},
|
||||||
|
error: function (request, status, error) {
|
||||||
|
$('#configTplShowLabel').html('Error');
|
||||||
|
$('#configTplShow .modal-body').html('<div class="alert alert-danger" role="alert">' + request.responseJSON.message + '</div>');
|
||||||
|
const myModal = new bootstrap.Modal(document.getElementById('configTplShow'));
|
||||||
|
myModal.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user