Compare commits

...

177 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
Michael Kaufmann
46df429909 set version to 0.10.30 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-05 09:27:58 +01:00
Michael Kaufmann
eb841da007 avoid possible DivisionByZeroError in APCu info page, fixes #995
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-04 07:44:03 +01:00
Michael Kaufmann
c4a2db03be enable bind for testing-scenarios explicitly
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-03 14:16:21 +01:00
Michael Kaufmann
e5838f00cf add quota-plugin parameters to dovecot-config-templates; update standardcustomer index.html; set nameserver disabled by default
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-03 14:08:57 +01:00
Michael Kaufmann
bcde7e93df check whether the domain to clean from pdns actually still exists there; fixes #992
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-21 12:00:36 +02:00
Michael Kaufmann
bd8327afbe soften/correct permissions on pdns configs; fixes #991
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-21 11:56:34 +02:00
Michael Kaufmann
b961eba382 fix api documentation for Domains.add() and Domains.update(); fixes #987
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-20 16:51:16 +02:00
Michael Kaufmann
a552ea878e avoid undefined index of 'wwwserveralias' field if issueing/renewing lets encrypt certificate for froxlor-hostname
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-17 11:48:40 +02:00
Michael Kaufmann
4ad2a1da1c add complete list of nameserver-ips and given axfr-servers to allow-axfr-ips list for PowerDNS; fixes #985
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-14 19:07:05 +02:00
Michael Kaufmann
37ae69f07a correct language strings in phpconfig formfield for new setting; refs #980
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-14 17:13:55 +02:00
Michael Kaufmann
9870db2560 add possibility to assign new/edited php-config to all customer accounts; fixes #980
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-14 17:09:29 +02:00
Michael Kaufmann
724a5e172a don't remove 0-value parameter values from bulk-actions
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-12 16:29:04 +02:00
Michael Kaufmann
8e166cb842 adjust debian 11 config templates, fixes #982
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-12 14:25:42 +02:00
Michael Kaufmann
5e281cf486 fix allowed-phpconfigs check in SubDomains.add() and SubDomains.update()
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-11 19:26:13 +02:00
Michael Kaufmann
5d2f44ecd8 only validate custom database name if used at all
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-11 18:59:26 +02:00
Michael Kaufmann
5009c625d8 prep.statement cannot be used for create database query; regex-validate database_name
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-11 18:55:15 +02:00
Michael Kaufmann
eb592340b0 use prepared statement for creating databases to avoid sql injections in custom db-names
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-11 18:33:48 +02: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
532 changed files with 11500 additions and 1312 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

