Compare commits

...

314 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
Michael Kaufmann
c6f556c8d9 set version to 0.10.29.1 for bugfix release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-10 14:45:17 +02:00
Michael Kaufmann
db1df84ef1 correct db-exists check in installation-process
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-10 14:32:02 +02:00
Michael Kaufmann
52135a1d3a set version to 0.10.29 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-08 08:46:58 +02:00
Michael Kaufmann
7f13bd09da add optional ssl parameters to powerdns-config-template
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-08 08:39:22 +02:00
Nick Ufer
7ccbb37c4e feat: adds mysql tls support (#979) 2021-10-08 08:28:32 +02:00
Michael Kaufmann
7feddf0aec generate unpredictable unique session ids
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-02 12:38:17 +02:00
Michael Kaufmann
e73523531a let user decide whether an existing database should be backup'ed and removed when installing froxlor; dont rely on parse_ini_file for OS check; enhance mysqldump so there is no issues with complex passwords and bash-escaping
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-09-24 10:49:57 +02:00
Michael Kaufmann
a47b790e19 actually integrate the new czech language file; refs #976
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-09-04 09:30:44 +02:00
Michael Kaufmann
319eec6124 fix session for 2fa enabled logins
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-27 13:17:05 +02:00
Michael Kaufmann
21983f27b6 secure commonly used filename-variable against url manipulation
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-25 16:36:09 +02:00
Michael Kaufmann
5d375b784d login action always goes to index.php
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-25 16:30:56 +02:00
Michael Kaufmann
4b22470872 set php session security related settings (correctly in every case)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-25 16:21:33 +02:00
Michael Kaufmann
ec1c37aa06 set version to 0.10.28 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-20 09:23:23 +02:00
Nicolas
67351ec3c2 Adding support for PowerDNS-Replication (#974)
Adding support for powerdns-replication
2021-08-19 12:00:09 +02:00
Michael Kaufmann
f1887aaaf2 enable iterate_query in dovecot by default
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-13 09:28:10 +02:00
Michael Kaufmann
afd2d7b5e9 fix dns-validation in Domains.add() and Domains.update() when using Let's Encrypt DNS-check
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-08 11:14:57 +02:00
Michael Kaufmann
c967e585b5 avoid duplicate entries in mysql-access-host setting
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-06 08:11:06 +02:00
Michael Kaufmann
73e364d4ba fix compare of old/new value of aliasdomain when editing a domain as customer to avoid unnecessary regeneration of configfiles
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-04 14:55:22 +02:00
Michael Kaufmann
eb49331b21 remove superfluous inserttask when editing domain as it will be called when there are actually changes to the domain earlier
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-04 14:06:32 +02:00
Michael Kaufmann
0a1a3e023f check dns for lets encrypt when adding/editing domains and via cron; fixes #971
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-04 13:44:13 +02:00
Michael Kaufmann
bef5cedcd0 only add link to customername when editing domain when panel.allow_domain_change_customer is false
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-02 16:58:34 +02:00
Stefan Weil
f8e2bc7bff Fix some typos in code (found by codespell) (#970)
Signed-off-by: Stefan Weil <sw@weilnetz.de>
2021-08-01 19:00:33 +02:00
Stefan Weil
09038ac7aa Fix some typos (found by codespell) (#969)
Signed-off-by: Stefan Weil <sw@weilnetz.de>
2021-07-31 09:51:54 +02:00
Michael Kaufmann
4c507232c7 add setting for a custom system group for all customer-users (required libnss-extrausers); fixes #953
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-30 12:16:37 +02:00
Michael Kaufmann
86939a64da add buypass testing/staging ACME endpoint; create CAA entries accordingly if activated; refs #968
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-29 21:24:43 +02:00
Jens Meißner
926ce427fc Add Buypass to the list of ACME providers. (#968) 2021-07-29 21:15:49 +02:00
Michael Kaufmann
53401eebfb integrity check should allow utf8_* charachter sets and not only 'utf8', thx to lod
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-29 21:04:46 +02:00
Michael Kaufmann
bef580929e Update README.md 2021-07-27 08:14:08 +02:00
Michael Kaufmann
c7b7c67ff4 normalize ipv6 addresses to avoid possible comparison problems; fixes #965
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-26 17:53:44 +02:00
Michael Kaufmann
ed42d4e3df try to fix github action...
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-24 20:31:34 +02:00
Michael Kaufmann
69a2ebce36 create user as froxlor would create it for mysql-8.0
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-24 20:29:56 +02:00
Michael Kaufmann
15f08739fa add github action workflow for mysql
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-24 20:17:42 +02:00
nachtgeist
571690c8c5 admin_customers/edit domain: make customer login name a link (#962) 2021-07-23 16:35:31 +02:00
rex2630
b2005d7f29 [WIP] Czech language (#870)
* Update czech.lng.php
2021-07-21 20:41:07 +02:00
Michael Kaufmann
4354598c64 fix unittests
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-21 10:21:58 +02:00
Michael Kaufmann
05d4bdc499 restore behaviour for unittests as 'create stdsubdomain' default was yes in the settings but no for direct API usage
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-21 10:10:18 +02:00
Michael Kaufmann
25c6a37df2 fix wrong variable-name in Customers.delete()
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-21 10:03:20 +02:00
Michael Kaufmann
41a470fe36 added option to disable creation of default subdomain; fixes #960
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-21 09:53:54 +02:00
Michael Kaufmann
8a4aa2a721 fix lng strings
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-20 23:45:57 +02:00
Michael Kaufmann
1d903770fc have more power over theme logo, custom theme logo and uploaded logo; refs #958
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-20 20:35:54 +02:00
Nicolas
934be5a238 Fix SOA-Record (#959) 2021-07-20 19:29:06 +02:00
Michael Kaufmann
5608f0407f correct heredoc indentation in AcmeSh for php-7.1; fixes #957
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-20 08:11:32 +02:00
Kai
ce9d8dad7f Feature-request #672 - database name prefixes + custom name (#956)
* Fix makeoption function call

* Update formfield.mysql_add.php

Added database name

* Update formfield.mysql_add.php

* Update formfield.mysql_add.php

* Update Mysqls.php

* Update DbManager.php

* Update formfield.mysql_add.php

* Update german.lng.php

* Update formfield.mysql_add.php

* Update Mysqls.php

* Added field database_name (Feature #672)

* Added Testfunction for customer choosed database name

* Fixed test for customer choosed database name
Added docs for param $name

* Fixed mysql api command add
Removed doubled code

* Set settings for customer choosed db name

* Fixed wrong excepted for database name

* Renamed parameter database_name to custom_suffix

* Changed testCustomerMysqlsList
Added testCustomerMysqlsDBNameDelete
2021-07-19 19:10:12 +02:00
Michael Kaufmann
d6fe263e68 Update issue templates 2021-07-19 07:20:46 +02:00
Michael Kaufmann
156846a845 set version to 0.10.27 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-18 10:57:38 +02:00
Michael Kaufmann
abe00b79a7 Update README.md
add github actions build badge
2021-07-17 14:16:29 +02:00
Michael Kaufmann
26ab659c6a Ga testing (#955)
* switch from travis-ci to github actions

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-17 14:14:35 +02:00
Michael Kaufmann
b0273c68d2 remove debian jessie config-templates (outdated); set debian stretch as deprecated; add debian bullseye config templates
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-16 12:15:03 +02:00
Michael Kaufmann
720cf9d74f Merge branch 'master' of github.com:Froxlor/Froxlor 2021-07-13 09:01:25 +02:00
Michael Kaufmann
35cd567c48 check whether there was an image upload at all
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-13 09:01:22 +02:00
Michael Kaufmann
2332d5be7b Merge pull request #949 from bashgeek/custom-css
Custom CSS File in default theme
2021-07-13 08:38:23 +02:00
Daniel
14cdc3801a Merge branch 'Froxlor-master' into custom-css 2021-07-13 10:31:35 +08:00
Daniel
d85efe480e conflict 2021-07-13 10:31:24 +08:00
Daniel
4f2ceaa3ab wip 2021-07-13 10:29:36 +08:00
Michael Kaufmann
3b6792d548 Merge branch 'master' of github.com:Froxlor/Froxlor 2021-07-12 17:29:25 +02:00
Michael Kaufmann
36de6e09d4 remove beta notice from let's encrypt settings
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-12 17:29:21 +02:00
Michael Kaufmann
300c410b18 Merge pull request #948 from bashgeek/logo-custom-login
Custom Logo(s) via Image-Upload in Panel Settings
2021-07-12 17:28:42 +02:00
Daniel Schmitz
282d7d9101 migrate old image + fix versioning 2021-07-09 17:07:50 +08:00
Daniel Schmitz
48f6601003 check mime types 2021-07-09 16:42:21 +08:00
Daniel
c4c4279171 Merge branch 'Froxlor:master' into logo-custom-login 2021-07-09 16:32:59 +08:00
Michael Kaufmann
b88f9c1f18 allow defining php_value/php_admin_value for session.save_path when using php-fpm; fixes #954
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-09 08:23:46 +02:00
Daniel Schmitz
0dac045dc9 wip 2021-07-07 14:11:54 +08:00
Daniel Schmitz
80b5f97367 wip 2021-07-07 14:10:21 +08:00
Daniel Schmitz
7a8b39fad0 wip 2021-07-07 14:00:55 +08:00
Daniel Schmitz
9f5978e875 german translations 2021-07-07 13:33:33 +08:00
Daniel
155fd757bf Merge branch 'Froxlor:master' into logo-custom-login 2021-07-07 13:30:22 +08:00
Daniel Schmitz
518ec202ab wip 2021-07-07 13:26:15 +08:00
Michael Kaufmann
871083d613 Merge pull request #952 from bashgeek/install-warnings
Installer Cleanup & Bug Fixes
2021-06-28 08:06:59 +02:00
Daniel Schmitz
79f0c8d28f wip 2021-06-28 11:01:22 +08:00
Daniel
dfbb4127e2 Merge branch 'Froxlor:master' into logo-custom-login 2021-06-28 10:39:02 +08:00
Daniel Schmitz
b9b2f00f30 wip 2021-06-28 10:37:23 +08:00
Daniel Schmitz
6923f9d926 Revert "wip"
This reverts commit cacbf7fec7.
2021-06-28 10:35:15 +08:00
Daniel Schmitz
cacbf7fec7 wip 2021-06-28 10:34:21 +08:00
Michael Kaufmann
73991e855c Support ZeroSSL via acme.sh (v3); refs #946
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-06-27 09:00:44 +02:00
Michael Kaufmann
0208812013 prefer custom zone entries over automatically created ones when system.dns_createmailentry is enabled, fixes #944
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-06-27 08:41:16 +02:00
Michael Kaufmann
48bd2561f7 Merge pull request #947 from Froxlor/dependabot/composer/phpmailer/phpmailer-6.5.0
Bump phpmailer/phpmailer from 6.4.1 to 6.5.0
2021-06-27 08:37:38 +02:00
Michael Kaufmann
af12c4102b Merge pull request #950 from kruegerj/patch-1
Update focal.xml
2021-06-24 07:57:00 +02:00
kruegerj
d2efa3ecc4 Update focal.xml 2021-06-24 03:16:12 +02:00
Daniel Schmitz
acb04566f5 wip 2021-06-23 11:28:07 +08:00
Daniel Schmitz
abb98ae960 wip 2021-06-23 11:21:33 +08:00
Daniel Schmitz
0d202a7e4d wip 2021-06-23 11:20:18 +08:00
Daniel Schmitz
c69ef20b17 wip 2021-06-23 10:58:52 +08:00
dependabot[bot]
5872d0682a Bump phpmailer/phpmailer from 6.4.1 to 6.5.0
Bumps [phpmailer/phpmailer](https://github.com/PHPMailer/PHPMailer) from 6.4.1 to 6.5.0.
- [Release notes](https://github.com/PHPMailer/PHPMailer/releases)
- [Changelog](https://github.com/PHPMailer/PHPMailer/blob/master/changelog.md)
- [Commits](https://github.com/PHPMailer/PHPMailer/compare/v6.4.1...v6.5.0)

---
updated-dependencies:
- dependency-name: phpmailer/phpmailer
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-22 15:20:44 +00:00
Michael Kaufmann
c4fa8feb8c update dev tools
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-06-17 08:25:43 +02:00
Michael Kaufmann
61a50cc657 add setting for default serveralias value for new domains, refs #944
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-06-16 15:10:52 +02:00
Michael Kaufmann
3df3261ac0 switch from freenode irc network to libera.chat irc network as freenode is dead
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-06-16 11:57:38 +02:00
Michael Kaufmann
f2636e14f0 Merge pull request #945 from MisterDuval/patch-1
Deny all robots
2021-06-01 15:06:31 +02:00
MisterDuval
a23f22f561 Deny all robots
Search engine and all Robots should be denied to the whole Froxlor directory. This file will help!
2021-06-01 14:45:47 +02:00
Michael Kaufmann
8cf3f4ee24 set version to 0.10.26 for upcoming maintenance releasae
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-05-14 08:21:53 +02:00
Michael Kaufmann
e83f7634f8 Merge pull request #938 from Froxlor/dependabot/composer/phpmailer/phpmailer-6.4.1
Bump phpmailer/phpmailer from 6.2.0 to 6.4.1
2021-05-04 19:57:10 +02:00
dependabot[bot]
6eb6595a46 Bump phpmailer/phpmailer from 6.2.0 to 6.4.1
Bumps [phpmailer/phpmailer](https://github.com/PHPMailer/PHPMailer) from 6.2.0 to 6.4.1.
- [Release notes](https://github.com/PHPMailer/PHPMailer/releases)
- [Changelog](https://github.com/PHPMailer/PHPMailer/blob/master/changelog.md)
- [Commits](https://github.com/PHPMailer/PHPMailer/compare/v6.2.0...v6.4.1)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-04 17:43:20 +00:00
Michael Kaufmann
bd48fb7328 catch exception of password-complexity check when changing account password; fixes #935
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-04-14 08:59:44 +02:00
Michael Kaufmann
769525bb56 do not touch/chown error/access log if log is disabled, fixes #934
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-04-12 09:42:25 +02:00
Michael Kaufmann
9195fb3c98 additionally sort by length of username for libnss-extrausers passwd file to have the main user as first in result in any case; fixes #933
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-04-12 09:37:36 +02:00
Michael Kaufmann
82922f7aea add new settings for legal-notes; terms-of-use and privacy-policy; fixes #930
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-24 14:36:48 +01:00
Michael Kaufmann
db1a39b6d9 match composePhpOptions() definition everywhere
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-24 13:49:58 +01:00
Michael Kaufmann
7fbbc2ea0b add vhost replacer {FPMSOCKET} for custom vhost configs; fixes #931
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-24 13:46:24 +01:00
Michael Kaufmann
91d4432108 check rr against possible existing CNAME entries, fixes #927
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-15 17:33:30 +01:00
Michael Kaufmann
c8914312aa Refactoring columns from large table to avoid '1118 Row size too large' error
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-11 09:45:52 +01:00
Michael Kaufmann
3fd89c48e8 set version to 0.10.25 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-05 20:27:55 +01:00
Michael Kaufmann
eceb144a77 also trigger removal of domain in powerdns database if used; refs #923
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-04 12:09:03 +01:00
Michael Kaufmann
1d9651b18a trgger acme.sh removal for domains if customers is being deleted; fixes #923
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-04 12:07:20 +01:00
Michael Kaufmann
49db4e60cb escape passwords for email content (new email-account, new ftp-account and new database); fixes #905
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-03 11:25:58 +01:00
Michael Kaufmann
53e8ccbccb added 'deactivated' parameter to EmailAccounts.update() so admins can disable individual email-accounts, will be overridden if customer is deactivatd and re-enabled; fixes #921
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-03 10:59:16 +01:00
Michael Kaufmann
6d8fc215f1 add description field to panel_domains and mail_virtual table, API parameter 'description' for Domains.add()/Domains.update() and Email.add()/Emails.update(); fixes #910
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-03 10:25:42 +01:00
Michael Kaufmann
f94c303cb3 add API parameter 'show_usages' for Customers.listing() and Customers.get() to return number of domains, and diskspaced used split into webspace_used, mailspace_used and dbspace_used; fixes #912
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-03 09:50:30 +01:00
Michael Kaufmann
2be1873354 fix frontend issue with displaying correct options in domain listing when using php8, thx to cscholz
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-24 19:56:26 +01:00
Michael Kaufmann
d1d36c32fe Merge pull request #920 from RipClaw2971/patch-1
lowercase domain names for ssl-certificate file check (fallback)
2021-02-24 13:07:26 +01:00
RipClaw2971
3b3527348f Update AcmeSh.php
Renewed certificates are not recognized if the domain is in upper/lower case.
2021-02-24 13:00:31 +01:00
Michael Kaufmann
036d5f0713 Merge pull request #919 from nachtgeist/soa
dns: make mail address of SOA records configurable
2021-02-21 18:27:57 +01:00
Daniel Reichelt
a1b8807b0f dns: make mail address of SOA records configurable 2021-02-21 13:00:30 +01:00
Michael Kaufmann
356a087b6a Merge pull request #918 from nachtgeist/pns
dns: check NS entry to be used as primary NS
2021-02-21 09:14:37 +01:00
Michael Kaufmann
0a77fd7150 Merge pull request #917 from nachtgeist/pw
system: validatePassword(): also quote the delimiter ('/')
2021-02-21 09:13:02 +01:00
Daniel Reichelt
67d67a287f system: validatePassword(): also quote the delimiter ('/')
Quoting the default regex delimiter is required for the password
complexity check to work if '/' had been specified as special character
in Froxlor's account settings.
2021-02-21 02:33:46 +01:00
Daniel Reichelt
1f792466bf dns: check NS entry to be used as primary NS
Don't just blindly use the first custom NS entry for SOA, actually check
if it pertains to the domain in question
2021-02-21 02:33:23 +01:00
Michael Kaufmann
5a6343b47c php8 compatibility, fixes #916
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-16 12:38:01 +01:00
Michael Kaufmann
841c529107 fix check for required firstname/name/company in Customers.update(), fixes #915
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-15 23:26:18 +01:00
Michael Kaufmann
41c3f21f0b list only phpenabled and http-enabled domains in php-configuration overview; fixes #911
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-11 16:16:04 +01:00
Michael Kaufmann
b8c0688ba0 added possibility to use 'in' sql-operation in sql_where parameter for Api-calls; php-8 compat fix in admin_traffic
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-11 12:09:42 +01:00
Michael Kaufmann
24e02e99fb set version to 0.10.24 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-05 15:46:08 +01:00
Michael Kaufmann
97bb7b6227 add filecontent to allowed form-fields to not be escaped
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-05 15:44:49 +01:00
Michael Kaufmann
5ceddc8c65 remove not (yet) used cli script
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-05 15:42:38 +01:00
Michael Kaufmann
3a17d03796 add option to specify (optional) fileextension/suffix for generated dkim-private keys; fixes #907
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-20 12:12:41 +01:00
Michael Kaufmann
57ae195930 for percentage calculation always use bytes so we don't compare KiB with GiB or similar
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-18 21:22:29 +01:00
Michael Kaufmann
9b86d576fa do not display usages on dashboard in fixed size-units but dynamically adjusted
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-18 20:49:55 +01:00
Michael Kaufmann
02a12eda13 add missing field 'include_default_vhostconf' to settings table for new installations
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-16 10:50:49 +01:00
Michael Kaufmann
a31da97d66 exclude some formfields from xss-cleaning as it could alter the wanted content
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-13 10:14:51 +01:00
Michael Kaufmann
9f13aa9a12 only pass binding variable for prepared sql statement if variable exists
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-13 08:52:00 +01:00
Michael Kaufmann
2841051649 correctly read in domain's ssl-ips for CAA entries if enabled, fixes #903
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-12 21:08:10 +01:00
Michael Kaufmann
acfbf55d15 Check return of validateFormField() just for non-falsey values and not expect boolean data-type; fixes #904
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-12 19:17:38 +01:00
Michael Kaufmann
5848df28fd Merge pull request #902 from bashgeek/master
Put in trailing slash to /awstats/ location in nginx config
2021-01-12 12:25:22 +01:00
Michael Kaufmann
21925f48c3 set minimum required php-version to 7.1 and recommended php-version to 7.4
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-06 13:36:35 +01:00
Daniel
17a64c58c2 Put in a trailing "/" for /awstats/ location 2020-12-31 16:01:42 +08:00
Daniel
0ca38cff31 Merge pull request #1 from Froxlor/master
up
2020-12-31 15:59:07 +08:00
Michael Kaufmann
5efc1849b4 fix hide-incompatible-settings feature
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-12-30 17:16:15 +01:00
Michael Kaufmann
f213d666e2 fix typo
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-12-30 16:46:01 +01:00
Michael Kaufmann
78495b6487 update link to perl-fastcgi wiki on nginx.com; added setting to hide incompatible settings (depending on webserver)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-12-30 16:41:26 +01:00
2e81445a4e greylisting dis/enable 2020-11-11 13:40:33 +01:00
5821f4a0e5 dmarc entries for all emaildomains 2020-03-03 16:09:19 +01:00
a9c258105a Merge branch 'origin-0.10.13' into private-0.10.12 2020-03-03 14:49:44 +01:00
34fd64e5b9 theme 2020-01-30 15:04:18 +01:00
0adc511d07 theme 2020-01-30 14:56:49 +01:00
6f32d810c1 theme update 2020-01-30 14:48:22 +01:00
70faf0cf2a merged with 0.10.12 - greylisting still needs work 2020-01-21 12:54:21 +01:00
11b589c399 new dkim keys 2020-01-15 12:41:41 +01:00
c8e5668852 new DKIM keys 2020-01-15 12:37:07 +01:00
1eb0f698c0 restructuring dmarc entry 2020-01-15 11:47:54 +01:00
d4d98122bf DMARC 2019-06-13 12:00:59 +02:00
44d430950c dmarc w/o external auth 2018-07-11 21:04:28 +02:00
4ac5e2439c DKIM format fix 2018-07-11 21:02:51 +02:00
99f7fc14de merge 2018-03-25 11:48:01 +02:00
3dcd109ee2 merge 2018-03-25 11:30:04 +02:00
2ab6b9f6f3 other stuff 2018-03-23 12:31:46 +01:00
2c7502485b bind stuff 2018-03-23 12:30:02 +01:00
581e4deca1 checking for emaildomain and continue 2017-06-27 14:29:04 +02:00
92f8986477 fonts and colors 2016-12-16 17:59:04 +01:00
1f800f5298 merged for live 2016-12-16 17:22:28 +01:00
cb582a2947 Merge remote-tracking branch 'private/maketank-theme' into 0.9.38.4 2016-12-16 17:20:55 +01:00
caf2c21ae9 merged with dkim 2016-12-16 17:20:39 +01:00
18998d40c0 debug 2016-12-16 15:53:13 +01:00
e2380284e8 fonts and colors 2016-12-16 14:28:17 +01:00
dce20e55b8 fonts and colors 2016-12-16 14:27:12 +01:00
8bd32821dd fonts and colors 2016-12-16 14:26:58 +01:00
fe5072d0a2 fonts and colors 2016-12-16 14:25:55 +01:00
6ca2292820 fonts and colors 2016-12-16 14:25:23 +01:00
a51ff99ec2 fonts and colors 2016-12-16 14:23:03 +01:00
57464ba8c4 fonts and colors 2016-12-16 14:22:11 +01:00
924f93435f fonts and colors 2016-12-16 14:17:03 +01:00
c141868fd4 fonts and colors 2016-12-16 14:15:32 +01:00
3154914532 fonts and colors 2016-12-16 14:13:39 +01:00
f6e3779728 fonts and colors 2016-12-16 14:10:18 +01:00
c7e0fe57d1 fonts and colors 2016-12-16 14:09:33 +01:00
57aacd96e4 fonts and colors 2016-12-16 14:07:09 +01:00
27be204c96 fonts and colors 2016-12-16 14:06:26 +01:00
b7ab10665a fonts and colors 2016-12-16 14:02:04 +01:00
8bc1a5be69 fonts and colors 2016-12-16 14:00:44 +01:00
832799942e fonts and colors 2016-12-16 13:59:48 +01:00
081858d7bb fonts and colors 2016-12-16 13:58:30 +01:00
88791d3d4a fonts and colors 2016-12-16 13:57:24 +01:00
1f0b90ceef fonts and colors 2016-12-16 13:55:51 +01:00
8f295f1b5d fonts and colors 2016-12-16 13:54:21 +01:00
9abe4415af fonts and colors 2016-12-16 13:53:20 +01:00
d25dd58f7b fonts and colors 2016-12-16 13:49:51 +01:00
9d363c5eb0 fonts and colors 2016-12-16 13:48:25 +01:00
acd357f561 fonts and colors 2016-12-16 13:47:58 +01:00
660272b64b fonts and colors 2016-12-16 13:46:03 +01:00
e2209f53d1 logo 2016-12-16 13:44:41 +01:00
7a7f131861 logo 2016-12-16 13:38:22 +01:00
67803ff106 logo 2016-12-16 13:37:42 +01:00
03bafc9540 logo 2016-12-16 13:34:03 +01:00
8fbc3acba6 logo 2016-12-16 13:32:03 +01:00
0e9dad1b71 logo 2016-12-16 13:28:59 +01:00
3542e85195 Maketank theme 2016-12-16 13:23:16 +01:00
b4829b521b .gitignore not maketank 2016-12-16 13:22:44 +01:00
46bf7005e6 disabled AXFR settings 2016-12-15 15:51:21 +01:00
924731d54d disabled AXFR settings 2016-12-15 15:49:06 +01:00
bc550e086f DKIM and dmarc hardcoded 2016-12-15 15:31:40 +01:00
3167df9947 DKIM and dmarc hardcoded 2016-12-15 13:31:26 +01:00
8686b54fb8 DKIM and dmarc hardcoded 2016-12-15 13:29:15 +01:00
480afb0ccd what a bullshit 2016-12-15 13:20:33 +01:00
b52364a873 DKIM and dmarc hardcoded 2016-12-15 13:10:39 +01:00
ccc95b638b Greylisting TODO: Describe system config 2016-11-09 19:00:00 +01:00
2365d3eae3 initial Greylist: TODO: System-settings 2016-11-09 17:53:59 +01:00
2e0ee3d683 initial Greylist: TODO: System-settings 2016-11-09 17:52:38 +01:00
600 changed files with 16784 additions and 2977 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

View File

@@ -1,6 +1,6 @@
# Bug report vs. support request
If you're unsure of whether your problem is a bug or a configuration error
* contact us via IRC in #froxlor on freenode
* contact us via IRC in #froxlor on irc.libera.chat
* or post a thread in our forum at https://forum.froxlor.org
As a rule of thumb: before reporting an issue

40
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,40 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**As a rule of thumb: before reporting an issue**
* see if it hasn't been [reported](https://github.com/Froxlor/froxlor/issues) (and possibly already been [fixed](https://github.com/Froxlor/froxlor/issues?utf8=✓&q=is:issue%20is:closed)) first
* try with the git master
**Describe the bug**
A clear and concise description of what the bug is.
**System information**
* Froxlor version: $version/$gitSHA1
* Web server: apache2/nginx/lighttpd
* DNS server: Bind/PowerDNS (standalone)/PowerDNS (Bind-backend)
* POP/IMAP server: Courier/Dovecot
* SMTP server: postfix/exim
* FTP server: proftpd/pureftpd
* OS/Version: ...
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Logfiles**
If applicable, add log-entries to help explain your problem.
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

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}}

80
.github/workflows/build-mariadb.yml vendored Normal file
View File

@@ -0,0 +1,80 @@
name: Froxlor-CI-MariaDB
on: ['push', 'pull_request', 'create']
jobs:
froxlor:
name: Froxlor (PHP ${{ matrix.php-versions }}, MariaDB ${{ matrix.mariadb-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php-versions: ['7.4', '8.0']
mariadb-version: [10.5, 10.4]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
tools: composer:v2
extensions: mbstring, xml, ctype, pdo_mysql, mysql, curl, json, zip, session, filter, posix, openssl, fileinfo, bcmath
- name: Install tools
run: sudo apt-get install -y ant
- name: Adjust firewall
run: |
sudo ufw allow out 3306/tcp
sudo ufw allow in 3306/tcp
- name: Setup MariaDB
uses: getong/mariadb-action@v1.1
with:
mariadb version: ${{ matrix.mariadb-version }}
mysql database: 'froxlor010'
mysql root password: 'fr0xl0r.TravisCI'
- name: Wait for database
run: sleep 15
- name: Setup databases
run: |
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "CREATE USER 'froxlor010'@'%' IDENTIFIED BY 'fr0xl0r.TravisCI';"
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "GRANT ALL ON froxlor010.* TO 'froxlor010'@'%';"
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI froxlor010 < install/froxlor.sql
- name: Run testing
run: ant quick-build
# - name: irc push
# uses: rectalogic/notify-irc@v1
# if: github.event_name == 'push'
# with:
# channel: "#froxlor"
# server: "irc.libera.chat"
# nickname: froxlor-ci
# message: |
# ${{ github.actor }} pushed ${{ github.event.ref }} ${{ github.event.compare }}
# ${{ join(github.event.commits.*.message) }}
# - name: irc pull request
# uses: rectalogic/notify-irc@v1
# if: github.event_name == 'pull_request'
# with:
# channel: "#froxlor"
# server: "irc.libera.chat"
# nickname: froxlor-ci
# message: |
# ${{ github.actor }} opened PR ${{ github.event.pull_request.html_url }}
# - name: irc tag created
# uses: rectalogic/notify-irc@v1
# if: github.event_name == 'create' && github.event.ref_type == 'tag'
# with:
# channel: "#froxlor"
# server: "irc.libera.chat"
# nickname: froxlor-ci
# message: |
# ${{ github.actor }} tagged ${{ github.repository }} ${{ github.event.ref }}

57
.github/workflows/build-mysql.yml vendored Normal file
View File

@@ -0,0 +1,57 @@
name: Froxlor-CI-MySQL
on: ['push', 'pull_request', 'create']
jobs:
froxlor:
name: Froxlor (PHP ${{ matrix.php-versions }}, MySQL ${{ matrix.mysql-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php-versions: ['7.4', '8.0']
mysql-version: [8.0, 5.7]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
tools: composer:v2
extensions: mbstring, xml, ctype, pdo_mysql, mysql, curl, json, zip, session, filter, posix, openssl, fileinfo, bcmath
- name: Install tools
run: sudo apt-get install -y ant
- name: Adjust firewall
run: |
sudo ufw allow out 3306/tcp
sudo ufw allow in 3306/tcp
- name: Setup MySQL
uses: samin/mysql-action@v1.3
with:
mysql version: ${{ matrix.mysql-version }}
mysql database: 'froxlor010'
mysql root password: 'fr0xl0r.TravisCI'
- name: Wait for database
run: sleep 15
- name: Setup database (8.0)
if: matrix.mysql-version == '8.0'
run: |
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "CREATE USER 'froxlor010'@'%' IDENTIFIED WITH mysql_native_password BY 'fr0xl0r.TravisCI';"
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "GRANT ALL ON froxlor010.* TO 'froxlor010'@'%';"
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI froxlor010 < install/froxlor.sql
- name: Setup database (5.7)
if: matrix.mysql-version == '5.7'
run: |
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "CREATE USER 'froxlor010'@'%' IDENTIFIED BY 'fr0xl0r.TravisCI';"
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "GRANT ALL ON froxlor010.* TO 'froxlor010'@'%';"
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI froxlor010 < install/froxlor.sql
- name: Run testing
run: ant quick-build

4
.gitignore vendored
View File

@@ -12,9 +12,11 @@ logs/*
.well-known
.idea
*.iml
img/
!templates/Maketank/
!templates/Froxlor/
!templates/Sparkle/
!templates/misc/
templates/Froxlor/assets/img/logo_custom.png
templates/Sparkle/assets/css/custom.css
vendor/

View File

@@ -55,7 +55,7 @@ script:
- ant phpunit-no-coverage
notifications:
irc: "chat.freenode.net#froxlor"
irc: "irc.libera.chat#froxlor"
webhooks:
urls:
- https://webhooks.gitter.im/e/bdf91d1c3f745e51f796

View File

@@ -1,5 +1,6 @@
[![Build Status](https://travis-ci.com/Froxlor/Froxlor.svg?branch=master)](https://travis-ci.com/Froxlor/Froxlor)
[![Gitter](https://badges.gitter.im/Froxlor/community.svg)](https://gitter.im/Froxlor/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![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)
[![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.froxlor.org)
# Froxlor
@@ -20,16 +21,20 @@ 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 freenode.net, channel #froxlor:
irc://chat.freenode.net/froxlor
froxlor may be found on libera.chat, channel #froxlor:
irc://irc.libera.chat/froxlor
### Forum
@@ -37,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

@@ -77,14 +77,6 @@ return array(
'default' => false,
'save_method' => 'storeSettingField'
),
'panel_no_robots' => array(
'label' => $lng['serversettings']['no_robots'],
'settinggroup' => 'panel',
'varname' => 'no_robots',
'type' => 'bool',
'default' => true,
'save_method' => 'storeSettingField'
),
'panel_paging' => array(
'label' => $lng['serversettings']['paging'],
'settinggroup' => 'panel',
@@ -257,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",
@@ -265,7 +257,71 @@ return array(
'traffic.mail' => $lng['menue']['traffic']['traffic'] . " / Mail"
),
'save_method' => 'storeSettingField'
)
),
'panel_imprint_url' => array(
'label' => $lng['serversettings']['imprint_url'],
'settinggroup' => 'panel',
'varname' => 'imprint_url',
'type' => 'string',
'string_type' => 'url',
'string_emptyallowed' => true,
'default' => '',
'save_method' => 'storeSettingField'
),
'panel_terms_url' => array(
'label' => $lng['serversettings']['terms_url'],
'settinggroup' => 'panel',
'varname' => 'terms_url',
'type' => 'string',
'string_type' => 'url',
'string_emptyallowed' => true,
'default' => '',
'save_method' => 'storeSettingField'
),
'panel_privacy_url' => array(
'label' => $lng['serversettings']['privacy_url'],
'settinggroup' => 'panel',
'varname' => 'privacy_url',
'type' => 'string',
'string_type' => 'url',
'string_emptyallowed' => true,
'default' => '',
'save_method' => 'storeSettingField'
),
'panel_logo_overridetheme' => array(
'label' => $lng['serversettings']['logo_overridetheme'],
'settinggroup' => 'panel',
'varname' => 'logo_overridetheme',
'type' => 'bool',
'default' => false,
'save_method' => 'storeSettingField'
),
'panel_logo_overridecustom' => array(
'label' => $lng['serversettings']['logo_overridecustom'],
'settinggroup' => 'panel',
'varname' => 'logo_overridecustom',
'type' => 'bool',
'default' => false,
'save_method' => 'storeSettingField'
),
'panel_logo_image_header' => array(
'label' => $lng['serversettings']['logo_image_header'],
'settinggroup' => 'panel',
'varname' => 'logo_image_header',
'type' => 'image',
'image_name' => 'logo_header',
'default' => '',
'save_method' => 'storeSettingImage'
),
'panel_logo_image_login' => array(
'label' => $lng['serversettings']['logo_image_login'],
'settinggroup' => 'panel',
'varname' => 'logo_image_login',
'type' => 'image',
'image_name' => 'logo_login',
'default' => '',
'save_method' => 'storeSettingImage'
),
)
)
)

View File

@@ -205,9 +205,21 @@ return array(
'default' => false,
'cronmodule' => 'froxlor/backup',
'save_method' => 'storeSettingField'
)
),
'system_createstdsubdom_default' => array(
'label' => $lng['serversettings']['createstdsubdom_default'],
'settinggroup' => 'system',
'varname' => 'createstdsubdom_default',
'type' => 'option',
'default' => '1',
'option_mode' => 'one',
'option_options' => array(
'0' => $lng['panel']['no'],
'1' => $lng['panel']['yes']
),
'save_method' => 'storeSettingField'
),
)
)
)
);

View File

@@ -270,6 +270,28 @@ return array(
'default' => true,
'save_method' => 'storeSettingField'
),
'system_domaindefaultalias' => array(
'label' => $lng['admin']['domaindefaultalias'],
'settinggroup' => 'system',
'varname' => 'domaindefaultalias',
'type' => 'option',
'default' => '0',
'option_mode' => 'one',
'option_options' => array(
'0' => $lng['domains']['serveraliasoption_wildcard'],
'1' => $lng['domains']['serveraliasoption_www'],
'2' => $lng['domains']['serveraliasoption_none']
),
'save_method' => 'storeSettingField'
),
'hide_incompatible_settings' => array(
'label' => $lng['serversettings']['hide_incompatible_settings'],
'settinggroup' => 'system',
'varname' => 'hide_incompatible_settings',
'type' => 'bool',
'default' => false,
'save_method' => 'storeSettingField'
),
)
)
)

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',
@@ -142,6 +151,9 @@ return array(
'default' => '/etc/apache2/conf-enabled/acme.conf',
'save_method' => 'storeSettingField'
),
/**
* currently the only option anyway
*
'system_leapiversion' => array(
'label' => $lng['serversettings']['leapiversion'],
'settinggroup' => 'system',
@@ -154,16 +166,20 @@ return array(
),
'save_method' => 'storeSettingField'
),
*/
'system_letsencryptca' => array(
'label' => $lng['serversettings']['letsencryptca'],
'settinggroup' => 'system',
'varname' => 'letsencryptca',
'type' => 'option',
'default' => 'production',
'default' => 'letsencrypt',
'option_mode' => 'one',
'option_options' => array(
'testing' => 'https://acme-staging-v0' . \Froxlor\Settings::Get('system.leapiversion') . '.api.letsencrypt.org (Test)',
'production' => 'https://acme-v0' . \Froxlor\Settings::Get('system.leapiversion') . '.api.letsencrypt.org (Live)'
'letsencrypt_test' => 'Let\'s Encrypt (Test / Staging)',
'letsencrypt' => 'Let\'s Encrypt (Live)',
'buypass_test' => 'Buypass (Test / Staging)',
'buypass' => 'Buypass (Live)',
'zerossl' => 'ZeroSSL (Live)'
),
'save_method' => 'storeSettingField'
),
@@ -213,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

@@ -99,6 +99,19 @@ return array(
'default' => '',
'save_method' => 'storeSettingField'
),
'system_powerdns_mode' => array(
'label' => $lng['serversettings']['powerdns_mode'],
'settinggroup' => 'system',
'varname' => 'powerdns_mode',
'type' => 'option',
'default' => 'Native',
'option_mode' => 'one',
'option_options' => array(
'Native' => 'Native',
'Master' => 'Master'
),
'save_method' => 'storeSettingField'
),
'system_dns_createmailentry' => array(
'label' => $lng['serversettings']['mail_also_with_mxservers'],
'settinggroup' => 'system',
@@ -132,6 +145,16 @@ return array(
'int_min' => 3600, /* 1 hour */
'int_max' => 2147483647, /* integer max */
'save_method' => 'storeSettingField'
),
'system_soaemail' => array(
'label' => $lng['serversettings']['soaemail'],
'settinggroup' => 'system',
'varname' => 'soaemail',
'type' => 'string',
'string_type' => 'mail',
'string_emptyallowed' => true,
'default' => '',
'save_method' => 'storeSettingField'
)
)
)

View File

@@ -39,6 +39,15 @@ return array(
'default' => '/etc/postfix/dkim/',
'save_method' => 'storeSettingField'
),
'dkim_privkeysuffix' => array(
'label' => $lng['dkim']['privkeysuffix'],
'settinggroup' => 'dkim',
'varname' => 'privkeysuffix',
'type' => 'string',
'string_regexp' => '/^[a-z0-9\._]+$/i',
'default' => '.priv',
'save_method' => 'storeSettingField'
),
'dkim_domains' => array(
'label' => $lng['dkim']['dkim_domains'],
'settinggroup' => 'dkim',

View File

@@ -82,7 +82,20 @@ return array(
'string_emptyallowed' => true,
'default' => '',
'save_method' => 'storeSettingField'
)
),
'system_froxlorusergroup' => array(
'label' => $lng['serversettings']['froxlorusergroup'],
'settinggroup' => 'system',
'varname' => 'froxlorusergroup',
'type' => 'string',
'default' => '',
'save_method' => 'storeSettingField',
'plausibility_check_method' => array(
'\\Froxlor\\Validate\\Check',
'checkLocalGroup'
),
'visible' => \Froxlor\Settings::Get('system.nssextrausers')
),
)
)
)

View File

0
actions/index.html Normal file
View File

View File

@@ -129,7 +129,7 @@ if ($page == 'admins' && $userinfo['change_serversettings'] == '1') {
'userid' => $userinfo['userid']
));
$s = md5(uniqid(microtime(), 1));
$s = \Froxlor\Froxlor::genSessionId();
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_SESSIONS . "` SET
`hash` = :hash, `userid` = :userid, `ipaddress` = :ip,
@@ -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,10 +87,10 @@ 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);
// Fragementation: (freeseg - 1) / total_seg
// Fragmentation: (freeseg - 1) / total_seg
$nseg = $freeseg = $fragsize = $freetotal = 0;
for ($i = 0; $i < $mem['num_seg']; $i ++) {
$ptr = 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

@@ -178,7 +178,7 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
'hash' => $s
));
$s = md5(uniqid(microtime(), 1));
$s = \Froxlor\Froxlor::genSessionId();
$insert = Database::prepare("
INSERT INTO `" . TABLE_PANEL_SESSIONS . "` SET
`hash` = :hash,
@@ -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'];
@@ -290,9 +290,9 @@ if ($page == 'domains' || $page == 'overview') {
// create serveralias options
$serveraliasoptions = "";
$serveraliasoptions .= \Froxlor\UI\HTML::makeoption($lng['domains']['serveraliasoption_wildcard'], '0', '0', true, true);
$serveraliasoptions .= \Froxlor\UI\HTML::makeoption($lng['domains']['serveraliasoption_www'], '1', '0', true, true);
$serveraliasoptions .= \Froxlor\UI\HTML::makeoption($lng['domains']['serveraliasoption_none'], '2', '0', true, true);
$serveraliasoptions .= \Froxlor\UI\HTML::makeoption($lng['domains']['serveraliasoption_wildcard'], '0', Settings::Get('system.domaindefaultalias'), true, true);
$serveraliasoptions .= \Froxlor\UI\HTML::makeoption($lng['domains']['serveraliasoption_www'], '1', Settings::Get('system.domaindefaultalias'), true, true);
$serveraliasoptions .= \Froxlor\UI\HTML::makeoption($lng['domains']['serveraliasoption_none'], '2', Settings::Get('system.domaindefaultalias'), true, true);
$subcanemaildomain = \Froxlor\UI\HTML::makeoption($lng['admin']['subcanemaildomain']['never'], '0', '0', true, true);
$subcanemaildomain .= \Froxlor\UI\HTML::makeoption($lng['admin']['subcanemaildomain']['choosableno'], '1', '0', true, true);
@@ -428,7 +428,7 @@ if ($page == 'domains' || $page == 'overview') {
$customer = Database::pexecute_first($customer_stmt, array(
'customerid' => $result['customerid']
));
$result['customername'] = \Froxlor\User::getCorrectFullUserDetails($customer) . ' (' . $customer['loginname'] . ')';
$result['customername'] = \Froxlor\User::getCorrectFullUserDetails($customer);
}
if ($userinfo['customers_see_all'] == '1') {
@@ -594,6 +594,10 @@ if ($page == 'domains' || $page == 'overview') {
}
$result = \Froxlor\PhpHelper::htmlentitiesArray($result);
if (Settings::Get('panel.allow_domain_change_customer') != '1') {
$result['customername'] .= ' (<a href="' . $linker->getLink(array('section' => 'customers', 'page' => 'customers',
'action' => 'su', 'id' => $customer['customerid'])) . '" rel="external">' . $customer['loginname'] . '</a>)';
}
$domain_edit_data = include_once dirname(__FILE__) . '/lib/formfields/admin/domains/formfield.domains_edit.php';
$domain_edit_form = \Froxlor\UI\HtmlForm::genHTMLForm($domain_edit_data);
@@ -636,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(
@@ -670,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) {
@@ -681,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

@@ -57,6 +57,12 @@ if (isset($_POST['id'])) {
if ($page == 'overview') {
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_index");
$params = [];
if ($userinfo['customers_see_all'] == '0') {
$params = [
'adminid' => $userinfo['adminid']
];
}
$overview_stmt = Database::prepare("SELECT COUNT(*) AS `number_customers`,
SUM(`diskspace_used`) AS `diskspace_used`,
SUM(`mysqls_used`) AS `mysqls_used`,
@@ -68,20 +74,18 @@ if ($page == 'overview') {
SUM(`subdomains_used`) AS `subdomains_used`,
SUM(`traffic_used`) AS `traffic_used`
FROM `" . TABLE_PANEL_CUSTOMERS . "`" . ($userinfo['customers_see_all'] ? '' : " WHERE `adminid` = :adminid "));
$overview = Database::pexecute_first($overview_stmt, array(
'adminid' => $userinfo['adminid']
));
$overview = Database::pexecute_first($overview_stmt, $params);
$dec_places = Settings::Get('panel.decimal_places');
$overview['traffic_used'] = round($overview['traffic_used'] / (1024 * 1024), $dec_places);
$overview['diskspace_used'] = round($overview['diskspace_used'] / 1024, $dec_places);
$overview['traffic_bytes_used'] = $overview['traffic_used'] * 1024;
$overview['traffic_used'] = \Froxlor\PhpHelper::sizeReadable($overview['traffic_used'] * 1024, null, 'bi');
$overview['diskspace_bytes_used'] = $overview['diskspace_used'] * 1024;
$overview['diskspace_used'] = \Froxlor\PhpHelper::sizeReadable($overview['diskspace_used'] * 1024, null, 'bi');
$number_domains_stmt = Database::prepare("
SELECT COUNT(*) AS `number_domains` FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `parentdomainid`='0'" . ($userinfo['customers_see_all'] ? '' : " AND `adminid` = :adminid"));
$number_domains = Database::pexecute_first($number_domains_stmt, array(
'adminid' => $userinfo['adminid']
));
$number_domains = Database::pexecute_first($number_domains_stmt, $params);
$overview['number_domains'] = $number_domains['number_domains'];
@@ -111,11 +115,17 @@ if ($page == 'overview') {
}
$dec_places = Settings::Get('panel.decimal_places');
$userinfo['diskspace'] = round($userinfo['diskspace'] / 1024, $dec_places);
$userinfo['diskspace_used'] = round($userinfo['diskspace_used'] / 1024, $dec_places);
$userinfo['traffic'] = round($userinfo['traffic'] / (1024 * 1024), $dec_places);
$userinfo['traffic_used'] = round($userinfo['traffic_used'] / (1024 * 1024), $dec_places);
$userinfo = \Froxlor\PhpHelper::strReplaceArray('-1', $lng['customer']['unlimited'], $userinfo, 'customers domains diskspace traffic mysqls emails email_accounts email_forwarders email_quota ftps subdomains');
// get everything in bytes for the percentage calculation on the dashboard
$userinfo['diskspace_bytes'] = ($userinfo['diskspace'] > -1) ? $userinfo['diskspace'] * 1024 : -1;
$userinfo['diskspace_bytes_used'] = $userinfo['diskspace_used'] * 1024;
$userinfo['traffic_bytes'] = ($userinfo['traffic'] > -1) ? $userinfo['traffic'] * 1024 : - 1;
$userinfo['traffic_bytes_used'] = $userinfo['traffic_used'] * 1024;
$userinfo['diskspace'] = ($userinfo['diskspace'] > -1) ? \Froxlor\PhpHelper::sizeReadable($userinfo['diskspace'] * 1024, null, 'bi') : - 1;
$userinfo['diskspace_used'] = \Froxlor\PhpHelper::sizeReadable($userinfo['diskspace_used'] * 1024, null, 'bi');
$userinfo['traffic'] = ($userinfo['traffic'] > -1) ? \Froxlor\PhpHelper::sizeReadable($userinfo['traffic'] * 1024, null, 'bi') : - 1;
$userinfo['traffic_used'] = \Froxlor\PhpHelper::sizeReadable($userinfo['traffic_used'] * 1024, null, 'bi');
$userinfo = \Froxlor\PhpHelper::strReplaceArray('-1', $lng['customer']['unlimited'], $userinfo, 'customers domains diskspace diskspace_bytes traffic traffic_bytes mysqls emails email_accounts email_forwarders email_quota ftps subdomains');
$userinfo['custom_notes'] = ($userinfo['custom_notes'] != '') ? nl2br($userinfo['custom_notes']) : '';
@@ -183,8 +193,12 @@ if ($page == 'overview') {
\Froxlor\UI\Response::standard_error('oldpasswordnotcorrect');
}
$new_password = \Froxlor\Validate\Validate::validate($_POST['new_password'], 'new password');
$new_password_confirm = \Froxlor\Validate\Validate::validate($_POST['new_password_confirm'], 'new password confirm');
try {
$new_password = \Froxlor\System\Crypt::validatePassword($_POST['new_password'], 'new password');
$new_password_confirm = \Froxlor\System\Crypt::validatePassword($_POST['new_password_confirm'], 'new password confirm');
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
if ($old_password == '') {
\Froxlor\UI\Response::standard_error(array(

View File

@@ -32,10 +32,10 @@ if ($page == 'message') {
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'viewed panel_message');
if (isset($_POST['send']) && $_POST['send'] == 'send') {
if ($_POST['receipient'] == 0 && $userinfo['customers_see_all'] == '1') {
if ($_POST['recipient'] == 0 && $userinfo['customers_see_all'] == '1') {
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to admins');
$result = Database::query('SELECT `name`, `email` FROM `' . TABLE_PANEL_ADMINS . "`");
} elseif ($_POST['receipient'] == 1) {
} elseif ($_POST['recipient'] == 1) {
if ($userinfo['customers_see_all'] == '1') {
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to ALL customers');
$result = Database::query('SELECT `firstname`, `name`, `company`, `email` FROM `' . TABLE_PANEL_CUSTOMERS . "`");
@@ -49,7 +49,7 @@ if ($page == 'message') {
));
}
} else {
\Froxlor\UI\Response::standard_error('noreceipientsgiven');
\Froxlor\UI\Response::standard_error('norecipientsgiven');
}
$subject = $_POST['subject'];
@@ -105,7 +105,7 @@ if ($page == 'message') {
$sentitems = isset($_GET['sentitems']) ? (int) $_GET['sentitems'] : 0;
if ($sentitems == 0) {
$successmessage = $lng['message']['noreceipients'];
$successmessage = $lng['message']['norecipients'];
} else {
$successmessage = str_replace('%s', $sentitems, $lng['message']['success']);
}
@@ -116,12 +116,12 @@ if ($page == 'message') {
}
$action = '';
$receipients = '';
$recipients = '';
if ($userinfo['customers_see_all'] == '1') {
$receipients .= \Froxlor\UI\HTML::makeoption($lng['panel']['reseller'], 0);
$recipients .= \Froxlor\UI\HTML::makeoption($lng['panel']['reseller'], 0);
}
$receipients .= \Froxlor\UI\HTML::makeoption($lng['panel']['customer'], 1);
$recipients .= \Froxlor\UI\HTML::makeoption($lng['panel']['customer'], 1);
eval("echo \"" . \Froxlor\UI\Template::getTemplate('message/message') . "\";");
}

View File

@@ -22,7 +22,7 @@ require './lib/init.php';
if ($action == 'reset' && function_exists('opcache_reset') && $userinfo['change_serversettings'] == '1') {
opcache_reset();
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "reseted OPcache");
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "reset OPcache");
header('Location: ' . $linker->getLink(array(
'section' => 'opcacheinfo',
'page' => 'showinfo'

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

@@ -56,6 +56,26 @@ if ($page == 'overview' || $page == 'customers') {
$maxyears = date("Y") - $minyear['year'];
}
$params = [];
if ($userinfo['customers_see_all'] == '0') {
$params = [
'id' => $userinfo['adminid']
];
}
$customer_name_list_stmt = Database::prepare("
SELECT `customerid`,`company`,`name`,`firstname`
FROM `" . TABLE_PANEL_CUSTOMERS . "`
WHERE `deactivated`='0'" . ($userinfo['customers_see_all'] ? '' : " AND `adminid` = :id") . "
ORDER BY name"
);
$traffic_list_stmt = Database::prepare("
SELECT month, SUM(http+ftp_up+ftp_down+mail)*1024 AS traffic
FROM `" . TABLE_PANEL_TRAFFIC . "`
WHERE year = :year AND `customerid` = :id
GROUP BY month ORDER BY month"
);
for ($years = 0; $years <= $maxyears; $years ++) {
$overview['year'] = date("Y") - $years;
@@ -76,14 +96,7 @@ if ($page == 'overview' || $page == 'customers') {
'dec' => 0
);
$customer_name_list_stmt = Database::prepare("
SELECT `customerid`,`company`,`name`,`firstname`
FROM `" . TABLE_PANEL_CUSTOMERS . "`
WHERE `deactivated`='0'" . ($userinfo['customers_see_all'] ? '' : " AND `adminid` = :id") . "
ORDER BY name");
Database::pexecute($customer_name_list_stmt, array(
'id' => $userinfo['adminid']
));
Database::pexecute($customer_name_list_stmt, $params);
while ($customer_name = $customer_name_list_stmt->fetch(PDO::FETCH_ASSOC)) {
@@ -104,11 +117,6 @@ if ($page == 'overview' || $page == 'customers') {
'dec' => '-'
);
$traffic_list_stmt = Database::prepare("
SELECT month, SUM(http+ftp_up+ftp_down+mail)*1024 AS traffic
FROM `" . TABLE_PANEL_TRAFFIC . "`
WHERE year = :year AND `customerid` = :id
GROUP BY month ORDER BY month");
Database::pexecute($traffic_list_stmt, array(
'year' => (date("Y") - $years),
'id' => $customer_name['customerid']

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("
@@ -127,7 +147,7 @@ if ($action == 'delete') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed api::api_keys");
// select all my (accessable) certificates
// select all my (accessible) certificates
$keys_stmt_query = "SELECT ak.*, c.loginname, a.loginname as adminname
FROM `" . TABLE_API_KEYS . "` ak
LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` c ON `c`.`customerid` = `ak`.`customerid`

View File

@@ -6,21 +6,20 @@
<property name="pdepend" value="${basedir}/vendor/bin/pdepend" />
<property name="phpcpd" value="${basedir}/vendor/bin/phpcpd" />
<property name="phpcs" value="${basedir}/vendor/bin/phpcs" />
<property name="phpdox" value="${basedir}/vendor/bin/phpdox" />
<property name="phploc" value="${basedir}/vendor/bin/phploc" />
<property name="phpmd" value="${basedir}/vendor/bin/phpmd" />
<property name="phpunit" value="${basedir}/vendor/bin/phpunit" />
<target name="full-build"
depends="prepare,composer,static-analysis,phpunit,phpdox,-check-failure"
depends="prepare,composer,static-analysis,phpunit,-check-failure"
description="Performs static analysis, runs the tests, and generates project documentation" />
<target name="full-build-parallel"
depends="prepare,composer,static-analysis-parallel,phpunit,phpdox,-check-failure"
depends="prepare,composer,static-analysis-parallel,phpunit,-check-failure"
description="Performs static analysis (executing the tools in parallel), runs the tests, and generates project documentation" />
<target name="quick-build"
depends="prepare,composer,lint,phpunit-no-coverage"
depends="prepare,composer,lint,phpunit-no-coverage,-check-failure"
description="Performs a lint check and runs the tests (without generating code coverage reports)" />
<target name="static-analysis"
@@ -49,7 +48,6 @@
<delete dir="${basedir}/build/coverage" />
<delete dir="${basedir}/build/logs" />
<delete dir="${basedir}/build/pdepend" />
<delete dir="${basedir}/build/phpdox" />
<property name="clean.done" value="true" />
</target>
@@ -59,7 +57,6 @@
<mkdir dir="${basedir}/build/coverage" />
<mkdir dir="${basedir}/build/logs" />
<mkdir dir="${basedir}/build/pdepend" />
<mkdir dir="${basedir}/build/phpdox" />
<property name="prepare.done" value="true" />
</target>
@@ -257,7 +254,7 @@
<target name="phpunit-no-coverage" unless="phpunit.done"
depends="composer"
description="Run unit tests with PHPUnit (without generating code coverage reports)">
<exec executable="${phpunit}" failonerror="true"
<exec executable="${phpunit}" failonerror="true" resultproperty="result.phpunit"
taskname="phpunit">
<arg value="--configuration" />
<arg path="${basedir}/phpunit.xml" />
@@ -269,18 +266,6 @@
<property name="phpunit.done" value="true" />
</target>
<target name="phpdox" unless="phpdox.done"
depends="phploc-ci,phpcs-ci,phpcompat-ci,phpmd-ci"
description="Generate project documentation using phpDox">
<exec executable="${phpdox}" dir="${basedir}/build"
taskname="phpdox">
<arg value="--file" />
<arg path="${basedir}/phpdox.xml" />
</exec>
<property name="phpdox.done" value="true" />
</target>
<target name="-check-failure">
<fail message="PHPUnit did not finish successfully">
<condition>

View File

@@ -25,12 +25,12 @@
"issues": "https://github.com/Froxlor/Froxlor/issues",
"forum": "https://forum.froxlor.org/",
"wiki": "https://github.com/Froxlor/Froxlor/wiki",
"irc": "irc://chat.freenode.net/froxlor",
"irc": "irc://irc.libera.chat/froxlor",
"source": "https://github.com/Froxlor/Froxlor",
"docs": "https://github.com/Froxlor/Froxlor/wiki"
},
"require": {
"php": ">=7.0",
"php": "^7.1 || ^8.0",
"ext-session": "*",
"ext-ctype": "*",
"ext-pdo": "*",
@@ -43,23 +43,23 @@
"ext-curl": "*",
"ext-json": "*",
"ext-openssl": "*",
"ext-fileinfo": "*",
"phpmailer/phpmailer": "~6.0",
"monolog/monolog": "^1.24",
"robthree/twofactorauth": "^1.6",
"froxlor/idna-convert-legacy": "^2.1",
"voku/anti-xss": "^4.1"
},
},
"require-dev": {
"phpunit/phpunit": "8.4.1",
"php": ">=7.3",
"phpunit/phpunit": "^9",
"ext-pcntl": "*",
"phpcompatibility/php-compatibility": "*",
"squizlabs/php_codesniffer": "*",
"pdepend/pdepend": "^2.5",
"sebastian/phpcpd": "^4.1",
"theseer/phpdox": "^0.12.0",
"phploc/phploc": "^5.0",
"phpmd/phpmd": "^2.6"
"pdepend/pdepend": "^2.9",
"sebastian/phpcpd": "^6.0",
"phploc/phploc": "^7.0",
"phpmd/phpmd": "^2.10",
"phpunit/php-timer" : "^5"
},
"suggest": {
"ext-bcmath": "*",

2036
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

@@ -93,22 +93,30 @@ if ($page == 'overview') {
'cid' => $userinfo['customerid']
));
if ($usages)
{
$userinfo['diskspace_used'] = round($usages['webspace'] / 1024, Settings::Get('panel.decimal_places'));
$userinfo['mailspace_used'] = round($usages['mail'] / 1024, Settings::Get('panel.decimal_places'));
$userinfo['dbspace_used'] = round($usages['mysql'] / 1024, Settings::Get('panel.decimal_places'));
$userinfo['total_used'] = round(($usages['webspace'] + $usages['mail'] + $usages['mysql']) / 1024, Settings::Get('panel.decimal_places'));
// get everything in bytes for the percentage calculation on the dashboard
$userinfo['diskspace_bytes'] = ($userinfo['diskspace'] > -1) ? $userinfo['diskspace'] * 1024 : -1;
$userinfo['traffic_bytes'] = ($userinfo['traffic'] > -1) ? $userinfo['traffic'] * 1024 : - 1;
$userinfo['traffic_bytes_used'] = $userinfo['traffic_used'] * 1024;
if ($usages) {
$userinfo['diskspace_used'] = \Froxlor\PhpHelper::sizeReadable($usages['webspace'] * 1024, null, 'bi');
$userinfo['mailspace_used'] = \Froxlor\PhpHelper::sizeReadable($usages['mail'] * 1024, null, 'bi');
$userinfo['dbspace_used'] = \Froxlor\PhpHelper::sizeReadable($usages['mysql'] * 1024, null, 'bi');
$userinfo['total_used'] = \Froxlor\PhpHelper::sizeReadable(($usages['webspace'] + $usages['mail'] + $usages['mysql']) * 1024, null, 'bi');
$userinfo['diskspace_bytes_used'] = $usages['webspace'] * 1024;
$userinfo['total_bytes_used'] = ($usages['webspace'] + $usages['mail'] + $usages['mysql']) * 1024;
} else {
$userinfo['diskspace_used'] = 0;
$userinfo['mailspace_used'] = 0;
$userinfo['dbspace_used'] = 0;
$userinfo['total_used'] = 0;
$userinfo['diskspace_bytes_used'] = 0;
$userinfo['total_bytes_used'] = 0;
}
$userinfo['diskspace'] = round($userinfo['diskspace'] / 1024, Settings::Get('panel.decimal_places'));
$userinfo['traffic'] = round($userinfo['traffic'] / (1024 * 1024), Settings::Get('panel.decimal_places'));
$userinfo['traffic_used'] = round($userinfo['traffic_used'] / (1024 * 1024), Settings::Get('panel.decimal_places'));
$userinfo = \Froxlor\PhpHelper::strReplaceArray('-1', $lng['customer']['unlimited'], $userinfo, 'diskspace traffic mysqls emails email_accounts email_forwarders email_quota ftps subdomains');
$userinfo['diskspace'] = ($userinfo['diskspace'] > -1) ? \Froxlor\PhpHelper::sizeReadable($userinfo['diskspace'] * 1024, null, 'bi') : - 1;
$userinfo['traffic'] = ($userinfo['traffic'] > -1) ? \Froxlor\PhpHelper::sizeReadable($userinfo['traffic'] * 1024, null, 'bi') : - 1;
$userinfo['traffic_used'] = \Froxlor\PhpHelper::sizeReadable($userinfo['traffic_used'] * 1024, null, 'bi');
$userinfo = \Froxlor\PhpHelper::strReplaceArray('-1', $lng['customer']['unlimited'], $userinfo, 'diskspace diskspace_bytes traffic traffic_bytes mysqls emails email_accounts email_forwarders email_quota ftps subdomains');
$userinfo['custom_notes'] = ($userinfo['custom_notes'] != '') ? nl2br($userinfo['custom_notes']) : '';
@@ -123,19 +131,25 @@ if ($page == 'overview') {
if ($userinfo['perlenabled'] == '1')
$se[] = "Perl/CGI";
if ($userinfo['api_allowed'] == '1')
$se[] = '<a href="customer_index.php?s='.$s.'&page=apikeys">API</a>';
$se[] = '<a href="customer_index.php?s=' . $s . '&page=apikeys">API</a>';
$services_enabled = implode(", ", $se);
eval("echo \"" . \Froxlor\UI\Template::getTemplate('index/index') . "\";");
} elseif ($page == 'change_password') {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
$old_password = \Froxlor\Validate\Validate::validate($_POST['old_password'], 'old password');
if (! \Froxlor\System\Crypt::validatePasswordLogin($userinfo, $old_password, TABLE_PANEL_CUSTOMERS, 'customerid')) {
\Froxlor\UI\Response::standard_error('oldpasswordnotcorrect');
}
$new_password = \Froxlor\System\Crypt::validatePassword($_POST['new_password'], 'new password');
$new_password_confirm = \Froxlor\System\Crypt::validatePassword($_POST['new_password_confirm'], 'new password confirm');
try {
$new_password = \Froxlor\System\Crypt::validatePassword($_POST['new_password'], 'new password');
$new_password_confirm = \Froxlor\System\Crypt::validatePassword($_POST['new_password_confirm'], 'new password confirm');
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
if ($old_password == '') {
\Froxlor\UI\Response::standard_error(array(

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

293
index.php
View File

@@ -22,12 +22,19 @@ require './lib/init.php';
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\FroxlorLogger;
use Froxlor\Validate\Validate;
if ($action == '') {
$action = 'login';
}
if (session_status() == PHP_SESSION_NONE) {
ini_set("session.name", "s");
ini_set("url_rewriter.tags", "");
ini_set("session.use_cookies", false);
ini_set("session.cookie_httponly", true);
ini_set("session.cookie_secure", $is_ssl);
session_id('login');
session_start();
}
@@ -114,7 +121,7 @@ if ($action == '2fa_entercode') {
));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row['customer'] == $loginname) {
if ($row && $row['customer'] == $loginname) {
$table = "`" . TABLE_PANEL_CUSTOMERS . "`";
$uid = 'customerid';
$adminsession = '0';
@@ -142,7 +149,7 @@ if ($action == '2fa_entercode') {
"loginname" => $loginname
));
$row3 = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row3['customer'] == $loginname) {
if ($row3 && $row3['customer'] == $loginname) {
$table = "`" . TABLE_PANEL_CUSTOMERS . "`";
$uid = 'customerid';
$adminsession = '0';
@@ -181,7 +188,7 @@ if ($action == '2fa_entercode') {
$row = $stmt->fetch(PDO::FETCH_ASSOC);
}
if ($row['admin'] == $loginname) {
if ($row && $row['admin'] == $loginname) {
$table = "`" . TABLE_PANEL_ADMINS . "`";
$uid = 'adminid';
$adminsession = '1';
@@ -346,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'];
@@ -372,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 = "";
@@ -417,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'];
}
}
@@ -669,7 +680,7 @@ function finishLogin($userinfo)
global $version, $dbversion, $remote_addr, $http_user_agent, $languages;
if (isset($userinfo['userid']) && $userinfo['userid'] != '') {
$s = md5(uniqid(microtime(), 1));
$s = \Froxlor\Froxlor::genSessionId();
if (isset($_POST['language'])) {
$language = \Froxlor\Validate\Validate::validate($_POST['language'], 'language');

View File

@@ -71,6 +71,7 @@ CREATE TABLE `mail_virtual` (
`customerid` int(11) NOT NULL default '0',
`popaccountid` int(11) NOT NULL default '0',
`iscatchall` tinyint(1) unsigned NOT NULL default '0',
`description` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `email` (`email`)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -269,12 +270,13 @@ CREATE TABLE `panel_domains` (
`writeaccesslog` tinyint(1) DEFAULT '1',
`writeerrorlog` tinyint(1) DEFAULT '1',
`override_tls` tinyint(1) DEFAULT '0',
`ssl_protocols` text,
`ssl_cipher_list` text,
`tlsv13_cipher_list` text,
`ssl_protocols` varchar(255) NOT NULL DEFAULT '',
`ssl_cipher_list` varchar(500) NOT NULL DEFAULT '',
`tlsv13_cipher_list` varchar(500) NOT NULL DEFAULT '',
`ssl_enabled` tinyint(1) DEFAULT '1',
`ssl_honorcipherorder` tinyint(1) DEFAULT '0',
`ssl_sessiontickets` tinyint(1) DEFAULT '1',
`description` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `customerid` (`customerid`),
KEY `parentdomain` (`parentdomainid`),
@@ -387,6 +389,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('dkim', 'dkim_domains', 'domains'),
('dkim', 'dkim_dkimkeys', 'dkim-keys.conf'),
('dkim', 'dkimrestart_command', '/etc/init.d/dkim-filter restart'),
('dkim', 'privkeysuffix', '.priv'),
('admin', 'show_news_feed', '0'),
('admin', 'show_version_login', '0'),
('admin', 'show_version_footer', '0'),
@@ -492,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
@@ -516,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'),
@@ -529,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'),
@@ -608,6 +611,7 @@ opcache.interned_strings_buffer'),
('system', 'documentroot_use_default_value', '0'),
('system', 'passwordcryptfunc', '3'),
('system', 'axfrservers', ''),
('system', 'powerdns_mode', 'Native'),
('system', 'customer_ssl_path', '/etc/ssl/froxlor-custom/'),
('system', 'allow_error_report_admin', '1'),
('system', 'allow_error_report_customer', '0'),
@@ -625,7 +629,7 @@ opcache.interned_strings_buffer'),
('system', 'apacheitksupport', '0'),
('system', 'leprivatekey', 'unset'),
('system', 'lepublickey', 'unset'),
('system', 'letsencryptca', 'production'),
('system', 'letsencryptca', 'letsencrypt'),
('system', 'letsencryptcountrycode', 'DE'),
('system', 'letsencryptstate', 'Hessen'),
('system', 'letsencryptchallengepath', '/var/www/froxlor'),
@@ -671,6 +675,14 @@ opcache.interned_strings_buffer'),
('system', 'froxloraliases', ''),
('system', 'apply_specialsettings_default', '1'),
('system', 'apply_phpconfigs_default', '1'),
('system', 'hide_incompatible_settings', '0'),
('system', 'include_default_vhostconf', '0'),
('system', 'soaemail', ''),
('system', 'domaindefaultalias', '0'),
('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'),
@@ -683,7 +695,6 @@ opcache.interned_strings_buffer'),
('panel', 'paging', '20'),
('panel', 'natsorting', '1'),
('panel', 'sendalternativemail', '0'),
('panel', 'no_robots', '1'),
('panel', 'allow_domain_change_admin', '0'),
('panel', 'allow_domain_change_customer', '0'),
('panel', 'frontend', 'froxlor'),
@@ -705,8 +716,15 @@ opcache.interned_strings_buffer'),
('panel', 'password_special_char', '!?<>§$%+#=@'),
('panel', 'customer_hide_options', ''),
('panel', 'is_configured', '0'),
('panel', 'version', '0.10.23.1'),
('panel', 'db_version', '202009070');
('panel', 'imprint_url', ''),
('panel', 'terms_url', ''),
('panel', 'privacy_url', ''),
('panel', 'logo_image_header', ''),
('panel', 'logo_image_login', ''),
('panel', 'logo_overridetheme', '0'),
('panel', 'logo_overridecustom', '0'),
('panel', 'version', '0.10.38.3'),
('panel', 'db_version', '202112310');
DROP TABLE IF EXISTS `panel_tasks`;
@@ -805,7 +823,8 @@ INSERT INTO `panel_languages` (`id`, `language`, `iso`, `file`) VALUES
(4, 'Portugu&ecirc;s', 'pt', 'lng/portugues.lng.php'),
(5, 'Italiano', 'it', 'lng/italian.lng.php'),
(6, 'Nederlands', 'nl', 'lng/dutch.lng.php'),
(7, 'Svenska', 'sv', 'lng/swedish.lng.php');
(7, 'Svenska', 'sv', 'lng/swedish.lng.php'),
(8, '&#268;esk&aacute; republika', 'cs', 'lng/czech.lng.php');
DROP TABLE IF EXISTS `panel_syslog`;
@@ -923,7 +942,7 @@ CREATE TABLE IF NOT EXISTS `ftp_quotalimits` (
INSERT INTO `ftp_quotalimits` (`name`, `quota_type`, `per_session`, `limit_type`, `bytes_in_avail`, `bytes_out_avail`, `bytes_xfer_avail`, `files_in_avail`, `files_out_avail`, `files_xfer_avail`) VALUES
INSERT INTO `ftp_quotalimits` (`name`, `quota_type`, `per_session`, `limit_type`, `bytes_in_avail`, `bytes_out_avail`, `bytes_xfer_avail`, `files_in_avail`, `files_out_avail`, `files_xfer_avail`) VALUES
('froxlor', 'user', 'false', 'hard', 0, 0, 0, 0, 0, 0);

0
install/index.html Normal file
View File

View File

@@ -28,7 +28,7 @@
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Install
*
*
*/
class FroxlorInstall
{
@@ -123,7 +123,7 @@ class FroxlorInstall
if ((isset($_POST['installstep']) && $_POST['installstep'] == '1') || (isset($_GET['check']) && $_GET['check'] == '1')) {
$pagetitle = $this->_lng['install']['title'];
if ($this->_checkPostData()) {
// ceck data and create userdata etc.etc.etc.
// check data and create userdata etc.etc.etc.
$result = $this->_doInstall();
} elseif (isset($_GET['check']) && $_GET['check'] == '1') {
// gather data
@@ -163,10 +163,13 @@ class FroxlorInstall
$this->_getPostField('mysql_host', '127.0.0.1');
$this->_getPostField('mysql_database', 'froxlor');
$this->_getPostField('mysql_forcecreate', '0');
$this->_getPostField('mysql_unpriv_user', 'froxlor');
$this->_getPostField('mysql_unpriv_pass');
$this->_getPostField('mysql_root_user', 'root');
$this->_getPostField('mysql_root_pass');
$this->_getPostField('mysql_ssl_ca_file');
$this->_getPostField('mysql_ssl_verify_server_certificate', 0);
$this->_getPostField('admin_user', 'admin');
$this->_getPostField('admin_pass1');
$this->_getPostField('admin_pass2');
@@ -212,6 +215,12 @@ class FroxlorInstall
$options = array(
'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8'
);
if (!empty($this->_data['mysql_ssl_ca_file'])) {
$options[\PDO::MYSQL_ATTR_SSL_CA] = $this->_data['mysql_ssl_ca_file'];
$options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (bool) $this->_data['mysql_ssl_verify_server_certificate'];
}
$dsn = "mysql:host=" . $this->_data['mysql_host'] . ";";
$fatal_fail = false;
try {
@@ -246,15 +255,23 @@ class FroxlorInstall
$content .= $this->_status_message('green', "OK");
// check for existing db and create backup if so
$content .= $this->_backupExistingDatabase($db_root);
// create unprivileged user and the database itself
$content .= $this->_createDatabaseAndUser($db_root);
// importing data to new database
$content .= $this->_importDatabaseData();
if (!$this->_abort) {
// create unprivileged user and the database itself
$content .= $this->_createDatabaseAndUser($db_root);
// importing data to new database
$content .= $this->_importDatabaseData();
}
if (! $this->_abort) {
// create DB object for new database
$options = array(
'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8'
);
if (!empty($this->_data['mysql_ssl_ca_file'])) {
$options[\PDO::MYSQL_ATTR_SSL_CA] = $this->_data['mysql_ssl_ca_file'];
$options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (bool) $this->_data['mysql_ssl_verify_server_certificate'];
}
$dsn = "mysql:host=" . $this->_data['mysql_host'] . ";dbname=" . $this->_data['mysql_database'] . ";";
$another_fail = false;
try {
@@ -324,10 +341,14 @@ class FroxlorInstall
$userdata .= "\$sql['user']='" . addcslashes($this->_data['mysql_unpriv_user'], "'\\") . "';\n";
$userdata .= "\$sql['password']='" . addcslashes($this->_data['mysql_unpriv_pass'], "'\\") . "';\n";
$userdata .= "\$sql['db']='" . addcslashes($this->_data['mysql_database'], "'\\") . "';\n";
$userdata .= "\$sql['ssl']['caFile']='" . addcslashes($this->_data['mysql_ssl_ca_file'], "'\\") . "';\n";
$userdata .= "\$sql['ssl']['verifyServerCertificate']='" . addcslashes($this->_data['mysql_ssl_verify_server_certificate'], "'\\") . "';\n";
$userdata .= "\$sql_root[0]['caption']='Default';\n";
$userdata .= "\$sql_root[0]['host']='" . addcslashes($this->_data['mysql_host'], "'\\") . "';\n";
$userdata .= "\$sql_root[0]['user']='" . addcslashes($this->_data['mysql_root_user'], "'\\") . "';\n";
$userdata .= "\$sql_root[0]['password']='" . addcslashes($this->_data['mysql_root_pass'], "'\\") . "';\n";
$userdata .= "\$sql_root[0]['ssl']['caFile']='" . addcslashes($this->_data['mysql_ssl_ca_file'], "'\\") . "';\n";
$userdata .= "\$sql_root[0]['ssl']['verifyServerCertificate']='" . addcslashes($this->_data['mysql_ssl_verify_server_certificate'], "'\\") . "';\n";
$userdata .= "// enable debugging to browser in case of SQL errors\n";
$userdata .= "\$sql['debug'] = false;\n";
$userdata .= "?>";
@@ -360,6 +381,30 @@ class FroxlorInstall
return $content;
}
/**
* generate safe unique token
*
* @param int $length
* @return string
*/
private function genUniqueToken(int $length = 16)
{
if(!isset($length) || intval($length) <= 8 ){
$length = 16;
}
if (function_exists('random_bytes')) {
return bin2hex(random_bytes($length));
}
if (function_exists('mcrypt_create_iv')) {
return bin2hex(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM));
}
if (function_exists('openssl_random_pseudo_bytes')) {
return bin2hex(openssl_random_pseudo_bytes($length));
}
// if everything else fails, use unsafe fallback
return md5(uniqid(microtime(), 1));
}
/**
* create corresponding entries in froxlor database
*
@@ -403,8 +448,8 @@ class FroxlorInstall
$content .= $this->_status_message('begin', $this->_lng['install']['adding_admin_user']);
$ins_data = array(
'loginname' => $this->_data['admin_user'],
/* use SHA256 default crypt */
'password' => crypt($this->_data['admin_pass1'], '$5$' . md5(uniqid(microtime(), 1)) . md5(uniqid(microtime(), 1))),
/* use SHA256 default crypt */
'password' => crypt($this->_data['admin_pass1'], '$5$' . $this->genUniqueToken() . $this->genUniqueToken()),
'email' => 'admin@' . $this->_data['servername'],
'deflang' => $this->_languages[$this->_activelng]
);
@@ -505,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');
@@ -555,6 +607,12 @@ class FroxlorInstall
$options = array(
'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8'
);
if (!empty($this->_data['mysql_ssl_ca_file'])) {
$options[\PDO::MYSQL_ATTR_SSL_CA] = $this->_data['mysql_ssl_ca_file'];
$options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (bool) $this->_data['mysql_ssl_verify_server_certificate'];
}
$dsn = "mysql:host=" . $this->_data['mysql_host'] . ";dbname=" . $this->_data['mysql_database'] . ";";
$fatal_fail = false;
try {
@@ -683,8 +741,8 @@ class FroxlorInstall
private function _grantDbPrivilegesTo(&$db_root, $database, $username, $password, $access_host)
{
// mysql8 compatibility
if (version_compare($db_root->getAttribute(\PDO::ATTR_SERVER_VERSION), '8.0.11', '>=')) {
// 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
@@ -700,6 +758,24 @@ class FroxlorInstall
"username" => $username,
"host" => $access_host
));
}
// mysql8 compatibility
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
");
$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
));
} else {
// grant privileges
$stmt = $db_root->prepare("
@@ -733,39 +809,59 @@ class FroxlorInstall
));
$rows = $db_root->query("SELECT FOUND_ROWS()")->fetchColumn();
$content .= $this->_status_message('begin', $this->_lng['install']['check_db_exists']);
// check result
if ($result_stmt !== false && $rows > 0) {
$tables_exist = true;
}
if ($tables_exist) {
// tell whats going on
$content .= $this->_status_message('begin', $this->_lng['install']['backup_old_db']);
if ((int)$this->_data['mysql_forcecreate'] > 0) {
// set status
$content .= $this->_status_message('orange', 'exists (' . $this->_data['mysql_database'] . ')');
// tell what's going on
$content .= $this->_status_message('begin', $this->_lng['install']['backup_old_db']);
// create temporary backup-filename
$filename = "/tmp/froxlor_backup_" . date('YmdHi') . ".sql";
// create temporary backup-filename
$filename = "/tmp/froxlor_backup_" . date('YmdHi') . ".sql";
// look for mysqldump
$do_backup = false;
if (file_exists("/usr/bin/mysqldump")) {
$do_backup = true;
$mysql_dump = '/usr/bin/mysqldump';
} elseif (file_exists("/usr/local/bin/mysqldump")) {
$do_backup = true;
$mysql_dump = '/usr/local/bin/mysqldump';
}
// look for mysqldump
$do_backup = false;
if (file_exists("/usr/bin/mysqldump")) {
$do_backup = true;
$mysql_dump = '/usr/bin/mysqldump';
} elseif (file_exists("/usr/local/bin/mysqldump")) {
$do_backup = true;
$mysql_dump = '/usr/local/bin/mysqldump';
}
if ($do_backup) {
$command = $mysql_dump . " " . escapeshellarg($this->_data['mysql_database']) . " -u " . escapeshellarg($this->_data['mysql_root_user']) . " --password='" . escapeshellarg($this->_data['mysql_root_pass']) . "' --result-file=" . $filename;
$output = exec($command);
if (stristr($output, "error")) {
$content .= $this->_status_message('red', $this->_lng['install']['backup_failed']);
// create temporary .cnf file
$cnffilename = "/tmp/froxlor_dump.cnf";
$dumpcnf = "[mysqldump]" . PHP_EOL . "password=\"" . $this->_data['mysql_root_pass'] . "\"" . PHP_EOL;
file_put_contents($cnffilename, $dumpcnf);
if ($do_backup) {
$command = $mysql_dump . " --defaults-extra-file=" . $cnffilename . " " . escapeshellarg($this->_data['mysql_database']) . " -u " . escapeshellarg($this->_data['mysql_root_user']) . " --result-file=" . $filename;
$output = [];
exec($command, $output);
@unlink($cnffilename);
if (stristr(implode(" ", $output), "error") || ! file_exists($filename)) {
$content .= $this->_status_message('red', $this->_lng['install']['backup_failed']);
$this->_abort = true;
} else {
$content .= $this->_status_message('green', 'OK (' . $filename . ')');
}
} else {
$content .= $this->_status_message('green', 'OK (' . $filename . ')');
$content .= $this->_status_message('red', $this->_lng['install']['backup_binary_missing']);
$this->_abort = true;
}
} else {
$content .= $this->_status_message('red', $this->_lng['install']['backup_binary_missing']);
$content .= $this->_status_message('red', $this->_lng['install']['db_exists']);
$this->_abort = true;
}
} else {
$content .= $content .= $this->_status_message('green', 'OK');
}
return $content;
@@ -784,7 +880,7 @@ class FroxlorInstall
}
// language selection
$language_options = '';
foreach ($this->_languages as $language_name => $language_file) {
foreach ($this->_languages as $language_file => $language_name) {
$language_options .= \Froxlor\UI\HTML::makeoption($language_name, $language_file, $this->_activelng, true, true);
}
// get language-form-template
@@ -801,6 +897,8 @@ class FroxlorInstall
$formdata .= $this->_getSectionItemString('mysql_host', true);
// database
$formdata .= $this->_getSectionItemString('mysql_database', true);
// database overwrite if exists?
$formdata .= $this->_getSectionItemYesNo('mysql_forcecreate', false);
// unpriv-user has to be different from root
if ($this->_data['mysql_unpriv_user'] == $this->_data['mysql_root_user']) {
$style = 'blue';
@@ -830,6 +928,9 @@ class FroxlorInstall
}
$formdata .= $this->_getSectionItemString('mysql_root_pass', true, $style, 'password');
$formdata .= $this->_getSectionItemString('mysql_ssl_ca_file', false, $style);
$formdata .= $this->_getSectionItemYesNo('mysql_ssl_verify_server_certificate', false, $style);
/**
* admin data
*/
@@ -867,19 +968,24 @@ class FroxlorInstall
}
// show list of available distro's
$distributions_select_data = [];
$distros = glob(\Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . '/lib/configfiles/') . '*.xml');
foreach ($distros as $_distribution) {
$dist = new \Froxlor\Config\ConfigParser($_distribution);
$dist_display = $dist->distributionName . " " . $dist->distributionCodename . " (" . $dist->distributionVersion . ")";
if (!array_key_exists($dist_display, $distributions_select_data)) {
$distributions_select_data[$dist_display] = '';
}
$distributions_select_data[$dist_display] .= str_replace(".xml", "", strtolower(basename($_distribution)));
}
// sort by distribution name
ksort($distributions_select_data);
$distributions_select = '';
foreach ($distributions_select_data as $dist_display => $dist_index) {
// create select-box-option
$distributions_select .= \Froxlor\UI\HTML::makeoption($dist_display, $dist_index, $this->_data['distribution']);
$distributions_select .= \Froxlor\UI\HTML::makeoption($dist_display, $dist_index, $this->_data['distribution'] ?? '');
// $this->_data['distribution']
}
@@ -947,7 +1053,7 @@ class FroxlorInstall
* optional css
* @param string $type
* optional type of input-box (default: text)
*
*
* @return string
*/
private function _getSectionItemString($fieldname = null, $required = false, $style = "", $type = 'text')
@@ -994,7 +1100,6 @@ class FroxlorInstall
*/
private function _getSectionItemSelectbox($fieldname = null, $options = null, $style = "")
{
$groupname = $this->_lng['install'][$groupname];
$fieldlabel = $this->_lng['install'][$fieldname];
$sectionitem = "";
@@ -1036,11 +1141,11 @@ class FroxlorInstall
// check for correct php version
$content .= $this->_status_message('begin', $this->_lng['requirements']['phpversion']);
if (version_compare("7.0.0", PHP_VERSION, ">=")) {
if (version_compare("7.1.0", PHP_VERSION, ">=")) {
$content .= $this->_status_message('red', $this->_lng['requirements']['notfound'] . ' (' . PHP_VERSION . ')');
$_die = true;
} else {
if (version_compare("7.1.0", PHP_VERSION, ">=")) {
if (version_compare("7.4.0", PHP_VERSION, ">=")) {
$content .= $this->_status_message('orange', $this->_lng['requirements']['newerphpprefered'] . ' (' . PHP_VERSION . ')');
} else {
$content .= $this->_status_message('green', PHP_VERSION);
@@ -1239,7 +1344,7 @@ class FroxlorInstall
*
* @param string $template
* name of the template including subdirectory
*
*
* @return string
*/
private function _getTemplate($template = null)
@@ -1306,10 +1411,12 @@ class FroxlorInstall
// from form
if (! empty($_POST['serverip'])) {
$this->_data['serverip'] = $_POST['serverip'];
$this->_data['serverip'] = inet_ntop(inet_pton($this->_data['serverip']));
return;
// from $_SERVER
} elseif (! empty($_SERVER['SERVER_ADDR'])) {
$this->_data['serverip'] = $_SERVER['SERVER_ADDR'];
$this->_data['serverip'] = inet_ntop(inet_pton($this->_data['serverip']));
return;
}
// empty
@@ -1357,7 +1464,14 @@ class FroxlorInstall
// read os-release
if (file_exists('/etc/os-release')) {
$os_dist = parse_ini_file('/etc/os-release', false);
$os_dist_content = file_get_contents('/etc/os-release');
$os_dist_arr = explode("\n", $os_dist_content);
$os_dist = [];
foreach ($os_dist_arr as $os_dist_line) {
if (empty(trim($os_dist_line))) continue;
$tmp = explode("=", $os_dist_line);
$os_dist[$tmp[0]] = str_replace('"', "", trim($tmp[1]));
}
if (is_array($os_dist) && array_key_exists('ID', $os_dist) && array_key_exists('VERSION_ID', $os_dist)) {
$os_version = explode('.', $os_dist['VERSION_ID'])[0];
}

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 prefered.';
$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...';
@@ -39,7 +39,7 @@ $lng['requirements']['phpjson'] = 'PHP json-extension...';
$lng['requirements']['bcmathdescription'] = 'Traffic-calculation related functions will not work correctly!';
$lng['requirements']['zipdescription'] = 'The auto-update feature requires the zip extension.';
$lng['requirements']['openbasedir'] = 'open_basedir...';
$lng['requirements']['openbasedirenabled'] = 'Froxlor will not work properly with open_basedir enabled. Please disable open_basedir for Froxlor in the coresponding php.ini';
$lng['requirements']['openbasedirenabled'] = 'Froxlor will not work properly with open_basedir enabled. Please disable open_basedir for Froxlor in the corresponding php.ini';
$lng['requirements']['mysqldump'] = 'MySQL dump tool';
$lng['requirements']['mysqldumpmissing'] = 'Automatic backup of possible existing database is not possible. Please install mysql-client tools';
$lng['requirements']['diedbecauseofrequirements'] = 'Cannot install Froxlor without these requirements! Try to fix them and retry.';
@@ -53,10 +53,13 @@ $lng['install']['welcometext'] = 'Thank you for choosing Froxlor. Please fill ou
$lng['install']['database'] = 'Database connection';
$lng['install']['mysql_host'] = 'MySQL-Hostname';
$lng['install']['mysql_database'] = 'Database name';
$lng['install']['mysql_forcecreate'] = 'Backup and overwrite database if exists?';
$lng['install']['mysql_unpriv_user'] = 'Username for the unprivileged MySQL-account';
$lng['install']['mysql_unpriv_pass'] = 'Password for the unprivileged MySQL-account';
$lng['install']['mysql_root_user'] = 'Username for the MySQL-root-account';
$lng['install']['mysql_root_pass'] = 'Password for the MySQL-root-account';
$lng['install']['mysql_ssl_ca_file'] = 'MySQL server certificate file path';
$lng['install']['mysql_ssl_verify_server_certificate'] = 'Verify MySQL TLS certificate';
$lng['install']['admin_account'] = 'Administrator Account';
$lng['install']['admin_user'] = 'Administrator Username';
$lng['install']['admin_pass1'] = 'Administrator Password';
@@ -79,6 +82,8 @@ $lng['install']['testing_mysql_fail'] = 'There seems to be a problem with the da
$lng['install']['backup_old_db'] = 'Creating backup of old database...';
$lng['install']['backup_binary_missing'] = 'Could not find mysqldump';
$lng['install']['backup_failed'] = 'Could not backup database';
$lng['install']['check_db_exists'] = 'Checking database...';
$lng['install']['db_exists'] = 'Unable to create database. A database with the same name exists and should not be overwritten';
$lng['install']['prepare_db'] = 'Preparing database...';
$lng['install']['create_mysqluser_and_db'] = 'Creating database and username...';
$lng['install']['testing_new_db'] = 'Testing if database and user have been created correctly...';

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...';
@@ -53,10 +53,13 @@ $lng['install']['welcometext'] = 'Vielen Dank dass Sie sich für Froxlor entschi
$lng['install']['database'] = 'Datenbankverbindung';
$lng['install']['mysql_host'] = 'MySQL-Hostname';
$lng['install']['mysql_database'] = 'Datenbank Name';
$lng['install']['mysql_forcecreate'] = 'Datenbank sichern und überschreiben wenn vorhanden?';
$lng['install']['mysql_unpriv_user'] = 'Benutzername für den unprivilegierten MySQL-Account';
$lng['install']['mysql_unpriv_pass'] = 'Passwort für den unprivilegierten MySQL-Account';
$lng['install']['mysql_root_user'] = 'Benutzername für den MySQL-Root-Account';
$lng['install']['mysql_root_pass'] = 'Passwort für den MySQL-Root-Account';
$lng['install']['mysql_ssl_ca_file'] = 'MySQL-Server Zertifikatspfad';
$lng['install']['mysql_ssl_verify_server_certificate'] = 'Validieren des MySQL-Server Zertifikats';
$lng['install']['admin_account'] = 'Admin-Zugang';
$lng['install']['admin_user'] = 'Administrator-Benutzername';
$lng['install']['admin_pass1'] = 'Administrator-Passwort';
@@ -79,6 +82,8 @@ $lng['install']['testing_mysql_fail'] = 'Bei der Verwendung der Datenbank gibt e
$lng['install']['backup_old_db'] = 'Sicherung vorheriger Datenbank...';
$lng['install']['backup_binary_missing'] = 'Konnte mysqldump nicht finden';
$lng['install']['backup_failed'] = 'Sicherung fehlgeschlagen';
$lng['install']['check_db_exists'] = 'Databenbank wird geprüft...';
$lng['install']['db_exists'] = 'Datenbank kann nicht erstellt werden. Eine Datenbank mit dem selben Namen existiert bereits und soll nicht überschrieben werden.';
$lng['install']['prepare_db'] = 'Datenbank wird vorbereitet...';
$lng['install']['create_mysqluser_and_db'] = 'Erstelle Datenbank und Benutzer...';
$lng['install']['testing_new_db'] = 'Teste, ob Datenbank und Benutzer korrekt angelegt wurden...';

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

@@ -1,6 +1,7 @@
<?php
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Validate\Validate;
/**
* This file is part of the Froxlor project.
@@ -14,7 +15,7 @@ use Froxlor\Settings;
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Install
*
*
*/
if (! defined('_CRON_UPDATE')) {
if (! defined('AREA') || (defined('AREA') && AREA != 'admin') || ! isset($userinfo['loginname']) || (isset($userinfo['loginname']) && $userinfo['loginname'] == '')) {
@@ -699,6 +700,324 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.22')) {
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.23')) {
showUpdateStep("Updating from 0.10.23 to 0.10.23.1", false);
\Froxlor\Froxlor::updateToVersion('0.10.23.1');
showUpdateStep("Updating from 0.10.23 to 0.10.23.1", false);
\Froxlor\Froxlor::updateToVersion('0.10.23.1');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202009070')) {
showUpdateStep("Adding setting to hide incompatible settings", true);
Settings::AddNew("system.hide_incompatible_settings", '0');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202012300');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202012300')) {
showUpdateStep("Adding setting for DKIM private key extension/suffix", true);
Settings::AddNew("dkim.privkeysuffix", '.priv');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202101200');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.23.1')) {
showUpdateStep("Updating from 0.10.23.1 to 0.10.24", false);
\Froxlor\Froxlor::updateToVersion('0.10.24');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202101200')) {
showUpdateStep("Adding setting for mail address used in SOA records", true);
Settings::AddNew("system.soaemail", '');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202102200');
}
/*
* skip due to potential "1118 Row size too large" error
*
if (\Froxlor\Froxlor::isDatabaseVersion('202102200')) {
showUpdateStep("Add new description fields to mail and domain table", true);
Database::query("ALTER TABLE panel_domains ADD `description` varchar(255) NOT NULL DEFAULT '' AFTER `ssl_sessiontickets`;");
Database::query("ALTER TABLE mail_virtual ADD `description` varchar(255) NOT NULL DEFAULT '' AFTER `iscatchall`");
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202103030');
}
*/
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.24')) {
showUpdateStep("Updating from 0.10.24 to 0.10.25", false);
\Froxlor\Froxlor::updateToVersion('0.10.25');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202102200') || \Froxlor\Froxlor::isDatabaseVersion('202103030')) {
showUpdateStep("Refactoring columns from large tables", true);
Database::query("ALTER TABLE panel_domains CHANGE `ssl_protocols` `ssl_protocols` varchar(255) NOT NULL DEFAULT '';");
Database::query("ALTER TABLE panel_domains CHANGE `ssl_cipher_list` `ssl_cipher_list` varchar(500) NOT NULL DEFAULT '';");
Database::query("ALTER TABLE panel_domains CHANGE `tlsv13_cipher_list` `tlsv13_cipher_list` varchar(500) NOT NULL DEFAULT '';");
lastStepStatus(0);
showUpdateStep("Add new description fields to mail and domain table", true);
$result = Database::query("DESCRIBE `panel_domains`");
$columnfound = 0;
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
if ($row['Field'] == 'description') {
$columnfound = 1;
}
}
if (! $columnfound) {
Database::query("ALTER TABLE panel_domains ADD `description` varchar(255) NOT NULL DEFAULT '' AFTER `ssl_sessiontickets`;");
}
$result = Database::query("DESCRIBE `mail_virtual`");
$columnfound = 0;
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
if ($row['Field'] == 'description') {
$columnfound = 1;
}
}
if (! $columnfound) {
Database::query("ALTER TABLE mail_virtual ADD `description` varchar(255) NOT NULL DEFAULT '' AFTER `iscatchall`");
}
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202103110');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202103110')) {
showUpdateStep("Adding settings for imprint, terms of use and privacy policy URLs", true);
Settings::AddNew("panel.imprint_url", '');
Settings::AddNew("panel.terms_url", '');
Settings::AddNew("panel.privacy_url", '');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202103240');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.25')) {
showUpdateStep("Updating from 0.10.25 to 0.10.26", false);
\Froxlor\Froxlor::updateToVersion('0.10.26');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202103240')) {
showUpdateStep("Adding setting for default serveralias value for new domains", true);
Settings::AddNew("system.domaindefaultalias", '0');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202106160');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202106160')) {
showUpdateStep("Adjusting Let's Encrypt endpoint configuration to support ZeroSSL", true);
if (Settings::Get('system.letsencryptca') == 'testing') {
Settings::Set("system.letsencryptca", 'letsencrypt_test');
} else {
Settings::Set("system.letsencryptca", 'letsencrypt');
}
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202106270');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202106270')) {
showUpdateStep("Adding custom logo image settings", true);
Settings::AddNew("panel.logo_image_header", '');
Settings::AddNew("panel.logo_image_login", '');
lastStepStatus(0);
// Migrating old custom logo over, if exists
$custom_logo_file_old = \Froxlor\Froxlor::getInstallDir() . '/templates/Sparkle/assets/img/logo_custom.png';
if (file_exists($custom_logo_file_old)) {
showUpdateStep("Migrating existing custom logo to new settings", true);
$path = \Froxlor\Froxlor::getInstallDir().'/img/';
if (!is_dir($path) && !mkdir($path, 0775)) {
throw new \Exception("img directory does not exist and cannot be created");
}
if (!is_writable($path)) {
if (!chmod($path, 0775)) {
throw new \Exception("Cannot write to img directory");
}
}
// Save as new custom logo header
$save_to = 'logo_header.png';
copy($custom_logo_file_old, $path.$save_to);
Settings::Set("panel.logo_image_header", "img/{$save_to}?v=".time());
// Save as new custom logo login
$save_to = 'logo_login.png';
copy($custom_logo_file_old, $path.$save_to);
Settings::Set("panel.logo_image_login", "img/{$save_to}?v=".time());
lastStepStatus(0);
}
\Froxlor\Froxlor::updateToDbVersion('202107070');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.26')) {
showUpdateStep("Updating from 0.10.26 to 0.10.27", false);
\Froxlor\Froxlor::updateToVersion('0.10.27');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202107070')) {
showUpdateStep("Adding settings to overwrite theme- or custom theme-logo with the new logo settings", true);
Settings::AddNew("panel.logo_overridetheme", '0');
Settings::AddNew("panel.logo_overridecustom", '0');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202107200');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202107200')) {
showUpdateStep("Adding settings to define default value of 'create std-subdomain' when creating a customer", true);
Settings::AddNew("system.createstdsubdom_default", '1');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202107210');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202107210')) {
showUpdateStep("Normalizing ipv6 for correct comparison", true);
$result_stmt = Database::prepare("
SELECT `id`, `ip` FROM `" . TABLE_PANEL_IPSANDPORTS . "`"
);
Database::pexecute($result_stmt);
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_IPSANDPORTS . "` SET `ip` = :ip WHERE `id` = :id");
while ($iprow = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
if (Validate::is_ipv6($iprow['ip'])) {
$ip = inet_ntop(inet_pton($iprow['ip']));
Database::pexecute($upd_stmt, [
'ip' => $ip,
'id' => $iprow['id']
]);
}
}
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202107260');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202107260')) {
showUpdateStep("Removing setting for search-engine allow yes/no", true);
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'panel' AND `varname` = 'no_robots'");
lastStepStatus(0);
showUpdateStep("Adding setting to have all froxlor customers in a local group", true);
Settings::AddNew("system.froxlorusergroup", '');
Settings::AddNew("system.froxlorusergroup_gid", '');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202107300');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202107300')) {
showUpdateStep("Adds the possibility to select the PowerDNS Operation Mode", true);
Settings::AddNew("system.powerdns_mode", 'Native');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202108180');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.27')) {
showUpdateStep("Updating from 0.10.27 to 0.10.28", false);
\Froxlor\Froxlor::updateToVersion('0.10.28');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202108180')) {
showUpdateStep("Adding czech language file", true);
Database::query("INSERT INTO `" . TABLE_PANEL_LANGUAGE . "` SET `language` = '&#268;esk&aacute; republika', `iso` = 'cs', `file` = 'lng/czech.lng.php'");
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202109040');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.28')) {
showUpdateStep("Updating from 0.10.28 to 0.10.29", false);
\Froxlor\Froxlor::updateToVersion('0.10.29');
}
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

@@ -2505,7 +2505,7 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.9.30')) {
showUpdateStep("Updating from 0.9.30 to 0.9.31-dev1", true);
lastStepStatus(0);
showUpdateStep("Removing unsused tables");
showUpdateStep("Removing unused tables");
Database::query("DROP TABLE IF EXISTS `ipsandports_docrootsettings`;");
Database::query("DROP TABLE IF EXISTS `domain_docrootsettings`;");
lastStepStatus(0);
@@ -2856,7 +2856,7 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.9.32-rc1')) {
Settings::AddNew("system.croncmdline", $croncmdline);
// add task to generate cron.d-file
\Froxlor\System\Cronjob::inserttask('99');
// silenty add the auto-update setting - we do not want everybody to know and use this
// silently add the auto-update setting - we do not want everybody to know and use this
// as it is a very dangerous setting
Settings::AddNew("system.cron_allowautoupdate", 0);
lastStepStatus(0);
@@ -3872,7 +3872,7 @@ opcache.interned_strings_buffer');
if (\Froxlor\Froxlor::isDatabaseVersion('201801110')) {
showUpdateStep("Adding php-fpm php PATH setting for envrironment");
showUpdateStep("Adding php-fpm php PATH setting for environment");
Settings::AddNew("phpfpm.envpath", '/usr/local/bin:/usr/bin:/bin');
lastStepStatus(0);

View File

View File

View File

@@ -19,7 +19,7 @@
* Function getPreConfig
*
* outputs various content before the update process
* can be continued (askes for agreement whatever is being asked)
* can be continued (asks for agreement whatever is being asked)
*
* @param string $current_version
* @param int $current_db_version

View File

View File

@@ -414,7 +414,7 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
if (Settings::Get('system.webserver') == 'apache2') {
$has_preconfig = true;
$description = 'Froxlor now supports the new Apache 2.4. Please be aware that you need to load additional apache-modules in ordner to use it.<br />';
$description = 'Froxlor now supports the new Apache 2.4. Please be aware that you need to load additional apache-modules in order to use it.<br />';
$description .= '<pre>LoadModule authz_core_module modules/mod_authz_core.so
LoadModule authz_host_module modules/mod_authz_host.so</pre><br />';
$question = '<strong>Do you want to enable the Apache-2.4 modification?:</strong>&nbsp;';

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 ';
}
@@ -310,6 +314,21 @@ abstract class ApiCommand extends ApiParameter
} elseif (in_array($valoper['op'], $ops)) {
$condition .= $field . ' ' . $valoper['op'] . ':' . $cleanfield;
$query_fields[':' . $cleanfield] = $valoper['value'] ?? '';
} 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 ?? '';
}
$condition = substr($condition, 0, - 2) . ')';
} else {
continue;
}
@@ -391,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',
@@ -416,6 +439,7 @@ abstract class ApiCommand extends ApiParameter
return $order;
}
/**
* return logger instance
*
@@ -518,7 +542,7 @@ abstract class ApiCommand extends ApiParameter
$customer_ids[] = $customer['customerid'];
}
} else {
if (!$this->isInternal() && ! empty($customer_hide_option) && \Froxlor\Settings::IsInList('panel.customer_hide_options', $customer_hide_option)) {
if (! $this->isInternal() && ! empty($customer_hide_option) && \Froxlor\Settings::IsInList('panel.customer_hide_options', $customer_hide_option)) {
throw new \Exception("You cannot access this resource", 405);
}
$customer_ids = array(

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

@@ -189,7 +189,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
*/
public function listing()
{
// select all my (accessable) certificates
// select all my (accessible) certificates
$certs_stmt_query = "SELECT s.*, d.domain, d.letsencrypt, c.customerid, c.loginname
FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON `d`.`id` = `s`.`domainid`
@@ -237,7 +237,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
*/
public function listingCount()
{
// select all my (accessable) certificates
// select all my (accessible) certificates
$certs_stmt_query = "SELECT COUNT(*) as num_certs
FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON `d`.`id` = `s`.`domainid`
@@ -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

@@ -23,7 +23,7 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
{
/**
* check whether backup is enabled systemwide and if accessable for customer (hide_options)
* check whether backup is enabled systemwide and if accessible for customer (hide_options)
*
* @throws \Exception
*/
@@ -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

@@ -33,7 +33,9 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @param bool $show_usages
* optional, default false
*
* @access admin
* @throws \Exception
* @return string json-encoded array count|list
@@ -41,6 +43,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
public function listing()
{
if ($this->isAdmin()) {
$show_usages = $this->getBoolParam('show_usages', true, false);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list customers");
$query_fields = array();
$result_stmt = Database::prepare("
@@ -57,7 +60,47 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$params = array_merge($params, $query_fields);
Database::pexecute($result_stmt, $params, true, true);
$result = array();
$domains_stmt = null;
$usages_stmt = null;
if ($show_usages) {
$domains_stmt = Database::prepare("
SELECT COUNT(`id`) AS `domains`
FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `customerid` = :cid
AND `parentdomainid` = '0'
AND `id`<> :stdd
");
$usages_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DISKSPACE . "`
WHERE `customerid` = :cid
ORDER BY `stamp` DESC LIMIT 1
");
}
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
if ($show_usages) {
// get number of domains
Database::pexecute($domains_stmt, array(
'cid' => $row['customerid'],
'stdd' => $row['standardsubdomain']
));
$domains = $domains_stmt->fetch(\PDO::FETCH_ASSOC);
$row['domains'] = intval($domains['domains']);
// get disk-space usages for web, mysql and mail
$usages = Database::pexecute_first($usages_stmt, array(
'cid' => $row['customerid']
));
if ($usages) {
$row['webspace_used'] = $usages['webspace'];
$row['mailspace_used'] = $usages['mail'];
$row['dbspace_used'] = $usages['mysql'];
} else {
$row['webspace_used'] = 0;
$row['mailspace_used'] = 0;
$row['dbspace_used'] = 0;
}
}
$result[] = $row;
}
return $this->response(200, "successful", array(
@@ -103,6 +146,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* optional, the customer-id
* @param string $loginname
* optional, the loginname
* @param bool $show_usages
* optional, default false
*
* @access admin, customer
* @throws \Exception
@@ -113,6 +158,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$id = $this->getParam('id', true, 0);
$ln_optional = ($id <= 0 ? false : true);
$loginname = $this->getParam('loginname', $ln_optional, '');
$show_usages = $this->getBoolParam('show_usages', true, false);
if ($this->isAdmin()) {
$result_stmt = Database::prepare("
@@ -142,6 +188,40 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
if (! $this->isAdmin() && $result['custom_notes_show'] != 1) {
$result['custom_notes'] = "";
}
if ($show_usages) {
// get number of domains
$domains_stmt = Database::prepare("
SELECT COUNT(`id`) AS `domains`
FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `customerid` = :cid
AND `parentdomainid` = '0'
AND `id`<> :stdd
");
Database::pexecute($domains_stmt, array(
'cid' => $result['customerid'],
'stdd' => $result['standardsubdomain']
));
$domains = $domains_stmt->fetch(\PDO::FETCH_ASSOC);
$result['domains'] = intval($domains['domains']);
// get disk-space usages for web, mysql and mail
$usages_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DISKSPACE . "`
WHERE `customerid` = :cid
ORDER BY `stamp` DESC LIMIT 1
");
$usages = Database::pexecute_first($usages_stmt, array(
'cid' => $result['customerid']
));
if ($usages) {
$result['webspace_used'] = $usages['webspace'];
$result['mailspace_used'] = $usages['mail'];
$result['dbspace_used'] = $usages['mysql'];
} else {
$result['webspace_used'] = 0;
$result['mailspace_used'] = 0;
$result['dbspace_used'] = 0;
}
}
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get customer '" . $result['loginname'] . "'");
return $this->response(200, "successful", $result);
}
@@ -228,7 +308,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 [system.createstdsubdom_default]
* @param bool $phpenabled
* optional, whether to allow usage of PHP, default 0 (false)
* @param array $allowed_phpconfigs
@@ -236,9 +316,9 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* @param bool $perlenabled
* optional, whether to allow usage of Perl/CGI, default 0 (false)
* @param bool $dnsenabled
* optional, wether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false)
* optional, whether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false)
* @param bool $logviewenabled
* optional, wether to allow acccess to webserver access/error-logs, default 0 (false)
* optional, whether to allow access to webserver access/error-logs, default 0 (false)
* @param bool $store_defaultindex
* optional, whether to store the default index file to customers homedir
* @param int $hosting_plan_id
@@ -272,7 +352,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$gender = (int) $this->getParam('gender', true, 0);
$custom_notes = $this->getParam('custom_notes', true, '');
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
$createstdsubdomain = $this->getBoolParam('createstdsubdomain', true, 0);
$createstdsubdomain = $this->getBoolParam('createstdsubdomain', true, Settings::Get('system.createstdsubdom_default'));
$password = $this->getParam('new_customer_password', true, '');
$sendpassword = $this->getBoolParam('sendpassword', true, 0);
$store_defaultindex = $this->getBoolParam('store_defaultindex', true, 0);
@@ -288,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;
@@ -305,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);
@@ -324,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();
@@ -453,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,
@@ -494,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,
@@ -565,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);
@@ -594,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
@@ -659,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);
}
}
@@ -835,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
@@ -843,9 +927,9 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* @param bool $perlenabled
* optional, whether to allow usage of Perl/CGI, default 0 (false)
* @param bool $dnsenabled
* optional, ether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false)
* optional, whether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false)
* @param bool $logviewenabled
* optional, ether to allow acccess to webserver access/error-logs, default 0 (false)
* optional, whether to allow access to webserver access/error-logs, default 0 (false)
* @param string $theme
* optional, change theme
*
@@ -870,10 +954,10 @@ 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($name) && empty($firstname)) || (empty($name) && ! empty($firstname)) || (empty($name) && empty($firstname));
$company_required = empty($result['company']) && ((! empty($name) && empty($firstname)) || (empty($name) && ! empty($firstname)) || (empty($name) && empty($firstname)));
$company = $this->getParam('company', ($company_required ? false : true), $result['company']);
$street = $this->getParam('street', true, $result['street']);
$zipcode = $this->getParam('zipcode', true, $result['zipcode']);
@@ -888,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']);
@@ -899,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));
@@ -918,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));
@@ -971,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';
}
@@ -1008,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);
}
}
@@ -1022,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
@@ -1112,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
@@ -1154,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,
@@ -1196,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,
@@ -1224,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` ";
@@ -1411,7 +1498,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
), true, true);
// first gather all domain-id's to clean up panel_domaintoip, dns-entries and certificates accordingly
$did_stmt = Database::prepare("SELECT `id` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :id");
$did_stmt = Database::prepare("SELECT `id`, `domain` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :id");
Database::pexecute($did_stmt, array(
'id' => $id
), true, true);
@@ -1431,6 +1518,10 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
Database::pexecute($stmt, array(
'did' => $row['id']
), true, true);
// remove domains DNS from powerDNS if used, #581
\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(\Froxlor\Cron\TaskId::DELETE_DOMAIN_SSL, $row['domain']);
}
// remove customer domains
$stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :id");
@@ -1559,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,
@@ -322,7 +322,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
}
/**
* returns the total number of accessable directory options
* returns the total number of accessible directory options
*
* @param int $customerid
* optional, admin-only, select directory-protections of a specific customer by id
@@ -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'] . ")'");
@@ -305,7 +305,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
}
/**
* returns the total number of accessable directory protections
* returns the total number of accessible directory protections
*
* @param int $customerid
* optional, admin-only, select directory-protections of a specific customer by id
@@ -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

@@ -136,8 +136,24 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
// types
if ($type == 'A' && filter_var($content, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) {
$errors[] = $this->lng['error']['dns_arec_noipv4'];
} elseif ($type == 'A') {
// check whether there is a CNAME-record for the same resource
foreach ($dom_entries as $existing_entries) {
if ($existing_entries['type'] == 'CNAME' && $existing_entries['record'] == $record) {
$errors[] = $this->lng['error']['dns_other_nomorerr'];
break;
}
}
} elseif ($type == 'AAAA' && filter_var($content, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
$errors[] = $this->lng['error']['dns_aaaarec_noipv6'];
} elseif ($type == 'AAAA') {
// check whether there is a CNAME-record for the same resource
foreach ($dom_entries as $existing_entries) {
if ($existing_entries['type'] == 'CNAME' && $existing_entries['record'] == $record) {
$errors[] = $this->lng['error']['dns_other_nomorerr'];
break;
}
}
} elseif ($type == 'CAA' && ! empty($content)) {
$re = '/(?\'critical\'\d)\h*(?\'type\'iodef|issue|issuewild)\h*(?\'value\'(?\'issuevalue\'"(?\'domain\'(?=.{3,128}$)(?>(?>[a-zA-Z0-9]+[a-zA-Z0-9-]*[a-zA-Z0-9]+|[a-zA-Z0-9]+)\.)*(?>[a-zA-Z]{2,}|[a-zA-Z0-9]{2,}\.[a-zA-Z]{2,}))[;\h]*(?\'parameters\'(?>[a-zA-Z0-9]{1,60}=[a-zA-Z0-9]{1,60}\h*)+)?")|(?\'iodefvalue\'"(?\'url\'(mailto:.*|http:\/\/.*|https:\/\/.*))"))/';
preg_match($re, $content, $matches);
@@ -198,6 +214,10 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$errors[] = $this->lng['error']['dns_mx_noalias'];
break;
}
elseif ($existing_entries['type'] == 'CNAME' && $existing_entries['record'] == $record) {
$errors[] = $this->lng['error']['dns_other_nomorerr'];
break;
}
}
}
// append trailing dot (again)
@@ -210,6 +230,14 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
}
if (! \Froxlor\Validate\Validate::validateDomain($content)) {
$errors[] = $this->lng['error']['dns_ns_invaliddom'];
} else {
// check whether there is a CNAME-record for the same resource
foreach ($dom_entries as $existing_entries) {
if ($existing_entries['type'] == 'CNAME' && $existing_entries['record'] == $record) {
$errors[] = $this->lng['error']['dns_other_nomorerr'];
break;
}
}
}
// append trailing dot (again)
$content .= '.';
@@ -308,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
@@ -514,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

@@ -77,7 +77,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
}
/**
* returns the total number of accessable domains
* returns the total number of accessible domains
*
* @access admin
* @throws \Exception
@@ -193,6 +193,27 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
return $ipandports;
}
/**
* get ips from array of id's
*
* @param array $ips
* @return array
*/
private function getIpsFromIdArray(array $ids)
{
$resultips_stmt = Database::prepare("
SELECT `ip` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE id = :id
");
$result = [];
foreach ($ids as $id) {
$entry = Database::pexecute_first($resultips_stmt, array(
'id' => $id
));
$result[] = $entry['ip'];
}
return $result;
}
/**
* add new domain entry
*
@@ -213,12 +234,12 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* @param bool $email_only
* optional, restrict domain to email usage, default 0 (false)
* @param int $selectserveralias
* optional, 0 = wildcard, 1 = www-alias, 2 = none, default 0
* optional, 0 = wildcard, 1 = www-alias, 2 = none, default [system.domaindefaultalias]
* @param bool $speciallogfile
* 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)
@@ -288,6 +309,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional list of allowed/used ssl/tls ciphers, see system.ssl_cipher_list setting, only used/required if $override_tls is true, default empty or system.ssl_cipher_list setting if $override_tls is true
* @param string $tlsv13_cipher_list
* optional list of allowed/used tls-1.3 specific ciphers, see system.tlsv13_cipher_list setting, only used/required if $override_tls is true, default empty or system.tlsv13_cipher_list setting if $override_tls is true
* @param string $description
* optional custom description (currently not used/shown in the frontend), default empty
*
* @access admin
* @throws \Exception
@@ -307,7 +330,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$subcanemaildomain = $this->getParam('subcanemaildomain', true, 0);
$isemaildomain = $this->getBoolParam('isemaildomain', true, 0);
$email_only = $this->getBoolParam('email_only', true, 0);
$serveraliasoption = $this->getParam('selectserveralias', true, 0);
$serveraliasoption = $this->getParam('selectserveralias', true, Settings::Get('system.domaindefaultalias'));
$speciallogfile = $this->getBoolParam('speciallogfile', true, 0);
$aliasdomain = intval($this->getParam('alias', true, 0));
$issubof = $this->getParam('issubof', true, 0);
@@ -354,6 +377,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$tlsv13_cipher_list = $this->getParam('tlsv13_cipher_list', true, Settings::Get('system.tlsv13_cipher_list'));
}
}
$description = $this->getParam('description', true, '');
// validation
$p_domain = strtolower($p_domain);
@@ -403,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',
@@ -430,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)) {
@@ -483,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();
}
@@ -571,6 +597,15 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$include_specialsettings = 0;
}
// validate dns if lets encrypt is enabled to check whether we can use it at all
if ($letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
$domain_ips = \Froxlor\PhpHelper::gethostbynamel6($domain);
$selected_ips = $this->getIpsFromIdArray($ssl_ipandports);
if ($domain_ips == false || count(array_intersect($selected_ips, $domain_ips)) <= 0) {
\Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true);
}
}
// We can't enable let's encrypt for wildcard-domains
if ($serveraliasoption == '0' && $letsencrypt == '1') {
\Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true);
@@ -728,7 +763,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
'tlsv13_cipher_list' => $tlsv13_cipher_list,
'sslenabled' => $sslenabled,
'honorcipherorder' => $honorcipherorder,
'sessiontickets' => $sessiontickets
'sessiontickets' => $sessiontickets,
'description' => $description
);
$ins_stmt = Database::prepare("
@@ -780,7 +816,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
`tlsv13_cipher_list` = :tlsv13_cipher_list,
`ssl_enabled` = :sslenabled,
`ssl_honorcipherorder` = :honorcipherorder,
`ssl_sessiontickets`= :sessiontickets
`ssl_sessiontickets` = :sessiontickets,
`description` = :description
");
Database::pexecute($ins_stmt, $ins_data, true, true);
$domainid = Database::lastInsertId();
@@ -820,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 . "'");
@@ -866,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)
@@ -932,6 +969,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional whether to honor the (server) cipher order for this domain. default 0 (false), requires SSL
* @param bool $sessiontickets
* optional whether to enable or disable TLS sessiontickets (RFC 5077) for this domain. default 1 (true), requires SSL
* @param string $description
* optional custom description (currently not used/shown in the frontend), default empty
*
* @access admin
* @throws \Exception
@@ -1027,6 +1066,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$ssl_cipher_list = $result['ssl_cipher_list'];
$tlsv13_cipher_list = $result['tlsv13_cipher_list'];
}
$description = $this->getParam('description', true, $result['description']);
// count subdomain usage of source-domain
$subdomains_stmt = Database::prepare("
@@ -1149,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') {
@@ -1163,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)) {
@@ -1229,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'];
}
@@ -1318,6 +1362,15 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$include_specialsettings = 0;
}
// validate dns if lets encrypt is enabled to check whether we can use it at all
if ($letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
$domain_ips = \Froxlor\PhpHelper::gethostbynamel6($result['domain']);
$selected_ips = $this->getIpsFromIdArray($ssl_ipandports);
if ($domain_ips == false || count(array_intersect($selected_ips, $domain_ips)) <= 0) {
\Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true);
}
}
// We can't enable let's encrypt for wildcard-domains
if ($serveraliasoption == '0' && $letsencrypt == '1') {
\Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true);
@@ -1411,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') {
@@ -1420,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') {
@@ -1453,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 = '';
@@ -1589,6 +1642,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$update_data['sslenabled'] = $sslenabled;
$update_data['honorcipherorder'] = $honorcipherorder;
$update_data['sessiontickets'] = $sessiontickets;
$update_data['description'] = $description;
$update_data['id'] = $id;
$update_stmt = Database::prepare("
@@ -1634,7 +1688,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
`tlsv13_cipher_list` = :tlsv13_cipher_list,
`ssl_enabled` = :sslenabled,
`ssl_honorcipherorder` = :honorcipherorder,
`ssl_sessiontickets` = :sessiontickets
`ssl_sessiontickets` = :sessiontickets,
`description` = :description
WHERE `id` = :id
");
Database::pexecute($update_stmt, $update_data, true, true);
@@ -1692,9 +1747,6 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
");
Database::pexecute($_update_stmt, $_update_data, true, true);
// insert a rebuild-task
\Froxlor\System\Cronjob::inserttask('1');
// Cleanup domain <-> ip mapping
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :id
@@ -1932,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

@@ -100,7 +100,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
// alternative email address to send info to
if (Settings::Get('panel.sendalternativemail') == 1) {
$alternative_email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($alternative_email, 'alternative_email', '', '', array(), true));
if (!empty($alternative_email) && ! \Froxlor\Validate\Validate::validateEmail($alternative_email)) {
if (! empty($alternative_email) && ! \Froxlor\Validate\Validate::validateEmail($alternative_email)) {
\Froxlor\UI\Response::standard_error('alternativeemailiswrong', $alternative_email, true);
}
} else {
@@ -192,11 +192,12 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
$replace_arr = array(
'EMAIL' => $email_full,
'USERNAME' => $username,
'PASSWORD' => $password,
'PASSWORD' => htmlentities(htmlentities($password)),
'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($customer),
'NAME' => $customer['name'],
'FIRSTNAME' => $customer['firstname'],
'COMPANY' => $customer['company'],
'USERNAME' => $customer['loginname'],
'CUSTOMER_NO' => $customer['customernumber']
);
@@ -236,7 +237,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
$this->mailer()->clearAddresses();
// customer wants to send the e-mail to an alternative email address too
if (Settings::Get('panel.sendalternativemail') == 1 && !empty($alternative_email)) {
if (Settings::Get('panel.sendalternativemail') == 1 && ! empty($alternative_email)) {
// get template for mail subject
$mail_subject = $this->getMailTemplate($customer, 'mails', 'pop_success_alternative_subject', $replace_arr, $this->lng['mails']['pop_success_alternative']['subject']);
// get template for mail body
@@ -302,6 +303,8 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
* optional, update quota
* @param string $email_password
* optional, update password
* @param bool $deactivated
* optional, admin-only
*
* @access admin, customer
* @throws \Exception
@@ -331,6 +334,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
$password = $this->getParam('email_password', true, '');
$quota = $this->getParam('email_quota', true, $result['quota']);
$deactivated = $this->getBoolParam('deactivated', true, (strtolower($result['postfix']) == 'n' ? true : false));
// get needed customer info to reduce the email-account-counter by one
$customer = $this->getCustomerData();
@@ -372,6 +376,18 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
$quota = 0;
}
if ($this->isAdmin()) {
if (($deactivated == true && strtolower($result['postfix']) == 'y') || ($deactivated == false && strtolower($result['postfix']) == 'n')) {
if (! empty($upd_query)) {
$upd_query .= ", ";
}
$upd_query .= "`postfix` = :postfix, `imap` = :imap, `pop3` = :pop3";
$upd_params['postfix'] = $deactivated ? 'N' : 'Y';
$upd_params['imap'] = $deactivated ? '0' : '1';
$upd_params['pop3'] = $deactivated ? '0' : '1';
}
}
// build update query
if (! empty($upd_query)) {
$upd_stmt = Database::prepare("
@@ -484,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

@@ -35,6 +35,8 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
* @param string $description
* optional custom description (currently not used/shown in the frontend), default empty
*
* @access admin, customer
* @throws \Exception
@@ -54,6 +56,8 @@ 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--') {
@@ -73,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) {
@@ -121,14 +128,18 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
`email` = :email,
`email_full` = :email_full,
`iscatchall` = :iscatchall,
`domainid` = :domainid
`disablegreylist` = :disablegreylist,
`domainid` = :domainid,
`description` = :description
");
$params = array(
"cid" => $customer['customerid'],
"email" => $email,
"email_full" => $email_full,
"iscatchall" => $iscatchall,
"domainid" => $domain_check['id']
"disablegreylist" => $disablegreylist,
"domainid" => $domain_check['id'],
"description" => $description
);
Database::pexecute($stmt, $params, true, true);
@@ -167,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`, u.`quota`
$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) . ")
@@ -195,6 +206,8 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, required when called as admin (if $customerid is not specified)
* @param boolean $iscatchall
* optional
* @param string $description
* optional custom description (currently not used/shown in the frontend), default empty
*
* @access admin, customer
* @throws \Exception
@@ -227,7 +240,8 @@ 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();
@@ -256,12 +270,13 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$stmt = Database::prepare("
UPDATE `" . TABLE_MAIL_VIRTUAL . "`
SET `email` = :email , `iscatchall` = :caflag
SET `email` = :email , `iscatchall` = :caflag, `description` = :description
WHERE `customerid`= :cid AND `id`= :id
");
$params = array(
"email" => $email,
"caflag" => $iscatchall,
"description" => $description,
"cid" => $customer['customerid'],
"id" => $id
);
@@ -273,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
*
@@ -300,7 +405,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$result = array();
$query_fields = array();
$result_stmt = Database::prepare("
SELECT m.`id`, m.`domainid`, m.`email`, m.`email_full`, m.`iscatchall`, u.`quota`, m.`destination`, m.`popaccountid`, d.`domain`, u.`mboxsize`
SELECT m.`id`, m.`domainid`, m.`email`, m.`email_full`, m.`iscatchall`, m.`destination`, m.`popaccountid`, d.`domain`, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize`
FROM `" . TABLE_MAIL_VIRTUAL . "` m
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON (m.`domainid` = d.`id`)
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON (m.`popaccountid` = u.`id`)
@@ -317,7 +422,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
}
/**
* returns the total number of accessable email addresses
* returns the total number of accessible email addresses
*
* @param int $customerid
* optional, admin-only, select email addresses of a specific customer by id

View File

@@ -79,7 +79,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
}
/**
* returns the total number of accessable fpm daemons
* returns the total number of accessible fpm daemons
*
* @access admin
* @throws \Exception
@@ -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

@@ -62,7 +62,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
if (($this->getUserDetail('ftps_used') < $this->getUserDetail('ftps') || $this->getUserDetail('ftps') == '-1') || $this->isAdmin() && $is_defaultuser == 1) {
// required paramters
// required parameters
$path = $this->getParam('path');
$password = $this->getParam('ftp_password');
@@ -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,9 +243,10 @@ 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' => $password,
'USR_PASS' => htmlentities(htmlentities($password)),
'USR_PATH' => \Froxlor\FileDir::makeCorrectDir(str_replace($customer['documentroot'], "/", $path))
);
// get template for mail subject
@@ -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 . "`
@@ -512,7 +513,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
}
/**
* returns the total number of accessable ftp accounts
* returns the total number of accessible ftp accounts
*
* @param int $customerid
* optional, admin-only, select ftp-users of a specific customer by id
@@ -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

@@ -66,7 +66,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
}
/**
* returns the total number of accessable hosting plans
* returns the total number of accessible hosting plans
*
* @access admin
* @throws \Exception
@@ -182,9 +182,9 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
* @param bool $perlenabled
* optional, whether to allow usage of Perl/CGI, default 0 (false)
* @param bool $dnsenabled
* optional, ether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false)
* optional, whether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false)
* @param bool $logviewenabled
* optional, ether to allow acccess to webserver access/error-logs, default 0 (false)
* optional, whether to allow access to webserver access/error-logs, default 0 (false)
*
* @access admin
* @throws \Exception
@@ -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;
@@ -309,9 +309,9 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
* @param bool $perlenabled
* optional, whether to allow usage of Perl/CGI, default 0 (false)
* @param bool $dnsenabled
* optional, ether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false)
* optional, either to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false)
* @param bool $logviewenabled
* optional, ether to allow acccess to webserver access/error-logs, default 0 (false)
* optional, either to allow access to webserver access/error-logs, default 0 (false)
*
* @access admin
* @throws \Exception
@@ -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

@@ -65,7 +65,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
}
/**
* returns the total number of accessable ip/port entries
* returns the total number of accessible ip/port entries
*
* @access admin
* @throws \Exception
@@ -247,6 +247,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$docroot = '';
}
// always use compressed ipv6 format
$ip = inet_ntop(inet_pton($ip));
$result_checkfordouble_stmt = Database::prepare("
SELECT `id` FROM `" . TABLE_PANEL_IPSANDPORTS . "`
WHERE `ip` = :ip AND `port` = :port");
@@ -295,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 . ']';
@@ -375,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) {
@@ -386,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;
@@ -462,6 +465,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$docroot = '';
}
// always use compressed ipv6 format
$ip = inet_ntop(inet_pton($ip));
if ($result['ip'] != $ip && $result['ip'] == Settings::Get('system.ipaddress') && $result_sameipotherport == false) {
\Froxlor\UI\Response::standard_error('cantchangesystemip', '', true);
} elseif ($result_checkfordouble && $result_checkfordouble['id'] != '' && $result_checkfordouble['id'] != $id) {
@@ -505,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 . "'");
@@ -578,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;
@@ -17,7 +18,7 @@ use Froxlor\Settings;
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*
*/
class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity
{
@@ -31,63 +32,75 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, default is 0
* @param string $description
* optional, description for database
* @param string $custom_suffix
* optional, name for database
* @param bool $sendinfomail
* optional, send created resource-information to customer, default: false
* @param int $customerid
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
*
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
*/
public function add()
{
// required paramters
$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, '');
$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);
// 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);
if (! isset($sql_root) || ! is_array($sql_root)) {
throw new \Exception("Database server with index #" . $dbserver . " is unknown", 404);
}
// 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;
}
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());
$username = $dbm->createDatabase($newdb_params['loginname'], $password, $newdb_params['mysql_lastaccountnumber']);
$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());
// we've checked against the password in dbm->createDatabase
if ($username == false) {
\Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', 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']);
}
// add database info to froxlor
$stmt = Database::prepare("
// 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,
@@ -95,81 +108,84 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
`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'],
'CUSTOMER_NO' => $userinfo['customernumber'],
'DB_NAME' => $username,
'DB_PASS' => $password,
'DB_DESC' => $databasedescription,
'DB_SRV' => $sql_root['host'],
'PMA_URI' => $pma
$params = array(
"customerid" => $customer['customerid'],
"databasename" => $username,
"description" => $databasedescription,
"dbserver" => $dbserver
);
Database::pexecute($stmt, $params, true, true);
$databaseid = Database::lastInsertId();
$params['id'] = $databaseid;
// 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']);
// update customer usage
Customers::increaseUsage($customer['customerid'], 'mysqls_used');
Customers::increaseUsage($customer['customerid'], 'mysql_lastaccountnumber');
$_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;
// 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 . "'");
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();
$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);
}
/**
@@ -181,7 +197,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, the databasename
* @param int $mysql_server
* optional, specify database-server, default is none
*
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
@@ -191,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) {
@@ -281,7 +297,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
*
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
@@ -291,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')) {
@@ -305,13 +321,13 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
));
$id = $result['id'];
// paramters
// parameters
$password = $this->getParam('mysql_password', true, '');
$databasedescription = $this->getParam('description', true, $result['description']);
// 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
@@ -370,7 +386,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array count|list
@@ -378,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("
@@ -428,13 +444,13 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
}
/**
* returns the total number of accessable databases
* returns the total number of accessible databases
*
* @param int $customerid
* optional, admin-only, select dbs of a specific customer by id
* @param string $loginname
* optional, admin-only, select dbs of a specific customer by loginname
*
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
@@ -465,7 +481,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
*
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
@@ -475,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

@@ -59,7 +59,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
);
$query = "SELECT * FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `phpsettingid` = :id";
WHERE `phpsettingid` = :id AND `email_only` = '0' AND `phpenabled` = '1'";
if (! $with_subdomains) {
$query .= " AND `parentdomainid` = '0'";
@@ -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');
}
@@ -122,7 +122,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
}
/**
* returns the total number of accessable php-setting entries
* returns the total number of accessible php-setting entries
*
* @access admin
* @throws \Exception
@@ -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

@@ -2,6 +2,7 @@
namespace Froxlor\Api\Commands;
use Froxlor\Database\Database;
use Froxlor\Domain\Domain;
use Froxlor\Settings;
/**
@@ -230,6 +231,15 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
}
}
// validate dns if lets encrypt is enabled to check whether we can use it at all
if ($letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
$our_ips = Domain::getIpsOfDomain($domain_check['id']);
$domain_ips = \Froxlor\PhpHelper::gethostbynamel6($completedomain);
if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) {
\Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true);
}
}
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
if ($ssl_redirect > 0 && $letsencrypt == 1) {
$ssl_redirect = 2;
@@ -252,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
@@ -336,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');
@@ -595,9 +618,18 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
}
}
// validate dns if lets encrypt is enabled to check whether we can use it at all
if ($result['letsencrypt'] != $letsencrypt && $letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
$our_ips = Domain::getIpsOfDomain($result['parentdomainid']);
$domain_ips = \Froxlor\PhpHelper::gethostbynamel6($result['domain']);
if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) {
\Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true);
}
}
// 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
@@ -619,12 +651,25 @@ 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);
}
if ($path != $result['documentroot'] || $isemaildomain != $result['isemaildomain'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $aliasdomain != $result['aliasdomain'] || $openbasedir_path != $result['openbasedir_path'] || $ssl_redirect != $result['ssl_redirect'] || $letsencrypt != $result['letsencrypt'] || $hsts_maxage != $result['hsts'] || $hsts_sub != $result['hsts_sub'] || $hsts_preload != $result['hsts_preload'] || $phpsettingid != $result['phpsettingid']) {
if ($path != $result['documentroot'] || $isemaildomain != $result['isemaildomain'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $aliasdomain != (int)$result['aliasdomain'] || $openbasedir_path != $result['openbasedir_path'] || $ssl_redirect != $result['ssl_redirect'] || $letsencrypt != $result['letsencrypt'] || $hsts_maxage != $result['hsts'] || $hsts_sub != $result['hsts_sub'] || $hsts_preload != $result['hsts_preload'] || $phpsettingid != $result['phpsettingid']) {
$stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET
`documentroot` = :documentroot,
@@ -688,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']) . "'");
}
@@ -810,7 +855,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
}
/**
* returns the total number of accessable subdomain entries
* returns the total number of accessible subdomain entries
*
* @param int $customerid
* optional, admin-only, select (sub)domains of a specific customer by id
@@ -974,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];
}
}
@@ -150,7 +150,7 @@ abstract class BulkAction
/**
* reads in the csv import file and returns an array with
* all the entites to be imported
* all the entities to be imported
*
* @param string $separator
*

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'),
@@ -402,7 +431,7 @@ class ConfigServicesAction extends \Froxlor\Cli\Action
} 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 direcotry cannot be read ('" . $this->_args["froxlor-dir"] . "')");
throw new \Exception("Given froxlor directory cannot be read ('" . $this->_args["froxlor-dir"] . "')");
}
}
}

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"] . "')");
}
}
}
}

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