Compare commits

...

160 Commits

Author SHA1 Message Date
4dd13200d0 updated dmarc entry 2025-09-03 12:16:59 +02:00
77d399a645 WET RUN
Some checks reported errors
continuous-integration/drone/push Build was killed
2023-12-06 18:59:18 +01:00
c3186e9803 WET RUN
Some checks reported errors
continuous-integration/drone/push Build was killed
2023-12-06 18:51:36 +01:00
92824194fb vars test - fuck it!
Some checks reported errors
continuous-integration/drone/push Build was killed
2023-12-06 18:48:20 +01:00
3b42d5832b vars test
Some checks reported errors
continuous-integration/drone/push Build was killed
2023-12-06 18:45:34 +01:00
9be43e98fa running compose
Some checks reported errors
continuous-integration/drone/push Build was killed
2023-12-06 18:40:40 +01:00
59ce699440 exclude vendor
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-06 18:33:41 +01:00
9dbb5322f2 drone yaml typo
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-06 18:30:23 +01:00
b3290085c0 drone yaml 01
Some checks failed
continuous-integration/drone/push Build is failing
2023-12-06 18:27:45 +01:00
0e75f74eb8 drone yaml
Some checks failed
continuous-integration/drone/push Build is failing
2023-12-06 18:03:16 +01:00
91d2f2da8a drone deployment 2023-12-06 17:48:53 +01:00
638b153969 Merge remote-tracking branch 'origin/0.10.x' into private-0.10.35.1-dmarc 2023-01-18 16:18:03 +01:00
Michael Kaufmann
fbac2f2bbc fix deletion of dns entry
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-12-07 13:50:54 +01:00
Michael Kaufmann
e10f77e219 fix missing id parameter after security question when deleting a ssl-certificate
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-12-02 16:17:59 +01:00
Michael Kaufmann
83ff0f5b00 fix api-key creation
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-12-02 13:42:26 +01:00
Michael Kaufmann
0562d248b5 use same error message for invalid user and disabled password reset to not give away if a user exists
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-12-02 13:24:27 +01:00
Michael Kaufmann
3fda5be5a3 set version to 0.10.38.3 for upcoming security release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-12-02 09:32:29 +01:00
Michael Kaufmann
4d454a3903 secure api-key generation, dns-record as well as ssl-certificate deletion, logo uploading, frame-inclusion and user/email enumeration via 'forgot password'
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-12-02 09:22:08 +01:00
Michael Kaufmann
0e703a4199 adjust validate-test for 'sql username too long' for mariadb
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-11-24 10:30:01 +01:00
Michael Kaufmann
47c71f6035 adjust mysql-usernamelength values for mariadb according to docs
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-11-24 10:03:23 +01:00
Michael Kaufmann
5923cbb1d5 set version to 0.10.38.2 for security release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-11-05 12:41:50 +01:00
Michael Kaufmann
3f10a4aded fix still possible html injection
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-11-05 12:37:53 +01:00
Michael Kaufmann
eaea93296d set version to 0.10.38.1 for security release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-11-04 08:23:44 +01:00
Michael Kaufmann
1182453c18 fix possible code-injection when adding/editing admins/customers; dont output invalid email address in index on error message
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-10-27 14:06:00 +02:00
Michael Kaufmann
2c8bdfbbbc set version to 0.10.38 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-09-02 13:23:51 +02:00
Michael Kaufmann
bbe82286aa add security question for deleting api-keys to avoid accidental deletion
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-08-27 15:02:48 +02:00
Michael Kaufmann
13571f1f16 correct Dropdown directory selection; fixes #1044
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-08-16 08:32:43 +02:00
d82e9b1e81 more template update 2022-08-10 13:57:53 +02:00
992ebebf89 more template update 2022-08-10 13:55:25 +02:00
Michael Kaufmann
d6b34cc8f8 set version to 0.10.37 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-08-05 14:36:02 +02:00
Michael Kaufmann
cfda35a36b update sql-users with their corresponding password-hash-algorithm; remove a few notices for empty values in str_replace and others
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-07-17 12:03:37 +02:00
Michael Kaufmann
57ae625d38 use correct version_compare as PHP8+ does not compare correctly
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-07-11 12:35:07 +02:00
Michael Kaufmann
65ab064289 re-enable quota and sieve plugins for dovecot in buster and bullseye config-templates, fixes #1042
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-07-07 15:13:32 +02:00
Michael Kaufmann
e6a6f6f9de rework FileDir::makePathfield() is mode is 'dropdown' to show all directories correctly (depth limited); fixes #1044
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-07-07 14:45:50 +02:00
Michael Kaufmann
a7b91eb1ed fix missing namespace in BackupCron
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-07-05 17:03:45 +02:00
Michael Kaufmann
a2342ad1d2 set version to 0.10.36 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-07-01 10:16:47 +02:00
Michael Kaufmann
add1818723 fix missing mapping for recently added loginname placeholder in ReportsCron; fixes #1039
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-06-29 08:23:40 +02:00
Michael Kaufmann
51c1d648b2 fix passing complex passwords with special characters to mysqldump in backup-cron; fixes #1038
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-06-28 20:06:52 +02:00
2cb06be3d6 Merge tag '0.10.35.1' into private-0.10.33-dmarc
tagging release 0.10.35.1
2022-06-20 20:06:59 +02:00
93c72e6754 nextcloud quotas for froxlor logins 2022-06-20 20:06:50 +02:00
Daniel
0fca98c652 Add login header image max-width (#1036) 2022-06-16 07:36:12 +02:00
Michael Kaufmann
3682116ba2 set version to 0.10.35.1 for bugfix release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-06-03 08:58:31 +02:00
Michael Kaufmann
3b99070496 argh, typo in the version to update to
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-06-03 08:57:01 +02:00
Michael Kaufmann
25f20e4a7d set version to 0.10.35 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-06-03 08:28:15 +02:00
Michael Kaufmann
d46b2d1d80 add USERNAME replacer to all email templates; fixes #1032
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-05-31 10:43:39 +02:00
Michael Kaufmann
4750dad9e2 fix wrong number of bound variables when customers_see_all == 0
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-05-25 18:54:15 +02:00
Michael Kaufmann
c6830d8e7a set default-ca for acme.sh after updating acme.sh
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-05-09 08:34:38 +02:00
Michael Kaufmann
10b4de4cf9 remove unused IgnorantRecursiveDirectoryIterator and fix uninitialized variables
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-04-20 15:11:48 +02:00
FliegenKLATSCH
ae39a1759a Silence some php 8.1 warnings (#1029) 2022-04-20 15:09:19 +02:00
Michael Kaufmann
989b4fee0e set version to 0.10.34.1 for upcoming bugfix release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-04-13 12:46:16 +02:00
Michael Kaufmann
7f6810c5bd remove accidentally added character
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-04-03 14:43:37 +02:00
Michael Kaufmann
3fbc9815ea respect domain.writeerrorlog and domain.writeaccesslog when using log-to-pipe
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-04-03 14:34:20 +02:00
Michael Kaufmann
11533c2d75 fix exit statement in cli scripts
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-04-02 18:07:36 +02:00
Michael Kaufmann
652a998188 don't rely on executable flag for php-sessionclean script
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-04-01 12:01:06 +02:00
Michael Kaufmann
4546c00adb validate sql_search and sql_orderby API parameters, set version to 0.10.34 for security release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-04-01 09:27:45 +02:00
FliegenKLATSCH
3c16fab92c Fix distro in postfix smtpd banner (#1014) 2022-03-27 11:10:43 +02:00
FliegenKLATSCH
c8c1f7e691 Set RC 1 if an exception occured (#1013) 2022-03-26 13:54:32 +01:00
Michael Kaufmann
02d0194b9f add empty index.html file to all folders to avoid accidental folder-content disclosure if 'Options Indexes' is set for a (parent)folder containing froxlor in webserver-config
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-03-24 14:30:34 +01:00
Michael Kaufmann
54876efc8c fix sh command in install howto
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-03-08 07:55:31 +01:00
Michael Kaufmann
a2f8d02b16 fix installation for mariadb-10.5; fix warnings for not used feature; thx to Akecheta for the hints and testing
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-03-07 18:40:31 +01:00
Michael Kaufmann
0d45e03f19 fix missing $ for a variable in Lighttpd-class
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-03-07 16:37:40 +01:00
Michael Kaufmann
ae74cdda53 update debian/ubuntu instructions
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-03-07 09:28:01 +01:00
b118883013 merged with v0.10.33 2022-03-01 12:29:50 +01:00
Michael Kaufmann
84f5de42a9 move php-sessionclean script to scripts-dir instead of install/scripts/; add cronjob calling php-sessionclean if php-fpm is enabled; remove testing-note for let's encrypt in german language file
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-02-24 08:49:36 +01:00
Michael Kaufmann
1d7d32130a setting version to 0.10.33 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-02-04 13:24:41 +01:00
Michael Kaufmann
9babcde3e5 additional mkdir/chmod parameter fixes and cron-lock file adjustments
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-02-04 10:52:12 +01:00
Kris
9ec76c9fd6 Improve composer.json syntax (#1008)
* Improve composer.json syntax

* Run composer upgrade with PHP 7.4
2022-01-26 14:10:08 +01:00
Michael Kaufmann
61dfeb947f fix incorrect parameter type for mkdir() and chmod()
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-01-25 15:47:37 +01:00
Michael Kaufmann
6fdf2636fc update docs url for api-documentation
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-01-25 14:54:52 +01:00
Michael Kaufmann
0a38d1ab5f add workflow to automatically trigger api-docs generation in Froxlor/Documentation
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-01-21 17:02:35 +01:00
Michael Kaufmann
7c80dc3d1d add script for php-session cleanup
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-01-21 16:02:21 +01:00
Manuel
5ab49e3f50 Call PHP-FPM only when file exists (#1006)
Added `<If "-f %{SCRIPT_FILENAME}">` to load only PHP files that exists. This is to prevent `File not found` error from PHP-FPM and let Apache handle the error output. It removes also unnecessary PHP-FPM calls and `AH01071: Got error ‘Primary script unknown` in PHP error log.

Usually you can find the error whenever someone goes fishing for paths like wp-login.php.

The `<If>` directive is only available in Apache 2.4+ and not 2.2 or earlier.
2022-01-21 12:25:14 +01:00
Michael Kaufmann
06849133a8 modernize parameters of Cronjob::inserttask()
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-01-21 10:39:32 +01:00
Oskar Eisemuth
4a912e3902 Feature/crontaskid (#1005)
* Add \Froxlor\Cron\TaskId for fixed task id naming

* Replace Cronjob::inserttask numbers with \Froxlor\Cron\TaskId constants

* Use TaskId in Froxlor\Cron\System\TasksCron

* Use TaskId in Froxlor\System\Cronjob,
simplify getOutstandingTasks.
Rename lng['tasks'] cronjob task description.
WARNING: DELETE_DOMAIN_PDNS, DELETE_DOMAIN_SSL now use %domain%

* Remove Froxlor\System\Cronjob type 3 check
2022-01-21 10:03:45 +01:00
Michael Kaufmann
bcb95e9b7d check resource-usage for Mysql.add(), thx again to zerody
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-01-18 23:18:54 +01:00
Michael Kaufmann
c97f5f1e29 updated README; sanitize script parameter in index.php; sanitize description fields of entities (thx to zerody for pointing these out)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-01-18 09:29:13 +01:00
timdeluxe
4d289e2a7f Improves text for global open basedir setting (#1004) 2022-01-13 19:50:39 +01:00
Michael Kaufmann
c491f2c03e put commands for cronjob setup at the end of the list (should be the last thing to execute)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-01-13 18:42:40 +01:00
Michael Kaufmann
5832346f75 set version to 0.10.32 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-01-07 15:38:12 +01:00
Michael Kaufmann
4b4770ab36 add missing change-check when ssl-specialsettings are changed
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2022-01-03 20:27:19 +01:00
Michael Kaufmann
8c998dd6f2 Update README.md 2022-01-02 14:53:59 +01:00
Michael Kaufmann
965359ec79 Update README.md 2022-01-02 14:35:36 +01:00
Michael Kaufmann
d1d42f2055 allow setting path to acme.sh installation; fixes #1002
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-12-31 10:38:49 +01:00
Michael Kaufmann
5f41b37770 test dns entry string without any whitespaces/tabs/etc.
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-12-27 16:08:46 +01:00
Michael Kaufmann
61265778a5 fix unit-test
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-12-27 16:01:45 +01:00
Michael Kaufmann
8f0f890145 fix too strict comparison for isemaildomain check in Dns-Zone generation; fixes #1003
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-12-27 15:38:59 +01:00
Michael Kaufmann
5ccae3f9bb do not check for allowed-phpconfigs if fpm/fcgid is not activated (no possibility to select a config anyway)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-12-14 11:23:36 +01:00
Michael Kaufmann
f4d9e64804 set version to 0.10.31 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-12-03 15:30:09 +01:00
Michael Kaufmann
149c0935fa fix Domains.update() with correct path and change_serversettings=0; refs #1001
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-27 22:06:29 +01:00
Michael Kaufmann
cb0b537f6c allow settings/updating documentroot (only relative to customer homedirectory) when change_serversettings permission is not granted; fixes #1000
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-27 18:04:36 +01:00
Michael Kaufmann
b54c012579 respect deactivated flag when createstdsubdomain's default falls back to 'true' if the customer has one (prior to deactivating); refs #998
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-15 20:24:55 +01:00
Michael Kaufmann
389d83f5a3 fix behaviour in Customers.update() in case 'createstdsubdomain' is not set when called via API (wrong default); fixes #998
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-15 20:04:01 +01:00
Michael Kaufmann
00771381e8 set correct php-version numbers for installation dependencies-check; fixes #997
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-13 20:20:05 +01:00
2e81445a4e greylisting dis/enable 2020-11-11 13:40:33 +01:00
5821f4a0e5 dmarc entries for all emaildomains 2020-03-03 16:09:19 +01:00
a9c258105a Merge branch 'origin-0.10.13' into private-0.10.12 2020-03-03 14:49:44 +01:00
34fd64e5b9 theme 2020-01-30 15:04:18 +01:00
0adc511d07 theme 2020-01-30 14:56:49 +01:00
6f32d810c1 theme update 2020-01-30 14:48:22 +01:00
70faf0cf2a merged with 0.10.12 - greylisting still needs work 2020-01-21 12:54:21 +01:00
11b589c399 new dkim keys 2020-01-15 12:41:41 +01:00
c8e5668852 new DKIM keys 2020-01-15 12:37:07 +01:00
1eb0f698c0 restructuring dmarc entry 2020-01-15 11:47:54 +01:00
d4d98122bf DMARC 2019-06-13 12:00:59 +02:00
44d430950c dmarc w/o external auth 2018-07-11 21:04:28 +02:00
4ac5e2439c DKIM format fix 2018-07-11 21:02:51 +02:00
99f7fc14de merge 2018-03-25 11:48:01 +02:00
3dcd109ee2 merge 2018-03-25 11:30:04 +02:00
2ab6b9f6f3 other stuff 2018-03-23 12:31:46 +01:00
2c7502485b bind stuff 2018-03-23 12:30:02 +01:00
581e4deca1 checking for emaildomain and continue 2017-06-27 14:29:04 +02:00
92f8986477 fonts and colors 2016-12-16 17:59:04 +01:00
1f800f5298 merged for live 2016-12-16 17:22:28 +01:00
cb582a2947 Merge remote-tracking branch 'private/maketank-theme' into 0.9.38.4 2016-12-16 17:20:55 +01:00
caf2c21ae9 merged with dkim 2016-12-16 17:20:39 +01:00
18998d40c0 debug 2016-12-16 15:53:13 +01:00
e2380284e8 fonts and colors 2016-12-16 14:28:17 +01:00
dce20e55b8 fonts and colors 2016-12-16 14:27:12 +01:00
8bd32821dd fonts and colors 2016-12-16 14:26:58 +01:00
fe5072d0a2 fonts and colors 2016-12-16 14:25:55 +01:00
6ca2292820 fonts and colors 2016-12-16 14:25:23 +01:00
a51ff99ec2 fonts and colors 2016-12-16 14:23:03 +01:00
57464ba8c4 fonts and colors 2016-12-16 14:22:11 +01:00
924f93435f fonts and colors 2016-12-16 14:17:03 +01:00
c141868fd4 fonts and colors 2016-12-16 14:15:32 +01:00
3154914532 fonts and colors 2016-12-16 14:13:39 +01:00
f6e3779728 fonts and colors 2016-12-16 14:10:18 +01:00
c7e0fe57d1 fonts and colors 2016-12-16 14:09:33 +01:00
57aacd96e4 fonts and colors 2016-12-16 14:07:09 +01:00
27be204c96 fonts and colors 2016-12-16 14:06:26 +01:00
b7ab10665a fonts and colors 2016-12-16 14:02:04 +01:00
8bc1a5be69 fonts and colors 2016-12-16 14:00:44 +01:00
832799942e fonts and colors 2016-12-16 13:59:48 +01:00
081858d7bb fonts and colors 2016-12-16 13:58:30 +01:00
88791d3d4a fonts and colors 2016-12-16 13:57:24 +01:00
1f0b90ceef fonts and colors 2016-12-16 13:55:51 +01:00
8f295f1b5d fonts and colors 2016-12-16 13:54:21 +01:00
9abe4415af fonts and colors 2016-12-16 13:53:20 +01:00
d25dd58f7b fonts and colors 2016-12-16 13:49:51 +01:00
9d363c5eb0 fonts and colors 2016-12-16 13:48:25 +01:00
acd357f561 fonts and colors 2016-12-16 13:47:58 +01:00
660272b64b fonts and colors 2016-12-16 13:46:03 +01:00
e2209f53d1 logo 2016-12-16 13:44:41 +01:00
7a7f131861 logo 2016-12-16 13:38:22 +01:00
67803ff106 logo 2016-12-16 13:37:42 +01:00
03bafc9540 logo 2016-12-16 13:34:03 +01:00
8fbc3acba6 logo 2016-12-16 13:32:03 +01:00
0e9dad1b71 logo 2016-12-16 13:28:59 +01:00
3542e85195 Maketank theme 2016-12-16 13:23:16 +01:00
b4829b521b .gitignore not maketank 2016-12-16 13:22:44 +01:00
46bf7005e6 disabled AXFR settings 2016-12-15 15:51:21 +01:00
924731d54d disabled AXFR settings 2016-12-15 15:49:06 +01:00
bc550e086f DKIM and dmarc hardcoded 2016-12-15 15:31:40 +01:00
3167df9947 DKIM and dmarc hardcoded 2016-12-15 13:31:26 +01:00
8686b54fb8 DKIM and dmarc hardcoded 2016-12-15 13:29:15 +01:00
480afb0ccd what a bullshit 2016-12-15 13:20:33 +01:00
b52364a873 DKIM and dmarc hardcoded 2016-12-15 13:10:39 +01:00
ccc95b638b Greylisting TODO: Describe system config 2016-11-09 19:00:00 +01:00
2365d3eae3 initial Greylist: TODO: System-settings 2016-11-09 17:53:59 +01:00
2e0ee3d683 initial Greylist: TODO: System-settings 2016-11-09 17:52:38 +01:00
523 changed files with 11134 additions and 1225 deletions

40
.drone.yml Normal file
View File

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

14
.github/workflows/build-apidocs.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
name: build-docs
on:
release:
types: [published]
jobs:
build_docs:
runs-on: ubuntu-latest
steps:
- env:
GITHUB_TOKEN: ${{ secrets.ORG_GITHUB_TOKEN }}
run: |
gh workflow run --repo Froxlor/Documentation build-docs -f ref=${{github.ref_name}}

1
.gitignore vendored
View File

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

View File

@@ -1,6 +1,6 @@
[![Froxlor-CI](https://github.com/Froxlor/Froxlor/actions/workflows/build-mariadb.yml/badge.svg?branch=master)](https://github.com/Froxlor/Froxlor/actions/workflows/build-mariadb.yml)
[![Froxlor-CI](https://github.com/Froxlor/Froxlor/actions/workflows/build-mysql.yml/badge.svg?branch=master)](https://github.com/Froxlor/Froxlor/actions/workflows/build-mysql.yml)
[![Gitter](https://badges.gitter.im/Froxlor/community.svg)](https://gitter.im/Froxlor/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.froxlor.org)
# Froxlor
@@ -21,12 +21,16 @@ Developed by experienced server administrators, this panel simplifies the effort
9. Have fun!
### Detailed installation
https://github.com/Froxlor/Froxlor/wiki/Install-froxlor-from-tarball
https://docs.froxlor.org/general/installation/index.html
## Help
You may find help in the following places:
### Discord
The froxlor community discord server can be found here: https://discord.froxlor.org
### IRC
froxlor may be found on libera.chat, channel #froxlor:
@@ -38,36 +42,36 @@ The community is located on https://forum.froxlor.org/
### Wiki
More documentation may be found in the froxlor - wiki:
https://github.com/Froxlor/Froxlor/wiki
More documentation may be found in the froxlor - documentation:
https://docs.froxlor.org/
## License
May be found in COPYING
May be found in [COPYING](COPYING)
## Downloads
### Tarball
https://files.froxlor.org/releases/froxlor-latest.tar.gz [MD5](https://files.froxlor.org/releases/froxlor-latest.tar.gz.md5) [SHA1](https://files.froxlor.org/releases/froxlor-latest.tar.gz.sha1)
### Debian repository
### Debian / Ubutnu repository
[HowTo](https://github.com/Froxlor/Froxlor/wiki/Install-froxlor-on-debian)
[HowTo](https://docs.froxlor.org/general/installation/aptpackage.html)
#### Debian
```
apt-get -y install apt-transport-https lsb-release ca-certificates
wget -O - https://deb.froxlor.org/froxlor.gpg | apt-key add -
echo "deb https://deb.froxlor.org/debian $(lsb_release -sc) main" > /etc/apt/sources.list.d/froxlor.list
apt-get -y install apt-transport-https lsb-release ca-certificates curl
curl -sSLo /usr/share/keyrings/deb.froxlor.org-froxlor.gpg https://deb.froxlor.org/froxlor.gpg
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 repository
[HowTo](https://github.com/Froxlor/Froxlor/wiki/Install-froxlor-on-ubuntu)
#### Ubuntu
```
apt-get -y install apt-transport-https lsb-release ca-certificates
wget -O - https://deb.froxlor.org/froxlor.gpg | apt-key add -
echo "deb https://deb.froxlor.org/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/froxlor.list
apt-get -y install apt-transport-https lsb-release ca-certificates curl
curl -sSLo /usr/share/keyrings/deb.froxlor.org-froxlor.gpg https://deb.froxlor.org/froxlor.gpg
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

0
actions/admin/index.html Normal file
View File

View File

@@ -249,7 +249,7 @@ return array(
'extras' => $lng['menue']['extras']['extras'],
'extras.directoryprotection' => $lng['menue']['extras']['extras'] . " / " . $lng['menue']['extras']['directoryprotection'],
'extras.pathoptions' => $lng['menue']['extras']['extras'] . " / " . $lng['menue']['extras']['pathoptions'],
'extras.logger' => $lng['menue']['extras']['extras'] . " / " . $lng['menue']['logger']['logger'],
'extras.logger' => $lng['menue']['extras']['extras'] . " / " . $lng['admin']['loggersystem'],
'extras.backup' => $lng['menue']['extras']['extras'] . " / " . $lng['menue']['extras']['backup'],
'traffic' => $lng['menue']['traffic']['traffic'],
'traffic.http' => $lng['menue']['traffic']['traffic'] . " / HTTP",

View File

@@ -133,6 +133,15 @@ return array(
'cronmodule' => 'froxlor/letsencrypt',
'save_method' => 'storeSettingField'
),
'system_acmeshpath' => array(
'label' => $lng['serversettings']['acmeshpath'],
'settinggroup' => 'system',
'varname' => 'acmeshpath',
'type' => 'string',
'string_type' => 'file',
'default' => '/root/.acme.sh/acme.sh',
'save_method' => 'storeSettingField'
),
'system_letsencryptacmeconf' => array(
'label' => $lng['serversettings']['letsencryptacmeconf'],
'settinggroup' => 'system',
@@ -220,7 +229,7 @@ return array(
'default' => true,
'save_method' => 'storeSettingField'
),
'system_disable_le_selfcheck' => array(
'system_le_domain_dnscheck' => array(
'label' => $lng['serversettings']['le_domain_dnscheck'],
'settinggroup' => 'system',
'varname' => 'le_domain_dnscheck',

View File

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

View File

0
actions/index.html Normal file
View File

View File

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

View File

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

View File

@@ -148,7 +148,7 @@ if ($page == 'domains' || $page == 'overview') {
$customers = \Froxlor\UI\HTML::makeoption($lng['panel']['please_choose'], 0, 0, true);
$result_customers_stmt = Database::prepare("
SELECT `customerid`, `loginname`, `name`, `firstname`, `company`
FROM `" . TABLE_PANEL_CUSTOMERS . "` " . ($userinfo['customers_see_all'] ? '' : " WHERE `adminid` = '" . (int) $userinfo['adminid'] . "' ") . " ORDER BY COALESCE(NULLIF(`name`,''), `company`) ASC");
FROM `" . TABLE_PANEL_CUSTOMERS . "` " . ($userinfo['customers_see_all'] ? '' : " WHERE `adminid` = :adminid ") . " ORDER BY COALESCE(NULLIF(`name`,''), `company`) ASC");
$params = array();
if ($userinfo['customers_see_all'] == '0') {
$params['adminid'] = $userinfo['adminid'];
@@ -640,8 +640,8 @@ if ($page == 'domains' || $page == 'overview') {
// update customer/admin counters
\Froxlor\User::updateCounters(false);
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
$result_str = $result['imported'] . ' / ' . $result['all'] . (! empty($result['note']) ? ' (' . $result['note'] . ')' : '');
\Froxlor\UI\Response::standard_success('domain_import_successfully', $result_str, array(
@@ -674,7 +674,7 @@ if ($page == 'domains' || $page == 'overview') {
function formatDomainEntry(&$row, &$idna_convert)
{
$row['domain'] = $idna_convert->decode($row['domain']);
$row['aliasdomain'] = $idna_convert->decode($row['aliasdomain']);
$row['aliasdomain'] = $idna_convert->decode($row['aliasdomain'] ?? '');
$row['ipandport'] = '';
foreach ($row['ipsandports'] as $rowip) {
@@ -685,7 +685,7 @@ function formatDomainEntry(&$row, &$idna_convert)
}
}
$row['ipandport'] = substr($row['ipandport'], 0, - 1);
$row['termination_date'] = str_replace("0000-00-00", "", $row['termination_date']);
$row['termination_date'] = str_replace("0000-00-00", "", $row['termination_date'] ?? '');
$row['termination_css'] = "";
if ($row['termination_date'] != "") {

View File

@@ -66,11 +66,11 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
'page' => $page
), $_part, $settings_all, $settings_part, $only_enabledisable)) {
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "rebuild configfiles due to changed setting");
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
// Using nameserver, insert a task which rebuilds the server config
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
// cron.d file
\Froxlor\System\Cronjob::inserttask('99');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_CRON);
\Froxlor\UI\Response::standard_success('settingssaved', '', array(
'filename' => $filename,
@@ -146,12 +146,12 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "rebuild configfiles");
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask('10');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA);
// Using nameserver, insert a task which rebuilds the server config
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
// cron.d file
\Froxlor\System\Cronjob::inserttask('99');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_CRON);
\Froxlor\UI\Response::standard_success('rebuildingconfigs', '', array(
'filename' => 'admin_index.php'

View File

@@ -65,7 +65,7 @@ if ($page == 'overview') {
eval("echo \"" . \Froxlor\UI\Template::getTemplate('update/update_end') . "\";");
\Froxlor\User::updateCounters();
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
@chmod(\Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php', 0440);
$successful_update = true;

View File

@@ -1,5 +1,5 @@
<?php
if (! defined('AREA')) {
if (!defined('AREA')) {
header("Location: index.php");
exit();
}
@@ -27,12 +27,13 @@ use Froxlor\Database\Database;
$del_stmt = Database::prepare("DELETE FROM `" . TABLE_API_KEYS . "` WHERE id = :id");
$success_message = "";
$id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
$id = isset($_POST['id']) ? (int) $_POST['id'] : (isset($_GET['id']) ? (int) $_GET['id'] : 0);
$area = AREA;
// do the delete and then just show a success-message and the apikeys list again
if ($action == 'delete') {
if ($id > 0) {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
$chk = (AREA == 'admin' && $userinfo['customers_see_all'] == '1') ? true : false;
if (AREA == 'customer') {
$chk_stmt = Database::prepare("
@@ -61,8 +62,17 @@ if ($action == 'delete') {
));
$success_message = sprintf($lng['apikeys']['apikey_removed'], $id);
}
} else {
\Froxlor\UI\HTML::askYesNo('api_reallydelete', $filename, array(
'page' => $page,
'action' => $action,
'id' => $id
), $id);
}
}
} elseif ($action == 'add') {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_API_KEYS . "` SET
`apikey` = :key, `secret` = :secret, `adminid` = :aid, `customerid` = :cid, `valid_until` = '-1', `allowed_from` = ''
@@ -82,13 +92,23 @@ if ($action == 'delete') {
'cid' => $cid
));
$success_message = $lng['apikeys']['apikey_added'];
} else {
\Froxlor\UI\HTML::askYesNo('api_reallyadd', $filename, array(
'page' => $page,
'action' => $action
), $id);
}
} elseif ($action == 'jqEditApiKey') {
$keyid = isset($_POST['id']) ? (int) $_POST['id'] : 0;
if (empty($keyid)) {
echo json_encode(false);
exit;
}
$allowed_from = isset($_POST['allowed_from']) ? $_POST['allowed_from'] : "";
$valid_until = isset($_POST['valid_until']) ? (int) $_POST['valid_until'] : - 1;
$valid_until = isset($_POST['valid_until']) ? (int) $_POST['valid_until'] : -1;
// validate allowed_from
if (! empty($allowed_from)) {
if (!empty($allowed_from)) {
$ip_list = array_map('trim', explode(",", $allowed_from));
$_check_list = $ip_list;
foreach ($_check_list as $idx => $ip) {
@@ -100,8 +120,8 @@ if ($action == 'delete') {
$allowed_from = implode(",", array_unique($ip_list));
}
if ($valid_until <= 0 || ! is_numeric($valid_until)) {
$valid_until = - 1;
if ($valid_until <= 0 || !is_numeric($valid_until)) {
$valid_until = -1;
}
$upd_stmt = Database::prepare("

View File

@@ -30,7 +30,7 @@
"docs": "https://github.com/Froxlor/Froxlor/wiki"
},
"require": {
"php": ">=7.1",
"php": "^7.1 || ^8.0",
"ext-session": "*",
"ext-ctype": "*",
"ext-pdo": "*",
@@ -52,7 +52,6 @@
},
"require-dev": {
"phpunit/phpunit": "^9",
"php": ">=7.3",
"ext-pcntl": "*",
"phpcompatibility/php-compatibility": "*",
"squizlabs/php_codesniffer": "*",

615
composer.lock generated

File diff suppressed because it is too large Load Diff

0
css/images/index.html Normal file
View File

0
css/index.html Normal file
View File

View File

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

View File

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

View File

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

0
doc/example/index.html Normal file
View File

0
doc/index.html Normal file
View File

View File

@@ -22,6 +22,7 @@ require './lib/init.php';
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\FroxlorLogger;
use Froxlor\Validate\Validate;
if ($action == '') {
$action = 'login';
@@ -352,8 +353,7 @@ if ($action == '2fa_entercode') {
$message = sprintf($lng['error']['login_blocked'], Settings::Get('login.deactivatetime'));
break;
case 4:
$cmail = isset($_GET['customermail']) ? $_GET['customermail'] : 'unknown';
$message = str_replace('%s', $cmail, $lng['error']['errorsendingmail']);
$message = $lng['error']['errorsendingmailpub'];
break;
case 5:
$message = $lng['error']['user_banned'];
@@ -378,6 +378,8 @@ if ($action == '2fa_entercode') {
$lastscript = "";
if (isset($_REQUEST['script']) && $_REQUEST['script'] != "") {
$lastscript = $_REQUEST['script'];
$lastscript = str_replace("..", "", $lastscript);
$lastscript = htmlspecialchars($lastscript, ENT_QUOTES);
if (! file_exists(__DIR__ . "/" . $lastscript)) {
$lastscript = "";
@@ -423,6 +425,19 @@ if ($action == 'forgotpwd') {
}
}
$no_action = false;
if ($adminchecked) {
if (Settings::Get('panel.allow_preset_admin') != '1') {
$message = $lng['pwdreminder']['notallowed'];
unset($adminchecked);
}
} else {
if (Settings::Get('panel.allow_preset') != '1') {
$message = $lng['pwdreminder']['notallowed'];
}
}
if (empty($message)) {
if ($result_stmt !== null) {
$user = $result_stmt->fetch(PDO::FETCH_ASSOC);
@@ -564,18 +579,8 @@ if ($action == 'forgotpwd') {
unset($user);
}
} else {
$message = $lng['login']['usernotfound'];
}
}
if ($adminchecked) {
if (Settings::Get('panel.allow_preset_admin') != '1') {
$message = $lng['pwdreminder']['notallowed'];
unset($adminchecked);
}
} else {
if (Settings::Get('panel.allow_preset') != '1') {
$message = $lng['pwdreminder']['notallowed'];
}
}

View File

@@ -495,7 +495,6 @@ opcache.load_comments
opcache.revalidate_path
opcache.save_comments
opcache.use_cwd
opcache.validate_timestamps
opcache.fast_shutdown'),
('phpfpm', 'ini_admin_values', 'cgi.redirect_status_env
date.timezone
@@ -519,7 +518,8 @@ opcache.restrict_api
opcache.revalidate_freq
opcache.max_accelerated_files
opcache.memory_consumption
opcache.interned_strings_buffer'),
opcache.interned_strings_buffer
opcache.validate_timestamps'),
('nginx', 'fastcgiparams', '/etc/nginx/fastcgi_params'),
('system', 'lastaccountnumber', '0'),
('system', 'lastguid', '9999'),
@@ -682,6 +682,7 @@ opcache.interned_strings_buffer'),
('system', 'createstdsubdom_default', '1'),
('system', 'froxlorusergroup', ''),
('system', 'froxlorusergroup_gid', ''),
('system', 'acmeshpath', '/root/.acme.sh/acme.sh'),
('api', 'enabled', '0'),
('2fa', 'enabled', '1'),
('panel', 'decimal_places', '4'),
@@ -722,8 +723,8 @@ opcache.interned_strings_buffer'),
('panel', 'logo_image_login', ''),
('panel', 'logo_overridetheme', '0'),
('panel', 'logo_overridecustom', '0'),
('panel', 'version', '0.10.30'),
('panel', 'db_version', '202109040');
('panel', 'version', '0.10.38.3'),
('panel', 'db_version', '202112310');
DROP TABLE IF EXISTS `panel_tasks`;

0
install/index.html Normal file
View File

View File

@@ -550,16 +550,23 @@ class FroxlorInstall
$this->_updateSetting($upd_stmt, 'error', 'system', 'errorlog_level');
}
/*
* not yet used in configfiles
* -> 0.11.x
*
$distros = glob(\Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . '/lib/configfiles/') . '*.xml');
foreach ($distros as $_distribution) {
if ($this->_data['distribution'] == str_replace(".xml", "", strtolower(basename($_distribution)))) {
$dist = new \Froxlor\Config\ConfigParser($_distribution);
$defaults = $dist->getDefaults();
foreach ($defaults->property as $property) {
$this->_updateSetting($upd_stmt, $property->value, $property->settinggroup, $property->varname);
if (!empty($defaults)) {
foreach ($defaults as $property) {
$this->_updateSetting($upd_stmt, $property->attributes()->value, $property->attributes()->settinggroup, $property->attributes()->varname);
}
}
}
}
*/
$this->_updateSetting($upd_stmt, $this->_data['activate_newsfeed'], 'admin', 'show_news_feed');
$this->_updateSetting($upd_stmt, dirname(dirname(dirname(__FILE__))), 'system', 'letsencryptchallengepath');
@@ -734,8 +741,26 @@ class FroxlorInstall
private function _grantDbPrivilegesTo(&$db_root, $database, $username, $password, $access_host)
{
// mariadb
if (version_compare($db_root->getAttribute(\PDO::ATTR_SERVER_VERSION), '10.0.0', '>=')) {
// create user
$stmt = $db_root->prepare("
CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY :password
");
$stmt->execute(array(
"password" => $password
));
// grant privileges
$stmt = $db_root->prepare("
GRANT ALL ON `" . $database . "`.* TO :username@:host
");
$stmt->execute(array(
"username" => $username,
"host" => $access_host
));
}
// mysql8 compatibility
if (version_compare($db_root->getAttribute(\PDO::ATTR_SERVER_VERSION), '8.0.11', '>=')) {
elseif (version_compare($db_root->getAttribute(\PDO::ATTR_SERVER_VERSION), '8.0.11', '>=')) {
// create user
$stmt = $db_root->prepare("
CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED WITH mysql_native_password BY :password

0
install/lib/index.html Normal file
View File

View File

@@ -22,8 +22,8 @@ $lng['requirements']['not_true'] = 'no';
$lng['requirements']['notfound'] = 'not found';
$lng['requirements']['notinstalled'] = 'not installed';
$lng['requirements']['activated'] = 'enabled';
$lng['requirements']['phpversion'] = 'PHP version >= 7.0';
$lng['requirements']['newerphpprefered'] = 'Good, but php-7.1 is preferred.';
$lng['requirements']['phpversion'] = 'PHP version >= 7.1';
$lng['requirements']['newerphpprefered'] = 'Good, but php-7.4 is preferred.';
$lng['requirements']['phppdo'] = 'PHP PDO extension and PDO-MySQL driver...';
$lng['requirements']['phpsession'] = 'PHP session-extension...';
$lng['requirements']['phpctype'] = 'PHP ctype-extension...';

View File

@@ -22,7 +22,7 @@ $lng['requirements']['not_true'] = 'non';
$lng['requirements']['notfound'] = 'introuvable';
$lng['requirements']['notinstalled'] = 'non installé';
$lng['requirements']['activated'] = 'activé';
$lng['requirements']['phpversion'] = 'PHP version >= 7.0';
$lng['requirements']['phpversion'] = 'PHP version >= 7.1';
$lng['requirements']['phppdo'] = 'extension PHP PDO et pilote PDO-MySQL ...';
$lng['requirements']['phpxml'] = 'extension PHP XML...';
$lng['requirements']['phpfilter'] = 'extension PHP filter ...';

View File

@@ -22,8 +22,8 @@ $lng['requirements']['not_true'] = 'nein';
$lng['requirements']['notfound'] = 'nicht gefunden';
$lng['requirements']['notinstalled'] = 'nicht installiert';
$lng['requirements']['activated'] = 'ist aktiviert.';
$lng['requirements']['phpversion'] = 'PHP Version >= 7.0';
$lng['requirements']['newerphpprefered'] = 'Passt, aber php-7.1 wird bevorzugt.';
$lng['requirements']['phpversion'] = 'PHP Version >= 7.1';
$lng['requirements']['newerphpprefered'] = 'Passt, aber php-7.4 wird bevorzugt.';
$lng['requirements']['phppdo'] = 'PHP PDO Erweiterung und PDO-MySQL Treiber...';
$lng['requirements']['phpsession'] = 'PHP session-Erweiterung...';
$lng['requirements']['phpctype'] = 'PHP ctype-Erweiterung...';

0
install/lng/index.html Normal file
View File

View File

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

View File

View File

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

View File

View File

View File

View File

View File

@@ -843,7 +843,7 @@ if (\Froxlor\Froxlor::isDatabaseVersion('202106270')) {
throw new \Exception("img directory does not exist and cannot be created");
}
if (!is_writable($path)) {
if (!chmod($path, '0775')) {
if (!chmod($path, 0775)) {
throw new \Exception("Cannot write to img directory");
}
}
@@ -948,3 +948,76 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.29.1')) {
showUpdateStep("Updating from 0.10.29.1 to 0.10.30", false);
\Froxlor\Froxlor::updateToVersion('0.10.30');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.30')) {
showUpdateStep("Updating from 0.10.30 to 0.10.31", false);
\Froxlor\Froxlor::updateToVersion('0.10.31');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202109040')) {
showUpdateStep("Add setting for acme.sh install location", true);
Settings::AddNew("system.acmeshpath", '/root/.acme.sh/acme.sh');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202112310');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.31')) {
showUpdateStep("Updating from 0.10.31 to 0.10.32", false);
\Froxlor\Froxlor::updateToVersion('0.10.32');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.32')) {
showUpdateStep("Updating from 0.10.32 to 0.10.33", false);
\Froxlor\Froxlor::updateToVersion('0.10.33');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.33')) {
showUpdateStep("Updating from 0.10.33 to 0.10.34", false);
\Froxlor\Froxlor::updateToVersion('0.10.34');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.34')) {
showUpdateStep("Updating from 0.10.34 to 0.10.34.1", false);
\Froxlor\Froxlor::updateToVersion('0.10.34.1');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.34.1')) {
showUpdateStep("Updating from 0.10.34.1 to 0.10.35", false);
\Froxlor\Froxlor::updateToVersion('0.10.35');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.35')) {
showUpdateStep("Updating from 0.10.35 to 0.10.35.1", false);
\Froxlor\Froxlor::updateToVersion('0.10.35.1');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.35.1')) {
showUpdateStep("Updating from 0.10.35.1 to 0.10.36", false);
\Froxlor\Froxlor::updateToVersion('0.10.36');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.36')) {
showUpdateStep("Updating from 0.10.36 to 0.10.37", false);
\Froxlor\Froxlor::updateToVersion('0.10.37');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.37')) {
showUpdateStep("Updating from 0.10.37 to 0.10.38", false);
\Froxlor\Froxlor::updateToVersion('0.10.38');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.38')) {
showUpdateStep("Updating from 0.10.38 to 0.10.38.1", false);
\Froxlor\Froxlor::updateToVersion('0.10.38.1');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.38.1')) {
showUpdateStep("Updating from 0.10.38.1 to 0.10.38.2", false);
\Froxlor\Froxlor::updateToVersion('0.10.38.2');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.38.2')) {
showUpdateStep("Updating from 0.10.38.2 to 0.10.38.3", false);
\Froxlor\Froxlor::updateToVersion('0.10.38.3');
}

View File

View File

View File

View File

View File

0
js/index.html Normal file
View File

0
js/plugins/index.html Normal file
View File

View File

@@ -297,6 +297,10 @@ abstract class ApiCommand extends ApiParameter
$sortfield[$id] = $sfield;
}
$field = implode('.', $sortfield);
if (preg_match('/^([a-z0-9\-\._`]+)$/i', $field) == false) {
// skip
continue;
}
if (! $first) {
$condition .= ' AND ';
}
@@ -313,6 +317,14 @@ abstract class ApiCommand extends ApiParameter
} elseif (strtolower($valoper['op']) == 'in' && is_array($valoper['value']) && count($valoper['value']) > 0) {
$condition .= $field . ' ' . $valoper['op'] . ' (';
foreach ($valoper['value'] as $incnt => $invalue) {
if (!is_numeric($incnt)) {
// skip
continue;
}
if (!empty($invalue) && preg_match('/^([a-z0-9\-\._`]+)$/i', $invalue) == false) {
// skip
continue;
}
$condition .= ":" . $cleanfield . $incnt . ", ";
$query_fields[':' . $cleanfield . $incnt] = $invalue ?? '';
}
@@ -398,6 +410,10 @@ abstract class ApiCommand extends ApiParameter
$sortfield[$id] = $sfield;
}
$field = implode('.', $sortfield);
if (preg_match('/^([a-z0-9\-\._`]+)$/i', $field) == false) {
// skip
continue;
}
$by = strtoupper($by);
if (! in_array($by, [
'ASC',
@@ -423,6 +439,7 @@ abstract class ApiCommand extends ApiParameter
return $order;
}
/**
* return logger instance
*

View File

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

View File

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

View File

@@ -323,7 +323,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
));
// trigger removing of certificate from acme.sh if let's encrypt
if ($chk['letsencrypt'] == '1') {
\Froxlor\System\Cronjob::inserttask('12', $chk['domain']);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $chk['domain']);
}
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] removed ssl-certificate for '" . $chk['domain'] . "'");
return $this->response(200, "successful", $result);
@@ -421,7 +421,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
);
Database::pexecute($stmt, $params, true, true);
// insert task to re-generate webserver-configs (#1260)
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
return true;
}
}

View File

@@ -114,7 +114,7 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE
), true, true);
// insert task to re-generate the cron.d-file
\Froxlor\System\Cronjob::inserttask('99');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_CRON);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] cronjob with description '" . $result['module'] . '/' . $result['cronfile'] . "' has been updated by '" . $this->getUserDetail('loginname') . "'");
$result = $this->apiCall('Cronjobs.get', array(
'id' => $id

View File

@@ -108,7 +108,7 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
'backup_web' => $backup_web
);
// schedule backup job
\Froxlor\System\Cronjob::inserttask('20', $task_data);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_CUSTOMER_BACKUP, $task_data);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added customer-backup job for '" . $customer['loginname'] . "'. Target directory: " . $userpath);
return $this->response(200, "successful", $task_data);

View File

@@ -368,6 +368,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
foreach ($hp_result['value'] as $index => $value) {
$hp_result[$index] = $value;
}
$nextcloud_quota = $hp_result['nextcloud_quota'] ?? 0;
$diskspace = $hp_result['diskspace'] ?? 0;
$traffic = $hp_result['traffic'] ?? 0;
$subdomains = $hp_result['subdomains'] ?? 0;
@@ -385,6 +386,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$dnsenabled = $hp_result['dnsenabled'] ?? 0;
$logviewenabled = $hp_result['logviewenabled'] ?? 0;
} else {
$nextcloud_quota = $this->getUlParam('nextcloud_quota', 'nextcloud_quota_ul', true, 0);
$diskspace = $this->getUlParam('diskspace', 'diskspace_ul', true, 0);
$traffic = $this->getUlParam('traffic', 'traffic_ul', true, 0);
$subdomains = $this->getUlParam('subdomains', 'subdomains_ul', true, 0);
@@ -404,12 +406,12 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
}
// validation
$name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true);
$firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', '', '', array(), true);
$company = \Froxlor\Validate\Validate::validate($company, 'company', '', '', array(), true);
$street = \Froxlor\Validate\Validate::validate($street, 'street', '', '', array(), true);
$name = \Froxlor\Validate\Validate::validate($name, 'name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$company = \Froxlor\Validate\Validate::validate($company, 'company', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$street = \Froxlor\Validate\Validate::validate($street, 'street', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$zipcode = \Froxlor\Validate\Validate::validate($zipcode, 'zipcode', '/^[0-9 \-A-Z]*$/', '', array(), true);
$city = \Froxlor\Validate\Validate::validate($city, 'city', '', '', array(), true);
$city = \Froxlor\Validate\Validate::validate($city, 'city', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$phone = \Froxlor\Validate\Validate::validate($phone, 'phone', '/^[0-9\- \+\(\)\/]*$/', '', array(), true);
$fax = \Froxlor\Validate\Validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', array(), true);
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
@@ -533,6 +535,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'api_allowed' => $api_allowed,
'docroot' => $documentroot,
'guid' => $guid,
'nextcloud_quota' => $nextcloud_quota,
'diskspace' => $diskspace,
'traffic' => $traffic,
'subdomains' => $subdomains,
@@ -574,6 +577,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
`api_allowed` = :api_allowed,
`documentroot` = :docroot,
`guid` = :guid,
`nextcloud_quota` = :nextcloud_quota,
`diskspace` = :diskspace,
`traffic` = :traffic,
`subdomains` = :subdomains,
@@ -645,10 +649,10 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
unset($ins_data);
// insert task to create homedir etc.
\Froxlor\System\Cronjob::inserttask('2', $loginname, $guid, $guid, $store_defaultindex);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_HOME, $loginname, $guid, $guid, $store_defaultindex);
// Using filesystem - quota, insert a task which cleans the filesystem - quota
\Froxlor\System\Cronjob::inserttask('10');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA);
// Add htpasswd for the stats-pages
$htpasswdPassword = \Froxlor\System\Crypt::makeCryptPassword($password, true);
@@ -674,7 +678,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically added " . $stats_folder . " htpasswd for user '" . $loginname . "'");
Database::pexecute($ins_stmt, $ins_data, true, true);
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
// add default FTP-User
// also, add froxlor-local user to ftp-group (if exists!) to
@@ -739,7 +743,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'customerid' => $customerid
), true, true);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically added standardsubdomain for user '" . $loginname . "'");
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
}
}
@@ -915,7 +919,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* @param bool $mysqls_ul
* optional, whether customer should have unlimited mysql-databases, default 0 (false)
* @param bool $createstdsubdomain
* optional, whether to create a standard-subdomain ([loginname].froxlor-hostname.tld), default 0 (false)
* optional, whether to create a standard-subdomain ([loginname].froxlor-hostname.tld), default 1 (if customer has std-subdomain) else 0 (false)
* @param bool $phpenabled
* optional, whether to allow usage of PHP, default 0 (false)
* @param array $allowed_phpconfigs
@@ -950,7 +954,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$move_to_admin = (int) ($this->getParam('move_to_admin', true, 0));
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$email = $this->getParam('email', true, $idna_convert->decode($result['email']));
$email = $this->getParam('email', true, $idna_convert->decode($result['email'] ?? ''));
$name = $this->getParam('name', true, $result['name']);
$firstname = $this->getParam('firstname', true, $result['firstname']);
$company_required = empty($result['company']) && ((! empty($name) && empty($firstname)) || (empty($name) && ! empty($firstname)) || (empty($name) && empty($firstname)));
@@ -968,6 +972,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, $result['custom_notes_show']);
$dec_places = Settings::Get('panel.decimal_places');
$nextcloud_quota = $this->getUlParam('nextcloud_quota', 'nextcloud_quota_ul', true, round($result['nextcloud_quota'], $dec_places));
$diskspace = $this->getUlParam('diskspace', 'diskspace_ul', true, round($result['diskspace'] / 1024, $dec_places));
$traffic = $this->getUlParam('traffic', 'traffic_ul', true, round($result['traffic'] / (1024 * 1024), $dec_places));
$subdomains = $this->getUlParam('subdomains', 'subdomains_ul', true, $result['subdomains']);
@@ -979,7 +984,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$email_pop3 = $this->getParam('email_pop3', true, $result['pop3']);
$ftps = $this->getUlParam('ftps', 'ftps_ul', true, $result['ftps']);
$mysqls = $this->getUlParam('mysqls', 'mysqls_ul', true, $result['mysqls']);
$createstdsubdomain = $this->getBoolParam('createstdsubdomain', true, 0);
$createstdsubdomain = $this->getBoolParam('createstdsubdomain', true, ($result['standardsubdomain'] != 0 ? 1 : 0));
$password = $this->getParam('new_customer_password', true, '');
$phpenabled = $this->getBoolParam('phpenabled', true, $result['phpenabled']);
$allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, json_decode($result['allowed_phpconfigs'], true));
@@ -998,12 +1003,12 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
// validation
if ($this->isAdmin()) {
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true);
$firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', '', '', array(), true);
$company = \Froxlor\Validate\Validate::validate($company, 'company', '', '', array(), true);
$street = \Froxlor\Validate\Validate::validate($street, 'street', '', '', array(), true);
$name = \Froxlor\Validate\Validate::validate($name, 'name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$company = \Froxlor\Validate\Validate::validate($company, 'company', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$street = \Froxlor\Validate\Validate::validate($street, 'street', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$zipcode = \Froxlor\Validate\Validate::validate($zipcode, 'zipcode', '/^[0-9 \-A-Z]*$/', '', array(), true);
$city = \Froxlor\Validate\Validate::validate($city, 'city', '', '', array(), true);
$city = \Froxlor\Validate\Validate::validate($city, 'city', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$phone = \Froxlor\Validate\Validate::validate($phone, 'phone', '/^[0-9\- \+\(\)\/]*$/', '', array(), true);
$fax = \Froxlor\Validate\Validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', array(), true);
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true));
@@ -1051,7 +1056,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
}
if ($this->isAdmin()) {
if ($createstdsubdomain != '1') {
if ($createstdsubdomain != '1' || $deactivated) {
$createstdsubdomain = '0';
}
@@ -1088,7 +1093,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'customerid' => $result['customerid']
), true, true);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically added standardsubdomain for user '" . $result['loginname'] . "'");
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
}
}
@@ -1102,11 +1107,11 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_ERR, "[API] Unable to delete standard-subdomain: " . $e->getMessage());
}
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically deleted standardsubdomain for user '" . $result['loginname'] . "'");
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
}
if ($phpenabled != $result['phpenabled'] || $perlenabled != $result['perlenabled'] || $email != $result['email']) {
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
}
// activate/deactivate customer services
@@ -1192,7 +1197,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
), true, true);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] " . ($deactivated ? 'deactivated' : 'reactivated') . " user '" . $result['loginname'] . "'");
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
}
// Disable or enable POP3 Login for customers Mail Accounts
@@ -1234,6 +1239,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'fax' => $fax,
'email' => $email,
'customerno' => $customernumber,
'nextcloud_quota' => $nextcloud_quota,
'diskspace' => $diskspace,
'traffic' => $traffic,
'subdomains' => $subdomains,
@@ -1276,6 +1282,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
`fax` = :fax,
`email` = :email,
`customernumber` = :customerno,
`nextcloud_quota` = :nextcloud_quota,
`diskspace` = :diskspace,
`traffic` = :traffic,
`subdomains` = :subdomains,
@@ -1304,7 +1311,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
if ($this->isAdmin()) {
// Using filesystem - quota, insert a task which cleans the filesystem - quota
\Froxlor\System\Cronjob::inserttask('10');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA);
$admin_update_query = "UPDATE `" . TABLE_PANEL_ADMINS . "` SET `customers_used` = `customers_used` ";
@@ -1512,9 +1519,9 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'did' => $row['id']
), true, true);
// remove domains DNS from powerDNS if used, #581
\Froxlor\System\Cronjob::inserttask('11', $row['domain']);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_PDNS, $row['domain']);
// remove domain from acme.sh / lets encrypt if used
\Froxlor\System\Cronjob::inserttask('12', $row['domain']);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $row['domain']);
}
// remove customer domains
$stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :id");
@@ -1643,18 +1650,18 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
}
// rebuild configs
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
// Using nameserver, insert a task which rebuilds the server config
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
if ($delete_userfiles == 1) {
// insert task to remove the customers files from the filesystem
\Froxlor\System\Cronjob::inserttask('6', $result['loginname']);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_CUSTOMER_FILES, $result['loginname']);
}
// Using filesystem - quota, insert a task which cleans the filesystem - quota
\Froxlor\System\Cronjob::inserttask('10');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted customer '" . $result['loginname'] . "'");
return $this->response(200, "successful", $result);

View File

@@ -123,7 +123,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
Database::pexecute($stmt, $params, true, true);
$id = Database::lastInsertId();
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added directory-option for '" . $userpath . "'");
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
$result = $this->apiCall('DirOptions.get', array(
'id' => $id
@@ -248,7 +248,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
}
if (($options_indexes != $result['options_indexes']) || ($error404path != $result['error404path']) || ($error403path != $result['error403path']) || ($error500path != $result['error500path']) || ($options_cgi != $result['options_cgi'])) {
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
$stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_HTACCESS . "`
SET `options_indexes` = :options_indexes,
@@ -413,7 +413,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
"id" => $id
), true, true);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted directory-option for '" . str_replace($customer_data['documentroot'], '/', $result['path']) . "'");
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
return $this->response(200, "successful", $result);
}

View File

@@ -106,7 +106,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
Database::pexecute($stmt, $params, true, true);
$id = Database::lastInsertId();
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added directory-protection for '" . $username . " (" . $path . ")'");
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
$result = $this->apiCall('DirProtections.get', array(
'id' => $id
@@ -251,7 +251,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
UPDATE `" . TABLE_PANEL_HTPASSWDS . "` SET " . $upd_query . " WHERE `id` = :id AND `customerid`= :cid
");
Database::pexecute($upd_stmt, $upd_params, true, true);
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
}
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] updated directory-protection '" . $result['username'] . " (" . $result['path'] . ")'");
@@ -385,7 +385,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
));
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted htpasswd for '" . $result['username'] . " (" . $result['path'] . ")'");
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
return $this->response(200, "successful", $result);
}
}

View File

@@ -336,7 +336,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$dom_entries[] = $new_entry;
// re-generate bind configs
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
$result = $this->apiCall('DomainZones.get', array(
'id' => $id
@@ -542,7 +542,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
), true, true);
if ($del_stmt->rowCount() > 0) {
// re-generate bind configs
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
return $this->response(200, "successful", true);
}
return $this->response(304, "successful", true);

View File

@@ -427,6 +427,20 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
}
$_documentroot = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . $path_suffix);
$documentroot = \Froxlor\Validate\Validate::validate($documentroot, 'documentroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
// If path is empty and 'Use domain name as default value for DocumentRoot path' is enabled in settings,
// set default path to subdomain or domain name
if (! empty($documentroot)) {
if (substr($documentroot, 0, 1) != '/' && ! preg_match('/^https?\:\/\//', $documentroot)) {
$documentroot = $_documentroot . '/' . $documentroot;
} elseif (substr($documentroot, 0, 1) == '/' && $this->getUserDetail('change_serversettings') != '1') {
\Froxlor\UI\Response::standard_error('pathmustberelative', '', true);
}
} else {
$documentroot = $_documentroot;
}
$registration_date = \Froxlor\Validate\Validate::validate($registration_date, 'registration_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', array(
'0000-00-00',
'0',
@@ -454,17 +468,6 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
}
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
\Froxlor\Validate\Validate::validate($documentroot, 'documentroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
// If path is empty and 'Use domain name as default value for DocumentRoot path' is enabled in settings,
// set default path to subdomain or domain name
if (! empty($documentroot)) {
if (substr($documentroot, 0, 1) != '/' && ! preg_match('/^https?\:\/\//', $documentroot)) {
$documentroot = $_documentroot . '/' . $documentroot;
}
} else {
$documentroot = $_documentroot;
}
$ssl_protocols = array();
if (! empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) {
@@ -507,7 +510,6 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$notryfiles = '0';
$writeaccesslog = '1';
$writeerrorlog = '1';
$documentroot = $_documentroot;
$override_tls = '0';
$ssl_protocols = array();
}
@@ -855,9 +857,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
\Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger());
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
// Using nameserver, insert a task which rebuilds the server config
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added domain '" . $domain . "'");
@@ -1187,22 +1189,12 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$serveraliasoption = $p_serveraliasoption;
}
if ($this->getUserDetail('change_serversettings') == '1') {
if (Settings::Get('system.bind_enable') == '1') {
$zonefile = \Froxlor\Validate\Validate::validate($zonefile, 'zonefile', '', '', array(), true);
} else {
$isbinddomain = $result['isbinddomain'];
$zonefile = $result['zonefile'];
}
if (Settings::Get('dkim.use_dkim') != '1') {
$dkim = $result['dkim'];
}
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$documentroot = \Froxlor\Validate\Validate::validate($documentroot, 'documentroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
if (! empty($documentroot) && $documentroot != $result['documentroot'] && substr($documentroot, 0, 1) == '/' && substr($documentroot, 0, strlen($customer['documentroot'])) != $customer['documentroot'] && $this->getUserDetail('change_serversettings') != '1') {
\Froxlor\UI\Response::standard_error('pathmustberelative', '', true);
}
// when moving customer and no path is specified, update would normally reuse the current document-root
// which would point to the wrong customer, therefore we will re-create that directory
if (! empty($documentroot) && $customerid > 0 && $customerid != $result['customerid'] && Settings::Get('panel.allow_domain_change_customer') == '1') {
@@ -1229,6 +1221,21 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
\Froxlor\UI\Response::standard_error('pathmaynotcontaincolon', '', true);
}
if ($this->getUserDetail('change_serversettings') == '1') {
if (Settings::Get('system.bind_enable') == '1') {
$zonefile = \Froxlor\Validate\Validate::validate($zonefile, 'zonefile', '', '', array(), true);
} else {
$isbinddomain = $result['isbinddomain'];
$zonefile = $result['zonefile'];
}
if (Settings::Get('dkim.use_dkim') != '1') {
$dkim = $result['dkim'];
}
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$ssl_protocols = array();
if (! empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) {
$p_ssl_protocols = array(
@@ -1267,7 +1274,6 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$notryfiles = $result['notryfiles'];
$writeaccesslog = $result['writeaccesslog'];
$writeerrorlog = $result['writeerrorlog'];
$documentroot = $result['documentroot'];
$ssl_protocols = $p_ssl_protocols;
$override_tls = $result['override_tls'];
}
@@ -1458,8 +1464,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$wwwserveralias = ($serveraliasoption == '1') ? '1' : '0';
$iswildcarddomain = ($serveraliasoption == '0') ? '1' : '0';
if ($documentroot != $result['documentroot'] || $ssl_redirect != $result['ssl_redirect'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $phpenabled != $result['phpenabled'] || $openbasedir != $result['openbasedir'] || $phpsettingid != $result['phpsettingid'] || $mod_fcgid_starter != $result['mod_fcgid_starter'] || $mod_fcgid_maxrequests != $result['mod_fcgid_maxrequests'] || $specialsettings != $result['specialsettings'] || $notryfiles != $result['notryfiles'] || $writeaccesslog != $result['writeaccesslog'] || $writeerrorlog != $result['writeerrorlog'] || $aliasdomain != $result['aliasdomain'] || $issubof != $result['ismainbutsubto'] || $email_only != $result['email_only'] || ($speciallogfile != $result['speciallogfile'] && $speciallogverified == '1') || $letsencrypt != $result['letsencrypt'] || $http2 != $result['http2'] || $hsts_maxage != $result['hsts'] || $hsts_sub != $result['hsts_sub'] || $hsts_preload != $result['hsts_preload'] || $ocsp_stapling != $result['ocsp_stapling']) {
\Froxlor\System\Cronjob::inserttask('1');
if ($documentroot != $result['documentroot'] || $ssl_redirect != $result['ssl_redirect'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $phpenabled != $result['phpenabled'] || $openbasedir != $result['openbasedir'] || $phpsettingid != $result['phpsettingid'] || $mod_fcgid_starter != $result['mod_fcgid_starter'] || $mod_fcgid_maxrequests != $result['mod_fcgid_maxrequests'] || $specialsettings != $result['specialsettings'] || $ssl_specialsettings != $result['ssl_specialsettings'] || $notryfiles != $result['notryfiles'] || $writeaccesslog != $result['writeaccesslog'] || $writeerrorlog != $result['writeerrorlog'] || $aliasdomain != $result['aliasdomain'] || $issubof != $result['ismainbutsubto'] || $email_only != $result['email_only'] || ($speciallogfile != $result['speciallogfile'] && $speciallogverified == '1') || $letsencrypt != $result['letsencrypt'] || $http2 != $result['http2'] || $hsts_maxage != $result['hsts'] || $hsts_sub != $result['hsts_sub'] || $hsts_preload != $result['hsts_preload'] || $ocsp_stapling != $result['ocsp_stapling']) {
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
}
if ($speciallogfile != $result['speciallogfile'] && $speciallogverified != '1') {
@@ -1467,11 +1473,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
}
if ($isbinddomain != $result['isbinddomain'] || $zonefile != $result['zonefile'] || $dkim != $result['dkim'] || $isemaildomain != $result['isemaildomain']) {
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
}
// check whether nameserver has been disabled, #581
if ($isbinddomain != $result['isbinddomain'] && $isbinddomain == 0) {
\Froxlor\System\Cronjob::inserttask('11', $result['domain']);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_PDNS, $result['domain']);
}
if ($isemaildomain == '0' && $result['isemaildomain'] == '1') {
@@ -1500,7 +1506,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
'id' => $id
), true, true);
// remove domain from acme.sh / lets encrypt if used
\Froxlor\System\Cronjob::inserttask('12', $result['domain']);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $result['domain']);
}
$updatechildren = '';
@@ -1978,16 +1984,16 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
\Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger());
// remove domains DNS from powerDNS if used, #581
\Froxlor\System\Cronjob::inserttask('11', $result['domain']);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_PDNS, $result['domain']);
// remove domain from acme.sh / lets encrypt if used
\Froxlor\System\Cronjob::inserttask('12', $result['domain']);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $result['domain']);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] deleted domain/subdomains (#" . $result['id'] . ")");
\Froxlor\User::updateCounters();
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
// Using nameserver, insert a task which rebuilds the server config
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
return $this->response(200, "successful", $result);
}
throw new \Exception("Not allowed to execute given command.", 403);

View File

@@ -197,6 +197,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
'NAME' => $customer['name'],
'FIRSTNAME' => $customer['firstname'],
'COMPANY' => $customer['company'],
'USERNAME' => $customer['loginname'],
'CUSTOMER_NO' => $customer['customernumber']
);
@@ -499,7 +500,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
}
if ($delete_userfiles) {
\Froxlor\System\Cronjob::inserttask('7', $customer['loginname'], $result['email_full']);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_EMAIL_DATA, $customer['loginname'], $result['email_full']);
}
// decrease usage for customer

View File

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

View File

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

View File

@@ -178,9 +178,9 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$custom_config = $this->getParam('custom_config', true, '');
// validation
$description = \Froxlor\Validate\Validate::validate($description, 'description', '', '', array(), true);
$description = \Froxlor\Validate\Validate::validate($description, 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$reload_cmd = \Froxlor\Validate\Validate::validate($reload_cmd, 'reload_cmd', '', '', array(), true);
$config_dir = \Froxlor\Validate\Validate::validate($config_dir, 'config_dir', '', '', array(), true);
$config_dir = \Froxlor\Validate\Validate::validate($config_dir, 'config_dir', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
if (! in_array($pmanager, array(
'static',
'dynamic',
@@ -229,7 +229,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
Database::pexecute($ins_stmt, $ins_data);
$id = Database::lastInsertId();
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] fpm-daemon with description '" . $description . "' has been created by '" . $this->getUserDetail('loginname') . "'");
$result = $this->apiCall('FpmDaemons.get', array(
'id' => $id
@@ -299,9 +299,9 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$custom_config = $this->getParam('custom_config', true, $result['custom_config']);
// validation
$description = \Froxlor\Validate\Validate::validate($description, 'description', '', '', array(), true);
$description = \Froxlor\Validate\Validate::validate($description, 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$reload_cmd = \Froxlor\Validate\Validate::validate($reload_cmd, 'reload_cmd', '', '', array(), true);
$config_dir = \Froxlor\Validate\Validate::validate($config_dir, 'config_dir', '', '', array(), true);
$config_dir = \Froxlor\Validate\Validate::validate($config_dir, 'config_dir', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
if (! in_array($pmanager, array(
'static',
'dynamic',
@@ -351,7 +351,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
);
Database::pexecute($upd_stmt, $upd_data, true, true);
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] fpm-daemon with description '" . $description . "' has been updated by '" . $this->getUserDetail('loginname') . "'");
$result = $this->apiCall('FpmDaemons.get', array(
'id' => $id
@@ -400,7 +400,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
'id' => $id
), true, true);
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] fpm-daemon setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'");
return $this->response(200, "successful", $result);
}

View File

@@ -123,12 +123,12 @@ class Froxlor extends \Froxlor\Api\ApiCommand
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "User " . $this->getUserDetail('loginname') . " imported settings");
try {
\Froxlor\SImExporter::import($json_str);
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask('10');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA);
// Using nameserver, insert a task which rebuilds the server config
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
// cron.d file
\Froxlor\System\Cronjob::inserttask('99');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_CRON);
return $this->response(200, "successful", true);
} catch (\Exception $e) {
throw new \Exception($e->getMessage(), 406);

View File

@@ -79,7 +79,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
// validation
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
$password = \Froxlor\System\Crypt::validatePassword($password, true);
$description = \Froxlor\Validate\Validate::validate(trim($description), 'description', '', '', array(), true);
$description = \Froxlor\Validate\Validate::validate(trim($description), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
if (Settings::Get('system.allow_customer_shell') == '1') {
$shell = \Froxlor\Validate\Validate::validate(trim($shell), 'shell', '', '', array(), true);
@@ -234,7 +234,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
}
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added ftp-account '" . $username . " (" . $path . ")'");
\Froxlor\System\Cronjob::inserttask(5);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_FTP);
if ($sendinfomail == 1) {
$replace_arr = array(
@@ -243,6 +243,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
'NAME' => $customer['name'],
'FIRSTNAME' => $customer['firstname'],
'COMPANY' => $customer['company'],
'USERNAME' => $customer['loginname'],
'CUSTOMER_NO' => $customer['customernumber'],
'USR_NAME' => $username,
'USR_PASS' => htmlentities(htmlentities($password)),
@@ -396,7 +397,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
// validation
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
$description = \Froxlor\Validate\Validate::validate(trim($description), 'description', '', '', array(), true);
$description = \Froxlor\Validate\Validate::validate(trim($description), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
if (Settings::Get('system.allow_customer_shell') == '1') {
$shell = \Froxlor\Validate\Validate::validate(trim($shell), 'shell', '', '', array(), true);
@@ -450,7 +451,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
}
// it's the task for "new ftp" but that will
// create all directories and correct their permissions
\Froxlor\System\Cronjob::inserttask(5);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_FTP);
$stmt = Database::prepare("
UPDATE `" . TABLE_FTP_USERS . "`
@@ -628,11 +629,11 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
// refs #293
if ($delete_userfiles == 1) {
\Froxlor\System\Cronjob::inserttask('8', $customer_data['loginname'], $result['homedir']);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_FTP_DATA, $customer_data['loginname'], $result['homedir']);
} else {
if (Settings::Get('system.nssextrausers') == 1) {
// this is used so that the libnss-extrausers cron is fired
\Froxlor\System\Cronjob::inserttask(5);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_FTP);
}
}

View File

@@ -216,7 +216,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
// validation
$name = \Froxlor\Validate\Validate::validate(trim($name), 'name', '', '', array(), true);
$description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $description), 'description', '/^[^\0]*$/');
$description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $description), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT);
if (Settings::Get('system.mail_quota_enabled') != '1') {
$value_arr['email_quota'] = - 1;
@@ -361,7 +361,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
// validation
$name = \Froxlor\Validate\Validate::validate(trim($name), 'name', '', '', array(), true);
$description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $description), 'description', '/^[^\0]*$/');
$description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $description), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT);
if (Settings::Get('system.mail_quota_enabled') != '1') {
$value_arr['email_quota'] = - 1;

View File

@@ -298,9 +298,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
Database::pexecute($ins_stmt, $ins_data);
$ins_data['id'] = Database::lastInsertId();
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
// Using nameserver, insert a task which rebuilds the server config
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
$ip = '[' . $ip . ']';
@@ -378,9 +378,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$listen_statement = $this->getBoolParam('listen_statement', true, $result['listen_statement']);
$namevirtualhost_statement = $this->getBoolParam('namevirtualhost_statement', true, $result['namevirtualhost_statement']);
$vhostcontainer = $this->getBoolParam('vhostcontainer', true, $result['vhostcontainer']);
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, $result['specialsettings'])), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, ($result['specialsettings'] ?? ""))), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$vhostcontainer_servername_statement = $this->getParam('vhostcontainer_servername_statement', true, $result['vhostcontainer_servername_statement']);
$default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, $result['default_vhostconf_domain'])), 'default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, ($result['default_vhostconf_domain'] ?? ""))), 'default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$docroot = \Froxlor\Validate\Validate::validate($this->getParam('docroot', true, $result['docroot']), 'docroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
if ((int) Settings::Get('system.use_ssl') == 1) {
@@ -389,9 +389,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$ssl_key_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_key_file', $ssl, $result['ssl_key_file']), 'ssl_key_file', '', '', array(), true);
$ssl_ca_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_ca_file', true, $result['ssl_ca_file']), 'ssl_ca_file', '', '', array(), true);
$ssl_cert_chainfile = \Froxlor\Validate\Validate::validate($this->getParam('ssl_cert_chainfile', true, $result['ssl_cert_chainfile']), 'ssl_cert_chainfile', '', '', array(), true);
$ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, $result['ssl_specialsettings'])), 'ssl_specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, ($result['ssl_specialsettings'] ?? ""))), 'ssl_specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$include_specialsettings = $this->getBoolParam('include_specialsettings', true, $result['include_specialsettings']);
$ssl_default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, $result['ssl_default_vhostconf_domain'])), 'ssl_default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$ssl_default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, ($result['ssl_default_vhostconf_domain'] ?? ""))), 'ssl_default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$include_default_vhostconf_domain = $this->getBoolParam('include_default_vhostconf_domain', true, $result['include_default_vhostconf_domain']);
} else {
$ssl = 0;
@@ -511,9 +511,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
);
Database::pexecute($upd_stmt, $upd_data);
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
// Using nameserver, insert a task which rebuilds the server config
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] changed IP/port from '" . $result['ip'] . ":" . $result['port'] . "' to '" . $ip . ":" . $port . "'");
@@ -584,9 +584,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
'id' => $id
), true, true);
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
// Using nameserver, insert a task which rebuilds the server config
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted IP/port '" . $result['ip'] . ":" . $result['port'] . "'");
return $this->response(200, "successful", $result);

View File

@@ -1,4 +1,5 @@
<?php
namespace Froxlor\Api\Commands;
use Froxlor\Database\Database;
@@ -46,6 +47,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*/
public function add()
{
if (($this->getUserDetail('mysqls_used') < $this->getUserDetail('mysqls') || $this->getUserDetail('mysqls') == '-1') || $this->isAdmin()) {
// required parameters
$password = $this->getParam('mysql_password');
@@ -60,7 +62,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// validation
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
$password = \Froxlor\System\Crypt::validatePassword($password, true);
$databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true);
$databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
if (!empty($databasename)) {
$databasename = \Froxlor\Validate\Validate::validate(trim($databasename), 'database_name', '/^[A-Za-z0-9][A-Za-z0-9\-_]+$/i', '', array(), true);
}
@@ -71,7 +73,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
if (! isset($sql_root) || ! is_array($sql_root)) {
if (!isset($sql_root) || !is_array($sql_root)) {
throw new \Exception("Database server with index #" . $dbserver . " is unknown", 404);
}
@@ -86,8 +88,8 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// create database, user, set permissions, etc.pp.
$dbm = new \Froxlor\Database\DbManager($this->logger());
if(strtoupper(Settings::Get('customer.mysqlprefix')) == 'DBNAME' && !empty($databasename)) {
$username = $dbm->createDatabase($newdb_params['loginname'].'_'.$databasename, $password);
if (strtoupper(Settings::Get('customer.mysqlprefix')) == 'DBNAME' && !empty($databasename)) {
$username = $dbm->createDatabase($newdb_params['loginname'] . '_' . $databasename, $password);
} else {
$username = $dbm->createDatabase($newdb_params['loginname'], $password, $newdb_params['mysql_lastaccountnumber']);
}
@@ -139,6 +141,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
'NAME' => $userinfo['name'],
'FIRSTNAME' => $userinfo['firstname'],
'COMPANY' => $userinfo['company'],
'USERNAME' => $userinfo['loginname'],
'CUSTOMER_NO' => $userinfo['customernumber'],
'DB_NAME' => $username,
'DB_PASS' => htmlentities(htmlentities($password)),
@@ -182,6 +185,8 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
));
return $this->response(200, "successful", $result);
}
throw new \Exception("No more resources available", 406);
}
/**
* return a mysql database entry by either id or dbname
@@ -202,7 +207,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$dbname = $this->getParam('dbname', $dn_optional, '');
$dbserver = $this->getParam('mysql_server', true, - 1);
$dbserver = $this->getParam('mysql_server', true, -1);
if ($this->isAdmin()) {
if ($this->getUserDetail('customers_see_all') != 1) {
@@ -302,7 +307,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$dbname = $this->getParam('dbname', $dn_optional, '');
$dbserver = $this->getParam('mysql_server', true, - 1);
$dbserver = $this->getParam('mysql_server', true, -1);
$customer = $this->getCustomerData();
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) {
@@ -322,7 +327,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// validation
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
$databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true);
$databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
if ($password != '') {
// validate password
@@ -389,7 +394,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
public function listing()
{
$result = array();
$dbserver = $this->getParam('mysql_server', true, - 1);
$dbserver = $this->getParam('mysql_server', true, -1);
$customer_ids = $this->getAllowedCustomerIds('mysql');
$query_fields = array();
$result_stmt = Database::prepare("
@@ -486,7 +491,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$dbname = $this->getParam('dbname', $dn_optional, '');
$dbserver = $this->getParam('mysql_server', true, - 1);
$dbserver = $this->getParam('mysql_server', true, -1);
$customer = $this->getCustomerData();
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) {

View File

@@ -99,7 +99,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
}
// check whether we use that config as froxor-vhost config
if (Settings::Get('system.mod_fcgid_defaultini_ownvhost') == $row['id'] || Settings::Get('phpfpm.vhost_defaultini') == $row['id']) {
if ((Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_defaultini_ownvhost') == $row['id']) || (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.vhost_defaultini') == $row['id'])) {
$domains[] = Settings::Get('system.hostname');
}
@@ -266,7 +266,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$allow_all_customers = $this->getBoolParam('allow_all_customers', true, 0);
// validation
$description = \Froxlor\Validate\Validate::validate($description, 'description', '', '', array(), true);
$description = \Froxlor\Validate\Validate::validate($description, 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$phpsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $phpsettings), 'phpsettings', '/^[^\0]*$/', '', array(), true);
if (Settings::Get('system.mod_fcgid') == 1) {
$binary = \Froxlor\FileDir::makeCorrectFile(\Froxlor\Validate\Validate::validate($binary, 'binary', '', '', array(), true));
@@ -364,7 +364,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
Database::pexecute($ins_stmt, $ins_data, true, true);
$ins_data['id'] = Database::lastInsertId();
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] php setting with description '" . $description . "' has been created by '" . $this->getUserDetail('loginname') . "'");
$result = $this->apiCall('PhpSettings.get', array(
@@ -466,7 +466,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$allow_all_customers = $this->getBoolParam('allow_all_customers', true, 0);
// validation
$description = \Froxlor\Validate\Validate::validate($description, 'description', '', '', array(), true);
$description = \Froxlor\Validate\Validate::validate($description, 'description', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$phpsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $phpsettings), 'phpsettings', '/^[^\0]*$/', '', array(), true);
if (Settings::Get('system.mod_fcgid') == 1) {
$binary = \Froxlor\FileDir::makeCorrectFile(\Froxlor\Validate\Validate::validate($binary, 'binary', '', '', array(), true));
@@ -565,7 +565,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
);
Database::pexecute($upd_stmt, $upd_data, true, true);
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] php setting with description '" . $description . "' has been updated by '" . $this->getUserDetail('loginname') . "'");
$result = $this->apiCall('PhpSettings.get', array(
@@ -622,7 +622,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
'id' => $id
), true, true);
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] php setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'");
return $this->response(200, "successful", $result);
}

View File

@@ -268,9 +268,12 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
} else {
$allowed_phpconfigs = [];
}
// 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 (! in_array($phpsid_result['phpsettingid'], $allowed_phpconfigs)) {
\Froxlor\UI\Response::standard_error('notallowedphpconfigused', '', true);
}
}
// actually insert domain
$stmt = Database::prepare("
@@ -356,9 +359,9 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
\Froxlor\Domain\Domain::addRedirectToDomain($subdomain_id, $redirectcode);
}
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
// Using nameserver, insert a task which rebuilds the server config
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
Customers::increaseUsage($customer['customerid'], 'subdomains_used');
@@ -654,9 +657,12 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
} else {
$allowed_phpconfigs = [];
}
// 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 (! in_array($phpsettingid, $allowed_phpconfigs)) {
\Froxlor\UI\Response::standard_error('notallowedphpconfigused', '', true);
}
}
// handle redirect
if ($_doredirect) {
@@ -727,11 +733,11 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
'id' => $id
), true, true);
// remove domain from acme.sh / lets encrypt if used
\Froxlor\System\Cronjob::inserttask('12', $result['domain']);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $result['domain']);
}
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] edited domain '" . $idna_convert->decode($result['domain']) . "'");
}
@@ -1013,13 +1019,13 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
'domainid' => $id
), true, true);
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
// Using nameserver, insert a task which rebuilds the server config
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
// remove domains DNS from powerDNS if used, #581
\Froxlor\System\Cronjob::inserttask('11', $result['domain']);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_PDNS, $result['domain']);
// remove domain from acme.sh / lets encrypt if used
\Froxlor\System\Cronjob::inserttask('12', $result['domain']);
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $result['domain']);
// reduce subdomain-usage-counter
Customers::decreaseUsage($customer['customerid'], 'subdomains_used');

View File

View File

View File

View File

@@ -85,8 +85,8 @@ class ConfigServicesAction extends \Froxlor\Cli\Action
$distributions_select_data = array();
//set default os.
$os_dist = array('ID' => 'buster');
$os_version = array('0' => '10');
$os_dist = array('ID' => 'bullseye');
$os_version = array('0' => '11');
$os_default = $os_dist['ID'];
//read os-release

View File

@@ -0,0 +1,99 @@
<?php
namespace Froxlor\Cli\Action;
use Froxlor\Database\Database;
use Froxlor\Settings;
class PhpSessioncleanAction extends \Froxlor\Cli\Action
{
public function __construct($args)
{
parent::__construct($args);
}
public function run()
{
$this->validate();
if ((int) Settings::Get('phpfpm.enabled') == 1) {
if (isset($this->_args["max-lifetime"]) && is_numeric($this->_args["max-lifetime"]) && $this->_args["max-lifetime"] > 0) {
$this->cleanSessionfiles((int)$this->_args["max-lifetime"]);
} else {
// use default max-lifetime value
$this->cleanSessionfiles();
}
}
}
/**
* validates the parsed command line parameters
*
* @throws \Exception
*/
private function validate()
{
global $lng;
$this->checkConfigParam(true);
$this->parseConfig();
require FROXLOR_INSTALL_DIR . '/lib/tables.inc.php';
}
private function cleanSessionfiles(int $maxlifetime = 1440)
{
// store paths to clean up
$paths_to_clean = [];
// get all pool-config directories configured
$sel_stmt = Database::prepare("SELECT DISTINCT `config_dir` FROM `" . TABLE_PANEL_FPMDAEMONS . "`");
Database::pexecute($sel_stmt);
while ($fpmd = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
$poolfiles = glob(\Froxlor\FileDir::makeCorrectFile($fpmd['config_dir'] . '/*.conf'));
foreach ($poolfiles as $cf) {
$contents = file_get_contents($cf);
$pattern = preg_quote('session.save_path', '/');
$pattern = "/" . $pattern . ".+?\=(.*)/";
if (preg_match_all($pattern, $contents, $matches)) {
$paths_to_clean[] = \Froxlor\FileDir::makeCorrectDir(trim($matches[1][0]));
}
}
}
// every path is just needed once
$paths_to_clean = array_unique($paths_to_clean);
if (count($paths_to_clean) > 0) {
foreach ($paths_to_clean as $ptc) {
// find all files older then maxlifetime and delete them
\Froxlor\FileDir::safe_exec("find -O3 \"" . $ptc . "\" -ignore_readdir_race -depth -mindepth 1 -name 'sess_*' -type f -cmin \"+" . $maxlifetime . "\" -delete");
}
}
}
private function parseConfig()
{
define('FROXLOR_INSTALL_DIR', $this->_args['froxlor-dir']);
if (!class_exists('\\Froxlor\\Database\\Database')) {
throw new \Exception("Could not find froxlor's Database class. Is froxlor really installed to '" . FROXLOR_INSTALL_DIR . "'?");
}
if (!file_exists(FROXLOR_INSTALL_DIR . '/lib/userdata.inc.php')) {
throw new \Exception("Could not find froxlor's userdata.inc.php file. You should use this script only with a fully installed and setup froxlor system.");
}
}
private function checkConfigParam($needed = false)
{
if ($needed) {
if (!isset($this->_args["froxlor-dir"])) {
$this->_args["froxlor-dir"] = \Froxlor\Froxlor::getInstallDir();
} elseif (!is_dir($this->_args["froxlor-dir"])) {
throw new \Exception("Given --froxlor-dir parameter is not a directory");
} elseif (!file_exists($this->_args["froxlor-dir"])) {
throw new \Exception("Given froxlor directory cannot be found ('" . $this->_args["froxlor-dir"] . "')");
} elseif (!is_readable($this->_args["froxlor-dir"])) {
throw new \Exception("Given froxlor directory cannot be read ('" . $this->_args["froxlor-dir"] . "')");
}
}
}
}

View File

View File

@@ -0,0 +1,64 @@
<?php
namespace Froxlor\Cli;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2022 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2018-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
*/
class PhpSessioncleanCmd extends CmdLineHandler
{
/**
* list of valid switches
*
* @var array
*/
public static $switches = array(
'h'
);
/**
* list of valid parameters
*
* @var array
*/
public static $params = array(
'froxlor-dir',
'max-lifetime',
'help'
);
public static $action_class = '\\Froxlor\\Cli\\Action\\PhpSessioncleanAction';
public static function printHelp()
{
self::println("");
self::println("Help / command line parameters:");
self::println("");
// commands
self::println("--froxlor-dir\t\tpath to froxlor installation");
self::println("\t\t\tExample: --froxlor-dir=/var/www/froxlor/");
self::println("");
self::println("--max-lifetime\t\tThe number of seconds after which data will be seen as 'garbage' and potentially cleaned up. Defaults to '1440'");
self::println("\t\t\tExample: --max-lifetime=2000");
self::println("");
self::println("--help\t\t\tshow help screen (this)");
self::println("");
// switches
self::println("-h\t\t\tsame as --help");
self::println("");
die(); // end of execution
}
}

View File

View File

@@ -182,7 +182,7 @@ class ConfigParser
}
/**
* Parse the XML and populate $this->services
* Parse the XML and populate $this->defaults
*
* @return bool
*/
@@ -194,9 +194,9 @@ class ConfigParser
}
// Get all defaults
$defaults = $this->xml->xpath('//defaults');
$defaults = $this->xml->xpath('//defaults/default');
foreach ($defaults as $default) {
$this->defaults = $default;
$this->defaults[] = $default;
}
// Switch flag to indicate we parsed our data

View File

View File

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

View File

View File

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

View File

@@ -56,7 +56,9 @@ class ApacheFcgi extends Apache
// start block, cut off last pipe and close block
$filesmatch = '(' . str_replace(".", "\.", substr($filesmatch, 0, - 1)) . ')';
$php_options_text .= ' <FilesMatch \.' . $filesmatch . '$>' . "\n";
$php_options_text .= ' <If "-f %{SCRIPT_FILENAME}">' . "\n";
$php_options_text .= ' SetHandler proxy:unix:' . $domain['fpm_socket'] . '|fcgi://localhost' . "\n";
$php_options_text .= ' </If>' . "\n";
$php_options_text .= ' </FilesMatch>' . "\n";
$mypath_dir = new \Froxlor\Http\Directory($domain['documentroot']);

View File

@@ -310,7 +310,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
{
if (! empty($domains)) {
$acmesh_cmd = self::$acmesh . " --server " . self::$apiserver . " --issue -d " . implode(" -d ", $domains);
$acmesh_cmd = self::getAcmeSh() . " --server " . self::$apiserver . " --issue -d " . implode(" -d ", $domains);
// challenge path
$acmesh_cmd .= " -w " . Settings::Get('system.letsencryptchallengepath');
if (Settings::Get('system.leecc') > 0) {
@@ -530,7 +530,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
if (Settings::Get('system.leecc') > 0 && ! $forced_noecc) {
$domain .= "_ecc";
}
$env_file = FileDir::makeCorrectFile(dirname(self::$acmesh) . '/acme.sh.env');
$env_file = FileDir::makeCorrectFile(dirname(self::getAcmeSh()) . '/acme.sh.env');
if (file_exists($env_file)) {
$output = [];
$cut = <<<EOC
@@ -541,11 +541,15 @@ EOC;
return FileDir::makeCorrectDir($output[0] . "/" . $domain);
}
}
return FileDir::makeCorrectDir(dirname(self::$acmesh) . "/" . $domain);
return FileDir::makeCorrectDir(dirname(self::getAcmeSh()) . "/" . $domain);
}
public static function getAcmeSh()
{
$from_settings = Settings::Get('system.acmeshpath');
if (file_exists($from_settings)) {
return $from_settings;
}
return self::$acmesh;
}
@@ -599,16 +603,24 @@ EOC;
*/
private static function checkInstall($tries = 0)
{
if (! file_exists(self::$acmesh) && $tries > 0) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Download/installation of acme.sh seems to have failed. Re-run cronjob to try again or install manually to '" . self::$acmesh . "'");
echo PHP_EOL . "Download/installation of acme.sh seems to have failed. Re-run cronjob to try again or install manually to '" . self::$acmesh . "'" . PHP_EOL;
if (! file_exists(self::getAcmeSh()) && $tries > 0) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Download/installation of acme.sh seems to have failed. Re-run cronjob to try again or install manually to '" . self::getAcmeSh() . "'");
echo PHP_EOL . "Download/installation of acme.sh seems to have failed. Re-run cronjob to try again or install manually to '" . self::getAcmeSh() . "'" . PHP_EOL;
return false;
} else if (! file_exists(self::$acmesh)) {
} else if (! file_exists(self::getAcmeSh())) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Could not find acme.sh - installing it to /root/.acme.sh/");
$return = false;
\Froxlor\FileDir::safe_exec("wget -O - https://get.acme.sh | sh", $return, array(
\Froxlor\FileDir::safe_exec("wget -O - https://get.acme.sh | sh -s email=" . Settings::Get('panel.adminmail'), $return, array(
'|'
));
$set_path = self::getAcmeSh();
// after this, regardless of what the user specified, the acme.sh installation will be in /root/.acme.sh
if ($set_path != '/root/.acme.sh/acme.sh') {
Settings::Set('system.acmeshpath', '/root/.acme.sh/acme.sh', true);
// let the user know
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Acme.sh could not be found in '" . $set_path . "' so froxlor installed it to the default location, which is '/root/.acme.sh/'");
echo PHP_EOL . "Acme.sh could not be found in '" . $set_path . "' so froxlor installed it to the default location, which is '/root/.acme.sh/'" . PHP_EOL;
}
// check whether the installation worked
return self::checkInstall(++ $tries);
}
@@ -620,9 +632,12 @@ EOC;
*/
private static function checkUpgrade()
{
$acmesh_result = \Froxlor\FileDir::safe_exec(self::$acmesh . " --upgrade --auto-upgrade 0");
$acmesh_result = \Froxlor\FileDir::safe_exec(self::getAcmeSh() . " --upgrade --auto-upgrade 0");
// check for activated cron
$acmesh_result2 = \Froxlor\FileDir::safe_exec(self::$acmesh . " --install-cronjob");
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Checking for LetsEncrypt client upgrades before renewing certificates:\n" . implode("\n", $acmesh_result) . "\n" . implode("\n", $acmesh_result2));
$acmesh_result2 = \Froxlor\FileDir::safe_exec(self::getAcmeSh() . " --install-cronjob");
// set default CA
$acmesh_result3 = \Froxlor\FileDir::safe_exec(self::getAcmeSh() . " --set-default-ca --server " . self::$apiserver);
// log messages
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Checking for LetsEncrypt client upgrades before renewing certificates:\n" . implode("\n", $acmesh_result) . "\n" . implode("\n", $acmesh_result2) . "\n" . implode("\n", $acmesh_result3));
}
}

View File

@@ -251,7 +251,7 @@ class Lighttpd extends HttpConfigBase
// check for existence, #1485
if (! file_exists($domain['ssl_ca_file'])) {
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, $ip . ':' . $port . ' :: certificate CA file "' . $domain['ssl_ca_file'] . '" does not exist! Cannot create ssl-directives');
echo $ip . ':' . port . ' :: certificate CA file "' . $domain['ssl_ca_file'] . '" does not exist! SSL-directives might not be working' . "\n";
echo $ip . ':' . $port . ' :: certificate CA file "' . $domain['ssl_ca_file'] . '" does not exist! SSL-directives might not be working' . "\n";
} else {
$this->lighttpd_data[$vhost_filename] .= 'ssl.ca-file = "' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_ca_file']) . '"' . "\n";
}
@@ -760,6 +760,7 @@ class Lighttpd extends HttpConfigBase
'customerid' => $domain['customerid']
));
$diroption_text = '';
while ($row_htpasswds = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
if ($this->auth_backend_loaded[$domain['ipandport']] != 'yes' && $this->auth_backend_loaded[$domain['ssl_ipandport']] != 'yes') {
$filename = $domain['customerid'] . '.htpasswd';
@@ -836,6 +837,7 @@ class Lighttpd extends HttpConfigBase
}
}
$servernames_text = '';
for ($i = 0; $i < sizeof($server_string); $i ++) {
$data = $server_string[$i];

View File

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

View File

View File

View File

@@ -24,6 +24,13 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
private static $debugHandler = null;
private static $noncron_params = [
'force',
'debug',
'no-fork',
'run-task'
];
public static function setArguments($argv = null)
{
self::$argv = $argv;
@@ -47,6 +54,7 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
echo "--run-task\t\trun a specific task [1 = re-generate configs, 4 = re-generate dns zones, 10 = re-set quotas, 99 = re-create cron.d-file]\n";
echo "--debug\t\t\toutput debug information about what is going on to STDOUT.\n";
echo "--no-fork\t\tdo not fork to backkground (traffic cron only).\n\n";
exit();
}
/**
@@ -63,13 +71,13 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
if (strtolower($argv[$x]) == '--force') {
// really force re-generating of config-files by
// inserting task 1
\Froxlor\System\Cronjob::inserttask('1');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_VHOST);
// bind (if enabled, \Froxlor\System\Cronjob::inserttask() checks this)
\Froxlor\System\Cronjob::inserttask('4');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
// set quotas (if enabled)
\Froxlor\System\Cronjob::inserttask('10');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::CREATE_QUOTA);
// also regenerate cron.d-file
\Froxlor\System\Cronjob::inserttask('99');
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_CRON);
array_push($jobs_to_run, 'tasks');
define('CRON_IS_FORCED', 1);
} elseif (strtolower($argv[$x]) == '--debug') {
@@ -161,7 +169,7 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
$crontype = "";
if (isset(self::$argv) && is_array(self::$argv) && count(self::$argv) > 1) {
for ($x = 1; $x < count(self::$argv); $x ++) {
if (substr(strtolower(self::$argv[$x]), 0, 2) == '--' && strlen(self::$argv[$x]) > 3) {
if (substr(self::$argv[$x], 0, 2) == '--' && strlen(self::$argv[$x]) > 3 && !in_array(substr(strtolower(self::$argv[$x]), 2),self::$noncron_params)) {
$crontype = substr(strtolower(self::$argv[$x]), 2);
$basename .= "-" . $crontype;
break;

View File

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

View File

@@ -4,6 +4,8 @@ namespace Froxlor\Cron\System;
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Cron\TaskId;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2003-2009 the SysCP Team (see authors).
@@ -45,55 +47,55 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
$row['data'] = json_decode($row['data'], true);
}
if ($row['type'] == '1') {
if ($row['type'] == TaskId::REBUILD_VHOST) {
/**
* TYPE=1 MEANS TO REBUILD APACHE VHOSTS.CONF
*/
self::rebuildWebserverConfigs();
} elseif ($row['type'] == '2') {
} elseif ($row['type'] == TaskId::CREATE_HOME) {
/**
* TYPE=2 MEANS TO CREATE A NEW HOME AND CHOWN
*/
self::createNewHome($row);
} elseif ($row['type'] == '4' && (int) Settings::Get('system.bind_enable') != 0) {
} elseif ($row['type'] == TaskId::REBUILD_DNS && (int) Settings::Get('system.bind_enable') != 0) {
/**
* TYPE=4 MEANS THAT SOMETHING IN THE BIND CONFIG HAS CHANGED.
* REBUILD froxlor_bind.conf IF BIND IS ENABLED
*/
self::rebuildDnsConfigs();
} elseif ($row['type'] == '5') {
} elseif ($row['type'] == TaskId::CREATE_FTP) {
/**
* TYPE=5 MEANS THAT A NEW FTP-ACCOUNT HAS BEEN CREATED, CREATE THE DIRECTORY
*/
self::createNewFtpHome($row);
} elseif ($row['type'] == '6') {
} elseif ($row['type'] == TaskId::DELETE_CUSTOMER_FILES) {
/**
* TYPE=6 MEANS THAT A CUSTOMER HAS BEEN DELETED AND THAT WE HAVE TO REMOVE ITS FILES
*/
self::deleteCustomerData($row);
} elseif ($row['type'] == '7') {
} elseif ($row['type'] == TaskId::DELETE_EMAIL_DATA) {
/**
* TYPE=7 Customer deleted an email account and wants the data to be deleted on the filesystem
*/
self::deleteEmailData($row);
} elseif ($row['type'] == '8') {
} elseif ($row['type'] == TaskId::DELETE_FTP_DATA) {
/**
* TYPE=8 Customer deleted a ftp account and wants the homedir to be deleted on the filesystem
* refs #293
*/
self::deleteFtpData($row);
} elseif ($row['type'] == '10' && (int) Settings::Get('system.diskquota_enabled') != 0) {
} elseif ($row['type'] == TaskId::CREATE_QUOTA && (int) Settings::Get('system.diskquota_enabled') != 0) {
/**
* TYPE=10 Set the filesystem - quota
*/
self::setFilesystemQuota();
} elseif ($row['type'] == '11' && Settings::Get('system.dns_server') == 'PowerDNS') {
} elseif ($row['type'] == TaskId::DELETE_DOMAIN_PDNS && Settings::Get('system.dns_server') == 'PowerDNS') {
/**
* TYPE=11 domain has been deleted, remove from pdns database if used
*/
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Removing PowerDNS entries for domain " . $row['data']['domain']);
\Froxlor\Dns\PowerDNS::cleanDomainZone($row['data']['domain']);
} elseif ($row['type'] == '12') {
} elseif ($row['type'] == TaskId::DELETE_DOMAIN_SSL) {
/**
* TYPE=12 domain has been deleted, remove from acme.sh/let's encrypt directory if used
*/
@@ -322,8 +324,8 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
if (file_exists($logsdir) && $logsdir != '/' && $logsdir != \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.logfiles_directory')) && substr($logsdir, 0, strlen(Settings::Get('system.logfiles_directory'))) == Settings::Get('system.logfiles_directory')) {
// build up wildcard for webX-{access,error}.log{*}
$logfiles .= '-*';
\Froxlor\FileDir::safe_exec('rm -f ' . escapeshellarg($logfiles));
$logsdir .= '-*';
\Froxlor\FileDir::safe_exec('rm -f ' . escapeshellarg($logsdir));
}
}
}

View File

105
lib/Froxlor/Cron/TaskId.php Normal file
View File

@@ -0,0 +1,105 @@
<?php
namespace Froxlor\Cron;
class TaskId {
/**
* TYPE=1 MEANS TO REBUILD APACHE VHOSTS.CONF
*/
const REBUILD_VHOST = 1;
/**
* TYPE=2 MEANS TO CREATE A NEW HOME AND CHOWN
*/
const CREATE_HOME = 2;
/**
* TYPE=4 MEANS THAT SOMETHING IN THE DNS CONFIG HAS CHANGED.
* REBUILD froxlor_bind.conf IF BIND IS ENABLED, UPDATE DKIM KEYS
*/
const REBUILD_DNS = 4;
/**
* TYPE=5 MEANS THAT A NEW FTP-ACCOUNT HAS BEEN CREATED, CREATE THE DIRECTORY
*/
const CREATE_FTP = 5;
/**
* TYPE=6 MEANS THAT A CUSTOMER HAS BEEN DELETED AND THAT WE HAVE TO REMOVE ITS FILES
*/
const DELETE_CUSTOMER_FILES = 6;
/**
* TYPE=7 Customer deleted an email account and wants the data to be deleted on the filesystem
*/
const DELETE_EMAIL_DATA = 7;
/**
* TYPE=8 Customer deleted a ftp account and wants the homedir to be deleted on the filesystem
* refs #293
*/
const DELETE_FTP_DATA = 8;
/**
* TYPE=10 Set the filesystem - quota
*/
const CREATE_QUOTA = 10;
/**
* TYPE=11 domain has been deleted, remove from pdns database if used
*/
const DELETE_DOMAIN_PDNS = 11;
/**
* TYPE=12 domain has been deleted, remove from acme.sh/let's encrypt directory if used
*/
const DELETE_DOMAIN_SSL = 12;
/**
* TYPE=20 COSTUMERBACKUP
*/
const CREATE_CUSTOMER_BACKUP = 20;
/**
* TYPE=99 REGENERATE CRON
*/
const REBUILD_CRON = 99;
/**
* Return if a cron task id is valid
* @param int|string $id cron task id (legacy string support)
* @return boolean
*/
public static function isValid($id) {
static $reflContants;
if (!is_numeric($id)) {
return false;
}
$numericid = (int)$id;
if (!is_array($reflContants)) {
$reflClass = new \ReflectionClass(get_called_class());
$reflContants = $reflClass->getConstants();
}
return in_array($numericid, $reflContants, true);
}
/**
* Get constant name by id
* @param int|string $id cron task id (legacy string support)
* @return string|false constant name or false if not found
*/
public static function convertToConstant($id) {
static $reflContants;
if (!is_numeric($id)) {
return false;
}
$numericid = (int)$id;
if (!is_array($reflContants)) {
$reflClass = new \ReflectionClass(get_called_class());
$reflContants = $reflClass->getConstants();
}
return array_search($numericid, $reflContants, true);
}
}

View File

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

View File

View File

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