@@ -67,6 +67,9 @@ if ($page == 'showinfo') {
$uptime_duration = duration($cache['start_time']);
$size_vars = bsize($cache['mem_size']);
$num_hits_and_misses = $cache['num_hits'] + $cache['num_misses'];
$num_hits_and_misses = 0 >= $num_hits_and_misses ? 1 : $num_hits_and_misses;
// check for possible empty values that are used in the templates
if (! isset($cache['file_upload_progress'])) {
$cache['file_upload_progress'] = $lng['logger']['unknown'];
@@ -84,8 +87,8 @@ if ($page == 'showinfo') {
$freemem = bsize($mem_avail) . sprintf(" (%.1f%%)", $mem_avail * 100 / $mem_size);
$usedmem = bsize($mem_used) . sprintf(" (%.1f%%)", $mem_used * 100 / $mem_size);
$hits = $cache['num_hits'] . @sprintf(" (%.1f%%)", $cache['num_hits'] * 100 / ($cache['num_hits'] + $cache['num_misses']));
$misses = $cache['num_misses'] . @sprintf(" (%.1f%%)", $cache['num_misses'] * 100 / ($cache['num_hits'] + $cache['num_misses']));
$hits = $cache['num_hits'] . @sprintf(" (%.1f%%)", $cache['num_hits'] * 100 / $num_hits_and_misses);
$misses = $cache['num_misses'] . @sprintf(" (%.1f%%)", $cache['num_misses'] * 100 / $num_hits_and_misses);
// Fragmentation: (freeseg - 1) / total_seg
$nseg = $freeseg = $fragsize = $freetotal = 0;

View File

@@ -38,13 +38,43 @@ if ($userinfo['change_serversettings'] == '1') {
// try to convert namserver hosts to ip's
$ns_ips = "";
$known_ns_ips = [];
if (Settings::Get('system.nameservers') != '') {
$nameservers = explode(',', Settings::Get('system.nameservers'));
foreach ($nameservers as $nameserver) {
$nameserver = trim($nameserver);
// DNS servers might be multi homed; allow transfer from all ip
// addresses of the DNS server
$nameserver_ips = \Froxlor\PhpHelper::gethostbynamel6($nameserver);
if (is_array($nameserver_ips) && count($nameserver_ips) > 0) {
$ns_ips .= implode(",", $nameserver_ips);
// append dot to hostname
if (substr($nameserver, - 1, 1) != '.') {
$nameserver .= '.';
}
// ignore invalid responses
if (! is_array($nameserver_ips)) {
// act like \Froxlor\PhpHelper::gethostbynamel6() and return unmodified hostname on error
$nameserver_ips = array(
$nameserver
);
} else {
$known_ns_ips = array_merge($known_ns_ips, $nameserver_ips);
}
if (!empty($ns_ips)) {
$ns_ips .= ',';
}
$ns_ips .= implode(",", $nameserver_ips);
}
}
// AXFR server
if (Settings::Get('system.axfrservers') != '') {
$axfrservers = explode(',', Settings::Get('system.axfrservers'));
foreach ($axfrservers as $axfrserver) {
if (!in_array(trim($axfrserver), $known_ns_ips)) {
if (!empty($ns_ips)) {
$ns_ips .= ',';
}
$ns_ips .= trim($axfrserver);
}
}
}
@@ -59,7 +89,6 @@ if ($userinfo['change_serversettings'] == '1') {
'<SERVERIP>' => Settings::Get('system.ipaddress'),
'<NAMESERVERS>' => Settings::Get('system.nameservers'),
'<NAMESERVERS_IP>' => $ns_ips,
'<AXFRSERVERS>' => Settings::Get('system.axfrservers'),
'<VIRTUAL_MAILBOX_BASE>' => Settings::Get('system.vmail_homedir'),
'<VIRTUAL_UID_MAPS>' => Settings::Get('system.vmail_uid'),
'<VIRTUAL_GID_MAPS>' => Settings::Get('system.vmail_gid'),

View File

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

View File

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

View File

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

View File

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

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

0
doc/index.html Normal file
View File

279
index.php
View File

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

View File

@@ -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'),
@@ -532,7 +532,7 @@ opcache.interned_strings_buffer'),
('system', 'vmail_gid', '2000'),
('system', 'vmail_homedir', '/var/customers/mail/'),
('system', 'vmail_maildirname', 'Maildir'),
('system', 'bind_enable', '1'),
('system', 'bind_enable', '0'),
('system', 'bindconf_directory', '/etc/bind/'),
('system', 'bindreload_command', '/etc/init.d/bind9 reload'),
('system', 'hostname', 'SERVERNAME'),
@@ -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.29.1'),
('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
@@ -835,6 +860,8 @@ class FroxlorInstall
$content .= $this->_status_message('red', $this->_lng['install']['db_exists']);
$this->_abort = true;
}
} else {
$content .= $content .= $this->_status_message('green', 'OK');
}
return $content;

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");
}
}
@@ -943,3 +943,81 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.29')) {
showUpdateStep("Updating from 0.10.29 to 0.10.29.1", false);
\Froxlor\Froxlor::updateToVersion('0.10.29.1');
}
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

@@ -239,7 +239,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional, whether to create an exclusive web-logfile for this domain, default 0 (false)
* @param int $alias
* optional, domain-id of a domain that the new domain should be an alias of, default 0 (none)
* @param bool $issubof
* @param int $issubof
* optional, domain-id of a domain this domain is a subdomain of (required for webserver-cronjob to generate the correct order), default 0 (none)
* @param string $registration_date
* optional, date of domain registration in form of YYYY-MM-DD, default empty (none)
@@ -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 . "'");
@@ -901,7 +903,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional, when setting $speciallogfile to false, this needs to be set to true to confirm the action, default 0 (false)
* @param int $alias
* optional, domain-id of a domain that the new domain should be an alias of, default 0 (none)
* @param bool $issubof
* @param int $issubof
* optional, domain-id of a domain this domain is a subdomain of (required for webserver-cronjob to generate the correct order), default 0 (none)
* @param string $registration_date
* optional, date of domain registration in form of YYYY-MM-DD, default empty (none)
@@ -1187,6 +1189,38 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$serveraliasoption = $p_serveraliasoption;
}
$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') {
if (Settings::Get('system.documentroot_use_default_value') == 1) {
$_documentroot = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $result['domain']);
} else {
$_documentroot = $customer['documentroot'];
}
// set the customers default docroot
$documentroot = $_documentroot;
}
if ($documentroot == '') {
// 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 (Settings::Get('system.documentroot_use_default_value') == 1) {
$documentroot = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $result['domain']);
} else {
$documentroot = $customer['documentroot'];
}
}
if (! preg_match('/^https?\:\/\//', $documentroot) && strstr($documentroot, ":") !== false) {
\Froxlor\UI\Response::standard_error('pathmaynotcontaincolon', '', true);
}
if ($this->getUserDetail('change_serversettings') == '1') {
if (Settings::Get('system.bind_enable') == '1') {
@@ -1201,33 +1235,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);
$documentroot = \Froxlor\Validate\Validate::validate($documentroot, 'documentroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), 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') {
if (Settings::Get('system.documentroot_use_default_value') == 1) {
$_documentroot = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $result['domain']);
} else {
$_documentroot = $customer['documentroot'];
}
// set the customers default docroot
$documentroot = $_documentroot;
}
if ($documentroot == '') {
// 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 (Settings::Get('system.documentroot_use_default_value') == 1) {
$documentroot = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $result['domain']);
} else {
$documentroot = $customer['documentroot'];
}
}
if (! preg_match('/^https?\:\/\//', $documentroot) && strstr($documentroot, ":") !== false) {
\Froxlor\UI\Response::standard_error('pathmaynotcontaincolon', '', true);
}
$ssl_protocols = array();
if (! empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) {
@@ -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,8 +137,9 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
"email" => $email,
"email_full" => $email_full,
"iscatchall" => $iscatchall,
"disablegreylist" => $disablegreylist,
"domainid" => $domain_check['id'],
"description" => $description
"description" => $description
);
Database::pexecute($stmt, $params, true, true);
@@ -172,7 +178,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$customer_ids = $this->getAllowedCustomerIds('email');
$params['idea'] = ($id <= 0 ? $emailaddr : $id);
$result_stmt = Database::prepare("SELECT v.`id`, v.`email`, v.`email_full`, v.`iscatchall`, v.`destination`, v.`customerid`, v.`popaccountid`, v.`domainid`, v.`description`, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize`
$result_stmt = Database::prepare("SELECT v.`id`, v.`email`, v.`email_full`, v.`iscatchall`, v.`destination`, v.`customerid`, v.`popaccountid`, v.`domainid`, v.`description`, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize`, v.`disablegreylist`
FROM `" . TABLE_MAIL_VIRTUAL . "` v
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON v.`popaccountid` = u.`id`
WHERE v.`customerid` IN (" . implode(", ", $customer_ids) . ")
@@ -235,7 +241,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// parameters
$iscatchall = $this->getBoolParam('iscatchall', true, $result['iscatchall']);
$description = $this->getParam('description', true, $result['description']);
// get needed customer info to reduce the email-address-counter by one
$customer = $this->getCustomerData();
@@ -282,7 +288,97 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
));
return $this->response(200, "successful", $result);
}
/**
* toggle greylist flag of given email address either by id or email-address
*
* @param int $id
* optional, the email-address-id
* @param string $emailaddr
* optional, the email-address
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
* @param boolean $disablegreylist
* optional
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
*/
public function update_greylist()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
throw new \Exception("You cannot access this resource", 405);
}
// if enabling catchall is not allowed by settings, we do not need
// to run update()
if (Settings::Get('mail.greylist_enabled') != '1') {
\Froxlor\UI\Response::standard_error(array(
'operationnotpermitted',
'featureisdisabled'
), 'catchall', true);
}
$id = $this->getParam('id', true, 0);
$ea_optional = ($id <= 0 ? false : true);
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
$result = $this->apiCall('Emails.get', array(
'id' => $id,
'emailaddr' => $emailaddr
));
$id = $result['id'];
// parameters
$disablegreylist = $this->getBoolParam('disablegreylist', true, $result['disablegreylist']);
// get needed customer info to reduce the email-address-counter by one
$customer = $this->getCustomerData();
// check for catchall-flag
if ($disablegreylist) {
$disablegreylist = '1';
$email_parts = explode('@', $result['email_full']);
$email = '@' . $email_parts[1];
// catchall check
$stmt = Database::prepare("
SELECT `email_full` FROM `" . TABLE_MAIL_VIRTUAL . "`
WHERE `email` = :email AND `customerid` = :cid AND `disablegreylist` = '1'
");
$params = array(
"email" => $email,
"cid" => $customer['customerid']
);
$email_check = Database::pexecute_first($stmt, $params, true, true);
if ($email_check) {
\Froxlor\UI\Response::standard_error('youhavealreadyacatchallforthisdomain', '', true);
}
} else {
$disablegreylist = '0';
$email = $result['email_full'];
}
$stmt = Database::prepare("
UPDATE `" . TABLE_MAIL_VIRTUAL . "`
SET `email` = :email , `disablegreylist` = :disablegreylist
WHERE `customerid`= :cid AND `id`= :id
");
$params = array(
"email" => $email,
"disablegreylist" => $disablegreylist,
"cid" => $customer['customerid'],
"id" => $id
);
Database::pexecute($stmt, $params, true, true);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] toggled greylist-flag for email address '" . $result['email_full'] . "'");
$result = $this->apiCall('Emails.get', array(
'emailaddr' => $result['email_full']
));
return $this->response(200, "successfull", $result);
}
/**
* list all email addresses, if called from an admin, list all email addresses of all customers you are allowed to view, or specify id or loginname for one specific customer
*

View File

@@ -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,139 +47,145 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*/
public function add()
{
// required parameters
$password = $this->getParam('mysql_password');
if (($this->getUserDetail('mysqls_used') < $this->getUserDetail('mysqls') || $this->getUserDetail('mysqls') == '-1') || $this->isAdmin()) {
// required parameters
$password = $this->getParam('mysql_password');
// parameters
$dbserver = $this->getParam('mysql_server', true, 0);
$databasedescription = $this->getParam('description', true, '');
$databasename = $this->getParam('custom_suffix', true, '');
$sendinfomail = $this->getBoolParam('sendinfomail', true, 0);
// get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData('mysqls');
// parameters
$dbserver = $this->getParam('mysql_server', true, 0);
$databasedescription = $this->getParam('description', true, '');
$databasename = $this->getParam('custom_suffix', true, '');
$sendinfomail = $this->getBoolParam('sendinfomail', true, 0);
// get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData('mysqls');
// 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);
$databasename = \Froxlor\Validate\Validate::validate(trim($databasename), 'database_name', '', '', array(), true);
// validate whether the dbserver exists
$dbserver = \Froxlor\Validate\Validate::validate($dbserver, html_entity_decode($this->lng['mysql']['mysql_server']), '', '', 0, true);
Database::needRoot(true, $dbserver);
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
if (! isset($sql_root) || ! is_array($sql_root)) {
throw new \Exception("Database server with index #" . $dbserver . " is unknown", 404);
}
if ($sendinfomail != 1) {
$sendinfomail = 0;
}
$newdb_params = array(
'loginname' => ($this->isAdmin() ? $customer['loginname'] : $this->getUserDetail('loginname')),
'mysql_lastaccountnumber' => ($this->isAdmin() ? $customer['mysql_lastaccountnumber'] : $this->getUserDetail('mysql_lastaccountnumber'))
);
// 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);
} else {
$username = $dbm->createDatabase($newdb_params['loginname'], $password, $newdb_params['mysql_lastaccountnumber']);
}
// we've checked against the password in dbm->createDatabase
if ($username == false) {
\Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true);
}
// add database info to froxlor
$stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_DATABASES . "`
SET
`customerid` = :customerid,
`databasename` = :databasename,
`description` = :description,
`dbserver` = :dbserver
");
$params = array(
"customerid" => $customer['customerid'],
"databasename" => $username,
"description" => $databasedescription,
"dbserver" => $dbserver
);
Database::pexecute($stmt, $params, true, true);
$databaseid = Database::lastInsertId();
$params['id'] = $databaseid;
// update customer usage
Customers::increaseUsage($customer['customerid'], 'mysqls_used');
Customers::increaseUsage($customer['customerid'], 'mysql_lastaccountnumber');
// send info-mail?
if ($sendinfomail == 1) {
$pma = $this->lng['admin']['notgiven'];
if (Settings::Get('panel.phpmyadmin_url') != '') {
$pma = Settings::Get('panel.phpmyadmin_url');
// 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', \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);
}
// validate whether the dbserver exists
$dbserver = \Froxlor\Validate\Validate::validate($dbserver, html_entity_decode($this->lng['mysql']['mysql_server']), '', '', 0, true);
Database::needRoot(true, $dbserver);
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
$userinfo = $customer;
if (!isset($sql_root) || !is_array($sql_root)) {
throw new \Exception("Database server with index #" . $dbserver . " is unknown", 404);
}
$replace_arr = array(
'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($userinfo),
'CUST_NAME' => \Froxlor\User::getCorrectUserSalutation($userinfo), // < keep this for compatibility
'NAME' => $userinfo['name'],
'FIRSTNAME' => $userinfo['firstname'],
'COMPANY' => $userinfo['company'],
'CUSTOMER_NO' => $userinfo['customernumber'],
'DB_NAME' => $username,
'DB_PASS' => htmlentities(htmlentities($password)),
'DB_DESC' => $databasedescription,
'DB_SRV' => $sql_root['host'],
'PMA_URI' => $pma
if ($sendinfomail != 1) {
$sendinfomail = 0;
}
$newdb_params = array(
'loginname' => ($this->isAdmin() ? $customer['loginname'] : $this->getUserDetail('loginname')),
'mysql_lastaccountnumber' => ($this->isAdmin() ? $customer['mysql_lastaccountnumber'] : $this->getUserDetail('mysql_lastaccountnumber'))
);
// create database, user, set permissions, etc.pp.
$dbm = new \Froxlor\Database\DbManager($this->logger());
// get template for mail subject
$mail_subject = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_subject', $replace_arr, $this->lng['mails']['new_database_by_customer']['subject']);
// get template for mail body
$mail_body = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_mailbody', $replace_arr, $this->lng['mails']['new_database_by_customer']['mailbody']);
$_mailerror = false;
$mailerr_msg = "";
try {
$this->mailer()->Subject = $mail_subject;
$this->mailer()->AltBody = $mail_body;
$this->mailer()->msgHTML(str_replace("\n", "<br />", $mail_body));
$this->mailer()->addAddress($userinfo['email'], \Froxlor\User::getCorrectUserSalutation($userinfo));
$this->mailer()->send();
} catch (\PHPMailer\PHPMailer\Exception $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (\Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
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']);
}
if ($_mailerror) {
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg);
\Froxlor\UI\Response::standard_error('errorsendingmail', $userinfo['email'], true);
// we've checked against the password in dbm->createDatabase
if ($username == false) {
\Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true);
}
$this->mailer()->clearAddresses();
// add database info to froxlor
$stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_DATABASES . "`
SET
`customerid` = :customerid,
`databasename` = :databasename,
`description` = :description,
`dbserver` = :dbserver
");
$params = array(
"customerid" => $customer['customerid'],
"databasename" => $username,
"description" => $databasedescription,
"dbserver" => $dbserver
);
Database::pexecute($stmt, $params, true, true);
$databaseid = Database::lastInsertId();
$params['id'] = $databaseid;
// update customer usage
Customers::increaseUsage($customer['customerid'], 'mysqls_used');
Customers::increaseUsage($customer['customerid'], 'mysql_lastaccountnumber');
// send info-mail?
if ($sendinfomail == 1) {
$pma = $this->lng['admin']['notgiven'];
if (Settings::Get('panel.phpmyadmin_url') != '') {
$pma = Settings::Get('panel.phpmyadmin_url');
}
Database::needRoot(true, $dbserver);
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
$userinfo = $customer;
$replace_arr = array(
'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($userinfo),
'CUST_NAME' => \Froxlor\User::getCorrectUserSalutation($userinfo), // < keep this for compatibility
'NAME' => $userinfo['name'],
'FIRSTNAME' => $userinfo['firstname'],
'COMPANY' => $userinfo['company'],
'USERNAME' => $userinfo['loginname'],
'CUSTOMER_NO' => $userinfo['customernumber'],
'DB_NAME' => $username,
'DB_PASS' => htmlentities(htmlentities($password)),
'DB_DESC' => $databasedescription,
'DB_SRV' => $sql_root['host'],
'PMA_URI' => $pma
);
// get template for mail subject
$mail_subject = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_subject', $replace_arr, $this->lng['mails']['new_database_by_customer']['subject']);
// get template for mail body
$mail_body = $this->getMailTemplate($userinfo, 'mails', 'new_database_by_customer_mailbody', $replace_arr, $this->lng['mails']['new_database_by_customer']['mailbody']);
$_mailerror = false;
$mailerr_msg = "";
try {
$this->mailer()->Subject = $mail_subject;
$this->mailer()->AltBody = $mail_body;
$this->mailer()->msgHTML(str_replace("\n", "<br />", $mail_body));
$this->mailer()->addAddress($userinfo['email'], \Froxlor\User::getCorrectUserSalutation($userinfo));
$this->mailer()->send();
} catch (\PHPMailer\PHPMailer\Exception $e) {
$mailerr_msg = $e->errorMessage();
$_mailerror = true;
} catch (\Exception $e) {
$mailerr_msg = $e->getMessage();
$_mailerror = true;
}
if ($_mailerror) {
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_ERR, "[API] Error sending mail: " . $mailerr_msg);
\Froxlor\UI\Response::standard_error('errorsendingmail', $userinfo['email'], true);
}
$this->mailer()->clearAddresses();
}
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] added mysql-database '" . $username . "'");
$result = $this->apiCall('Mysqls.get', array(
'dbname' => $username
));
return $this->response(200, "successful", $result);
}
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] added mysql-database '" . $username . "'");
$result = $this->apiCall('Mysqls.get', array(
'dbname' => $username
));
return $this->response(200, "successful", $result);
throw new \Exception("No more resources available", 406);
}
/**
@@ -200,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) {
@@ -300,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')) {
@@ -320,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
@@ -387,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("
@@ -484,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');
}
@@ -217,7 +217,9 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
* optional number of seconds for idle-timeout if FPM is used, default is fpm-daemon-value
* @param string $limit_extensions
* optional limitation of php-file-extensions if FPM is used, default is fpm-daemon-value
*
* @param bool $allow_all_customers
* optional add this configuration to the list of every existing customer's allowed-fpm-config list, default is false (no)
*
* @access admin
* @throws \Exception
* @return string json-encoded array
@@ -261,9 +263,10 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$max_requests = $this->getParam('max_requests', true, $def_fpmconfig['max_requests']);
$idle_timeout = $this->getParam('idle_timeout', true, $def_fpmconfig['idle_timeout']);
$limit_extensions = $this->getParam('limit_extensions', true, $def_fpmconfig['limit_extensions']);
$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));
@@ -361,12 +364,14 @@ 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(
'id' => $ins_data['id']
));
$this->addForAllCustomers($allow_all_customers, $ins_data['id']);
return $this->response(200, "successful", $result);
}
throw new \Exception("Not allowed to execute given command.", 403);
@@ -418,6 +423,8 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
* optional number of seconds for idle-timeout if FPM is used, default is fpm-daemon-value
* @param string $limit_extensions
* optional limitation of php-file-extensions if FPM is used, default is fpm-daemon-value
* @param bool $allow_all_customers
* optional add this configuration to the list of every existing customer's allowed-fpm-config list, default is false (no)
*
* @access admin
* @throws \Exception
@@ -456,9 +463,10 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$max_requests = $this->getParam('max_requests', true, $result['max_requests']);
$idle_timeout = $this->getParam('idle_timeout', true, $result['idle_timeout']);
$limit_extensions = $this->getParam('limit_extensions', true, $result['limit_extensions']);
$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));
@@ -557,12 +565,14 @@ 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(
'id' => $id
));
$this->addForAllCustomers($allow_all_customers, $id);
return $this->response(200, "successful", $result);
}
throw new \Exception("Not allowed to execute given command.", 403);
@@ -612,10 +622,44 @@ 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);
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* add given php-config id to the list of allowed php-config to all currently existing customers
* if allow_all_customers parameter is true in PhpSettings::add() or PhpSettings::update()
*
* @param bool $allow_all_customers
* @param int $config_id
*/
private function addForAllCustomers(bool $allow_all_customers, int $config_id)
{
// should this config be added to the allowed list of all existing customers?
if ($allow_all_customers) {
$sel_stmt = Database::prepare("SELECT customerid, allowed_phpconfigs FROM `" . TABLE_PANEL_CUSTOMERS . "`");
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET allowed_phpconfigs = :ap WHERE customerid = :cid");
Database::pexecute($sel_stmt);
while ($cust = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
// get existing entries of customer
$ap = json_decode($cust['allowed_phpconfigs'], true);
// initialize array if it's empty
if (empty($ap)) {
$ap = [];
}
// add this config
$ap[] = $config_id;
// check for duplicates and force value-type to be int
$ap = array_map('intval', array_unique($ap));
// update customer-entry
Database::pexecute($upd_stmt, [
'ap' => json_encode($ap),
'cid' => $cust['customerid']
]);
}
}
}
}

