Compare commits
264 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3ec02f258 | ||
|
|
f31ee2e360 | ||
|
|
57206b2f72 | ||
|
|
73906f252b | ||
|
|
7206f5fee2 | ||
|
|
55212607e0 | ||
|
|
e6bfe205c5 | ||
|
|
596075d141 | ||
|
|
a58a5fd972 | ||
|
|
bcbfcb34e8 | ||
|
|
56d8a565b4 | ||
|
|
a60c21218c | ||
|
|
cd2a08e731 | ||
|
|
5d2ce4ecfb | ||
|
|
869b01204a | ||
|
|
d357bded60 | ||
|
|
292741516a | ||
|
|
27db472a0c | ||
|
|
fc4041e88c | ||
|
|
75bc0142a0 | ||
|
|
b888e920f4 | ||
|
|
585b16d199 | ||
|
|
4d3cf5da9a | ||
|
|
2dae780e0b | ||
|
|
bda24d7d63 | ||
|
|
9d47d670a1 | ||
|
|
b3dc7f9187 | ||
|
|
1d246fee02 | ||
|
|
10e87a909a | ||
|
|
0a3caa9f9b | ||
|
|
820326a7e0 | ||
|
|
3a2e70f79f | ||
|
|
f8032b1952 | ||
|
|
a0794cbbf1 | ||
|
|
a3139da388 | ||
|
|
3dd6a7d2ac | ||
|
|
062e610ae7 | ||
|
|
5dc9aa34ba | ||
|
|
d4a6c2cacc | ||
|
|
1f5982e8a0 | ||
|
|
c89d320957 | ||
|
|
a602865fee | ||
|
|
597f338353 | ||
|
|
cda0b3116f | ||
|
|
73182a6909 | ||
|
|
0d86340a4c | ||
|
|
1a5680d2a8 | ||
|
|
c07ff16274 | ||
|
|
cf18140499 | ||
|
|
9f44b21a04 | ||
|
|
7934684982 | ||
|
|
fce310049a | ||
|
|
914204b483 | ||
|
|
fc3f0d8ebf | ||
|
|
27753962cf | ||
|
|
63b21f385d | ||
|
|
1b44ee2e06 | ||
|
|
7f8b36e0bd | ||
|
|
71746f8dac | ||
|
|
d6b8eb08c0 | ||
|
|
7d99244b9d | ||
|
|
0109c2d26f | ||
|
|
c1bc422677 | ||
|
|
5625503e2d | ||
|
|
61ae182ba7 | ||
|
|
b49f20af95 | ||
|
|
1f4f1d8203 | ||
|
|
ff4c54a9d5 | ||
|
|
bb83e78c64 | ||
|
|
7c3e89ccc0 | ||
|
|
76c23cf9b1 | ||
|
|
ed6154fa4b | ||
|
|
f22c1db8cb | ||
|
|
ee7b47c3c0 | ||
|
|
537b274b4c | ||
|
|
d8b86fc3c5 | ||
|
|
b675c84ae4 | ||
|
|
c0fdc62032 | ||
|
|
b14eaf454c | ||
|
|
3503d605cc | ||
|
|
2fc319b991 | ||
|
|
d86da23187 | ||
|
|
70b3e61f4c | ||
|
|
fb5958f5d4 | ||
|
|
8132976559 | ||
|
|
686ca84a30 | ||
|
|
953baec023 | ||
|
|
396274d954 | ||
|
|
4e23b9652c | ||
|
|
594e61408d | ||
|
|
ece4b34f25 | ||
|
|
9c70976018 | ||
|
|
594d7d84bb | ||
|
|
9d4bc94aef | ||
|
|
f03b49d0db | ||
|
|
bcf0818faf | ||
|
|
dd765089c9 | ||
|
|
a7ee5e0ae3 | ||
|
|
2629718b22 | ||
|
|
c4cf8ededc | ||
|
|
9b20f4ac39 | ||
|
|
616dcb1fda | ||
|
|
bc1892d4ec | ||
|
|
83047019b0 | ||
|
|
8fa286a71d | ||
|
|
f420551888 | ||
|
|
854c930696 | ||
|
|
8740947323 | ||
|
|
e684de687f | ||
|
|
284def5832 | ||
|
|
9c23013777 | ||
|
|
75af5c6a1a | ||
|
|
2a348cf34e | ||
|
|
089bec7255 | ||
|
|
c393317adb | ||
|
|
734d6888c8 | ||
|
|
ba11b0ab7d | ||
|
|
1054095b3b | ||
|
|
b15f99b1e1 | ||
|
|
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 | ||
|
|
cfae3540fc | ||
|
|
9e8f32f1e8 | ||
|
|
a7b66227e6 | ||
|
|
532982784f | ||
|
|
0754be3028 | ||
|
|
166ec0575b | ||
|
|
e8ed43056c | ||
|
|
a808a3f782 | ||
|
|
686065c294 | ||
|
|
41ac713325 | ||
|
|
d1cb32b47f | ||
|
|
13b6ab0b07 | ||
|
|
215e749ba8 | ||
|
|
0b7d2358ed | ||
|
|
f3c965fe53 | ||
|
|
5b58ab4371 | ||
|
|
3ad203535a | ||
|
|
6edc6553bd | ||
|
|
3fc18f9903 | ||
|
|
506cccd7c8 | ||
|
|
6ad1ca2ba9 | ||
|
|
6d9014c29b | ||
|
|
7e168f5a0e | ||
|
|
4fcf0606c7 | ||
|
|
9d2077ddee | ||
|
|
10555bff76 | ||
|
|
338b855947 | ||
|
|
5d04b8c829 | ||
|
|
37aa7af4da | ||
|
|
4b75369597 | ||
|
|
9d0e463906 | ||
|
|
a0406932c3 | ||
|
|
a7198f58ce | ||
|
|
47be4b2847 | ||
|
|
b0fae4bd14 | ||
|
|
4711a41436 | ||
|
|
faa71ceaef | ||
|
|
2d30394150 | ||
|
|
99c1182af8 | ||
|
|
d9abe58dd2 | ||
|
|
23034b8ad2 | ||
|
|
1cae5638d3 | ||
|
|
ce9a5f97a3 | ||
|
|
c38b90deef | ||
|
|
13daa7d6fa | ||
|
|
b0e43d332d | ||
|
|
75c8754fb4 |
40
.drone.yml
40
.drone.yml
@@ -1,40 +0,0 @@
|
|||||||
kind: pipeline
|
|
||||||
name: deploy-froxlor
|
|
||||||
type: docker
|
|
||||||
|
|
||||||
platform:
|
|
||||||
os: linux
|
|
||||||
arch: arm64
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
branch:
|
|
||||||
- 2.1.x
|
|
||||||
event:
|
|
||||||
include:
|
|
||||||
- push
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: deploy
|
|
||||||
image: cr.wks/drone/drone-rsync:latest
|
|
||||||
settings:
|
|
||||||
hosts: ["rechner02.maketank.net"]
|
|
||||||
source: ./
|
|
||||||
target: ~/froxlor-test
|
|
||||||
user: www-data
|
|
||||||
exclude: ['vendor', '.git*', '*drone.yml', '.settings', '.buildpath', '.editorconfig', '.project', '.travis.yml']
|
|
||||||
args: '-v --delete'
|
|
||||||
log_level: quiet
|
|
||||||
key:
|
|
||||||
from_secret: ssh-www-data-maketank-rsa
|
|
||||||
command_timeout: 10m
|
|
||||||
- name: compose-install
|
|
||||||
image: appleboy/drone-ssh
|
|
||||||
settings:
|
|
||||||
host:
|
|
||||||
- rechner02.maketank.net
|
|
||||||
username: www-data
|
|
||||||
key:
|
|
||||||
from_secret: ssh-www-data-maketank-rsa
|
|
||||||
script:
|
|
||||||
- cd ~/froxlor-test && composer install --no-dev
|
|
||||||
|
|
||||||
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}}
|
||||||
|
|||||||
114
.github/workflows/build-mariadb.yml
vendored
114
.github/workflows/build-mariadb.yml
vendored
@@ -1,5 +1,5 @@
|
|||||||
name: Froxlor-CI-MariaDB
|
name: Froxlor-CI-MariaDB
|
||||||
on: ['push', 'pull_request', 'create']
|
on: [ 'push', 'pull_request', 'create' ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
froxlor:
|
froxlor:
|
||||||
@@ -8,18 +8,18 @@ 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@v4
|
||||||
|
|
||||||
- name: Setup PHP, with composer and extensions
|
- name: Setup PHP, with composer and extensions
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@v2
|
||||||
with:
|
with:
|
||||||
php-version: ${{ matrix.php-versions }}
|
php-version: ${{ matrix.php-versions }}
|
||||||
tools: composer:v2
|
tools: composer:v2
|
||||||
extensions: mbstring, xml, ctype, pdo_mysql, mysql, curl, json, zip, session, filter, posix, openssl, fileinfo, bcmath, gmp
|
extensions: mbstring, xml, ctype, pdo_mysql, mysql, curl, json, zip, session, filter, posix, openssl, fileinfo, bcmath, gmp, gnupg
|
||||||
|
|
||||||
- name: Install tools
|
- name: Install tools
|
||||||
run: sudo apt-get install -y ant
|
run: sudo apt-get install -y ant
|
||||||
@@ -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@v4
|
||||||
# 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@v4
|
||||||
|
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@main
|
||||||
|
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 }}"
|
||||||
|
|||||||
17
.github/workflows/build-mysql.yml
vendored
17
.github/workflows/build-mysql.yml
vendored
@@ -8,18 +8,18 @@ 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
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup PHP, with composer and extensions
|
- name: Setup PHP, with composer and extensions
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@v2
|
||||||
with:
|
with:
|
||||||
php-version: ${{ matrix.php-versions }}
|
php-version: ${{ matrix.php-versions }}
|
||||||
tools: composer:v2
|
tools: composer:v2
|
||||||
extensions: mbstring, xml, ctype, pdo_mysql, mysql, curl, json, zip, session, filter, posix, openssl, fileinfo, bcmath, gmp
|
extensions: mbstring, xml, ctype, pdo_mysql, mysql, curl, json, zip, session, filter, posix, openssl, fileinfo, bcmath, gmp, gnupg
|
||||||
|
|
||||||
- name: Install tools
|
- name: Install tools
|
||||||
run: sudo apt-get install -y ant
|
run: sudo apt-get install -y ant
|
||||||
@@ -39,16 +39,7 @@ jobs:
|
|||||||
- name: Wait for database
|
- name: Wait for database
|
||||||
run: sleep 15
|
run: sleep 15
|
||||||
|
|
||||||
- name: Setup database (8.0)
|
- name: Setup database
|
||||||
if: matrix.mysql-version == '8.0'
|
|
||||||
run: |
|
|
||||||
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "CREATE USER 'froxlor010'@'%' IDENTIFIED WITH mysql_native_password BY 'fr0xl0r.TravisCI';"
|
|
||||||
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "GRANT ALL ON froxlor010.* TO 'froxlor010'@'%';"
|
|
||||||
php -r "echo include('install/froxlor.sql.php');" > /tmp/froxlor.sql
|
|
||||||
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI froxlor010 < /tmp/froxlor.sql
|
|
||||||
|
|
||||||
- name: Setup database (5.7)
|
|
||||||
if: matrix.mysql-version == '5.7'
|
|
||||||
run: |
|
run: |
|
||||||
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "CREATE USER 'froxlor010'@'%' IDENTIFIED BY 'fr0xl0r.TravisCI';"
|
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "CREATE USER 'froxlor010'@'%' IDENTIFIED BY 'fr0xl0r.TravisCI';"
|
||||||
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "GRANT ALL ON froxlor010.* TO 'froxlor010'@'%';"
|
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "GRANT ALL ON froxlor010.* TO 'froxlor010'@'%';"
|
||||||
|
|||||||
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/
|
||||||
|
|||||||
9
2fa.php
9
2fa.php
@@ -33,6 +33,7 @@ use Froxlor\FroxlorLogger;
|
|||||||
use Froxlor\FroxlorTwoFactorAuth;
|
use Froxlor\FroxlorTwoFactorAuth;
|
||||||
use Froxlor\Settings;
|
use Froxlor\Settings;
|
||||||
use Froxlor\UI\Panel\UI;
|
use Froxlor\UI\Panel\UI;
|
||||||
|
use Froxlor\UI\Request;
|
||||||
use Froxlor\UI\Response;
|
use Froxlor\UI\Response;
|
||||||
use Froxlor\PhpHelper;
|
use Froxlor\PhpHelper;
|
||||||
use Froxlor\User;
|
use Froxlor\User;
|
||||||
@@ -63,7 +64,7 @@ if ($action == 'delete') {
|
|||||||
]);
|
]);
|
||||||
Response::standardSuccess('2fa.2fa_removed');
|
Response::standardSuccess('2fa.2fa_removed');
|
||||||
} elseif ($action == 'preadd') {
|
} elseif ($action == 'preadd') {
|
||||||
$type = isset($_POST['type_2fa']) ? $_POST['type_2fa'] : '0';
|
$type = Request::post('type_2fa', '0');
|
||||||
|
|
||||||
$data = "";
|
$data = "";
|
||||||
if ($type > 0) {
|
if ($type > 0) {
|
||||||
@@ -107,9 +108,9 @@ if ($action == 'delete') {
|
|||||||
Response::dynamicError('Select one of the possible values for 2FA');
|
Response::dynamicError('Select one of the possible values for 2FA');
|
||||||
}
|
}
|
||||||
} elseif ($action == 'add') {
|
} elseif ($action == 'add') {
|
||||||
$type = isset($_POST['type_2fa']) ? $_POST['type_2fa'] : '0';
|
$type = Request::post('type_2fa', '0');
|
||||||
$data = isset($_POST['data_2fa']) ? $_POST['data_2fa'] : '';
|
$data = Request::post('data_2fa', '');
|
||||||
$code = isset($_POST['codevalidation']) ? $_POST['codevalidation'] : '';
|
$code = Request::post('codevalidation', '');
|
||||||
|
|
||||||
// validate
|
// validate
|
||||||
$result = $tfa->verifyCode($data, $code, 3);
|
$result = $tfa->verifyCode($data, $code, 3);
|
||||||
|
|||||||
18
README.md
18
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
|
||||||
|
|
||||||
@@ -64,17 +58,17 @@ https://files.froxlor.org/releases/froxlor-latest.tar.gz [MD5](https://files.fro
|
|||||||
#### Debian
|
#### Debian
|
||||||
|
|
||||||
```
|
```
|
||||||
apt-get -y install apt-transport-https lsb-release ca-certificates curl
|
apt -y install apt-transport-https lsb-release ca-certificates curl gnupg
|
||||||
curl -sSLo /usr/share/keyrings/deb.froxlor.org-froxlor.gpg https://deb.froxlor.org/froxlor.gpg
|
curl -sSLo /usr/share/keyrings/deb.froxlor.org-froxlor.gpg https://deb.froxlor.org/froxlor.gpg
|
||||||
echo sh -c '"deb [signed-by=/usr/share/keyrings/deb.froxlor.org-froxlor.gpg] https://deb.froxlor.org/debian $(lsb_release -sc) main" > /etc/apt/sources.list.d/froxlor.list'
|
sh -c 'echo "deb [signed-by=/usr/share/keyrings/deb.froxlor.org-froxlor.gpg] https://deb.froxlor.org/debian $(lsb_release -sc) main" > /etc/apt/sources.list.d/froxlor.list'
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Ubuntu
|
#### Ubuntu
|
||||||
|
|
||||||
```
|
```
|
||||||
apt-get -y install apt-transport-https lsb-release ca-certificates curl
|
apt -y install apt-transport-https lsb-release ca-certificates curl gnupg
|
||||||
curl -sSLo /usr/share/keyrings/deb.froxlor.org-froxlor.gpg https://deb.froxlor.org/froxlor.gpg
|
curl -sSLo /usr/share/keyrings/deb.froxlor.org-froxlor.gpg https://deb.froxlor.org/froxlor.gpg
|
||||||
echo sh -c '"deb [signed-by=/usr/share/keyrings/deb.froxlor.org-froxlor.gpg] https://deb.froxlor.org/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/froxlor.list'
|
sh -c 'echo "deb [signed-by=/usr/share/keyrings/deb.froxlor.org-froxlor.gpg] https://deb.froxlor.org/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/froxlor.list'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
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).
|
||||||
|
|||||||
@@ -337,7 +337,15 @@ return [
|
|||||||
'image_name' => 'logo_login',
|
'image_name' => 'logo_login',
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'save_method' => 'storeSettingImage'
|
'save_method' => 'storeSettingImage'
|
||||||
]
|
],
|
||||||
|
'panel_menu_collapsed' => [
|
||||||
|
'label' => lng('serversettings.panel_menu_collapsed'),
|
||||||
|
'settinggroup' => 'panel',
|
||||||
|
'varname' => 'menu_collapsed',
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'default' => true,
|
||||||
|
'save_method' => 'storeSettingField',
|
||||||
|
],
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ return [
|
|||||||
'varname' => 'sessiontimeout',
|
'varname' => 'sessiontimeout',
|
||||||
'type' => 'number',
|
'type' => 'number',
|
||||||
'min' => 60,
|
'min' => 60,
|
||||||
|
'max' => 31536000,
|
||||||
'default' => 600,
|
'default' => 600,
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -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',
|
||||||
@@ -189,18 +180,6 @@ return [
|
|||||||
'default' => true,
|
'default' => true,
|
||||||
'save_method' => 'storeSettingField'
|
'save_method' => 'storeSettingField'
|
||||||
],
|
],
|
||||||
'system_httpuser' => [
|
|
||||||
'settinggroup' => 'system',
|
|
||||||
'varname' => 'httpuser',
|
|
||||||
'type' => 'hidden',
|
|
||||||
'default' => 'www-data'
|
|
||||||
],
|
|
||||||
'system_httpgroup' => [
|
|
||||||
'settinggroup' => 'system',
|
|
||||||
'varname' => 'httpgroup',
|
|
||||||
'type' => 'hidden',
|
|
||||||
'default' => 'www-data'
|
|
||||||
],
|
|
||||||
'system_report_enable' => [
|
'system_report_enable' => [
|
||||||
'label' => lng('serversettings.report.report'),
|
'label' => lng('serversettings.report.report'),
|
||||||
'settinggroup' => 'system',
|
'settinggroup' => 'system',
|
||||||
|
|||||||
@@ -176,6 +176,7 @@ return [
|
|||||||
'varname' => 'mod_fcgid_httpuser',
|
'varname' => 'mod_fcgid_httpuser',
|
||||||
'type' => 'text',
|
'type' => 'text',
|
||||||
'default' => 'froxlorlocal',
|
'default' => 'froxlorlocal',
|
||||||
|
'string_emptyallowed' => false,
|
||||||
'save_method' => 'storeSettingWebserverFcgidFpmUser',
|
'save_method' => 'storeSettingWebserverFcgidFpmUser',
|
||||||
'websrv_avail' => [
|
'websrv_avail' => [
|
||||||
'apache2'
|
'apache2'
|
||||||
@@ -193,6 +194,7 @@ return [
|
|||||||
'type' => 'text',
|
'type' => 'text',
|
||||||
'default' => 'froxlorlocal',
|
'default' => 'froxlorlocal',
|
||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
|
'string_emptyallowed' => false,
|
||||||
'websrv_avail' => [
|
'websrv_avail' => [
|
||||||
'apache2'
|
'apache2'
|
||||||
],
|
],
|
||||||
@@ -243,6 +245,7 @@ return [
|
|||||||
'varname' => 'vhost_httpuser',
|
'varname' => 'vhost_httpuser',
|
||||||
'type' => 'text',
|
'type' => 'text',
|
||||||
'default' => 'froxlorlocal',
|
'default' => 'froxlorlocal',
|
||||||
|
'string_emptyallowed' => false,
|
||||||
'save_method' => 'storeSettingWebserverFcgidFpmUser',
|
'save_method' => 'storeSettingWebserverFcgidFpmUser',
|
||||||
'visible' => Settings::Get('phpfpm.enabled') && call_user_func([
|
'visible' => Settings::Get('phpfpm.enabled') && call_user_func([
|
||||||
'\Froxlor\Settings\FroxlorVhostSettings',
|
'\Froxlor\Settings\FroxlorVhostSettings',
|
||||||
@@ -256,6 +259,7 @@ return [
|
|||||||
'varname' => 'vhost_httpgroup',
|
'varname' => 'vhost_httpgroup',
|
||||||
'type' => 'text',
|
'type' => 'text',
|
||||||
'default' => 'froxlorlocal',
|
'default' => 'froxlorlocal',
|
||||||
|
'string_emptyallowed' => false,
|
||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
'visible' => Settings::Get('phpfpm.enabled') && call_user_func([
|
'visible' => Settings::Get('phpfpm.enabled') && call_user_func([
|
||||||
'\Froxlor\Settings\FroxlorVhostSettings',
|
'\Froxlor\Settings\FroxlorVhostSettings',
|
||||||
|
|||||||
@@ -248,11 +248,40 @@ 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',
|
||||||
]
|
'advanced_mode' => true
|
||||||
|
],
|
||||||
|
'system_le_renew_services' => [
|
||||||
|
'label' => lng('serversettings.le_renew_services'),
|
||||||
|
'settinggroup' => 'system',
|
||||||
|
'varname' => 'le_renew_services',
|
||||||
|
'type' => 'select',
|
||||||
|
'default' => '',
|
||||||
|
'select_mode' => 'multiple',
|
||||||
|
'option_emptyallowed' => true,
|
||||||
|
'select_var' => [
|
||||||
|
'' => lng('panel.none_value'),
|
||||||
|
'postfix' => 'postfix (smtp)',
|
||||||
|
'dovecot' => 'dovecot (imap/pop3)',
|
||||||
|
'proftpd' => 'proftpd (ftp)',
|
||||||
|
],
|
||||||
|
'save_method' => 'storeSettingField',
|
||||||
|
'advanced_mode' => true
|
||||||
|
],
|
||||||
|
'system_le_renew_hook' => [
|
||||||
|
'label' => lng('serversettings.le_renew_hook'),
|
||||||
|
'settinggroup' => 'system',
|
||||||
|
'varname' => 'le_renew_hook',
|
||||||
|
'type' => 'text',
|
||||||
|
'string_regexp' => '/^[a-z0-9\/\._\- ]+$/i',
|
||||||
|
'default' => 'systemctl restart postfix dovecot proftpd',
|
||||||
|
'save_method' => 'storeSettingField',
|
||||||
|
'advanced_mode' => true,
|
||||||
|
'required_otp' => true
|
||||||
|
],
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|||||||
111
actions/admin/settings/180.antispam.php
Normal file
111
actions/admin/settings/180.antispam.php
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file is part of the Froxlor project.
|
||||||
|
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you can also view it online at
|
||||||
|
* https://files.froxlor.org/misc/COPYING.txt
|
||||||
|
*
|
||||||
|
* @copyright the authors
|
||||||
|
* @author Froxlor team <team@froxlor.org>
|
||||||
|
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||||
|
*/
|
||||||
|
|
||||||
|
return [
|
||||||
|
'groups' => [
|
||||||
|
'antispam' => [
|
||||||
|
'title' => lng('admin.antispam_settings'),
|
||||||
|
'icon' => 'fa-solid fa-clipboard-check',
|
||||||
|
'fields' => [
|
||||||
|
'antispam_activated' => [
|
||||||
|
'label' => lng('antispam.activated'),
|
||||||
|
'settinggroup' => 'antispam',
|
||||||
|
'varname' => 'activated',
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'default' => true,
|
||||||
|
'overview_option' => true,
|
||||||
|
'save_method' => 'storeSettingFieldInsertAntispamTask',
|
||||||
|
],
|
||||||
|
'antispam_config_file' => [
|
||||||
|
'label' => lng('antispam.config_file'),
|
||||||
|
'settinggroup' => 'antispam',
|
||||||
|
'varname' => 'config_file',
|
||||||
|
'type' => 'text',
|
||||||
|
'string_type' => 'file',
|
||||||
|
'default' => '/etc/rspamd/local.d/froxlor_settings.conf',
|
||||||
|
'save_method' => 'storeSettingFieldInsertAntispamTask',
|
||||||
|
'requires_reconf' => ['antispam']
|
||||||
|
],
|
||||||
|
'antispam_reload_command' => [
|
||||||
|
'label' => lng('antispam.reload_command'),
|
||||||
|
'settinggroup' => 'antispam',
|
||||||
|
'varname' => 'reload_command',
|
||||||
|
'type' => 'text',
|
||||||
|
'string_regexp' => '/^[a-z0-9\/\._\- ]+$/i',
|
||||||
|
'default' => 'service rspamd restart',
|
||||||
|
'save_method' => 'storeSettingField',
|
||||||
|
'required_otp' => true
|
||||||
|
],
|
||||||
|
'antispam_dkim_keylength' => [
|
||||||
|
'label' => lng('antispam.dkim_keylength'),
|
||||||
|
'settinggroup' => 'antispam',
|
||||||
|
'varname' => 'dkim_keylength',
|
||||||
|
'type' => 'select',
|
||||||
|
'default' => '1024',
|
||||||
|
'select_var' => [
|
||||||
|
'1024' => '1024 Bit',
|
||||||
|
'2048' => '2048 Bit'
|
||||||
|
],
|
||||||
|
'save_method' => 'storeSettingFieldInsertBindTask',
|
||||||
|
'advanced_mode' => true,
|
||||||
|
],
|
||||||
|
'spf_use_spf' => [
|
||||||
|
'label' => lng('spf.use_spf'),
|
||||||
|
'settinggroup' => 'spf',
|
||||||
|
'varname' => 'use_spf',
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'default' => false,
|
||||||
|
'save_method' => 'storeSettingField',
|
||||||
|
],
|
||||||
|
'spf_spf_entry' => [
|
||||||
|
'label' => lng('spf.spf_entry'),
|
||||||
|
'settinggroup' => 'spf',
|
||||||
|
'varname' => 'spf_entry',
|
||||||
|
'type' => 'text',
|
||||||
|
'string_regexp' => '/^v=spf[a-z0-9:~?\s.-]+$/i',
|
||||||
|
'default' => 'v=spf1 a mx -all',
|
||||||
|
'save_method' => 'storeSettingField'
|
||||||
|
],
|
||||||
|
'dmarc_use_dmarc' => [
|
||||||
|
'label' => lng('dmarc.use_dmarc'),
|
||||||
|
'settinggroup' => 'dmarc',
|
||||||
|
'varname' => 'use_dmarc',
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'default' => false,
|
||||||
|
'save_method' => 'storeSettingField',
|
||||||
|
],
|
||||||
|
'dmarc_dmarc_entry' => [
|
||||||
|
'label' => lng('dmarc.dmarc_entry'),
|
||||||
|
'settinggroup' => 'dmarc',
|
||||||
|
'varname' => 'dmarc_entry',
|
||||||
|
'type' => 'text',
|
||||||
|
'string_regexp' => '/^v=dmarc1(.+)$/i',
|
||||||
|
'default' => 'v=DMARC1; p=none;',
|
||||||
|
'save_method' => 'storeSettingField'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file is part of the Froxlor project.
|
|
||||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, you can also view it online at
|
|
||||||
* https://files.froxlor.org/misc/COPYING.txt
|
|
||||||
*
|
|
||||||
* @copyright the authors
|
|
||||||
* @author Froxlor team <team@froxlor.org>
|
|
||||||
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Froxlor\Settings;
|
|
||||||
|
|
||||||
return [
|
|
||||||
'groups' => [
|
|
||||||
'dkim' => [
|
|
||||||
'title' => lng('admin.dkimsettings'),
|
|
||||||
'icon' => 'fa-solid fa-fingerprint',
|
|
||||||
'fields' => [
|
|
||||||
'dkim_use_dkim' => [
|
|
||||||
'label' => lng('dkim.use_dkim'),
|
|
||||||
'settinggroup' => 'dkim',
|
|
||||||
'varname' => 'use_dkim',
|
|
||||||
'type' => 'checkbox',
|
|
||||||
'default' => false,
|
|
||||||
'save_method' => 'storeSettingFieldInsertBindTask',
|
|
||||||
'overview_option' => true
|
|
||||||
],
|
|
||||||
'dkim_dkim_prefix' => [
|
|
||||||
'label' => lng('dkim.dkim_prefix'),
|
|
||||||
'settinggroup' => 'dkim',
|
|
||||||
'varname' => 'dkim_prefix',
|
|
||||||
'type' => 'text',
|
|
||||||
'string_type' => 'dir',
|
|
||||||
'default' => '/etc/postfix/dkim/',
|
|
||||||
'save_method' => 'storeSettingField'
|
|
||||||
],
|
|
||||||
'dkim_privkeysuffix' => [
|
|
||||||
'label' => lng('dkim.privkeysuffix'),
|
|
||||||
'settinggroup' => 'dkim',
|
|
||||||
'varname' => 'privkeysuffix',
|
|
||||||
'type' => 'text',
|
|
||||||
'string_regexp' => '/^[a-z0-9\._]+$/i',
|
|
||||||
'default' => '.priv',
|
|
||||||
'save_method' => 'storeSettingField',
|
|
||||||
'advanced_mode' => true
|
|
||||||
],
|
|
||||||
'dkim_dkim_domains' => [
|
|
||||||
'label' => lng('dkim.dkim_domains'),
|
|
||||||
'settinggroup' => 'dkim',
|
|
||||||
'varname' => 'dkim_domains',
|
|
||||||
'type' => 'text',
|
|
||||||
'string_regexp' => '/^[a-z0-9\._]+$/i',
|
|
||||||
'default' => 'domains',
|
|
||||||
'save_method' => 'storeSettingField'
|
|
||||||
],
|
|
||||||
'dkim_dkim_dkimkeys' => [
|
|
||||||
'label' => lng('dkim.dkim_dkimkeys'),
|
|
||||||
'settinggroup' => 'dkim',
|
|
||||||
'varname' => 'dkim_dkimkeys',
|
|
||||||
'type' => 'text',
|
|
||||||
'string_regexp' => '/^[a-z0-9\._]+$/i',
|
|
||||||
'default' => 'dkim-keys.conf',
|
|
||||||
'save_method' => 'storeSettingField'
|
|
||||||
],
|
|
||||||
'dkim_dkim_algorithm' => [
|
|
||||||
'label' => lng('dkim.dkim_algorithm'),
|
|
||||||
'settinggroup' => 'dkim',
|
|
||||||
'varname' => 'dkim_algorithm',
|
|
||||||
'type' => 'select',
|
|
||||||
'default' => 'all',
|
|
||||||
'select_mode' => 'multiple',
|
|
||||||
'select_var' => [
|
|
||||||
'all' => 'All',
|
|
||||||
'sha1' => 'SHA1',
|
|
||||||
'sha256' => 'SHA256'
|
|
||||||
],
|
|
||||||
'save_method' => 'storeSettingFieldInsertBindTask',
|
|
||||||
'advanced_mode' => true
|
|
||||||
],
|
|
||||||
'dkim_dkim_servicetype' => [
|
|
||||||
'label' => lng('dkim.dkim_servicetype'),
|
|
||||||
'settinggroup' => 'dkim',
|
|
||||||
'varname' => 'dkim_servicetype',
|
|
||||||
'type' => 'select',
|
|
||||||
'default' => '0',
|
|
||||||
'select_var' => [
|
|
||||||
'0' => 'All',
|
|
||||||
'1' => 'E-Mail'
|
|
||||||
],
|
|
||||||
'save_method' => 'storeSettingFieldInsertBindTask',
|
|
||||||
'advanced_mode' => true
|
|
||||||
],
|
|
||||||
'dkim_dkim_keylength' => [
|
|
||||||
'label' => [
|
|
||||||
'title' => lng('dkim.dkim_keylength.title'),
|
|
||||||
'description' => lng('dkim.dkim_keylength.description', [Settings::Get('dkim.dkim_prefix')])
|
|
||||||
],
|
|
||||||
'settinggroup' => 'dkim',
|
|
||||||
'varname' => 'dkim_keylength',
|
|
||||||
'type' => 'select',
|
|
||||||
'default' => '1024',
|
|
||||||
'select_var' => [
|
|
||||||
'1024' => '1024 Bit',
|
|
||||||
'2048' => '2048 Bit'
|
|
||||||
],
|
|
||||||
'save_method' => 'storeSettingFieldInsertBindTask'
|
|
||||||
],
|
|
||||||
'dkim_dkim_notes' => [
|
|
||||||
'label' => lng('dkim.dkim_notes'),
|
|
||||||
'settinggroup' => 'dkim',
|
|
||||||
'varname' => 'dkim_notes',
|
|
||||||
'type' => 'text',
|
|
||||||
'string_regexp' => '/^[a-z0-9\._]+$/i',
|
|
||||||
'default' => '',
|
|
||||||
'save_method' => 'storeSettingFieldInsertBindTask',
|
|
||||||
'advanced_mode' => true
|
|
||||||
],
|
|
||||||
'dkim_dkimrestart_command' => [
|
|
||||||
'label' => lng('dkim.dkimrestart_command'),
|
|
||||||
'settinggroup' => 'dkim',
|
|
||||||
'varname' => 'dkimrestart_command',
|
|
||||||
'type' => 'text',
|
|
||||||
'string_regexp' => '/^[a-z0-9\/\._\- ]+$/i',
|
|
||||||
'default' => '/etc/init.d/dkim-filter restart',
|
|
||||||
'save_method' => 'storeSettingField',
|
|
||||||
'required_otp' => true
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file is part of the Froxlor project.
|
|
||||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, you can also view it online at
|
|
||||||
* https://files.froxlor.org/misc/COPYING.txt
|
|
||||||
*
|
|
||||||
* @copyright the authors
|
|
||||||
* @author Froxlor team <team@froxlor.org>
|
|
||||||
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
|
||||||
*/
|
|
||||||
|
|
||||||
return [
|
|
||||||
'groups' => [
|
|
||||||
'backup' => [
|
|
||||||
'title' => lng('backup'),
|
|
||||||
'icon' => 'fa-solid fa-sliders',
|
|
||||||
'advanced_mode' => true,
|
|
||||||
'fields' => [
|
|
||||||
'backup_enabled' => [
|
|
||||||
'label' => lng('serversettings.backup_enabled'),
|
|
||||||
'settinggroup' => 'backup',
|
|
||||||
'varname' => 'enabled',
|
|
||||||
'type' => 'checkbox',
|
|
||||||
'default' => false,
|
|
||||||
'save_method' => 'storeSettingField',
|
|
||||||
'overview_option' => true,
|
|
||||||
'cronmodule' => 'froxlor/backup'
|
|
||||||
],
|
|
||||||
'backup_default_storage' => [
|
|
||||||
'label' => lng('serversettings.backup_default_storage'),
|
|
||||||
'settinggroup' => 'backup',
|
|
||||||
'varname' => 'default_storage',
|
|
||||||
'type' => 'select',
|
|
||||||
'default' => '1',
|
|
||||||
'option_options_method' => [
|
|
||||||
'\\Froxlor\\Backup\\Backup',
|
|
||||||
'getBackupStorages'
|
|
||||||
],
|
|
||||||
'save_method' => 'storeSettingField'
|
|
||||||
],
|
|
||||||
'backup_default_retention' => [
|
|
||||||
'label' => lng('serversettings.backup_default_retention'),
|
|
||||||
'settinggroup' => 'backup',
|
|
||||||
'varname' => 'default_retention',
|
|
||||||
'type' => 'number',
|
|
||||||
'default' => 3,
|
|
||||||
'min' => 0,
|
|
||||||
'save_method' => 'storeSettingField',
|
|
||||||
],
|
|
||||||
'backup_default_customer_access' => [
|
|
||||||
'label' => lng('serversettings.backup_default_customer_access'),
|
|
||||||
'settinggroup' => 'backup',
|
|
||||||
'varname' => 'default_customer_access',
|
|
||||||
'type' => 'checkbox',
|
|
||||||
'default' => true,
|
|
||||||
'save_method' => 'storeSettingField',
|
|
||||||
],
|
|
||||||
'backup_default_pgp_public_key' => [
|
|
||||||
'label' => lng('serversettings.backup_default_pgp_public_key'),
|
|
||||||
'settinggroup' => 'backup',
|
|
||||||
'varname' => 'default_pgp_public_key',
|
|
||||||
'type' => 'textarea',
|
|
||||||
'default' => '',
|
|
||||||
'save_method' => 'storeSettingField',
|
|
||||||
'plausibility_check_method' => [
|
|
||||||
'\\Froxlor\\Validate\\Check',
|
|
||||||
'checkPgpPublicKeySetting'
|
|
||||||
],
|
|
||||||
],
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
|
||||||
@@ -106,7 +106,7 @@ if (($page == 'admins' || $page == 'overview') && $userinfo['change_serversettin
|
|||||||
Response::standardError('youcantdeleteyourself');
|
Response::standardError('youcantdeleteyourself');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
Admins::getLocal($userinfo, [
|
Admins::getLocal($userinfo, [
|
||||||
'id' => $id
|
'id' => $id
|
||||||
])->delete();
|
])->delete();
|
||||||
@@ -122,9 +122,9 @@ if (($page == 'admins' || $page == 'overview') && $userinfo['change_serversettin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($action == 'add') {
|
} elseif ($action == 'add') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
Admins::getLocal($userinfo, $_POST)->add();
|
Admins::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -159,9 +159,9 @@ if (($page == 'admins' || $page == 'overview') && $userinfo['change_serversettin
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if ($result['loginname'] != '') {
|
if ($result['loginname'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
Admins::getLocal($userinfo, $_POST)->update();
|
Admins::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
use Froxlor\FroxlorLogger;
|
use Froxlor\FroxlorLogger;
|
||||||
use Froxlor\UI\Panel\UI;
|
use Froxlor\UI\Panel\UI;
|
||||||
|
use Froxlor\UI\Request;
|
||||||
use Froxlor\UI\Response;
|
use Froxlor\UI\Response;
|
||||||
use Froxlor\UI\HTML;
|
use Froxlor\UI\HTML;
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ require __DIR__ . '/lib/init.php';
|
|||||||
$horizontal_bar_size = 950; // 1280px window width
|
$horizontal_bar_size = 950; // 1280px window width
|
||||||
|
|
||||||
if ($action == 'delete' && function_exists('apcu_clear_cache') && $userinfo['change_serversettings'] == '1') {
|
if ($action == 'delete' && function_exists('apcu_clear_cache') && $userinfo['change_serversettings'] == '1') {
|
||||||
if ($_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
apcu_clear_cache();
|
apcu_clear_cache();
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "cleared APCu cache");
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "cleared APCu cache");
|
||||||
header('Location: ' . $linker->getLink([
|
header('Location: ' . $linker->getLink([
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ use Froxlor\FileDir;
|
|||||||
use Froxlor\Install\AutoUpdate;
|
use Froxlor\Install\AutoUpdate;
|
||||||
use Froxlor\Settings;
|
use Froxlor\Settings;
|
||||||
use Froxlor\UI\Panel\UI;
|
use Froxlor\UI\Panel\UI;
|
||||||
|
use Froxlor\UI\Request;
|
||||||
use Froxlor\UI\Response;
|
use Froxlor\UI\Response;
|
||||||
|
|
||||||
if ($page != 'error') {
|
if ($page != 'error') {
|
||||||
@@ -110,7 +111,7 @@ if ($page == 'overview') {
|
|||||||
} // download the new archive
|
} // download the new archive
|
||||||
elseif ($page == 'getdownload') {
|
elseif ($page == 'getdownload') {
|
||||||
// retrieve the new version from the form
|
// retrieve the new version from the form
|
||||||
$newversion = isset($_POST['newversion']) ? $_POST['newversion'] : null;
|
$newversion = Request::post('newversion');
|
||||||
|
|
||||||
$result = 6;
|
$result = 6;
|
||||||
// valid?
|
// valid?
|
||||||
@@ -130,8 +131,8 @@ elseif ($page == 'getdownload') {
|
|||||||
]);
|
]);
|
||||||
} // extract and install new version
|
} // extract and install new version
|
||||||
elseif ($page == 'extract') {
|
elseif ($page == 'extract') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
$toExtract = isset($_POST['archive']) ? $_POST['archive'] : null;
|
$toExtract = Request::post('archive');
|
||||||
$localArchive = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/updates/' . $toExtract);
|
$localArchive = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/updates/' . $toExtract);
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Extracting " . $localArchive . " to " . Froxlor::getInstallDir());
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Extracting " . $localArchive . " to " . Froxlor::getInstallDir());
|
||||||
$result = AutoUpdate::extractZip($localArchive);
|
$result = AutoUpdate::extractZip($localArchive);
|
||||||
@@ -145,7 +146,7 @@ elseif ($page == 'extract') {
|
|||||||
// redirect to update-page
|
// redirect to update-page
|
||||||
Response::redirectTo('admin_updates.php');
|
Response::redirectTo('admin_updates.php');
|
||||||
} else {
|
} else {
|
||||||
$toExtract = isset($_GET['archive']) ? $_GET['archive'] : null;
|
$toExtract = Request::get('archive');
|
||||||
$localArchive = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/updates/' . $toExtract);
|
$localArchive = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/updates/' . $toExtract);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +193,7 @@ elseif ($page == 'extract') {
|
|||||||
} // display error
|
} // display error
|
||||||
elseif ($page == 'error') {
|
elseif ($page == 'error') {
|
||||||
// retrieve error-number via url-parameter
|
// retrieve error-number via url-parameter
|
||||||
$errno = isset($_GET['errno']) ? (int)$_GET['errno'] : 0;
|
$errno = Request::get('errno', 0);
|
||||||
|
|
||||||
// 2 = no Zlib
|
// 2 = no Zlib
|
||||||
// 3 = custom version detected
|
// 3 = custom version detected
|
||||||
|
|||||||
@@ -1,183 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file is part of the Froxlor project.
|
|
||||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, you can also view it online at
|
|
||||||
* https://files.froxlor.org/misc/COPYING.txt
|
|
||||||
*
|
|
||||||
* @copyright the authors
|
|
||||||
* @author Froxlor team <team@froxlor.org>
|
|
||||||
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
|
||||||
*/
|
|
||||||
|
|
||||||
const AREA = 'admin';
|
|
||||||
require __DIR__ . '/lib/init.php';
|
|
||||||
|
|
||||||
use Froxlor\Api\Commands\Backups;
|
|
||||||
use Froxlor\Api\Commands\BackupStorages;
|
|
||||||
use Froxlor\FroxlorLogger;
|
|
||||||
use Froxlor\UI\Collection;
|
|
||||||
use Froxlor\UI\HTML;
|
|
||||||
use Froxlor\UI\Listing;
|
|
||||||
use Froxlor\UI\Panel\UI;
|
|
||||||
use Froxlor\UI\Request;
|
|
||||||
use Froxlor\UI\Response;
|
|
||||||
|
|
||||||
$id = (int)Request::any('id');
|
|
||||||
|
|
||||||
if (($page == 'backups' || $page == 'overview')) {
|
|
||||||
if ($action == '') {
|
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "viewed admin_backups");
|
|
||||||
|
|
||||||
try {
|
|
||||||
$admin_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.backups.php';
|
|
||||||
$collection = (new Collection(Backups::class, $userinfo))
|
|
||||||
->withPagination($admin_list_data['backups_list']['columns'], $admin_list_data['backups_list']['default_sorting']);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
Response::dynamicError($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
UI::view('user/table.html.twig', [
|
|
||||||
'listing' => Listing::format($collection, $admin_list_data, 'backups_list'),
|
|
||||||
'actions_links' => [
|
|
||||||
[
|
|
||||||
'href' => $linker->getLink(['section' => 'backups', 'page' => $page, 'action' => 'restore']),
|
|
||||||
'label' => lng('admin.backups_restore'),
|
|
||||||
'icon' => 'fa-solid fa-file-import',
|
|
||||||
'class' => 'btn-outline-secondary'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'href' => $linker->getLink(['section' => 'backups', 'page' => 'storages']),
|
|
||||||
'label' => lng('admin.backup_storages'),
|
|
||||||
'icon' => 'fa-solid fa-hard-drive',
|
|
||||||
'class' => 'btn-outline-secondary',
|
|
||||||
'visible' => $userinfo['change_serversettings'] == '1'
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
} elseif ($action == 'delete' && $id != 0) {
|
|
||||||
|
|
||||||
} elseif ($action == 'add') {
|
|
||||||
|
|
||||||
} elseif ($action == 'edit' && $id != 0) {
|
|
||||||
|
|
||||||
} elseif ($action == 'restore') {
|
|
||||||
|
|
||||||
}
|
|
||||||
} else if ($page == 'storages' && $userinfo['change_serversettings'] == '1') {
|
|
||||||
if ($action == '') {
|
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "list backup storages");
|
|
||||||
|
|
||||||
try {
|
|
||||||
$backup_storage_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.backup_storages.php';
|
|
||||||
$collection = (new Collection(BackupStorages::class, $userinfo))
|
|
||||||
->withPagination($backup_storage_list_data['backup_storages_list']['columns'], $backup_storage_list_data['backup_storages_list']['default_sorting']);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
Response::dynamicError($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
UI::view('user/table.html.twig', [
|
|
||||||
'listing' => Listing::format($collection, $backup_storage_list_data, 'backup_storages_list'),
|
|
||||||
'actions_links' => [
|
|
||||||
[
|
|
||||||
'href' => $linker->getLink(['section' => 'backups', 'page' => 'backups']),
|
|
||||||
'label' => lng('admin.backups'),
|
|
||||||
'icon' => 'fa-solid fa-reply'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'href' => $linker->getLink(['section' => 'backups', 'page' => $page, 'action' => 'add']),
|
|
||||||
'label' => lng('admin.backup_storage_add')
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
} elseif ($action == 'delete' && $id != 0) {
|
|
||||||
try {
|
|
||||||
$json_result = BackupStorages::getLocal($userinfo, [
|
|
||||||
'id' => $id
|
|
||||||
])->get();
|
|
||||||
} catch (Exception $e) {
|
|
||||||
Response::dynamicError($e->getMessage());
|
|
||||||
}
|
|
||||||
$result = json_decode($json_result, true)['data'];
|
|
||||||
|
|
||||||
if ($result['id'] != '') {
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
|
||||||
BackupStorages::getLocal($userinfo, [
|
|
||||||
'id' => $id
|
|
||||||
])->delete();
|
|
||||||
Response::redirectTo($filename, [
|
|
||||||
'page' => $page
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
HTML::askYesNo('backup_backup_server_reallydelete', $filename, [
|
|
||||||
'id' => $id,
|
|
||||||
'page' => $page,
|
|
||||||
'action' => $action
|
|
||||||
], $result['id']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} elseif ($action == 'add') {
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
|
||||||
try {
|
|
||||||
BackupStorages::getLocal($userinfo, $_POST)->add();
|
|
||||||
} catch (Exception $e) {
|
|
||||||
Response::dynamicError($e->getMessage());
|
|
||||||
}
|
|
||||||
Response::redirectTo($filename, [
|
|
||||||
'page' => $page
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
$admin_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/backup_storages/formfield.backup_storage_add.php';
|
|
||||||
|
|
||||||
UI::view('user/form.html.twig', [
|
|
||||||
'formaction' => $linker->getLink(['section' => 'backups']),
|
|
||||||
'formdata' => $admin_add_data['backup_storage_add']
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
} elseif ($action == 'edit' && $id != 0) {
|
|
||||||
try {
|
|
||||||
$json_result = BackupStorages::getLocal($userinfo, [
|
|
||||||
'id' => $id
|
|
||||||
])->get();
|
|
||||||
} catch (Exception $e) {
|
|
||||||
Response::dynamicError($e->getMessage());
|
|
||||||
}
|
|
||||||
$result = json_decode($json_result, true)['data'];
|
|
||||||
|
|
||||||
if ($result['id'] != '') {
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
|
||||||
try {
|
|
||||||
BackupStorages::getLocal($userinfo, $_POST)->update();
|
|
||||||
} catch (Exception $e) {
|
|
||||||
Response::dynamicError($e->getMessage());
|
|
||||||
}
|
|
||||||
Response::redirectTo($filename, [
|
|
||||||
'page' => $page
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
$backup_storage_edit_data = include_once dirname(__FILE__) . '/lib/formfields/admin/backup_storages/formfield.backup_storage_edit.php';
|
|
||||||
|
|
||||||
UI::view('user/form.html.twig', [
|
|
||||||
'formaction' => $linker->getLink(['section' => 'backups', 'id' => $id]),
|
|
||||||
'formdata' => $backup_storage_edit_data['backup_storage_edit'],
|
|
||||||
'editid' => $id
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Response::dynamicError('403');
|
|
||||||
}
|
|
||||||
@@ -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
|
||||||
@@ -91,14 +93,14 @@ if ($userinfo['change_serversettings'] == '1') {
|
|||||||
asort($distributions_select);
|
asort($distributions_select);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($distribution != "" && isset($_POST['finish'])) {
|
if ($distribution != "" && !empty(Request::post('finish'))) {
|
||||||
$valid_keys = ['http', 'dns', 'smtp', 'mail', 'ftp', 'system', 'distro'];
|
$valid_keys = ['http', 'dns', 'smtp', 'mail', 'antispam', 'ftp', 'system', 'distro'];
|
||||||
unset($_POST['finish']);
|
unset($_POST['finish']);
|
||||||
unset($_POST['csrf_token']);
|
unset($_POST['csrf_token']);
|
||||||
$params = $_POST;
|
$params = Request::postAll();
|
||||||
$params['distro'] = $distribution;
|
$params['distro'] = $distribution;
|
||||||
$params['system'] = [];
|
$params['system'] = [];
|
||||||
foreach ($_POST['system'] as $sysdaemon) {
|
foreach (Request::post('system', []) as $sysdaemon) {
|
||||||
$params['system'][] = $sysdaemon;
|
$params['system'][] = $sysdaemon;
|
||||||
}
|
}
|
||||||
// validate params
|
// validate params
|
||||||
|
|||||||
@@ -68,9 +68,9 @@ if (($page == 'cronjobs' || $page == 'overview') && $userinfo['change_serversett
|
|||||||
}
|
}
|
||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
if ($result['cronfile'] != '') {
|
if ($result['cronfile'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
Cronjobs::getLocal($userinfo, $_POST)->update();
|
Cronjobs::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ const AREA = 'admin';
|
|||||||
require __DIR__ . '/lib/init.php';
|
require __DIR__ . '/lib/init.php';
|
||||||
|
|
||||||
use Froxlor\Api\Commands\Admins;
|
use Froxlor\Api\Commands\Admins;
|
||||||
use Froxlor\Api\Commands\BackupStorages;
|
|
||||||
use Froxlor\Api\Commands\Customers;
|
use Froxlor\Api\Commands\Customers;
|
||||||
use Froxlor\Api\Commands\MysqlServer;
|
use Froxlor\Api\Commands\MysqlServer;
|
||||||
use Froxlor\CurrentUser;
|
use Froxlor\CurrentUser;
|
||||||
@@ -99,7 +98,7 @@ if (($page == 'customers' || $page == 'overview') && $userinfo['customers'] != '
|
|||||||
|
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "switched user and is now '" . $destination_user . "'");
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "switched user and is now '" . $destination_user . "'");
|
||||||
|
|
||||||
$target = (isset($_GET['target']) ? $_GET['target'] : 'index');
|
$target = Request::get('target', 'index');
|
||||||
$redirect = "customer_" . $target . ".php";
|
$redirect = "customer_" . $target . ".php";
|
||||||
if (!file_exists(Froxlor::getInstallDir() . "/" . $redirect)) {
|
if (!file_exists(Froxlor::getInstallDir() . "/" . $redirect)) {
|
||||||
$redirect = "customer_index.php";
|
$redirect = "customer_index.php";
|
||||||
@@ -120,7 +119,7 @@ if (($page == 'customers' || $page == 'overview') && $userinfo['customers'] != '
|
|||||||
}
|
}
|
||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
$json_result = Customers::getLocal($userinfo, [
|
$json_result = Customers::getLocal($userinfo, [
|
||||||
'id' => $id
|
'id' => $id
|
||||||
@@ -148,11 +147,11 @@ if (($page == 'customers' || $page == 'overview') && $userinfo['customers'] != '
|
|||||||
}
|
}
|
||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
$json_result = Customers::getLocal($userinfo, [
|
$json_result = Customers::getLocal($userinfo, [
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
'delete_userfiles' => (isset($_POST['delete_userfiles']) ? (int)$_POST['delete_userfiles'] : 0)
|
'delete_userfiles' => Request::post('delete_userfiles', 0)
|
||||||
])->delete();
|
])->delete();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
@@ -168,9 +167,9 @@ if (($page == 'customers' || $page == 'overview') && $userinfo['customers'] != '
|
|||||||
], $result['loginname']);
|
], $result['loginname']);
|
||||||
}
|
}
|
||||||
} elseif ($action == 'add') {
|
} elseif ($action == 'add') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
Customers::getLocal($userinfo, $_POST)->add();
|
Customers::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -226,23 +225,6 @@ if (($page == 'customers' || $page == 'overview') && $userinfo['customers'] != '
|
|||||||
$hosting_plans[$row['id']] = $row['name'];
|
$hosting_plans[$row['id']] = $row['name'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// backup storages
|
|
||||||
$backup_storages = [];
|
|
||||||
if (Settings::Get('backup.enabled') == '1' && $userinfo['change_serversettings'] == '1') {
|
|
||||||
$backup_storages = [
|
|
||||||
0 => lng('backup.storage_none')
|
|
||||||
];
|
|
||||||
try {
|
|
||||||
$result_json = BackupStorages::getLocal($userinfo)->listing();
|
|
||||||
$result_decoded = json_decode($result_json, true)['data']['list'];
|
|
||||||
foreach ($result_decoded as $storagedata) {
|
|
||||||
$backup_storages[$storagedata['id']] = "[" . $storagedata['type'] . "] " . html_entity_decode($storagedata['description']);
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
/* just none */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$customer_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/customer/formfield.customer_add.php';
|
$customer_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/customer/formfield.customer_add.php';
|
||||||
|
|
||||||
UI::view('user/form.html.twig', [
|
UI::view('user/form.html.twig', [
|
||||||
@@ -261,9 +243,9 @@ if (($page == 'customers' || $page == 'overview') && $userinfo['customers'] != '
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if ($result['loginname'] != '') {
|
if ($result['loginname'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
Customers::getLocal($userinfo, $_POST)->update();
|
Customers::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -325,23 +307,6 @@ if (($page == 'customers' || $page == 'overview') && $userinfo['customers'] != '
|
|||||||
$hosting_plans[$row['id']] = $row['name'];
|
$hosting_plans[$row['id']] = $row['name'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// backup storages
|
|
||||||
$backup_storages = [];
|
|
||||||
if (Settings::Get('backup.enabled') == '1' && $userinfo['change_serversettings'] == '1') {
|
|
||||||
$backup_storages = [
|
|
||||||
0 => lng('backup.storage_none')
|
|
||||||
];
|
|
||||||
try {
|
|
||||||
$result_json = BackupStorages::getLocal($userinfo)->listing();
|
|
||||||
$result_decoded = json_decode($result_json, true)['data']['list'];
|
|
||||||
foreach ($result_decoded as $storagedata) {
|
|
||||||
$backup_storages[$storagedata['id']] = "[" . $storagedata['type'] . "] " . html_entity_decode($storagedata['description']);
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
/* just none */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$available_admins_stmt = Database::prepare("
|
$available_admins_stmt = Database::prepare("
|
||||||
SELECT * FROM `" . TABLE_PANEL_ADMINS . "`
|
SELECT * FROM `" . TABLE_PANEL_ADMINS . "`
|
||||||
WHERE (`customers` = '-1' OR `customers` > `customers_used`)
|
WHERE (`customers` = '-1' OR `customers` > `customers_used`)
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ use Froxlor\Api\Commands\Customers as Customers;
|
|||||||
use Froxlor\Api\Commands\Domains as Domains;
|
use Froxlor\Api\Commands\Domains as Domains;
|
||||||
use Froxlor\Bulk\DomainBulkAction;
|
use Froxlor\Bulk\DomainBulkAction;
|
||||||
use Froxlor\Cron\TaskId;
|
use Froxlor\Cron\TaskId;
|
||||||
|
use Froxlor\CurrentUser;
|
||||||
use Froxlor\Customer\Customer;
|
use Froxlor\Customer\Customer;
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
use Froxlor\Domain\Domain;
|
|
||||||
use Froxlor\FileDir;
|
use Froxlor\FileDir;
|
||||||
use Froxlor\FroxlorLogger;
|
use Froxlor\FroxlorLogger;
|
||||||
use Froxlor\Settings;
|
use Froxlor\Settings;
|
||||||
@@ -45,7 +45,6 @@ use Froxlor\UI\Request;
|
|||||||
use Froxlor\UI\Response;
|
use Froxlor\UI\Response;
|
||||||
use Froxlor\User;
|
use Froxlor\User;
|
||||||
use Froxlor\Validate\Validate;
|
use Froxlor\Validate\Validate;
|
||||||
use Froxlor\CurrentUser;
|
|
||||||
|
|
||||||
$id = (int)Request::any('id');
|
$id = (int)Request::any('id');
|
||||||
|
|
||||||
@@ -101,9 +100,9 @@ if ($page == 'domains' || $page == 'overview') {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
if ($result['domain'] != '') {
|
if ($result['domain'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send' && $alias_check['count'] == 0) {
|
if (Request::post('send') == 'send' && $alias_check['count'] == 0) {
|
||||||
try {
|
try {
|
||||||
Domains::getLocal($userinfo, $_POST)->delete();
|
Domains::getLocal($userinfo, Request::postAll())->delete();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -114,7 +113,7 @@ if ($page == 'domains' || $page == 'overview') {
|
|||||||
} elseif ($alias_check['count'] > 0) {
|
} elseif ($alias_check['count'] > 0) {
|
||||||
Response::standardError('domains_cantdeletedomainwithaliases');
|
Response::standardError('domains_cantdeletedomainwithaliases');
|
||||||
} else {
|
} else {
|
||||||
HTML::askYesNo('admin_domain_reallydelete', $filename, [
|
HTML::askYesNoWithCheckbox('admin_domain_reallydelete', 'admin_customer_alsoremovemail', $filename, [
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
'action' => $action
|
'action' => $action
|
||||||
@@ -122,9 +121,9 @@ if ($page == 'domains' || $page == 'overview') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($action == 'add') {
|
} elseif ($action == 'add') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
Domains::getLocal($userinfo, $_POST)->add();
|
Domains::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -356,13 +355,13 @@ if ($page == 'domains' || $page == 'overview') {
|
|||||||
$usedips[] = $ipsresultrow['id_ipandports'];
|
$usedips[] = $ipsresultrow['id_ipandports'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
// remove ssl ip/ports if set is empty
|
// remove ssl ip/ports if set is empty
|
||||||
if (!isset($_POST['ssl_ipandport']) || empty($_POST['ssl_ipandport'])) {
|
if (empty(Request::post('ssl_ipandport'))) {
|
||||||
$_POST['remove_ssl_ipandport'] = true;
|
$_POST['remove_ssl_ipandport'] = true;
|
||||||
}
|
}
|
||||||
Domains::getLocal($userinfo, $_POST)->update();
|
Domains::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -573,13 +572,13 @@ if ($page == 'domains' || $page == 'overview') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($action == 'jqGetCustomerPHPConfigs') {
|
} elseif ($action == 'jqGetCustomerPHPConfigs') {
|
||||||
$customerid = intval($_POST['customerid']);
|
$customerid = intval(Request::post('customerid'));
|
||||||
$allowed_phpconfigs = Customer::getCustomerDetail($customerid, 'allowed_phpconfigs');
|
$allowed_phpconfigs = Customer::getCustomerDetail($customerid, 'allowed_phpconfigs');
|
||||||
echo !empty($allowed_phpconfigs) ? $allowed_phpconfigs : json_encode([]);
|
echo !empty($allowed_phpconfigs) ? $allowed_phpconfigs : json_encode([]);
|
||||||
exit();
|
exit();
|
||||||
} elseif ($action == 'jqSpeciallogfileNote') {
|
} elseif ($action == 'jqSpeciallogfileNote') {
|
||||||
$domainid = intval($_POST['id']);
|
$domainid = intval(Request::post('id'));
|
||||||
$newval = intval($_POST['newval']);
|
$newval = intval(Request::post('newval'));
|
||||||
try {
|
try {
|
||||||
$json_result = Domains::getLocal($userinfo, [
|
$json_result = Domains::getLocal($userinfo, [
|
||||||
'id' => $domainid
|
'id' => $domainid
|
||||||
@@ -595,9 +594,9 @@ if ($page == 'domains' || $page == 'overview') {
|
|||||||
echo 0;
|
echo 0;
|
||||||
exit();
|
exit();
|
||||||
} elseif ($action == 'import') {
|
} elseif ($action == 'import') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
$separator = Validate::validate($_POST['separator'], 'separator');
|
$separator = Validate::validate(Request::post('separator'), 'separator');
|
||||||
$offset = (int)Validate::validate($_POST['offset'], 'offset', "/[0-9]/i");
|
$offset = (int)Validate::validate(Request::post('offset'), 'offset', "/[0-9]/i");
|
||||||
|
|
||||||
$file_name = $_FILES['file']['tmp_name'];
|
$file_name = $_FILES['file']['tmp_name'];
|
||||||
|
|
||||||
@@ -637,16 +636,16 @@ if ($page == 'domains' || $page == 'overview') {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
} elseif ($action == 'duplicate') {
|
} elseif ($action == 'duplicate') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
Domains::getLocal($userinfo, $_POST)->duplicate();
|
Domains::getLocal($userinfo, Request::postAll())->duplicate();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
Response::redirectTo($filename, [
|
Response::redirectTo($filename, [
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
'searchfield' => 'd.domain_ace',
|
'searchfield' => 'd.domain_ace',
|
||||||
'searchtext' => $_POST['domain'] ?? ""
|
'searchtext' => Request::post('domain', "")
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
Response::redirectTo($filename, [
|
Response::redirectTo($filename, [
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ if ($action == 'logout') {
|
|||||||
$result = $result['switched_user'];
|
$result = $result['switched_user'];
|
||||||
session_regenerate_id(true);
|
session_regenerate_id(true);
|
||||||
CurrentUser::setData($result);
|
CurrentUser::setData($result);
|
||||||
$target = (isset($_GET['target']) ? $_GET['target'] : 'index');
|
$target = Request::get('target', 'index');
|
||||||
$redirect = "admin_" . $target . ".php";
|
$redirect = "admin_" . $target . ".php";
|
||||||
if (!file_exists(\Froxlor\Froxlor::getInstallDir() . "/" . $redirect)) {
|
if (!file_exists(\Froxlor\Froxlor::getInstallDir() . "/" . $redirect)) {
|
||||||
$redirect = "admin_index.php";
|
$redirect = "admin_index.php";
|
||||||
@@ -111,7 +111,7 @@ if ($page == 'overview') {
|
|||||||
|
|
||||||
$overview['number_domains'] = $number_domains['number_domains'];
|
$overview['number_domains'] = $number_domains['number_domains'];
|
||||||
|
|
||||||
if ((isset($_GET['lookfornewversion']) && $_GET['lookfornewversion'] == 'yes') || (isset($lookfornewversion) && $lookfornewversion == 'yes')) {
|
if (Request::get('lookfornewversion') == 'yes' || (isset($lookfornewversion) && $lookfornewversion == 'yes')) {
|
||||||
try {
|
try {
|
||||||
$json_result = Froxlor::getLocal($userinfo)->checkUpdate();
|
$json_result = Froxlor::getLocal($userinfo)->checkUpdate();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
@@ -201,16 +201,16 @@ if ($page == 'overview') {
|
|||||||
$languages = Language::getLanguages();
|
$languages = Language::getLanguages();
|
||||||
|
|
||||||
if (!empty($_POST)) {
|
if (!empty($_POST)) {
|
||||||
if ($_POST['send'] == 'changepassword') {
|
if (Request::post('send') == 'changepassword') {
|
||||||
$old_password = Validate::validate($_POST['old_password'], 'old password');
|
$old_password = Validate::validate(Request::post('old_password'), 'old password');
|
||||||
|
|
||||||
if (!Crypt::validatePasswordLogin($userinfo, $old_password, TABLE_PANEL_ADMINS, 'adminid')) {
|
if (!Crypt::validatePasswordLogin($userinfo, $old_password, TABLE_PANEL_ADMINS, 'adminid')) {
|
||||||
Response::standardError('oldpasswordnotcorrect');
|
Response::standardError('oldpasswordnotcorrect');
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$new_password = Crypt::validatePassword($_POST['new_password'], 'new password');
|
$new_password = Crypt::validatePassword(Request::post('new_password'), 'new password');
|
||||||
$new_password_confirm = Crypt::validatePassword($_POST['new_password_confirm'], 'new password confirm');
|
$new_password_confirm = Crypt::validatePassword(Request::post('new_password_confirm'), 'new password confirm');
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -244,9 +244,9 @@ if ($page == 'overview') {
|
|||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'changed password');
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'changed password');
|
||||||
Response::redirectTo($filename);
|
Response::redirectTo($filename);
|
||||||
}
|
}
|
||||||
} elseif ($_POST['send'] == 'changetheme') {
|
} elseif (Request::post('send') == 'changetheme') {
|
||||||
if (Settings::Get('panel.allow_theme_change_admin') == 1) {
|
if (Settings::Get('panel.allow_theme_change_admin') == 1) {
|
||||||
$theme = Validate::validate($_POST['theme'], 'theme');
|
$theme = Validate::validate(Request::post('theme'), 'theme');
|
||||||
try {
|
try {
|
||||||
Admins::getLocal($userinfo, [
|
Admins::getLocal($userinfo, [
|
||||||
'id' => $userinfo['adminid'],
|
'id' => $userinfo['adminid'],
|
||||||
@@ -259,8 +259,8 @@ if ($page == 'overview') {
|
|||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "changed his/her theme to '" . $theme . "'");
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "changed his/her theme to '" . $theme . "'");
|
||||||
}
|
}
|
||||||
Response::redirectTo($filename);
|
Response::redirectTo($filename);
|
||||||
} elseif ($_POST['send'] == 'changelanguage') {
|
} elseif (Request::post('send') == 'changelanguage') {
|
||||||
$def_language = Validate::validate($_POST['def_language'], 'default language');
|
$def_language = Validate::validate(Request::post('def_language'), 'default language');
|
||||||
|
|
||||||
if (isset($languages[$def_language])) {
|
if (isset($languages[$def_language])) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ if (($page == 'ipsandports' || $page == 'overview') && $userinfo['change_servers
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['id']) && $result['id'] == $id) {
|
if (isset($result['id']) && $result['id'] == $id) {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
IpsAndPorts::getLocal($userinfo, [
|
IpsAndPorts::getLocal($userinfo, [
|
||||||
'id' => $id
|
'id' => $id
|
||||||
@@ -91,9 +91,9 @@ if (($page == 'ipsandports' || $page == 'overview') && $userinfo['change_servers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($action == 'add') {
|
} elseif ($action == 'add') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
IpsAndPorts::getLocal($userinfo, $_POST)->add();
|
IpsAndPorts::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -119,9 +119,9 @@ if (($page == 'ipsandports' || $page == 'overview') && $userinfo['change_servers
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if ($result['ip'] != '') {
|
if ($result['ip'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
IpsAndPorts::getLocal($userinfo, $_POST)->update();
|
IpsAndPorts::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -141,9 +141,11 @@ if (($page == 'ipsandports' || $page == 'overview') && $userinfo['change_servers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($action == 'jqCheckIP') {
|
} elseif ($action == 'jqCheckIP') {
|
||||||
$ip = $_POST['ip'] ?? "";
|
$ip = Request::post('ip', '');
|
||||||
if ((filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) || filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) && filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE) == false) {
|
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
|
||||||
// returns notice if private network detected so we can display it
|
echo json_encode('<div id="ipnote" class="invalid-feedback">'.lng('error.invalidip', [$ip]).'</div>');
|
||||||
|
} elseif (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE)) {
|
||||||
|
// returns notice if private network detected, so we can display it
|
||||||
echo json_encode(lng('admin.ipsandports.ipnote'));
|
echo json_encode(lng('admin.ipsandports.ipnote'));
|
||||||
} else {
|
} else {
|
||||||
echo 0;
|
echo 0;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ use Froxlor\UI\Collection;
|
|||||||
use Froxlor\UI\HTML;
|
use Froxlor\UI\HTML;
|
||||||
use Froxlor\UI\Listing;
|
use Froxlor\UI\Listing;
|
||||||
use Froxlor\UI\Panel\UI;
|
use Froxlor\UI\Panel\UI;
|
||||||
|
use Froxlor\UI\Request;
|
||||||
use Froxlor\UI\Response;
|
use Froxlor\UI\Response;
|
||||||
|
|
||||||
if ($page == 'log' && $userinfo['change_serversettings'] == '1') {
|
if ($page == 'log' && $userinfo['change_serversettings'] == '1') {
|
||||||
@@ -55,7 +56,7 @@ if ($page == 'log' && $userinfo['change_serversettings'] == '1') {
|
|||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
} elseif ($action == 'truncate') {
|
} elseif ($action == 'truncate') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
SysLog::getLocal($userinfo, [
|
SysLog::getLocal($userinfo, [
|
||||||
'min_to_keep' => 10
|
'min_to_keep' => 10
|
||||||
|
|||||||
@@ -42,11 +42,11 @@ if ($page == 'message') {
|
|||||||
if ($action == '') {
|
if ($action == '') {
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'viewed panel_message');
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'viewed panel_message');
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
if ($_POST['recipient'] == 0 && $userinfo['customers_see_all'] == '1') {
|
if (Request::post('recipient', -1) == 0 && $userinfo['customers_see_all'] == '1') {
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to admins');
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to admins');
|
||||||
$result = Database::query('SELECT `name`, `email` FROM `' . TABLE_PANEL_ADMINS . "`");
|
$result = Database::query('SELECT `name`, `email` FROM `' . TABLE_PANEL_ADMINS . "`");
|
||||||
} elseif ($_POST['recipient'] == 1) {
|
} elseif (Request::post('recipient', -1) == 1) {
|
||||||
if ($userinfo['customers_see_all'] == '1') {
|
if ($userinfo['customers_see_all'] == '1') {
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to ALL customers');
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to ALL customers');
|
||||||
$result = Database::query('SELECT `firstname`, `name`, `company`, `email` FROM `' . TABLE_PANEL_CUSTOMERS . "`");
|
$result = Database::query('SELECT `firstname`, `name`, `company`, `email` FROM `' . TABLE_PANEL_CUSTOMERS . "`");
|
||||||
@@ -63,8 +63,8 @@ if ($page == 'message') {
|
|||||||
Response::standardError('norecipientsgiven');
|
Response::standardError('norecipientsgiven');
|
||||||
}
|
}
|
||||||
|
|
||||||
$subject = $_POST['subject'];
|
$subject = Request::post('subject');
|
||||||
$message = wordwrap($_POST['message'], 70);
|
$message = wordwrap(Request::post('message'), 70);
|
||||||
|
|
||||||
if (!empty($message)) {
|
if (!empty($message)) {
|
||||||
$mailcounter = 0;
|
$mailcounter = 0;
|
||||||
@@ -107,7 +107,7 @@ if ($page == 'message') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($action == 'showsuccess') {
|
} elseif ($action == 'showsuccess') {
|
||||||
$sentitems = isset($_GET['sentitems']) ? (int)$_GET['sentitems'] : 0;
|
$sentitems = Request::get('sentitems', 0);
|
||||||
|
|
||||||
if ($sentitems == 0) {
|
if ($sentitems == 0) {
|
||||||
$note_type = 'info';
|
$note_type = 'info';
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ if (($page == 'mysqlserver' || $page == 'overview') && $userinfo['change_servers
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['id']) && $result['id'] == $id) {
|
if (isset($result['id']) && $result['id'] == $id) {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
MysqlServer::getLocal($userinfo, [
|
MysqlServer::getLocal($userinfo, [
|
||||||
'id' => $id
|
'id' => $id
|
||||||
@@ -91,9 +91,9 @@ if (($page == 'mysqlserver' || $page == 'overview') && $userinfo['change_servers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($action == 'add') {
|
} elseif ($action == 'add') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
MysqlServer::getLocal($userinfo, $_POST)->add();
|
MysqlServer::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -119,9 +119,9 @@ if (($page == 'mysqlserver' || $page == 'overview') && $userinfo['change_servers
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['id']) && $result['id'] == $id) {
|
if (isset($result['id']) && $result['id'] == $id) {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
MysqlServer::getLocal($userinfo, $_POST)->update();
|
MysqlServer::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,10 +35,11 @@ require __DIR__ . '/lib/init.php';
|
|||||||
use Froxlor\FroxlorLogger;
|
use Froxlor\FroxlorLogger;
|
||||||
use Froxlor\UI\HTML;
|
use Froxlor\UI\HTML;
|
||||||
use Froxlor\UI\Panel\UI;
|
use Froxlor\UI\Panel\UI;
|
||||||
|
use Froxlor\UI\Request;
|
||||||
use Froxlor\UI\Response;
|
use Froxlor\UI\Response;
|
||||||
|
|
||||||
if ($action == 'reset' && function_exists('opcache_reset') && $userinfo['change_serversettings'] == '1') {
|
if ($action == 'reset' && function_exists('opcache_reset') && $userinfo['change_serversettings'] == '1') {
|
||||||
if ($_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
opcache_reset();
|
opcache_reset();
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "reset OPcache");
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "reset OPcache");
|
||||||
header('Location: ' . $linker->getLink([
|
header('Location: ' . $linker->getLink([
|
||||||
|
|||||||
@@ -62,9 +62,9 @@ if ($page == 'overview') {
|
|||||||
|
|
||||||
if ($action == 'add') {
|
if ($action == 'add') {
|
||||||
if ((int)$userinfo['change_serversettings'] == 1) {
|
if ((int)$userinfo['change_serversettings'] == 1) {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
PhpSettings::getLocal($userinfo, $_POST)->add();
|
PhpSettings::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -114,7 +114,7 @@ if ($page == 'overview') {
|
|||||||
|
|
||||||
if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1 && $id != 1) // cannot delete the default php.config
|
if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1 && $id != 1) // cannot delete the default php.config
|
||||||
{
|
{
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
PhpSettings::getLocal($userinfo, [
|
PhpSettings::getLocal($userinfo, [
|
||||||
'id' => $id
|
'id' => $id
|
||||||
@@ -148,9 +148,9 @@ if ($page == 'overview') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1) {
|
if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1) {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
PhpSettings::getLocal($userinfo, $_POST)->update();
|
PhpSettings::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -200,9 +200,9 @@ if ($page == 'overview') {
|
|||||||
|
|
||||||
if ($action == 'add') {
|
if ($action == 'add') {
|
||||||
if ((int)$userinfo['change_serversettings'] == 1) {
|
if ((int)$userinfo['change_serversettings'] == 1) {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
FpmDaemons::getLocal($userinfo, $_POST)->add();
|
FpmDaemons::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -239,9 +239,9 @@ if ($page == 'overview') {
|
|||||||
|
|
||||||
if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1 && $id != 1) // cannot delete the default php.config
|
if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1 && $id != 1) // cannot delete the default php.config
|
||||||
{
|
{
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
FpmDaemons::getLocal($userinfo, $_POST)->delete();
|
FpmDaemons::getLocal($userinfo, Request::postAll())->delete();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -271,9 +271,9 @@ if ($page == 'overview') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1) {
|
if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1) {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
FpmDaemons::getLocal($userinfo, $_POST)->update();
|
FpmDaemons::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ if ($page == '' || $page == 'overview') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['adminid'] == $result['adminid']) {
|
if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['adminid'] == $result['adminid']) {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
HostingPlans::getLocal($userinfo, [
|
HostingPlans::getLocal($userinfo, [
|
||||||
'id' => $id
|
'id' => $id
|
||||||
@@ -96,9 +96,9 @@ if ($page == '' || $page == 'overview') {
|
|||||||
Response::standardError('nopermissionsorinvalidid');
|
Response::standardError('nopermissionsorinvalidid');
|
||||||
}
|
}
|
||||||
} elseif ($action == 'add') {
|
} elseif ($action == 'add') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
HostingPlans::getLocal($userinfo, $_POST)->add();
|
HostingPlans::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -176,9 +176,9 @@ if ($page == '' || $page == 'overview') {
|
|||||||
}
|
}
|
||||||
$result['allowed_phpconfigs'] = json_encode($result['allowed_phpconfigs']);
|
$result['allowed_phpconfigs'] = json_encode($result['allowed_phpconfigs']);
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
HostingPlans::getLocal($userinfo, $_POST)->update();
|
HostingPlans::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,10 +47,10 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
|
|||||||
$settings_data = PhpHelper::loadConfigArrayDir('./actions/admin/settings/');
|
$settings_data = PhpHelper::loadConfigArrayDir('./actions/admin/settings/');
|
||||||
Settings::loadSettingsInto($settings_data);
|
Settings::loadSettingsInto($settings_data);
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
$_part = isset($_GET['part']) ? $_GET['part'] : '';
|
$_part = Request::get('part', '');
|
||||||
if ($_part == '') {
|
if ($_part == '') {
|
||||||
$_part = isset($_POST['part']) ? $_POST['part'] : '';
|
$_part = Request::post('part', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($_part != '') {
|
if ($_part != '') {
|
||||||
@@ -69,12 +69,12 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if the session timeout is too low #815
|
// check if the session timeout is too low #815
|
||||||
if (isset($_POST['session_sessiontimeout']) && $_POST['session_sessiontimeout'] < 60) {
|
if (!empty(Request::post('session_sessiontimeout')) && intval(Request::post('session_sessiontimeout', 0)) < 60) {
|
||||||
Response::standardError(['session_timeout', 'session_timeout_desc']);
|
Response::standardError(['session_timeout', 'session_timeout_desc']);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (Form::processForm($settings_data, $_POST, [
|
if (Form::processForm($settings_data, Request::postAll(), [
|
||||||
'filename' => $filename,
|
'filename' => $filename,
|
||||||
'action' => $action,
|
'action' => $action,
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
@@ -97,9 +97,9 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
|
|||||||
Response::dynamicError($e->getMessage(), $e->getCode());
|
Response::dynamicError($e->getMessage(), $e->getCode());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$_part = isset($_GET['part']) ? $_GET['part'] : '';
|
$_part = Request::get('part', '');
|
||||||
if ($_part == '') {
|
if ($_part == '') {
|
||||||
$_part = isset($_POST['part']) ? $_POST['part'] : '';
|
$_part = Request::post('part', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
$fields = Form::buildForm($settings_data, $_part);
|
$fields = Form::buildForm($settings_data, $_part);
|
||||||
@@ -140,7 +140,7 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
|
|||||||
'phpinfo' => $phpinfo
|
'phpinfo' => $phpinfo
|
||||||
]);
|
]);
|
||||||
} elseif ($page == 'rebuildconfigs' && $userinfo['change_serversettings'] == '1') {
|
} elseif ($page == 'rebuildconfigs' && $userinfo['change_serversettings'] == '1') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "rebuild configfiles");
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "rebuild configfiles");
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
Cronjob::inserttask(TaskId::CREATE_QUOTA);
|
Cronjob::inserttask(TaskId::CREATE_QUOTA);
|
||||||
@@ -158,7 +158,7 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
} elseif ($page == 'updatecounters' && $userinfo['change_serversettings'] == '1') {
|
} elseif ($page == 'updatecounters' && $userinfo['change_serversettings'] == '1') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "updated resource-counters");
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "updated resource-counters");
|
||||||
$updatecounters = User::updateCounters(true);
|
$updatecounters = User::updateCounters(true);
|
||||||
UI::view('user/resource-counter.html.twig', [
|
UI::view('user/resource-counter.html.twig', [
|
||||||
@@ -170,7 +170,7 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
} elseif ($page == 'wipecleartextmailpws' && $userinfo['change_serversettings'] == '1') {
|
} elseif ($page == 'wipecleartextmailpws' && $userinfo['change_serversettings'] == '1') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "wiped all cleartext mail passwords");
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "wiped all cleartext mail passwords");
|
||||||
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password` = '';");
|
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password` = '';");
|
||||||
Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `value` = '0' WHERE `settinggroup` = 'system' AND `varname` = 'mailpwcleartext'");
|
Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `value` = '0' WHERE `settinggroup` = 'system' AND `varname` = 'mailpwcleartext'");
|
||||||
@@ -181,7 +181,7 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
} elseif ($page == 'wipequotas' && $userinfo['change_serversettings'] == '1') {
|
} elseif ($page == 'wipequotas' && $userinfo['change_serversettings'] == '1') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "wiped all mailquotas");
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "wiped all mailquotas");
|
||||||
|
|
||||||
// Set the quota to 0 which means unlimited
|
// Set the quota to 0 which means unlimited
|
||||||
@@ -194,7 +194,7 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
} elseif ($page == 'enforcequotas' && $userinfo['change_serversettings'] == '1') {
|
} elseif ($page == 'enforcequotas' && $userinfo['change_serversettings'] == '1') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
// Fetch all accounts
|
// Fetch all accounts
|
||||||
$result_stmt = Database::query("SELECT `quota`, `customerid` FROM `" . TABLE_MAIL_USERS . "`");
|
$result_stmt = Database::query("SELECT `quota`, `customerid` FROM `" . TABLE_MAIL_USERS . "`");
|
||||||
|
|
||||||
@@ -233,9 +233,9 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
|
|||||||
}
|
}
|
||||||
} elseif ($page == 'integritycheck' && $userinfo['change_serversettings'] == '1') {
|
} elseif ($page == 'integritycheck' && $userinfo['change_serversettings'] == '1') {
|
||||||
$integrity = new IntegrityCheck();
|
$integrity = new IntegrityCheck();
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
$integrity->fixAll();
|
$integrity->fixAll();
|
||||||
} elseif (isset($_GET['action']) && $_GET['action'] == "fix") {
|
} elseif (Request::get('action') == "fix") {
|
||||||
HTML::askYesNo('admin_integritycheck_reallyfix', $filename, [
|
HTML::askYesNo('admin_integritycheck_reallyfix', $filename, [
|
||||||
'page' => $page
|
'page' => $page
|
||||||
]);
|
]);
|
||||||
@@ -273,7 +273,7 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
|
|||||||
Response::standardError('jsonextensionnotfound');
|
Response::standardError('jsonextensionnotfound');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_GET['action']) && $_GET['action'] == "export") {
|
if (Request::get('action') == "export") {
|
||||||
// export
|
// export
|
||||||
try {
|
try {
|
||||||
$json_result = Froxlor::getLocal($userinfo)->exportSettings();
|
$json_result = Froxlor::getLocal($userinfo)->exportSettings();
|
||||||
@@ -285,9 +285,9 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
|
|||||||
header('Content-type: application/json');
|
header('Content-type: application/json');
|
||||||
echo $json_export;
|
echo $json_export;
|
||||||
exit();
|
exit();
|
||||||
} elseif (isset($_GET['action']) && $_GET['action'] == "import") {
|
} elseif (Request::get('action') == "import") {
|
||||||
// import
|
// import
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
// get uploaded file
|
// get uploaded file
|
||||||
if (isset($_FILES["import_file"]["tmp_name"])) {
|
if (isset($_FILES["import_file"]["tmp_name"])) {
|
||||||
$imp_content = file_get_contents($_FILES["import_file"]["tmp_name"]);
|
$imp_content = file_get_contents($_FILES["import_file"]["tmp_name"]);
|
||||||
@@ -330,8 +330,8 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
|
|||||||
$note_type = 'info';
|
$note_type = 'info';
|
||||||
$note_msg = lng('admin.smtptestnote');
|
$note_msg = lng('admin.smtptestnote');
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
$test_addr = isset($_POST['test_addr']) ? $_POST['test_addr'] : null;
|
$test_addr = Request::post('test_addr');
|
||||||
|
|
||||||
// Initialize the mailingsystem
|
// Initialize the mailingsystem
|
||||||
$testmail = new PHPMailer(true);
|
$testmail = new PHPMailer(true);
|
||||||
|
|||||||
@@ -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();
|
||||||
@@ -191,7 +192,7 @@ if ($action == '') {
|
|||||||
$result = $result_stmt->fetch(PDO::FETCH_ASSOC);
|
$result = $result_stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
if ($result['varname'] != '') {
|
if ($result['varname'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
$del_stmt = Database::prepare("
|
$del_stmt = Database::prepare("
|
||||||
DELETE FROM `" . TABLE_PANEL_TEMPLATES . "`
|
DELETE FROM `" . TABLE_PANEL_TEMPLATES . "`
|
||||||
WHERE `adminid` = :adminid
|
WHERE `adminid` = :adminid
|
||||||
@@ -227,7 +228,7 @@ if ($action == '') {
|
|||||||
if (Database::num_rows() > 0) {
|
if (Database::num_rows() > 0) {
|
||||||
$row = $result_stmt->fetch(PDO::FETCH_ASSOC);
|
$row = $result_stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
$del_stmt = Database::prepare("
|
$del_stmt = Database::prepare("
|
||||||
DELETE FROM `" . TABLE_PANEL_TEMPLATES . "`
|
DELETE FROM `" . TABLE_PANEL_TEMPLATES . "`
|
||||||
WHERE `adminid` = :adminid AND `id` = :id");
|
WHERE `adminid` = :adminid AND `id` = :id");
|
||||||
@@ -250,13 +251,13 @@ if ($action == '') {
|
|||||||
Response::standardError('templatenotfound');
|
Response::standardError('templatenotfound');
|
||||||
}
|
}
|
||||||
} elseif ($action == 'add') {
|
} elseif ($action == 'add') {
|
||||||
if (isset($_POST['prepare']) && $_POST['prepare'] == 'prepare') {
|
if (Request::post('prepare') == 'prepare') {
|
||||||
// email templates
|
// email templates
|
||||||
$language = htmlentities(Validate::validate($_POST['language'], 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect'));
|
$language = htmlentities(Validate::validate(Request::post('language'), 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect'));
|
||||||
if (!array_key_exists($language, $languages)) {
|
if (!array_key_exists($language, $languages)) {
|
||||||
Response::standardError('templatelanguageinvalid');
|
Response::standardError('templatelanguageinvalid');
|
||||||
}
|
}
|
||||||
$template = Validate::validate($_POST['template'], 'template');
|
$template = Validate::validate(Request::post('template'), 'template');
|
||||||
|
|
||||||
$result_stmt = Database::prepare("
|
$result_stmt = Database::prepare("
|
||||||
SELECT COUNT(*) as def FROM `" . TABLE_PANEL_TEMPLATES . "`
|
SELECT COUNT(*) as def FROM `" . TABLE_PANEL_TEMPLATES . "`
|
||||||
@@ -288,15 +289,15 @@ if ($action == '') {
|
|||||||
'formdata' => $template_add_data['template_add'],
|
'formdata' => $template_add_data['template_add'],
|
||||||
'replacers' => $template_add_data['template_replacers']
|
'replacers' => $template_add_data['template_replacers']
|
||||||
]);
|
]);
|
||||||
} elseif (isset($_POST['send']) && $_POST['send'] == 'send' && !isset($_POST['filesend'])) {
|
} elseif (Request::post('send') == 'send' && empty(Request::post('filesend'))) {
|
||||||
// email templates
|
// email templates
|
||||||
$language = htmlentities(Validate::validate($_POST['language'], 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect'));
|
$language = htmlentities(Validate::validate(Request::post('language'), 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect'));
|
||||||
if (!array_key_exists($language, $languages)) {
|
if (!array_key_exists($language, $languages)) {
|
||||||
Response::standardError('templatelanguageinvalid');
|
Response::standardError('templatelanguageinvalid');
|
||||||
}
|
}
|
||||||
$template = Validate::validate($_POST['template'], 'template');
|
$template = Validate::validate(Request::post('template'), 'template');
|
||||||
$subject = Validate::validate($_POST['subject'], 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate');
|
$subject = Validate::validate(Request::post('subject'), 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate');
|
||||||
$mailbody = Validate::validate($_POST['mailbody'], 'mailbody', '/^[^\0]+$/', 'nomailbodycreate');
|
$mailbody = Validate::validate(Request::post('mailbody'), 'mailbody', '/^[^\0]+$/', 'nomailbodycreate');
|
||||||
$templates = [];
|
$templates = [];
|
||||||
$result_stmt = Database::prepare("
|
$result_stmt = Database::prepare("
|
||||||
SELECT `varname` FROM `" . TABLE_PANEL_TEMPLATES . "`
|
SELECT `varname` FROM `" . TABLE_PANEL_TEMPLATES . "`
|
||||||
@@ -346,10 +347,10 @@ if ($action == '') {
|
|||||||
'page' => $page
|
'page' => $page
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
} elseif (isset($_POST['filesend']) && $_POST['filesend'] == 'filesend') {
|
} elseif (Request::post('filesend') == 'filesend') {
|
||||||
// file templates
|
// file templates
|
||||||
$template = Validate::validate($_POST['template'], 'template');
|
$template = Validate::validate(Request::post('template'), 'template');
|
||||||
$filecontent = Validate::validate($_POST['filecontent'], 'filecontent', '/^[^\0]+$/', 'filecontentnotset');
|
$filecontent = Validate::validate(Request::post('filecontent'), 'filecontent', '/^[^\0]+$/', 'filecontentnotset');
|
||||||
|
|
||||||
$ins_stmt = Database::prepare("
|
$ins_stmt = Database::prepare("
|
||||||
INSERT INTO `" . TABLE_PANEL_TEMPLATES . "` SET
|
INSERT INTO `" . TABLE_PANEL_TEMPLATES . "` SET
|
||||||
@@ -370,7 +371,7 @@ if ($action == '') {
|
|||||||
Response::redirectTo($filename, [
|
Response::redirectTo($filename, [
|
||||||
'page' => $page
|
'page' => $page
|
||||||
]);
|
]);
|
||||||
} elseif (!isset($_GET['files'])) {
|
} elseif (empty(Request::get('files'))) {
|
||||||
// email templates
|
// email templates
|
||||||
$add = false;
|
$add = false;
|
||||||
$language_options = [];
|
$language_options = [];
|
||||||
@@ -482,9 +483,9 @@ if ($action == '') {
|
|||||||
$result = $result_stmt->fetch(PDO::FETCH_ASSOC);
|
$result = $result_stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
if ($result['varname'] != '') {
|
if ($result['varname'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
$subject = Validate::validate($_POST['subject'], 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate');
|
$subject = Validate::validate(Request::post('subject'), 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate');
|
||||||
$mailbody = Validate::validate($_POST['mailbody'], 'mailbody', '/^[^\0]+$/', 'nomailbodycreate');
|
$mailbody = Validate::validate(Request::post('mailbody'), 'mailbody', '/^[^\0]+$/', 'nomailbodycreate');
|
||||||
|
|
||||||
$upd_stmt = Database::prepare("
|
$upd_stmt = Database::prepare("
|
||||||
UPDATE `" . TABLE_PANEL_TEMPLATES . "` SET
|
UPDATE `" . TABLE_PANEL_TEMPLATES . "` SET
|
||||||
@@ -550,8 +551,8 @@ if ($action == '') {
|
|||||||
$row = $result_stmt->fetch(PDO::FETCH_ASSOC);
|
$row = $result_stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// filetemplates
|
// filetemplates
|
||||||
if (isset($_POST['filesend']) && $_POST['filesend'] == 'filesend') {
|
if (Request::post('filesend') == 'filesend') {
|
||||||
$filecontent = Validate::validate($_POST['filecontent'], 'filecontent', '/^[^\0]+$/', 'filecontentnotset');
|
$filecontent = Validate::validate(Request::post('filecontent'), 'filecontent', '/^[^\0]+$/', 'filecontentnotset');
|
||||||
$upd_stmt = Database::prepare("
|
$upd_stmt = Database::prepare("
|
||||||
UPDATE `" . TABLE_PANEL_TEMPLATES . "` SET
|
UPDATE `" . TABLE_PANEL_TEMPLATES . "` SET
|
||||||
`value` = :value
|
`value` = :value
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ use Froxlor\Install\Update;
|
|||||||
use Froxlor\Settings;
|
use Froxlor\Settings;
|
||||||
use Froxlor\System\Cronjob;
|
use Froxlor\System\Cronjob;
|
||||||
use Froxlor\UI\Panel\UI;
|
use Froxlor\UI\Panel\UI;
|
||||||
|
use Froxlor\UI\Request;
|
||||||
use Froxlor\UI\Response;
|
use Froxlor\UI\Response;
|
||||||
use Froxlor\User;
|
use Froxlor\User;
|
||||||
|
|
||||||
@@ -48,8 +49,8 @@ if ($page == 'overview') {
|
|||||||
$successful_update = false;
|
$successful_update = false;
|
||||||
$message = '';
|
$message = '';
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
if ((isset($_POST['update_preconfig']) && isset($_POST['update_changesagreed']) && intval($_POST['update_changesagreed']) != 0) || !isset($_POST['update_preconfig'])) {
|
if ((!empty(Request::post('update_preconfig')) && intval(Request::post('update_changesagreed', 0)) != 0) || empty(Request::post('update_preconfig'))) {
|
||||||
include_once Froxlor::getInstallDir() . 'install/updatesql.php';
|
include_once Froxlor::getInstallDir() . 'install/updatesql.php';
|
||||||
|
|
||||||
User::updateCounters();
|
User::updateCounters();
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ if ($action == 'delete' && $id > 0) {
|
|||||||
'section' => 'index',
|
'section' => 'index',
|
||||||
'page' => $page
|
'page' => $page
|
||||||
]);
|
]);
|
||||||
} elseif (isset($_POST['send']) && $_POST['send'] == 'send' && $action == 'deletesure' && $id > 0) {
|
} elseif (Request::post('send') == 'send' && $action == 'deletesure' && $id > 0) {
|
||||||
$chk = (AREA == 'admin' && $userinfo['customers_see_all'] == '1') ? true : false;
|
$chk = (AREA == 'admin' && $userinfo['customers_see_all'] == '1') ? true : false;
|
||||||
if (AREA == 'customer') {
|
if (AREA == 'customer') {
|
||||||
$chk_stmt = Database::prepare("
|
$chk_stmt = Database::prepare("
|
||||||
@@ -94,7 +94,7 @@ if ($action == 'delete' && $id > 0) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
} elseif ($action == 'add') {
|
} elseif ($action == 'add') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
$ins_stmt = Database::prepare("
|
$ins_stmt = Database::prepare("
|
||||||
INSERT INTO `" . TABLE_API_KEYS . "` SET
|
INSERT INTO `" . TABLE_API_KEYS . "` SET
|
||||||
`apikey` = :key, `secret` = :secret, `adminid` = :aid, `customerid` = :cid, `valid_until` = '-1', `allowed_from` = ''
|
`apikey` = :key, `secret` = :secret, `adminid` = :aid, `customerid` = :cid, `valid_until` = '-1', `allowed_from` = ''
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -46,17 +46,17 @@
|
|||||||
"ext-fileinfo": "*",
|
"ext-fileinfo": "*",
|
||||||
"ext-gmp": "*",
|
"ext-gmp": "*",
|
||||||
"ext-gd": "*",
|
"ext-gd": "*",
|
||||||
"ext-ftp": "*",
|
"ext-gnupg": "*",
|
||||||
"phpmailer/phpmailer": "~6.0",
|
"phpmailer/phpmailer": "~6.0",
|
||||||
"monolog/monolog": "^1.24",
|
"monolog/monolog": "^1.24",
|
||||||
"robthree/twofactorauth": "^1.6",
|
"robthree/twofactorauth": "^1.6",
|
||||||
"froxlor/idna-convert-legacy": "^2.1",
|
"froxlor/idna-convert-legacy": "^2.1",
|
||||||
"voku/anti-xss": "^4.1",
|
"voku/anti-xss": "^4.1",
|
||||||
"twig/twig": "^3.3",
|
"twig/twig": "^3.3",
|
||||||
"erusev/parsedown": "^1.7",
|
|
||||||
"symfony/console": "^5.4",
|
"symfony/console": "^5.4",
|
||||||
"pear/net_dns2": "^1.5",
|
"pear/net_dns2": "^1.5",
|
||||||
"amnuts/opcache-gui": "^3.4"
|
"amnuts/opcache-gui": "^3.4",
|
||||||
|
"league/commonmark": "^2.4"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^9",
|
"phpunit/phpunit": "^9",
|
||||||
|
|||||||
1113
composer.lock
generated
1113
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,8 @@
|
|||||||
const AREA = 'customer';
|
const AREA = 'customer';
|
||||||
require __DIR__ . '/lib/init.php';
|
require __DIR__ . '/lib/init.php';
|
||||||
|
|
||||||
use Froxlor\Api\Commands\SubDomains as SubDomains;
|
use Froxlor\Api\Commands\SubDomains;
|
||||||
|
use Froxlor\CurrentUser;
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
use Froxlor\Domain\Domain;
|
use Froxlor\Domain\Domain;
|
||||||
use Froxlor\FileDir;
|
use Froxlor\FileDir;
|
||||||
@@ -40,7 +41,6 @@ use Froxlor\UI\Panel\UI;
|
|||||||
use Froxlor\UI\Request;
|
use Froxlor\UI\Request;
|
||||||
use Froxlor\UI\Response;
|
use Froxlor\UI\Response;
|
||||||
use Froxlor\Validate\Validate;
|
use Froxlor\Validate\Validate;
|
||||||
use Froxlor\CurrentUser;
|
|
||||||
|
|
||||||
// redirect if this customer page is hidden via settings
|
// redirect if this customer page is hidden via settings
|
||||||
if (Settings::IsInList('panel.customer_hide_options', 'domains')) {
|
if (Settings::IsInList('panel.customer_hide_options', 'domains')) {
|
||||||
@@ -63,16 +63,21 @@ if ($page == 'overview' || $page == 'domains') {
|
|||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
$actions_links = false;
|
$actions_links = [];
|
||||||
if (CurrentUser::canAddResource('subdomains')) {
|
if (CurrentUser::canAddResource('subdomains')) {
|
||||||
$actions_links = [
|
$actions_links[] = [
|
||||||
[
|
|
||||||
'href' => $linker->getLink(['section' => 'domains', 'page' => 'domains', 'action' => 'add']),
|
'href' => $linker->getLink(['section' => 'domains', 'page' => 'domains', 'action' => 'add']),
|
||||||
'label' => lng('domains.subdomain_add')
|
'label' => lng('domains.subdomain_add')
|
||||||
]
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$actions_links[] = [
|
||||||
|
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/domains/',
|
||||||
|
'target' => '_blank',
|
||||||
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
|
'class' => 'btn-outline-secondary'
|
||||||
|
];
|
||||||
|
|
||||||
$table_tpl = 'table.html.twig';
|
$table_tpl = 'table.html.twig';
|
||||||
if ($collection->count() == 0) {
|
if ($collection->count() == 0) {
|
||||||
$table_tpl = 'table-note.html.twig';
|
$table_tpl = 'table-note.html.twig';
|
||||||
@@ -101,9 +106,9 @@ if ($page == 'overview' || $page == 'domains') {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
if (isset($result['parentdomainid']) && $result['parentdomainid'] != '0' && $alias_check['count'] == 0) {
|
if (isset($result['parentdomainid']) && $result['parentdomainid'] != '0' && $alias_check['count'] == 0) {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
SubDomains::getLocal($userinfo, $_POST)->delete();
|
SubDomains::getLocal($userinfo, Request::postAll())->delete();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -122,9 +127,9 @@ if ($page == 'overview' || $page == 'domains') {
|
|||||||
}
|
}
|
||||||
} elseif ($action == 'add') {
|
} elseif ($action == 'add') {
|
||||||
if ($userinfo['subdomains_used'] < $userinfo['subdomains'] || $userinfo['subdomains'] == '-1') {
|
if ($userinfo['subdomains_used'] < $userinfo['subdomains'] || $userinfo['subdomains'] == '-1') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
SubDomains::getLocal($userinfo, $_POST)->add();
|
SubDomains::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -239,13 +244,13 @@ if ($page == 'overview' || $page == 'domains') {
|
|||||||
|
|
||||||
if (isset($result['customerid']) && $result['customerid'] == $userinfo['customerid']) {
|
if (isset($result['customerid']) && $result['customerid'] == $userinfo['customerid']) {
|
||||||
|
|
||||||
if ((int) $result['caneditdomain'] == 0) {
|
if ((int)$result['caneditdomain'] == 0) {
|
||||||
Response::standardError('domaincannotbeedited', $result['domain']);
|
Response::standardError('domaincannotbeedited', $result['domain']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
SubDomains::getLocal($userinfo, $_POST)->update();
|
SubDomains::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -390,8 +395,8 @@ if ($page == 'overview' || $page == 'domains') {
|
|||||||
Response::standardError('domains_canteditdomain');
|
Response::standardError('domains_canteditdomain');
|
||||||
}
|
}
|
||||||
} elseif ($action == 'jqSpeciallogfileNote') {
|
} elseif ($action == 'jqSpeciallogfileNote') {
|
||||||
$domainid = intval($_POST['id']);
|
$domainid = intval(Request::post('id'));
|
||||||
$newval = intval($_POST['newval']);
|
$newval = intval(Request::post('newval'));
|
||||||
try {
|
try {
|
||||||
$json_result = SubDomains::getLocal($userinfo, [
|
$json_result = SubDomains::getLocal($userinfo, [
|
||||||
'id' => $domainid
|
'id' => $domainid
|
||||||
|
|||||||
@@ -27,9 +27,11 @@ const AREA = 'customer';
|
|||||||
require __DIR__ . '/lib/init.php';
|
require __DIR__ . '/lib/init.php';
|
||||||
|
|
||||||
use Froxlor\Api\Commands\EmailAccounts;
|
use Froxlor\Api\Commands\EmailAccounts;
|
||||||
|
use Froxlor\Api\Commands\EmailDomains;
|
||||||
use Froxlor\Api\Commands\EmailForwarders;
|
use Froxlor\Api\Commands\EmailForwarders;
|
||||||
use Froxlor\Api\Commands\Emails;
|
use Froxlor\Api\Commands\Emails;
|
||||||
use Froxlor\Api\Commands\EmailDomains;
|
use Froxlor\Cron\Mail\Rspamd;
|
||||||
|
use Froxlor\CurrentUser;
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
use Froxlor\FroxlorLogger;
|
use Froxlor\FroxlorLogger;
|
||||||
use Froxlor\PhpHelper;
|
use Froxlor\PhpHelper;
|
||||||
@@ -41,7 +43,6 @@ use Froxlor\UI\Panel\UI;
|
|||||||
use Froxlor\UI\Request;
|
use Froxlor\UI\Request;
|
||||||
use Froxlor\UI\Response;
|
use Froxlor\UI\Response;
|
||||||
use Froxlor\Validate\Check;
|
use Froxlor\Validate\Check;
|
||||||
use Froxlor\CurrentUser;
|
|
||||||
|
|
||||||
// redirect if this customer page is hidden via settings
|
// redirect if this customer page is hidden via settings
|
||||||
if (Settings::IsInList('panel.customer_hide_options', 'email') || $userinfo['emails'] == 0) {
|
if (Settings::IsInList('panel.customer_hide_options', 'email') || $userinfo['emails'] == 0) {
|
||||||
@@ -67,14 +68,24 @@ if ($page == 'overview' || $page == 'emails') {
|
|||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
UI::view('user/table.html.twig', [
|
$actions_links = [];
|
||||||
'listing' => Listing::format($collection, $emaildomain_list_data, 'emaildomain_list'),
|
if (CurrentUser::canAddResource('emails')) {
|
||||||
'actions_links' => CurrentUser::canAddResource('emails') ? [
|
$actions_links[] = [
|
||||||
[
|
|
||||||
'href' => $linker->getLink(['section' => 'email', 'page' => 'email_domain', 'action' => 'add']),
|
'href' => $linker->getLink(['section' => 'email', 'page' => 'email_domain', 'action' => 'add']),
|
||||||
'label' => lng('emails.emails_add')
|
'label' => lng('emails.emails_add')
|
||||||
]
|
];
|
||||||
] : null,
|
}
|
||||||
|
|
||||||
|
$actions_links[] = [
|
||||||
|
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/emails/',
|
||||||
|
'target' => '_blank',
|
||||||
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
|
'class' => 'btn-outline-secondary'
|
||||||
|
];
|
||||||
|
|
||||||
|
UI::view('user/table.html.twig', [
|
||||||
|
'listing' => Listing::format($collection, $emaildomain_list_data, 'emaildomain_list'),
|
||||||
|
'actions_links' => $actions_links,
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
// only emails for one domain -> show email address listing directly
|
// only emails for one domain -> show email address listing directly
|
||||||
@@ -127,6 +138,12 @@ if ($page == 'email_domain') {
|
|||||||
'label' => lng('emails.emails_add')
|
'label' => lng('emails.emails_add')
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
$actions_links[] = [
|
||||||
|
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/emails/',
|
||||||
|
'target' => '_blank',
|
||||||
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
|
'class' => 'btn-outline-secondary'
|
||||||
|
];
|
||||||
|
|
||||||
UI::view('user/table.html.twig', [
|
UI::view('user/table.html.twig', [
|
||||||
'listing' => Listing::format($collection, $email_list_data, 'email_list'),
|
'listing' => Listing::format($collection, $email_list_data, 'email_list'),
|
||||||
@@ -144,11 +161,11 @@ if ($page == 'email_domain') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['email']) && $result['email'] != '') {
|
if (isset($result['email']) && $result['email'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
Emails::getLocal($userinfo, [
|
Emails::getLocal($userinfo, [
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
'delete_userfiles' => ($_POST['delete_userfiles'] ?? 0)
|
'delete_userfiles' => Request::post('delete_userfiles', 0)
|
||||||
])->delete();
|
])->delete();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
@@ -171,9 +188,9 @@ if ($page == 'email_domain') {
|
|||||||
}
|
}
|
||||||
} elseif ($action == 'add') {
|
} elseif ($action == 'add') {
|
||||||
if ($userinfo['emails_used'] < $userinfo['emails'] || $userinfo['emails'] == '-1') {
|
if ($userinfo['emails_used'] < $userinfo['emails'] || $userinfo['emails'] == '-1') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
$json_result = Emails::getLocal($userinfo, $_POST)->add();
|
$json_result = Emails::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -228,7 +245,16 @@ if ($page == 'email_domain') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['email']) && $result['email'] != '') {
|
if (isset($result['email']) && $result['email'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
|
try {
|
||||||
|
Emails::getLocal($userinfo, [
|
||||||
|
'id' => $id,
|
||||||
|
'spam_tag_level' => Request::post('spam_tag_level', Rspamd::DEFAULT_MARK_LVL),
|
||||||
|
'spam_kill_level' => Request::post('spam_kill_level', Rspamd::DEFAULT_REJECT_LVL)
|
||||||
|
])->update();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Response::dynamicError($e->getMessage());
|
||||||
|
}
|
||||||
Response::redirectTo($filename, [
|
Response::redirectTo($filename, [
|
||||||
'page' => $page
|
'page' => $page
|
||||||
]);
|
]);
|
||||||
@@ -275,6 +301,54 @@ if ($page == 'email_domain') {
|
|||||||
'editid' => $id
|
'editid' => $id
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
} elseif ($action == 'togglebypass' && $id != 0) {
|
||||||
|
try {
|
||||||
|
$json_result = Emails::getLocal($userinfo, [
|
||||||
|
'id' => $id
|
||||||
|
])->get();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Response::dynamicError($e->getMessage());
|
||||||
|
}
|
||||||
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
|
try {
|
||||||
|
Emails::getLocal($userinfo, [
|
||||||
|
'id' => $id,
|
||||||
|
'bypass_spam' => ($result['bypass_spam'] == '1' ? 0 : 1)
|
||||||
|
])->update();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Response::dynamicError($e->getMessage());
|
||||||
|
}
|
||||||
|
Response::redirectTo($filename, [
|
||||||
|
'page' => $page,
|
||||||
|
'domainid' => $email_domainid,
|
||||||
|
'action' => 'edit',
|
||||||
|
'id' => $id,
|
||||||
|
]);
|
||||||
|
} elseif ($action == 'togglegreylist' && $id != 0) {
|
||||||
|
try {
|
||||||
|
$json_result = Emails::getLocal($userinfo, [
|
||||||
|
'id' => $id
|
||||||
|
])->get();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Response::dynamicError($e->getMessage());
|
||||||
|
}
|
||||||
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
|
try {
|
||||||
|
Emails::getLocal($userinfo, [
|
||||||
|
'id' => $id,
|
||||||
|
'policy_greylist' => ($result['policy_greylist'] == '1' ? 0 : 1)
|
||||||
|
])->update();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Response::dynamicError($e->getMessage());
|
||||||
|
}
|
||||||
|
Response::redirectTo($filename, [
|
||||||
|
'page' => $page,
|
||||||
|
'domainid' => $email_domainid,
|
||||||
|
'action' => 'edit',
|
||||||
|
'id' => $id,
|
||||||
|
]);
|
||||||
} elseif ($action == 'togglecatchall' && $id != 0) {
|
} elseif ($action == 'togglecatchall' && $id != 0) {
|
||||||
try {
|
try {
|
||||||
$json_result = Emails::getLocal($userinfo, [
|
$json_result = Emails::getLocal($userinfo, [
|
||||||
@@ -313,9 +387,9 @@ if ($page == 'email_domain') {
|
|||||||
}
|
}
|
||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
EmailAccounts::getLocal($userinfo, $_POST)->add();
|
EmailAccounts::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -384,9 +458,9 @@ if ($page == 'email_domain') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['popaccountid']) && $result['popaccountid'] != '') {
|
if (isset($result['popaccountid']) && $result['popaccountid'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
EmailAccounts::getLocal($userinfo, $_POST)->update();
|
EmailAccounts::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -443,9 +517,9 @@ if ($page == 'email_domain') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['popaccountid']) && $result['popaccountid'] != '') {
|
if (isset($result['popaccountid']) && $result['popaccountid'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
EmailAccounts::getLocal($userinfo, $_POST)->update();
|
EmailAccounts::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -502,9 +576,9 @@ if ($page == 'email_domain') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['popaccountid']) && $result['popaccountid'] != '') {
|
if (isset($result['popaccountid']) && $result['popaccountid'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
EmailAccounts::getLocal($userinfo, $_POST)->delete();
|
EmailAccounts::getLocal($userinfo, Request::postAll())->delete();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -538,9 +612,9 @@ if ($page == 'email_domain') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['email']) && $result['email'] != '') {
|
if (isset($result['email']) && $result['email'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
EmailForwarders::getLocal($userinfo, $_POST)->add();
|
EmailForwarders::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -600,22 +674,15 @@ if ($page == 'email_domain') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['destination']) && $result['destination'] != '') {
|
if (isset($result['destination']) && $result['destination'] != '') {
|
||||||
if (isset($_POST['forwarderid'])) {
|
$forwarderid = Request::any('forwarderid', 0);
|
||||||
$forwarderid = intval($_POST['forwarderid']);
|
|
||||||
} elseif (isset($_GET['forwarderid'])) {
|
|
||||||
$forwarderid = intval($_GET['forwarderid']);
|
|
||||||
} else {
|
|
||||||
$forwarderid = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result['destination'] = explode(' ', $result['destination']);
|
$result['destination'] = explode(' ', $result['destination']);
|
||||||
|
|
||||||
if (isset($result['destination'][$forwarderid]) && $result['email'] != $result['destination'][$forwarderid]) {
|
if (isset($result['destination'][$forwarderid]) && $result['email'] != $result['destination'][$forwarderid]) {
|
||||||
$forwarder = $result['destination'][$forwarderid];
|
$forwarder = $result['destination'][$forwarderid];
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
EmailForwarders::getLocal($userinfo, $_POST)->delete();
|
EmailForwarders::getLocal($userinfo, Request::postAll())->delete();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,14 +68,22 @@ if ($page == 'overview' || $page == 'htpasswds') {
|
|||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
UI::view('user/table.html.twig', [
|
$actions_links = [];
|
||||||
'listing' => Listing::format($collection, $htpasswd_list_data, 'htpasswd_list'),
|
$actions_links[] = [
|
||||||
'actions_links' => [
|
|
||||||
[
|
|
||||||
'href' => $linker->getLink(['section' => 'extras', 'page' => 'htpasswds', 'action' => 'add']),
|
'href' => $linker->getLink(['section' => 'extras', 'page' => 'htpasswds', 'action' => 'add']),
|
||||||
'label' => lng('extras.directoryprotection_add')
|
'label' => lng('extras.directoryprotection_add')
|
||||||
]
|
];
|
||||||
],
|
|
||||||
|
$actions_links[] = [
|
||||||
|
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/extras/',
|
||||||
|
'target' => '_blank',
|
||||||
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
|
'class' => 'btn-outline-secondary'
|
||||||
|
];
|
||||||
|
|
||||||
|
UI::view('user/table.html.twig', [
|
||||||
|
'listing' => Listing::format($collection, $htpasswd_list_data, 'htpasswd_list'),
|
||||||
|
'actions_links' => $actions_links,
|
||||||
'entity_info' => lng('extras.description')
|
'entity_info' => lng('extras.description')
|
||||||
]);
|
]);
|
||||||
} elseif ($action == 'delete' && $id != 0) {
|
} elseif ($action == 'delete' && $id != 0) {
|
||||||
@@ -89,9 +97,9 @@ if ($page == 'overview' || $page == 'htpasswds') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['username']) && $result['username'] != '') {
|
if (isset($result['username']) && $result['username'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
DirProtections::getLocal($userinfo, $_POST)->delete();
|
DirProtections::getLocal($userinfo, Request::postAll())->delete();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -111,9 +119,9 @@ if ($page == 'overview' || $page == 'htpasswds') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($action == 'add') {
|
} elseif ($action == 'add') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
DirProtections::getLocal($userinfo, $_POST)->add();
|
DirProtections::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -141,9 +149,9 @@ if ($page == 'overview' || $page == 'htpasswds') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['username']) && $result['username'] != '') {
|
if (isset($result['username']) && $result['username'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
DirProtections::getLocal($userinfo, $_POST)->update();
|
DirProtections::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -185,14 +193,22 @@ if ($page == 'overview' || $page == 'htpasswds') {
|
|||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
UI::view('user/table.html.twig', [
|
$actions_links = [];
|
||||||
'listing' => Listing::format($collection, $htaccess_list_data, 'htaccess_list'),
|
$actions_links[] = [
|
||||||
'actions_links' => [
|
|
||||||
[
|
|
||||||
'href' => $linker->getLink(['section' => 'extras', 'page' => 'htaccess', 'action' => 'add']),
|
'href' => $linker->getLink(['section' => 'extras', 'page' => 'htaccess', 'action' => 'add']),
|
||||||
'label' => lng('extras.pathoptions_add')
|
'label' => lng('extras.pathoptions_add')
|
||||||
]
|
];
|
||||||
],
|
|
||||||
|
$actions_links[] = [
|
||||||
|
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/extras/',
|
||||||
|
'target' => '_blank',
|
||||||
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
|
'class' => 'btn-outline-secondary'
|
||||||
|
];
|
||||||
|
|
||||||
|
UI::view('user/table.html.twig', [
|
||||||
|
'listing' => Listing::format($collection, $htaccess_list_data, 'htaccess_list'),
|
||||||
|
'actions_links' => $actions_links,
|
||||||
'entity_info' => lng('extras.description')
|
'entity_info' => lng('extras.description')
|
||||||
]);
|
]);
|
||||||
} elseif ($action == 'delete' && $id != 0) {
|
} elseif ($action == 'delete' && $id != 0) {
|
||||||
@@ -206,9 +222,9 @@ if ($page == 'overview' || $page == 'htpasswds') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['customerid']) && $result['customerid'] != '' && $result['customerid'] == $userinfo['customerid']) {
|
if (isset($result['customerid']) && $result['customerid'] != '' && $result['customerid'] == $userinfo['customerid']) {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
DirOptions::getLocal($userinfo, $_POST)->delete();
|
DirOptions::getLocal($userinfo, Request::postAll())->delete();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -224,9 +240,9 @@ if ($page == 'overview' || $page == 'htpasswds') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($action == 'add') {
|
} elseif ($action == 'add') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
DirOptions::getLocal($userinfo, $_POST)->add();
|
DirOptions::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -255,9 +271,9 @@ if ($page == 'overview' || $page == 'htpasswds') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if ((isset($result['customerid'])) && ($result['customerid'] != '') && ($result['customerid'] == $userinfo['customerid'])) {
|
if ((isset($result['customerid'])) && ($result['customerid'] != '') && ($result['customerid'] == $userinfo['customerid'])) {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
DirOptions::getLocal($userinfo, $_POST)->update();
|
DirOptions::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -290,10 +306,10 @@ if ($page == 'overview' || $page == 'htpasswds') {
|
|||||||
|
|
||||||
if (Settings::Get('system.exportenabled') == 1) {
|
if (Settings::Get('system.exportenabled') == 1) {
|
||||||
if ($action == 'abort') {
|
if ($action == 'abort') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
$log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "customer_extras::export - aborted scheduled data export job");
|
$log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "customer_extras::export - aborted scheduled data export job");
|
||||||
try {
|
try {
|
||||||
DataDump::getLocal($userinfo, $_POST)->delete();
|
DataDump::getLocal($userinfo, Request::postAll())->delete();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -320,9 +336,9 @@ if ($page == 'overview' || $page == 'htpasswds') {
|
|||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
DataDump::getLocal($userinfo, $_POST)->add();
|
DataDump::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -331,9 +347,19 @@ if ($page == 'overview' || $page == 'htpasswds') {
|
|||||||
$pathSelect = FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']);
|
$pathSelect = FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']);
|
||||||
$export_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.export.php';
|
$export_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.export.php';
|
||||||
|
|
||||||
|
$actions_links = [
|
||||||
|
[
|
||||||
|
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/extras/',
|
||||||
|
'target' => '_blank',
|
||||||
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
|
'class' => 'btn-outline-secondary'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
UI::view('user/form-datatable.html.twig', [
|
UI::view('user/form-datatable.html.twig', [
|
||||||
'formaction' => $linker->getLink(['section' => 'extras']),
|
'formaction' => $linker->getLink(['section' => 'extras']),
|
||||||
'formdata' => $export_data['export'],
|
'formdata' => $export_data['export'],
|
||||||
|
'actions_links' => $actions_links,
|
||||||
'tabledata' => Listing::format($collection, $export_list_data, 'export_list'),
|
'tabledata' => Listing::format($collection, $export_list_data, 'export_list'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ const AREA = 'customer';
|
|||||||
require __DIR__ . '/lib/init.php';
|
require __DIR__ . '/lib/init.php';
|
||||||
|
|
||||||
use Froxlor\Api\Commands\Ftps as Ftps;
|
use Froxlor\Api\Commands\Ftps as Ftps;
|
||||||
|
use Froxlor\CurrentUser;
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
use Froxlor\FileDir;
|
use Froxlor\FileDir;
|
||||||
use Froxlor\FroxlorLogger;
|
use Froxlor\FroxlorLogger;
|
||||||
@@ -37,7 +38,6 @@ use Froxlor\UI\Listing;
|
|||||||
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\CurrentUser;
|
|
||||||
|
|
||||||
// redirect if this customer page is hidden via settings
|
// redirect if this customer page is hidden via settings
|
||||||
if (Settings::IsInList('panel.customer_hide_options', 'ftp')) {
|
if (Settings::IsInList('panel.customer_hide_options', 'ftp')) {
|
||||||
@@ -57,15 +57,19 @@ if ($page == 'overview' || $page == 'accounts') {
|
|||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
$actions_links = false;
|
$actions_links = [];
|
||||||
if (CurrentUser::canAddResource('ftps')) {
|
if (CurrentUser::canAddResource('ftps')) {
|
||||||
$actions_links = [
|
$actions_links[] = [
|
||||||
[
|
|
||||||
'href' => $linker->getLink(['section' => 'ftp', 'page' => 'accounts', 'action' => 'add']),
|
'href' => $linker->getLink(['section' => 'ftp', 'page' => 'accounts', 'action' => 'add']),
|
||||||
'label' => lng('ftp.account_add')
|
'label' => lng('ftp.account_add')
|
||||||
]
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
$actions_links[] = [
|
||||||
|
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/ftp-accounts/',
|
||||||
|
'target' => '_blank',
|
||||||
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
|
'class' => 'btn-outline-secondary'
|
||||||
|
];
|
||||||
|
|
||||||
UI::view('user/table.html.twig', [
|
UI::view('user/table.html.twig', [
|
||||||
'listing' => Listing::format($collection, $ftp_list_data, 'ftp_list'),
|
'listing' => Listing::format($collection, $ftp_list_data, 'ftp_list'),
|
||||||
@@ -83,9 +87,9 @@ if ($page == 'overview' || $page == 'accounts') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['username']) && $result['username'] != $userinfo['loginname']) {
|
if (isset($result['username']) && $result['username'] != $userinfo['loginname']) {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
Ftps::getLocal($userinfo, $_POST)->delete();
|
Ftps::getLocal($userinfo, Request::postAll())->delete();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -104,9 +108,9 @@ if ($page == 'overview' || $page == 'accounts') {
|
|||||||
}
|
}
|
||||||
} elseif ($action == 'add') {
|
} elseif ($action == 'add') {
|
||||||
if ($userinfo['ftps_used'] < $userinfo['ftps'] || $userinfo['ftps'] == '-1') {
|
if ($userinfo['ftps_used'] < $userinfo['ftps'] || $userinfo['ftps'] == '-1') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
Ftps::getLocal($userinfo, $_POST)->add();
|
Ftps::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -160,9 +164,9 @@ if ($page == 'overview' || $page == 'accounts') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['username']) && $result['username'] != '') {
|
if (isset($result['username']) && $result['username'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
Ftps::getLocal($userinfo, $_POST)->update();
|
Ftps::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ use Froxlor\Api\Commands\Customers as Customers;
|
|||||||
use Froxlor\Cron\TaskId;
|
use Froxlor\Cron\TaskId;
|
||||||
use Froxlor\CurrentUser;
|
use Froxlor\CurrentUser;
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
|
use Froxlor\Database\DbManager;
|
||||||
use Froxlor\Froxlor;
|
use Froxlor\Froxlor;
|
||||||
use Froxlor\FroxlorLogger;
|
use Froxlor\FroxlorLogger;
|
||||||
use Froxlor\Language;
|
use Froxlor\Language;
|
||||||
@@ -37,6 +38,7 @@ use Froxlor\Settings;
|
|||||||
use Froxlor\System\Cronjob;
|
use Froxlor\System\Cronjob;
|
||||||
use Froxlor\System\Crypt;
|
use Froxlor\System\Crypt;
|
||||||
use Froxlor\UI\Panel\UI;
|
use Froxlor\UI\Panel\UI;
|
||||||
|
use Froxlor\UI\Request;
|
||||||
use Froxlor\UI\Response;
|
use Froxlor\UI\Response;
|
||||||
use Froxlor\Validate\Validate;
|
use Froxlor\Validate\Validate;
|
||||||
|
|
||||||
@@ -54,7 +56,7 @@ if ($action == 'logout') {
|
|||||||
$result = $result['switched_user'];
|
$result = $result['switched_user'];
|
||||||
session_regenerate_id(true);
|
session_regenerate_id(true);
|
||||||
CurrentUser::setData($result);
|
CurrentUser::setData($result);
|
||||||
$target = (isset($_GET['target']) ? $_GET['target'] : 'index');
|
$target = Request::get('target', 'index');
|
||||||
$redirect = "admin_" . $target . ".php";
|
$redirect = "admin_" . $target . ".php";
|
||||||
if (!file_exists(Froxlor::getInstallDir() . "/" . $redirect)) {
|
if (!file_exists(Froxlor::getInstallDir() . "/" . $redirect)) {
|
||||||
$redirect = "admin_index.php";
|
$redirect = "admin_index.php";
|
||||||
@@ -115,8 +117,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) {
|
||||||
@@ -140,16 +142,16 @@ if ($page == 'overview') {
|
|||||||
$languages = Language::getLanguages();
|
$languages = Language::getLanguages();
|
||||||
|
|
||||||
if (!empty($_POST)) {
|
if (!empty($_POST)) {
|
||||||
if ($_POST['send'] == 'changepassword') {
|
if (Request::post('send') == 'changepassword') {
|
||||||
$old_password = Validate::validate($_POST['old_password'], 'old password');
|
$old_password = Validate::validate(Request::post('old_password'), 'old password');
|
||||||
|
|
||||||
if (!Crypt::validatePasswordLogin($userinfo, $old_password, TABLE_PANEL_CUSTOMERS, 'customerid')) {
|
if (!Crypt::validatePasswordLogin($userinfo, $old_password, TABLE_PANEL_CUSTOMERS, 'customerid')) {
|
||||||
Response::standardError('oldpasswordnotcorrect');
|
Response::standardError('oldpasswordnotcorrect');
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$new_password = Crypt::validatePassword($_POST['new_password'], 'new password');
|
$new_password = Crypt::validatePassword(Request::post('new_password'), 'new password');
|
||||||
$new_password_confirm = Crypt::validatePassword($_POST['new_password_confirm'], 'new password confirm');
|
$new_password_confirm = Crypt::validatePassword(Request::post('new_password_confirm'), 'new password confirm');
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -184,7 +186,7 @@ if ($page == 'overview') {
|
|||||||
$log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, 'changed password');
|
$log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, 'changed password');
|
||||||
|
|
||||||
// Update ftp password
|
// Update ftp password
|
||||||
if (isset($_POST['change_main_ftp']) && $_POST['change_main_ftp'] == 'true') {
|
if (Request::post('change_main_ftp') == 'true') {
|
||||||
$cryptPassword = Crypt::makeCryptPassword($new_password);
|
$cryptPassword = Crypt::makeCryptPassword($new_password);
|
||||||
$stmt = Database::prepare("UPDATE `" . TABLE_FTP_USERS . "`
|
$stmt = Database::prepare("UPDATE `" . TABLE_FTP_USERS . "`
|
||||||
SET `password` = :password
|
SET `password` = :password
|
||||||
@@ -200,7 +202,7 @@ if ($page == 'overview') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update statistics password
|
// Update statistics password
|
||||||
if (isset($_POST['change_stats']) && $_POST['change_stats'] == 'true') {
|
if (Request::post('change_stats') == 'true') {
|
||||||
$new_stats_password = Crypt::makeCryptPassword($new_password, true);
|
$new_stats_password = Crypt::makeCryptPassword($new_password, true);
|
||||||
|
|
||||||
$stmt = Database::prepare("UPDATE `" . TABLE_PANEL_HTPASSWDS . "`
|
$stmt = Database::prepare("UPDATE `" . TABLE_PANEL_HTPASSWDS . "`
|
||||||
@@ -216,11 +218,32 @@ if ($page == 'overview') {
|
|||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update global myqsl user password
|
||||||
|
if ($userinfo['mysqls'] != 0 && Request::post('change_global_mysql') == 'true') {
|
||||||
|
$allowed_mysqlservers = json_decode($userinfo['allowed_mysqlserver'] ?? '[]', true);
|
||||||
|
foreach ($allowed_mysqlservers as $dbserver) {
|
||||||
|
// require privileged access for target db-server
|
||||||
|
Database::needRoot(true, $dbserver, false);
|
||||||
|
// get DbManager
|
||||||
|
$dbm = new DbManager($log);
|
||||||
|
// give permission to the user on every access-host we have
|
||||||
|
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
|
||||||
|
if ($dbm->getManager()->userExistsOnHost($userinfo['loginname'], $mysql_access_host)) {
|
||||||
|
$dbm->getManager()->grantPrivilegesTo($userinfo['loginname'], $new_password, $mysql_access_host, false, true);
|
||||||
|
} else {
|
||||||
|
// create global mysql user if not exists
|
||||||
|
$dbm->getManager()->grantPrivilegesTo($userinfo['loginname'], $new_password, $mysql_access_host, false, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$dbm->getManager()->flushPrivileges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Response::redirectTo($filename);
|
Response::redirectTo($filename);
|
||||||
}
|
}
|
||||||
} elseif ($_POST['send'] == 'changetheme') {
|
} elseif (Request::post('send') == 'changetheme') {
|
||||||
if (Settings::Get('panel.allow_theme_change_customer') == 1) {
|
if (Settings::Get('panel.allow_theme_change_customer') == 1) {
|
||||||
$theme = Validate::validate($_POST['theme'], 'theme');
|
$theme = Validate::validate(Request::post('theme'), 'theme');
|
||||||
try {
|
try {
|
||||||
Customers::getLocal($userinfo, [
|
Customers::getLocal($userinfo, [
|
||||||
'id' => $userinfo['customerid'],
|
'id' => $userinfo['customerid'],
|
||||||
@@ -233,8 +256,8 @@ if ($page == 'overview') {
|
|||||||
$log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "changed default theme to '" . $theme . "'");
|
$log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "changed default theme to '" . $theme . "'");
|
||||||
}
|
}
|
||||||
Response::redirectTo($filename);
|
Response::redirectTo($filename);
|
||||||
} elseif ($_POST['send'] == 'changelanguage') {
|
} elseif (Request::post('send') == 'changelanguage') {
|
||||||
$def_language = Validate::validate($_POST['def_language'], 'default language');
|
$def_language = Validate::validate(Request::post('def_language'), 'default language');
|
||||||
if (isset($languages[$def_language])) {
|
if (isset($languages[$def_language])) {
|
||||||
try {
|
try {
|
||||||
Customers::getLocal($userinfo, [
|
Customers::getLocal($userinfo, [
|
||||||
|
|||||||
@@ -28,16 +28,18 @@ require __DIR__ . '/lib/init.php';
|
|||||||
|
|
||||||
use Froxlor\Api\Commands\Mysqls;
|
use Froxlor\Api\Commands\Mysqls;
|
||||||
use Froxlor\Api\Commands\MysqlServer;
|
use Froxlor\Api\Commands\MysqlServer;
|
||||||
|
use Froxlor\CurrentUser;
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
|
use Froxlor\Database\DbManager;
|
||||||
use Froxlor\FroxlorLogger;
|
use Froxlor\FroxlorLogger;
|
||||||
use Froxlor\Settings;
|
use Froxlor\Settings;
|
||||||
|
use Froxlor\System\Crypt;
|
||||||
use Froxlor\UI\Collection;
|
use Froxlor\UI\Collection;
|
||||||
use Froxlor\UI\HTML;
|
use Froxlor\UI\HTML;
|
||||||
use Froxlor\UI\Listing;
|
use Froxlor\UI\Listing;
|
||||||
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\CurrentUser;
|
|
||||||
|
|
||||||
// redirect if this customer page is hidden via settings or no resources given
|
// redirect if this customer page is hidden via settings or no resources given
|
||||||
if (Settings::IsInList('panel.customer_hide_options', 'mysql') || $userinfo['mysqls'] == 0) {
|
if (Settings::IsInList('panel.customer_hide_options', 'mysql') || $userinfo['mysqls'] == 0) {
|
||||||
@@ -66,20 +68,40 @@ if ($page == 'overview' || $page == 'mysqls') {
|
|||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
$actions_links = false;
|
$actions_links = [];
|
||||||
if (CurrentUser::canAddResource('mysqls')) {
|
if (CurrentUser::canAddResource('mysqls')) {
|
||||||
$actions_links = [
|
$actions_links[] = [
|
||||||
[
|
|
||||||
'href' => $linker->getLink(['section' => 'mysql', 'page' => 'mysqls', 'action' => 'add']),
|
'href' => $linker->getLink(['section' => 'mysql', 'page' => 'mysqls', 'action' => 'add']),
|
||||||
'label' => lng('mysql.database_create')
|
'label' => lng('mysql.database_create')
|
||||||
]
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
UI::view('user/table.html.twig', [
|
$view = 'user/table.html.twig';
|
||||||
|
if ($collection->count() > 0) {
|
||||||
|
$view = 'user/table-note.html.twig';
|
||||||
|
|
||||||
|
$actions_links[] = [
|
||||||
|
'href' => $linker->getLink(['section' => 'mysql', 'page' => 'mysqls', 'action' => 'global_user']),
|
||||||
|
'label' => lng('mysql.edit_global_user'),
|
||||||
|
'icon' => 'fa-solid fa-user-tie',
|
||||||
|
'class' => 'btn-outline-secondary'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$actions_links[] = [
|
||||||
|
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/databases/',
|
||||||
|
'target' => '_blank',
|
||||||
|
'icon' => 'fa-solid fa-circle-info',
|
||||||
|
'class' => 'btn-outline-secondary'
|
||||||
|
];
|
||||||
|
|
||||||
|
UI::view($view, [
|
||||||
'listing' => Listing::format($collection, $mysql_list_data, 'mysql_list'),
|
'listing' => Listing::format($collection, $mysql_list_data, 'mysql_list'),
|
||||||
'actions_links' => $actions_links,
|
'actions_links' => $actions_links,
|
||||||
'entity_info' => lng('mysql.description')
|
'entity_info' => lng('mysql.description'),
|
||||||
|
// alert-box
|
||||||
|
'type' => 'info',
|
||||||
|
'alert_msg' => lng('mysql.globaluserinfo', [$userinfo['loginname']]),
|
||||||
]);
|
]);
|
||||||
} elseif ($action == 'delete' && $id != 0) {
|
} elseif ($action == 'delete' && $id != 0) {
|
||||||
try {
|
try {
|
||||||
@@ -101,9 +123,9 @@ if ($page == 'overview' || $page == 'mysqls') {
|
|||||||
$result['dbserver'] = 0;
|
$result['dbserver'] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
Mysqls::getLocal($userinfo, $_POST)->delete();
|
Mysqls::getLocal($userinfo, Request::postAll())->delete();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -124,9 +146,9 @@ if ($page == 'overview' || $page == 'mysqls') {
|
|||||||
}
|
}
|
||||||
} elseif ($action == 'add') {
|
} elseif ($action == 'add') {
|
||||||
if ($userinfo['mysqls_used'] < $userinfo['mysqls'] || $userinfo['mysqls'] == '-1') {
|
if ($userinfo['mysqls_used'] < $userinfo['mysqls'] || $userinfo['mysqls'] == '-1') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
Mysqls::getLocal($userinfo, $_POST)->add();
|
Mysqls::getLocal($userinfo, Request::postAll())->add();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -164,9 +186,9 @@ if ($page == 'overview' || $page == 'mysqls') {
|
|||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
|
|
||||||
if (isset($result['databasename']) && $result['databasename'] != '') {
|
if (isset($result['databasename']) && $result['databasename'] != '') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
try {
|
try {
|
||||||
$json_result = Mysqls::getLocal($userinfo, $_POST)->update();
|
$json_result = Mysqls::getLocal($userinfo, Request::postAll())->update();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::dynamicError($e->getMessage());
|
Response::dynamicError($e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -179,7 +201,7 @@ if ($page == 'overview' || $page == 'mysqls') {
|
|||||||
$result_json = MysqlServer::getLocal($userinfo)->listing();
|
$result_json = MysqlServer::getLocal($userinfo)->listing();
|
||||||
$result_decoded = json_decode($result_json, true)['data']['list'];
|
$result_decoded = json_decode($result_json, true)['data']['list'];
|
||||||
foreach ($result_decoded as $dbserver => $dbdata) {
|
foreach ($result_decoded as $dbserver => $dbdata) {
|
||||||
$mysql_servers[$dbserver] = $dbdata['caption'] . ' (' . $dbdata['host'] . (isset($dbdata['port']) && !empty($dbdata['port']) ? ':' . $dbdata['port'] : '').')';
|
$mysql_servers[$dbserver] = $dbdata['caption'] . ' (' . $dbdata['host'] . (isset($dbdata['port']) && !empty($dbdata['port']) ? ':' . $dbdata['port'] : '') . ')';
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
/* just none */
|
/* just none */
|
||||||
@@ -194,5 +216,45 @@ if ($page == 'overview' || $page == 'mysqls') {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} elseif ($action == 'global_user') {
|
||||||
|
|
||||||
|
$allowed_mysqlservers = json_decode($userinfo['allowed_mysqlserver'] ?? '[]', true);
|
||||||
|
if ($userinfo['mysqls'] == 0 || empty($allowed_mysqlservers)) {
|
||||||
|
Response::dynamicError('No permission');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Request::post('send') == 'send') {
|
||||||
|
|
||||||
|
$new_password = Crypt::validatePassword(Request::post('mysql_password'));
|
||||||
|
foreach ($allowed_mysqlservers as $dbserver) {
|
||||||
|
// require privileged access for target db-server
|
||||||
|
Database::needRoot(true, $dbserver, false);
|
||||||
|
// get DbManager
|
||||||
|
$dbm = new DbManager($log);
|
||||||
|
// give permission to the user on every access-host we have
|
||||||
|
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
|
||||||
|
if ($dbm->getManager()->userExistsOnHost($userinfo['loginname'], $mysql_access_host)) {
|
||||||
|
// update password
|
||||||
|
$dbm->getManager()->grantPrivilegesTo($userinfo['loginname'], $new_password, $mysql_access_host, false, true, true);
|
||||||
|
} else {
|
||||||
|
// create missing user
|
||||||
|
$dbm->getManager()->grantPrivilegesTo($userinfo['loginname'], $new_password, $mysql_access_host, false, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$dbm->getManager()->flushPrivileges();
|
||||||
|
}
|
||||||
|
|
||||||
|
Response::redirectTo($filename, [
|
||||||
|
'page' => 'overview'
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
$mysql_global_user_data = include_once dirname(__FILE__) . '/lib/formfields/customer/mysql/formfield.mysql_global_user.php';
|
||||||
|
|
||||||
|
UI::view('user/form.html.twig', [
|
||||||
|
'formaction' => $linker->getLink(['section' => 'mysql', 'page' => 'mysqls', 'action' => 'global_user']),
|
||||||
|
'formdata' => $mysql_global_user_data['mysql_global_user'],
|
||||||
|
'editid' => $id
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ if (!defined('AREA')) {
|
|||||||
|
|
||||||
use Froxlor\Api\Commands\DomainZones;
|
use Froxlor\Api\Commands\DomainZones;
|
||||||
use Froxlor\Dns\Dns;
|
use Froxlor\Dns\Dns;
|
||||||
|
use Froxlor\Settings;
|
||||||
use Froxlor\UI\Collection;
|
use Froxlor\UI\Collection;
|
||||||
use Froxlor\UI\HTML;
|
use Froxlor\UI\HTML;
|
||||||
use Froxlor\UI\Listing;
|
use Froxlor\UI\Listing;
|
||||||
@@ -42,11 +43,11 @@ use Froxlor\UI\Response;
|
|||||||
|
|
||||||
$domain_id = (int)Request::any('domain_id');
|
$domain_id = (int)Request::any('domain_id');
|
||||||
|
|
||||||
$record = isset($_POST['dns_record']) ? trim($_POST['dns_record']) : null;
|
$record = Request::post('dns_record');
|
||||||
$type = isset($_POST['dns_type']) ? $_POST['dns_type'] : 'A';
|
$type = Request::post('dns_type', 'A');
|
||||||
$prio = isset($_POST['dns_mxp']) ? (int)$_POST['dns_mxp'] : null;
|
$prio = Request::post('dns_mxp');
|
||||||
$content = isset($_POST['dns_content']) ? trim($_POST['dns_content']) : null;
|
$content = Request::post('dns_content');
|
||||||
$ttl = isset($_POST['dns_ttl']) ? (int)$_POST['dns_ttl'] : 18000;
|
$ttl = (int)Request::post('dns_ttl', Settings::get('system.defaultttl'));
|
||||||
|
|
||||||
// get domain-name
|
// get domain-name
|
||||||
$domain = Dns::getAllowedDomainEntry($domain_id, AREA, $userinfo);
|
$domain = Dns::getAllowedDomainEntry($domain_id, AREA, $userinfo);
|
||||||
@@ -71,7 +72,7 @@ if ($action == 'add_record' && !empty($_POST)) {
|
|||||||
$errors = str_replace("\n", "<br>", $e->getMessage());
|
$errors = str_replace("\n", "<br>", $e->getMessage());
|
||||||
}
|
}
|
||||||
} elseif ($action == 'delete') {
|
} elseif ($action == 'delete') {
|
||||||
$entry_id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
$entry_id = (int)Request::get('id', 0);
|
||||||
HTML::askYesNo('dnsentry_reallydelete', $filename, [
|
HTML::askYesNo('dnsentry_reallydelete', $filename, [
|
||||||
'id' => $entry_id,
|
'id' => $entry_id,
|
||||||
'domain_id' => $domain_id,
|
'domain_id' => $domain_id,
|
||||||
@@ -82,9 +83,9 @@ if ($action == 'add_record' && !empty($_POST)) {
|
|||||||
'page' => $page,
|
'page' => $page,
|
||||||
'domain_id' => $domain_id
|
'domain_id' => $domain_id
|
||||||
]);
|
]);
|
||||||
} elseif (isset($_POST['send']) && $_POST['send'] == 'send' && $action == 'deletesure' && !empty($_POST)) {
|
} elseif (Request::post('send') == 'send' && $action == 'deletesure' && !empty($_POST)) {
|
||||||
$entry_id = isset($_POST['id']) ? (int)$_POST['id'] : 0;
|
$entry_id = (int)Request::post('id', 0);
|
||||||
$domain_id = isset($_POST['domain_id']) ? (int)$_POST['domain_id'] : 0;
|
$domain_id = (int)Request::post('domain_id', 0);
|
||||||
// remove entry
|
// remove entry
|
||||||
if ($entry_id > 0 && $domain_id > 0) {
|
if ($entry_id > 0 && $domain_id > 0) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ if (!empty($errid)) {
|
|||||||
$mail_html = nl2br($mail_body);
|
$mail_html = nl2br($mail_body);
|
||||||
|
|
||||||
// send actual report to dev-team
|
// send actual report to dev-team
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (Request::post('send') == 'send') {
|
||||||
// send mail and say thanks
|
// send mail and say thanks
|
||||||
$_mailerror = false;
|
$_mailerror = false;
|
||||||
try {
|
try {
|
||||||
|
|||||||
207
index.php
207
index.php
@@ -54,7 +54,7 @@ if ($action == '2fa_entercode') {
|
|||||||
Response::redirectTo('index.php');
|
Response::redirectTo('index.php');
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
$smessage = isset($_GET['showmessage']) ? (int)$_GET['showmessage'] : 0;
|
$smessage = (int)Request::get('showmessage', 0);
|
||||||
$message = "";
|
$message = "";
|
||||||
if ($smessage > 0) {
|
if ($smessage > 0) {
|
||||||
$message = lng('error.2fa_wrongcode');
|
$message = lng('error.2fa_wrongcode');
|
||||||
@@ -62,6 +62,7 @@ if ($action == '2fa_entercode') {
|
|||||||
// show template to enter code
|
// show template to enter code
|
||||||
UI::view('login/enter2fa.html.twig', [
|
UI::view('login/enter2fa.html.twig', [
|
||||||
'pagetitle' => lng('login.2fa'),
|
'pagetitle' => lng('login.2fa'),
|
||||||
|
'remember_me' => (Settings::Get('panel.db_version') >= 202407200) ? true : false,
|
||||||
'message' => $message
|
'message' => $message
|
||||||
]);
|
]);
|
||||||
} elseif ($action == '2fa_verify') {
|
} elseif ($action == '2fa_verify') {
|
||||||
@@ -71,30 +72,31 @@ if ($action == '2fa_entercode') {
|
|||||||
Response::redirectTo('index.php');
|
Response::redirectTo('index.php');
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
$code = isset($_POST['2fa_code']) ? $_POST['2fa_code'] : null;
|
$code = Request::post('2fa_code');
|
||||||
|
$remember = Request::post('2fa_remember');
|
||||||
// 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]);
|
||||||
|
// 60sec discrepancy (possible slow email delivery)
|
||||||
|
$result = $tfa->verifyCode($userinfo_code['data_2fa'], $code, 60);
|
||||||
|
} 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)) {
|
||||||
@@ -106,13 +108,6 @@ if ($action == '2fa_entercode') {
|
|||||||
$userinfo['adminsession'] = $isadmin;
|
$userinfo['adminsession'] = $isadmin;
|
||||||
$userinfo['userid'] = $uid;
|
$userinfo['userid'] = $uid;
|
||||||
|
|
||||||
// if not successful somehow - start again
|
|
||||||
if (!finishLogin($userinfo)) {
|
|
||||||
Response::redirectTo('index.php', [
|
|
||||||
'showmessage' => '2'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// when using email-2fa, remove the one-time-code
|
// when using email-2fa, remove the one-time-code
|
||||||
if ($userinfo['type_2fa'] == '1') {
|
if ($userinfo['type_2fa'] == '1') {
|
||||||
$del_stmt = Database::prepare("UPDATE " . $table . " SET `data_2fa` = '' WHERE `" . $field . "` = :uid");
|
$del_stmt = Database::prepare("UPDATE " . $table . " SET `data_2fa` = '' WHERE `" . $field . "` = :uid");
|
||||||
@@ -120,6 +115,42 @@ if ($action == '2fa_entercode') {
|
|||||||
'uid' => $uid
|
'uid' => $uid
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// when remember is activated, set the cookie
|
||||||
|
if ($remember) {
|
||||||
|
$selector = base64_encode(Froxlor::genSessionId(9));
|
||||||
|
$authenticator = Froxlor::genSessionId(33);
|
||||||
|
$valid_until = time()+60*60*24*30;
|
||||||
|
$ins_stmt = Database::prepare("
|
||||||
|
INSERT INTO `".TABLE_PANEL_2FA_TOKENS."` SET
|
||||||
|
`selector` = :selector,
|
||||||
|
`token` = :authenticator,
|
||||||
|
`userid` = :userid,
|
||||||
|
`valid_until` = :valid_until
|
||||||
|
");
|
||||||
|
Database::pexecute($ins_stmt, [
|
||||||
|
'selector' => $selector,
|
||||||
|
'authenticator' => hash('sha256', $authenticator),
|
||||||
|
'userid' => $uid,
|
||||||
|
'valid_until' => $valid_until
|
||||||
|
]);
|
||||||
|
$cookie_params = [
|
||||||
|
'expires' => $valid_until, // 30 days
|
||||||
|
'path' => '/',
|
||||||
|
'domain' => UI::getCookieHost(),
|
||||||
|
'secure' => UI::requestIsHttps(),
|
||||||
|
'httponly' => true,
|
||||||
|
'samesite' => 'Strict'
|
||||||
|
];
|
||||||
|
setcookie('frx_2fa_remember', $selector.':'.base64_encode($authenticator), $cookie_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if not successful somehow - start again
|
||||||
|
if (!finishLogin($userinfo)) {
|
||||||
|
Response::redirectTo('index.php', [
|
||||||
|
'showmessage' => '2'
|
||||||
|
]);
|
||||||
|
}
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
// wrong 2fa code - treat like "wrong password"
|
// wrong 2fa code - treat like "wrong password"
|
||||||
@@ -163,30 +194,41 @@ if ($action == '2fa_entercode') {
|
|||||||
exit();
|
exit();
|
||||||
} elseif ($action == 'login') {
|
} elseif ($action == 'login') {
|
||||||
if (!empty($_POST)) {
|
if (!empty($_POST)) {
|
||||||
$loginname = Validate::validate($_POST['loginname'], 'loginname');
|
$loginname = Validate::validate(Request::post('loginname'), 'loginname');
|
||||||
$password = Validate::validate($_POST['password'], 'password');
|
$password = Validate::validate(Request::post('password'), 'password');
|
||||||
|
|
||||||
$stmt = Database::prepare("SELECT `loginname` AS `customer` FROM `" . TABLE_PANEL_CUSTOMERS . "`
|
$select_additional = '';
|
||||||
WHERE `loginname`= :loginname");
|
if (Settings::Get('panel.db_version') >= 202312230) {
|
||||||
|
$select_additional = ' AND `gui_access` = 1';
|
||||||
|
}
|
||||||
|
$stmt = Database::prepare("
|
||||||
|
SELECT `loginname` AS `customer`
|
||||||
|
FROM `" . TABLE_PANEL_CUSTOMERS . "`
|
||||||
|
WHERE `loginname`= :loginname" .
|
||||||
|
$select_additional
|
||||||
|
);
|
||||||
Database::pexecute($stmt, [
|
Database::pexecute($stmt, [
|
||||||
"loginname" => $loginname
|
"loginname" => $loginname
|
||||||
]);
|
]);
|
||||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
$is_admin = false;
|
||||||
|
$table = "";
|
||||||
if ($row && $row['customer'] == $loginname) {
|
if ($row && $row['customer'] == $loginname) {
|
||||||
$table = "`" . TABLE_PANEL_CUSTOMERS . "`";
|
$table = "`" . TABLE_PANEL_CUSTOMERS . "`";
|
||||||
$uid = 'customerid';
|
$uid = 'customerid';
|
||||||
$adminsession = '0';
|
$adminsession = '0';
|
||||||
$is_admin = false;
|
|
||||||
} else {
|
} else {
|
||||||
$is_admin = true;
|
|
||||||
if ((int)Settings::Get('login.domain_login') == 1) {
|
if ((int)Settings::Get('login.domain_login') == 1) {
|
||||||
$domainname = $idna_convert->encode(preg_replace([
|
$domainname = $idna_convert->encode(preg_replace([
|
||||||
'/\:(\d)+$/',
|
'/\:(\d)+$/',
|
||||||
'/^https?\:\/\//'
|
'/^https?\:\/\//'
|
||||||
], '', $loginname));
|
], '', $loginname));
|
||||||
$stmt = Database::prepare("SELECT `customerid` FROM `" . TABLE_PANEL_DOMAINS . "`
|
$stmt = Database::prepare("
|
||||||
WHERE `domain` = :domain");
|
SELECT `customerid`
|
||||||
|
FROM `" . TABLE_PANEL_DOMAINS . "`
|
||||||
|
WHERE `domain` = :domain
|
||||||
|
");
|
||||||
Database::pexecute($stmt, [
|
Database::pexecute($stmt, [
|
||||||
"domain" => $domainname
|
"domain" => $domainname
|
||||||
]);
|
]);
|
||||||
@@ -195,8 +237,11 @@ if ($action == '2fa_entercode') {
|
|||||||
if (isset($row2['customerid']) && $row2['customerid'] > 0) {
|
if (isset($row2['customerid']) && $row2['customerid'] > 0) {
|
||||||
$loginname = Customer::getCustomerDetail($row2['customerid'], 'loginname');
|
$loginname = Customer::getCustomerDetail($row2['customerid'], 'loginname');
|
||||||
if ($loginname !== false) {
|
if ($loginname !== false) {
|
||||||
$stmt = Database::prepare("SELECT `loginname` AS `customer` FROM `" . TABLE_PANEL_CUSTOMERS . "`
|
$stmt = Database::prepare("
|
||||||
WHERE `loginname`= :loginname");
|
SELECT `loginname` AS `customer`
|
||||||
|
FROM `" . TABLE_PANEL_CUSTOMERS . "`
|
||||||
|
WHERE `loginname`= :loginname
|
||||||
|
");
|
||||||
Database::pexecute($stmt, [
|
Database::pexecute($stmt, [
|
||||||
"loginname" => $loginname
|
"loginname" => $loginname
|
||||||
]);
|
]);
|
||||||
@@ -205,13 +250,17 @@ if ($action == '2fa_entercode') {
|
|||||||
$table = "`" . TABLE_PANEL_CUSTOMERS . "`";
|
$table = "`" . TABLE_PANEL_CUSTOMERS . "`";
|
||||||
$uid = 'customerid';
|
$uid = 'customerid';
|
||||||
$adminsession = '0';
|
$adminsession = '0';
|
||||||
$is_admin = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (empty($table)) {
|
||||||
|
// try login as admin of no customer-login method worked
|
||||||
|
$is_admin = true;
|
||||||
|
}
|
||||||
|
|
||||||
if ((Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) && $is_admin == false) {
|
if ((Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) && $is_admin == false) {
|
||||||
Response::redirectTo('index.php');
|
Response::redirectTo('index.php');
|
||||||
exit();
|
exit();
|
||||||
@@ -219,9 +268,11 @@ if ($action == '2fa_entercode') {
|
|||||||
|
|
||||||
if ($is_admin) {
|
if ($is_admin) {
|
||||||
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
|
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
|
||||||
$stmt = Database::prepare("SELECT `loginname` AS `admin` FROM `" . TABLE_PANEL_ADMINS . "`
|
$stmt = Database::prepare("
|
||||||
|
SELECT `loginname` AS `admin` FROM `" . TABLE_PANEL_ADMINS . "`
|
||||||
WHERE `loginname`= :loginname
|
WHERE `loginname`= :loginname
|
||||||
AND `change_serversettings` = '1'");
|
AND `change_serversettings` = '1'
|
||||||
|
");
|
||||||
Database::pexecute($stmt, [
|
Database::pexecute($stmt, [
|
||||||
"loginname" => $loginname
|
"loginname" => $loginname
|
||||||
]);
|
]);
|
||||||
@@ -232,8 +283,16 @@ if ($action == '2fa_entercode') {
|
|||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$stmt = Database::prepare("SELECT `loginname` AS `admin` FROM `" . TABLE_PANEL_ADMINS . "`
|
$select_additional = '';
|
||||||
WHERE `loginname`= :loginname");
|
if (Settings::Get('panel.db_version') >= 202312230) {
|
||||||
|
$select_additional = ' AND `gui_access` = 1';
|
||||||
|
}
|
||||||
|
$stmt = Database::prepare("
|
||||||
|
SELECT `loginname` AS `admin`
|
||||||
|
FROM `" . TABLE_PANEL_ADMINS . "`
|
||||||
|
WHERE `loginname`= :loginname" .
|
||||||
|
$select_additional
|
||||||
|
);
|
||||||
Database::pexecute($stmt, [
|
Database::pexecute($stmt, [
|
||||||
"loginname" => $loginname
|
"loginname" => $loginname
|
||||||
]);
|
]);
|
||||||
@@ -249,7 +308,7 @@ if ($action == '2fa_entercode') {
|
|||||||
$rstlog = FroxlorLogger::getInstanceOf([
|
$rstlog = FroxlorLogger::getInstanceOf([
|
||||||
'loginname' => $_SERVER['REMOTE_ADDR']
|
'loginname' => $_SERVER['REMOTE_ADDR']
|
||||||
]);
|
]);
|
||||||
$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "Unknown user '" . $loginname . "' tried to login.");
|
$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "Unknown user tried to login.");
|
||||||
|
|
||||||
Response::redirectTo('index.php', [
|
Response::redirectTo('index.php', [
|
||||||
'showmessage' => '2'
|
'showmessage' => '2'
|
||||||
@@ -258,8 +317,9 @@ if ($action == '2fa_entercode') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$userinfo_stmt = Database::prepare("SELECT * FROM $table
|
$userinfo_stmt = Database::prepare("
|
||||||
WHERE `loginname`= :loginname");
|
SELECT * FROM $table WHERE `loginname`= :loginname
|
||||||
|
");
|
||||||
Database::pexecute($userinfo_stmt, [
|
Database::pexecute($userinfo_stmt, [
|
||||||
"loginname" => $loginname
|
"loginname" => $loginname
|
||||||
]);
|
]);
|
||||||
@@ -282,9 +342,11 @@ if ($action == '2fa_entercode') {
|
|||||||
} else {
|
} else {
|
||||||
// login correct
|
// login correct
|
||||||
// reset loginfail_counter, set lastlogin_succ
|
// reset loginfail_counter, set lastlogin_succ
|
||||||
$stmt = Database::prepare("UPDATE $table
|
$stmt = Database::prepare("
|
||||||
|
UPDATE $table
|
||||||
SET `lastlogin_succ`= :lastlogin_succ, `loginfail_count`='0'
|
SET `lastlogin_succ`= :lastlogin_succ, `loginfail_count`='0'
|
||||||
WHERE `$uid`= :uid");
|
WHERE `$uid`= :uid
|
||||||
|
");
|
||||||
Database::pexecute($stmt, [
|
Database::pexecute($stmt, [
|
||||||
"lastlogin_succ" => time(),
|
"lastlogin_succ" => time(),
|
||||||
"uid" => $userinfo[$uid]
|
"uid" => $userinfo[$uid]
|
||||||
@@ -294,9 +356,11 @@ if ($action == '2fa_entercode') {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// login incorrect
|
// login incorrect
|
||||||
$stmt = Database::prepare("UPDATE $table
|
$stmt = Database::prepare("
|
||||||
|
UPDATE $table
|
||||||
SET `lastlogin_fail`= :lastlogin_fail, `loginfail_count`=`loginfail_count`+1
|
SET `lastlogin_fail`= :lastlogin_fail, `loginfail_count`=`loginfail_count`+1
|
||||||
WHERE `$uid`= :uid");
|
WHERE `$uid`= :uid
|
||||||
|
");
|
||||||
Database::pexecute($stmt, [
|
Database::pexecute($stmt, [
|
||||||
"lastlogin_fail" => time(),
|
"lastlogin_fail" => time(),
|
||||||
"uid" => $userinfo[$uid]
|
"uid" => $userinfo[$uid]
|
||||||
@@ -306,7 +370,7 @@ if ($action == '2fa_entercode') {
|
|||||||
$rstlog = FroxlorLogger::getInstanceOf([
|
$rstlog = FroxlorLogger::getInstanceOf([
|
||||||
'loginname' => $_SERVER['REMOTE_ADDR']
|
'loginname' => $_SERVER['REMOTE_ADDR']
|
||||||
]);
|
]);
|
||||||
$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "User '" . $loginname . "' tried to login with wrong password.");
|
$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "User tried to login with wrong password.");
|
||||||
|
|
||||||
unset($userinfo);
|
unset($userinfo);
|
||||||
Response::redirectTo('index.php', [
|
Response::redirectTo('index.php', [
|
||||||
@@ -317,6 +381,25 @@ if ($action == '2fa_entercode') {
|
|||||||
|
|
||||||
// 2FA activated
|
// 2FA activated
|
||||||
if (Settings::Get('2fa.enabled') == '1' && $userinfo['type_2fa'] > 0) {
|
if (Settings::Get('2fa.enabled') == '1' && $userinfo['type_2fa'] > 0) {
|
||||||
|
|
||||||
|
// check for remember cookie
|
||||||
|
if (!empty($_COOKIE['frx_2fa_remember'])) {
|
||||||
|
list($selector, $authenticator) = explode(':', $_COOKIE['frx_2fa_remember']);
|
||||||
|
$sel_stmt = Database::prepare("SELECT `token` FROM `".TABLE_PANEL_2FA_TOKENS."` WHERE `selector` = :selector AND `userid` = :uid AND `valid_until` >= UNIX_TIMESTAMP()");
|
||||||
|
$token_check = Database::pexecute_first($sel_stmt, ['selector' => $selector, 'uid' => $userinfo[$uid]]);
|
||||||
|
if ($token_check && hash_equals($token_check['token'], hash('sha256', base64_decode($authenticator)))) {
|
||||||
|
if (!finishLogin($userinfo)) {
|
||||||
|
Response::redirectTo('index.php', [
|
||||||
|
'showmessage' => '2'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
// not found or invalid, this cookie is useless, get rid of it
|
||||||
|
unset($_COOKIE['frx_2fa_remember']);
|
||||||
|
setcookie('frx_2fa_remember', "", time()-3600);
|
||||||
|
}
|
||||||
|
|
||||||
// redirect to code-enter-page
|
// redirect to code-enter-page
|
||||||
$_SESSION['secret_2fa'] = ($userinfo['type_2fa'] == 2 ? $userinfo['data_2fa'] : 'email');
|
$_SESSION['secret_2fa'] = ($userinfo['type_2fa'] == 2 ? $userinfo['data_2fa'] : 'email');
|
||||||
$_SESSION['uid_2fa'] = $userinfo[$uid];
|
$_SESSION['uid_2fa'] = $userinfo[$uid];
|
||||||
@@ -327,11 +410,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
|
||||||
@@ -383,7 +467,7 @@ if ($action == '2fa_entercode') {
|
|||||||
}
|
}
|
||||||
exit();
|
exit();
|
||||||
} else {
|
} else {
|
||||||
$smessage = isset($_GET['showmessage']) ? (int)$_GET['showmessage'] : 0;
|
$smessage = (int)Request::get('showmessage', 0);
|
||||||
$message = '';
|
$message = '';
|
||||||
$successmessage = '';
|
$successmessage = '';
|
||||||
|
|
||||||
@@ -420,25 +504,20 @@ if ($action == '2fa_entercode') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pass the last used page if needed
|
// Pass the last used page if needed
|
||||||
$lastscript = "";
|
$lastscript = Request::any('script', '');
|
||||||
if (isset($_REQUEST['script']) && $_REQUEST['script'] != "") {
|
if (!empty($lastscript)) {
|
||||||
$lastscript = $_REQUEST['script'];
|
|
||||||
$lastscript = str_replace("..", "", $lastscript);
|
$lastscript = str_replace("..", "", $lastscript);
|
||||||
$lastscript = htmlspecialchars($lastscript, ENT_QUOTES);
|
$lastscript = htmlspecialchars($lastscript, ENT_QUOTES);
|
||||||
|
|
||||||
if (!file_exists(__DIR__ . "/" . $lastscript)) {
|
if (file_exists(__DIR__ . "/" . $lastscript)) {
|
||||||
|
$_SESSION['lastscript'] = $lastscript;
|
||||||
|
} else {
|
||||||
$lastscript = "";
|
$lastscript = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$lastqrystr = "";
|
$lastqrystr = Request::any('qrystr', '');
|
||||||
if (isset($_REQUEST['qrystr']) && $_REQUEST['qrystr'] != "") {
|
|
||||||
$lastqrystr = urlencode($_REQUEST['qrystr']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($lastscript)) {
|
|
||||||
$_SESSION['lastscript'] = $lastscript;
|
|
||||||
}
|
|
||||||
if (!empty($lastqrystr)) {
|
if (!empty($lastqrystr)) {
|
||||||
|
$lastqrystr = urlencode($lastqrystr);
|
||||||
$_SESSION['lastqrystr'] = $lastqrystr;
|
$_SESSION['lastqrystr'] = $lastqrystr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,8 +535,8 @@ if ($action == 'forgotpwd') {
|
|||||||
$message = '';
|
$message = '';
|
||||||
|
|
||||||
if (!empty($_POST)) {
|
if (!empty($_POST)) {
|
||||||
$loginname = Validate::validate($_POST['loginname'], 'loginname');
|
$loginname = Validate::validate(Request::post('loginname'), 'loginname');
|
||||||
$email = Validate::validateEmail($_POST['loginemail']);
|
$email = Validate::validateEmail(Request::post('loginemail'));
|
||||||
$result_stmt = Database::prepare("SELECT `adminid`, `customerid`, `customernumber`, `firstname`, `name`, `company`, `email`, `loginname`, `def_language`, `deactivated` FROM `" . TABLE_PANEL_CUSTOMERS . "`
|
$result_stmt = Database::prepare("SELECT `adminid`, `customerid`, `customernumber`, `firstname`, `name`, `company`, `email`, `loginname`, `def_language`, `deactivated` FROM `" . TABLE_PANEL_CUSTOMERS . "`
|
||||||
WHERE `loginname`= :loginname
|
WHERE `loginname`= :loginname
|
||||||
AND `email`= :email");
|
AND `email`= :email");
|
||||||
@@ -624,7 +703,7 @@ if ($action == 'forgotpwd') {
|
|||||||
$rstlog = FroxlorLogger::getInstanceOf([
|
$rstlog = FroxlorLogger::getInstanceOf([
|
||||||
'loginname' => 'password_reset'
|
'loginname' => 'password_reset'
|
||||||
]);
|
]);
|
||||||
$rstlog->logAction(FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $loginname . "' requested to set a new password, but was not found in database!");
|
$rstlog->logAction(FroxlorLogger::USR_ACTION, LOG_WARNING, "Unknown user requested to set a new password, but was not found in database!");
|
||||||
$message = lng('login.usernotfound');
|
$message = lng('login.usernotfound');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -654,9 +733,9 @@ if ($action == 'resetpwd') {
|
|||||||
"oldest" => time() - 86400
|
"oldest" => time() - 86400
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (isset($_GET['resetcode']) && strlen($_GET['resetcode']) == 50) {
|
$activationcode = Request::get('resetcode');
|
||||||
|
if (!empty($activationcode) && strlen($activationcode) == 50) {
|
||||||
// Check if activation code is valid
|
// Check if activation code is valid
|
||||||
$activationcode = $_GET['resetcode'];
|
|
||||||
$timestamp = substr($activationcode, 15, 10);
|
$timestamp = substr($activationcode, 15, 10);
|
||||||
$third = substr($activationcode, 25, 15);
|
$third = substr($activationcode, 25, 15);
|
||||||
$check = substr($activationcode, 40, 10);
|
$check = substr($activationcode, 40, 10);
|
||||||
@@ -671,8 +750,8 @@ if ($action == 'resetpwd') {
|
|||||||
|
|
||||||
if ($result !== false) {
|
if ($result !== false) {
|
||||||
try {
|
try {
|
||||||
$new_password = Crypt::validatePassword($_POST['new_password'], true);
|
$new_password = Crypt::validatePassword(Request::post('new_password'), true);
|
||||||
$new_password_confirm = Crypt::validatePassword($_POST['new_password_confirm'], true);
|
$new_password_confirm = Crypt::validatePassword(Request::post('new_password_confirm'), true);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$message = $e->getMessage();
|
$message = $e->getMessage();
|
||||||
}
|
}
|
||||||
@@ -801,8 +880,8 @@ function finishLogin($userinfo)
|
|||||||
$theme = $userinfo['theme'];
|
$theme = $userinfo['theme'];
|
||||||
} else {
|
} else {
|
||||||
$theme = Settings::Get('panel.default_theme');
|
$theme = Settings::Get('panel.default_theme');
|
||||||
CurrentUser::setField('theme', $theme);
|
|
||||||
}
|
}
|
||||||
|
CurrentUser::setField('theme', $theme);
|
||||||
|
|
||||||
$qryparams = [];
|
$qryparams = [];
|
||||||
if (!empty($_SESSION['lastqrystr'])) {
|
if (!empty($_SESSION['lastqrystr'])) {
|
||||||
|
|||||||
@@ -94,6 +94,10 @@ CREATE TABLE `mail_virtual` (
|
|||||||
`popaccountid` int(11) NOT NULL default '0',
|
`popaccountid` int(11) NOT NULL default '0',
|
||||||
`iscatchall` tinyint(1) unsigned NOT NULL default '0',
|
`iscatchall` tinyint(1) unsigned NOT NULL default '0',
|
||||||
`description` varchar(255) NOT NULL DEFAULT '',
|
`description` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`spam_tag_level` float(4,1) NOT NULL DEFAULT 7.0,
|
||||||
|
`spam_kill_level` float(4,1) NOT NULL DEFAULT 14.0,
|
||||||
|
`bypass_spam` tinyint(1) NOT NULL default '0',
|
||||||
|
`policy_greylist` tinyint(1) NOT NULL default '1',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `email` (`email`)
|
KEY `email` (`email`)
|
||||||
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
|
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
|
||||||
@@ -155,9 +159,10 @@ CREATE TABLE `panel_admins` (
|
|||||||
`type_2fa` tinyint(1) NOT NULL default '0',
|
`type_2fa` tinyint(1) NOT NULL default '0',
|
||||||
`data_2fa` varchar(25) NOT NULL default '',
|
`data_2fa` varchar(25) NOT NULL default '',
|
||||||
`api_allowed` tinyint(1) NOT NULL default '1',
|
`api_allowed` tinyint(1) NOT NULL default '1',
|
||||||
|
`gui_access` 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`;
|
||||||
@@ -223,8 +228,7 @@ CREATE TABLE `panel_customers` (
|
|||||||
`api_allowed` tinyint(1) NOT NULL default '1',
|
`api_allowed` tinyint(1) NOT NULL default '1',
|
||||||
`logviewenabled` tinyint(1) NOT NULL default '0',
|
`logviewenabled` tinyint(1) NOT NULL default '0',
|
||||||
`allowed_mysqlserver` text NOT NULL,
|
`allowed_mysqlserver` text NOT NULL,
|
||||||
`backup` int(11) NOT NULL default '1',
|
`gui_access` tinyint(1) NOT NULL default '1',
|
||||||
`access_backups` tinyint(1) NOT NULL default '1',
|
|
||||||
PRIMARY KEY (`customerid`),
|
PRIMARY KEY (`customerid`),
|
||||||
UNIQUE KEY `loginname` (`loginname`)
|
UNIQUE KEY `loginname` (`loginname`)
|
||||||
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=DYNAMIC;
|
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=DYNAMIC;
|
||||||
@@ -301,7 +305,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`;
|
||||||
@@ -358,23 +362,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,
|
||||||
@@ -399,22 +386,18 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
|
|||||||
('logger', 'logfile', ''),
|
('logger', 'logfile', ''),
|
||||||
('logger', 'logtypes', 'syslog,mysql'),
|
('logger', 'logtypes', 'syslog,mysql'),
|
||||||
('logger', 'severity', '1'),
|
('logger', 'severity', '1'),
|
||||||
('dkim', 'use_dkim', '0'),
|
('antispam', 'activated', '0'),
|
||||||
('dkim', 'dkim_prefix', '/etc/postfix/dkim/'),
|
('antispam', 'config_file', '/etc/rspamd/local.d/froxlor_settings.conf'),
|
||||||
('dkim', 'dkim_domains', 'domains'),
|
('antispam', 'reload_command', 'service rspamd restart'),
|
||||||
('dkim', 'dkim_dkimkeys', 'dkim-keys.conf'),
|
('antispam', 'dkim_keylength', '1024'),
|
||||||
('dkim', 'dkimrestart_command', 'service dkim-filter restart'),
|
|
||||||
('dkim', 'privkeysuffix', '.priv'),
|
|
||||||
('admin', 'show_news_feed', '0'),
|
('admin', 'show_news_feed', '0'),
|
||||||
('admin', 'show_version_login', '0'),
|
('admin', 'show_version_login', '0'),
|
||||||
('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'),
|
('dmarc', 'use_dmarc', '0'),
|
||||||
('dkim', 'dkim_keylength', '1024'),
|
('dmarc', 'dmarc_entry', 'v=DMARC1; p=none;'),
|
||||||
('dkim', 'dkim_servicetype', '0'),
|
|
||||||
('dkim', 'dkim_notes', ''),
|
|
||||||
('defaultwebsrverrhandler', 'enabled', '0'),
|
('defaultwebsrverrhandler', 'enabled', '0'),
|
||||||
('defaultwebsrverrhandler', 'err401', ''),
|
('defaultwebsrverrhandler', 'err401', ''),
|
||||||
('defaultwebsrverrhandler', 'err403', ''),
|
('defaultwebsrverrhandler', 'err403', ''),
|
||||||
@@ -564,7 +547,7 @@ opcache.validate_timestamps'),
|
|||||||
('system', 'mod_fcgid', '0'),
|
('system', 'mod_fcgid', '0'),
|
||||||
('system', 'apacheconf_vhost', '/etc/apache2/sites-enabled/'),
|
('system', 'apacheconf_vhost', '/etc/apache2/sites-enabled/'),
|
||||||
('system', 'apacheconf_diroptions', '/etc/apache2/sites-enabled/'),
|
('system', 'apacheconf_diroptions', '/etc/apache2/sites-enabled/'),
|
||||||
('system', 'apacheconf_htpasswddir', '/etc/apache2/htpasswd/'),
|
('system', 'apacheconf_htpasswddir', '/etc/apache2/froxlor-htpasswd/'),
|
||||||
('system', 'webalizer_quiet', '2'),
|
('system', 'webalizer_quiet', '2'),
|
||||||
('system', 'last_archive_run', '000000'),
|
('system', 'last_archive_run', '000000'),
|
||||||
('system', 'mod_fcgid_configdir', '/var/www/php-fcgi-scripts'),
|
('system', 'mod_fcgid_configdir', '/var/www/php-fcgi-scripts'),
|
||||||
@@ -581,7 +564,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', ''),
|
||||||
@@ -656,6 +638,8 @@ opcache.validate_timestamps'),
|
|||||||
('system', 'available_shells', ''),
|
('system', 'available_shells', ''),
|
||||||
('system', 'le_froxlor_enabled', '0'),
|
('system', 'le_froxlor_enabled', '0'),
|
||||||
('system', 'le_froxlor_redirect', '0'),
|
('system', 'le_froxlor_redirect', '0'),
|
||||||
|
('system', 'le_renew_hook', 'systemctl restart postfix dovecot proftpd'),
|
||||||
|
('system', 'le_renew_services', ''),
|
||||||
('system', 'letsencryptacmeconf', '/etc/apache2/conf-enabled/acme.conf'),
|
('system', 'letsencryptacmeconf', '/etc/apache2/conf-enabled/acme.conf'),
|
||||||
('system', 'mail_use_smtp', '0'),
|
('system', 'mail_use_smtp', '0'),
|
||||||
('system', 'mail_smtp_host', 'localhost'),
|
('system', 'mail_smtp_host', 'localhost'),
|
||||||
@@ -698,20 +682,15 @@ opcache.validate_timestamps'),
|
|||||||
('system', 'distribution', ''),
|
('system', 'distribution', ''),
|
||||||
('system', 'update_channel', 'stable'),
|
('system', 'update_channel', 'stable'),
|
||||||
('system', 'updatecheck_data', ''),
|
('system', 'updatecheck_data', ''),
|
||||||
('system', 'update_notify_last', '2.0.20'),
|
('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),
|
||||||
('backup', 'enabled', 0),
|
|
||||||
('backup', 'default_storage', '1'),
|
|
||||||
('backup', 'default_customer_access', '1'),
|
|
||||||
('backup', 'default_pgp_public_key', ''),
|
|
||||||
('backup', 'default_retention', '3'),
|
|
||||||
('api', 'enabled', '0'),
|
('api', 'enabled', '0'),
|
||||||
('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', ''),
|
||||||
@@ -750,8 +729,9 @@ opcache.validate_timestamps'),
|
|||||||
('panel', 'logo_overridetheme', '0'),
|
('panel', 'logo_overridetheme', '0'),
|
||||||
('panel', 'logo_overridecustom', '0'),
|
('panel', 'logo_overridecustom', '0'),
|
||||||
('panel', 'settings_mode', '0'),
|
('panel', 'settings_mode', '0'),
|
||||||
('panel', 'version', '2.0.20'),
|
('panel', 'menu_collapsed', '1'),
|
||||||
('panel', 'db_version', '202305240');
|
('panel', 'version', '2.2.1'),
|
||||||
|
('panel', 'db_version', '202408140');
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `panel_tasks`;
|
DROP TABLE IF EXISTS `panel_tasks`;
|
||||||
@@ -774,6 +754,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;
|
||||||
@@ -920,8 +901,7 @@ INSERT INTO `cronjobs_run` (`id`, `module`, `cronfile`, `cronclass`, `interval`,
|
|||||||
(3, 'froxlor/reports', 'usage_report', '\\Froxlor\\Cron\\Traffic\\ReportsCron', '1 DAY', '1', 'cron_usage_report'),
|
(3, 'froxlor/reports', 'usage_report', '\\Froxlor\\Cron\\Traffic\\ReportsCron', '1 DAY', '1', 'cron_usage_report'),
|
||||||
(4, 'froxlor/core', 'mailboxsize', '\\Froxlor\\Cron\\System\\MailboxsizeCron', '6 HOUR', '1', 'cron_mailboxsize'),
|
(4, 'froxlor/core', 'mailboxsize', '\\Froxlor\\Cron\\System\\MailboxsizeCron', '6 HOUR', '1', 'cron_mailboxsize'),
|
||||||
(5, 'froxlor/letsencrypt', 'letsencrypt', '\\Froxlor\\Cron\\Http\\LetsEncrypt\\AcmeSh', '5 MINUTE', '0', 'cron_letsencrypt'),
|
(5, 'froxlor/letsencrypt', 'letsencrypt', '\\Froxlor\\Cron\\Http\\LetsEncrypt\\AcmeSh', '5 MINUTE', '0', 'cron_letsencrypt'),
|
||||||
(6, 'froxlor/export', 'export', '\\Froxlor\\Cron\\System\\ExportCron', '1 HOUR', '0', 'cron_export'),
|
(6, 'froxlor/export', 'export', '\\Froxlor\\Cron\\System\\ExportCron', '1 HOUR', '0', 'cron_export');
|
||||||
(7, 'froxlor/backup', 'backup', '\\Froxlor\\Cron\\Backup\\BackupCron', '1 DAY', '0', 'cron_backup');
|
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `ftp_quotalimits`;
|
DROP TABLE IF EXISTS `ftp_quotalimits`;
|
||||||
@@ -1071,36 +1051,13 @@ CREATE TABLE `panel_loginlinks` (
|
|||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `panel_backup_storages`;
|
DROP TABLE IF EXISTS `panel_2fa_tokens`;
|
||||||
CREATE TABLE `panel_backup_storages` (
|
CREATE TABLE `panel_2fa_tokens` (
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL auto_increment,
|
||||||
`description` varchar(255) NOT NULL,
|
`selector` varchar(200) NOT NULL,
|
||||||
`type` varchar(255) NOT NULL DEFAULT 'local',
|
`token` varchar(200) NOT NULL,
|
||||||
`region` varchar(255) NULL,
|
`userid` int(11) NOT NULL default '0',
|
||||||
`bucket` varchar(255) NULL,
|
`valid_until` int(15) NOT NULL,
|
||||||
`destination_path` varchar(255) NOT NULL,
|
PRIMARY KEY (id)
|
||||||
`hostname` varchar(255) NULL,
|
|
||||||
`username` varchar(255) NULL,
|
|
||||||
`password` text,
|
|
||||||
`pgp_public_key` text,
|
|
||||||
`retention` int(3) NOT NULL DEFAULT 3,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
|
|
||||||
|
|
||||||
INSERT INTO `panel_backup_storages` (`id`, `description`, `destination_path`) VALUES
|
|
||||||
(1, 'Local backup storage', '/var/customers/backups');
|
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `panel_backups`;
|
|
||||||
CREATE TABLE `panel_backups` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`adminid` int(11) NOT NULL,
|
|
||||||
`customerid` int(11) NOT NULL,
|
|
||||||
`loginname` varchar(255) NOT NULL,
|
|
||||||
`size` bigint(20) NOT NULL,
|
|
||||||
`storage_id` int(11) NOT NULL,
|
|
||||||
`filename` varchar(255) NOT NULL,
|
|
||||||
`created_at` int(15) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
|
||||||
FROXLORSQL;
|
FROXLORSQL;
|
||||||
|
|||||||
@@ -99,7 +99,6 @@ if (Froxlor::isFroxlorVersion('0.10.38.3')) {
|
|||||||
}
|
}
|
||||||
Update::lastStepStatus(0);
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
Update::showUpdateStep("Cleaning up old files");
|
|
||||||
$to_clean = array(
|
$to_clean = array(
|
||||||
"install/lib",
|
"install/lib",
|
||||||
"install/lng",
|
"install/lng",
|
||||||
@@ -121,35 +120,12 @@ if (Froxlor::isFroxlorVersion('0.10.38.3')) {
|
|||||||
"lng/swedish.lng.php",
|
"lng/swedish.lng.php",
|
||||||
"scripts",
|
"scripts",
|
||||||
);
|
);
|
||||||
$disabled = explode(',', ini_get('disable_functions'));
|
Update::cleanOldFiles($to_clean);
|
||||||
$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>');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Update::showUpdateStep("Adding new settings");
|
Update::showUpdateStep("Adding new settings");
|
||||||
$panel_settings_mode = isset($_POST['panel_settings_mode']) ? (int)$_POST['panel_settings_mode'] : 0;
|
$panel_settings_mode = isset($_POST['panel_settings_mode']) ? (int)$_POST['panel_settings_mode'] : 0;
|
||||||
Settings::AddNew("panel.settings_mode", $panel_settings_mode);
|
Settings::AddNew("panel.settings_mode", $panel_settings_mode);
|
||||||
$system_distribution = isset($_POST['system_distribution']) ? $_POST['system_distribution'] : '';
|
$system_distribution = isset($_POST['system_distribution']) ? $_POST['system_distribution'] : 'bullseye';
|
||||||
Settings::AddNew("system.distribution", $system_distribution);
|
Settings::AddNew("system.distribution", $system_distribution);
|
||||||
Settings::AddNew("system.update_channel", 'stable');
|
Settings::AddNew("system.update_channel", 'stable');
|
||||||
Settings::AddNew("system.updatecheck_data", '');
|
Settings::AddNew("system.updatecheck_data", '');
|
||||||
@@ -497,3 +473,23 @@ if (Froxlor::isFroxlorVersion('2.0.19')) {
|
|||||||
Update::showUpdateStep("Updating from 2.0.19 to 2.0.20", false);
|
Update::showUpdateStep("Updating from 2.0.19 to 2.0.20", false);
|
||||||
Froxlor::updateToVersion('2.0.20');
|
Froxlor::updateToVersion('2.0.20');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.20')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.20 to 2.0.21", false);
|
||||||
|
Froxlor::updateToVersion('2.0.21');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.21')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.21 to 2.0.22", false);
|
||||||
|
Froxlor::updateToVersion('2.0.22');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.22')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.22 to 2.0.23", false);
|
||||||
|
Froxlor::updateToVersion('2.0.23');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.23')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.23 to 2.0.24", false);
|
||||||
|
Froxlor::updateToVersion('2.0.24');
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,8 +36,9 @@ if (!defined('_CRON_UPDATE')) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Froxlor::isDatabaseVersion('202304260')) {
|
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);
|
||||||
|
|
||||||
@@ -53,6 +54,10 @@ if (Froxlor::isDatabaseVersion('202304260')) {
|
|||||||
Database::query($sql);
|
Database::query($sql);
|
||||||
Update::lastStepStatus(0);
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Update::showUpdateStep("Adding new settings");
|
||||||
|
Settings::AddNew('panel.menu_collapsed', 1);
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
Update::showUpdateStep("Adjusting setting for deactivated webroot");
|
Update::showUpdateStep("Adjusting setting for deactivated webroot");
|
||||||
$current_deactivated_webroot = Settings::Get('system.deactivateddocroot');
|
$current_deactivated_webroot = Settings::Get('system.deactivateddocroot');
|
||||||
if (empty($current_deactivated_webroot)) {
|
if (empty($current_deactivated_webroot)) {
|
||||||
@@ -62,80 +67,188 @@ if (Froxlor::isDatabaseVersion('202304260')) {
|
|||||||
Update::lastStepStatus(1, 'Customized setting, not changing');
|
Update::lastStepStatus(1, 'Customized setting, not changing');
|
||||||
}
|
}
|
||||||
|
|
||||||
Update::showUpdateStep("Creating new tables and fields for backups");
|
|
||||||
Database::query("DROP TABLE IF EXISTS `". TABLE_PANEL_BACKUP_STORAGES ."`;");
|
|
||||||
$sql = "CREATE TABLE `". TABLE_PANEL_BACKUP_STORAGES ."` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`description` varchar(255) NOT NULL,
|
|
||||||
`type` varchar(255) NOT NULL DEFAULT 'local',
|
|
||||||
`region` varchar(255) NULL,
|
|
||||||
`bucket` varchar(255) NULL,
|
|
||||||
`destination_path` varchar(255) NOT NULL,
|
|
||||||
`hostname` varchar(255) NULL,
|
|
||||||
`username` varchar(255) NULL,
|
|
||||||
`password` text,
|
|
||||||
`pgp_public_key` text,
|
|
||||||
`retention` int(3) NOT NULL DEFAULT 3,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;";
|
|
||||||
Database::query($sql);
|
|
||||||
Database::query("
|
|
||||||
INSERT INTO `panel_backup_storages` (`id`, `description`, `destination_path`) VALUES
|
|
||||||
(1, 'Local backup storage', '/var/customers/backups');
|
|
||||||
");
|
|
||||||
Database::query("DROP TABLE IF EXISTS `". TABLE_PANEL_BACKUPS ."`;");
|
|
||||||
$sql = "CREATE TABLE `". TABLE_PANEL_BACKUPS ."` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`adminid` int(11) NOT NULL,
|
|
||||||
`customerid` int(11) NOT NULL,
|
|
||||||
`loginname` varchar(255) NOT NULL,
|
|
||||||
`size` bigint(20) NOT NULL,
|
|
||||||
`storage_id` int(11) NOT NULL,
|
|
||||||
`filename` varchar(255) NOT NULL,
|
|
||||||
`created_at` int(15) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;";
|
|
||||||
Database::query($sql);
|
|
||||||
// add customer backup-target-storage
|
|
||||||
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `backup` int(11) NOT NULL default '1' AFTER `allowed_mysqlserver`;");
|
|
||||||
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `access_backups` tinyint(1) NOT NULL default '1' AFTER `backup`;");
|
|
||||||
Update::lastStepStatus(0);
|
|
||||||
|
|
||||||
Update::showUpdateStep("Adding new backup settings");
|
|
||||||
Settings::AddNew('backup.enabled', 0);
|
|
||||||
Settings::AddNew('backup.default_storage', 1);
|
|
||||||
Settings::AddNew('backup.default_customer_access', 1);
|
|
||||||
Settings::AddNew('backup.default_pgp_public_key', '');
|
|
||||||
Settings::AddNew('backup.default_retention', 3);
|
|
||||||
Update::lastStepStatus(0);
|
|
||||||
|
|
||||||
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::query("
|
Database::pexecute($cfupd_stmt, [
|
||||||
INSERT INTO `" . TABLE_PANEL_CRONRUNS . "` SET
|
'cc' => '\\Froxlor\\Cron\\System\\ExportCron'
|
||||||
`module`= 'froxlor/backup',
|
]);
|
||||||
`cronfile` = 'backup',
|
|
||||||
`cronclass` = '\\Froxlor\\Cron\\Backup\\BackupCron',
|
|
||||||
`interval` = '1 DAY',
|
|
||||||
`isactive` = '0',
|
|
||||||
`desc_lng_key` = 'cron_backup'
|
|
||||||
");
|
|
||||||
Update::lastStepStatus(0);
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
Update::showUpdateStep("Adjusting system for data-export function");
|
Update::showUpdateStep("Adjusting system for data-export function");
|
||||||
Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "`SET `varname` = 'exportenabled' WHERE `settinggroup`= 'system' AND `varname`= 'backupenabled");
|
Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "`SET `varname` = 'exportenabled' WHERE `settinggroup`= 'system' AND `varname`= 'backupenabled'");
|
||||||
Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "`SET `value` = REPLACE(`value`, 'extras.backup', 'extras.export') WHERE `settinggroup` = 'panel' AND `varname` = 'customer_hide_options'");
|
Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "`SET `value` = REPLACE(`value`, 'extras.backup', 'extras.export') WHERE `settinggroup` = 'panel' AND `varname` = 'customer_hide_options'");
|
||||||
Database::query("DELETE FROM `" . TABLE_PANEL_USERCOLUMNS . "` WHERE `section` = 'backup_list'");
|
Database::query("DELETE FROM `" . TABLE_PANEL_USERCOLUMNS . "` WHERE `section` = 'backup_list'");
|
||||||
Database::query("DELETE FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20'");
|
Database::query("DELETE FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20'");
|
||||||
Update::lastStepStatus(0);
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
Froxlor::updateToDbVersion('202305240');
|
Froxlor::updateToDbVersion('202305240');
|
||||||
|
Froxlor::updateToVersion('2.1.0-dev1');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.0-dev1')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.1.0-dev1 to 2.1.0-beta1", false);
|
||||||
|
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')) {
|
||||||
|
$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"
|
||||||
|
);
|
||||||
|
Update::cleanOldFiles($to_clean);
|
||||||
|
|
||||||
|
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')) {
|
||||||
|
$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",
|
||||||
|
);
|
||||||
|
Update::cleanOldFiles($to_clean);
|
||||||
|
|
||||||
|
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');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.7')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.1.7 to 2.1.8", false);
|
||||||
|
Froxlor::updateToVersion('2.1.8');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.8')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.1.8 to 2.1.9", false);
|
||||||
|
Froxlor::updateToVersion('2.1.9');
|
||||||
}
|
}
|
||||||
|
|||||||
171
install/updates/froxlor/update_2.2.inc.php
Normal file
171
install/updates/froxlor/update_2.2.inc.php
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file is part of the Froxlor project.
|
||||||
|
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you can also view it online at
|
||||||
|
* https://files.froxlor.org/misc/COPYING.txt
|
||||||
|
*
|
||||||
|
* @copyright the authors
|
||||||
|
* @author Froxlor team <team@froxlor.org>
|
||||||
|
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Froxlor\Database\Database;
|
||||||
|
use Froxlor\Froxlor;
|
||||||
|
use Froxlor\Install\Update;
|
||||||
|
use Froxlor\Settings;
|
||||||
|
|
||||||
|
if (!defined('_CRON_UPDATE')) {
|
||||||
|
if (!defined('AREA') || (defined('AREA') && AREA != 'admin') || !isset($userinfo['loginname']) || (isset($userinfo['loginname']) && $userinfo['loginname'] == '')) {
|
||||||
|
header('Location: ../../../../index.php');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.1.9')) {
|
||||||
|
Update::showUpdateStep("Enhancing virtual email table");
|
||||||
|
Database::query("ALTER TABLE `" . TABLE_MAIL_VIRTUAL . "` ADD `spam_tag_level` float(4,1) NOT NULL DEFAULT 7.0;");
|
||||||
|
Database::query("ALTER TABLE `" . TABLE_MAIL_VIRTUAL . "` ADD `spam_kill_level` float(4,1) NOT NULL DEFAULT 14.0;");
|
||||||
|
Database::query("ALTER TABLE `" . TABLE_MAIL_VIRTUAL . "` ADD `bypass_spam` tinyint(1) NOT NULL default '0';");
|
||||||
|
Database::query("ALTER TABLE `" . TABLE_MAIL_VIRTUAL . "` ADD `policy_greylist` tinyint(1) NOT NULL default '1';");
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Update::showUpdateStep("Adjusting settings");
|
||||||
|
$antispam_activated = $_POST['antispam_activated'] ?? 0;
|
||||||
|
Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `settinggroup` = 'antispam', `varname` = 'activated', `value` = '" . (int)$antispam_activated . "' WHERE `settinggroup` = 'dkim' AND `varname` = 'use_dkim';");
|
||||||
|
Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `settinggroup` = 'antispam', `varname` = 'reload_command', `value` = 'service rspamd restart' WHERE `settinggroup` = 'dkim' AND `varname` = 'dkimrestart_command';");
|
||||||
|
Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `settinggroup` = 'antispam', `varname` = 'config_file', `value` = '/etc/rspamd/local.d/froxlor_settings.conf' WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_prefix';");
|
||||||
|
Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `settinggroup` = 'antispam' WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_keylength';");
|
||||||
|
Settings::AddNew("dmarc.use_dmarc", "0");
|
||||||
|
Settings::AddNew("dmarc.dmarc_entry", "v=DMARC1; p=none;");
|
||||||
|
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'privkeysuffix';");
|
||||||
|
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_domains';");
|
||||||
|
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_algorithm';");
|
||||||
|
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_notes';");
|
||||||
|
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_add_adsp';");
|
||||||
|
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_dkimkeys';");
|
||||||
|
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_servicetype';");
|
||||||
|
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_add_adsppolicy';");
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
if ($antispam_activated) {
|
||||||
|
Update::showUpdateStep("Converting existing domainkeys");
|
||||||
|
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `dkim` = '1' AND `dkim_pubkey` <> ''");
|
||||||
|
Database::pexecute($sel_stmt);
|
||||||
|
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `dkim_pubkey` = :pkey WHERE `id` = :did");
|
||||||
|
while ($domain = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||||
|
$pubkey = trim(preg_replace(
|
||||||
|
'/-----BEGIN PUBLIC KEY-----(.+)-----END PUBLIC KEY-----/s',
|
||||||
|
'$1',
|
||||||
|
str_replace("\n", '', $domain['dkim_pubkey'])
|
||||||
|
));
|
||||||
|
Database::pexecute($upd_stmt, ['pkey' => $pubkey, 'did' => $domain['id']]);
|
||||||
|
}
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Update::showUpdateStep("Configure antispam services");
|
||||||
|
$froxlorCliBin = Froxlor::getInstallDir() . '/bin/froxlor-cli';
|
||||||
|
$currentDistro = Settings::Get('system.distribution');
|
||||||
|
$manual_command = <<<EOC
|
||||||
|
{$froxlorCliBin} froxlor:config-services -a '{"http":"x","dns":"x","smtp":"x","mail":"x","antispam":"rspamd","ftp":"x","distro":"{$currentDistro}","system":[]}'
|
||||||
|
EOC;
|
||||||
|
Update::lastStepStatus(
|
||||||
|
1,
|
||||||
|
'manual action needed',
|
||||||
|
"Please run the following command manually as root:<br><pre>" . $manual_command . "</pre>"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Update::showUpdateStep("Removing existing domainkeys because antispam is disabled");
|
||||||
|
Database::query("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `dkim` = '0', `dkim_id` = '0', `dkim_privkey` = '', `dkim_pubkey` = '' WHERE `dkim` = '1';");
|
||||||
|
Update::lastStepStatus(1, '!!!');
|
||||||
|
}
|
||||||
|
|
||||||
|
Update::showUpdateStep("Enhancing admin and user table");
|
||||||
|
Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` ADD `gui_access` tinyint(1) NOT NULL default '1';");
|
||||||
|
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `gui_access` tinyint(1) NOT NULL default '1';");
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
$to_clean = [
|
||||||
|
'actions/admin/settings/180.dkim.php',
|
||||||
|
'actions/admin/settings/185.spf.php',
|
||||||
|
];
|
||||||
|
Update::cleanOldFiles($to_clean);
|
||||||
|
|
||||||
|
Froxlor::updateToDbVersion('202312230');
|
||||||
|
Froxlor::updateToVersion('2.2.0-dev1');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isDatabaseVersion('202312230')) {
|
||||||
|
|
||||||
|
Update::showUpdateStep("Adding new settings");
|
||||||
|
Settings::AddNew("system.le_renew_services", "");
|
||||||
|
Settings::AddNew("system.le_renew_hook", "systemctl restart postfix dovecot proftpd");
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Froxlor::updateToDbVersion('202401090');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.2.0-dev1')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.2.0-dev1 to 2.2.0-rc1", false);
|
||||||
|
Froxlor::updateToVersion('2.2.0-rc1');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isDatabaseVersion('202401090')) {
|
||||||
|
|
||||||
|
Update::showUpdateStep("Adding new table for 2fa tokens");
|
||||||
|
Database::query("DROP TABLE IF EXISTS `panel_2fa_tokens`;");
|
||||||
|
$sql = "CREATE TABLE `panel_2fa_tokens` (
|
||||||
|
`id` int(11) NOT NULL auto_increment,
|
||||||
|
`selector` varchar(20) NOT NULL,
|
||||||
|
`token` varchar(200) NOT NULL,
|
||||||
|
`userid` int(11) NOT NULL default '0',
|
||||||
|
`valid_until` int(15) NOT NULL,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;";
|
||||||
|
Database::query($sql);
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Froxlor::updateToDbVersion('202407200');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.2.0-rc1')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.2.0-rc1 to 2.2.0-rc2", false);
|
||||||
|
Froxlor::updateToVersion('2.2.0-rc2');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.2.0-rc2')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.2.0-rc2 to 2.2.0-rc3", false);
|
||||||
|
Froxlor::updateToVersion('2.2.0-rc3');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isDatabaseVersion('202407200')) {
|
||||||
|
|
||||||
|
Update::showUpdateStep("Adjusting field in 2fa-token table");
|
||||||
|
Database::query("ALTER TABLE `panel_2fa_tokens` CHANGE COLUMN `selector` `selector` varchar(200) NOT NULL;");
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Froxlor::updateToDbVersion('202408140');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.2.0-rc3')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.2.0-rc3 to 2.2.0 stable", false);
|
||||||
|
Froxlor::updateToVersion('2.2.0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.2.0')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.2.0 to 2.2.1", false);
|
||||||
|
Froxlor::updateToVersion('2.2.1');
|
||||||
|
}
|
||||||
@@ -54,7 +54,7 @@ if (Update::versionInUpdate($current_version, '2.0.0-beta1')) {
|
|||||||
$config_dir = FileDir::makeCorrectDir(Froxlor::getInstallDir() . '/lib/configfiles/');
|
$config_dir = FileDir::makeCorrectDir(Froxlor::getInstallDir() . '/lib/configfiles/');
|
||||||
// show list of available distro's
|
// show list of available distro's
|
||||||
$distros = glob($config_dir . '*.xml');
|
$distros = glob($config_dir . '*.xml');
|
||||||
$distributions_select[''] = '-';
|
// selection is required $distributions_select[''] = '-';
|
||||||
// read in all the distros
|
// read in all the distros
|
||||||
foreach ($distros as $_distribution) {
|
foreach ($distros as $_distribution) {
|
||||||
// get configparser object
|
// get configparser object
|
||||||
|
|||||||
@@ -36,19 +36,7 @@ $preconfig = [
|
|||||||
$return = [];
|
$return = [];
|
||||||
|
|
||||||
if (Update::versionInUpdate($current_version, '2.1.0-dev1')) {
|
if (Update::versionInUpdate($current_version, '2.1.0-dev1')) {
|
||||||
// Backup
|
|
||||||
$description = 'Froxlor now comes with a backup capability (More info see [DOCS LINK].';
|
|
||||||
$question = '<strong>Would you like to enable the backup-feature (default: yes)</strong>';
|
|
||||||
$return['panel_settings_mode'] = [
|
|
||||||
'type' => 'select',
|
|
||||||
'select_var' => [
|
|
||||||
0 => 'No',
|
|
||||||
1 => 'Yes'
|
|
||||||
],
|
|
||||||
'selected' => 1,
|
|
||||||
'label' => $question,
|
|
||||||
'prior_infotext' => $description
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$preconfig['fields'] = $return;
|
$preconfig['fields'] = $return;
|
||||||
|
|||||||
@@ -23,28 +23,26 @@
|
|||||||
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace Froxlor\UI\Callbacks;
|
use Froxlor\Install\Update;
|
||||||
|
|
||||||
use Froxlor\Database\Database;
|
$preconfig = [
|
||||||
use Froxlor\UI\Panel\UI;
|
'title' => '2.2.x updates',
|
||||||
|
'fields' => []
|
||||||
|
];
|
||||||
|
$return = [];
|
||||||
|
|
||||||
class Backup
|
if (Update::versionInUpdate($current_version, '2.2.0-dev1')) {
|
||||||
{
|
$has_preconfig = true;
|
||||||
public static function backupStorageLink(array $attributes)
|
$description = 'Froxlor now features antispam configurations using rspamd. Would you like to enable the antispam feature (required re-configuration of services)?<br><strong>ATTENTION:</strong> When not enabled and the former DomainKey feature was used, keep in mind that all existing domainkeys for all domain are being removed and the dkim-flag disabled for the domains.';
|
||||||
{
|
$question = '<strong>Enable antispam (recommended)</strong> ';
|
||||||
$sel_stmt = Database::prepare("SELECT `description` FROM `" . TABLE_PANEL_BACKUP_STORAGES . "` WHERE `id` = :id");
|
$return['antispam_activated'] = [
|
||||||
$backupstorage = Database::pexecute_first($sel_stmt, ['id' => $attributes['data']]);
|
'type' => 'checkbox',
|
||||||
if ((int)UI::getCurrentUser()['adminsession'] == 1 && UI::getCurrentUser()['change_serversettings']) {
|
'value' => 1,
|
||||||
$linker = UI::getLinker();
|
'checked' => 0,
|
||||||
$result = '<a href="' . $linker->getLink([
|
'label' => $question,
|
||||||
'section' => 'backups',
|
'prior_infotext' => $description
|
||||||
'page' => 'storages',
|
];
|
||||||
'searchfield' => 'id',
|
|
||||||
'searchtext' => $attributes['data'],
|
|
||||||
]) . '">' . $backupstorage['description'] . '</a>';
|
|
||||||
} else {
|
|
||||||
$result = $backupstorage['description'];
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$preconfig['fields'] = $return;
|
||||||
|
return $preconfig;
|
||||||
@@ -55,6 +55,7 @@ if (Froxlor::isFroxlor()) {
|
|||||||
include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_0.10.inc.php'));
|
include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_0.10.inc.php'));
|
||||||
include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_2.0.inc.php'));
|
include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_2.0.inc.php'));
|
||||||
include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_2.1.inc.php'));
|
include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_2.1.inc.php'));
|
||||||
|
include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_2.2.inc.php'));
|
||||||
|
|
||||||
// Check Froxlor - database integrity (only happens after all updates are done, so we know the db-layout is okay)
|
// Check Froxlor - database integrity (only happens after all updates are done, so we know the db-layout is okay)
|
||||||
Update::showUpdateStep("Checking database integrity");
|
Update::showUpdateStep("Checking database integrity");
|
||||||
|
|||||||
@@ -193,7 +193,8 @@ class Ajax
|
|||||||
UI::initTwig();
|
UI::initTwig();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$json_result = \Froxlor\Api\Commands\Froxlor::getLocal($this->userinfo)->checkUpdate();
|
$force = Request::get('force', 0);
|
||||||
|
$json_result = \Froxlor\Api\Commands\Froxlor::getLocal($this->userinfo, ['force' => $force])->checkUpdate();
|
||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
$result['full_version'] = Froxlor::getFullVersion();
|
$result['full_version'] = Froxlor::getFullVersion();
|
||||||
$result['dbversion'] = Froxlor::DBVERSION;
|
$result['dbversion'] = Froxlor::DBVERSION;
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ class GlobalSearch
|
|||||||
],
|
],
|
||||||
'result_key' => 'domain_ace',
|
'result_key' => 'domain_ace',
|
||||||
'result_format' => [
|
'result_format' => [
|
||||||
'title' => ['self', 'getFieldFromResult'],
|
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'],
|
||||||
'title_args' => 'domain_ace',
|
'title_args' => 'domain_ace',
|
||||||
'href' => 'admin_domains.php?page=domains&searchfield=d.domain_ace&searchtext='
|
'href' => 'admin_domains.php?page=domains&searchfield=d.domain_ace&searchtext='
|
||||||
]
|
]
|
||||||
@@ -172,7 +172,7 @@ class GlobalSearch
|
|||||||
'result_key' => 'ip',
|
'result_key' => 'ip',
|
||||||
'result_groupkey' => 'ip',
|
'result_groupkey' => 'ip',
|
||||||
'result_format' => [
|
'result_format' => [
|
||||||
'title' => ['self', 'getFieldFromResult'],
|
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'],
|
||||||
'title_args' => 'ip',
|
'title_args' => 'ip',
|
||||||
'href' => 'admin_ipsandports.php?page=ipsandports&searchfield=ip&searchtext='
|
'href' => 'admin_ipsandports.php?page=ipsandports&searchfield=ip&searchtext='
|
||||||
]
|
]
|
||||||
@@ -186,7 +186,7 @@ class GlobalSearch
|
|||||||
],
|
],
|
||||||
'result_key' => 'id',
|
'result_key' => 'id',
|
||||||
'result_format' => [
|
'result_format' => [
|
||||||
'title' => ['self', 'getFieldFromResult'],
|
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'],
|
||||||
'title_args' => 'name',
|
'title_args' => 'name',
|
||||||
'href' => 'admin_plans.php?page=overview&searchfield=id&searchtext='
|
'href' => 'admin_plans.php?page=overview&searchfield=id&searchtext='
|
||||||
]
|
]
|
||||||
@@ -201,7 +201,7 @@ class GlobalSearch
|
|||||||
],
|
],
|
||||||
'result_key' => 'id',
|
'result_key' => 'id',
|
||||||
'result_format' => [
|
'result_format' => [
|
||||||
'title' => ['self', 'getFieldFromResult'],
|
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'],
|
||||||
'title_args' => 'description',
|
'title_args' => 'description',
|
||||||
'href' => 'admin_phpsettings.php?page=overview&searchfield=id&searchtext='
|
'href' => 'admin_phpsettings.php?page=overview&searchfield=id&searchtext='
|
||||||
]
|
]
|
||||||
@@ -215,7 +215,7 @@ class GlobalSearch
|
|||||||
],
|
],
|
||||||
'result_key' => 'id',
|
'result_key' => 'id',
|
||||||
'result_format' => [
|
'result_format' => [
|
||||||
'title' => ['self', 'getFieldFromResult'],
|
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'],
|
||||||
'title_args' => 'description',
|
'title_args' => 'description',
|
||||||
'href' => 'admin_phpsettings.php?page=fpmdaemons&searchfield=id&searchtext='
|
'href' => 'admin_phpsettings.php?page=fpmdaemons&searchfield=id&searchtext='
|
||||||
]
|
]
|
||||||
@@ -234,7 +234,7 @@ class GlobalSearch
|
|||||||
],
|
],
|
||||||
'result_key' => 'loginname',
|
'result_key' => 'loginname',
|
||||||
'result_format' => [
|
'result_format' => [
|
||||||
'title' => ['self', 'getFieldFromResult'],
|
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'],
|
||||||
'title_args' => 'name',
|
'title_args' => 'name',
|
||||||
'href' => 'admin_admins.php?page=admins&searchfield=loginname&searchtext='
|
'href' => 'admin_admins.php?page=admins&searchfield=loginname&searchtext='
|
||||||
]
|
]
|
||||||
@@ -252,7 +252,7 @@ class GlobalSearch
|
|||||||
],
|
],
|
||||||
'result_key' => 'domain_ace',
|
'result_key' => 'domain_ace',
|
||||||
'result_format' => [
|
'result_format' => [
|
||||||
'title' => ['self', 'getFieldFromResult'],
|
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'],
|
||||||
'title_args' => 'domain_ace',
|
'title_args' => 'domain_ace',
|
||||||
'href' => 'customer_domains.php?page=domains&searchfield=d.domain_ace&searchtext='
|
'href' => 'customer_domains.php?page=domains&searchfield=d.domain_ace&searchtext='
|
||||||
]
|
]
|
||||||
@@ -266,7 +266,7 @@ class GlobalSearch
|
|||||||
],
|
],
|
||||||
'result_key' => 'email',
|
'result_key' => 'email',
|
||||||
'result_format' => [
|
'result_format' => [
|
||||||
'title' => ['self', 'getFieldFromResult'],
|
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'],
|
||||||
'title_args' => 'email',
|
'title_args' => 'email',
|
||||||
'href' => 'customer_email.php?page=email_domain&domainid={domainid}&searchfield=m.email&searchtext='
|
'href' => 'customer_email.php?page=email_domain&domainid={domainid}&searchfield=m.email&searchtext='
|
||||||
]
|
]
|
||||||
@@ -279,7 +279,7 @@ class GlobalSearch
|
|||||||
],
|
],
|
||||||
'result_key' => 'domain',
|
'result_key' => 'domain',
|
||||||
'result_format' => [
|
'result_format' => [
|
||||||
'title' => ['self', 'getFieldFromResult'],
|
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'],
|
||||||
'title_args' => 'domain',
|
'title_args' => 'domain',
|
||||||
'href' => 'customer_email.php?page=emails&searchfield=d.domain&searchtext='
|
'href' => 'customer_email.php?page=emails&searchfield=d.domain&searchtext='
|
||||||
]
|
]
|
||||||
@@ -293,7 +293,7 @@ class GlobalSearch
|
|||||||
],
|
],
|
||||||
'result_key' => 'databasename',
|
'result_key' => 'databasename',
|
||||||
'result_format' => [
|
'result_format' => [
|
||||||
'title' => ['self', 'getFieldFromResult'],
|
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'],
|
||||||
'title_args' => 'databasename',
|
'title_args' => 'databasename',
|
||||||
'href' => 'customer_mysql.php?page=mysqls&searchfield=databasename&searchtext='
|
'href' => 'customer_mysql.php?page=mysqls&searchfield=databasename&searchtext='
|
||||||
]
|
]
|
||||||
@@ -307,7 +307,7 @@ class GlobalSearch
|
|||||||
],
|
],
|
||||||
'result_key' => 'username',
|
'result_key' => 'username',
|
||||||
'result_format' => [
|
'result_format' => [
|
||||||
'title' => ['self', 'getFieldFromResult'],
|
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'],
|
||||||
'title_args' => 'username',
|
'title_args' => 'username',
|
||||||
'href' => 'customer_ftp.php?page=accounts&searchfield=username&searchtext='
|
'href' => 'customer_ftp.php?page=accounts&searchfield=username&searchtext='
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -140,12 +140,18 @@ class Admins extends ApiCommand implements ResourceEntity
|
|||||||
* create a new admin user
|
* create a new admin user
|
||||||
*
|
*
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
* required, name of the adminstrator
|
||||||
* @param string $email
|
* @param string $email
|
||||||
|
* required, email address of the administrator
|
||||||
* @param string $new_loginname
|
* @param string $new_loginname
|
||||||
|
* required, loginname/username of the administrator
|
||||||
* @param string $admin_password
|
* @param string $admin_password
|
||||||
* optional, default auto-generated
|
* optional, default auto-generated
|
||||||
* @param string $def_language
|
* @param string $def_language
|
||||||
* optional, default is system-default language
|
* * optional, ISO 639-1 language code (e.g. 'en', 'de', see lng-folder for supported languages),
|
||||||
|
* * default is system-default language
|
||||||
|
* @param bool $gui_access
|
||||||
|
* optional, allow login via webui, if false ONLY the login via webui is disallowed; default true
|
||||||
* @param bool $api_allowed
|
* @param bool $api_allowed
|
||||||
* optional, default is true if system setting api.enabled is true, else false
|
* optional, default is true if system setting api.enabled is true, else false
|
||||||
* @param string $custom_notes
|
* @param string $custom_notes
|
||||||
@@ -219,6 +225,7 @@ class Admins extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
// parameters
|
// parameters
|
||||||
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
|
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
|
||||||
|
$gui_access = $this->getBoolParam('gui_access', true, true);
|
||||||
$api_allowed = $this->getBoolParam('api_allowed', true, Settings::Get('api.enabled'));
|
$api_allowed = $this->getBoolParam('api_allowed', true, Settings::Get('api.enabled'));
|
||||||
$custom_notes = $this->getParam('custom_notes', true, '');
|
$custom_notes = $this->getParam('custom_notes', true, '');
|
||||||
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
|
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
|
||||||
@@ -316,6 +323,7 @@ class Admins extends ApiCommand implements ResourceEntity
|
|||||||
'name' => $name,
|
'name' => $name,
|
||||||
'email' => $email,
|
'email' => $email,
|
||||||
'lang' => $def_language,
|
'lang' => $def_language,
|
||||||
|
'gui_access' => $gui_access,
|
||||||
'api_allowed' => $api_allowed,
|
'api_allowed' => $api_allowed,
|
||||||
'change_serversettings' => $change_serversettings,
|
'change_serversettings' => $change_serversettings,
|
||||||
'customers' => $customers,
|
'customers' => $customers,
|
||||||
@@ -344,6 +352,7 @@ class Admins extends ApiCommand implements ResourceEntity
|
|||||||
`name` = :name,
|
`name` = :name,
|
||||||
`email` = :email,
|
`email` = :email,
|
||||||
`def_language` = :lang,
|
`def_language` = :lang,
|
||||||
|
`gui_access` = :gui_access,
|
||||||
`api_allowed` = :api_allowed,
|
`api_allowed` = :api_allowed,
|
||||||
`change_serversettings` = :change_serversettings,
|
`change_serversettings` = :change_serversettings,
|
||||||
`customers` = :customers,
|
`customers` = :customers,
|
||||||
@@ -430,7 +439,10 @@ class Admins extends ApiCommand implements ResourceEntity
|
|||||||
* @param string $admin_password
|
* @param string $admin_password
|
||||||
* optional, default auto-generated
|
* optional, default auto-generated
|
||||||
* @param string $def_language
|
* @param string $def_language
|
||||||
* optional, default is system-default language
|
* * optional, ISO 639-1 language code (e.g. 'en', 'de', see lng-folder for supported languages),
|
||||||
|
* * default is system-default language
|
||||||
|
* @param bool $gui_access
|
||||||
|
* * optional, allow login via webui, if false ONLY the login via webui is disallowed; default true
|
||||||
* @param bool $api_allowed
|
* @param bool $api_allowed
|
||||||
* optional, default is true if system setting api.enabled is true, else false
|
* optional, default is true if system setting api.enabled is true, else false
|
||||||
* @param string $custom_notes
|
* @param string $custom_notes
|
||||||
@@ -524,6 +536,7 @@ class Admins extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
// you cannot edit some of the details of yourself
|
// you cannot edit some of the details of yourself
|
||||||
if ($result['adminid'] == $this->getUserDetail('adminid')) {
|
if ($result['adminid'] == $this->getUserDetail('adminid')) {
|
||||||
|
$gui_access = $result['gui_access'];
|
||||||
$api_allowed = $result['api_allowed'];
|
$api_allowed = $result['api_allowed'];
|
||||||
$deactivated = $result['deactivated'];
|
$deactivated = $result['deactivated'];
|
||||||
$customers = $result['customers'];
|
$customers = $result['customers'];
|
||||||
@@ -542,6 +555,7 @@ class Admins extends ApiCommand implements ResourceEntity
|
|||||||
$traffic = $result['traffic'];
|
$traffic = $result['traffic'];
|
||||||
$ipaddress = ($result['ip'] != -1 ? json_decode($result['ip'], true) : -1);
|
$ipaddress = ($result['ip'] != -1 ? json_decode($result['ip'], true) : -1);
|
||||||
} else {
|
} else {
|
||||||
|
$gui_access = $this->getBoolParam('gui_access', true, $result['gui_access']);
|
||||||
$api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']);
|
$api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']);
|
||||||
$deactivated = $this->getBoolParam('deactivated', true, $result['deactivated']);
|
$deactivated = $this->getBoolParam('deactivated', true, $result['deactivated']);
|
||||||
|
|
||||||
@@ -665,6 +679,7 @@ class Admins extends ApiCommand implements ResourceEntity
|
|||||||
'name' => $name,
|
'name' => $name,
|
||||||
'email' => $email,
|
'email' => $email,
|
||||||
'lang' => $def_language,
|
'lang' => $def_language,
|
||||||
|
'gui_access' => $gui_access,
|
||||||
'api_allowed' => $api_allowed,
|
'api_allowed' => $api_allowed,
|
||||||
'change_serversettings' => $change_serversettings,
|
'change_serversettings' => $change_serversettings,
|
||||||
'customers' => $customers,
|
'customers' => $customers,
|
||||||
@@ -694,6 +709,7 @@ class Admins extends ApiCommand implements ResourceEntity
|
|||||||
`name` = :name,
|
`name` = :name,
|
||||||
`email` = :email,
|
`email` = :email,
|
||||||
`def_language` = :lang,
|
`def_language` = :lang,
|
||||||
|
`gui_access` = :gui_access,
|
||||||
`api_allowed` = :api_allowed,
|
`api_allowed` = :api_allowed,
|
||||||
`change_serversettings` = :change_serversettings,
|
`change_serversettings` = :change_serversettings,
|
||||||
`customers` = :customers,
|
`customers` = :customers,
|
||||||
|
|||||||
@@ -1,487 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file is part of the Froxlor project.
|
|
||||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, you can also view it online at
|
|
||||||
* https://files.froxlor.org/misc/COPYING.txt
|
|
||||||
*
|
|
||||||
* @copyright the authors
|
|
||||||
* @author Froxlor team <team@froxlor.org>
|
|
||||||
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Froxlor\Api\Commands;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Froxlor\Api\ApiCommand;
|
|
||||||
use Froxlor\Api\ResourceEntity;
|
|
||||||
use Froxlor\Database\Database;
|
|
||||||
use Froxlor\FileDir;
|
|
||||||
use Froxlor\FroxlorLogger;
|
|
||||||
use Froxlor\Settings;
|
|
||||||
use Froxlor\UI\Response;
|
|
||||||
use Froxlor\Validate\Validate;
|
|
||||||
use PDO;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @since 2.1.0
|
|
||||||
*/
|
|
||||||
class BackupStorages extends ApiCommand implements ResourceEntity
|
|
||||||
{
|
|
||||||
const SUPPORTED_TYPES = [
|
|
||||||
'local',
|
|
||||||
'ftp',
|
|
||||||
'sftp',
|
|
||||||
'rsync',
|
|
||||||
's3',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* lists all backup storages entries
|
|
||||||
*
|
|
||||||
* @param array $sql_search
|
|
||||||
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =),
|
|
||||||
* LIKE is used if left empty and 'value' => searchvalue
|
|
||||||
* @param int $sql_limit
|
|
||||||
* optional specify number of results to be returned
|
|
||||||
* @param int $sql_offset
|
|
||||||
* optional specify offset for resultset
|
|
||||||
* @param array $sql_orderby
|
|
||||||
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more
|
|
||||||
* fields
|
|
||||||
*
|
|
||||||
* @access admin
|
|
||||||
* @return string json-encoded array count|list
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function listing()
|
|
||||||
{
|
|
||||||
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
|
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] list backup storages");
|
|
||||||
$query_fields = [];
|
|
||||||
$result_stmt = Database::prepare("
|
|
||||||
SELECT * FROM `" . TABLE_PANEL_BACKUP_STORAGES . "` ". $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit()
|
|
||||||
);
|
|
||||||
Database::pexecute($result_stmt, $query_fields, true, true);
|
|
||||||
$result = [];
|
|
||||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
|
||||||
$result[] = $row;
|
|
||||||
}
|
|
||||||
return $this->response([
|
|
||||||
'count' => count($result),
|
|
||||||
'list' => $result
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
throw new Exception("Not allowed to execute given command.", 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns the total number of backup storages
|
|
||||||
*
|
|
||||||
* @access admin
|
|
||||||
* @return string json-encoded response message
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function listingCount()
|
|
||||||
{
|
|
||||||
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
|
|
||||||
$result_stmt = Database::prepare("
|
|
||||||
SELECT COUNT(*) as num_backup_storagess
|
|
||||||
FROM `" . TABLE_PANEL_BACKUP_STORAGES . "`
|
|
||||||
");
|
|
||||||
$result = Database::pexecute_first($result_stmt, null, true, true);
|
|
||||||
if ($result) {
|
|
||||||
return $this->response($result['num_backup_storagess']);
|
|
||||||
}
|
|
||||||
$this->response(0);
|
|
||||||
}
|
|
||||||
throw new Exception("Not allowed to execute given command.", 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create a backup storage
|
|
||||||
*
|
|
||||||
* @param string $type
|
|
||||||
* required, backup storage type
|
|
||||||
* @param string $destination_path
|
|
||||||
* required, destination path for backup storage
|
|
||||||
* @param string $description
|
|
||||||
* required, description for backup storage
|
|
||||||
* @param string $region
|
|
||||||
* optional, required if type=s3. Region for backup storage (used for S3)
|
|
||||||
* @param string $bucket
|
|
||||||
* optional, required if type=s3. Bucket for backup storage (used for S3)
|
|
||||||
* @param string $hostname
|
|
||||||
* optional, required if type != local. Hostname for backup storage
|
|
||||||
* @param string $username
|
|
||||||
* optional, required if type != local. Username for backup storage (also used as access key for S3)
|
|
||||||
* @param string $password
|
|
||||||
* optional, required if type != local. Password for backup storage (also used as secret key for S3)
|
|
||||||
* @param string $pgp_public_key
|
|
||||||
* optional, pgp public key for backup storage
|
|
||||||
* @param string $retention
|
|
||||||
* optional, retention for backup storage (default 3)
|
|
||||||
*
|
|
||||||
* @access admin
|
|
||||||
* @return string json-encoded array
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function add()
|
|
||||||
{
|
|
||||||
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
|
|
||||||
// required parameters
|
|
||||||
$type = $this->getParam('type');
|
|
||||||
$destination_path = $this->getParam('destination_path');
|
|
||||||
$description = $this->getParam('description');
|
|
||||||
|
|
||||||
// type related requirements
|
|
||||||
$optional_flags = [
|
|
||||||
'region' => true,
|
|
||||||
'bucket' => true,
|
|
||||||
'hostname' => true,
|
|
||||||
'username' => true,
|
|
||||||
'password' => true,
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!in_array($type, self::SUPPORTED_TYPES)) {
|
|
||||||
throw new Exception("Unsupported storage type: '" . $type . "'", 406);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($type != 'local') {
|
|
||||||
$optional_flags['hostname'] = false;
|
|
||||||
$optional_flags['username'] = false;
|
|
||||||
$optional_flags['password'] = false;
|
|
||||||
}
|
|
||||||
if ($type == 's3') {
|
|
||||||
$optional_flags['region'] = false;
|
|
||||||
$optional_flags['bucket'] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// parameters
|
|
||||||
$region = $this->getParam('region', $optional_flags['region']);
|
|
||||||
$bucket = $this->getParam('bucket', $optional_flags['bucket']);
|
|
||||||
$hostname = $this->getParam('hostname', $optional_flags['hostname']);
|
|
||||||
$username = $this->getParam('username', $optional_flags['username']);
|
|
||||||
$password = $this->getParam('password', $optional_flags['password']);
|
|
||||||
$pgp_public_key = $this->getParam('pgp_public_key', true, null);
|
|
||||||
$retention = $this->getParam('retention', true, 3);
|
|
||||||
|
|
||||||
// validation
|
|
||||||
$destination_path = FileDir::makeCorrectDir(Validate::validate($destination_path, 'destination_path', Validate::REGEX_DIR, '', [], true));
|
|
||||||
// TODO: add more validation
|
|
||||||
|
|
||||||
// pgp public key validation
|
|
||||||
if (!empty($pgp_public_key)) {
|
|
||||||
// check if gnupg extension is loaded
|
|
||||||
if (!extension_loaded('gnupg')) {
|
|
||||||
Response::standardError('gnupgextensionnotavailable', '', true);
|
|
||||||
}
|
|
||||||
// check if the pgp public key is a valid key
|
|
||||||
putenv('GNUPGHOME=' . sys_get_temp_dir());
|
|
||||||
if (gnupg_import(gnupg_init(), $pgp_public_key) === false) {
|
|
||||||
Response::standardError('invalidpgppublickey', '', true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// store
|
|
||||||
$stmt = Database::prepare("
|
|
||||||
INSERT INTO `" . TABLE_PANEL_BACKUP_STORAGES . "` (
|
|
||||||
`description`,
|
|
||||||
`type`,
|
|
||||||
`region`,
|
|
||||||
`bucket`,
|
|
||||||
`destination_path`,
|
|
||||||
`hostname`,
|
|
||||||
`username`,
|
|
||||||
`password`,
|
|
||||||
`pgp_public_key`,
|
|
||||||
`retention`
|
|
||||||
) VALUES (
|
|
||||||
:description,
|
|
||||||
:type,
|
|
||||||
:region,
|
|
||||||
:bucket,
|
|
||||||
:destination_path,
|
|
||||||
:hostname,
|
|
||||||
:username,
|
|
||||||
:password,
|
|
||||||
:pgp_public_key,
|
|
||||||
:retention
|
|
||||||
)
|
|
||||||
");
|
|
||||||
$params = [
|
|
||||||
"description" => $description,
|
|
||||||
"type" => $type,
|
|
||||||
"region" => $region,
|
|
||||||
"bucket" => $bucket,
|
|
||||||
"destination_path" => $destination_path,
|
|
||||||
"hostname" => $hostname,
|
|
||||||
"username" => $username,
|
|
||||||
"password" => $password,
|
|
||||||
"pgp_public_key" => $pgp_public_key,
|
|
||||||
"retention" => $retention,
|
|
||||||
];
|
|
||||||
Database::pexecute($stmt, $params, true, true);
|
|
||||||
$id = Database::lastInsertId();
|
|
||||||
|
|
||||||
// return
|
|
||||||
$result = $this->apiCall('BackupStorages.get', [
|
|
||||||
'id' => $id
|
|
||||||
]);
|
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] added backup storage '" . $result['description'] . "' (" . $result['type'] . ")");
|
|
||||||
return $this->response($result);
|
|
||||||
}
|
|
||||||
throw new Exception("Not allowed to execute given command.", 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return a backup storage entry by id
|
|
||||||
*
|
|
||||||
* @param int $id
|
|
||||||
* the backup-storage-id
|
|
||||||
*
|
|
||||||
* @access admin
|
|
||||||
* @return string json-encoded array
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function get()
|
|
||||||
{
|
|
||||||
$id = $this->getParam('id');
|
|
||||||
|
|
||||||
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
|
|
||||||
$result_stmt = Database::prepare("
|
|
||||||
SELECT * FROM `" . TABLE_PANEL_BACKUP_STORAGES . "`
|
|
||||||
WHERE `id` = :id"
|
|
||||||
);
|
|
||||||
$params = [
|
|
||||||
'id' => $id
|
|
||||||
];
|
|
||||||
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
|
||||||
if ($result) {
|
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] get backup storage '" . $result['description'] . "'");
|
|
||||||
return $this->response($result);
|
|
||||||
}
|
|
||||||
throw new Exception("Backup storage with " . $id . " could not be found", 404);
|
|
||||||
}
|
|
||||||
throw new Exception("Not allowed to execute given command.", 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* update a backup storage by given id
|
|
||||||
*
|
|
||||||
* @param int $id
|
|
||||||
* required, the backup-storage-id
|
|
||||||
* @param string $type
|
|
||||||
* optional, backup storage type
|
|
||||||
* @param string $destination_path
|
|
||||||
* optional, destination path for backup storage
|
|
||||||
* @param string $description
|
|
||||||
* required, description for backup storage
|
|
||||||
* @param string $region
|
|
||||||
* optional, region for backup storage (used for S3)
|
|
||||||
* @param string $bucket
|
|
||||||
* optional, bucket for backup storage (used for S3)
|
|
||||||
* @param string $hostname
|
|
||||||
* optional, hostname for backup storage
|
|
||||||
* @param string $username
|
|
||||||
* optional, username for backup storage (also used as access key for S3)
|
|
||||||
* @param string $password
|
|
||||||
* optional, password for backup storage (also used as secret key for S3)
|
|
||||||
* @param string $pgp_public_key
|
|
||||||
* optional, pgp public key for backup storage
|
|
||||||
* @param string $retention
|
|
||||||
* optional, retention for backup storage (default 3)
|
|
||||||
*
|
|
||||||
* @access admin
|
|
||||||
* @return string json-encoded array
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function update()
|
|
||||||
{
|
|
||||||
$id = $this->getParam('id');
|
|
||||||
|
|
||||||
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
|
|
||||||
// validation
|
|
||||||
$result = $this->apiCall('BackupStorages.get', [
|
|
||||||
'id' => $id
|
|
||||||
]);
|
|
||||||
|
|
||||||
// parameters
|
|
||||||
$description = $this->getParam('description', true, $result['description']);
|
|
||||||
$type = $this->getParam('type', true, $result['type']);
|
|
||||||
$region = $this->getParam('region', true, $result['region']);
|
|
||||||
$bucket = $this->getParam('bucket', true, $result['bucket']);
|
|
||||||
$destination_path = $this->getParam('destination_path', true, $result['destination_path']);
|
|
||||||
$hostname = $this->getParam('hostname', true, $result['hostname']);
|
|
||||||
$username = $this->getParam('username', true, $result['username']);
|
|
||||||
$password = $this->getParam('password', true, '');
|
|
||||||
$pgp_public_key = $this->getParam('pgp_public_key', true, $result['pgp_public_key']);
|
|
||||||
$retention = $this->getParam('retention', true, $result['retention']);
|
|
||||||
|
|
||||||
if (!in_array($type, self::SUPPORTED_TYPES)) {
|
|
||||||
throw new Exception("Unsupported storage type: '" . $type . "'", 406);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($type != 'local') {
|
|
||||||
if (empty($hostname)) {
|
|
||||||
throw new Exception("Field 'hostname' cannot be empty", 406);
|
|
||||||
}
|
|
||||||
if (empty($username)) {
|
|
||||||
throw new Exception("Field 'username' cannot be empty", 406);
|
|
||||||
}
|
|
||||||
$password = Validate::validate($password, 'password', '', '', [], true);
|
|
||||||
}
|
|
||||||
if ($type == 's3') {
|
|
||||||
if (empty($region)) {
|
|
||||||
throw new Exception("Field 'region' cannot be empty", 406);
|
|
||||||
}
|
|
||||||
if (empty($bucket)) {
|
|
||||||
throw new Exception("Field 'bucket' cannot be empty", 406);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// validation
|
|
||||||
$destination_path = FileDir::makeCorrectDir(Validate::validate($destination_path, 'destination_path', Validate::REGEX_DIR, '', [], true));
|
|
||||||
// TODO: add more validation
|
|
||||||
|
|
||||||
// pgp public key validation
|
|
||||||
if (!empty($pgp_public_key) && $pgp_public_key != $result['pgp_public_key']) {
|
|
||||||
// check if gnupg extension is loaded
|
|
||||||
if (!extension_loaded('gnupg')) {
|
|
||||||
Response::standardError('gnupgextensionnotavailable', '', true);
|
|
||||||
}
|
|
||||||
// check if the pgp public key is a valid key
|
|
||||||
putenv('GNUPGHOME=' . sys_get_temp_dir());
|
|
||||||
if (gnupg_import(gnupg_init(), $pgp_public_key) === false) {
|
|
||||||
Response::standardError('invalidpgppublickey', '', true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($password)) {
|
|
||||||
$stmt = Database::prepare("UPDATE `" . TABLE_PANEL_BACKUP_STORAGES . "`
|
|
||||||
SET `password` = :password
|
|
||||||
WHERE `id` = :id
|
|
||||||
");
|
|
||||||
Database::pexecute($stmt, [
|
|
||||||
"id" => $id,
|
|
||||||
"password" => $password
|
|
||||||
], true, true);
|
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] updated password for backup-storage '" . $result['description'] . "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
// update
|
|
||||||
$stmt = Database::prepare("
|
|
||||||
UPDATE `" . TABLE_PANEL_BACKUP_STORAGES . "`
|
|
||||||
SET `description` = :description,
|
|
||||||
`type` = :type,
|
|
||||||
`region` = :region,
|
|
||||||
`bucket` = :bucket,
|
|
||||||
`destination_path` = :destination_path,
|
|
||||||
`hostname` = :hostname,
|
|
||||||
`username` = :username,
|
|
||||||
`pgp_public_key` = :pgp_public_key,
|
|
||||||
`retention` = :retention
|
|
||||||
WHERE `id` = :id
|
|
||||||
");
|
|
||||||
$params = [
|
|
||||||
"id" => $id,
|
|
||||||
"description" => $description,
|
|
||||||
"type" => $type,
|
|
||||||
"region" => $region,
|
|
||||||
"bucket" => $bucket,
|
|
||||||
"destination_path" => $destination_path,
|
|
||||||
"hostname" => $hostname,
|
|
||||||
"username" => $username,
|
|
||||||
"pgp_public_key" => $pgp_public_key,
|
|
||||||
"retention" => $retention,
|
|
||||||
];
|
|
||||||
Database::pexecute($stmt, $params, true, true);
|
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] edited backup storage '" . $result['description'] . "'");
|
|
||||||
|
|
||||||
// return
|
|
||||||
$result = $this->apiCall('BackupStorages.get', [
|
|
||||||
'id' => $id
|
|
||||||
]);
|
|
||||||
return $this->response($result);
|
|
||||||
}
|
|
||||||
throw new Exception("Not allowed to execute given command.", 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* delete a backup-storage entry by id
|
|
||||||
*
|
|
||||||
* @param int $id
|
|
||||||
* required, the backup-storage-id
|
|
||||||
*
|
|
||||||
* @access admin
|
|
||||||
* @return string json-encoded array
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function delete()
|
|
||||||
{
|
|
||||||
$id = $this->getParam('id');
|
|
||||||
|
|
||||||
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
|
|
||||||
// validation
|
|
||||||
$result = $this->apiCall('BackupStorages.get', [
|
|
||||||
'id' => $id
|
|
||||||
]);
|
|
||||||
|
|
||||||
// validate no-one's using it
|
|
||||||
|
|
||||||
// settings
|
|
||||||
if ($id == Settings::Get('backup.default_storage')) {
|
|
||||||
throw new Exception("Given backup storage is currently set as default storage and cannot be deleted.", 406);
|
|
||||||
}
|
|
||||||
// customers
|
|
||||||
$sel_stmt = Database::prepare("
|
|
||||||
SELECT COUNT(*) as num_storage_users
|
|
||||||
FROM `" . TABLE_PANEL_CUSTOMERS . "`
|
|
||||||
WHERE `backup` = :id
|
|
||||||
");
|
|
||||||
$storage_users_result = Database::pexecute_first($sel_stmt, ['id' => $id]);
|
|
||||||
if ($storage_users_result && $storage_users_result['num_storage_users'] > 0) {
|
|
||||||
throw new Exception("Given backup storage is currently assigned to " . $storage_users_result['num_storage_users'] . " customers and cannot be deleted.", 406);
|
|
||||||
}
|
|
||||||
// existing backups
|
|
||||||
$sel_stmt = Database::prepare("
|
|
||||||
SELECT COUNT(*) as num_storage_backups
|
|
||||||
FROM `" . TABLE_PANEL_BACKUPS . "`
|
|
||||||
WHERE `storage_id` = :id
|
|
||||||
");
|
|
||||||
$storage_backups_result = Database::pexecute_first($sel_stmt, ['id' => $id]);
|
|
||||||
if ($storage_backups_result && $storage_backups_result['num_storage_backups'] > 0) {
|
|
||||||
throw new Exception("Given backup storage has still " . $storage_backups_result['num_storage_backups'] . " backups on it and cannot be deleted.", 406);
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete
|
|
||||||
$stmt = Database::prepare("
|
|
||||||
DELETE FROM `" . TABLE_PANEL_BACKUP_STORAGES . "`
|
|
||||||
WHERE `id` = :id
|
|
||||||
");
|
|
||||||
$params = [
|
|
||||||
"id" => $id
|
|
||||||
];
|
|
||||||
Database::pexecute($stmt, $params, true, true);
|
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] deleted backup storage '" . $result['description'] . "'");
|
|
||||||
|
|
||||||
// return
|
|
||||||
return $this->response(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Exception("Not allowed to execute given command.", 403);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,211 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file is part of the Froxlor project.
|
|
||||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, you can also view it online at
|
|
||||||
* https://files.froxlor.org/misc/COPYING.txt
|
|
||||||
*
|
|
||||||
* @copyright the authors
|
|
||||||
* @author Froxlor team <team@froxlor.org>
|
|
||||||
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Froxlor\Api\Commands;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Froxlor\Api\ApiCommand;
|
|
||||||
use Froxlor\Api\ResourceEntity;
|
|
||||||
use Froxlor\Database\Database;
|
|
||||||
use Froxlor\FroxlorLogger;
|
|
||||||
use PDO;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @since 2.1.0
|
|
||||||
*/
|
|
||||||
class Backups extends ApiCommand implements ResourceEntity
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* lists all admin entries
|
|
||||||
*
|
|
||||||
* @param array $sql_search
|
|
||||||
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =),
|
|
||||||
* LIKE is used if left empty and 'value' => searchvalue
|
|
||||||
* @param int $sql_limit
|
|
||||||
* optional specify number of results to be returned
|
|
||||||
* @param int $sql_offset
|
|
||||||
* optional specify offset for resultset
|
|
||||||
* @param array $sql_orderby
|
|
||||||
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more
|
|
||||||
* fields
|
|
||||||
*
|
|
||||||
* @access admin
|
|
||||||
* @return string json-encoded array count|list
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function listing()
|
|
||||||
{
|
|
||||||
if ($this->isAdmin()) {
|
|
||||||
// if we're an admin, list all backups of all the admins customers
|
|
||||||
// or optionally for one specific customer identified by id or loginname
|
|
||||||
$customerid = $this->getParam('customerid', true, 0);
|
|
||||||
$loginname = $this->getParam('loginname', true, '');
|
|
||||||
|
|
||||||
if (!empty($customerid) || !empty($loginname)) {
|
|
||||||
$result = $this->apiCall('Customers.get', [
|
|
||||||
'id' => $customerid,
|
|
||||||
'loginname' => $loginname
|
|
||||||
]);
|
|
||||||
$custom_list_result = [
|
|
||||||
$result
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
$_custom_list_result = $this->apiCall('Customers.listing');
|
|
||||||
$custom_list_result = $_custom_list_result['list'];
|
|
||||||
}
|
|
||||||
$customer_ids = [];
|
|
||||||
foreach ($custom_list_result as $customer) {
|
|
||||||
$customer_ids[] = $customer['customerid'];
|
|
||||||
}
|
|
||||||
if (empty($customer_ids)) {
|
|
||||||
throw new Exception("Required resource unsatisfied.", 405);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$customer_ids = [
|
|
||||||
$this->getUserDetail('customerid')
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] list backups");
|
|
||||||
$query_fields = [];
|
|
||||||
$result_stmt = Database::prepare("
|
|
||||||
SELECT `b`.*, `a`.`loginname` as `adminname`
|
|
||||||
FROM `" . TABLE_PANEL_BACKUPS . "` `b`
|
|
||||||
LEFT JOIN `" . TABLE_PANEL_ADMINS . "` `a` USING(`adminid`)
|
|
||||||
WHERE `b`.`customerid` IN (" . implode(', ', $customer_ids) . ")
|
|
||||||
" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()
|
|
||||||
);
|
|
||||||
Database::pexecute($result_stmt, $query_fields, true, true);
|
|
||||||
$result = [];
|
|
||||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
|
||||||
$result[] = $row;
|
|
||||||
}
|
|
||||||
return $this->response([
|
|
||||||
'count' => count($result),
|
|
||||||
'list' => $result
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns the total number of backups for the given admin
|
|
||||||
*
|
|
||||||
* @access admin
|
|
||||||
* @return string json-encoded response message
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function listingCount()
|
|
||||||
{
|
|
||||||
if ($this->isAdmin()) {
|
|
||||||
// if we're an admin, list all backups of all the admins customers
|
|
||||||
// or optionally for one specific customer identified by id or loginname
|
|
||||||
$customerid = $this->getParam('customerid', true, 0);
|
|
||||||
$loginname = $this->getParam('loginname', true, '');
|
|
||||||
|
|
||||||
if (!empty($customerid) || !empty($loginname)) {
|
|
||||||
$result = $this->apiCall('Customers.get', [
|
|
||||||
'id' => $customerid,
|
|
||||||
'loginname' => $loginname
|
|
||||||
]);
|
|
||||||
$custom_list_result = [
|
|
||||||
$result
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
$_custom_list_result = $this->apiCall('Customers.listing');
|
|
||||||
$custom_list_result = $_custom_list_result['list'];
|
|
||||||
}
|
|
||||||
$customer_ids = [];
|
|
||||||
foreach ($custom_list_result as $customer) {
|
|
||||||
$customer_ids[] = $customer['customerid'];
|
|
||||||
}
|
|
||||||
if (empty($customer_ids)) {
|
|
||||||
throw new Exception("Required resource unsatisfied.", 405);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$customer_ids = [
|
|
||||||
$this->getUserDetail('customerid')
|
|
||||||
];
|
|
||||||
}
|
|
||||||
$result_stmt = Database::prepare("
|
|
||||||
SELECT COUNT(*) as num_backups
|
|
||||||
FROM `" . TABLE_PANEL_BACKUPS . "` `b`
|
|
||||||
WHERE `b`.`customerid` IN (" . implode(', ', $customer_ids) . ")
|
|
||||||
");
|
|
||||||
$result = Database::pexecute_first($result_stmt, null, true, true);
|
|
||||||
if ($result) {
|
|
||||||
return $this->response($result['num_backups']);
|
|
||||||
}
|
|
||||||
$this->response(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* You cannot add a backup entry
|
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function add()
|
|
||||||
{
|
|
||||||
throw new Exception('You cannot add a backup entry', 303);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return a backup entry by id
|
|
||||||
*
|
|
||||||
* @param int $id
|
|
||||||
* optional, the backup-entry-id
|
|
||||||
*
|
|
||||||
* @access admin, customers
|
|
||||||
* @return string json-encoded array
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function get()
|
|
||||||
{
|
|
||||||
throw new Exception("@TODO", 303);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* You cannot update a backup entry
|
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function update()
|
|
||||||
{
|
|
||||||
throw new Exception('You cannot update a backup entry', 303);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* delete a backup entry by id
|
|
||||||
*
|
|
||||||
* @param int $id
|
|
||||||
* required, the backup-entry-id
|
|
||||||
*
|
|
||||||
* @access admin, customer
|
|
||||||
* @return string json-encoded array
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function delete()
|
|
||||||
{
|
|
||||||
throw new Exception("@TODO", 303);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -171,6 +171,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
* create a new customer with default ftp-user and standard-subdomain (if wanted)
|
* create a new customer with default ftp-user and standard-subdomain (if wanted)
|
||||||
*
|
*
|
||||||
* @param string $email
|
* @param string $email
|
||||||
|
* required, email address of new customer
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* optional if company is set, else required
|
* optional if company is set, else required
|
||||||
* @param string $firstname
|
* @param string $firstname
|
||||||
@@ -189,8 +190,11 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
* optional
|
* optional
|
||||||
* @param int $customernumber
|
* @param int $customernumber
|
||||||
* optional
|
* optional
|
||||||
* @param string $def_language ,
|
* @param string $def_language
|
||||||
* optional, default is system-default language
|
* optional, ISO 639-1 language code (e.g. 'en', 'de', see lng-folder for supported languages),
|
||||||
|
* default is system-default language
|
||||||
|
* @param bool $gui_access
|
||||||
|
* optional, allow login via webui, if false ONLY the login via webui is disallowed; default true
|
||||||
* @param bool $api_allowed
|
* @param bool $api_allowed
|
||||||
* optional, default is true if system setting api.enabled is true, else false
|
* optional, default is true if system setting api.enabled is true, else false
|
||||||
* @param int $gender
|
* @param int $gender
|
||||||
@@ -273,13 +277,6 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
* @param array $allowed_mysqlserver
|
* @param array $allowed_mysqlserver
|
||||||
* optional, array of IDs of defined mysql-servers the customer is allowed to use,
|
* optional, array of IDs of defined mysql-servers the customer is allowed to use,
|
||||||
* default is to allow the default dbserver (id=0)
|
* default is to allow the default dbserver (id=0)
|
||||||
* @param int $backup
|
|
||||||
* optional, either 0 to disable backup for this customer or a backup-storage-id
|
|
||||||
* where backups are to be stored, requires change_serversettings permissions,
|
|
||||||
* default is system-setting backup.default_storage
|
|
||||||
* @param bool $access_backups
|
|
||||||
* optional, where the customer is allowed to view backups, default is system-setting
|
|
||||||
* default_customer_access
|
|
||||||
*
|
*
|
||||||
* @access admin
|
* @access admin
|
||||||
* @return string json-encoded array
|
* @return string json-encoded array
|
||||||
@@ -304,6 +301,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
$fax = $this->getParam('fax', true, '');
|
$fax = $this->getParam('fax', true, '');
|
||||||
$customernumber = $this->getParam('customernumber', true, '');
|
$customernumber = $this->getParam('customernumber', true, '');
|
||||||
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
|
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
|
||||||
|
$gui_access = $this->getBoolParam('gui_access', true, 1);
|
||||||
$api_allowed = $this->getBoolParam('api_allowed', true, (Settings::Get('api.enabled') && Settings::Get('api.customer_default')));
|
$api_allowed = $this->getBoolParam('api_allowed', true, (Settings::Get('api.enabled') && Settings::Get('api.customer_default')));
|
||||||
$gender = (int)$this->getParam('gender', true, 0);
|
$gender = (int)$this->getParam('gender', true, 0);
|
||||||
$custom_notes = $this->getParam('custom_notes', true, '');
|
$custom_notes = $this->getParam('custom_notes', true, '');
|
||||||
@@ -366,24 +364,6 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
$p_allowed_mysqlserver = [];
|
$p_allowed_mysqlserver = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->getUserDetail('change_serversettings')) {
|
|
||||||
$backup = $this->getParam('backup', true, Settings::Get('backup.default_storage'));
|
|
||||||
if ($backup > 0) {
|
|
||||||
try {
|
|
||||||
$this->apiCall('BackupStorages.get', [
|
|
||||||
'id' => $backup
|
|
||||||
]);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// not found or other issue, set default
|
|
||||||
$backup = Settings::Get('backup.default_storage');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$access_backups = $this->getBoolParam('access_backups', true, Settings::Get('backup.default_customer_access'));
|
|
||||||
} else {
|
|
||||||
$backup = Settings::Get('backup.default_storage');
|
|
||||||
$access_backups = Settings::Get('backup.default_customer_access');
|
|
||||||
}
|
|
||||||
|
|
||||||
// validation
|
// validation
|
||||||
$name = Validate::validate($name, 'name', Validate::REGEX_DESC_TEXT, '', [], true);
|
$name = Validate::validate($name, 'name', Validate::REGEX_DESC_TEXT, '', [], true);
|
||||||
$firstname = Validate::validate($firstname, 'first name', Validate::REGEX_DESC_TEXT, '', [], true);
|
$firstname = Validate::validate($firstname, 'first name', Validate::REGEX_DESC_TEXT, '', [], true);
|
||||||
@@ -425,11 +405,14 @@ 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)) {
|
||||||
foreach ($p_allowed_mysqlserver as $allowed_ms) {
|
foreach ($p_allowed_mysqlserver as $allowed_ms) {
|
||||||
$allowed_ms = intval($allowed_ms);
|
$allowed_ms = intval($allowed_ms);
|
||||||
$allowed_mysqlserver[] = $allowed_ms;
|
$allowed_mysqlserver[] = $allowed_ms;
|
||||||
@@ -477,6 +460,28 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
if (function_exists('posix_getpwnam') && !in_array("posix_getpwnam", explode(",", ini_get('disable_functions'))) && posix_getpwnam($loginname)) {
|
if (function_exists('posix_getpwnam') && !in_array("posix_getpwnam", explode(",", ini_get('disable_functions'))) && posix_getpwnam($loginname)) {
|
||||||
Response::standardError('loginnameissystemaccount', $loginname, true);
|
Response::standardError('loginnameissystemaccount', $loginname, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// blacklist some system-internal names that might lead to issues
|
||||||
|
Database::needSqlData();
|
||||||
|
$sqldata = Database::getSqlData();
|
||||||
|
Database::needRoot(true);
|
||||||
|
Database::needSqlData();
|
||||||
|
$sqlrdata = Database::getSqlData();
|
||||||
|
$login_blacklist = [
|
||||||
|
'root',
|
||||||
|
'admin',
|
||||||
|
'froxroot',
|
||||||
|
'froxlor',
|
||||||
|
$sqldata['user'],
|
||||||
|
$sqldata['db'],
|
||||||
|
$sqlrdata['user'],
|
||||||
|
];
|
||||||
|
unset($sqldata);
|
||||||
|
unset($sqlrdata);
|
||||||
|
$login_blacklist = array_unique($login_blacklist);
|
||||||
|
if (in_array($loginname, $login_blacklist)) {
|
||||||
|
Response::standardError('loginnameisreservedname', $loginname, true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$accountnumber = intval(Settings::Get('system.lastaccountnumber')) + 1;
|
$accountnumber = intval(Settings::Get('system.lastaccountnumber')) + 1;
|
||||||
$loginname = Settings::Get('customer.accountprefix') . $accountnumber;
|
$loginname = Settings::Get('customer.accountprefix') . $accountnumber;
|
||||||
@@ -540,6 +545,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
'email' => $email,
|
'email' => $email,
|
||||||
'customerno' => $customernumber,
|
'customerno' => $customernumber,
|
||||||
'lang' => $def_language,
|
'lang' => $def_language,
|
||||||
|
'gui_access' => $gui_access,
|
||||||
'api_allowed' => $api_allowed,
|
'api_allowed' => $api_allowed,
|
||||||
'docroot' => $documentroot,
|
'docroot' => $documentroot,
|
||||||
'guid' => $guid,
|
'guid' => $guid,
|
||||||
@@ -562,9 +568,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
'theme' => $_theme,
|
'theme' => $_theme,
|
||||||
'custom_notes' => $custom_notes,
|
'custom_notes' => $custom_notes,
|
||||||
'custom_notes_show' => $custom_notes_show,
|
'custom_notes_show' => $custom_notes_show,
|
||||||
'allowed_mysqlserver' => empty($allowed_mysqlserver) ? "" : json_encode($allowed_mysqlserver),
|
'allowed_mysqlserver' => empty($allowed_mysqlserver) ? "" : json_encode($allowed_mysqlserver)
|
||||||
'backup' => $backup,
|
|
||||||
'access_backups' => $access_backups
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$ins_stmt = Database::prepare("
|
$ins_stmt = Database::prepare("
|
||||||
@@ -584,6 +588,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
`email` = :email,
|
`email` = :email,
|
||||||
`customernumber` = :customerno,
|
`customernumber` = :customerno,
|
||||||
`def_language` = :lang,
|
`def_language` = :lang,
|
||||||
|
`gui_access` = :gui_access,
|
||||||
`api_allowed` = :api_allowed,
|
`api_allowed` = :api_allowed,
|
||||||
`documentroot` = :docroot,
|
`documentroot` = :docroot,
|
||||||
`guid` = :guid,
|
`guid` = :guid,
|
||||||
@@ -607,9 +612,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
`theme` = :theme,
|
`theme` = :theme,
|
||||||
`custom_notes` = :custom_notes,
|
`custom_notes` = :custom_notes,
|
||||||
`custom_notes_show` = :custom_notes_show,
|
`custom_notes_show` = :custom_notes_show,
|
||||||
`allowed_mysqlserver`= :allowed_mysqlserver,
|
`allowed_mysqlserver`= :allowed_mysqlserver
|
||||||
`backup` = :backup,
|
|
||||||
`access_backups` = :access_backups
|
|
||||||
");
|
");
|
||||||
Database::pexecute($ins_stmt, $ins_data, true, true);
|
Database::pexecute($ins_stmt, $ins_data, true, true);
|
||||||
|
|
||||||
@@ -758,6 +761,22 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create default mysql-user if enabled
|
||||||
|
if ($mysqls != 0) {
|
||||||
|
foreach ($allowed_mysqlserver as $dbserver) {
|
||||||
|
// require privileged access for target db-server
|
||||||
|
Database::needRoot(true, $dbserver, false);
|
||||||
|
// get DbManager
|
||||||
|
$dbm = new DbManager($this->logger());
|
||||||
|
// give permission to the user on every access-host we have
|
||||||
|
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
|
||||||
|
$dbm->getManager()->grantPrivilegesTo($loginname, $password, $mysql_access_host, false, false, true);
|
||||||
|
}
|
||||||
|
$dbm->getManager()->flushPrivileges();
|
||||||
|
Database::needRoot(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($sendpassword == '1') {
|
if ($sendpassword == '1') {
|
||||||
$srv_hostname = Settings::Get('system.hostname');
|
$srv_hostname = Settings::Get('system.hostname');
|
||||||
if (Settings::Get('system.froxlordirectlyviahostname') == '0') {
|
if (Settings::Get('system.froxlordirectlyviahostname') == '0') {
|
||||||
@@ -957,6 +976,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
* @param string $loginname
|
* @param string $loginname
|
||||||
* optional, the loginname
|
* optional, the loginname
|
||||||
* @param string $email
|
* @param string $email
|
||||||
|
* optional
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* optional if company is set, else required
|
* optional if company is set, else required
|
||||||
* @param string $firstname
|
* @param string $firstname
|
||||||
@@ -975,8 +995,11 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
* optional
|
* optional
|
||||||
* @param int $customernumber
|
* @param int $customernumber
|
||||||
* optional
|
* optional
|
||||||
* @param string $def_language ,
|
* @param string $def_language
|
||||||
* optional, default is system-default language
|
* * optional, ISO 639-1 language code (e.g. 'en', 'de', see lng-folder for supported languages),
|
||||||
|
* * default is system-default language
|
||||||
|
* @param bool $gui_access
|
||||||
|
* optional, allow login via webui, if false ONLY the login via webui is disallowed; default true
|
||||||
* @param bool $api_allowed
|
* @param bool $api_allowed
|
||||||
* optional, default is true if system setting api.enabled is true, else false
|
* optional, default is true if system setting api.enabled is true, else false
|
||||||
* @param int $gender
|
* @param int $gender
|
||||||
@@ -987,7 +1010,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
* optional, whether to show the content of custom_notes to the customer, default 0
|
* optional, whether to show the content of custom_notes to the customer, default 0
|
||||||
* (false)
|
* (false)
|
||||||
* @param string $new_customer_password
|
* @param string $new_customer_password
|
||||||
* optional, iset new password
|
* optional, set new password
|
||||||
* @param bool $sendpassword
|
* @param bool $sendpassword
|
||||||
* optional, whether to send the password to the customer after creation, default 0
|
* optional, whether to send the password to the customer after creation, default 0
|
||||||
* (false)
|
* (false)
|
||||||
@@ -1057,13 +1080,6 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
* @param array $allowed_mysqlserver
|
* @param array $allowed_mysqlserver
|
||||||
* optional, array of IDs of defined mysql-servers the customer is allowed to use,
|
* optional, array of IDs of defined mysql-servers the customer is allowed to use,
|
||||||
* default is to allow the default dbserver (id=0)
|
* default is to allow the default dbserver (id=0)
|
||||||
* @param int $backup
|
|
||||||
* optional, either 0 to disable backup for this customer or a backup-storage-id
|
|
||||||
* where backups are to be stored, requires change_serversettings permissions,
|
|
||||||
* default is system-setting backup.default_storage
|
|
||||||
* @param bool $access_backups
|
|
||||||
* optional, where the customer is allowed to view backups, default is system-setting
|
|
||||||
* default_customer_access
|
|
||||||
*
|
*
|
||||||
* @access admin, customer
|
* @access admin, customer
|
||||||
* @return string json-encoded array
|
* @return string json-encoded array
|
||||||
@@ -1089,7 +1105,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']);
|
||||||
@@ -1098,6 +1114,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
$fax = $this->getParam('fax', true, $result['fax']);
|
$fax = $this->getParam('fax', true, $result['fax']);
|
||||||
$customernumber = $this->getParam('customernumber', true, $result['customernumber']);
|
$customernumber = $this->getParam('customernumber', true, $result['customernumber']);
|
||||||
$def_language = $this->getParam('def_language', true, $result['def_language']);
|
$def_language = $this->getParam('def_language', true, $result['def_language']);
|
||||||
|
$gui_access = $this->getBoolParam('gui_access', true, $result['gui_access']);
|
||||||
$api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']);
|
$api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']);
|
||||||
$gender = (int)$this->getParam('gender', true, $result['gender']);
|
$gender = (int)$this->getParam('gender', true, $result['gender']);
|
||||||
$custom_notes = $this->getParam('custom_notes', true, $result['custom_notes']);
|
$custom_notes = $this->getParam('custom_notes', true, $result['custom_notes']);
|
||||||
@@ -1125,24 +1142,6 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
$deactivated = $this->getBoolParam('deactivated', true, $result['deactivated']);
|
$deactivated = $this->getBoolParam('deactivated', true, $result['deactivated']);
|
||||||
$theme = $this->getParam('theme', true, $result['theme']);
|
$theme = $this->getParam('theme', true, $result['theme']);
|
||||||
$allowed_mysqlserver = $this->getParam('allowed_mysqlserver', true, json_decode($result['allowed_mysqlserver'], true));
|
$allowed_mysqlserver = $this->getParam('allowed_mysqlserver', true, json_decode($result['allowed_mysqlserver'], true));
|
||||||
|
|
||||||
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
|
|
||||||
$backup = $this->getParam('backup', true, $result['backup']);
|
|
||||||
if ($backup > 0) {
|
|
||||||
try {
|
|
||||||
$this->apiCall('BackupStorages.get', [
|
|
||||||
'id' => $backup
|
|
||||||
]);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// not found or other issue, dont update
|
|
||||||
$backup = $result['backup'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$access_backups = $this->getBoolParam('access_backups', true, Settings::Get('backup.default_customer_access'));
|
|
||||||
} else {
|
|
||||||
$backup = $result['backup'];
|
|
||||||
$access_backups = $result['access_backups'];
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// allowed parameters
|
// allowed parameters
|
||||||
$def_language = $this->getParam('def_language', true, $result['def_language']);
|
$def_language = $this->getParam('def_language', true, $result['def_language']);
|
||||||
@@ -1168,14 +1167,17 @@ 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)) {
|
||||||
$allowed_mysqlserver = $this->getParam('allowed_mysqlserver', true, [0]);
|
$allowed_mysqlserver = $this->getParam('allowed_mysqlserver', true, [0]);
|
||||||
}
|
}
|
||||||
if (! empty($allowed_mysqlserver)) {
|
if (!empty($allowed_mysqlserver)) {
|
||||||
$allowed_mysqlserver = array_map('intval', $allowed_mysqlserver);
|
$allowed_mysqlserver = array_map('intval', $allowed_mysqlserver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1333,12 +1335,34 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$upd_stmt = Database::prepare("
|
$upd_stmt = Database::prepare("
|
||||||
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `deactivated`= :deactivated WHERE `customerid` = :customerid");
|
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `deactivated`= :deactivated WHERE `customerid` = :customerid
|
||||||
|
");
|
||||||
Database::pexecute($upd_stmt, [
|
Database::pexecute($upd_stmt, [
|
||||||
'deactivated' => $deactivated,
|
'deactivated' => $deactivated,
|
||||||
'customerid' => $id
|
'customerid' => $id
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// enable/disable global mysql-user (loginname)
|
||||||
|
$current_allowed_mysqlserver = isset($result['allowed_mysqlserver']) && !empty($result['allowed_mysqlserver']) ? json_decode($result['allowed_mysqlserver'], true) : [];
|
||||||
|
foreach ($current_allowed_mysqlserver as $dbserver) {
|
||||||
|
// require privileged access for target db-server
|
||||||
|
Database::needRoot(true, $dbserver, false);
|
||||||
|
// get DbManager
|
||||||
|
$dbm = new DbManager($this->logger());
|
||||||
|
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
|
||||||
|
// Prevent access, if deactivated
|
||||||
|
if ($deactivated) {
|
||||||
|
// failsafe if user has been deleted manually (requires MySQL 4.1.2+)
|
||||||
|
$dbm->getManager()->disableUser($result['loginname'], $mysql_access_host);
|
||||||
|
} else {
|
||||||
|
// Otherwise grant access
|
||||||
|
$dbm->getManager()->enableUser($result['loginname'], $mysql_access_host, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$dbm->getManager()->flushPrivileges();
|
||||||
|
Database::needRoot(false);
|
||||||
|
}
|
||||||
|
|
||||||
// Retrieve customer's databases
|
// Retrieve customer's databases
|
||||||
$databases_stmt = Database::prepare("SELECT * FROM " . TABLE_PANEL_DATABASES . " WHERE customerid = :customerid ORDER BY `dbserver`");
|
$databases_stmt = Database::prepare("SELECT * FROM " . TABLE_PANEL_DATABASES . " WHERE customerid = :customerid ORDER BY `dbserver`");
|
||||||
Database::pexecute($databases_stmt, [
|
Database::pexecute($databases_stmt, [
|
||||||
@@ -1359,9 +1383,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
$last_dbserver = $row_database['dbserver'];
|
$last_dbserver = $row_database['dbserver'];
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (array_unique(explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
|
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
|
||||||
$mysql_access_host = trim($mysql_access_host);
|
|
||||||
|
|
||||||
// Prevent access, if deactivated
|
// Prevent access, if deactivated
|
||||||
if ($deactivated) {
|
if ($deactivated) {
|
||||||
// failsafe if user has been deleted manually (requires MySQL 4.1.2+)
|
// failsafe if user has been deleted manually (requires MySQL 4.1.2+)
|
||||||
@@ -1450,10 +1472,9 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
'logviewenabled' => $logviewenabled,
|
'logviewenabled' => $logviewenabled,
|
||||||
'custom_notes' => $custom_notes,
|
'custom_notes' => $custom_notes,
|
||||||
'custom_notes_show' => $custom_notes_show,
|
'custom_notes_show' => $custom_notes_show,
|
||||||
|
'gui_access' => $gui_access,
|
||||||
'api_allowed' => $api_allowed,
|
'api_allowed' => $api_allowed,
|
||||||
'allowed_mysqlserver' => empty($allowed_mysqlserver) ? "" : json_encode($allowed_mysqlserver),
|
'allowed_mysqlserver' => empty($allowed_mysqlserver) ? "" : json_encode($allowed_mysqlserver)
|
||||||
'backup' => $backup,
|
|
||||||
'access_backups' => $access_backups
|
|
||||||
];
|
];
|
||||||
$upd_data += $admin_upd_data;
|
$upd_data += $admin_upd_data;
|
||||||
}
|
}
|
||||||
@@ -1495,10 +1516,9 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
`logviewenabled` = :logviewenabled,
|
`logviewenabled` = :logviewenabled,
|
||||||
`custom_notes` = :custom_notes,
|
`custom_notes` = :custom_notes,
|
||||||
`custom_notes_show` = :custom_notes_show,
|
`custom_notes_show` = :custom_notes_show,
|
||||||
|
`gui_access` = :gui_access,
|
||||||
`api_allowed` = :api_allowed,
|
`api_allowed` = :api_allowed,
|
||||||
`allowed_mysqlserver` = :allowed_mysqlserver,
|
`allowed_mysqlserver` = :allowed_mysqlserver";
|
||||||
`backup`= :backup,
|
|
||||||
`access_backups` = :access_backups";
|
|
||||||
$upd_query .= $admin_upd_query;
|
$upd_query .= $admin_upd_query;
|
||||||
}
|
}
|
||||||
$upd_query .= " WHERE `customerid` = :customerid";
|
$upd_query .= " WHERE `customerid` = :customerid";
|
||||||
@@ -1654,6 +1674,21 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
]);
|
]);
|
||||||
$id = $result['customerid'];
|
$id = $result['customerid'];
|
||||||
|
|
||||||
|
// remove global mysql-user (loginname)
|
||||||
|
$current_allowed_mysqlserver = isset($result['allowed_mysqlserver']) && !empty($result['allowed_mysqlserver']) ? json_decode($result['allowed_mysqlserver'], true) : [];
|
||||||
|
foreach ($current_allowed_mysqlserver as $dbserver) {
|
||||||
|
// require privileged access for target db-server
|
||||||
|
Database::needRoot(true, $dbserver, false);
|
||||||
|
// get DbManager
|
||||||
|
$dbm = new DbManager($this->logger());
|
||||||
|
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
|
||||||
|
$dbm->getManager()->deleteUser($result['loginname'], $mysql_access_host);
|
||||||
|
}
|
||||||
|
$dbm->getManager()->flushPrivileges();
|
||||||
|
Database::needRoot(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove all databases
|
||||||
$databases_stmt = Database::prepare("
|
$databases_stmt = Database::prepare("
|
||||||
SELECT * FROM `" . TABLE_PANEL_DATABASES . "`
|
SELECT * FROM `" . TABLE_PANEL_DATABASES . "`
|
||||||
WHERE `customerid` = :id ORDER BY `dbserver`
|
WHERE `customerid` = :id ORDER BY `dbserver`
|
||||||
@@ -1669,8 +1704,8 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
$priv_changed = false;
|
$priv_changed = false;
|
||||||
while ($row_database = $databases_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($row_database = $databases_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
if ($last_dbserver != $row_database['dbserver']) {
|
if ($last_dbserver != $row_database['dbserver']) {
|
||||||
Database::needRoot(true, $row_database['dbserver']);
|
|
||||||
$dbm->getManager()->flushPrivileges();
|
$dbm->getManager()->flushPrivileges();
|
||||||
|
Database::needRoot(true, $row_database['dbserver']);
|
||||||
$last_dbserver = $row_database['dbserver'];
|
$last_dbserver = $row_database['dbserver'];
|
||||||
}
|
}
|
||||||
$dbm->getManager()->deleteDatabase($row_database['databasename']);
|
$dbm->getManager()->deleteDatabase($row_database['databasename']);
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ class DirOptions extends ApiCommand implements ResourceEntity
|
|||||||
// validation
|
// validation
|
||||||
$path = FileDir::makeCorrectDir(Validate::validate($path, 'path', Validate::REGEX_DIR, '', [], true));
|
$path = FileDir::makeCorrectDir(Validate::validate($path, 'path', Validate::REGEX_DIR, '', [], true));
|
||||||
$userpath = $path;
|
$userpath = $path;
|
||||||
$path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path);
|
$path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path, $customer['documentroot']);
|
||||||
|
|
||||||
if (!empty($error404path)) {
|
if (!empty($error404path)) {
|
||||||
$error404path = $this->correctErrorDocument($error404path, true);
|
$error404path = $this->correctErrorDocument($error404path, true);
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class DirProtections extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
// validation
|
// validation
|
||||||
$path = FileDir::makeCorrectDir(Validate::validate($path, 'path', Validate::REGEX_DIR, '', [], true));
|
$path = FileDir::makeCorrectDir(Validate::validate($path, 'path', Validate::REGEX_DIR, '', [], true));
|
||||||
$path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path);
|
$path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path, $customer['documentroot']);
|
||||||
$username = Validate::validate($username, 'username', '/^[a-zA-Z0-9][a-zA-Z0-9\-_]+\$?$/', '', [], true);
|
$username = Validate::validate($username, 'username', '/^[a-zA-Z0-9][a-zA-Z0-9\-_]+\$?$/', '', [], true);
|
||||||
$authname = Validate::validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', [], true);
|
$authname = Validate::validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', [], true);
|
||||||
$password = Validate::validate($password, 'password', '', '', [], true);
|
$password = Validate::validate($password, 'password', '', '', [], true);
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ class DomainZones extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
// validation
|
// validation
|
||||||
$errors = [];
|
$errors = [];
|
||||||
if (empty($record)) {
|
if (empty(trim($record))) {
|
||||||
$record = "@";
|
$record = "@";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +227,7 @@ class DomainZones extends ApiCommand implements ResourceEntity
|
|||||||
// remove it for checks
|
// remove it for checks
|
||||||
$content = substr($content, 0, -1);
|
$content = substr($content, 0, -1);
|
||||||
}
|
}
|
||||||
if (!Validate::validateDomain($content)) {
|
if (!empty($content) && !Validate::validateDomain($content)) {
|
||||||
$errors[] = lng('error.dns_mx_needdom');
|
$errors[] = lng('error.dns_mx_needdom');
|
||||||
} else {
|
} else {
|
||||||
// check whether there is a CNAME-record for the same resource
|
// check whether there is a CNAME-record for the same resource
|
||||||
@@ -244,6 +244,10 @@ class DomainZones extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
// append trailing dot (again)
|
// append trailing dot (again)
|
||||||
$content .= '.';
|
$content .= '.';
|
||||||
|
// if content is only ".", the prio needs to be 0 which results in a "null mx" entry
|
||||||
|
if ($content == '.' && $prio != 0) {
|
||||||
|
$prio = 0;
|
||||||
|
}
|
||||||
} elseif ($type == 'NS') {
|
} elseif ($type == 'NS') {
|
||||||
// check for trailing dot
|
// check for trailing dot
|
||||||
if (substr($content, -1) == '.') {
|
if (substr($content, -1) == '.') {
|
||||||
|
|||||||
@@ -316,9 +316,9 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, -1);
|
$mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, -1);
|
||||||
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, 0);
|
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, 0);
|
||||||
$letsencrypt = $this->getBoolParam('letsencrypt', true, 0);
|
$letsencrypt = $this->getBoolParam('letsencrypt', true, 0);
|
||||||
|
$sslenabled = $this->getBoolParam('sslenabled', true, 1);
|
||||||
$dont_use_default_ssl_ipandport_if_empty = $this->getBoolParam('dont_use_default_ssl_ipandport_if_empty', true, 0);
|
$dont_use_default_ssl_ipandport_if_empty = $this->getBoolParam('dont_use_default_ssl_ipandport_if_empty', true, 0);
|
||||||
$p_ssl_ipandports = $this->getParam('ssl_ipandport', true, $dont_use_default_ssl_ipandport_if_empty ? [] : explode(',', Settings::Get('system.defaultsslip')));
|
$p_ssl_ipandports = $this->getParam('ssl_ipandport', true, $dont_use_default_ssl_ipandport_if_empty ? [] : explode(',', Settings::Get('system.defaultsslip')));
|
||||||
$sslenabled = $this->getBoolParam('sslenabled', true, 1);
|
|
||||||
$http2 = $this->getBoolParam('http2', true, 0);
|
$http2 = $this->getBoolParam('http2', true, 0);
|
||||||
$hsts_maxage = $this->getParam('hsts_maxage', true, 0);
|
$hsts_maxage = $this->getParam('hsts_maxage', true, 0);
|
||||||
$hsts_sub = $this->getBoolParam('hsts_sub', true, 0);
|
$hsts_sub = $this->getBoolParam('hsts_sub', true, 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) {
|
||||||
@@ -544,6 +547,10 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$ssl_specialsettings = Validate::validate(str_replace("\r\n", "\n", $ssl_specialsettings), 'ssl_specialsettings', '/^[^\0]*$/', '', [], true);
|
$ssl_specialsettings = Validate::validate(str_replace("\r\n", "\n", $ssl_specialsettings), 'ssl_specialsettings', '/^[^\0]*$/', '', [], true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (Settings::Get('system.use_ssl') == "1" && $sslenabled == 1 && empty($ssl_ipandports)) {
|
||||||
|
// enabled ssl for the domain but no ssl ip/port is selected
|
||||||
|
Response::standardError('nosslippportgiven', '', true);
|
||||||
|
}
|
||||||
if (Settings::Get('system.use_ssl') == "0" || empty($ssl_ipandports)) {
|
if (Settings::Get('system.use_ssl') == "0" || empty($ssl_ipandports)) {
|
||||||
$ssl_redirect = 0;
|
$ssl_redirect = 0;
|
||||||
$letsencrypt = 0;
|
$letsencrypt = 0;
|
||||||
@@ -824,6 +831,9 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
// Using nameserver, insert a task which rebuilds the server config
|
// Using nameserver, insert a task which rebuilds the server config
|
||||||
Cronjob::inserttask(TaskId::REBUILD_DNS);
|
Cronjob::inserttask(TaskId::REBUILD_DNS);
|
||||||
|
if ($dkim == '1') {
|
||||||
|
Cronjob::inserttask(TaskId::REBUILD_RSPAMD);
|
||||||
|
}
|
||||||
|
|
||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added domain '" . $domain . "'");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added domain '" . $domain . "'");
|
||||||
|
|
||||||
@@ -1207,7 +1217,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$p_ssl_ipandports = $this->getParam('ssl_ipandport', true, $remove_ssl_ipandport ? [
|
$p_ssl_ipandports = $this->getParam('ssl_ipandport', true, $remove_ssl_ipandport ? [
|
||||||
-1
|
-1
|
||||||
] : null);
|
] : null);
|
||||||
$sslenabled = $this->getBoolParam('sslenabled', true, $result['ssl_enabled']);
|
$sslenabled = $remove_ssl_ipandport ? false : $this->getBoolParam('sslenabled', true, $result['ssl_enabled']);
|
||||||
$http2 = $this->getBoolParam('http2', true, $result['http2']);
|
$http2 = $this->getBoolParam('http2', true, $result['http2']);
|
||||||
$hsts_maxage = $this->getParam('hsts_maxage', true, $result['hsts']);
|
$hsts_maxage = $this->getParam('hsts_maxage', true, $result['hsts']);
|
||||||
$hsts_sub = $this->getBoolParam('hsts_sub', true, $result['hsts_sub']);
|
$hsts_sub = $this->getBoolParam('hsts_sub', true, $result['hsts_sub']);
|
||||||
@@ -1401,7 +1411,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$zonefile = $result['zonefile'];
|
$zonefile = $result['zonefile'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::Get('dkim.use_dkim') != '1') {
|
if (Settings::Get('antispam.activated') != '1') {
|
||||||
$dkim = $result['dkim'];
|
$dkim = $result['dkim'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1517,13 +1527,16 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
if ($remove_ssl_ipandport || (!empty($p_ssl_ipandports) && $p_ssl_ipandports[0] == -1)) {
|
if ($remove_ssl_ipandport || (!empty($p_ssl_ipandports) && $p_ssl_ipandports[0] == -1)) {
|
||||||
$ssl_ipandports = [];
|
$ssl_ipandports = [];
|
||||||
}
|
}
|
||||||
if (Settings::Get('system.use_ssl') == "0" || empty($ssl_ipandports)) {
|
if (Settings::Get('system.use_ssl') == "1" && $sslenabled && empty($ssl_ipandports)) {
|
||||||
|
// enabled ssl for the domain but no ssl ip/port is selected
|
||||||
|
Response::standardError('nosslippportgiven', '', true);
|
||||||
|
}
|
||||||
|
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;
|
||||||
@@ -1553,7 +1566,7 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
|
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
|
||||||
if ($ssl_redirect > 0 && $letsencrypt == 1 && $result['letsencrypt'] != $letsencrypt) {
|
if (($result['letsencrypt'] != $letsencrypt || $result['ssl_redirect'] != $ssl_redirect) && $ssl_redirect > 0 && $letsencrypt == 1) {
|
||||||
$ssl_redirect = 2;
|
$ssl_redirect = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1642,6 +1655,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']
|
||||||
@@ -1659,10 +1673,15 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($dkim != $result['dkim']) {
|
||||||
|
Cronjob::inserttask(TaskId::REBUILD_RSPAMD);
|
||||||
|
}
|
||||||
|
|
||||||
if ($speciallogfile != $result['speciallogfile'] && $speciallogverified != '1') {
|
if ($speciallogfile != $result['speciallogfile'] && $speciallogverified != '1') {
|
||||||
$speciallogfile = $result['speciallogfile'];
|
$speciallogfile = $result['speciallogfile'];
|
||||||
}
|
}
|
||||||
@@ -1807,7 +1826,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;
|
||||||
@@ -2086,6 +2105,8 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
* @param bool $is_stdsubdomain
|
* @param bool $is_stdsubdomain
|
||||||
* optional, default false, specify whether it's a std-subdomain you are deleting as it does not count
|
* optional, default false, specify whether it's a std-subdomain you are deleting as it does not count
|
||||||
* as subdomain-resource
|
* as subdomain-resource
|
||||||
|
* @param bool $delete_userfiles
|
||||||
|
* optional, delete email account files on filesystem (if any), default false
|
||||||
*
|
*
|
||||||
* @access admin
|
* @access admin
|
||||||
* @return string json-encoded array
|
* @return string json-encoded array
|
||||||
@@ -2097,7 +2118,8 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$id = $this->getParam('id', true, 0);
|
$id = $this->getParam('id', true, 0);
|
||||||
$dn_optional = $id > 0;
|
$dn_optional = $id > 0;
|
||||||
$domainname = $this->getParam('domainname', $dn_optional, '');
|
$domainname = $this->getParam('domainname', $dn_optional, '');
|
||||||
$is_stdsubdomain = $this->getParam('is_stdsubdomain', true, 0);
|
$is_stdsubdomain = $this->getBoolParam('is_stdsubdomain', true, 0);
|
||||||
|
$delete_user_emailfiles = $this->getBoolParam('delete_userfiles', true, 0);
|
||||||
|
|
||||||
$result = $this->apiCall('Domains.get', [
|
$result = $this->apiCall('Domains.get', [
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
@@ -2121,6 +2143,14 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
$idString = implode(' OR ', $idString);
|
$idString = implode(' OR ', $idString);
|
||||||
|
|
||||||
if ($idString != '') {
|
if ($idString != '') {
|
||||||
|
if ($delete_user_emailfiles) {
|
||||||
|
// determine all connected email-accounts
|
||||||
|
$emailaccount_sel = Database::prepare("SELECT `email`, `homedir`, `maildir` FROM `" . TABLE_MAIL_USERS . "` WHERE " . $idString);
|
||||||
|
Database::pexecute($emailaccount_sel, $paramString, true, true);
|
||||||
|
while ($emailacc_row = $emailaccount_sel->fetch(PDO::FETCH_ASSOC)) {
|
||||||
|
Cronjob::inserttask(TaskId::DELETE_EMAIL_DATA, $emailacc_row['email'], FileDir::makeCorrectDir($emailacc_row['homedir'] . '/' . $emailacc_row['maildir']));
|
||||||
|
}
|
||||||
|
}
|
||||||
$del_stmt = Database::prepare("
|
$del_stmt = Database::prepare("
|
||||||
DELETE FROM `" . TABLE_MAIL_USERS . "` WHERE " . $idString);
|
DELETE FROM `" . TABLE_MAIL_USERS . "` WHERE " . $idString);
|
||||||
Database::pexecute($del_stmt, $paramString, true, true);
|
Database::pexecute($del_stmt, $paramString, true, true);
|
||||||
@@ -2313,6 +2343,10 @@ class Domains extends ApiCommand implements ResourceEntity
|
|||||||
unset($result['wwwserveralias']);
|
unset($result['wwwserveralias']);
|
||||||
unset($result['iswildcarddomain']);
|
unset($result['iswildcarddomain']);
|
||||||
|
|
||||||
|
// translate sslenabled flag
|
||||||
|
$result['sslenabled'] = $result['ssl_enabled'];
|
||||||
|
unset($result['ssl_enabled']);
|
||||||
|
|
||||||
$additional_params = $this->getParamList();
|
$additional_params = $this->getParamList();
|
||||||
// unset unneeded params from this call
|
// unset unneeded params from this call
|
||||||
unset($additional_params['id']);
|
unset($additional_params['id']);
|
||||||
|
|||||||
@@ -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:
|
||||||
@@ -523,7 +523,7 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
|
|||||||
$result = $this->apiCall('Emails.get', [
|
$result = $this->apiCall('Emails.get', [
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
'emailaddr' => $emailaddr
|
'emailaddr' => $emailaddr
|
||||||
]);
|
], true);
|
||||||
$id = $result['id'];
|
$id = $result['id'];
|
||||||
|
|
||||||
if (empty($result['popaccountid']) || $result['popaccountid'] == 0) {
|
if (empty($result['popaccountid']) || $result['popaccountid'] == 0) {
|
||||||
@@ -563,7 +563,7 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($delete_userfiles) {
|
if ($delete_userfiles) {
|
||||||
Cronjob::inserttask(TaskId::DELETE_EMAIL_DATA, $customer['loginname'], $result['email_full']);
|
Cronjob::inserttask(TaskId::DELETE_EMAIL_DATA, $customer['loginname'], FileDir::makeCorrectDir($result['homedir'] . '/' . $result['maildir']));
|
||||||
}
|
}
|
||||||
|
|
||||||
// decrease usage for customer
|
// decrease usage for customer
|
||||||
|
|||||||
@@ -28,10 +28,12 @@ namespace Froxlor\Api\Commands;
|
|||||||
use Exception;
|
use Exception;
|
||||||
use Froxlor\Api\ApiCommand;
|
use Froxlor\Api\ApiCommand;
|
||||||
use Froxlor\Api\ResourceEntity;
|
use Froxlor\Api\ResourceEntity;
|
||||||
|
use Froxlor\Cron\TaskId;
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
use Froxlor\FroxlorLogger;
|
use Froxlor\FroxlorLogger;
|
||||||
use Froxlor\Idna\IdnaWrapper;
|
use Froxlor\Idna\IdnaWrapper;
|
||||||
use Froxlor\Settings;
|
use Froxlor\Settings;
|
||||||
|
use Froxlor\System\Cronjob;
|
||||||
use Froxlor\UI\Response;
|
use Froxlor\UI\Response;
|
||||||
use Froxlor\Validate\Validate;
|
use Froxlor\Validate\Validate;
|
||||||
use PDO;
|
use PDO;
|
||||||
@@ -49,6 +51,14 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
* name of the address before @
|
* name of the address before @
|
||||||
* @param string $domain
|
* @param string $domain
|
||||||
* domain-name for the email-address
|
* domain-name for the email-address
|
||||||
|
* @param float $spam_tag_level
|
||||||
|
* optional, score which is required to tag emails as spam, default: 7.0
|
||||||
|
* @param float $spam_kill_level
|
||||||
|
* optional, score which is required to discard emails, default: 14.0
|
||||||
|
* @param boolean $bypass_spam
|
||||||
|
* optional, disable spam-filter entirely, default: no
|
||||||
|
* @param boolean $policy_greylist
|
||||||
|
* optional, enable grey-listing, default: yes
|
||||||
* @param boolean $iscatchall
|
* @param boolean $iscatchall
|
||||||
* optional, make this address a catchall address, default: no
|
* optional, make this address a catchall address, default: no
|
||||||
* @param int $customerid
|
* @param int $customerid
|
||||||
@@ -74,6 +84,10 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
$domain = $this->getParam('domain');
|
$domain = $this->getParam('domain');
|
||||||
|
|
||||||
// parameters
|
// parameters
|
||||||
|
$spam_tag_level = $this->getParam('spam_tag_level', true, '7.0');
|
||||||
|
$spam_kill_level = $this->getParam('spam_kill_level', true, '14.0');
|
||||||
|
$bypass_spam = $this->getBoolParam('bypass_spam', true, 0);
|
||||||
|
$policy_greylist = $this->getBoolParam('policy_greylist', true, 1);
|
||||||
$iscatchall = $this->getBoolParam('iscatchall', true, 0);
|
$iscatchall = $this->getBoolParam('iscatchall', true, 0);
|
||||||
$description = $this->getParam('description', true, '');
|
$description = $this->getParam('description', true, '');
|
||||||
|
|
||||||
@@ -140,11 +154,19 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$spam_tag_level = Validate::validate($spam_tag_level, 'spam_tag_level', '/^\d{1,}(\.\d{1,2})?$/', '', [7.0], true);
|
||||||
|
$spam_kill_level = Validate::validate($spam_kill_level, 'spam_kill_level', '/^\d{1,}(\.\d{1,2})?$/', '', [14.0], true);
|
||||||
|
$description = Validate::validate(trim($description), 'description', Validate::REGEX_DESC_TEXT, '', [], true);
|
||||||
|
|
||||||
$stmt = Database::prepare("
|
$stmt = Database::prepare("
|
||||||
INSERT INTO `" . TABLE_MAIL_VIRTUAL . "` SET
|
INSERT INTO `" . TABLE_MAIL_VIRTUAL . "` SET
|
||||||
`customerid` = :cid,
|
`customerid` = :cid,
|
||||||
`email` = :email,
|
`email` = :email,
|
||||||
`email_full` = :email_full,
|
`email_full` = :email_full,
|
||||||
|
`spam_tag_level` = :spam_tag_level,
|
||||||
|
`spam_kill_level` = :spam_kill_level,
|
||||||
|
`bypass_spam` = :bypass_spam,
|
||||||
|
`policy_greylist` = :policy_greylist,
|
||||||
`iscatchall` = :iscatchall,
|
`iscatchall` = :iscatchall,
|
||||||
`domainid` = :domainid,
|
`domainid` = :domainid,
|
||||||
`description` = :description
|
`description` = :description
|
||||||
@@ -153,6 +175,10 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
"cid" => $customer['customerid'],
|
"cid" => $customer['customerid'],
|
||||||
"email" => $email,
|
"email" => $email,
|
||||||
"email_full" => $email_full,
|
"email_full" => $email_full,
|
||||||
|
"spam_tag_level" => $spam_tag_level,
|
||||||
|
"spam_kill_level" => $spam_kill_level,
|
||||||
|
"bypass_spam" => $bypass_spam,
|
||||||
|
"policy_greylist" => $policy_greylist,
|
||||||
"iscatchall" => $iscatchall,
|
"iscatchall" => $iscatchall,
|
||||||
"domainid" => $domain_check['id'],
|
"domainid" => $domain_check['id'],
|
||||||
"description" => $description
|
"description" => $description
|
||||||
@@ -162,6 +188,7 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
// update customer usage
|
// update customer usage
|
||||||
Customers::increaseUsage($customer['customerid'], 'emails_used');
|
Customers::increaseUsage($customer['customerid'], 'emails_used');
|
||||||
|
|
||||||
|
Cronjob::inserttask(TaskId::REBUILD_RSPAMD);
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added email address '" . $email_full . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added email address '" . $email_full . "'");
|
||||||
|
|
||||||
$result = $this->apiCall('Emails.get', [
|
$result = $this->apiCall('Emails.get', [
|
||||||
@@ -194,12 +221,12 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
$customer_ids = $this->getAllowedCustomerIds('email');
|
$customer_ids = $this->getAllowedCustomerIds('email');
|
||||||
$params['idea'] = ($id <= 0 ? $emailaddr : $id);
|
$params['idea'] = ($id <= 0 ? $emailaddr : $id);
|
||||||
|
|
||||||
$result_stmt = Database::prepare("SELECT v.`id`, v.`email`, v.`email_full`, v.`iscatchall`, v.`destination`, v.`customerid`, v.`popaccountid`, v.`domainid`, v.`description`, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize`
|
$result_stmt = Database::prepare("SELECT v.*, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize` " . ($this->isInternal() ? ", `u`.`homedir`, `u`.`maildir`" : "") . "
|
||||||
FROM `" . TABLE_MAIL_VIRTUAL . "` v
|
FROM `" . TABLE_MAIL_VIRTUAL . "` v
|
||||||
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON v.`popaccountid` = u.`id`
|
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON v.`popaccountid` = u.`id`
|
||||||
WHERE v.`customerid` IN (" . implode(", ", $customer_ids) . ")
|
WHERE v.`customerid` IN (" . implode(", ", $customer_ids) . ")
|
||||||
AND " . (is_numeric($params['idea']) ? "v.`id`= :idea" : "(v.`email` = :idea OR v.`email_full` = :idea)")
|
AND " . (is_numeric($params['idea']) ? "v.`id`= :idea" : "(v.`email` = :idea OR v.`email_full` = :idea)"
|
||||||
);
|
));
|
||||||
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
$result = Database::pexecute_first($result_stmt, $params, true, true);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] get email address '" . $result['email_full'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] get email address '" . $result['email_full'] . "'");
|
||||||
@@ -220,6 +247,14 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
* optional, required when called as admin (if $loginname is not specified)
|
* optional, required when called as admin (if $loginname is not specified)
|
||||||
* @param string $loginname
|
* @param string $loginname
|
||||||
* optional, required when called as admin (if $customerid is not specified)
|
* optional, required when called as admin (if $customerid is not specified)
|
||||||
|
* @param float $spam_tag_level
|
||||||
|
* optional, score which is required to tag emails as spam, default: 7.0
|
||||||
|
* @param float $spam_kill_level
|
||||||
|
* optional, score which is required to discard emails, default: 14.0
|
||||||
|
* @param boolean $bypass_spam
|
||||||
|
* optional, disable spam-filter entirely, default: no
|
||||||
|
* @param boolean $policy_greylist
|
||||||
|
* optional, enable grey-listing, default: yes
|
||||||
* @param boolean $iscatchall
|
* @param boolean $iscatchall
|
||||||
* optional
|
* optional
|
||||||
* @param string $description
|
* @param string $description
|
||||||
@@ -235,15 +270,6 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
throw new Exception("You cannot access this resource", 405);
|
throw new Exception("You cannot access this resource", 405);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if enabling catchall is not allowed by settings, we do not need
|
|
||||||
// to run update()
|
|
||||||
if (Settings::Get('catchall.catchall_enabled') != '1') {
|
|
||||||
Response::standardError([
|
|
||||||
'operationnotpermitted',
|
|
||||||
'featureisdisabled'
|
|
||||||
], 'catchall', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$id = $this->getParam('id', true, 0);
|
$id = $this->getParam('id', true, 0);
|
||||||
$ea_optional = $id > 0;
|
$ea_optional = $id > 0;
|
||||||
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
|
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
|
||||||
@@ -255,15 +281,32 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
$id = $result['id'];
|
$id = $result['id'];
|
||||||
|
|
||||||
// parameters
|
// parameters
|
||||||
|
$spam_tag_level = $this->getParam('spam_tag_level', true, $result['spam_tag_level']);
|
||||||
|
$spam_kill_level = $this->getParam('spam_kill_level', true, $result['spam_kill_level']);
|
||||||
|
$bypass_spam = $this->getBoolParam('bypass_spam', true, $result['bypass_spam']);
|
||||||
|
$policy_greylist = $this->getBoolParam('policy_greylist', true, $result['policy_greylist']);
|
||||||
$iscatchall = $this->getBoolParam('iscatchall', true, $result['iscatchall']);
|
$iscatchall = $this->getBoolParam('iscatchall', true, $result['iscatchall']);
|
||||||
$description = $this->getParam('description', true, $result['description']);
|
$description = $this->getParam('description', true, $result['description']);
|
||||||
|
|
||||||
|
// if enabling catchall is not allowed by settings, we do not need
|
||||||
|
// to run update()
|
||||||
|
if ($iscatchall && $result['iscatchall'] == 0 && Settings::Get('catchall.catchall_enabled') != '1') {
|
||||||
|
Response::standardError([
|
||||||
|
'operationnotpermitted',
|
||||||
|
'featureisdisabled'
|
||||||
|
], 'catchall', true);
|
||||||
|
}
|
||||||
|
|
||||||
// get needed customer info to reduce the email-address-counter by one
|
// get needed customer info to reduce the email-address-counter by one
|
||||||
$customer = $this->getCustomerData();
|
$customer = $this->getCustomerData();
|
||||||
|
|
||||||
// check for catchall-flag
|
// check for catchall-flag
|
||||||
|
$email = $result['email_full'];
|
||||||
if ($iscatchall) {
|
if ($iscatchall) {
|
||||||
$iscatchall = '1';
|
$iscatchall = '1';
|
||||||
|
$email = $result['email'];
|
||||||
|
// update only required if it was not a catchall before
|
||||||
|
if ($result['iscatchall'] == 0) {
|
||||||
$email_parts = explode('@', $result['email_full']);
|
$email_parts = explode('@', $result['email_full']);
|
||||||
$email = '@' . $email_parts[1];
|
$email = '@' . $email_parts[1];
|
||||||
// catchall check
|
// catchall check
|
||||||
@@ -279,24 +322,37 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
if ($email_check) {
|
if ($email_check) {
|
||||||
Response::standardError('youhavealreadyacatchallforthisdomain', '', true);
|
Response::standardError('youhavealreadyacatchallforthisdomain', '', true);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
$iscatchall = '0';
|
|
||||||
$email = $result['email_full'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$spam_tag_level = Validate::validate($spam_tag_level, 'spam_tag_level', '/^\d{1,}(\.\d{1,2})?$/', '', [7.0], true);
|
||||||
|
$spam_kill_level = Validate::validate($spam_kill_level, 'spam_kill_level', '/^\d{1,}(\.\d{1,2})?$/', '', [14.0], true);
|
||||||
|
$description = Validate::validate(trim($description), 'description', Validate::REGEX_DESC_TEXT, '', [], true);
|
||||||
|
|
||||||
$stmt = Database::prepare("
|
$stmt = Database::prepare("
|
||||||
UPDATE `" . TABLE_MAIL_VIRTUAL . "`
|
UPDATE `" . TABLE_MAIL_VIRTUAL . "` SET
|
||||||
SET `email` = :email , `iscatchall` = :caflag, `description` = :description
|
`email` = :email ,
|
||||||
|
`spam_tag_level` = :spam_tag_level,
|
||||||
|
`spam_kill_level` = :spam_kill_level,
|
||||||
|
`bypass_spam` = :bypass_spam,
|
||||||
|
`policy_greylist` = :policy_greylist,
|
||||||
|
`iscatchall` = :caflag,
|
||||||
|
`description` = :description
|
||||||
WHERE `customerid`= :cid AND `id`= :id
|
WHERE `customerid`= :cid AND `id`= :id
|
||||||
");
|
");
|
||||||
$params = [
|
$params = [
|
||||||
"email" => $email,
|
"email" => $email,
|
||||||
|
"spam_tag_level" => $spam_tag_level,
|
||||||
|
"spam_kill_level" => $spam_kill_level,
|
||||||
|
"bypass_spam" => $bypass_spam,
|
||||||
|
"policy_greylist" => $policy_greylist,
|
||||||
"caflag" => $iscatchall,
|
"caflag" => $iscatchall,
|
||||||
"description" => $description,
|
"description" => $description,
|
||||||
"cid" => $customer['customerid'],
|
"cid" => $customer['customerid'],
|
||||||
"id" => $id
|
"id" => $id
|
||||||
];
|
];
|
||||||
Database::pexecute($stmt, $params, true, true);
|
Database::pexecute($stmt, $params, true, true);
|
||||||
|
Cronjob::inserttask(TaskId::REBUILD_RSPAMD);
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] toggled catchall-flag for email address '" . $result['email_full'] . "'");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] toggled catchall-flag for email address '" . $result['email_full'] . "'");
|
||||||
|
|
||||||
$result = $this->apiCall('Emails.get', [
|
$result = $this->apiCall('Emails.get', [
|
||||||
@@ -334,7 +390,7 @@ class Emails extends ApiCommand implements ResourceEntity
|
|||||||
$result = [];
|
$result = [];
|
||||||
$query_fields = [];
|
$query_fields = [];
|
||||||
$result_stmt = Database::prepare("
|
$result_stmt = Database::prepare("
|
||||||
SELECT m.`id`, m.`domainid`, m.`email`, m.`email_full`, m.`iscatchall`, m.`destination`, m.`popaccountid`, d.`domain`, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize`
|
SELECT m.*, d.`domain`, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize`
|
||||||
FROM `" . TABLE_MAIL_VIRTUAL . "` m
|
FROM `" . TABLE_MAIL_VIRTUAL . "` m
|
||||||
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON (m.`domainid` = d.`id`)
|
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON (m.`domainid` = d.`id`)
|
||||||
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON (m.`popaccountid` = u.`id`)
|
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON (m.`popaccountid` = u.`id`)
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ class FpmDaemons extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
// validation
|
// validation
|
||||||
$description = Validate::validate($description, 'description', Validate::REGEX_DESC_TEXT, '', [], true);
|
$description = Validate::validate($description, 'description', Validate::REGEX_DESC_TEXT, '', [], true);
|
||||||
$reload_cmd = Validate::validate($reload_cmd, 'reload_cmd', '/^[a-z0-9\/\._\- ]+$/i', '', [], true);
|
$reload_cmd = Validate::validate($reload_cmd, 'reload_cmd', '/^[a-z0-9\/\._\-@ ]+$/i', '', [], true);
|
||||||
$sel_stmt = Database::prepare("SELECT `id` FROM `".TABLE_PANEL_FPMDAEMONS."` WHERE `reload_cmd` = :rc");
|
$sel_stmt = Database::prepare("SELECT `id` FROM `".TABLE_PANEL_FPMDAEMONS."` WHERE `reload_cmd` = :rc");
|
||||||
$dupcheck = Database::pexecute_first($sel_stmt, ['rc' => $reload_cmd]);
|
$dupcheck = Database::pexecute_first($sel_stmt, ['rc' => $reload_cmd]);
|
||||||
if ($dupcheck && $dupcheck['id']) {
|
if ($dupcheck && $dupcheck['id']) {
|
||||||
@@ -327,7 +327,7 @@ class FpmDaemons extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
// validation
|
// validation
|
||||||
$description = Validate::validate($description, 'description', Validate::REGEX_DESC_TEXT, '', [], true);
|
$description = Validate::validate($description, 'description', Validate::REGEX_DESC_TEXT, '', [], true);
|
||||||
$reload_cmd = Validate::validate($reload_cmd, 'reload_cmd', '/^[a-z0-9\/\._\- ]+$/i', '', [], true);
|
$reload_cmd = Validate::validate($reload_cmd, 'reload_cmd', '/^[a-z0-9\/\._\-@ ]+$/i', '', [], true);
|
||||||
$sel_stmt = Database::prepare("SELECT `id` FROM `".TABLE_PANEL_FPMDAEMONS."` WHERE `reload_cmd` = :rc");
|
$sel_stmt = Database::prepare("SELECT `id` FROM `".TABLE_PANEL_FPMDAEMONS."` WHERE `reload_cmd` = :rc");
|
||||||
$dupcheck = Database::pexecute_first($sel_stmt, ['rc' => $reload_cmd]);
|
$dupcheck = Database::pexecute_first($sel_stmt, ['rc' => $reload_cmd]);
|
||||||
if ($dupcheck && $dupcheck['id'] != $id) {
|
if ($dupcheck && $dupcheck['id'] != $id) {
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -91,7 +91,7 @@ class Froxlor extends ApiCommand
|
|||||||
'additional_info' => AutoUpdate::getFromResult('info'),
|
'additional_info' => AutoUpdate::getFromResult('info'),
|
||||||
'aucheck' => $aucheck
|
'aucheck' => $aucheck
|
||||||
];
|
];
|
||||||
} else if ($aucheck < 0 || $aucheck > 1) {
|
} elseif ($aucheck < 0 || $aucheck > 1) {
|
||||||
// errors
|
// errors
|
||||||
if ($aucheck < 0) {
|
if ($aucheck < 0) {
|
||||||
$errmsg = AutoUpdate::getLastError();
|
$errmsg = AutoUpdate::getLastError();
|
||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ class Ftps extends ApiCommand implements ResourceEntity
|
|||||||
} elseif ($username == $password) {
|
} elseif ($username == $password) {
|
||||||
Response::standardError('passwordshouldnotbeusername', '', true);
|
Response::standardError('passwordshouldnotbeusername', '', true);
|
||||||
} else {
|
} else {
|
||||||
$path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path);
|
$path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path, $customer['documentroot']);
|
||||||
$cryptPassword = Crypt::makeCryptPassword($password, false, true);
|
$cryptPassword = Crypt::makeCryptPassword($password, false, true);
|
||||||
|
|
||||||
$stmt = Database::prepare("INSERT INTO `" . TABLE_FTP_USERS . "`
|
$stmt = Database::prepare("INSERT INTO `" . TABLE_FTP_USERS . "`
|
||||||
@@ -469,7 +469,7 @@ class Ftps extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
// path update?
|
// path update?
|
||||||
if ($path != '') {
|
if ($path != '') {
|
||||||
$path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path);
|
$path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path, $customer['documentroot']);
|
||||||
|
|
||||||
if ($path != $result['homedir']) {
|
if ($path != $result['homedir']) {
|
||||||
$stmt = Database::prepare("UPDATE `" . TABLE_FTP_USERS . "`
|
$stmt = Database::prepare("UPDATE `" . TABLE_FTP_USERS . "`
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ class HostingPlans extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
// validation
|
// validation
|
||||||
$name = Validate::validate(trim($name), 'name', Validate::REGEX_DESC_TEXT, '', [], true);
|
$name = Validate::validate(trim($name), 'name', Validate::REGEX_DESC_TEXT, '', [], true);
|
||||||
$description = Validate::validate(str_replace("\r\n", "\n", $description), 'description', Validate::REGEX_CONF_TEXT);
|
$description = Validate::validate(str_replace("\r\n", "\n", $description), 'description', Validate::REGEX_DESC_TEXT);
|
||||||
|
|
||||||
if (Settings::Get('system.mail_quota_enabled') != '1') {
|
if (Settings::Get('system.mail_quota_enabled') != '1') {
|
||||||
$value_arr['email_quota'] = -1;
|
$value_arr['email_quota'] = -1;
|
||||||
@@ -383,7 +383,7 @@ class HostingPlans extends ApiCommand implements ResourceEntity
|
|||||||
|
|
||||||
// validation
|
// validation
|
||||||
$name = Validate::validate(trim($name), 'name', Validate::REGEX_DESC_TEXT, '', [], true);
|
$name = Validate::validate(trim($name), 'name', Validate::REGEX_DESC_TEXT, '', [], true);
|
||||||
$description = Validate::validate(str_replace("\r\n", "\n", $description), 'description', Validate::REGEX_CONF_TEXT);
|
$description = Validate::validate(str_replace("\r\n", "\n", $description), 'description', Validate::REGEX_DESC_TEXT);
|
||||||
|
|
||||||
if (Settings::Get('system.mail_quota_enabled') != '1') {
|
if (Settings::Get('system.mail_quota_enabled') != '1') {
|
||||||
$value_arr['email_quota'] = -1;
|
$value_arr['email_quota'] = -1;
|
||||||
|
|||||||
@@ -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']);
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
|||||||
* @param string $description
|
* @param string $description
|
||||||
* optional, description for database
|
* optional, description for database
|
||||||
* @param string $custom_suffix
|
* @param string $custom_suffix
|
||||||
* optional, name for database
|
* optional, name for database if customer.mysqlprefix setting is set to "DBNAME"
|
||||||
* @param bool $sendinfomail
|
* @param bool $sendinfomail
|
||||||
* optional, send created resource-information to customer, default: false
|
* optional, send created resource-information to customer, default: false
|
||||||
* @param int $customerid
|
* @param int $customerid
|
||||||
@@ -110,6 +110,9 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
|||||||
$dbm = new DbManager($this->logger());
|
$dbm = new DbManager($this->logger());
|
||||||
|
|
||||||
if (strtoupper(Settings::Get('customer.mysqlprefix')) == 'DBNAME' && !empty($databasename)) {
|
if (strtoupper(Settings::Get('customer.mysqlprefix')) == 'DBNAME' && !empty($databasename)) {
|
||||||
|
if (strlen($newdb_params['loginname'] . '_' . $databasename) > Database::getSqlUsernameLength()) {
|
||||||
|
throw new Exception("Database name cannot be longer than " . (Database::getSqlUsernameLength() - strlen($newdb_params['loginname'] . '_')) . " characters.", 406);
|
||||||
|
}
|
||||||
$username = $dbm->createDatabase($newdb_params['loginname'] . '_' . $databasename, $password, $dbserver);
|
$username = $dbm->createDatabase($newdb_params['loginname'] . '_' . $databasename, $password, $dbserver);
|
||||||
} else {
|
} else {
|
||||||
$username = $dbm->createDatabase($newdb_params['loginname'], $password, $dbserver, $newdb_params['mysql_lastaccountnumber']);
|
$username = $dbm->createDatabase($newdb_params['loginname'], $password, $dbserver, $newdb_params['mysql_lastaccountnumber']);
|
||||||
|
|||||||
@@ -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("
|
||||||
@@ -564,9 +567,9 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
// If path is empty or '/' and 'Use domain name as default value for DocumentRoot path' is enabled in settings,
|
// If path is empty or '/' and 'Use domain name as default value for DocumentRoot path' is enabled in settings,
|
||||||
// set default path to subdomain or domain name
|
// set default path to subdomain or domain name
|
||||||
if ((($path == '') || ($path == '/')) && Settings::Get('system.documentroot_use_default_value') == 1) {
|
if ((($path == '') || ($path == '/')) && Settings::Get('system.documentroot_use_default_value') == 1) {
|
||||||
$path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $completedomain);
|
$path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $completedomain, $customer['documentroot']);
|
||||||
} else {
|
} else {
|
||||||
$path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path);
|
$path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path, $customer['documentroot']);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// no it's not, create a redirect
|
// no it's not, create a redirect
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -980,9 +983,11 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
'`d`.`letsencrypt`',
|
'`d`.`letsencrypt`',
|
||||||
'`d`.`registration_date`',
|
'`d`.`registration_date`',
|
||||||
'`d`.`termination_date`',
|
'`d`.`termination_date`',
|
||||||
'`d`.`deactivated`'
|
'`d`.`deactivated`',
|
||||||
|
'`d`.`email_only`',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$query_fields = [];
|
$query_fields = [];
|
||||||
|
|
||||||
// prepare select statement
|
// prepare select statement
|
||||||
@@ -993,7 +998,6 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
|||||||
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id`
|
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id`
|
||||||
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `pd` ON `pd`.`id`=`d`.`parentdomainid`
|
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `pd` ON `pd`.`id`=`d`.`parentdomainid`
|
||||||
WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ")
|
WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ")
|
||||||
AND `d`.`email_only` = '0'
|
|
||||||
" . $this->getSearchWhere($query_fields, true) . " GROUP BY `d`.`id` ORDER BY `parentdomainname` ASC, `d`.`parentdomainid` ASC " . $this->getOrderBy(true) . $this->getLimit());
|
" . $this->getSearchWhere($query_fields, true) . " GROUP BY `d`.`id` ORDER BY `parentdomainname` ASC, `d`.`parentdomainid` ASC " . $this->getOrderBy(true) . $this->getLimit());
|
||||||
|
|
||||||
$result = [];
|
$result = [];
|
||||||
@@ -1078,10 +1082,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,18 +1092,14 @@ 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
|
||||||
$domains_stmt = Database::prepare("
|
$domains_stmt = Database::prepare("
|
||||||
SELECT COUNT(*) as num_subdom
|
SELECT COUNT(*) as num_subdom
|
||||||
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`.`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) {
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ class SysLog extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
Database::pexecute($result_stmt, $query_fields, true, true);
|
Database::pexecute($result_stmt, $query_fields, true, true);
|
||||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
|
// clean log-text
|
||||||
|
$row['text'] = preg_replace("/[^\w @#\"':.,()\[\]+\-_\/\\\!]/i", "_", $row['text']);
|
||||||
$result[] = $row;
|
$result[] = $row;
|
||||||
}
|
}
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] list log-entries");
|
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] list log-entries");
|
||||||
@@ -223,7 +225,7 @@ class SysLog extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
$params['trunc'] = $truncatedate;
|
$params['trunc'] = $truncatedate;
|
||||||
Database::pexecute($result_stmt, $params, true, true);
|
Database::pexecute($result_stmt, $params, true, true);
|
||||||
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] truncated the froxlor syslog");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] truncated the froxlor syslog");
|
||||||
return $this->response(true);
|
return $this->response(true);
|
||||||
}
|
}
|
||||||
throw new Exception("Not allowed to execute given command.", 403);
|
throw new Exception("Not allowed to execute given command.", 403);
|
||||||
|
|||||||
@@ -1,102 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Froxlor\Backup\Storages;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Froxlor\FileDir;
|
|
||||||
|
|
||||||
class Ftp extends Storage
|
|
||||||
{
|
|
||||||
private $ftp_conn = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function init(): bool
|
|
||||||
{
|
|
||||||
$hostname = $this->sData['storage']['hostname'] ?? '';
|
|
||||||
$username = $this->sData['storage']['username'] ?? '';
|
|
||||||
$password = $this->sData['storage']['password'] ?? '';
|
|
||||||
if (!empty($hostname) && !empty($username) && !empty($password)) {
|
|
||||||
$tmp = explode(":", $hostname);
|
|
||||||
$hostname = $tmp[0];
|
|
||||||
$port = $tmp[1] ?? 21;
|
|
||||||
$this->ftp_conn = ftp_connect($hostname, $port);
|
|
||||||
if ($this->ftp_conn === false) {
|
|
||||||
throw new Exception('Unable to connect to ftp-server "' . $hostname . ':' . $port . '"');
|
|
||||||
}
|
|
||||||
if (!ftp_login($this->ftp_conn, $username, $password)) {
|
|
||||||
throw new Exception('Unable to login to ftp-server "' . $hostname . ':' . $port . '"');
|
|
||||||
}
|
|
||||||
return $this->changeToCorrectDirectory();
|
|
||||||
}
|
|
||||||
throw new Exception('Empty hostname for FTP backup storage');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move/Upload file from tmp-source-directory. The file should be moved or deleted afterward.
|
|
||||||
* Must return the (relative) path including filename to the backup.
|
|
||||||
*
|
|
||||||
* @param string $filename
|
|
||||||
* @param string $tmp_source_directory
|
|
||||||
* @return string
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
protected function putFile(string $filename, string $tmp_source_directory): string
|
|
||||||
{
|
|
||||||
$source = FileDir::makeCorrectFile($tmp_source_directory . "/" . $filename);
|
|
||||||
if (file_exists($source) && ftp_size($this->ftp_conn, $filename) == -1) {
|
|
||||||
if (ftp_put($this->ftp_conn, $filename, $source, FTP_BINARY)) {
|
|
||||||
return FileDir::makeCorrectFile($this->getDestinationDirectory() . '/' . $filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $filename
|
|
||||||
* @return bool
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
protected function rmFile(string $filename): bool
|
|
||||||
{
|
|
||||||
$target = basename($filename);
|
|
||||||
if (ftp_size($this->ftp_conn, $target) >= 0) {
|
|
||||||
return ftp_delete($this->ftp_conn, $target);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function shutdown(): bool
|
|
||||||
{
|
|
||||||
return ftp_close($this->ftp_conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
private function changeToCorrectDirectory(): bool
|
|
||||||
{
|
|
||||||
$dirs = explode("/", $this->getDestinationDirectory());
|
|
||||||
array_shift($dirs);
|
|
||||||
if (count($dirs) > 0 && !empty($dirs[0])) {
|
|
||||||
foreach ($dirs as $dir) {
|
|
||||||
if (empty($dir)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!@ftp_chdir($this->ftp_conn, $dir)) {
|
|
||||||
ftp_mkdir($this->ftp_conn, $dir);
|
|
||||||
ftp_chmod($this->ftp_conn, 0700, $dir);
|
|
||||||
ftp_chdir($this->ftp_conn, $dir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return ftp_chdir($this->ftp_conn, "/");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Froxlor\Backup\Storages;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Froxlor\FileDir;
|
|
||||||
|
|
||||||
class Local extends Storage
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function init(): bool
|
|
||||||
{
|
|
||||||
// create destination_path
|
|
||||||
if (!file_exists($this->getDestinationDirectory())) {
|
|
||||||
return mkdir($this->getDestinationDirectory(), 0700, true);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move/Upload file from tmp-source-directory. The file should be moved or deleted afterward.
|
|
||||||
* Must return the (relative) path including filename to the backup.
|
|
||||||
*
|
|
||||||
* @param string $filename
|
|
||||||
* @param string $tmp_source_directory
|
|
||||||
* @return string
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
protected function putFile(string $filename, string $tmp_source_directory): string
|
|
||||||
{
|
|
||||||
$source = FileDir::makeCorrectFile($tmp_source_directory . "/" . $filename);
|
|
||||||
$target = FileDir::makeCorrectFile($this->getDestinationDirectory() . "/" . $filename);
|
|
||||||
if (file_exists($source) && !file_exists($target)) {
|
|
||||||
rename($source, $target);
|
|
||||||
return $target;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $filename
|
|
||||||
* @return bool
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
protected function rmFile(string $filename): bool
|
|
||||||
{
|
|
||||||
$target = FileDir::makeCorrectFile($this->getDestinationDirectory() . "/" . $filename);
|
|
||||||
if (file_exists($target)) {
|
|
||||||
return @unlink($target);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function shutdown(): bool
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Froxlor\Backup\Storages;
|
|
||||||
|
|
||||||
class Rsync extends Storage
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function init(): bool
|
|
||||||
{
|
|
||||||
// TODO: Implement init() method.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move/Upload file from tmp-source-directory. The file should be moved or deleted afterward.
|
|
||||||
* Must return the (relative) path including filename to the backup.
|
|
||||||
*
|
|
||||||
* @param string $filename
|
|
||||||
* @param string $tmp_source_directory
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function putFile(string $filename, string $tmp_source_directory): string
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $filename
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected function rmFile(string $filename): bool
|
|
||||||
{
|
|
||||||
// TODO: Implement removeOld() method.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function shutdown(): bool
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Froxlor\Backup\Storages;
|
|
||||||
|
|
||||||
class S3 extends Storage
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function init(): bool
|
|
||||||
{
|
|
||||||
// TODO: Implement init() method.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move/Upload file from tmp-source-directory. The file should be moved or deleted afterward.
|
|
||||||
* Must return the (relative) path including filename to the backup.
|
|
||||||
*
|
|
||||||
* @param string $filename
|
|
||||||
* @param string $tmp_source_directory
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function putFile(string $filename, string $tmp_source_directory): string
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $filename
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected function rmFile(string $filename): bool
|
|
||||||
{
|
|
||||||
// TODO: Implement removeOld() method.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function shutdown(): bool
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Froxlor\Backup\Storages;
|
|
||||||
|
|
||||||
class Sftp extends Storage
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function init(): bool
|
|
||||||
{
|
|
||||||
// TODO: Implement init() method.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move/Upload file from tmp-source-directory. The file should be moved or deleted afterward.
|
|
||||||
* Must return the (relative) path including filename to the backup.
|
|
||||||
*
|
|
||||||
* @param string $filename
|
|
||||||
* @param string $tmp_source_directory
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function putFile(string $filename, string $tmp_source_directory): string
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $filename
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected function rmFile(string $filename): bool
|
|
||||||
{
|
|
||||||
// TODO: Implement removeOld() method.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function shutdown(): bool
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,281 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Froxlor\Backup\Storages;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Froxlor\Database\Database;
|
|
||||||
use Froxlor\FileDir;
|
|
||||||
|
|
||||||
abstract class Storage
|
|
||||||
{
|
|
||||||
private string $tmpDirectory;
|
|
||||||
protected array $sData;
|
|
||||||
|
|
||||||
protected array $filesToStore;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function __construct(array $storage_data)
|
|
||||||
{
|
|
||||||
$this->sData = $storage_data;
|
|
||||||
$this->tmpDirectory = FileDir::makeCorrectDir(sys_get_temp_dir() . '/backup-' . $this->sData['loginname']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate sData, open connection to target storage, etc.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
abstract public function init(): bool;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disconnect / clean up connection if needed
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
abstract public function shutdown(): bool;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* prepare files to back up (e.g. create archive or similar) and fill $filesToStore
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function prepareFiles(): void
|
|
||||||
{
|
|
||||||
$this->filesToStore = [];
|
|
||||||
|
|
||||||
$tmpdir = FileDir::makeCorrectDir($this->tmpDirectory . '/.tmp/');
|
|
||||||
FileDir::safe_exec('mkdir -p ' . escapeshellarg($tmpdir));
|
|
||||||
|
|
||||||
// create archive of web, mail and database data
|
|
||||||
$this->prepareWebData();
|
|
||||||
$this->prepareDatabaseData();
|
|
||||||
$this->prepareMailData();
|
|
||||||
|
|
||||||
// create json-info-file
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
private function prepareWebData(): void
|
|
||||||
{
|
|
||||||
$tmpdir = FileDir::makeCorrectDir($this->tmpDirectory . '/.tmp/web');
|
|
||||||
FileDir::safe_exec('mkdir -p ' . escapeshellarg($tmpdir));
|
|
||||||
FileDir::safe_exec('tar cfz ' . escapeshellarg(FileDir::makeCorrectFile($tmpdir . '/' . $this->sData['loginname'] . '-web.tar.gz')) . ' -C ' . escapeshellarg($this->sData['documentroot']) . ' .');
|
|
||||||
$this->filesToStore[] = FileDir::makeCorrectFile($tmpdir . '/' . $this->sData['loginname'] . '-web.tar.gz');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
private function prepareDatabaseData(): void
|
|
||||||
{
|
|
||||||
$tmpdir = FileDir::makeCorrectDir($this->tmpDirectory . '/.tmp/mysql');
|
|
||||||
FileDir::safe_exec('mkdir -p ' . escapeshellarg($tmpdir));
|
|
||||||
|
|
||||||
// get all customer database-names
|
|
||||||
$sel_stmt = Database::prepare("
|
|
||||||
SELECT `databasename`, `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`
|
|
||||||
WHERE `customerid` = :cid ORDER BY `dbserver`
|
|
||||||
");
|
|
||||||
Database::pexecute($sel_stmt, [
|
|
||||||
'cid' => $this->sData['customerid']
|
|
||||||
]);
|
|
||||||
|
|
||||||
$has_dbs = false;
|
|
||||||
$current_dbserver = -1;
|
|
||||||
while ($row = $sel_stmt->fetch()) {
|
|
||||||
// Get sql_root data for the specific database-server the database resides on
|
|
||||||
if ($current_dbserver != $row['dbserver']) {
|
|
||||||
Database::needRoot(true, $row['dbserver']);
|
|
||||||
Database::needSqlData();
|
|
||||||
$sql_root = Database::getSqlData();
|
|
||||||
Database::needRoot(false);
|
|
||||||
// create temporary mysql-defaults file for the connection-credentials/details
|
|
||||||
$mysqlcnf_file = tempnam("/tmp", "frx");
|
|
||||||
$mysqlcnf = "[mysqldump]\npassword=" . $sql_root['passwd'] . "\nhost=" . $sql_root['host'] . "\n";
|
|
||||||
if (!empty($sql_root['port'])) {
|
|
||||||
$mysqlcnf .= "port=" . $sql_root['port'] . "\n";
|
|
||||||
} elseif (!empty($sql_root['socket'])) {
|
|
||||||
$mysqlcnf .= "socket=" . $sql_root['socket'] . "\n";
|
|
||||||
}
|
|
||||||
file_put_contents($mysqlcnf_file, $mysqlcnf);
|
|
||||||
}
|
|
||||||
$bool_false = false;
|
|
||||||
FileDir::safe_exec('mysqldump --defaults-file=' . escapeshellarg($mysqlcnf_file) . ' -u ' . escapeshellarg($sql_root['user']) . ' ' . $row['databasename'] . ' > ' . FileDir::makeCorrectFile($tmpdir . '/' . $row['databasename'] . '_' . date('YmdHi', time()) . '.sql'), $bool_false, [
|
|
||||||
'>'
|
|
||||||
]);
|
|
||||||
$has_dbs = true;
|
|
||||||
$current_dbserver = $row['dbserver'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($has_dbs) {
|
|
||||||
$this->filesToStore[] = $tmpdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (@file_exists($mysqlcnf_file)) {
|
|
||||||
@unlink($mysqlcnf_file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function prepareMailData(): void
|
|
||||||
{
|
|
||||||
$tmpdir = FileDir::makeCorrectDir($this->tmpDirectory . '/.tmp/mail');
|
|
||||||
FileDir::safe_exec('mkdir -p ' . escapeshellarg($tmpdir));
|
|
||||||
|
|
||||||
// get all customer mail-accounts
|
|
||||||
$sel_stmt = Database::prepare("
|
|
||||||
SELECT `homedir`, `maildir` FROM `" . TABLE_MAIL_USERS . "`
|
|
||||||
WHERE `customerid` = :cid
|
|
||||||
");
|
|
||||||
Database::pexecute($sel_stmt, [
|
|
||||||
'cid' => $this->sData['customerid']
|
|
||||||
]);
|
|
||||||
|
|
||||||
$tar_file_list = "";
|
|
||||||
$mail_homedir = "";
|
|
||||||
while ($row = $sel_stmt->fetch()) {
|
|
||||||
$tar_file_list .= escapeshellarg("./" . $row['maildir']) . " ";
|
|
||||||
if (empty($mail_homedir)) {
|
|
||||||
// this should be equal for all entries
|
|
||||||
$mail_homedir = $row['homedir'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($tar_file_list)) {
|
|
||||||
FileDir::safe_exec('tar cfz ' . escapeshellarg(FileDir::makeCorrectFile($tmpdir . '/' . $this->sData['loginname'] . '-mail.tar.gz')) . ' -C ' . escapeshellarg($mail_homedir) . ' ' . trim($tar_file_list));
|
|
||||||
$this->filesToStore[] = FileDir::makeCorrectFile($tmpdir . '/' . $this->sData['loginname'] . '-mail.tar.gz');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move/Upload file from tmp-source-directory. The file should be moved or deleted afterward.
|
|
||||||
* Must return the (relative) path including filename to the backup.
|
|
||||||
*
|
|
||||||
* @param string $filename
|
|
||||||
* @param string $tmp_source_directory
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
abstract protected function putFile(string $filename, string $tmp_source_directory): string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $filename
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
abstract protected function rmFile(string $filename): bool;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function removeOld(): bool
|
|
||||||
{
|
|
||||||
// retention in days
|
|
||||||
$retention = $this->sData['storage']['retention'] ?? 3;
|
|
||||||
// keep date
|
|
||||||
$keepDate = new \DateTime();
|
|
||||||
$keepDate->setTime(0, 0, 0, 1);
|
|
||||||
// subtract retention days
|
|
||||||
$keepDate->sub(new \DateInterval('P' . $retention . 'D'));
|
|
||||||
// select target backups to remove for this storage-id and customer
|
|
||||||
$sel_stmt = Database::prepare("
|
|
||||||
SELECT * FROM `" . TABLE_PANEL_BACKUPS . "`
|
|
||||||
WHERE `created_at` < :keepdate
|
|
||||||
AND `storage_id` = :sid
|
|
||||||
AND `customerid` = :cid
|
|
||||||
");
|
|
||||||
Database::pexecute($sel_stmt, [
|
|
||||||
'keepdate' => $keepDate->format('U'),
|
|
||||||
'sid' => $this->sData['backup'],
|
|
||||||
'cid' => $this->sData['customerid']
|
|
||||||
]);
|
|
||||||
while ($oldBackup = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
|
|
||||||
$this->rmFile($oldBackup['filename']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the storage configured destination path for all backups
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function getDestinationDirectory(): string
|
|
||||||
{
|
|
||||||
return FileDir::makeCorrectDir($this->sData['storage']['destination_path'] ?? "/");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create backup-archive/file from $filesToStore and call putFile()
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function createFromFiles(): bool
|
|
||||||
{
|
|
||||||
if (empty($this->filesToStore)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$filename = FileDir::makeCorrectFile($this->tmpDirectory . "/backup-" . $this->sData['loginname'] . "-" . date('c') . ".tar.gz");
|
|
||||||
$tmpdir = FileDir::makeCorrectDir($this->tmpDirectory . '/.tmp/');
|
|
||||||
$create_export_tar_data = implode(" ", $this->filesToStore);
|
|
||||||
FileDir::safe_exec('chown -R ' . (int)$this->sData['guid'] . ':' . (int)$this->sData['guid'] . ' ' . escapeshellarg($tmpdir));
|
|
||||||
|
|
||||||
if (!empty($data['pgp_public_key'])) {
|
|
||||||
// pack all archives in tmp-dir to one archive and encrypt it with gpg
|
|
||||||
$recipient_file = FileDir::makeCorrectFile($this->tmpDirectory . '/' . $this->sData['loginname'] . '-recipients.gpg');
|
|
||||||
file_put_contents($recipient_file, $data['pgp_public_key']);
|
|
||||||
$return_value = [];
|
|
||||||
FileDir::safe_exec('tar cfz - -C ' . escapeshellarg($tmpdir) . ' ' . trim($create_export_tar_data) . ' | gpg --encrypt --recipient-file ' . escapeshellarg($recipient_file) . ' --output ' . escapeshellarg($filename) . ' --trust-model always --batch --yes', $return_value, ['|']);
|
|
||||||
} else {
|
|
||||||
// pack all archives in tmp-dir to one archive
|
|
||||||
FileDir::safe_exec('tar cfz ' . escapeshellarg($filename) . ' -C ' . escapeshellarg($tmpdir) . ' ' . trim($create_export_tar_data));
|
|
||||||
}
|
|
||||||
|
|
||||||
// determine filesize (use stat locally here b/c files are possibly large and php's filesize() can't handle them)
|
|
||||||
$fileSizeOutput = FileDir::safe_exec('/usr/bin/stat -c "%s" ' . escapeshellarg($filename));
|
|
||||||
$fileSize = (int)array_shift($fileSizeOutput);
|
|
||||||
|
|
||||||
// add entry to database and upload/store file
|
|
||||||
|
|
||||||
FileDir::safe_exec('rm -rf ' . escapeshellarg($tmpdir));
|
|
||||||
$fileDest = $this->putFile(basename($filename), $this->tmpDirectory);
|
|
||||||
if (!empty($fileDest)) {
|
|
||||||
$this->addEntry($fileDest, $fileSize);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $filename
|
|
||||||
* @param int $fileSize
|
|
||||||
* @return void
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
private function addEntry(string $filename, int $fileSize): void
|
|
||||||
{
|
|
||||||
$ins_stmt = Database::prepare("
|
|
||||||
INSERT INTO `" . TABLE_PANEL_BACKUPS . "` SET
|
|
||||||
`adminid` = :adminid,
|
|
||||||
`customerid` = :customerid,
|
|
||||||
`loginname` = :loginname,
|
|
||||||
`size` = :size,
|
|
||||||
`storage_id` = :sid,
|
|
||||||
`filename` = :filename,
|
|
||||||
`created_at` = UNIX_TIMESTAMP()
|
|
||||||
");
|
|
||||||
Database::pexecute($ins_stmt, [
|
|
||||||
'adminid' => $this->sData['adminid'],
|
|
||||||
'customerid' => $this->sData['customerid'],
|
|
||||||
'loginname' => $this->sData['loginname'],
|
|
||||||
'size' => $fileSize,
|
|
||||||
'sid' => $this->sData['backup'],
|
|
||||||
'filename' => $filename
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Froxlor\Backup\Storages;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Froxlor\Database\Database;
|
|
||||||
|
|
||||||
class StorageFactory
|
|
||||||
{
|
|
||||||
public static function fromType(string $type, array $storage_data): Storage
|
|
||||||
{
|
|
||||||
$type = "\\Froxlor\\Backup\\Storages\\" . ucfirst($type);
|
|
||||||
return new $type($storage_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public static function fromStorageId(int $storage_id, array $user_data): Storage
|
|
||||||
{
|
|
||||||
$storage = self::readStorageData($storage_id);
|
|
||||||
$storage_data = $user_data;
|
|
||||||
$storage_data['storage'] = $storage;
|
|
||||||
return self::fromType($storage['type'], $storage_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
private static function readStorageData(int $storage_id): array
|
|
||||||
{
|
|
||||||
$stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_BACKUP_STORAGES . "` WHERE `id` = :bid");
|
|
||||||
$storage = Database::pexecute_first($stmt, ['bid' => $storage_id]);
|
|
||||||
if (empty($storage)) {
|
|
||||||
throw new Exception("Invalid/empty backup-storage. Unable to continue");
|
|
||||||
}
|
|
||||||
return $storage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -25,19 +25,18 @@
|
|||||||
|
|
||||||
namespace Froxlor\Cli;
|
namespace Froxlor\Cli;
|
||||||
|
|
||||||
use PDO;
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Froxlor\Database\Database;
|
||||||
use Froxlor\Froxlor;
|
use Froxlor\Froxlor;
|
||||||
use Froxlor\Settings;
|
use Froxlor\Settings;
|
||||||
use Froxlor\Database\Database;
|
use PDO;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
class CliCommand extends Command
|
class CliCommand extends Command
|
||||||
{
|
{
|
||||||
|
|
||||||
protected function validateRequirements(InputInterface $input, OutputInterface $output, bool $ignore_has_updates = false): int
|
protected function validateRequirements(OutputInterface $output, bool $ignore_has_updates = false): int
|
||||||
{
|
{
|
||||||
if (!file_exists(Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
|
if (!file_exists(Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
|
||||||
$output->writeln("<error>Could not find froxlor's userdata.inc.php file. You should use this script only with an installed froxlor system.</>");
|
$output->writeln("<error>Could not find froxlor's userdata.inc.php file. You should use this script only with an installed froxlor system.</>");
|
||||||
@@ -116,9 +115,11 @@ class CliCommand extends Command
|
|||||||
return $userinfo;
|
return $userinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function runUpdate(OutputInterface $output): int
|
protected function runUpdate(OutputInterface $output, bool $manual = false): int
|
||||||
{
|
{
|
||||||
|
if (!$manual) {
|
||||||
$output->writeln('<comment>Automatic update is activated and we are going to proceed without any notices</>');
|
$output->writeln('<comment>Automatic update is activated and we are going to proceed without any notices</>');
|
||||||
|
}
|
||||||
include_once Froxlor::getInstallDir() . '/lib/tables.inc.php';
|
include_once Froxlor::getInstallDir() . '/lib/tables.inc.php';
|
||||||
define('_CRON_UPDATE', 1);
|
define('_CRON_UPDATE', 1);
|
||||||
ob_start([
|
ob_start([
|
||||||
@@ -127,11 +128,11 @@ class CliCommand extends Command
|
|||||||
]);
|
]);
|
||||||
include_once Froxlor::getInstallDir() . '/install/updatesql.php';
|
include_once Froxlor::getInstallDir() . '/install/updatesql.php';
|
||||||
ob_end_flush();
|
ob_end_flush();
|
||||||
$output->writeln('<info>Automatic update done - you should check your settings to be sure everything is fine</>');
|
$output->writeln('<info>' . ($manual ? 'Database' : 'Automatic') . ' update done - you should check your settings to be sure everything is fine</>');
|
||||||
return self::SUCCESS;
|
return self::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function cleanUpdateOutput($buffer)
|
private function cleanUpdateOutput($buffer): string
|
||||||
{
|
{
|
||||||
return strip_tags(preg_replace("/<br\W*?\/>/", "\n", $buffer));
|
return strip_tags(preg_replace("/<br\W*?\/>/", "\n", $buffer));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ final class ConfigDiff extends CliCommand
|
|||||||
->addOption('diff-params', '', InputOption::VALUE_REQUIRED, 'Additional parameters for `diff`, e.g. --diff-params="--color=always"');
|
->addOption('diff-params', '', InputOption::VALUE_REQUIRED, 'Additional parameters for `diff`, e.g. --diff-params="--color=always"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
require Froxlor::getInstallDir() . '/lib/functions.php';
|
require Froxlor::getInstallDir() . '/lib/functions.php';
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
namespace Froxlor\Cli;
|
namespace Froxlor\Cli;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use Froxlor\Config\ConfigParser;
|
use Froxlor\Config\ConfigParser;
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
use Froxlor\FileDir;
|
use Froxlor\FileDir;
|
||||||
@@ -40,14 +41,12 @@ use Symfony\Component\Console\Style\SymfonyStyle;
|
|||||||
|
|
||||||
final class ConfigServices extends CliCommand
|
final class ConfigServices extends CliCommand
|
||||||
{
|
{
|
||||||
|
|
||||||
private $yes_to_all_supported = [
|
private $yes_to_all_supported = [
|
||||||
'bookworm',
|
'bookworm',
|
||||||
'bionic',
|
|
||||||
'bullseye',
|
'bullseye',
|
||||||
'buster',
|
|
||||||
'focal',
|
'focal',
|
||||||
'jammy',
|
'jammy',
|
||||||
|
'noble',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected function configure()
|
protected function configure()
|
||||||
@@ -62,11 +61,9 @@ final class ConfigServices extends CliCommand
|
|||||||
->addOption('yes-to-all', 'A', InputOption::VALUE_NONE, 'Install packages without asking questions (Debian/Ubuntu only currently)');
|
->addOption('yes-to-all', 'A', InputOption::VALUE_NONE, 'Install packages without asking questions (Debian/Ubuntu only currently)');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$result = self::SUCCESS;
|
$result = $this->validateRequirements($output);
|
||||||
|
|
||||||
$result = $this->validateRequirements($input, $output);
|
|
||||||
|
|
||||||
require Froxlor::getInstallDir() . '/lib/functions.php';
|
require Froxlor::getInstallDir() . '/lib/functions.php';
|
||||||
|
|
||||||
@@ -93,7 +90,7 @@ final class ConfigServices extends CliCommand
|
|||||||
if ($result == self::SUCCESS) {
|
if ($result == self::SUCCESS) {
|
||||||
$io = new SymfonyStyle($input, $output);
|
$io = new SymfonyStyle($input, $output);
|
||||||
if ($input->getOption('create')) {
|
if ($input->getOption('create')) {
|
||||||
$result = $this->createConfig($input, $output, $io);
|
$result = $this->createConfig($output, $io);
|
||||||
} elseif ($input->getOption('apply')) {
|
} elseif ($input->getOption('apply')) {
|
||||||
$result = $this->applyConfig($input, $output, $io);
|
$result = $this->applyConfig($input, $output, $io);
|
||||||
} elseif ($input->getOption('list') || $input->getOption('daemon')) {
|
} elseif ($input->getOption('list') || $input->getOption('daemon')) {
|
||||||
@@ -158,7 +155,10 @@ final class ConfigServices extends CliCommand
|
|||||||
fclose($fp);
|
fclose($fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createConfig(InputInterface $input, OutputInterface $output, SymfonyStyle $io)
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function createConfig(OutputInterface $output, SymfonyStyle $io): int
|
||||||
{
|
{
|
||||||
$_daemons_config = [
|
$_daemons_config = [
|
||||||
'distro' => ""
|
'distro' => ""
|
||||||
@@ -171,8 +171,8 @@ final class ConfigServices extends CliCommand
|
|||||||
$distributions_select_data = [];
|
$distributions_select_data = [];
|
||||||
|
|
||||||
//set default os.
|
//set default os.
|
||||||
$os_dist = ['ID' => 'bullseye'];
|
$os_dist = ['ID' => 'bookworm'];
|
||||||
$os_version = ['0' => '11'];
|
$os_version = ['0' => '12'];
|
||||||
$os_default = $os_dist['ID'];
|
$os_default = $os_dist['ID'];
|
||||||
|
|
||||||
//read os-release
|
//read os-release
|
||||||
@@ -285,7 +285,10 @@ final class ConfigServices extends CliCommand
|
|||||||
return self::SUCCESS;
|
return self::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function applyConfig(InputInterface $input, OutputInterface $output, SymfonyStyle $io)
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function applyConfig(InputInterface $input, OutputInterface $output, SymfonyStyle $io): int
|
||||||
{
|
{
|
||||||
$applyFile = $input->getOption('apply');
|
$applyFile = $input->getOption('apply');
|
||||||
|
|
||||||
@@ -398,7 +401,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") {
|
||||||
@@ -407,7 +410,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -429,7 +432,10 @@ final class ConfigServices extends CliCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getReplacerArray()
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function getReplacerArray(): array
|
||||||
{
|
{
|
||||||
$customer_tmpdir = '/tmp/';
|
$customer_tmpdir = '/tmp/';
|
||||||
if (Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_tmpdir') != '') {
|
if (Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_tmpdir') != '') {
|
||||||
@@ -438,7 +444,7 @@ final class ConfigServices extends CliCommand
|
|||||||
$customer_tmpdir = Settings::Get('phpfpm.tmpdir');
|
$customer_tmpdir = Settings::Get('phpfpm.tmpdir');
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to convert namserver hosts to ip's
|
// try to convert nameserver hosts to ip's
|
||||||
$ns_ips = "";
|
$ns_ips = "";
|
||||||
$known_ns_ips = [];
|
$known_ns_ips = [];
|
||||||
if (Settings::Get('system.nameservers') != '') {
|
if (Settings::Get('system.nameservers') != '') {
|
||||||
@@ -484,12 +490,12 @@ final class ConfigServices extends CliCommand
|
|||||||
Database::needSqlData();
|
Database::needSqlData();
|
||||||
$sql = Database::getSqlData();
|
$sql = Database::getSqlData();
|
||||||
|
|
||||||
$replace_arr = [
|
return [
|
||||||
'<SQL_UNPRIVILEGED_USER>' => $sql['user'],
|
'<SQL_UNPRIVILEGED_USER>' => $sql['user'],
|
||||||
'<SQL_UNPRIVILEGED_PASSWORD>' => $sql['passwd'],
|
'<SQL_UNPRIVILEGED_PASSWORD>' => $sql['passwd'],
|
||||||
'<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'),
|
||||||
@@ -507,7 +513,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'),
|
||||||
];
|
];
|
||||||
return $replace_arr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,13 +26,16 @@
|
|||||||
namespace Froxlor\Cli;
|
namespace Froxlor\Cli;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Froxlor\Froxlor;
|
|
||||||
use Froxlor\Config\ConfigParser;
|
use Froxlor\Config\ConfigParser;
|
||||||
|
use Froxlor\Database\Database;
|
||||||
|
use Froxlor\Froxlor;
|
||||||
use Froxlor\Install\Install;
|
use Froxlor\Install\Install;
|
||||||
use Froxlor\Install\Install\Core;
|
use Froxlor\Install\Install\Core;
|
||||||
|
use Froxlor\Settings;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Helper\Table;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
@@ -50,10 +53,14 @@ final class InstallCommand extends Command
|
|||||||
$this->setDescription('Installation process to use instead of web-ui');
|
$this->setDescription('Installation process to use instead of web-ui');
|
||||||
$this->addArgument('input-file', InputArgument::OPTIONAL, 'Optional JSON array file to use for unattended installations');
|
$this->addArgument('input-file', InputArgument::OPTIONAL, 'Optional JSON array file to use for unattended installations');
|
||||||
$this->addOption('print-example-file', 'p', InputOption::VALUE_NONE, 'Outputs an example JSON content to be used with the input file parameter')
|
$this->addOption('print-example-file', 'p', InputOption::VALUE_NONE, 'Outputs an example JSON content to be used with the input file parameter')
|
||||||
->addOption('create-userdata-from-str', 'c', InputOption::VALUE_REQUIRED, 'Creates lib/userdata.inc.php file from string created by web-install process');
|
->addOption('create-userdata-from-str', 'c', InputOption::VALUE_REQUIRED, 'Creates lib/userdata.inc.php file from string created by web-install process')
|
||||||
|
->addOption('show-sysinfo', 's', InputOption::VALUE_NONE, 'Outputs system information about your froxlor installation');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$result = self::SUCCESS;
|
$result = self::SUCCESS;
|
||||||
|
|
||||||
@@ -69,6 +76,15 @@ final class InstallCommand extends Command
|
|||||||
return self::INVALID;
|
return self::INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($input->getOption('show-sysinfo') !== false) {
|
||||||
|
if (!file_exists(Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
|
||||||
|
$output->writeln("<error>Could not find froxlor's userdata.inc.php file. You can use this parameter only with an installed froxlor system.</>");
|
||||||
|
return self::INVALID;
|
||||||
|
}
|
||||||
|
$this->printSysInfo($output);
|
||||||
|
return self::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
session_start();
|
session_start();
|
||||||
|
|
||||||
require __DIR__ . '/install.functions.php';
|
require __DIR__ . '/install.functions.php';
|
||||||
@@ -137,10 +153,12 @@ final class InstallCommand extends Command
|
|||||||
$decoded_input = [];
|
$decoded_input = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->showStep(0, $extended, $decoded_input);
|
return $this->showStep(0, $extended, $decoded_input);
|
||||||
return $result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
private function showStep(int $step = 0, bool $extended = false, array $decoded_input = []): int
|
private function showStep(int $step = 0, bool $extended = false, array $decoded_input = []): int
|
||||||
{
|
{
|
||||||
$result = self::SUCCESS;
|
$result = self::SUCCESS;
|
||||||
@@ -206,7 +224,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) {
|
||||||
@@ -262,15 +280,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;
|
||||||
@@ -300,7 +320,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') {
|
||||||
@@ -313,7 +333,7 @@ final class InstallCommand extends Command
|
|||||||
$fieldval = '******';
|
$fieldval = '******';
|
||||||
} elseif ($field['type'] == 'select') {
|
} elseif ($field['type'] == 'select') {
|
||||||
$fieldval = implode("|", array_keys($field['select_var']));
|
$fieldval = implode("|", array_keys($field['select_var']));
|
||||||
} else if ($field['type'] == 'checkbox') {
|
} elseif ($field['type'] == 'checkbox') {
|
||||||
$fieldval = "1|0";
|
$fieldval = "1|0";
|
||||||
} else {
|
} else {
|
||||||
$fieldval = "?";
|
$fieldval = "?";
|
||||||
@@ -341,4 +361,61 @@ final class InstallCommand extends Command
|
|||||||
curl_close($ch);
|
curl_close($ch);
|
||||||
fclose($fp);
|
fclose($fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function printSysInfo(OutputInterface $output)
|
||||||
|
{
|
||||||
|
|
||||||
|
$php_sapi = 'mod_php';
|
||||||
|
$php_version = phpversion();
|
||||||
|
if (Settings::Get('system.mod_fcgid') == '1') {
|
||||||
|
$php_sapi = 'FCGID';
|
||||||
|
if (Settings::Get('system.mod_fcgid_ownvhost') == '1') {
|
||||||
|
$php_sapi .= ' (+ froxlor)';
|
||||||
|
}
|
||||||
|
} elseif (Settings::Get('phpfpm.enabled') == '1') {
|
||||||
|
$php_sapi = 'PHP-FPM';
|
||||||
|
if (Settings::Get('phpfpm.enabled_ownvhost') == '1') {
|
||||||
|
$php_sapi .= ' (+ froxlor)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$kernel = 'unknown';
|
||||||
|
if (function_exists('posix_uname')) {
|
||||||
|
$kernel_nfo = posix_uname();
|
||||||
|
$kernel = $kernel_nfo['release'] . ' (' . $kernel_nfo['machine'] . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
$ips = [];
|
||||||
|
$ips_stmt = Database::query("SELECT CONCAT(`ip`, ' (', `port`, ')') as ipaddr FROM `" . TABLE_PANEL_IPSANDPORTS . "` ORDER BY `id`");
|
||||||
|
while ($ip = $ips_stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||||
|
$ips[] = $ip['ipaddr'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = new Table($output);
|
||||||
|
$table
|
||||||
|
->setHeaders([
|
||||||
|
'Key', 'Value'
|
||||||
|
])
|
||||||
|
->setRows([
|
||||||
|
['Froxlor', Froxlor::getVersionString()],
|
||||||
|
['Update-channel', Settings::Get('system.update_channel')],
|
||||||
|
['Hostname', Settings::Get('system.hostname')],
|
||||||
|
['Install-dir', Froxlor::getInstallDir()],
|
||||||
|
['PHP CLI', $php_version],
|
||||||
|
['PHP SAPI', $php_sapi],
|
||||||
|
['Webserver', Settings::Get('system.webserver')],
|
||||||
|
['Kernel', $kernel],
|
||||||
|
['Database', Database::getAttribute(\PDO::ATTR_SERVER_VERSION)],
|
||||||
|
['Distro config', Settings::Get('system.distribution')],
|
||||||
|
['IP addresses', implode("\n", $ips)],
|
||||||
|
]);
|
||||||
|
$table->setStyle('box');
|
||||||
|
$table->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,19 +25,20 @@
|
|||||||
|
|
||||||
namespace Froxlor\Cli;
|
namespace Froxlor\Cli;
|
||||||
|
|
||||||
use PDO;
|
use Exception;
|
||||||
use Froxlor\Froxlor;
|
|
||||||
use Froxlor\FileDir;
|
|
||||||
use Froxlor\Settings;
|
|
||||||
use Froxlor\FroxlorLogger;
|
|
||||||
use Froxlor\Database\Database;
|
|
||||||
use Froxlor\System\Cronjob;
|
|
||||||
use Froxlor\Cron\TaskId;
|
|
||||||
use Froxlor\Cron\CronConfig;
|
use Froxlor\Cron\CronConfig;
|
||||||
use Froxlor\Cron\System\Extrausers;
|
use Froxlor\Cron\System\Extrausers;
|
||||||
|
use Froxlor\Cron\TaskId;
|
||||||
|
use Froxlor\Database\Database;
|
||||||
|
use Froxlor\FileDir;
|
||||||
|
use Froxlor\Froxlor;
|
||||||
|
use Froxlor\FroxlorLogger;
|
||||||
|
use Froxlor\Settings;
|
||||||
|
use Froxlor\System\Cronjob;
|
||||||
|
use PDO;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
final class MasterCron extends CliCommand
|
final class MasterCron extends CliCommand
|
||||||
@@ -51,16 +52,18 @@ final class MasterCron extends CliCommand
|
|||||||
$this->setName('froxlor:cron');
|
$this->setName('froxlor:cron');
|
||||||
$this->setDescription('Regulary perform tasks created by froxlor');
|
$this->setDescription('Regulary perform tasks created by froxlor');
|
||||||
$this->addArgument('job', InputArgument::IS_ARRAY, 'Job(s) to run');
|
$this->addArgument('job', InputArgument::IS_ARRAY, 'Job(s) to run');
|
||||||
$this->addOption('run-task', 'r', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Run a specific task [1 = re-generate configs, 4 = re-generate dns zones, 10 = re-set quotas, 99 = re-create cron.d-file]')
|
$this->addOption('run-task', 'r', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Run a specific task [1 = re-generate configs, 4 = re-generate dns zones, 9 = re-generate rspamd configs, 10 = re-set quotas, 99 = re-create cron.d-file]')
|
||||||
->addOption('force', 'f', InputOption::VALUE_NONE, 'Forces given job or, if none given, forces re-generating of config-files (webserver, nameserver, etc.)')
|
->addOption('force', 'f', InputOption::VALUE_NONE, 'Forces given job or, if none given, forces re-generating of config-files (webserver, nameserver, etc.)')
|
||||||
->addOption('debug', 'd', InputOption::VALUE_NONE, 'Output debug information about what is going on to STDOUT.')
|
->addOption('debug', 'd', InputOption::VALUE_NONE, 'Output debug information about what is going on to STDOUT.')
|
||||||
->addOption('no-fork', 'N', InputOption::VALUE_NONE, 'Do not fork to background (traffic cron only).');
|
->addOption('no-fork', 'N', InputOption::VALUE_NONE, 'Do not fork to background (traffic cron only).');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$result = self::SUCCESS;
|
$result = $this->validateRequirements($output);
|
||||||
$result = $this->validateRequirements($input, $output);
|
|
||||||
|
|
||||||
if ($result != self::SUCCESS) {
|
if ($result != self::SUCCESS) {
|
||||||
// requirements failed, exit
|
// requirements failed, exit
|
||||||
@@ -74,9 +77,10 @@ final class MasterCron extends CliCommand
|
|||||||
if (empty($jobs) || in_array('tasks', $jobs)) {
|
if (empty($jobs) || in_array('tasks', $jobs)) {
|
||||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||||
Cronjob::inserttask(TaskId::REBUILD_DNS);
|
Cronjob::inserttask(TaskId::REBUILD_DNS);
|
||||||
|
Cronjob::inserttask(TaskId::REBUILD_RSPAMD);
|
||||||
Cronjob::inserttask(TaskId::CREATE_QUOTA);
|
Cronjob::inserttask(TaskId::CREATE_QUOTA);
|
||||||
Cronjob::inserttask(TaskId::REBUILD_CRON);
|
Cronjob::inserttask(TaskId::REBUILD_CRON);
|
||||||
array_push($jobs, 'tasks');
|
$jobs[] = 'tasks';
|
||||||
}
|
}
|
||||||
define('CRON_IS_FORCED', 1);
|
define('CRON_IS_FORCED', 1);
|
||||||
}
|
}
|
||||||
@@ -92,9 +96,9 @@ final class MasterCron extends CliCommand
|
|||||||
if ($input->getOption('run-task')) {
|
if ($input->getOption('run-task')) {
|
||||||
$tasks_to_run = $input->getOption('run-task');
|
$tasks_to_run = $input->getOption('run-task');
|
||||||
foreach ($tasks_to_run as $ttr) {
|
foreach ($tasks_to_run as $ttr) {
|
||||||
if (in_array($ttr, [TaskId::REBUILD_VHOST, TaskId::REBUILD_DNS, TaskId::CREATE_QUOTA, TaskId::REBUILD_CRON])) {
|
if (in_array($ttr, [TaskId::REBUILD_VHOST, TaskId::REBUILD_DNS, TaskId::REBUILD_RSPAMD, TaskId::CREATE_QUOTA, TaskId::REBUILD_CRON])) {
|
||||||
Cronjob::inserttask($ttr);
|
Cronjob::inserttask($ttr);
|
||||||
array_push($jobs, 'tasks');
|
$jobs[] = 'tasks';
|
||||||
} else {
|
} else {
|
||||||
$output->writeln('<comment>Unknown task number "' . $ttr . '"</>');
|
$output->writeln('<comment>Unknown task number "' . $ttr . '"</>');
|
||||||
}
|
}
|
||||||
@@ -140,12 +144,12 @@ final class MasterCron extends CliCommand
|
|||||||
$cronfile::run();
|
$cronfile::run();
|
||||||
}
|
}
|
||||||
// free the lockfile
|
// free the lockfile
|
||||||
$this->unlockJob($job);
|
$this->unlockJob();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// regenerate nss-extrausers files / invalidate nscd cache (if used)
|
// regenerate nss-extrausers files / invalidate nscd cache (if used)
|
||||||
$this->refreshUsers((int) $tasks_cnt['jobcnt']);
|
$this->refreshUsers((int)$tasks_cnt['jobcnt']);
|
||||||
|
|
||||||
// we have to check the system's last guid with every cron run
|
// we have to check the system's last guid with every cron run
|
||||||
// in case the admin installed new software which added a new user
|
// in case the admin installed new software which added a new user
|
||||||
@@ -157,43 +161,26 @@ final class MasterCron extends CliCommand
|
|||||||
CronConfig::checkCrondConfigurationFile();
|
CronConfig::checkCrondConfigurationFile();
|
||||||
|
|
||||||
// check for old/compatibility cronjob file
|
// check for old/compatibility cronjob file
|
||||||
if (file_exists(Froxlor::getInstallDir().'/scripts/froxlor_master_cronjob.php')) {
|
if (file_exists(Froxlor::getInstallDir() . '/scripts/froxlor_master_cronjob.php')) {
|
||||||
@unlink(Froxlor::getInstallDir().'/scripts/froxlor_master_cronjob.php');
|
@unlink(Froxlor::getInstallDir() . '/scripts/froxlor_master_cronjob.php');
|
||||||
@rmdir(Froxlor::getInstallDir().'/scripts');
|
@rmdir(Froxlor::getInstallDir() . '/scripts');
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset cronlog-flag if set to "once"
|
// reset cronlog-flag if set to "once"
|
||||||
if ((int) Settings::Get('logger.log_cron') == 1) {
|
if ((int)Settings::Get('logger.log_cron') == 1) {
|
||||||
FroxlorLogger::getInstanceOf()->setCronLog(0);
|
FroxlorLogger::getInstanceOf()->setCronLog(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up possible old login-links
|
// clean up possible old login-links and 2fa tokens
|
||||||
Database::query("DELETE FROM `" . TABLE_PANEL_LOGINLINKS . "` WHERE `valid_until` < UNIX_TIMESTAMP()");
|
Database::query("DELETE FROM `" . TABLE_PANEL_LOGINLINKS . "` WHERE `valid_until` < UNIX_TIMESTAMP()");
|
||||||
|
Database::query("DELETE FROM `" . TABLE_PANEL_2FA_TOKENS . "` WHERE `valid_until` < UNIX_TIMESTAMP()");
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function refreshUsers(int $jobcount = 0)
|
/**
|
||||||
{
|
* @throws Exception
|
||||||
if ($jobcount > 0) {
|
*/
|
||||||
if (Settings::Get('system.nssextrausers') == 1) {
|
|
||||||
Extrausers::generateFiles($this->cronLog);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear NSCD cache if using fcgid or fpm, #1570 - not needed for nss-extrausers
|
|
||||||
if ((Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) && Settings::Get('system.nssextrausers') == 0) {
|
|
||||||
$false_val = false;
|
|
||||||
FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, [
|
|
||||||
'>'
|
|
||||||
]);
|
|
||||||
FileDir::safe_exec('nscd -i group 1> /dev/null', $false_val, [
|
|
||||||
'>'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function validateOwnership(OutputInterface $output)
|
private function validateOwnership(OutputInterface $output)
|
||||||
{
|
{
|
||||||
// when using fcgid or fpm for froxlor-vhost itself, we have to check
|
// when using fcgid or fpm for froxlor-vhost itself, we have to check
|
||||||
@@ -220,21 +207,6 @@ final class MasterCron extends CliCommand
|
|||||||
$output->writeln('OK');
|
$output->writeln('OK');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getCronModule(string $cronname, OutputInterface $output)
|
|
||||||
{
|
|
||||||
$upd_stmt = Database::prepare("
|
|
||||||
SELECT `cronclass` FROM `" . TABLE_PANEL_CRONRUNS . "` WHERE `cronfile` = :cron;
|
|
||||||
");
|
|
||||||
$cron = Database::pexecute_first($upd_stmt, [
|
|
||||||
'cron' => $cronname
|
|
||||||
]);
|
|
||||||
if ($cron) {
|
|
||||||
return $cron['cronclass'];
|
|
||||||
}
|
|
||||||
$output->writeln("<error>Requested cronjob '" . $cronname . "' could not be found.</>");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function lockJob(string $job, OutputInterface $output): bool
|
private function lockJob(string $job, OutputInterface $output): bool
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -247,12 +219,12 @@ final class MasterCron extends CliCommand
|
|||||||
system("kill -CHLD " . (int)$jobinfo['pid'] . " 1> /dev/null 2> /dev/null", $check_pid_return);
|
system("kill -CHLD " . (int)$jobinfo['pid'] . " 1> /dev/null 2> /dev/null", $check_pid_return);
|
||||||
if ($check_pid_return == 1) {
|
if ($check_pid_return == 1) {
|
||||||
// Process does not seem to run, most likely it has died
|
// Process does not seem to run, most likely it has died
|
||||||
$this->unlockJob($job);
|
$this->unlockJob();
|
||||||
} else {
|
} else {
|
||||||
// cronjob still running, output info and stop
|
// cronjob still running, output info and stop
|
||||||
$output->writeln([
|
$output->writeln([
|
||||||
'<comment>Job "' . $jobinfo['job'] . '" is currently running.',
|
'<comment>Job "' . $jobinfo['job'] . '" is currently running.',
|
||||||
'Started: ' . date('d.m.Y H:i', (int) $jobinfo['startts']),
|
'Started: ' . date('d.m.Y H:i', (int)$jobinfo['startts']),
|
||||||
'PID: ' . $jobinfo['pid'] . '</>'
|
'PID: ' . $jobinfo['pid'] . '</>'
|
||||||
]);
|
]);
|
||||||
return false;
|
return false;
|
||||||
@@ -268,8 +240,48 @@ final class MasterCron extends CliCommand
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function unlockJob(string $job): bool
|
private function unlockJob(): bool
|
||||||
{
|
{
|
||||||
return @unlink($this->lockFile);
|
return @unlink($this->lockFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getCronModule(string $cronname, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$upd_stmt = Database::prepare("
|
||||||
|
SELECT `cronclass` FROM `" . TABLE_PANEL_CRONRUNS . "` WHERE `cronfile` = :cron;
|
||||||
|
");
|
||||||
|
$cron = Database::pexecute_first($upd_stmt, [
|
||||||
|
'cron' => $cronname
|
||||||
|
]);
|
||||||
|
if ($cron) {
|
||||||
|
return $cron['cronclass'];
|
||||||
|
}
|
||||||
|
$output->writeln("<error>Requested cronjob '" . $cronname . "' could not be found.</>");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function refreshUsers(int $jobcount = 0)
|
||||||
|
{
|
||||||
|
if ($jobcount > 0) {
|
||||||
|
if (Settings::Get('system.nssextrausers') == 1) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear NSCD cache if using fcgid or fpm, #1570 - not needed for nss-extrausers
|
||||||
|
if ((Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) && Settings::Get('system.nssextrausers') == 0) {
|
||||||
|
$false_val = false;
|
||||||
|
FileDir::safe_exec('nscd -i passwd 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')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ final class PhpSessionclean extends CliCommand
|
|||||||
$this->addArgument('max-lifetime', InputArgument::OPTIONAL, 'The number of seconds after which data will be seen as "garbage" and potentially cleaned up. Defaults to "1440"');
|
$this->addArgument('max-lifetime', InputArgument::OPTIONAL, 'The number of seconds after which data will be seen as "garbage" and potentially cleaned up. Defaults to "1440"');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$result = $this->validateRequirements($input, $output);
|
$result = $this->validateRequirements($output);
|
||||||
|
|
||||||
if ($result == self::SUCCESS) {
|
if ($result == self::SUCCESS) {
|
||||||
if ((int)Settings::Get('phpfpm.enabled') == 1) {
|
if ((int)Settings::Get('phpfpm.enabled') == 1) {
|
||||||
@@ -89,7 +89,7 @@ final class PhpSessionclean extends CliCommand
|
|||||||
|
|
||||||
if (count($paths_to_clean) > 0) {
|
if (count($paths_to_clean) > 0) {
|
||||||
foreach ($paths_to_clean as $ptc) {
|
foreach ($paths_to_clean as $ptc) {
|
||||||
// find all files older then maxlifetime and delete them
|
// find all files older than maxlifetime and delete them
|
||||||
FileDir::safe_exec("find -O3 \"" . $ptc . "\" -ignore_readdir_race -depth -mindepth 1 -name 'sess_*' -type f -cmin \"+" . $maxlifetime . "\" -delete");
|
FileDir::safe_exec("find -O3 \"" . $ptc . "\" -ignore_readdir_race -depth -mindepth 1 -name 'sess_*' -type f -cmin \"+" . $maxlifetime . "\" -delete");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,14 +26,12 @@
|
|||||||
namespace Froxlor\Cli;
|
namespace Froxlor\Cli;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use PDO;
|
use Froxlor\Froxlor;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
use Froxlor\Database\Database;
|
|
||||||
use Froxlor\Froxlor;
|
|
||||||
|
|
||||||
final class RunApiCommand extends CliCommand
|
final class RunApiCommand extends CliCommand
|
||||||
{
|
{
|
||||||
@@ -48,11 +46,9 @@ final class RunApiCommand extends CliCommand
|
|||||||
$this->addOption('show-params', 's', InputOption::VALUE_NONE, 'Show possible parameters for given api-command (given command will *not* be called)');
|
$this->addOption('show-params', 's', InputOption::VALUE_NONE, 'Show possible parameters for given api-command (given command will *not* be called)');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$result = self::SUCCESS;
|
$result = $this->validateRequirements($output);
|
||||||
|
|
||||||
$result = $this->validateRequirements($input, $output);
|
|
||||||
|
|
||||||
require Froxlor::getInstallDir() . '/lib/functions.php';
|
require Froxlor::getInstallDir() . '/lib/functions.php';
|
||||||
|
|
||||||
@@ -110,6 +106,9 @@ final class RunApiCommand extends CliCommand
|
|||||||
return self::SUCCESS;
|
return self::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
private function validateCommand(string $command): array
|
private function validateCommand(string $command): array
|
||||||
{
|
{
|
||||||
$command = explode(".", $command);
|
$command = explode(".", $command);
|
||||||
|
|||||||
@@ -43,11 +43,9 @@ final class SwitchServerIp extends CliCommand
|
|||||||
->addOption('list', 'l', InputOption::VALUE_NONE, 'List all IP addresses currently added for this server in froxlor');
|
->addOption('list', 'l', InputOption::VALUE_NONE, 'List all IP addresses currently added for this server in froxlor');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$result = self::SUCCESS;
|
$result = $this->validateRequirements($output);
|
||||||
|
|
||||||
$result = $this->validateRequirements($input, $output);
|
|
||||||
|
|
||||||
if ($result == self::SUCCESS && $input->getOption('list') == false && $input->getOption('switch') == false) {
|
if ($result == self::SUCCESS && $input->getOption('list') == false && $input->getOption('switch') == false) {
|
||||||
$output->writeln('<error>Either --list or --switch option must be provided. Nothing to do, exiting.</>');
|
$output->writeln('<error>Either --list or --switch option must be provided. Nothing to do, exiting.</>');
|
||||||
@@ -83,6 +81,7 @@ final class SwitchServerIp extends CliCommand
|
|||||||
$ip_list = $input->getOption('switch');
|
$ip_list = $input->getOption('switch');
|
||||||
|
|
||||||
$has_error = false;
|
$has_error = false;
|
||||||
|
$ips_to_switch = [];
|
||||||
foreach ($ip_list as $ips_combo) {
|
foreach ($ip_list as $ips_combo) {
|
||||||
$ip_pair = explode(",", $ips_combo);
|
$ip_pair = explode(",", $ips_combo);
|
||||||
if (count($ip_pair) != 2) {
|
if (count($ip_pair) != 2) {
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ namespace Froxlor\Cli;
|
|||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Froxlor\Froxlor;
|
use Froxlor\Froxlor;
|
||||||
use Froxlor\Settings;
|
|
||||||
use Froxlor\Install\Update;
|
|
||||||
use Froxlor\Install\AutoUpdate;
|
use Froxlor\Install\AutoUpdate;
|
||||||
|
use Froxlor\Install\Update;
|
||||||
|
use Froxlor\Settings;
|
||||||
use Froxlor\System\Mailer;
|
use Froxlor\System\Mailer;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
@@ -44,6 +44,7 @@ final class UpdateCommand extends CliCommand
|
|||||||
$this->setName('froxlor:update');
|
$this->setName('froxlor:update');
|
||||||
$this->setDescription('Check for newer version and update froxlor');
|
$this->setDescription('Check for newer version and update froxlor');
|
||||||
$this->addOption('check-only', 'c', InputOption::VALUE_NONE, 'Only check for newer version and exit')
|
$this->addOption('check-only', 'c', InputOption::VALUE_NONE, 'Only check for newer version and exit')
|
||||||
|
->addOption('database', 'd', InputOption::VALUE_NONE, 'Only run database updates in case updates are done via apt or manually.')
|
||||||
->addOption('mail-notify', 'm', InputOption::VALUE_NONE, 'Additionally inform administrator via email if a newer version was found')
|
->addOption('mail-notify', 'm', InputOption::VALUE_NONE, 'Additionally inform administrator via email if a newer version was found')
|
||||||
->addOption('yes-to-all', 'A', InputOption::VALUE_NONE, 'Do not ask for download, extract and database-update, just do it (if not --check-only is set)')
|
->addOption('yes-to-all', 'A', InputOption::VALUE_NONE, 'Do not ask for download, extract and database-update, just do it (if not --check-only is set)')
|
||||||
->addOption('integer-return', 'i', InputOption::VALUE_NONE, 'Return integer whether a new version is available or not (implies --check-only). Useful for programmatic use.');
|
->addOption('integer-return', 'i', InputOption::VALUE_NONE, 'Return integer whether a new version is available or not (implies --check-only). Useful for programmatic use.');
|
||||||
@@ -53,7 +54,36 @@ final class UpdateCommand extends CliCommand
|
|||||||
{
|
{
|
||||||
$result = self::SUCCESS;
|
$result = self::SUCCESS;
|
||||||
|
|
||||||
$result = $this->validateRequirements($input, $output);
|
// database update only
|
||||||
|
if ($input->getOption('database')) {
|
||||||
|
$result = $this->validateRequirements($output, true);
|
||||||
|
if ($result == self::SUCCESS) {
|
||||||
|
require Froxlor::getInstallDir() . '/lib/functions.php';
|
||||||
|
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
|
||||||
|
$output->writeln('<info>' . lng('update.dbupdate_required') . '</>');
|
||||||
|
if ($input->getOption('check-only')) {
|
||||||
|
$output->writeln('<comment>Doing nothing because of "check-only" flag.</>');
|
||||||
|
} else {
|
||||||
|
$yestoall = $input->getOption('yes-to-all') !== false;
|
||||||
|
$helper = $this->getHelper('question');
|
||||||
|
$question = new ConfirmationQuestion('Update database? [no] ', false, '/^(y|j)/i');
|
||||||
|
if ($yestoall || $helper->ask($input, $output, $question)) {
|
||||||
|
$result = $this->runUpdate($output, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
$output->writeln('<info>' . lng('update.noupdatesavail', (Settings::Get('system.update_channel') == 'testing' ? lng('serversettings.uc_testing') . ' ' : '')) . '</>');
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $this->validateRequirements($output);
|
||||||
|
|
||||||
|
if ($result != self::SUCCESS) {
|
||||||
|
// requirements failed, exit
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
require Froxlor::getInstallDir() . '/lib/functions.php';
|
require Froxlor::getInstallDir() . '/lib/functions.php';
|
||||||
|
|
||||||
@@ -71,7 +101,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]);
|
||||||
}
|
}
|
||||||
@@ -81,7 +111,7 @@ final class UpdateCommand extends CliCommand
|
|||||||
$newversionavail = true;
|
$newversionavail = true;
|
||||||
$output->writeln('<comment>' . $text . '</>');
|
$output->writeln('<comment>' . $text . '</>');
|
||||||
$result = self::SUCCESS;
|
$result = self::SUCCESS;
|
||||||
} else if ($aucheck < 0 || $aucheck > 1) {
|
} elseif ($aucheck < 0 || $aucheck > 1) {
|
||||||
if ($input->getOption('integer-return')) {
|
if ($input->getOption('integer-return')) {
|
||||||
$output->write(-1);
|
$output->write(-1);
|
||||||
return self::INVALID;
|
return self::INVALID;
|
||||||
@@ -146,7 +176,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;
|
||||||
@@ -170,7 +200,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');
|
||||||
@@ -182,22 +212,4 @@ final class UpdateCommand extends CliCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updateDatabase()
|
|
||||||
{
|
|
||||||
include_once Froxlor::getInstallDir() . '/lib/tables.inc.php';
|
|
||||||
define('_CRON_UPDATE', 1);
|
|
||||||
ob_start([
|
|
||||||
$this,
|
|
||||||
'cleanUpdateOutput'
|
|
||||||
]);
|
|
||||||
include_once Froxlor::getInstallDir() . '/install/updatesql.php';
|
|
||||||
ob_end_flush();
|
|
||||||
return self::SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function cleanUpdateOutput($buffer)
|
|
||||||
{
|
|
||||||
return strip_tags(preg_replace("/<br\W*?\/>/", "\n", $buffer));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,15 +26,15 @@
|
|||||||
namespace Froxlor\Cli;
|
namespace Froxlor\Cli;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Froxlor\Api\Commands\Admins;
|
||||||
|
use Froxlor\Api\Commands\Customers;
|
||||||
|
use Froxlor\Froxlor;
|
||||||
|
use Froxlor\System\Crypt;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
use Froxlor\Api\Commands\Admins;
|
|
||||||
use Froxlor\Api\Commands\Customers;
|
|
||||||
use Froxlor\System\Crypt;
|
|
||||||
use Froxlor\Froxlor;
|
|
||||||
|
|
||||||
final class UserCommand extends CliCommand
|
final class UserCommand extends CliCommand
|
||||||
{
|
{
|
||||||
@@ -50,11 +50,11 @@ final class UserCommand extends CliCommand
|
|||||||
->addOption('show-info', 's', InputOption::VALUE_NONE, 'Output information details of given user');
|
->addOption('show-info', 's', InputOption::VALUE_NONE, 'Output information details of given user');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$result = self::SUCCESS;
|
$result = self::SUCCESS;
|
||||||
|
|
||||||
$result = $this->validateRequirements($input, $output);
|
$result = $this->validateRequirements($output);
|
||||||
|
|
||||||
require Froxlor::getInstallDir() . '/lib/functions.php';
|
require Froxlor::getInstallDir() . '/lib/functions.php';
|
||||||
|
|
||||||
|
|||||||
@@ -48,15 +48,16 @@ final class ValidateAcmeWebroot extends CliCommand
|
|||||||
$this->addOption('yes-to-all', 'A', InputOption::VALUE_NONE, 'Do not ask for confirmation, update files if necessary');
|
$this->addOption('yes-to-all', 'A', InputOption::VALUE_NONE, 'Do not ask for confirmation, update files if necessary');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
/**
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$result = self::SUCCESS;
|
$result = $this->validateRequirements($output, true);
|
||||||
|
|
||||||
$result = $this->validateRequirements($input, $output, true);
|
|
||||||
|
|
||||||
$io = new SymfonyStyle($input, $output);
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
if ((int) Settings::Get('system.leenabled') == 0) {
|
if ((int)Settings::Get('system.leenabled') == 0) {
|
||||||
$io->info("Let's Encrypt not activated in froxlor settings.");
|
$io->info("Let's Encrypt not activated in froxlor settings.");
|
||||||
$result = self::INVALID;
|
$result = self::INVALID;
|
||||||
}
|
}
|
||||||
@@ -94,7 +95,7 @@ final class ValidateAcmeWebroot extends CliCommand
|
|||||||
$acmesh_challenge_dir = $recommended;
|
$acmesh_challenge_dir = $recommended;
|
||||||
// need to update the corresponding acme-alias config-file
|
// need to update the corresponding acme-alias config-file
|
||||||
$acme_alias_file = Settings::Get('system.letsencryptacmeconf');
|
$acme_alias_file = Settings::Get('system.letsencryptacmeconf');
|
||||||
$sed_params = "s@".$former_value."@" . $acmesh_challenge_dir . "@";
|
$sed_params = "s@" . $former_value . "@" . $acmesh_challenge_dir . "@";
|
||||||
FileDir::safe_exec('sed -i -e "' . $sed_params . '" ' . escapeshellarg($acme_alias_file));
|
FileDir::safe_exec('sed -i -e "' . $sed_params . '" ' . escapeshellarg($acme_alias_file));
|
||||||
$count_changes++;
|
$count_changes++;
|
||||||
}
|
}
|
||||||
@@ -138,8 +139,6 @@ final class ValidateAcmeWebroot extends CliCommand
|
|||||||
$io->info("Domain '" . $domain . "' Le_Webroot value is correct");
|
$io->info("Domain '" . $domain . "' Le_Webroot value is correct");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,9 @@ class ConfigDaemon
|
|||||||
$this->fullxml = $xml;
|
$this->fullxml = $xml;
|
||||||
$this->xpath = $xpath;
|
$this->xpath = $xpath;
|
||||||
$this->daemon = $this->fullxml->xpath($this->xpath);
|
$this->daemon = $this->fullxml->xpath($this->xpath);
|
||||||
|
if (count($this->daemon) !== 1) {
|
||||||
|
throw new Exception('XPath "' . $this->xpath . '" didn\'t return exactly one element');
|
||||||
|
}
|
||||||
$attributes = $this->daemon[0]->attributes();
|
$attributes = $this->daemon[0]->attributes();
|
||||||
if ($attributes['title'] != '') {
|
if ($attributes['title'] != '') {
|
||||||
$this->title = $this->parseContent((string)$attributes['title']);
|
$this->title = $this->parseContent((string)$attributes['title']);
|
||||||
@@ -409,7 +412,7 @@ class ConfigDaemon
|
|||||||
}
|
}
|
||||||
$return[] = [
|
$return[] = [
|
||||||
'type' => 'command',
|
'type' => 'command',
|
||||||
'content' => $cmd . ' "' . $this->parseContent($attributes['name']) . '" "' . $this->parseContent($attributes['name']) . '.frx.bak"',
|
'content' => '[ -f ' . $this->parseContent($attributes['name']) . ' ] && ' . $cmd . ' "' . $this->parseContent($attributes['name']) . '" "' . $this->parseContent($attributes['name']) . '.frx.bak"',
|
||||||
'execute' => "pre"
|
'execute' => "pre"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 = "";
|
||||||
|
|||||||
@@ -1,95 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file is part of the Froxlor project.
|
|
||||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, you can also view it online at
|
|
||||||
* https://files.froxlor.org/misc/COPYING.txt
|
|
||||||
*
|
|
||||||
* @copyright the authors
|
|
||||||
* @author Froxlor team <team@froxlor.org>
|
|
||||||
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Froxlor\Cron\Backup;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Froxlor\Backup\Storages\StorageFactory;
|
|
||||||
use Froxlor\Cron\Forkable;
|
|
||||||
use Froxlor\Cron\FroxlorCron;
|
|
||||||
use Froxlor\Database\Database;
|
|
||||||
use Froxlor\FroxlorLogger;
|
|
||||||
use Froxlor\Settings;
|
|
||||||
use PDO;
|
|
||||||
|
|
||||||
class BackupCron extends FroxlorCron
|
|
||||||
{
|
|
||||||
use Forkable;
|
|
||||||
|
|
||||||
public static function run()
|
|
||||||
{
|
|
||||||
if (!Settings::Get('backup.enabled')) {
|
|
||||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'BackupCron: disabled - exiting');
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_BACKUP_STORAGES . "`");
|
|
||||||
Database::pexecute($stmt);
|
|
||||||
|
|
||||||
$storages = [];
|
|
||||||
while ($storage = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
|
||||||
$storages[$storage['id']] = $storage;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt = Database::prepare("SELECT
|
|
||||||
customerid,
|
|
||||||
loginname,
|
|
||||||
adminid,
|
|
||||||
backup,
|
|
||||||
guid,
|
|
||||||
documentroot
|
|
||||||
FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `backup` > 0
|
|
||||||
");
|
|
||||||
Database::pexecute($stmt);
|
|
||||||
|
|
||||||
$customers = [];
|
|
||||||
while ($customer = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
|
||||||
$customer['storage'] = $storages[$customer['backup']];
|
|
||||||
$customers[] = $customer;
|
|
||||||
}
|
|
||||||
|
|
||||||
self::runFork([self::class, 'handle'], $customers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
private static function handle(array $userdata)
|
|
||||||
{
|
|
||||||
echo "BackupCron: started - creating customer backup for user " . $userdata['loginname'] . "\n";
|
|
||||||
|
|
||||||
$backupStorage = StorageFactory::fromType($userdata['storage']['type'], $userdata);
|
|
||||||
// initialize storage
|
|
||||||
$backupStorage->init();
|
|
||||||
// do what is required to obtain files/archives and move/upload
|
|
||||||
$backupStorage->prepareFiles();
|
|
||||||
// upload/move to target
|
|
||||||
$backupStorage->createFromFiles();
|
|
||||||
// remove by retention
|
|
||||||
$backupStorage->removeOld();
|
|
||||||
|
|
||||||
echo "BackupCron: finished - creating customer backup for user " . $userdata['loginname'] . "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -117,85 +117,6 @@ abstract class DnsBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function writeDKIMconfigs()
|
|
||||||
{
|
|
||||||
if (Settings::Get('dkim.use_dkim') == '1') {
|
|
||||||
if (!file_exists(FileDir::makeCorrectDir(Settings::Get('dkim.dkim_prefix')))) {
|
|
||||||
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'mkdir -p ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('dkim.dkim_prefix'))));
|
|
||||||
FileDir::safe_exec('mkdir -p ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('dkim.dkim_prefix'))));
|
|
||||||
}
|
|
||||||
|
|
||||||
$dkimdomains = '';
|
|
||||||
$dkimkeys = '';
|
|
||||||
$result_domains_stmt = Database::query("
|
|
||||||
SELECT `id`, `domain`, `dkim`, `dkim_id`, `dkim_pubkey`, `dkim_privkey`
|
|
||||||
FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `dkim` = '1' ORDER BY `id` ASC
|
|
||||||
");
|
|
||||||
|
|
||||||
while ($domain = $result_domains_stmt->fetch(PDO::FETCH_ASSOC)) {
|
|
||||||
$privkey_filename = FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id'] . Settings::Get('dkim.privkeysuffix'));
|
|
||||||
$pubkey_filename = FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id'] . '.public');
|
|
||||||
|
|
||||||
if ($domain['dkim_privkey'] == '' || $domain['dkim_pubkey'] == '') {
|
|
||||||
$max_dkim_id_stmt = Database::query("SELECT MAX(`dkim_id`) as `max_dkim_id` FROM `" . TABLE_PANEL_DOMAINS . "`");
|
|
||||||
$max_dkim_id = $max_dkim_id_stmt->fetch(PDO::FETCH_ASSOC);
|
|
||||||
$domain['dkim_id'] = (int)$max_dkim_id['max_dkim_id'] + 1;
|
|
||||||
$privkey_filename = FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id'] . Settings::Get('dkim.privkeysuffix'));
|
|
||||||
FileDir::safe_exec('openssl genrsa -out ' . escapeshellarg($privkey_filename) . ' ' . Settings::Get('dkim.dkim_keylength'));
|
|
||||||
$domain['dkim_privkey'] = file_get_contents($privkey_filename);
|
|
||||||
FileDir::safe_exec("chmod 0640 " . escapeshellarg($privkey_filename));
|
|
||||||
$pubkey_filename = FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id'] . '.public');
|
|
||||||
FileDir::safe_exec('openssl rsa -in ' . escapeshellarg($privkey_filename) . ' -pubout -outform pem -out ' . escapeshellarg($pubkey_filename));
|
|
||||||
$domain['dkim_pubkey'] = file_get_contents($pubkey_filename);
|
|
||||||
FileDir::safe_exec("chmod 0664 " . escapeshellarg($pubkey_filename));
|
|
||||||
$upd_stmt = Database::prepare("
|
|
||||||
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET
|
|
||||||
`dkim_id` = :dkimid,
|
|
||||||
`dkim_privkey` = :privkey,
|
|
||||||
`dkim_pubkey` = :pubkey
|
|
||||||
WHERE `id` = :id
|
|
||||||
");
|
|
||||||
$upd_data = [
|
|
||||||
'dkimid' => $domain['dkim_id'],
|
|
||||||
'privkey' => $domain['dkim_privkey'],
|
|
||||||
'pubkey' => $domain['dkim_pubkey'],
|
|
||||||
'id' => $domain['id']
|
|
||||||
];
|
|
||||||
Database::pexecute($upd_stmt, $upd_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file_exists($privkey_filename) && $domain['dkim_privkey'] != '') {
|
|
||||||
$privkey_file_handler = fopen($privkey_filename, "w");
|
|
||||||
fwrite($privkey_file_handler, $domain['dkim_privkey']);
|
|
||||||
fclose($privkey_file_handler);
|
|
||||||
FileDir::safe_exec("chmod 0640 " . escapeshellarg($privkey_filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file_exists($pubkey_filename) && $domain['dkim_pubkey'] != '') {
|
|
||||||
$pubkey_file_handler = fopen($pubkey_filename, "w");
|
|
||||||
fwrite($pubkey_file_handler, $domain['dkim_pubkey']);
|
|
||||||
fclose($pubkey_file_handler);
|
|
||||||
FileDir::safe_exec("chmod 0644 " . escapeshellarg($pubkey_filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
$dkimdomains .= $domain['domain'] . "\n";
|
|
||||||
$dkimkeys .= "*@" . $domain['domain'] . ":" . $domain['domain'] . ":" . $privkey_filename . "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$dkimdomains_filename = FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/' . Settings::Get('dkim.dkim_domains'));
|
|
||||||
$dkimdomains_file_handler = fopen($dkimdomains_filename, "w");
|
|
||||||
fwrite($dkimdomains_file_handler, $dkimdomains);
|
|
||||||
fclose($dkimdomains_file_handler);
|
|
||||||
$dkimkeys_filename = FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/' . Settings::Get('dkim.dkim_dkimkeys'));
|
|
||||||
$dkimkeys_file_handler = fopen($dkimkeys_filename, "w");
|
|
||||||
fwrite($dkimkeys_file_handler, $dkimkeys);
|
|
||||||
fclose($dkimkeys_file_handler);
|
|
||||||
|
|
||||||
FileDir::safe_exec(escapeshellcmd(Settings::Get('dkim.dkimrestart_command')));
|
|
||||||
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Dkim-milter reloaded');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getDomainList()
|
protected function getDomainList()
|
||||||
{
|
{
|
||||||
$result_domains_stmt = Database::query("
|
$result_domains_stmt = Database::query("
|
||||||
@@ -244,7 +165,7 @@ abstract class DnsBase
|
|||||||
'zonefile' => '',
|
'zonefile' => '',
|
||||||
'froxlorhost' => '1'
|
'froxlorhost' => '1'
|
||||||
];
|
];
|
||||||
$domains['none'] = $hostname_arr;
|
$domains[0] = $hostname_arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($domains)) {
|
if (empty($domains)) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user