View File

@@ -262,6 +262,19 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$phpsid_result['phpsettingid'] = intval($phpsettingid);
}
$allowed_phpconfigs = $customer['allowed_phpconfigs'];
if (! empty($allowed_phpconfigs)) {
$allowed_phpconfigs = json_decode($allowed_phpconfigs, true);
} 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("
INSERT INTO `" . TABLE_PANEL_DOMAINS . "` SET
@@ -346,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');
@@ -616,7 +629,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
// We can't enable let's encrypt for wildcard-domains
if ($iswildcarddomain == '1' && $letsencrypt == '1') {
\Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt');
\Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true);
}
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
@@ -638,6 +651,19 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] automatically deleted mail-table entries for '" . $idna_convert->decode($result['domain']) . "'");
}
$allowed_phpconfigs = $customer['allowed_phpconfigs'];
if (! empty($allowed_phpconfigs)) {
$allowed_phpconfigs = json_decode($allowed_phpconfigs, true);
} 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) {
\Froxlor\Domain\Domain::updateRedirectOfDomain($id, $redirectcode);
@@ -707,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']) . "'");
}
@@ -993,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

@@ -133,7 +133,7 @@ abstract class BulkAction
$new_data = array();
foreach ($this->api_params as $idx => $param) {
if (isset($data_array[$idx]) && ! empty($data_array[$idx])) {
if (isset($data_array[$idx])) {
$new_data[$param] = $data_array[$idx];
}
}

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
@@ -341,13 +341,43 @@ class ConfigServicesAction extends \Froxlor\Cli\Action
// try to convert namserver hosts to ip's
$ns_ips = "";
$known_ns_ips = [];
if (Settings::Get('system.nameservers') != '') {
$nameservers = explode(',', Settings::Get('system.nameservers'));
foreach ($nameservers as $nameserver) {
$nameserver = trim($nameserver);
// DNS servers might be multi homed; allow transfer from all ip
// addresses of the DNS server
$nameserver_ips = \Froxlor\PhpHelper::gethostbynamel6($nameserver);
if (is_array($nameserver_ips) && count($nameserver_ips) > 0) {
$ns_ips .= implode(",", $nameserver_ips);
// append dot to hostname
if (substr($nameserver, - 1, 1) != '.') {
$nameserver .= '.';
}
// ignore invalid responses
if (! is_array($nameserver_ips)) {
// act like \Froxlor\PhpHelper::gethostbynamel6() and return unmodified hostname on error
$nameserver_ips = array(
$nameserver
);
} else {
$known_ns_ips = array_merge($known_ns_ips, $nameserver_ips);
}
if (!empty($ns_ips)) {
$ns_ips .= ',';
}
$ns_ips .= implode(",", $nameserver_ips);
}
}
// AXFR server
if (Settings::Get('system.axfrservers') != '') {
$axfrservers = explode(',', Settings::Get('system.axfrservers'));
foreach ($axfrservers as $axfrserver) {
if (!in_array(trim($axfrserver), $known_ns_ips)) {
if (!empty($ns_ips)) {
$ns_ips .= ',';
}
$ns_ips .= trim($axfrserver);
}
}
}
@@ -365,7 +395,6 @@ class ConfigServicesAction extends \Froxlor\Cli\Action
'<SERVERIP>' => Settings::Get('system.ipaddress'),
'<NAMESERVERS>' => Settings::Get('system.nameservers'),
'<NAMESERVERS_IP>' => $ns_ips,
'<AXFRSERVERS>' => Settings::Get('system.axfrservers'),
'<VIRTUAL_MAILBOX_BASE>' => Settings::Get('system.vmail_homedir'),
'<VIRTUAL_UID_MAPS>' => Settings::Get('system.vmail_uid'),
'<VIRTUAL_GID_MAPS>' => Settings::Get('system.vmail_gid'),

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

@@ -15,7 +15,7 @@ use Froxlor\Settings;
* @author Froxlor team <team@froxlor.org> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
*
*/
class PowerDNS extends DnsBase
{
@@ -99,30 +99,32 @@ class PowerDNS extends DnsBase
));
$pdns_domain = $pdns_domains_stmt->fetch(\PDO::FETCH_ASSOC);
$del_rec_stmt->execute(array(
'did' => $pdns_domain['id']
));
$del_meta_stmt->execute(array(
'did' => $pdns_domain['id']
));
$del_dom_stmt->execute(array(
'did' => $pdns_domain['id']
));
if ($pdns_domain && ! empty($pdns_domain['id'])) {
$del_rec_stmt->execute(array(
'did' => $pdns_domain['id']
));
$del_meta_stmt->execute(array(
'did' => $pdns_domain['id']
));
$del_dom_stmt->execute(array(
'did' => $pdns_domain['id']
));
}
}
}
private function insertZone($domainname, $serial = 0)
{
$ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("
$ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("
INSERT INTO domains set `name` = :domainname, `notified_serial` = :serial, `type` = :type
");
$ins_stmt->execute(array(
'domainname' => $domainname,
'serial' => $serial,
'type' => strtoupper(Settings::Get('system.powerdns_mode'))
));
$lastid = \Froxlor\Dns\PowerDNS::getDB()->lastInsertId();
return $lastid;;
$ins_stmt->execute(array(
'domainname' => $domainname,
'serial' => $serial,
'type' => strtoupper(Settings::Get('system.powerdns_mode'))
));
$lastid = \Froxlor\Dns\PowerDNS::getDB()->lastInsertId();
return $lastid;
}
private function insertRecords($domainid = 0, $records = array(), $origin = "")

View File

View File

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

View File

@@ -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 .= ' SetHandler proxy:unix:' . $domain['fpm_socket'] . '|fcgi://localhost' . "\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

@@ -131,7 +131,8 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
'ssl_key_file' => null,
'ssl_ca_file' => null,
'ssl_csr_file' => null,
'id' => null
'id' => null,
'wwwserveralias' => 0
);
// add to queue
@@ -165,7 +166,8 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
'ssl_key_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_key_file'] : null,
'ssl_ca_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_ca_file'] : null,
'ssl_csr_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_csr_file'] : null,
'id' => is_array($renew_froxlor) ? $renew_froxlor['id'] : null
'id' => is_array($renew_froxlor) ? $renew_froxlor['id'] : null,
'wwwserveralias' => 0
);
$renew_domains[] = $certrow;
}
@@ -308,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) {
@@ -528,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
@@ -539,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;
}
@@ -597,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);
}
@@ -618,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 = '';
$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

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