Compare commits

...

225 Commits

Author SHA1 Message Date
Michael Kaufmann
6cd061d74c set version to 0.10.4 for upcoming maintenance release; minor code formatting + adjustments
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-01 11:16:13 +01:00
Michael Kaufmann
53b7420dc9 fix stripping of escape-sequences in api-endpoint; fixes #746
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-01 07:39:28 +01:00
Michael Kaufmann
aa85c648a3 check for renewal of certificates not only if there's a task to regenerate vhosts but everytime the letsencrypt cronjob runs (which is basically obsolete due to the integration into the tasks cron but perfect for checking renewal dates
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-31 21:37:54 +01:00
Michael Kaufmann
35e228ff09 Merge pull request #745 from pquerner/unittests/564
Add UnitTests for #679
2019-10-30 13:01:02 +01:00
Pascal
62236da496 changed method name 2019-10-30 12:50:16 +01:00
Pascal
e1cc896b6c add unit tests for Validate::is_ipv6 2019-10-30 12:39:56 +01:00
Pascal
36595baa65 Merge remote-tracking branch 'Froxlor/master' 2019-10-30 12:14:39 +01:00
Michael Kaufmann
ec3fd1d105 Create SECURITY.md 2019-10-30 11:00:08 +01:00
Michael Kaufmann
e39dcfbfe2 Update FUNDING.yml 2019-10-30 10:50:20 +01:00
Michael Kaufmann
ef6254b307 Merge pull request #679 from pquerner/#564
Allow CIDR and Netmask in mysql_host_access; fixes #564
2019-10-30 10:40:26 +01:00
Michael Kaufmann
44bf211ab5 Merge pull request #743 from kionez/fix_split_path_info
Correct fastcgi_split_path_info; fixes #744
2019-10-29 16:09:44 +01:00
kionez
b0e920104f Fix fastcgi_split_path_info as https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/ 2019-10-29 16:00:14 +01:00
kionez
299e201142 Fix fastcgi_split_path_info 2019-10-29 15:47:28 +01:00
Michael Kaufmann
46982ad2dc validate that a customer gets the default ftp account created even if the admin/reseller has no more resource for ftp accounts; fixes #741
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-29 07:52:00 +01:00
Michael Kaufmann
c0e07fd659 fix undefined variable in hosting-plans frontend, fixes #742
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-28 20:06:14 +01:00
Pascal
5c11eecbd7 remove code for checking ipv6 mapped ipv4 notation 2019-10-28 17:27:39 +01:00
Pascal
9689afc759 change method signature of \Froxlor\Validate\Validate::validate_ip2 2019-10-28 16:58:34 +01:00
Pascal
d76f4108e5 dont need $result if we're expecting an exception 2019-10-28 16:40:22 +01:00
Pascal
9c4d619840 remove inner if statement
check ipv6 when cidr>netmask flag is set
2019-10-28 16:32:52 +01:00
Pascal
7774e7606d dont check notated ips again 2019-10-28 16:29:53 +01:00
Pascal
2ed0cad27b #564:
cidr notation can only be 1 through 32
2019-10-28 16:27:54 +01:00
Pascal
686c2ae534 fix comparison 2019-10-28 16:00:43 +01:00
Pascal
faf3abe800 introduce new parameter to allow automatic convert cidr notation to netmask notation 2019-10-28 15:33:26 +01:00
Pascal
220b493a1b better readability 2019-10-28 14:16:27 +01:00
Pascal
e8d67f9711 check if ipv6 first 2019-10-28 14:07:31 +01:00
Pascal
83e932b068 switch join with implode 2019-10-28 13:26:32 +01:00
Pascal
84d1be538e block ipv6 addresses in cidr notation (mysql can't handle it) 2019-10-28 13:25:34 +01:00
Pascal
c97cdb1c0e make it more readable 2019-10-28 13:15:48 +01:00
Pascal
ffefe85fb4 Merge branch 'master' into #564 2019-10-28 12:18:55 +01:00
Pascal
27341ca490 Merge remote-tracking branch 'Froxlor/master' 2019-10-28 12:17:51 +01:00
Michael Kaufmann
822bb2bd4d fixed deletion of default-ftp-user possible via API (not through the interface though); refs #741
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-27 16:02:32 +01:00
Michael Kaufmann
88ee76e4c9 setting version to 0.10.3 for upcoming release
Signed-off-by: Michael Kaufmann <michael.kaufmann@aixit.com>
2019-10-25 14:48:13 +02:00
Michael Kaufmann
90d921ebb5 preserve downward compatibility for 0.10.1 updaters regarding specialsettings for ssl-enabled domains; fixes #739
Signed-off-by: Michael Kaufmann <michael.kaufmann@aixit.com>
2019-10-24 18:14:51 +02:00
Michael Kaufmann
7b162c4bd0 added tls-settings per domain for admins with change_serversettings-flag set; fixes #519
Signed-off-by: Michael Kaufmann <michael.kaufmann@aixit.com>
2019-10-22 16:45:03 +02:00
Michael Kaufmann
32e2d48aed fallback to /tmp/froxlor.log if file-log is activated but no file given or not writeable; fixes #737
Signed-off-by: Michael Kaufmann <michael.kaufmann@aixit.com>
2019-10-22 15:06:41 +02:00
Michael Kaufmann
1fdc524171 correct permissions
Signed-off-by: Michael Kaufmann <michael.kaufmann@aixit.com>
2019-10-19 11:08:55 +02:00
Michael Kaufmann
4704798379 setting version to 0.10.2 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <michael.kaufmann@aixit.com>
2019-10-18 13:39:23 +02:00
Michael Kaufmann
e5c1e8350d set default_theme value in settings-array to 'Sparkle' as it is in install/froxlor.sql; improve language strings for adding php-configurations and fpm-versions
Signed-off-by: Michael Kaufmann <michael.kaufmann@aixit.com>
2019-10-17 18:40:53 +02:00
Michael Kaufmann
f0b36c03ad fix registration and termination date to flip between empty-value and 0000-00-00, thx to dxd
Signed-off-by: Michael Kaufmann <michael.kaufmann@aixit.com>
2019-10-17 09:35:33 +02:00
Michael Kaufmann
79056f20ee display API in the list of features the customer is allowed to use; display total diskspace used by customer (web, mail and mysql) on customers dashboard, fixes #733
Signed-off-by: Michael Kaufmann <michael.kaufmann@aixit.com>
2019-10-16 12:44:23 +02:00
Michael Kaufmann
5d6aa4d2bb Merge pull request #732 from TimoStramann/patch-1
fixing typo
2019-10-16 06:32:13 +02:00
Timo Stramann
f803276ca2 fixing typo
wrong variable name
2019-10-16 00:11:30 +02:00
Michael Kaufmann
5cf2d32e8a reverse parameter for Domains.add() into so users have to explicitly pass the parameter if they do NOT want the default ssl-ip to be used if left empty, so it behaves like the non-ssl ipandport parameter - if left empty, the system default is being used, thx J-BBB
Signed-off-by: Michael Kaufmann <michael.kaufmann@aixit.com>
2019-10-15 14:35:42 +02:00
Michael Kaufmann
9430f77c2e Setting system.leapiversion exists and just needs to be updated, no added
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-15 07:22:41 +02:00
Michael Kaufmann
302fe994b7 adjust ip/port settings for downward compatibility when adding new ssl-specialsettings related settings
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-14 14:26:13 +02:00
Michael Kaufmann
9b122bc003 order tasks by type descending to create bind and webserver configs at the end of the run; cleanUp configs files after creation of certificates to minimize downtime, thx to SCD for testing
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-14 13:56:55 +02:00
Michael Kaufmann
9410356bc7 fix output of acme command when upgrading
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-14 10:12:26 +02:00
Michael Kaufmann
5d5cc3dda3 fix array to string conversion
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-13 22:49:03 +02:00
Michael Kaufmann
a7ccb7007f add Unit-test for DomainZones.listing()
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-13 14:47:39 +02:00
Michael Kaufmann
5680c88da0 implement DomainZones.listing() to actually return custom stored dns entries for a given domain, fixes #731
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-13 14:40:04 +02:00
Michael Kaufmann
cf01a587c7 fix typo in updater
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-12 14:53:13 +02:00
Michael Kaufmann
b6367e1be1 forgot to add the ssl-default-vhostconf-domain fields in ipsandports
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-12 14:39:58 +02:00
Michael Kaufmann
93aa8bff1e add default-ssl-vhost settings and optionally allow including of non-ssl default-vhost settings, fixes #727
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-12 14:34:18 +02:00
Michael Kaufmann
15fa035dc4 check for minimum required php version in autoupdater
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-12 14:04:43 +02:00
Michael Kaufmann
057f4aaa10 Passing the and parameters in reverse order to implode has been deprecated since PHP 7.4
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-12 10:22:11 +02:00
Michael Kaufmann
f588927bc5 check for existence of certificate files created by acme.sh
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-12 08:17:04 +02:00
Michael Kaufmann
03d2a76dd0 clean up language and code for dropped let's encrypt ACMEv1 support
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-11 20:53:34 +02:00
Michael Kaufmann
0d0e557715 force Let's Encrypt ACMEv2 API, fixed #728
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-11 18:17:05 +02:00
Michael Kaufmann
fb54b887f2 remove unneeded apihelp-page code in admin/customer_index; set explicit version to api-doc URL; check for acme.sh cronjob and uninstall it, as froxlor manages that itself
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-10 16:42:32 +02:00
Michael Kaufmann
9167608794 set version to 0.10.1 for maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-10 14:55:45 +02:00
Michael Kaufmann
050af61082 show success in updater when there are no more old files to delete and exec() is disallowed (showed empty list)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-09 12:05:04 +02:00
Michael Kaufmann
2c23431daf show on API keys page wether api access is allowed
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-09 11:52:55 +02:00
Michael Kaufmann
4543c73b4f add possibility to enable/disable api access on a per user base
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-09 11:43:22 +02:00
Michael Kaufmann
88d85fc02e fix curly bracket array access (deprecated)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-09 07:59:38 +02:00
Michael Kaufmann
6102fabcb6 allow setting http2 flag for (sub)domains in customer view, fixes #725
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-09 07:59:11 +02:00
Michael Kaufmann
d7a7412973 Merge pull request #724 from kionez/add-ssl-expirationdate
Add expiration date to SSL certificates loaded via API request, fixes #723
2019-10-08 18:59:27 +02:00
kionez
1b3029b826 Fix typo 2019-10-08 18:50:10 +02:00
Michael Kaufmann
26cb53c8fb correctly validate that a domain has not a certificate in Certificates.add(), refs #722
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-08 18:44:42 +02:00
Michael Kaufmann
b4999fcc83 Throw exception if domain used to call Certificates.get() does not have a certificate, fixes #722
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-08 18:01:59 +02:00
kionez
05f602d457 Fix for null expiration date and coding style 2019-10-08 17:44:41 +02:00
Michael Kaufmann
89b95d61d2 return empty array in FroxlorAPI.php example class if last call was unsuccessful, fixes #722
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-08 17:36:42 +02:00
kionez
9ec03bade7 Add expiration date to SSL certificates loaded via API request 2019-10-08 17:32:03 +02:00
Michael Kaufmann
20699a15a6 update composer dependencies
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-08 12:54:15 +02:00
Michael Kaufmann
9b8a6e7e67 more php-7.4 compatibility
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-08 12:38:22 +02:00
Michael Kaufmann
3a8d5a9517 correct Mysql.add phpDoc to produce correct api-doc, fixes #721
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-08 12:11:00 +02:00
Michael Kaufmann
557b28a69d more php-7.4 compatibility
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-08 12:08:36 +02:00
Michael Kaufmann
0f1c5506e2 do not create username@domain ftp user if the default-ftp-user is being created in Ftps.add, fixes #720
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-08 12:04:10 +02:00
Michael Kaufmann
c6a93fa336 fix possible php-7.4 notice 'Trying to access array offset on value of type bool'
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-08 11:26:05 +02:00
Michael Kaufmann
466ea0fa99 show update steps for version updates (forgot that once or twice); add fallback for file deletion if exec() is not allowed; fix php7.4 warnings
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-08 10:54:08 +02:00
Michael Kaufmann
8f850ee7f3 simplify config-templates for cronjob setup
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-06 22:54:54 +02:00
Michael Kaufmann
55d21e475d set low timeout for version-check and output message if check is not possible (due to connection error, downtime of server, etc.)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-06 18:53:30 +02:00
Michael Kaufmann
fa3e3da7ac only flush privileges if anything at all happened
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-06 14:47:04 +02:00
Michael Kaufmann
05d66c034e update min-required version of php in composer.json
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-06 09:04:18 +02:00
Michael Kaufmann
98f0839664 Merge branch 'master' of github.com:Froxlor/Froxlor 2019-10-06 09:01:15 +02:00
Michael Kaufmann
4d52c6b6d0 Update README.md 2019-10-04 21:48:10 +02:00
Michael Kaufmann
eb5ea51da1 add explicit tlsv1.3 ciphersuite setting (used for apache-only as of now) 2019-10-04 17:43:11 +02:00
Michael Kaufmann
4b555b4ef2 set version to 0.10.0 for upcoming stable release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-03 12:35:42 +02:00
Michael Kaufmann
1657af8719 updating external libraries prior to release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-03 12:31:27 +02:00
Michael Kaufmann
c9d30654e0 update link to openssl-ciphers manual, thx to lod
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-10-02 09:12:06 +02:00
Michael Kaufmann
47ca350127 increase php requirement to 7.0 as 5.6 is way too old
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-09-27 12:55:14 +02:00
Michael Kaufmann
cc04e44031 add possibility to add customer using a hosting-plan instead of specifying resources
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-09-27 12:54:43 +02:00
Michael Kaufmann
eabad4917b correct try_files in NginxFcgi, fixes #717
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-09-26 09:50:13 +02:00
Michael Kaufmann
6188e5b0e3 Merge pull request #716 from Bobselp/patch-1
fix MysqlHandler user field
2019-09-25 20:18:22 +02:00
Bobselp
13ab7a598b fix MysqlHandler user field
See lib/Froxlor/FroxlorLogger.php:152
2019-09-25 20:03:16 +02:00
Michael Kaufmann
bf2584da65 Merge pull request #714 from Bobselp/patch-1
Get mailbox size with maildirsize file
2019-09-24 19:16:58 +02:00
Bobselp
31cebccd5d fix calc, add check if quota is enabled 2019-09-24 18:16:07 +02:00
Michael Kaufmann
3728e9b22c Merge pull request #715 from z3dm4n/master
lng/english.lng.php: fix typo
2019-09-24 12:55:45 +02:00
Erik Zettel
8a145eca92 lng/english.lng.php: fix typo 2019-09-24 12:44:33 +02:00
Bobselp
14914fce44 Get mailbox size with maildirsize file 2019-09-23 21:08:16 +02:00
Michael Kaufmann
6e3fdc1cf9 Merge pull request #713 from Bobselp/patch-1
fix missing namespaces in PowerDNS cron
2019-09-22 18:05:48 +02:00
Bobselp
6ca68f6a2d fix missing namespaces in PowerDNS cron
Some getDB calls were missing the `\Froxlor\Dns\` prefix
2019-09-22 17:59:21 +02:00
Michael Kaufmann
fd4d3cbcfd specify pop3_logout_format explicitly for dovecot to satisfy maillogparser
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-09-19 13:06:32 +02:00
Michael Kaufmann
75f49e2ee2 added HostingPlans ApiCommand + unit-tests
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-09-16 12:31:02 +02:00
Michael Kaufmann
aca22a9c94 only add lets encrypt certificate if cert is valid; display acme.sh output if --debug is specified
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-09-15 15:40:13 +02:00
Michael Kaufmann
5a8ae0f75f do not log multiple times due to pushing log-handlers multiple times
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-09-15 13:49:40 +02:00
Michael Kaufmann
6ef2be8c1a fixed typo
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-09-15 13:42:32 +02:00
Michael Kaufmann
1b968c885b remove old files from 0.9.x to avoid conflicts and errors; change mod_proxy-usage and ACMEv2 default values to true
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-09-15 10:28:19 +02:00
Michael Kaufmann
dc3f159c90 correctly trigger re-generation of let's encrypt certificates
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-09-15 10:22:25 +02:00
Michael Kaufmann
6ebb8dabc4 re-create certificate if SAN list or domain changes
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-09-12 12:30:47 +02:00
Michael Kaufmann
9e2dcf51d7 also remove let's encrypt certificate for froxlor-hostname when updating to acme.sh; make installation more mysql/mariadb compatible
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-09-09 17:16:41 +02:00
Michael Kaufmann
2d8b0181b3 add gitter notifications for travis-ci
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-08-22 16:20:42 +02:00
Michael Kaufmann
accd6e7416 Update README.md 2019-08-22 16:15:17 +02:00
Michael Kaufmann
f5027695dd Create FUNDING.yml 2019-08-22 15:45:00 +02:00
Michael Kaufmann
34696df700 Merge pull request #711 from TimoStramann/patch-1
Remove unnecessary slash for SSL redirect
2019-08-18 16:15:50 +02:00
Timo Stramann
8e9ddd3d50 Remove unnecessary slash for SSL redirect
Remove slash after hostname since requests directly to the hostname do not require a slash at the end and all other content goes to `$request_uri` which starts with shlash, hence no longer doubleslashes on hostname only queries.
2019-08-18 16:07:59 +02:00
Michael Kaufmann
eca941bdae Merge pull request #710 from TimoStramann/patch-1
Updating another fastcgi_param SCRIPT_FILENAME
2019-08-18 15:19:42 +02:00
Timo Stramann
bd6aba8875 Updating another fastcgi_param SCRIPT_FILENAME
Use $request_filename instead of $document_root$fastcgi_script_name as described in: https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#use-request-filename-for-script-filename
2019-08-17 13:04:18 +02:00
Michael Kaufmann
58f6b558df Merge pull request #709 from TimoStramann/patch-1
Updating fastcgi_param SCRIPT_FILENAME
2019-08-17 07:51:12 +02:00
Michael Kaufmann
7ba72269a4 add dovecot stats service and use correct permissions
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-08-11 11:12:53 +02:00
Michael Kaufmann
76c4486d26 fix subcanemaildomain parameter for Domains.update(); allow exec() in froxlor default vhost php.ini or logfiles-viewer feature
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-08-11 10:31:33 +02:00
Michael Kaufmann
69d7889f02 do not require codecoverage to pass checks
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-08-09 17:55:39 +02:00
Timo Stramann
04898c6114 Updating fastcgi_param
Use $request_filename instead of $document_root$fastcgi_script_name as described in: https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#use-request-filename-for-script-filename
2019-08-09 09:40:55 +02:00
Michael Kaufmann
7364dca53d fix homedir of automatically added ftp-user for new customers, thx Gamerboy59 for finding this
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-08-07 14:01:05 +02:00
Michael Kaufmann
90e7f7af0c correct language-array and minor formatting in serversettings.caa_entry_custom
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-30 10:05:26 +02:00
Michael Kaufmann
878be08563 Merge pull request #706 from makuser/master
Implement CAA DNS records
2019-07-30 09:53:46 +02:00
Michael Kaufmann
a98ae562b2 change mysql-username-test so it generates a loginname that fails depending on the mysql/mariadb version
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-30 08:48:44 +02:00
Michael Kaufmann
2aec6a10ed argh, mixed up the If statement for mysql-version check
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-30 08:31:03 +02:00
Michael Kaufmann
70ac914a86 fix drop database on mysql-5.6 as there is no 'if exists' for 'drop user' prior to mysql-5.7
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-30 07:34:42 +02:00
Michael Kaufmann
169353c429 Merge branch 'makuser-travis-test' 2019-07-30 07:30:56 +02:00
Marc-André Kolly
ede19946c2 Tell ant to fail the build when a php unit test fails 2019-07-29 16:29:39 +02:00
Marc-André Kolly
dd488106af Remove lib/userdata.inc.php.bak 2019-07-29 16:09:11 +02:00
Marc-André Kolly
2489658353 Extrawurst 2.0. 2019-07-29 16:03:27 +02:00
Marc-André Kolly
61b12e3f25 Extrawurst. 2019-07-29 15:47:45 +02:00
Marc-André Kolly
c2ffb6d6bd Update Travis CI to run database tests on MySQL 5.6, 5.7 and 8.0 and on MariaDB 10.3 and 10.4. 2019-07-29 15:12:35 +02:00
Marc-André Kolly
4ef78df27f Update Travis CI 2019-07-29 15:07:18 +02:00
Marc-André Kolly
84d80d695a Add Url and Domain validation for CAA records using native Froxlor function 2019-07-29 15:02:13 +02:00
Marc-André Kolly
3cba61a8d8 Simplify unit tests for CAA entry validation 2019-07-29 14:30:39 +02:00
Marc-André Kolly
16ccc273a9 Don't actually enclose CAA records in brackets 2019-07-29 14:27:44 +02:00
Marc-André Kolly
95d47eb6c9 Add unit tests for CAA entry validation 2019-07-29 11:53:00 +02:00
Marc-André Kolly
bfb3fb0a92 Add Regex to check for invalid CAA entry 2019-07-29 11:36:34 +02:00
Marc-André Kolly
78ef2a4e23 Fix serversettings field 2019-07-29 07:41:09 +02:00
Marc-André Kolly
a377c1e6c5 Split l18n string into title and description 2019-07-29 07:39:21 +02:00
Marc-André Kolly
e67e2a85de Implement test for Domain Zone CAA record 2019-07-28 20:05:55 +02:00
Marc-André Kolly
be0470aec1 Revert per-domain CAA settings 2019-07-28 19:49:56 +02:00
Marc-André Kolly
240178eba7 Implement global CAA settings 2019-07-28 19:49:32 +02:00
Marc-André Kolly
358ca61a26 Implement validators to prevent breaking DNS server when adding newly introduced RR types 2019-07-28 18:47:47 +02:00
Marc-André Kolly
b427212b00 Properly implement migrations for caa field in TABLE_DOMAIN_DNS using showUpdateStep() and lastStepStatus() 2019-07-28 18:12:00 +02:00
Marc-André Kolly
5eef98fdfd Bump DB Version to 201907270 2019-07-28 18:10:01 +02:00
Marc-André Kolly
57ac337ef7 Add a few more commonly used RR types to DNS editor 2019-07-28 16:52:05 +02:00
Marc-André Kolly
64fe300e42 Implement general CAA DNS records for all issuers 2019-07-28 16:28:29 +02:00
Marc-André Kolly
d4e5e32c14 Implement CAA DNS record for letsencrypt.org 2019-07-27 17:36:31 +02:00
Michael Kaufmann
d5e4182878 beautification and minor fixes
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-26 07:49:17 +02:00
Michael Kaufmann
dd87a7374e fix ftp-group not added correctly when new customer is added
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-26 07:45:38 +02:00
Michael Kaufmann
7bc57ed269 set password directly when adding new mysql user
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-26 07:34:32 +02:00
Michael Kaufmann
5658717653 fix wrong parameter for acme.sh --delete when ecc certificates are used
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-19 11:43:14 +02:00
Michael Kaufmann
6c0fb007e4 travis changed the default OS to xenial, set it to the previous trusty which works
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-19 08:43:42 +02:00
Michael Kaufmann
0b898b9936 Merge branch 'master' of github.com:Froxlor/Froxlor 2019-07-19 08:42:31 +02:00
Michael Kaufmann
a261e84830 Merge pull request #705 from MDXDave/patch-2
Disable mail redirections if customer is disabled, fixes #704
2019-07-19 08:28:40 +02:00
Dave
7e9b373a58 Update xenial.xml 2019-07-19 01:43:07 +02:00
Dave
5698f8360e Update rhel_centos.xml 2019-07-19 01:42:49 +02:00
Dave
de7c438315 Update gentoo.xml 2019-07-19 01:42:31 +02:00
Dave
0669450676 Update bionic.xml 2019-07-19 01:42:14 +02:00
Dave
507a62f52d Update trusty.xml 2019-07-19 01:41:54 +02:00
Dave
77a7037072 Update jessie.xml 2019-07-19 01:41:24 +02:00
Dave
577e9d3b70 Update buster.xml 2019-07-19 01:40:55 +02:00
Dave
2526512069 Update stretch.xml 2019-07-19 01:39:01 +02:00
Michael Kaufmann
e91debcbb1 buster dovceot has ssl enabled by default
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-14 09:41:46 +02:00
Michael Kaufmann
065fa0b58b do not store punycode-notation of email-account domain, fixes #703
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-13 09:09:39 +02:00
Michael Kaufmann
db3c95ea10 set last run of letsencrypt cron when called in webserver-cron
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-11 08:39:26 +02:00
Michael Kaufmann
8b417c044c let nginx auto-detect the best ecdh-curve to use, fixes #652
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-11 08:13:00 +02:00
Michael Kaufmann
5e3cfaf847 insert task to regenerate config files after removing old-format lets encrypt certificates
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-10 09:58:12 +02:00
Michael Kaufmann
0f0dd91246 combine Let's Encrypt cron with webserver-vhost-generation but allow manually execution using --debug/--force
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-09 07:50:11 +02:00
Michael Kaufmann
fd912dd161 combine webserver-reload command to parent class to avoid repeating code
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-09 07:13:02 +02:00
Michael Kaufmann
98325a0f40 don't need NSCD when using libnss-extrausers
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-03 18:07:02 +02:00
Michael Kaufmann
c43915c09d show task 12 in admin dashboard overview if active
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-03 12:00:47 +02:00
Michael Kaufmann
01bf814496 remove domain ssl information from acme.sh and filesystem on deletion to avoid trying to renew certificates
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-07-01 20:32:13 +02:00
Michael Kaufmann
2ce517e84a use Fts.add when adding new Customers to reduce duplicate code
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-28 15:15:17 +02:00
Michael Kaufmann
e209989f2a use EmailAccounts.delete API call in Emails.delete instead of repeating the code
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-28 11:07:29 +02:00
Michael Kaufmann
5dfb74701c improve error message display on missing vendor-folder
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-25 11:10:32 +02:00
Michael Kaufmann
bdd583d251 Merge branch 'drexlma-patch-2' 2019-06-25 10:59:06 +02:00
Michael Kaufmann
fd8a1d8dc2 Merge branch 'patch-2' of https://github.com/drexlma/Froxlor into drexlma-patch-2 2019-06-25 10:58:57 +02:00
Michael Kaufmann
d2818f8020 Merge branch 'drexlma-patch-3' 2019-06-25 10:58:20 +02:00
Michael Kaufmann
80a0a34b46 Merge branch 'patch-3' of https://github.com/drexlma/Froxlor into drexlma-patch-3 2019-06-25 10:57:45 +02:00
Michael Kaufmann
6e41c0ad2c add codecov.io to travis build for code-coverage stats - yay
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-17 14:11:40 +02:00
Michael Kaufmann
a07a9e6a88 more unit-testing, enhancements in Store-functions
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-11 12:10:56 +02:00
Michael Kaufmann
7a94a43053 started \Settings\Store unit tests
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-10 13:37:22 +02:00
Michael Kaufmann
028524291e test improvements and preparation for more tests later
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-10 11:38:47 +02:00
Michael Kaufmann
1ac304e5ac fix missing domainname parameter when manually adding ssl-certificates for a domain, fixes #700
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-10 11:36:05 +02:00
Michael Kaufmann
f266bb05c9 testing \Froxlor\Settings\FroxlorVhostSettings
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-06 13:04:43 +02:00
Michael Kaufmann
d8a8f76dc9 update dev-environment to use more recent versions, requries php-7.3 now (dev-only)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-06 10:18:03 +02:00
Michael Kaufmann
0afbe3d13b add validation tests
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-05 20:52:37 +02:00
Michael Kaufmann
4917b9c057 added first validation tests
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-05 09:07:21 +02:00
Michael Kaufmann
13bfd62ac5 move validateUrl function to correct file
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-05 06:50:06 +02:00
Michael Kaufmann
97703e7a0c add a few tests for Settings
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-05 06:39:44 +02:00
Michael Kaufmann
13086d91d8 only validate and process ip-list if given at all
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-04 15:14:51 +02:00
Michael Kaufmann
b7a10fdeda fix vhost(parts)-merging in nginx cron, fixes #669
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-06-03 11:59:56 +02:00
Michael Kaufmann
6806f896d6 fix proftp path of rhel/centos config template, fixes #636
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-05-31 08:02:03 +02:00
Michael Kaufmann
87a2f86365 do not set default ssl-ips if the frontend values are left empty; if default ssl-ips are specified, preset them in the form when adding a domain, fixes #697
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-05-30 17:44:08 +02:00
Michael Kaufmann
a647d48fbe fix up testing/production switch and challengepath for lets encrypt, fixes #696
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-05-27 17:48:33 +02:00
Daniel Drexlmaier
6ea91f55e5 Update install.php 2019-05-27 15:47:30 +02:00
Daniel Drexlmaier
fb87129e29 Update init.php 2019-05-27 15:46:39 +02:00
Daniel Drexlmaier
79e5113e12 Update init.php 2019-05-27 15:28:08 +02:00
Daniel Drexlmaier
b75c9ddff6 Update install.php 2019-05-27 15:27:28 +02:00
Michael Kaufmann
35e14fde14 set version to 0.10.0-rc2 for second release candidate
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-05-27 11:47:58 +02:00
Michael Kaufmann
68f55f9596 dont allow bootstrap.php file from tests/ to be called via browser
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-05-27 08:33:36 +02:00
Michael Kaufmann
3fec579f85 Merge pull request #683 from discordier/hotfix/pcre-maillog
Fixes #682 - mail log parsing regex character group
2019-05-13 20:03:49 +02:00
Christian Schiffler
e2d69c664a Fixes #682 - mail log parsing regex character group
The mail log parsing regex was incorrectly using a character group of `\A`
2019-05-13 19:53:55 +02:00
Pascal
836b6f2fdb Merge remote-tracking branch 'upstream/master' 2019-05-10 02:54:33 +02:00
Michael Kaufmann
72016a5735 fix integrity-check language-file entries
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-05-07 14:03:37 +02:00
Pascal
f297058461 #564
fix wording
add validation for cidr syntax
add automatic transform of cidr to netmask for mysql
2019-05-04 00:39:12 +02:00
Pascal
0f4d8d76ae #564
fix wording
2019-05-03 23:31:31 +02:00
Pascal
12884c91a6 #564
fix #564 by allowing CIDR in mysql host validation. 
fix english and german field description accordingly
2019-05-03 22:32:57 +02:00
Michael Kaufmann
eba163fc4a Merge pull request #677 from pquerner/#646
allow auth basic in URL, fixes #646
2019-04-30 07:14:48 +02:00
Michael Kaufmann
8df6654ad0 Merge pull request #676 from pquerner/#675
use correct validate-ip function in \Froxlor\Validate\Validate::validateUrl, fixes #675
2019-04-30 07:09:20 +02:00
Pascal
1a5e43b6f7 fixes #646
change regex by using well tested regex from here:
https://mathiasbynens.be/demo/url-regex

by @diegoperini
https://gist.github.com/dperini/729294
2019-04-30 00:08:32 +02:00
Pascal
c4c7f4b636 fixes #675
fix call to static method
2019-04-29 23:39:10 +02:00
Michael Kaufmann
9aa0de16be Merge branch 'foliengriller-annotationsAPI' 2019-04-26 12:24:15 +02:00
Michael Kaufmann
cb636fe2c9 Merge branch 'annotationsAPI' of https://github.com/foliengriller/Froxlor into foliengriller-annotationsAPI 2019-04-26 12:23:58 +02:00
Michael Kaufmann
f93dc5643f fix error that wildcard-domains and lets-encrypt are not possible when using ACMEv2; fixes #674
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-04-25 14:20:02 +02:00
Michael Kaufmann
974b151d02 add Debian 10 (Buster) and Ubuntu 18.04 (Bionic) config-templates for TESTING
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-04-25 14:04:15 +02:00
Michael Kaufmann
8835dd0b65 remove deprecated config-templates for Ubuntu 12.04 (Precise); mark Debian 7 (Jessie) and Ubuntu 14.04 (Trusty) as deprecated
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-04-25 14:03:39 +02:00
Michael Kaufmann
626b791c67 remove recursor options in powerdns config template for gentoo, as recursion has been removed in pdns >=4.1.0; fixes #673
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-04-25 13:56:42 +02:00
Michael Kaufmann
82508587b3 update mysql-table engines to InnoDB; fixes #671
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-04-25 13:31:18 +02:00
Michael Kaufmann
0d7fa5728c fix auto-delete of cetificates when no domain exists anylonger, thx to an error-report
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-04-14 08:13:34 +02:00
Michael Rosenberger
98f6ad183e Corrects annotations in API 2018-12-19 16:58:52 +01:00
136 changed files with 14430 additions and 3858 deletions

4
.codecov.yml Normal file
View File

@@ -0,0 +1,4 @@
codecov:
notify:
require_ci_to_pass: no

4
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,4 @@
# These are supported funding model platforms
github: d00p
custom: ['https://paypal.me/Froxlor']

1
.gitignore vendored
View File

@@ -1,6 +1,7 @@
install/update.log
templates/*
lib/userdata.inc.php
lib/userdata.inc.php.bak
logs/*
!logs/index.html
.buildpath

View File

@@ -1,11 +1,9 @@
language: php
dist: bionic
services:
- docker
php:
# - "5.4"
# - "5.6"
# - "7.0"
- "7.1"
# - "7.2"
- 7.3
branches:
only:
@@ -14,47 +12,56 @@ branches:
matrix:
include:
# - php: 5.6
# env: deps=highest
# - php: 5.4
# env: deps=lowest
- php: 7.1
env: deps=highest
mysql:
database: froxlor010
username: root
encoding: utf8
- php: 7.3
env: "DOCKER_MYSQL_TYPE=mysql DOCKER_MYSQL_VERSION=5.6"
- php: 7.3
env: "DOCKER_MYSQL_TYPE=mysql DOCKER_MYSQL_VERSION=5.7"
- php: 7.3
env: "DOCKER_MYSQL_TYPE=mysql DOCKER_MYSQL_VERSION=8.0 STARTCMD='mysqld --default-authentication-plugin=mysql_native_password'"
- php: 7.3
env: "DOCKER_MYSQL_TYPE=mariadb DOCKER_MYSQL_VERSION=10.3"
- php: 7.3
env: "DOCKER_MYSQL_TYPE=mariadb DOCKER_MYSQL_VERSION=10.4"
addons:
apt:
update: true
# build.xml includes that
#install:
# - composer install
before_install:
- export MYSQL_DATABASE=froxlor010
- docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=fr0xl0r.TravisCI -e MYSQL_DATABASE=$MYSQL_DATABASE -p 3306:3306 $DOCKER_MYSQL_TYPE:$DOCKER_MYSQL_VERSION $STARTCMD
- sudo apt-get install -y ant
- >
export tries=0;
export max_tries=20;
while [[ true ]]; do
tries=$((tries + 1));
echo "waiting for database server to start up... [$tries]";
sleep 5;
# Now see that today's table is there, which would indicate that the cron job ran.
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -s -e 'SHOW VARIABLES LIKE "%version%";'
look_exit=$?;
if [[ "$look_exit" = "0" ]]; then echo "Database server successfully started"; break; fi;
if [[ "$tries" -ge "$max_tries" ]]; then echo "Database server did not start in time"; exit 1; break; fi;
done;
service:
- mysql
before_script:
- mysql -e 'CREATE DATABASE IF NOT EXISTS froxlor010'
- echo "USE mysql;\nUPDATE user SET password=PASSWORD('fr0xl0r.TravisCI') WHERE user='root';\nFLUSH PRIVILEGES;\n" | mysql -u root
- mysql -u root -pfr0xl0r.TravisCI froxlor010 < install/froxlor.sql
- mysql -u root -pfr0xl0r.TravisCI -e "CREATE USER 'froxlor010'@'localhost' IDENTIFIED BY 'fr0xl0r.TravisCI';"
- mysql -u root -pfr0xl0r.TravisCI -e "GRANT ALL ON froxlor010.* TO 'froxlor010'@'localhost';"
install:
- mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "CREATE DATABASE IF NOT EXISTS froxlor010;"
- 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
script:
# sufficient for travis
- ant phpunit-no-coverage
# - ant full-build-parallel
# -Dpdepend=$(pwd)/vendor/bin/pdepend
# -Dphpmd=$(pwd)/vendor/bin/phpmd
# -Dphpcpd=$(pwd)/vendor/bin/phpcpd
# -Dphpcs=$(pwd)/vendor/bin/phpcs
# -Dphploc=$(pwd)/vendor/bin/phploc
# -Dphpdox=$(pwd)/vendor/bin/phpdox
# -Dphpunit=$(pwd)/vendor/bin/phpunit
- ant phpunit
after_success:
- bash <(curl -s https://codecov.io/bash) -f "build/logs/clover.xml"
notifications:
irc: "irc.freenode.org#froxlor"
webhooks:
urls:
- https://webhooks.gitter.im/e/bdf91d1c3f745e51f796
on_success: always
on_failure: always
on_start: never

View File

@@ -1,4 +1,5 @@
[![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
@@ -53,7 +54,7 @@ https://files.froxlor.org/releases/froxlor-latest.tar.gz [MD5](https://files.fro
[HowTo](https://github.com/Froxlor/Froxlor/wiki/Install-froxlor-on-debian)
/etc/apt/sources.list.d/froxlor.list
> deb http://debian.froxlor.org {wheezy|jessie|stretch} main
> deb http://debian.froxlor.org {stretch|buster} main
### Gentoo repository

14
SECURITY.md Normal file
View File

@@ -0,0 +1,14 @@
# Security Policy
## Supported Versions
Our main and active version is currently 0.10.x. It will receive maintenance and security updates periodically. The older version 0.9.x will not receive any kind of updates. Please update to [0.10.x](https://github.com/Froxlor/Froxlor/wiki/Updating-Froxlor)
| Version | Supported |
| ------- | ------------------ |
| 0.10.x | :white_check_mark: |
| 0.9.x | :x: |
## Reporting a Vulnerability
If you think you have found a vulnerability in froxlor, please send an email to [team@froxlor.org](mailto:team@froxlor.org) with as many information as possible. Also, please give us appropriate time to fix the issue and build update-packages before publishing anything into the wild.

View File

@@ -45,7 +45,7 @@ return array(
'settinggroup' => 'panel',
'varname' => 'default_theme',
'type' => 'option',
'default' => 'Froxlor',
'default' => 'Sparkle',
'option_mode' => 'one',
'option_options_method' => array(
'\\Froxlor\\UI\\Template',

View File

@@ -250,6 +250,23 @@ return array(
'default' => '',
'save_method' => 'storeSettingField'
),
'system_default_sslvhostconf' => array(
'label' => $lng['serversettings']['default_sslvhostconf'],
'settinggroup' => 'system',
'varname' => 'default_sslvhostconf',
'type' => 'text',
'default' => '',
'save_method' => 'storeSettingField',
'visible' => \Froxlor\Settings::Get('system.use_ssl') == 1
),
'system_include_default_vhostconf' => array(
'label' => $lng['serversettings']['includedefault_sslvhostconf'],
'settinggroup' => 'system',
'varname' => 'include_default_vhostconf',
'type' => 'bool',
'default' => false,
'save_method' => 'storeSettingField'
),
'system_apache_globaldiropt' => array(
'label' => $lng['serversettings']['apache_globaldiropt'],
'settinggroup' => 'system',

View File

@@ -54,6 +54,16 @@ return array(
'default' => 'ECDH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS:!DH:!AES128',
'save_method' => 'storeSettingField'
),
'system_tlsv13_cipher_list' => array(
'label' => $lng['serversettings']['ssl']['tlsv13_cipher_list'],
'settinggroup' => 'system',
'varname' => 'tlsv13_cipher_list',
'type' => 'string',
'string_emptyallowed' => true,
'default' => '',
'visible' => \Froxlor\Settings::Get('system.webserver') == "apache2" && \Froxlor\Settings::Get('system.apache24') == 1,
'save_method' => 'storeSettingField',
),
'system_ssl_cert_file' => array(
'label' => $lng['serversettings']['ssl']['ssl_cert_file'],
'settinggroup' => 'system',
@@ -128,10 +138,9 @@ return array(
'settinggroup' => 'system',
'varname' => 'leapiversion',
'type' => 'option',
'default' => '1',
'default' => '2',
'option_mode' => 'one',
'option_options' => array(
'1' => 'ACME v1',
'2' => 'ACME v2'
),
'save_method' => 'storeSettingField'

View File

@@ -99,7 +99,7 @@ return array(
'settinggroup' => 'phpfpm',
'varname' => 'use_mod_proxy',
'type' => 'bool',
'default' => false,
'default' => true,
'visible' => \Froxlor\Settings::Get('system.apache24'),
'save_method' => 'storeSettingField'
),

View File

@@ -107,6 +107,22 @@ return array(
'default' => false,
'save_method' => 'storeSettingField'
),
'system_dns_createcaaentry' => array(
'label' => $lng['serversettings']['caa_entry'],
'settinggroup' => 'system',
'varname' => 'dns_createcaaentry',
'type' => 'bool',
'default' => true,
'save_method' => 'storeSettingField'
),
'caa_caa_entry' => array(
'label' => $lng['serversettings']['caa_entry_custom'],
'settinggroup' => 'caa',
'varname' => 'caa_entry',
'type' => 'text',
'default' => '',
'save_method' => 'storeSettingField'
),
'system_defaultttl' => array(
'label' => $lng['serversettings']['defaultttl'],
'settinggroup' => 'system',

View File

@@ -36,6 +36,15 @@ if (! extension_loaded('zip')) {
));
}
// 0.10.x requires 7.0 at least
if (version_compare("7.0.0", PHP_VERSION, ">=")) {
\Froxlor\UI\Response::redirectTo($filename, array(
's' => $s,
'page' => 'error',
'errno' => 10
));
}
// display initial version check
if ($page == 'overview') {
@@ -43,8 +52,11 @@ if ($page == 'overview') {
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "checking auto-update");
// check for new version
$latestversion = HttpClient::urlGet(UPDATE_URI);
try {
$latestversion = HttpClient::urlGet(UPDATE_URI, true, 3);
} catch (\Exception $e) {
\Froxlor\UI\Response::dynamic_error("Version-check currently unavailable, please try again later");
}
$latestversion = explode('|', $latestversion);
if (is_array($latestversion) && count($latestversion) >= 1) {
@@ -175,6 +187,8 @@ elseif ($page == 'extract') {
$zip->close();
// success - remove unused archive
@unlink($localArchive);
// wait a bit before we redirect to be sure
sleep(2);
} else {
// error
\Froxlor\UI\Response::redirectTo($filename, array(
@@ -216,5 +230,6 @@ elseif ($page == 'error') {
// 7 = local archive does not exist
// 8 = could not extract archive
// 9 = checksum mismatch
// 10 = <php-7.0
\Froxlor\UI\Response::standard_error('autoupdate_' . $errno);
}

View File

@@ -91,10 +91,16 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
'cid' => $row['customerid']
));
$row['webspace_used'] = round($usages['webspace'] / 1024, $dec_places);
$row['mailspace_used'] = round($usages['mail'] / 1024, $dec_places);
$row['dbspace_used'] = round($usages['mysql'] / 1024, $dec_places);
if ($usages)
{
$row['webspace_used'] = round($usages['webspace'] / 1024, $dec_places);
$row['mailspace_used'] = round($usages['mail'] / 1024, $dec_places);
$row['dbspace_used'] = round($usages['mysql'] / 1024, $dec_places);
} else {
$row['webspace_used'] = 0;
$row['mailspace_used'] = 0;
$row['dbspace_used'] = 0;
}
$row['traffic_used'] = round($row['traffic_used'] / (1024 * 1024), $dec_places);
$row['traffic'] = round($row['traffic'] / (1024 * 1024), $dec_places);
$row['diskspace_used'] = round($row['diskspace_used'] / 1024, $dec_places);

View File

@@ -387,8 +387,6 @@ if ($page == 'overview') {
}
} elseif ($page == 'apikeys' && Settings::Get('api.enabled') == 1) {
require_once __DIR__ . '/api_keys.php';
} elseif ($page == 'apihelp' && Settings::Get('api.enabled') == 1) {
require_once __DIR__ . '/apihelp.php';
} elseif ($page == '2fa' && Settings::Get('2fa.enabled') == 1) {
require_once __DIR__ . '/2fa.php';
}

View File

@@ -83,7 +83,7 @@ if ($page == 'log' && $userinfo['change_serversettings'] == '1') {
case \Froxlor\FroxlorLogger::LOGIN_ACTION:
$_action = $lng['logger']['login'];
break;
case LOG_ERROR:
case \Froxlor\FroxlorLogger::LOG_ERROR:
$_action = $lng['logger']['intern'];
break;
default:

View File

@@ -17,6 +17,7 @@
define('AREA', 'admin');
require './lib/init.php';
use Froxlor\Api\Commands\HostingPlans;
use Froxlor\Database\Database;
use Froxlor\Settings;
@@ -69,22 +70,26 @@ if ($page == '' || $page == 'overview') {
eval("echo \"" . \Froxlor\UI\Template::getTemplate("plans/plans") . "\";");
} elseif ($action == 'delete' && $id != 0) {
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_PLANS . "` WHERE `id` = :id");
$result = Database::pexecute_first($result_stmt, array(
'id' => $id
));
try {
$json_result = HostingPlans::getLocal($userinfo, array(
'id' => $id
))->get();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
if ($result['id'] != 0 && $result['id'] == $id && (int) $userinfo['adminid'] == $result['adminid']) {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_PLANS . "` WHERE `id` = :id");
Database::pexecute($del_stmt, array(
'id' => $id
));
try {
HostingPlans::getLocal($userinfo, array(
'id' => $id
))->delete();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "Plan '" . $result['name'] . "' has been deleted by '" . $userinfo['loginname'] . "'");
\Froxlor\UI\Response::redirectTo($filename, array(
'page' => $page,
's' => $s
@@ -102,113 +107,11 @@ if ($page == '' || $page == 'overview') {
} elseif ($action == 'add') {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
$name = \Froxlor\Validate\Validate::validate($_POST['name'], 'name');
$description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $_POST['description']), 'description', '/^[^\0]*$/');
$value_arr = array();
if (empty($name)) {
\Froxlor\UI\Response::standard_error('stringmustntbeempty', 'name');
try {
HostingPlans::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$value_arr['diskspace'] = (int)($_POST['diskspace']);
if (isset($_POST['diskspace_ul'])) {
$value_arr['diskspace'] = - 1;
}
$value_arr['traffic'] = $_POST['traffic'];
if (isset($_POST['traffic_ul'])) {
$value_arr['traffic'] = - 1;
}
$value_arr['subdomains'] = (int)($_POST['subdomains']);
if (isset($_POST['subdomains_ul'])) {
$value_arr['subdomains'] = - 1;
}
$value_arr['emails'] = (int)($_POST['emails']);
if (isset($_POST['emails_ul'])) {
$value_arr['emails'] = - 1;
}
$value_arr['email_accounts'] = (int)($_POST['email_accounts']);
if (isset($_POST['email_accounts_ul'])) {
$value_arr['email_accounts'] = - 1;
}
$value_arr['email_forwarders'] = (int)($_POST['email_forwarders']);
if (isset($_POST['email_forwarders_ul'])) {
$value_arr['email_forwarders'] = - 1;
}
if (Settings::Get('system.mail_quota_enabled') == '1') {
$value_arr['email_quota'] = \Froxlor\Validate\Validate::validate($_POST['email_quota'], 'email_quota', '/^\d+$/', 'vmailquotawrong', array(
'0',
''
));
if (isset($_POST['email_quota_ul'])) {
$value_arr['email_quota'] = - 1;
}
} else {
$value_arr['email_quota'] = - 1;
}
$value_arr['email_imap'] = 0;
if (isset($_POST['email_imap'])) {
$value_arr['email_imap'] = (int)($_POST['email_imap']);
}
$value_arr['email_pop3'] = 0;
if (isset($_POST['email_pop3'])) {
$value_arr['email_pop3'] = (int)($_POST['email_pop3']);
}
$value_arr['ftps'] = (int)($_POST['ftps']);
if (isset($_POST['ftps_ul'])) {
$value_arr['ftps'] = - 1;
}
$value_arr['mysqls'] = (int)($_POST['mysqls']);
if (isset($_POST['mysqls_ul'])) {
$value_arr['mysqls'] = - 1;
}
$value_arr['phpenabled'] = 0;
if (isset($_POST['phpenabled'])) {
$value_arr['phpenabled'] = intval($_POST['phpenabled']);
}
$value_arr['allowed_phpconfigs'] = array();
if (isset($_POST['allowed_phpconfigs']) && is_array($_POST['allowed_phpconfigs'])) {
foreach ($_POST['allowed_phpconfigs'] as $allowed_phpconfig) {
$allowed_phpconfig = intval($allowed_phpconfig);
$value_arr['allowed_phpconfigs'][] = $allowed_phpconfig;
}
}
$value_arr['perlenabled'] = 0;
if (isset($_POST['perlenabled'])) {
$value_arr['perlenabled'] = intval($_POST['perlenabled']);
}
$value_arr['dnsenabled'] = 0;
if (isset($_POST['dnsenabled'])) {
$value_arr['dnsenabled'] = intval($_POST['dnsenabled']);
}
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_PLANS . "`
SET `adminid` = :adminid, `name` = :name, `description` = :desc, `value` = :valuearr, `ts` = UNIX_TIMESTAMP();
");
$ins_data = array(
'adminid' => $userinfo['adminid'],
'name' => $name,
'desc' => $description,
'valuearr' => json_encode($value_arr)
);
Database::pexecute($ins_stmt, $ins_data);
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "added plan '" . $name . "'");
\Froxlor\UI\Response::redirectTo($filename, array(
'page' => $page,
's' => $s
@@ -266,11 +169,14 @@ if ($page == '' || $page == 'overview') {
eval("echo \"" . \Froxlor\UI\Template::getTemplate("plans/plans_add") . "\";");
}
} elseif ($action == 'edit' && $id != 0) {
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_PLANS . "` WHERE `id` = :id");
$result = Database::pexecute_first($result_stmt, array(
'id' => $id
));
try {
$json_result = HostingPlans::getLocal($userinfo, array(
'id' => $id
))->get();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
if ($result['name'] != '') {
@@ -284,110 +190,13 @@ if ($page == '' || $page == 'overview') {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
$name = \Froxlor\Validate\Validate::validate($_POST['name'], 'name');
$description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $_POST['description']), 'description', '/^[^\0]*$/');
$value_arr = array();
$value_arr['diskspace'] = (int)($_POST['diskspace']);
if (isset($_POST['diskspace_ul'])) {
$value_arr['diskspace'] = - 1;
try {
HostingPlans::getLocal($userinfo, array(
'id' => $id
))->update();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$value_arr['traffic'] = $_POST['traffic'];
if (isset($_POST['traffic_ul'])) {
$value_arr['traffic'] = - 1;
}
$value_arr['subdomains'] = (int)($_POST['subdomains']);
if (isset($_POST['subdomains_ul'])) {
$value_arr['subdomains'] = - 1;
}
$value_arr['emails'] = (int)($_POST['emails']);
if (isset($_POST['emails_ul'])) {
$value_arr['emails'] = - 1;
}
$value_arr['email_accounts'] = (int)($_POST['email_accounts']);
if (isset($_POST['email_accounts_ul'])) {
$value_arr['email_accounts'] = - 1;
}
$value_arr['email_forwarders'] = (int)($_POST['email_forwarders']);
if (isset($_POST['email_forwarders_ul'])) {
$value_arr['email_forwarders'] = - 1;
}
if (Settings::Get('system.mail_quota_enabled') == '1') {
$value_arr['email_quota'] = \Froxlor\Validate\Validate::validate($_POST['email_quota'], 'email_quota', '/^\d+$/', 'vmailquotawrong', array(
'0',
''
));
if (isset($_POST['email_quota_ul'])) {
$value_arr['email_quota'] = - 1;
}
} else {
$value_arr['email_quota'] = - 1;
}
$value_arr['email_imap'] = 0;
if (isset($_POST['email_imap'])) {
$value_arr['email_imap'] = (int)($_POST['email_imap']);
}
$value_arr['email_pop3'] = 0;
if (isset($_POST['email_pop3'])) {
$value_arr['email_pop3'] = (int)($_POST['email_pop3']);
}
$value_arr['ftps'] = (int)($_POST['ftps']);
if (isset($_POST['ftps_ul'])) {
$value_arr['ftps'] = - 1;
}
$value_arr['mysqls'] = (int)($_POST['mysqls']);
if (isset($_POST['mysqls_ul'])) {
$value_arr['mysqls'] = - 1;
}
$value_arr['phpenabled'] = 0;
if (isset($_POST['phpenabled'])) {
$value_arr['phpenabled'] = intval($_POST['phpenabled']);
}
$value_arr['allowed_phpconfigs'] = array();
if (isset($_POST['allowed_phpconfigs']) && is_array($_POST['allowed_phpconfigs'])) {
foreach ($_POST['allowed_phpconfigs'] as $allowed_phpconfig) {
$allowed_phpconfig = intval($allowed_phpconfig);
$value_arr['allowed_phpconfigs'][] = $allowed_phpconfig;
}
}
$value_arr['perlenabled'] = 0;
if (isset($_POST['perlenabled'])) {
$value_arr['perlenabled'] = intval($_POST['perlenabled']);
}
$value_arr['dnsenabled'] = 0;
if (isset($_POST['dnsenabled'])) {
$value_arr['dnsenabled'] = intval($_POST['dnsenabled']);
}
$ins_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_PLANS . "`
SET `name` = :name, `description` = :desc, `value` = :valuearr, `ts` = UNIX_TIMESTAMP()
WHERE `id` = :id
");
$ins_data = array(
'name' => $name,
'desc' => $description,
'valuearr' => json_encode($value_arr),
'id' => $id
);
Database::pexecute($ins_stmt, $ins_data);
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "updated plan '" . $name . "'");
\Froxlor\UI\Response::redirectTo($filename, array(
'page' => $page,
's' => $s
@@ -480,6 +289,7 @@ if ($page == '' || $page == 'overview') {
$result['customernumber'] = null;
$result['custom_notes'] = null;
$result['custom_notes_show'] = null;
$result['api_allowed'] = null;
$hosting_plans = null;
$admin_select_cnt = null;
$admin_select = null;
@@ -502,11 +312,14 @@ if ($page == '' || $page == 'overview') {
}
} elseif ($action == 'jqGetPlanValues') {
$planid = isset($_POST['planid']) ? (int) $_POST['planid'] : 0;
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_PLANS . "` WHERE `id` = :id");
$result = Database::pexecute_first($result_stmt, array(
'id' => $planid
));
try {
$json_result = HostingPlans::getLocal($userinfo, array(
'id' => $planid
))->get();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
echo $result['value'];
exit();
}

View File

@@ -23,7 +23,7 @@ if (empty($request)) {
}
// decode json request
$decoded_request = json_decode(stripslashes($request), true);
$decoded_request = json_decode($request, true);
// is it valid?
if (is_null($decoded_request)) {
@@ -32,6 +32,7 @@ if (is_null($decoded_request)) {
// validate content
try {
$decoded_request = stripcslashes_deep($decoded_request);
$request = \Froxlor\Api\FroxlorRPC::validateRequest($decoded_request);
// now actually do it
$cls = "\\Froxlor\\Api\\Commands\\" . $request['command']['class'];
@@ -72,3 +73,8 @@ function json_response($status, $status_message = '', $data = null)
echo $json_response;
exit();
}
function stripcslashes_deep($value)
{
return is_array($value) ? array_map('stripcslashes_deep', $value) : stripcslashes($value);
}

View File

@@ -88,15 +88,17 @@ if ($action == 'delete') {
$valid_until = isset($_POST['valid_until']) ? (int) $_POST['valid_until'] : - 1;
// validate allowed_from
$ip_list = array_map('trim', explode(",", $allowed_from));
$_check_list = $ip_list;
foreach ($_check_list as $idx => $ip) {
if (\Froxlor\Validate\Validate::validate_ip2($ip, true, 'invalidip', true, true) == false) {
unset($ip_list[$idx]);
if (! empty($allowed_from)) {
$ip_list = array_map('trim', explode(",", $allowed_from));
$_check_list = $ip_list;
foreach ($_check_list as $idx => $ip) {
if (\Froxlor\Validate\Validate::validate_ip2($ip, true, 'invalidip', true, true) == false) {
unset($ip_list[$idx]);
}
}
$ip_list = array_map('inet_ntop', array_map('inet_pton', $ip_list));
$allowed_from = implode(",", array_unique($ip_list));
}
$ip_list = array_map('inet_ntop', array_map('inet_pton', $ip_list));
$allowed_from = implode(",", array_unique($ip_list));
if ($valid_until <= 0 || ! is_numeric($valid_until)) {
$valid_until = - 1;

View File

@@ -226,14 +226,29 @@
<property name="phpcpd.done" value="true" />
</target>
<target name="phpunit" unless="phpunit.done" depends="composer"
<target name="phpunit-prepare" unless="phpunit-prepare.done" depends="composer"
description="prepare xdebug unit tests">
<exec executable="${phpunit}" resultproperty="result.phpunit-prepare"
taskname="phpunit">
<arg value="--configuration" />
<arg path="${basedir}/phpunit.xml" />
<arg value="--dump-xdebug-filter" />
<arg path="${basedir}/tests/xdebug-filter.php" />
</exec>
<property name="phpunit-prepare.done" value="true" />
</target>
<target name="phpunit" unless="phpunit.done" depends="phpunit-prepare"
description="Run unit tests with PHPUnit">
<exec executable="${phpunit}" resultproperty="result.phpunit"
<exec executable="${phpunit}" failonerror="true" resultproperty="result.phpunit"
taskname="phpunit">
<arg value="--configuration" />
<arg path="${basedir}/phpunit.xml" />
<arg value="--testsuite" />
<arg value="froxlor" />
<arg value="--prepend" />
<arg path="${basedir}/tests/xdebug-filter.php" />
</exec>
<property name="phpunit.done" value="true" />

View File

@@ -30,7 +30,7 @@
"docs": "https://github.com/Froxlor/Froxlor/wiki"
},
"require": {
"php": ">=5.6",
"php": ">=7.0",
"ext-session": "*",
"ext-ctype": "*",
"ext-pdo": "*",
@@ -49,17 +49,16 @@
"algo26-matthias/idna-convert": "^2.1"
},
"require-dev": {
"phpunit/phpunit": "6.5.13",
"pdepend/pdepend": "2.5.0",
"phpmd/phpmd": "2.6.0",
"sebastian/phpcpd": "3.0.1",
"squizlabs/php_codesniffer": "3.3.2",
"phploc/phploc": "3.0.1",
"theseer/phpdox": "0.11.2",
"phpunit/php-invoker": "1.1.4",
"php": ">=7.1",
"phpunit/phpunit": "^8",
"php": ">=7.3",
"ext-pcntl": "*",
"phpcompatibility/php-compatibility": "*"
"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"
},
"suggest": {
"ext-bcmath": "*",

1117
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -369,7 +369,7 @@ if ($page == 'overview') {
$domains .= \Froxlor\UI\HTML::makeoption($idna_convert->decode($row_domain['domain']), $row_domain['id'], $result['aliasdomain']);
}
if (preg_match('/^https?\:\/\//', $result['documentroot']) && \Froxlor\Validate\Form\Data::validateUrl($result['documentroot'])) {
if (preg_match('/^https?\:\/\//', $result['documentroot']) && \Froxlor\Validate\Validate::validateUrl($result['documentroot'])) {
if (Settings::Get('panel.pathedit') == 'Dropdown') {
$urlvalue = $result['documentroot'];
$pathSelect = \Froxlor\FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']);
@@ -480,6 +480,17 @@ if ($page == 'overview') {
} elseif ($page == 'domainssleditor') {
if ($action == '' || $action == 'view') {
// get domain
try {
$json_result = SubDomains::getLocal($userinfo, array(
'id' => $id
))->get();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result_domain = json_decode($json_result, true)['data'];
if (isset($_POST['send']) && $_POST['send'] == 'send') {
$do_insert = isset($_POST['do_insert']) ? (($_POST['do_insert'] == 1) ? true : false) : false;
try {

View File

@@ -93,11 +93,19 @@ 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'));
} else {
$userinfo['diskspace_used'] = 0;
$userinfo['mailspace_used'] = 0;
$userinfo['dbspace_used'] = 0;
$userinfo['total_used'] = 0;
}
$userinfo['diskspace'] = round($userinfo['diskspace'] / 1024, Settings::Get('panel.decimal_places'));
$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['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');
@@ -114,6 +122,8 @@ if ($page == 'overview') {
$se[] = "PHP";
if ($userinfo['perlenabled'] == '1')
$se[] = "Perl/CGI";
if ($userinfo['api_allowed'] == '1')
$se[] = '<a href="customer_index.php?s='.$s.'&page=apikeys">API</a>';
$services_enabled = implode(", ", $se);
eval("echo \"" . \Froxlor\UI\Template::getTemplate('index/index') . "\";");
@@ -353,8 +363,6 @@ if ($page == 'overview') {
}
} elseif ($page == 'apikeys' && Settings::Get('api.enabled') == 1) {
require_once __DIR__ . '/api_keys.php';
} elseif ($page == 'apihelp' && Settings::Get('api.enabled') == 1) {
require_once __DIR__ . '/apihelp.php';
} elseif ($page == '2fa' && Settings::Get('2fa.enabled') == 1) {
require_once __DIR__ . '/2fa.php';
}

View File

@@ -96,7 +96,7 @@ if ($page == 'log') {
case \Froxlor\FroxlorLogger::LOGIN_ACTION:
$_action = $lng['logger']['login'];
break;
case LOG_ERROR:
case \Froxlor\FroxlorLogger::LOG_ERROR:
$_action = $lng['logger']['intern'];
break;
default:

View File

@@ -108,11 +108,16 @@ if (! empty($dom_entries)) {
$type_select_values = array(
'A',
'AAAA',
'NS',
'CAA',
'CNAME',
'DNAME',
'LOC',
'MX',
'NS',
'RP',
'SRV',
'SSHFP',
'TXT',
'CNAME'
);
asort($type_select_values);
foreach ($type_select_values as $_type) {

View File

@@ -148,6 +148,11 @@ class FroxlorAPI
*/
public function getLastResponse(): array
{
if (!empty($this->getLastError())) {
// nothing is returned when the last call
// was not successful
return [];
}
return $this->last_body;
}

View File

@@ -8,7 +8,7 @@ CREATE TABLE `ftp_groups` (
PRIMARY KEY (`id`),
UNIQUE KEY `groupname` (`groupname`),
KEY `customerid` (`customerid`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -33,7 +33,7 @@ CREATE TABLE `ftp_users` (
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
KEY `customerid` (`customerid`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -57,7 +57,7 @@ CREATE TABLE `mail_users` (
`mboxsize` bigint(30) NOT NULL default '0',
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -73,7 +73,7 @@ CREATE TABLE `mail_virtual` (
`iscatchall` tinyint(1) unsigned NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `email` (`email`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
DROP TABLE IF EXISTS `panel_activation`;
@@ -84,7 +84,7 @@ CREATE TABLE `panel_activation` (
`creation` int(11) unsigned NOT NULL default '0',
`activationcode` varchar(50) default NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
DROP TABLE IF EXISTS `panel_admins`;
@@ -132,9 +132,10 @@ CREATE TABLE `panel_admins` (
`custom_notes_show` tinyint(1) NOT NULL default '0',
`type_2fa` tinyint(1) NOT NULL default '0',
`data_2fa` varchar(500) NOT NULL default '',
`api_allowed` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`adminid`),
UNIQUE KEY `loginname` (`loginname`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -199,10 +200,11 @@ CREATE TABLE `panel_customers` (
`allowed_phpconfigs` varchar(500) NOT NULL default '',
`type_2fa` tinyint(1) NOT NULL default '0',
`data_2fa` varchar(500) NOT NULL default '',
`api_allowed` tinyint(1) NOT NULL default '1',
`logviewenabled` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`customerid`),
UNIQUE KEY `loginname` (`loginname`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -215,7 +217,7 @@ CREATE TABLE `panel_databases` (
`dbserver` int(11) unsigned NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `customerid` (`customerid`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -246,6 +248,8 @@ CREATE TABLE `panel_domains` (
`speciallogfile` tinyint(1) NOT NULL default '0',
`ssl_redirect` tinyint(4) NOT NULL default '0',
`specialsettings` text,
`ssl_specialsettings` text,
`include_specialsettings` tinyint(1) NOT NULL default '0',
`deactivated` tinyint(1) NOT NULL default '0',
`bindserial` varchar(10) NOT NULL default '2000010100',
`add_date` int( 11 ) NOT NULL default '0',
@@ -264,11 +268,15 @@ CREATE TABLE `panel_domains` (
`notryfiles` tinyint(1) DEFAULT '0',
`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,
PRIMARY KEY (`id`),
KEY `customerid` (`customerid`),
KEY `parentdomain` (`parentdomainid`),
KEY `domain` (`domain`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -289,9 +297,13 @@ CREATE TABLE `panel_ipsandports` (
`default_vhostconf_domain` text,
`ssl_cert_chainfile` varchar(255) NOT NULL default '',
`docroot` varchar(255) NOT NULL default '',
`ssl_specialsettings` text,
`include_specialsettings` tinyint(1) NOT NULL default '0',
`ssl_default_vhostconf_domain` text,
`include_default_vhostconf_domain` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`id`),
UNIQUE KEY `ip_port` (`ip`,`port`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -307,7 +319,7 @@ CREATE TABLE `panel_htaccess` (
`error401path` varchar(255) NOT NULL default '',
`options_cgi` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -321,7 +333,7 @@ CREATE TABLE `panel_htpasswds` (
`authname` varchar(255) NOT NULL default 'Restricted Area',
PRIMARY KEY (`id`),
KEY `customerid` (`customerid`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -350,7 +362,7 @@ CREATE TABLE `panel_settings` (
`varname` varchar(255) NOT NULL default '',
`value` text NOT NULL,
PRIMARY KEY (`settingid`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('catchall', 'catchall_enabled', '1'),
@@ -375,6 +387,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('admin', 'show_news_feed', '0'),
('admin', 'show_version_login', '0'),
('admin', 'show_version_footer', '0'),
('caa', 'caa_entry', ''),
('spf', 'use_spf', '0'),
('spf', 'spf_entry', '"v=spf1 a mx -all"'),
('dkim', 'dkim_algorithm', 'all'),
@@ -404,7 +417,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('phpfpm', 'defaultini', '1'),
('phpfpm', 'vhost_defaultini', '2'),
('phpfpm', 'fastcgi_ipcdir', '/var/lib/apache2/fastcgi/'),
('phpfpm', 'use_mod_proxy', '0'),
('phpfpm', 'use_mod_proxy', '1'),
('phpfpm', 'ini_flags', 'asp_tags
display_errors
display_startup_errors
@@ -561,6 +574,7 @@ opcache.interned_strings_buffer'),
('system', 'mod_fcgid_defaultini', '1'),
('system', 'ftpserver', 'proftpd'),
('system', 'dns_createmailentry', '0'),
('system', 'dns_createcaaentry', '1'),
('system', 'froxlordirectlyviahostname', '0'),
('system', 'report_enable', '1'),
('system', 'report_webmax', '90'),
@@ -613,7 +627,7 @@ opcache.interned_strings_buffer'),
('system', 'letsencryptkeysize', '4096'),
('system', 'letsencryptreuseold', 0),
('system', 'leenabled', '0'),
('system', 'leapiversion', '1'),
('system', 'leapiversion', '2'),
('system', 'backupenabled', '0'),
('system', 'dnsenabled', '0'),
('system', 'dns_server', 'Bind'),
@@ -638,6 +652,7 @@ opcache.interned_strings_buffer'),
('system', 'nssextrausers', '0'),
('system', 'disable_le_selfcheck', '0'),
('system', 'ssl_protocols', 'TLSv1,TLSv1.2'),
('system', 'tlsv13_cipher_list', ''),
('system', 'logfiles_format', ''),
('system', 'logfiles_type', '1'),
('system', 'logfiles_piped', '0'),
@@ -680,8 +695,8 @@ opcache.interned_strings_buffer'),
('panel', 'password_special_char', '!?<>§$%+#=@'),
('panel', 'customer_hide_options', ''),
('panel', 'is_configured', '0'),
('panel', 'version', '0.10.0-rc1'),
('panel', 'db_version', '201904100');
('panel', 'version', '0.10.4'),
('panel', 'db_version', '201910200');
DROP TABLE IF EXISTS `panel_tasks`;
@@ -690,7 +705,7 @@ CREATE TABLE `panel_tasks` (
`type` int(11) NOT NULL default '0',
`data` text,
PRIMARY KEY (`id`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
INSERT INTO `panel_tasks` (`type`) VALUES ('99');
@@ -705,7 +720,7 @@ CREATE TABLE `panel_templates` (
`value` longtext NOT NULL,
PRIMARY KEY (id),
KEY adminid (adminid)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -723,7 +738,7 @@ CREATE TABLE `panel_traffic` (
`mail` bigint(30) unsigned NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `customerid` (`customerid`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -741,7 +756,7 @@ CREATE TABLE `panel_traffic_admins` (
`mail` bigint(30) unsigned NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `adminid` (`adminid`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -758,7 +773,7 @@ CREATE TABLE `panel_diskspace` (
`mysql` bigint(30) unsigned NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `customerid` (`customerid`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -775,7 +790,7 @@ CREATE TABLE `panel_diskspace_admins` (
`mysql` bigint(30) unsigned NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `adminid` (`adminid`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -786,7 +801,7 @@ CREATE TABLE `panel_languages` (
`iso` char(3) NOT NULL DEFAULT 'foo',
`file` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -809,7 +824,7 @@ CREATE TABLE IF NOT EXISTS `panel_syslog` (
`user` varchar(50) NOT NULL,
`text` text NOT NULL,
PRIMARY KEY (`logid`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -830,7 +845,7 @@ CREATE TABLE `panel_fpmdaemons` (
PRIMARY KEY (`id`),
UNIQUE KEY `reload` (`reload_cmd`),
UNIQUE KEY `config` (`config_dir`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -865,13 +880,13 @@ CREATE TABLE `panel_phpconfigs` (
`limit_extensions` varchar(255) NOT NULL default '.php',
PRIMARY KEY (`id`),
KEY `fpmsettingid` (`fpmsettingid`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
INSERT INTO `panel_phpconfigs` (`id`, `description`, `binary`, `file_extensions`, `mod_fcgid_starter`, `mod_fcgid_maxrequests`, `phpsettings`) VALUES
(1, 'Default Config', '/usr/bin/php-cgi', 'php', '-1', '-1', 'allow_call_time_pass_reference = Off\r\nallow_url_fopen = Off\r\nasp_tags = Off\r\ndisable_classes =\r\ndisable_functions = curl_exec,curl_multi_exec,exec,parse_ini_file,passthru,popen,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,shell_exec,show_source,system\r\ndisplay_errors = Off\r\ndisplay_startup_errors = Off\r\nenable_dl = Off\r\nerror_reporting = E_ALL & ~E_NOTICE\r\nexpose_php = Off\r\nfile_uploads = On\r\ncgi.force_redirect = 1\r\ngpc_order = "GPC"\r\nhtml_errors = Off\r\nignore_repeated_errors = Off\r\nignore_repeated_source = Off\r\ninclude_path = ".:{PEAR_DIR}"\r\nlog_errors = On\r\nlog_errors_max_len = 1024\r\nmagic_quotes_gpc = Off\r\nmagic_quotes_runtime = Off\r\nmagic_quotes_sybase = Off\r\nmax_execution_time = 30\r\nmax_input_time = 60\r\nmemory_limit = 128M\r\n{OPEN_BASEDIR_C}open_basedir = "{OPEN_BASEDIR}"\r\noutput_buffering = 4096\r\npost_max_size = 16M\r\nprecision = 14\r\nregister_argc_argv = Off\r\nregister_globals = Off\r\nreport_memleaks = On\r\nsendmail_path = "/usr/sbin/sendmail -t -i -f {CUSTOMER_EMAIL}"\r\nsession.auto_start = 0\r\nsession.bug_compat_42 = 0\r\nsession.bug_compat_warn = 1\r\nsession.cache_expire = 180\r\nsession.cache_limiter = nocache\r\nsession.cookie_domain =\r\nsession.cookie_lifetime = 0\r\nsession.cookie_path = /\r\nsession.entropy_file = /dev/urandom\r\nsession.entropy_length = 16\r\nsession.gc_divisor = 1000\r\nsession.gc_maxlifetime = 1440\r\nsession.gc_probability = 1\r\nsession.name = PHPSESSID\r\nsession.referer_check =\r\nsession.save_handler = files\r\nsession.save_path = "{TMP_DIR}"\r\nsession.serialize_handler = php\r\nsession.use_cookies = 1\r\nsession.use_trans_sid = 0\r\nshort_open_tag = On\r\nsuhosin.mail.protect = 1\r\nsuhosin.simulation = Off\r\ntrack_errors = Off\r\nupload_max_filesize = 32M\r\nupload_tmp_dir = "{TMP_DIR}"\r\nvariables_order = "GPCS"\r\n;mail.add_x_header = On\r\n;mail.log = "/var/log/phpmail.log"\r\nopcache.restrict_api = "{DOCUMENT_ROOT}"\r\n'),
(2, 'Froxlor Vhost Config', '/usr/bin/php-cgi', 'php', '-1', '-1', 'allow_call_time_pass_reference = Off\r\nallow_url_fopen = On\r\nasp_tags = Off\r\ndisable_classes =\r\ndisable_functions = curl_multi_exec,exec,parse_ini_file,passthru,popen,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,shell_exec,show_source,system\r\ndisplay_errors = Off\r\ndisplay_startup_errors = Off\r\nenable_dl = Off\r\nerror_reporting = E_ALL & ~E_NOTICE\r\nexpose_php = Off\r\nfile_uploads = On\r\ncgi.force_redirect = 1\r\ngpc_order = "GPC"\r\nhtml_errors = Off\r\nignore_repeated_errors = Off\r\nignore_repeated_source = Off\r\ninclude_path = ".:{PEAR_DIR}"\r\nlog_errors = On\r\nlog_errors_max_len = 1024\r\nmagic_quotes_gpc = Off\r\nmagic_quotes_runtime = Off\r\nmagic_quotes_sybase = Off\r\nmax_execution_time = 60\r\nmax_input_time = 60\r\nmemory_limit = 128M\r\noutput_buffering = 4096\r\npost_max_size = 16M\r\nprecision = 14\r\nregister_argc_argv = Off\r\nregister_globals = Off\r\nreport_memleaks = On\r\nsendmail_path = "/usr/sbin/sendmail -t -i -f {CUSTOMER_EMAIL}"\r\nsession.auto_start = 0\r\nsession.bug_compat_42 = 0\r\nsession.bug_compat_warn = 1\r\nsession.cache_expire = 180\r\nsession.cache_limiter = nocache\r\nsession.cookie_domain =\r\nsession.cookie_lifetime = 0\r\nsession.cookie_path = /\r\nsession.entropy_file = /dev/urandom\r\nsession.entropy_length = 16\r\nsession.gc_divisor = 1000\r\nsession.gc_maxlifetime = 1440\r\nsession.gc_probability = 1\r\nsession.name = PHPSESSID\r\nsession.referer_check =\r\nsession.save_handler = files\r\nsession.save_path = "{TMP_DIR}"\r\nsession.serialize_handler = php\r\nsession.use_cookies = 1\r\nsession.use_trans_sid = 0\r\nshort_open_tag = On\r\nsuhosin.mail.protect = 1\r\nsuhosin.simulation = Off\r\ntrack_errors = Off\r\nupload_max_filesize = 32M\r\nupload_tmp_dir = "{TMP_DIR}"\r\nvariables_order = "GPCS"\r\n;mail.add_x_header = On\r\n;mail.log = "/var/log/phpmail.log"\r\nopcache.restrict_api = ""\r\n');
(2, 'Froxlor Vhost Config', '/usr/bin/php-cgi', 'php', '-1', '-1', 'allow_call_time_pass_reference = Off\r\nallow_url_fopen = On\r\nasp_tags = Off\r\ndisable_classes =\r\ndisable_functions = curl_multi_exec,parse_ini_file,passthru,popen,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,shell_exec,show_source,system\r\ndisplay_errors = Off\r\ndisplay_startup_errors = Off\r\nenable_dl = Off\r\nerror_reporting = E_ALL & ~E_NOTICE\r\nexpose_php = Off\r\nfile_uploads = On\r\ncgi.force_redirect = 1\r\ngpc_order = "GPC"\r\nhtml_errors = Off\r\nignore_repeated_errors = Off\r\nignore_repeated_source = Off\r\ninclude_path = ".:{PEAR_DIR}"\r\nlog_errors = On\r\nlog_errors_max_len = 1024\r\nmagic_quotes_gpc = Off\r\nmagic_quotes_runtime = Off\r\nmagic_quotes_sybase = Off\r\nmax_execution_time = 60\r\nmax_input_time = 60\r\nmemory_limit = 128M\r\noutput_buffering = 4096\r\npost_max_size = 16M\r\nprecision = 14\r\nregister_argc_argv = Off\r\nregister_globals = Off\r\nreport_memleaks = On\r\nsendmail_path = "/usr/sbin/sendmail -t -i -f {CUSTOMER_EMAIL}"\r\nsession.auto_start = 0\r\nsession.bug_compat_42 = 0\r\nsession.bug_compat_warn = 1\r\nsession.cache_expire = 180\r\nsession.cache_limiter = nocache\r\nsession.cookie_domain =\r\nsession.cookie_lifetime = 0\r\nsession.cookie_path = /\r\nsession.entropy_file = /dev/urandom\r\nsession.entropy_length = 16\r\nsession.gc_divisor = 1000\r\nsession.gc_maxlifetime = 1440\r\nsession.gc_probability = 1\r\nsession.name = PHPSESSID\r\nsession.referer_check =\r\nsession.save_handler = files\r\nsession.save_path = "{TMP_DIR}"\r\nsession.serialize_handler = php\r\nsession.use_cookies = 1\r\nsession.use_trans_sid = 0\r\nshort_open_tag = On\r\nsuhosin.mail.protect = 1\r\nsuhosin.simulation = Off\r\ntrack_errors = Off\r\nupload_max_filesize = 32M\r\nupload_tmp_dir = "{TMP_DIR}"\r\nvariables_order = "GPCS"\r\n;mail.add_x_header = On\r\n;mail.log = "/var/log/phpmail.log"\r\nopcache.restrict_api = ""\r\n');
DROP TABLE IF EXISTS `cronjobs_run`;
@@ -885,7 +900,7 @@ CREATE TABLE IF NOT EXISTS `cronjobs_run` (
`isactive` tinyint(1) DEFAULT '1',
`desc_lng_key` varchar(100) NOT NULL DEFAULT 'cron_unknown_desc',
PRIMARY KEY (`id`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
INSERT INTO `cronjobs_run` (`id`, `module`, `cronfile`, `cronclass`, `interval`, `isactive`, `desc_lng_key`) VALUES
@@ -910,7 +925,7 @@ CREATE TABLE IF NOT EXISTS `ftp_quotalimits` (
`files_in_avail` int(10) unsigned NOT NULL,
`files_out_avail` int(10) unsigned NOT NULL,
`files_xfer_avail` int(10) unsigned NOT NULL
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -929,7 +944,7 @@ CREATE TABLE IF NOT EXISTS `ftp_quotatallies` (
`files_in_used` int(10) unsigned NOT NULL,
`files_out_used` int(10) unsigned NOT NULL,
`files_xfer_used` int(10) unsigned NOT NULL
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -940,7 +955,7 @@ CREATE TABLE IF NOT EXISTS `redirect_codes` (
`desc` varchar(200) NOT NULL,
`enabled` tinyint(1) DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -958,7 +973,7 @@ CREATE TABLE IF NOT EXISTS `domain_redirect_codes` (
`rid` int(5) NOT NULL,
`did` int(11) unsigned NOT NULL,
UNIQUE KEY `rc` (`rid`, `did`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
DROP TABLE IF EXISTS `domain_ssl_settings`;
@@ -973,7 +988,7 @@ CREATE TABLE IF NOT EXISTS `domain_ssl_settings` (
`ssl_fullchain_file` mediumtext,
`expirationdate` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
DROP TABLE IF EXISTS `panel_domaintoip`;
@@ -981,7 +996,7 @@ CREATE TABLE IF NOT EXISTS `panel_domaintoip` (
`id_domain` int(11) unsigned NOT NULL,
`id_ipandports` int(11) unsigned NOT NULL,
PRIMARY KEY (`id_domain`,`id_ipandports`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
DROP TABLE IF EXISTS `domain_dns_entries`;
@@ -994,7 +1009,7 @@ CREATE TABLE `domain_dns_entries` (
`ttl` int(11) NOT NULL DEFAULT '18000',
`prio` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
DROP TABLE IF EXISTS `panel_plans`;
@@ -1007,7 +1022,7 @@ CREATE TABLE `panel_plans` (
`ts` int(15) NOT NULL default '0',
PRIMARY KEY (id),
KEY adminid (adminid)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
DROP TABLE IF EXISTS `api_keys`;
@@ -1022,5 +1037,5 @@ CREATE TABLE `api_keys` (
PRIMARY KEY (id),
KEY adminid (adminid),
KEY customerid (customerid)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;

View File

@@ -15,6 +15,14 @@
* @package Install
*
*/
if (! file_exists(dirname(__DIR__) . '/vendor/autoload.php')) {
// get hint-template
$vendor_hint = file_get_contents(dirname(__DIR__) . '/templates/Sparkle/misc/vendormissinghint.tpl');
// replace values
$vendor_hint = str_replace("<FROXLOR_INSTALL_DIR>", dirname(__DIR__), $vendor_hint);
$vendor_hint = str_replace("<CURRENT_YEAR>", date('Y', time()), $vendor_hint);
die($vendor_hint);
}
require dirname(__DIR__) . '/vendor/autoload.php';
require __DIR__ . '/lib/class.FroxlorInstall.php';

View File

@@ -104,7 +104,7 @@ class FroxlorInstall
// check if we have a valid installation already
$this->_checkUserdataFile();
// include the MySQL-Table-Definitions
require $this->_basepath . '/lib/tables.inc.php';
require_once $this->_basepath . '/lib/tables.inc.php';
// include language
$this->_includeLanguageFile();
// show the action
@@ -407,6 +407,7 @@ class FroxlorInstall
`name` = 'Froxlor-Administrator',
`email` = :email,
`def_language` = :deflang,
`api_allowed` = 1,
`customers` = -1,
`customers_see_all` = 1,
`caneditphpsettings` = 1,
@@ -643,21 +644,8 @@ class FroxlorInstall
$mysql_access_host_array[] = $this->_data['serverip'];
foreach ($mysql_access_host_array as $mysql_access_host) {
$_db = str_replace('`', '', $this->_data['mysql_database']);
$stmt = $db_root->prepare("
GRANT ALL PRIVILEGES ON `" . $_db . "`.*
TO :username@:host
IDENTIFIED BY 'password'");
$stmt->execute(array(
"username" => $this->_data['mysql_unpriv_user'],
"host" => $mysql_access_host
));
$stmt = $db_root->prepare("SET PASSWORD FOR :username@:host = PASSWORD(:password)");
$stmt->execute(array(
"username" => $this->_data['mysql_unpriv_user'],
"host" => $mysql_access_host,
"password" => $this->_data['mysql_unpriv_pass']
));
$frox_db = str_replace('`', '', $this->_data['mysql_database']);
$this->_grantDbPrivilegesTo($db_root, $frox_db, $this->_data['mysql_unpriv_user'], $this->_data['mysql_unpriv_pass'], $mysql_access_host);
}
$db_root->query("FLUSH PRIVILEGES;");
@@ -667,6 +655,38 @@ class FroxlorInstall
return $content;
}
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', '>=')) {
// create user
$stmt = $db_root->prepare("
CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY :password
");
$stmt->execute(array(
"password" => $password
));
// grant privileges
$stmt = $db_root->prepare("
GRANT ALL ON `" . $database . "`.* TO :username@:host
");
$stmt->execute(array(
"username" => $username,
"host" => $access_host
));
} else {
// grant privileges
$stmt = $db_root->prepare("
GRANT ALL PRIVILEGES ON `" . $database . "`.* TO :username@:host IDENTIFIED BY :password
");
$stmt->execute(array(
"username" => $username,
"host" => $access_host,
"password" => $password
));
}
}
/**
* Check if an old database exists and back it up if necessary
*
@@ -944,11 +964,11 @@ class FroxlorInstall
// check for correct php version
$content .= $this->_status_message('begin', $this->_lng['requirements']['phpversion']);
if (version_compare("5.6.0", PHP_VERSION, ">=")) {
if (version_compare("7.0.0", PHP_VERSION, ">=")) {
$content .= $this->_status_message('red', $this->_lng['requirements']['notfound'] . ' (' . PHP_VERSION . ')');
$_die = true;
} else {
if (version_compare("7.0.0", PHP_VERSION, ">=")) {
if (version_compare("7.1.0", PHP_VERSION, ">=")) {
$content .= $this->_status_message('orange', $this->_lng['requirements']['newerphpprefered'] . ' (' . PHP_VERSION . ')');
} else {
$content .= $this->_status_message('green', PHP_VERSION);
@@ -1060,12 +1080,13 @@ class FroxlorInstall
*/
private function _sendHeaders()
{
// no caching
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Pragma: no-cache");
header('Last-Modified: ' . gmdate('D, d M Y H:i:s \G\M\T', time()));
header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time()));
if (@php_sapi_name() !== 'cli') {
// no caching
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Pragma: no-cache");
header('Last-Modified: ' . gmdate('D, d M Y H:i:s \G\M\T', time()));
header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time()));
}
// ensure that default timezone is set
if (function_exists("date_default_timezone_set") && function_exists("date_default_timezone_get")) {
@date_default_timezone_set(@date_default_timezone_get());
@@ -1082,7 +1103,7 @@ class FroxlorInstall
if (file_exists($userdata)) {
// includes the usersettings (MySQL-Username/Passwort)
// to test if Froxlor is already installed
require $this->_basepath . '/lib/userdata.inc.php';
require_once $this->_basepath . '/lib/userdata.inc.php';
if (isset($sql) && is_array($sql)) {
// use sparkle theme for the notice
@@ -1126,7 +1147,7 @@ class FroxlorInstall
$lngfile = $this->_basepath . '/install/lng/' . $standardlanguage . '.lng.php';
if (file_exists($lngfile)) {
// includes file /lng/$language.lng.php if it exists
require $lngfile;
require_once $lngfile;
$this->_lng = $lng;
}
@@ -1135,7 +1156,7 @@ class FroxlorInstall
$lngfile = $this->_basepath . '/install/lng/' . $this->_activelng . '.lng.php';
if (file_exists($lngfile)) {
// includes file /lng/$language.lng.php if it exists
require $lngfile;
require_once $lngfile;
$this->_lng = $lng;
}
}

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 >= 5.6';
$lng['requirements']['newerphpprefered'] = 'Good, but php-7.0 is prefered.';
$lng['requirements']['phpversion'] = 'PHP version >= 7.0';
$lng['requirements']['newerphpprefered'] = 'Good, but php-7.1 is prefered.';
$lng['requirements']['phppdo'] = 'PHP PDO extension and PDO-MySQL driver...';
$lng['requirements']['phpsession'] = 'PHP session-extension...';
$lng['requirements']['phpctype'] = 'PHP ctype-extension...';

View File

@@ -22,7 +22,7 @@ $lng['requirements']['not_true'] = 'non';
$lng['requirements']['notfound'] = 'introuvable';
$lng['requirements']['notinstalled'] = 'non installé';
$lng['requirements']['activated'] = 'activé';
$lng['requirements']['phpversion'] = 'PHP version >= 5.6';
$lng['requirements']['phpversion'] = 'PHP version >= 7.0';
$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 >= 5.6';
$lng['requirements']['newerphpprefered'] = 'Passt, aber php-7.0 wird bevorzugt.';
$lng['requirements']['phpversion'] = 'PHP Version >= 7.0';
$lng['requirements']['newerphpprefered'] = 'Passt, aber php-7.1 wird bevorzugt.';
$lng['requirements']['phppdo'] = 'PHP PDO Erweiterung und PDO-MySQL Treiber...';
$lng['requirements']['phpsession'] = 'PHP session-Erweiterung...';
$lng['requirements']['phpctype'] = 'PHP ctype-Erweiterung...';

View File

@@ -220,6 +220,14 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201902120')) {
$domain_in = substr($domain_in, 0, - 1);
Database::query("DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` IN (" . $domain_in . ")");
}
// check for froxlor domain using let's encrypt
if (Settings::Get('system.le_froxlor_enabled') == 1) {
Database::query("DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = '0'");
}
lastStepStatus(0);
showUpdateStep("Inserting job to regenerate configfiles");
\Froxlor\System\Cronjob::inserttask('1');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201902170');
@@ -238,5 +246,209 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201902210')) {
// set correct version for people that have tested 0.10.0 before
\Froxlor\Froxlor::updateToVersion('0.10.0-rc1');
\Froxlor\Froxlor::updateToDbVersion('201904100');
\Froxlor\Froxlor::updateToDbVersion('201904100');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201904100')) {
showUpdateStep("Converting all MyISAM tables to InnoDB");
Database::needRoot(true);
Database::needSqlData();
$sql_data = Database::getSqlData();
$result = Database::query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '" . $sql_data['db'] . "' AND ENGINE = 'MyISAM'");
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
Database::query("ALTER TABLE `" . $row['TABLE_NAME'] . "` ENGINE=INNODB");
}
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201904250');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.0-rc1')) {
showUpdateStep("Updating from 0.10.0-rc1 to 0.10.0-rc2", false);
\Froxlor\Froxlor::updateToVersion('0.10.0-rc2');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201904250')) {
showUpdateStep("Adding new settings for CAA");
Settings::AddNew('caa.caa_entry', '', true);
Settings::AddNew('system.dns_createcaaentry', 1, true);
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201907270');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201907270')) {
showUpdateStep("Cleaning up old files");
$to_clean = array(
"actions/admin/settings/000.version.php",
"actions/admin/settings/190.ticket.php",
"admin_tickets.php",
"customer_tickets.php",
"install/scripts/language-check.php",
"install/updates/froxlor/upgrade_syscp.inc.php",
"lib/classes",
"lib/configfiles/precise.xml",
"lib/cron_init.php",
"lib/cron_shutdown.php",
"lib/formfields/admin/tickets",
"lib/formfields/customer/tickets",
"lib/functions.php",
"lib/functions",
"lib/navigation/10.tickets.php",
"scripts/classes",
"scripts/jobs",
"templates/Sparkle/admin/tickets",
"templates/Sparkle/customer/tickets"
);
$disabled = explode(',', ini_get('disable_functions'));
$exec_allowed = ! in_array('exec', $disabled);
$del_list = "";
foreach ($to_clean as $filedir) {
$complete_filedir = \Froxlor\Froxlor::getInstallDir() . $filedir;
if (file_exists($complete_filedir)) {
if ($exec_allowed) {
Froxlor\FileDir::safe_exec("rm -rf " . escapeshellarg($complete_filedir));
} else {
$del_list .= "rm -rf " . escapeshellarg($complete_filedir) . PHP_EOL;
}
}
}
if ($exec_allowed) {
lastStepStatus(0);
} else {
if (empty($del_list)) {
// none of the files existed
lastStepStatus(0);
} else {
lastStepStatus(1, 'manual commands needed');
echo '<span class="update-step update-step-err">Please run the following commands manually:</span><br><pre>' . $del_list . '</pre><br>';
}
}
\Froxlor\Froxlor::updateToDbVersion('201909150');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.0-rc2')) {
showUpdateStep("Updating from 0.10.0-rc2 to 0.10.0 final", false);
\Froxlor\Froxlor::updateToVersion('0.10.0');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201909150')) {
showUpdateStep("Adding TLSv1.3-cipherlist setting");
Settings::AddNew("system.tlsv13_cipher_list", '');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201910030');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201910030')) {
showUpdateStep("Adding field api_allowed to admins and customers");
Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` ADD `api_allowed` tinyint(1) NOT NULL default '1';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `api_allowed` tinyint(1) NOT NULL default '1';");
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201910090');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.0')) {
showUpdateStep("Updating from 0.10.0 to 0.10.1 final", false);
\Froxlor\Froxlor::updateToVersion('0.10.1');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201910090')) {
showUpdateStep("Adjusting Let's Encrypt API setting");
Settings::Set("system.leapiversion", '2');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201910110');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201910110')) {
showUpdateStep("Adding new settings for ssl-vhost default content");
Settings::AddNew("system.default_sslvhostconf", '');
Settings::AddNew("system.include_default_vhostconf", '0');
lastStepStatus(0);
showUpdateStep("Adding new fields to ips and ports-table");
Database::query("ALTER TABLE `" . TABLE_PANEL_IPSANDPORTS . "` ADD `ssl_specialsettings` text AFTER `docroot`;");
Database::query("ALTER TABLE `" . TABLE_PANEL_IPSANDPORTS . "` ADD `include_specialsettings` tinyint(1) NOT NULL default '0' AFTER `ssl_specialsettings`;");
Database::query("ALTER TABLE `" . TABLE_PANEL_IPSANDPORTS . "` ADD `ssl_default_vhostconf_domain` text AFTER `include_specialsettings`;");
Database::query("ALTER TABLE `" . TABLE_PANEL_IPSANDPORTS . "` ADD `include_default_vhostconf_domain` tinyint(1) NOT NULL default '0' AFTER `ssl_default_vhostconf_domain`;");
lastStepStatus(0);
showUpdateStep("Adding new fields to domains-table");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `ssl_specialsettings` text AFTER `specialsettings`;");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `include_specialsettings` tinyint(1) NOT NULL default '0' AFTER `ssl_specialsettings`;");
lastStepStatus(0);
// select all ips/ports with specialsettings and SSL enabled to include the specialsettings in the ssl-vhost
// because the former implementation included it and users might rely on that, see https://github.com/Froxlor/Froxlor/issues/727
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `specialsettings` <> '' AND `ssl` = '1'");
Database::pexecute($sel_stmt);
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_IPSANDPORTS . "` SET `include_specialsettings` = '1' WHERE `id` = :id");
if ($sel_stmt->columnCount() > 0) {
showUpdateStep("Adjusting IP/port settings for downward compatibility");
while ($row = $sel_stmt->fetch(PDO::FETCH_ASSOC)) {
Database::pexecute($upd_stmt, [
'id' => $row['id']
]);
}
lastStepStatus(0);
}
// select all domains with an ssl IP connected and specialsettings content to include these in the ssl-vhost
// to maintain former behavior
$sel_stmt = Database::prepare("
SELECT d.id FROM `" . TABLE_PANEL_DOMAINS . "` d
LEFT JOIN `" . TABLE_DOMAINTOIP . "` d2i ON d2i.id_domain = d.id
LEFT JOIN `" . TABLE_PANEL_IPSANDPORTS . "` i ON i.id = d2i.id_ipandports
WHERE d.specialsettings <> '' AND i.ssl = '1'
");
Database::pexecute($sel_stmt);
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `include_specialsettings` = '1' WHERE `id` = :id");
if ($sel_stmt->columnCount() > 0) {
showUpdateStep("Adjusting domain settings for downward compatibility");
while ($row = $sel_stmt->fetch(PDO::FETCH_ASSOC)) {
Database::pexecute($upd_stmt, [
'id' => $row['id']
]);
}
lastStepStatus(0);
}
\Froxlor\Froxlor::updateToDbVersion('201910120');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.1')) {
showUpdateStep("Updating from 0.10.1 to 0.10.2", false);
\Froxlor\Froxlor::updateToVersion('0.10.2');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201910120')) {
showUpdateStep("Adding new TLS options to domains-table");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `override_tls` tinyint(1) DEFAULT '0' AFTER `writeerrorlog`;");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `ssl_protocols` text AFTER `override_tls`;");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `ssl_cipher_list` text AFTER `ssl_protocols`;");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `tlsv13_cipher_list` text AFTER `ssl_cipher_list`;");
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201910200');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.2')) {
showUpdateStep("Updating from 0.10.2 to 0.10.3", false);
\Froxlor\Froxlor::updateToVersion('0.10.3');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.3')) {
showUpdateStep("Updating from 0.10.3 to 0.10.4", false);
\Froxlor\Froxlor::updateToVersion('0.10.4');
}

View File

@@ -27,7 +27,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*
* @access admin
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{
@@ -61,7 +61,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function get()
{
@@ -97,6 +97,8 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, default auto-generated
* @param string $def_language
* optional, default is system-default language
* @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false
* @param string $custom_notes
* optional, default empty
* @param bool $custom_notes_show
@@ -158,7 +160,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
@@ -171,6 +173,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// parameters
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
$api_allowed = $this->getBoolParam('api_allowed', true, Settings::Get('api.enabled'));
$custom_notes = $this->getParam('custom_notes', true, '');
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
$password = $this->getParam('admin_password', true, '');
@@ -271,6 +274,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
'name' => $name,
'email' => $email,
'lang' => $def_language,
'api_allowed' => $api_allowed,
'change_serversettings' => $change_serversettings,
'customers' => $customers,
'customers_see_all' => $customers_see_all,
@@ -299,6 +303,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
`name` = :name,
`email` = :email,
`def_language` = :lang,
`api_allowed` = :api_allowed,
`change_serversettings` = :change_serversettings,
`customers` = :customers,
`customers_see_all` = :customers_see_all,
@@ -350,6 +355,8 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, default auto-generated
* @param string $def_language
* optional, default is system-default language
* @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false
* @param string $custom_notes
* optional, default empty
* @param string $theme
@@ -415,7 +422,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function update()
{
@@ -444,6 +451,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// you cannot edit some of the details of yourself
if ($result['adminid'] == $this->getUserDetail('adminid')) {
$api_allowed = $result['api_allowed'];
$deactivated = $result['deactivated'];
$customers = $result['customers'];
$domains = $result['domains'];
@@ -462,6 +470,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$traffic = $result['traffic'];
$ipaddress = ($result['ip'] != - 1 ? json_decode($result['ip'], true) : - 1);
} else {
$api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']);
$deactivated = $this->getBoolParam('deactivated', true, $result['deactivated']);
$dec_places = Settings::Get('panel.decimal_places');
@@ -578,6 +587,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
'name' => $name,
'email' => $email,
'lang' => $def_language,
'api_allowed' => $api_allowed,
'change_serversettings' => $change_serversettings,
'customers' => $customers,
'customers_see_all' => $customers_see_all,
@@ -607,6 +617,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
`name` = :name,
`email` = :email,
`def_language` = :lang,
`api_allowed` = :api_allowed,
`change_serversettings` = :change_serversettings,
`customers` = :customers,
`customers_see_all` = :customers_see_all,
@@ -653,7 +664,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function delete()
{
@@ -753,7 +764,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function unlock()
{
@@ -788,12 +799,12 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
/**
* increase resource-usage
*
* @param int $customerid
* @param int $adminid
* @param string $resource
* @param string $extra
* optional, default empty
* @param int $increase_by
* optional, default 1
* optional, default 1
*/
public static function increaseUsage($adminid = 0, $resource = null, $extra = '', $increase_by = 1)
{
@@ -803,12 +814,12 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
/**
* decrease resource-usage
*
* @param int $customerid
* @param int $adminid
* @param string $resource
* @param string $extra
* optional, default empty
* @param int $decrease_by
* optional, default 1
* optional, default 1
*/
public static function decreaseUsage($adminid = 0, $resource = null, $extra = '', $decrease_by = 1)
{

View File

@@ -38,7 +38,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
@@ -63,10 +63,19 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
$ssl_cert_chainfile = $this->getParam('ssl_cert_chainfile', true, '');
// validate whether the domain does not already have an entry
$result = $this->apiCall('Certificates.get', array(
'id' => $domainid
));
if (empty($result)) {
$has_cert = true;
try {
$this->apiCall('Certificates.get', array(
'id' => $domainid
));
} catch (\Exception $e) {
if ($e->getCode() == 412) {
$has_cert = false;
} else {
throw $e;
}
}
if (!$has_cert) {
$this->addOrUpdateCertificate($domain['id'], $ssl_cert_file, $ssl_key_file, $ssl_ca_file, $ssl_cert_chainfile, true);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] added ssl-certificate for '" . $domain['domain'] . "'");
$result = $this->apiCall('Certificates.get', array(
@@ -87,7 +96,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function get()
{
@@ -110,6 +119,9 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
$result = Database::pexecute_first($stmt, array(
"domainid" => $domainid
));
if (! $result) {
throw new \Exception("Domain '" . $domain['domain'] . "' does not have a certificate.", 412);
}
return $this->response(200, "successfull", $result);
}
@@ -129,7 +141,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function update()
{
@@ -164,7 +176,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
*
* @access admin, customer
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{
@@ -211,8 +223,8 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
*
* @param int $id
*
* @return array
* @throws \Exception
* @return string json-encoded array
*/
public function delete()
{
@@ -271,6 +283,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
throw new \Exception("Unable to determine SSL certificate. Maybe no access?", 406);
}
/**
* insert or update certificates entry
*
@@ -292,6 +305,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
}
$do_verify = true;
$expirationdate = null;
// no cert-file given -> forget everything
if ($ssl_cert_file == '') {
$ssl_key_file = '';
@@ -332,6 +346,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
} else {
\Froxlor\UI\Response::standard_error('sslcertificateinvalidcert', '', true);
}
$expirationdate = empty($cert_content['validTo_time_t']) ? null : date("Y-m-d H:i:s", $cert_content['validTo_time_t']);
}
// Add/Update database entry
@@ -345,7 +360,8 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
`ssl_cert_file` = :ssl_cert_file,
`ssl_key_file` = :ssl_key_file,
`ssl_ca_file` = :ssl_ca_file,
`ssl_cert_chainfile` = :ssl_cert_chainfile
`ssl_cert_chainfile` = :ssl_cert_chainfile,
`expirationdate` = :expirationdate
" . $qrywhere . " `domainid`= :domainid
");
$params = array(
@@ -353,6 +369,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
"ssl_key_file" => $ssl_key_file,
"ssl_ca_file" => $ssl_ca_file,
"ssl_cert_chainfile" => $ssl_cert_chainfile,
"expirationdate" => $expirationdate,
"domainid" => $domainid
);
Database::pexecute($stmt, $params, true, true);

View File

@@ -37,7 +37,7 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function get()
{
@@ -71,7 +71,7 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function update()
{
@@ -129,7 +129,7 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE
*
* @access admin
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{

View File

@@ -55,8 +55,8 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
* required when called as admin, not needed when called as customer
*
* @access admin, customer
* @return array
* @throws \Exception
* @return string json-encoded array
*/
public function add()
{
@@ -140,7 +140,7 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
*
* @access admin, customer
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{

View File

@@ -27,7 +27,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
*
* @access admin
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{
@@ -69,7 +69,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function get()
{
@@ -136,6 +136,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* optional
* @param string $def_language,
* optional, default is system-default language
* @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false
* @param int $gender
* optional, 0 = no-gender, 1 = male, 2 = female
* @param string $custom_notes
@@ -197,15 +199,17 @@ 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, wether 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, wether to allow acccess 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
* optional, specify a hosting-plan to set certain resource-values from the plan instead of specifying them
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
@@ -227,32 +231,61 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$fax = $this->getParam('fax', true, '');
$customernumber = $this->getParam('customernumber', true, '');
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
$api_allowed = $this->getBoolParam('api_allowed', true, Settings::Get('api.enabled'));
$gender = (int) $this->getParam('gender', true, 0);
$custom_notes = $this->getParam('custom_notes', true, '');
$custom_notes_show = $this->getBoolParam('custom_notes_show', 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);
$emails = $this->getUlParam('emails', 'emails_ul', true, 0);
$email_accounts = $this->getUlParam('email_accounts', 'email_accounts_ul', true, 0);
$email_forwarders = $this->getUlParam('email_forwarders', 'email_forwarders_ul', true, 0);
$email_quota = $this->getUlParam('email_quota', 'email_quota_ul', true, Settings::Get('system.mail_quota'));
$email_imap = $this->getBoolParam('email_imap', true, 0);
$email_pop3 = $this->getBoolParam('email_pop3', true, 0);
$ftps = $this->getUlParam('ftps', 'ftps_ul', true, 0);
$mysqls = $this->getUlParam('mysqls', 'mysqls_ul', true, 0);
$createstdsubdomain = $this->getBoolParam('createstdsubdomain', true, 0);
$password = $this->getParam('new_customer_password', true, '');
$sendpassword = $this->getBoolParam('sendpassword', true, 0);
$phpenabled = $this->getBoolParam('phpenabled', true, 0);
$p_allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, array());
$perlenabled = $this->getBoolParam('perlenabled', true, 0);
$dnsenabled = $this->getBoolParam('dnsenabled', true, 0);
$logviewenabled = $this->getBoolParam('logviewenabled', true, 0);
$store_defaultindex = $this->getBoolParam('store_defaultindex', true, 0);
$loginname = $this->getParam('new_loginname', true, '');
// hosting-plan values
$hosting_plan_id = $this->getParam('hosting_plan_id', true, 0);
if ($hosting_plan_id > 0) {
$hp_result = $this->apiCall('HostingPlans.get', array(
'id' => $hosting_plan_id
));
$hp_result['value'] = json_decode($hp_result['value'], true);
foreach ($hp_result['value'] as $index => $value) {
$hp_result[$index] = $value;
}
$diskspace = $hp_result['diskspace'] ?? 0;
$traffic = $hp_result['traffic'] ?? 0;
$subdomains = $hp_result['subdomains'] ?? 0;
$emails = $hp_result['emails'] ?? 0;
$email_accounts = $hp_result['email_accounts'] ?? 0;
$email_forwarders = $hp_result['email_forwarders'] ?? 0;
$email_quota = $hp_result['email_quota'] ?? Settings::Get('system.mail_quota');
$email_imap = $hp_result['email_imap'] ?? 0;
$email_pop3 = $hp_result['email_pop3'] ?? 0;
$ftps = $hp_result['ftps'] ?? 0;
$mysqls = $hp_result['mysqls'] ?? 0;
$phpenabled = $hp_result['phpenabled'] ?? 0;
$p_allowed_phpconfigs = $hp_result['allowed_phpconfigs'] ?? 0;
$perlenabled = $hp_result['perlenabled'] ?? 0;
$dnsenabled = $hp_result['dnsenabled'] ?? 0;
$logviewenabled = $hp_result['logviewenabled'] ?? 0;
} else {
$diskspace = $this->getUlParam('diskspace', 'diskspace_ul', true, 0);
$traffic = $this->getUlParam('traffic', 'traffic_ul', true, 0);
$subdomains = $this->getUlParam('subdomains', 'subdomains_ul', true, 0);
$emails = $this->getUlParam('emails', 'emails_ul', true, 0);
$email_accounts = $this->getUlParam('email_accounts', 'email_accounts_ul', true, 0);
$email_forwarders = $this->getUlParam('email_forwarders', 'email_forwarders_ul', true, 0);
$email_quota = $this->getUlParam('email_quota', 'email_quota_ul', true, Settings::Get('system.mail_quota'));
$email_imap = $this->getBoolParam('email_imap', true, 0);
$email_pop3 = $this->getBoolParam('email_pop3', true, 0);
$ftps = $this->getUlParam('ftps', 'ftps_ul', true, 0);
$mysqls = $this->getUlParam('mysqls', 'mysqls_ul', true, 0);
$phpenabled = $this->getBoolParam('phpenabled', true, 0);
$p_allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, array());
$perlenabled = $this->getBoolParam('perlenabled', true, 0);
$dnsenabled = $this->getBoolParam('dnsenabled', true, 0);
$logviewenabled = $this->getBoolParam('logviewenabled', true, 0);
}
// validation
$name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true);
$firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', '', '', array(), true);
@@ -340,11 +373,12 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'login' => $loginname
), true, true);
$mysql_maxlen = \Froxlor\Database\Database::getSqlUsernameLength() - strlen(Settings::Get('customer.mysqlprefix'));
if (strtolower($loginname_check['loginname']) == strtolower($loginname) || strtolower($loginname_check_admin['loginname']) == strtolower($loginname)) {
\Froxlor\UI\Response::standard_error('loginnameexists', $loginname, true);
} elseif (! \Froxlor\Validate\Validate::validateUsername($loginname, Settings::Get('panel.unix_names'), 14 - strlen(Settings::Get('customer.mysqlprefix')))) {
if (strlen($loginname) > 14 - strlen(Settings::Get('customer.mysqlprefix'))) {
\Froxlor\UI\Response::standard_error('loginnameiswrong2', 14 - strlen(Settings::Get('customer.mysqlprefix')), true);
} elseif (! \Froxlor\Validate\Validate::validateUsername($loginname, Settings::Get('panel.unix_names'), $mysql_maxlen)) {
if (strlen($loginname) > $mysql_maxlen) {
\Froxlor\UI\Response::standard_error('loginnameiswrong2', $mysql_maxlen, true);
} else {
\Froxlor\UI\Response::standard_error('loginnameiswrong', $loginname, true);
}
@@ -357,26 +391,6 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
\Froxlor\UI\Response::standard_error('documentrootexists', $documentroot, true);
}
if ($createstdsubdomain != '1') {
$createstdsubdomain = '0';
}
if ($phpenabled != '0') {
$phpenabled = '1';
}
if ($perlenabled != '0') {
$perlenabled = '1';
}
if ($dnsenabled != '0') {
$dnsenabled = '1';
}
if ($logviewenabled != '0') {
$logviewenabled = '1';
}
if ($password == '') {
$password = \Froxlor\System\Crypt::generatePassword();
}
@@ -399,6 +413,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'email' => $email,
'customerno' => $customernumber,
'lang' => $def_language,
'api_allowed' => $api_allowed,
'docroot' => $documentroot,
'guid' => $guid,
'diskspace' => $diskspace,
@@ -439,6 +454,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
`email` = :email,
`customernumber` = :customerno,
`def_language` = :lang,
`api_allowed` = :api_allowed,
`documentroot` = :docroot,
`guid` = :guid,
`diskspace` = :diskspace,
@@ -542,37 +558,14 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
Database::pexecute($ins_stmt, $ins_data, true, true);
\Froxlor\System\Cronjob::inserttask('1');
$cryptPassword = \Froxlor\System\Crypt::makeCryptPassword($password);
// add FTP-User
// @fixme use Ftp-ApiCommand later
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_FTP_USERS . "` SET `customerid` = :customerid, `username` = :username, `description` = :desc,
`password` = :passwd, `homedir` = :homedir, `login_enabled` = 'y', `uid` = :guid, `gid` = :guid
");
$ins_data = array(
'customerid' => $customerid,
'username' => $loginname,
'passwd' => $cryptPassword,
'homedir' => $documentroot,
'guid' => $guid,
'desc' => "Default"
);
Database::pexecute($ins_stmt, $ins_data, true, true);
// add FTP-Group
// @fixme use Ftp-ApiCommand later
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_FTP_GROUPS . "` SET `customerid` = :customerid, `groupname` = :groupname, `gid` = :guid, `members` = :members
");
$ins_data = array(
'customerid' => $customerid,
'groupname' => $loginname,
'guid' => $guid,
'members' => $loginname . ',' . Settings::Get('system.httpuser')
);
// add default FTP-User
// also, add froxlor-local user to ftp-group (if exists!) to
// allow access to customer-directories from within the panel, which
// is necessary when pathedit = Dropdown
$local_users = array(
Settings::Get('system.httpuser')
);
if ((int) Settings::Get('system.mod_fcgid_ownvhost') == 1 || (int) Settings::Get('phpfpm.enabled_ownvhost') == 1) {
if ((int) Settings::Get('system.mod_fcgid') == 1) {
$local_user = Settings::Get('system.mod_fcgid_httpuser');
@@ -581,22 +574,20 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
}
// check froxlor-local user membership in ftp-group
// without this check addition may duplicate user in list if httpuser == local_user
if (strpos($ins_data['members'], $local_user) == false) {
$ins_data['members'] .= ',' . $local_user;
if (in_array($local_user, $local_users) == false) {
$local_users[] = $local_user;
}
}
Database::pexecute($ins_stmt, $ins_data, true, true);
// FTP-Quotatallies
// @fixme use Ftp-ApiCommand later
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_FTP_QUOTATALLIES . "` SET `name` = :name, `quota_type` = 'user', `bytes_in_used` = '0',
`bytes_out_used` = '0', `bytes_xfer_used` = '0', `files_in_used` = '0', `files_out_used` = '0', `files_xfer_used` = '0'
");
Database::pexecute($ins_stmt, array(
'name' => $loginname
), true, true);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically added ftp-account for user '" . $loginname . "'");
$this->apiCall('Ftps.add', array(
'customerid' => $customerid,
'path' => '/',
'ftp_password' => $password,
'ftp_description' => "Default",
'sendinfomail' => 0,
'ftp_username' => $loginname,
'additional_members' => $local_users,
'is_defaultuser' => 1
));
$_stdsubdomain = '';
if ($createstdsubdomain == '1') {
@@ -749,6 +740,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* optional
* @param string $def_language,
* optional, default is system-default language
* @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false
* @param int $gender
* optional, 0 = no-gender, 1 = male, 2 = female
* @param string $custom_notes
@@ -820,7 +813,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function update()
{
@@ -851,6 +844,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$fax = $this->getParam('fax', true, $result['fax']);
$customernumber = $this->getParam('customernumber', true, $result['customernumber']);
$def_language = $this->getParam('def_language', true, $result['def_language']);
$api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']);
$gender = (int) $this->getParam('gender', true, $result['gender']);
$custom_notes = $this->getParam('custom_notes', true, $result['custom_notes']);
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, $result['custom_notes_show']);
@@ -897,7 +891,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true));
$customernumber = \Froxlor\Validate\Validate::validate($customernumber, 'customer number', '/^[A-Za-z0-9 \-]*$/Di', '', array(), true);
$custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', '/^[^\0]*$/', '', array(), true);
if (!empty($allowed_phpconfigs)) {
if (! empty($allowed_phpconfigs)) {
$allowed_phpconfigs = array_map('intval', $allowed_phpconfigs);
}
}
@@ -993,30 +987,10 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
\Froxlor\System\Cronjob::inserttask('1');
}
if ($deactivated != '1') {
$deactivated = '0';
}
if ($phpenabled != '0') {
$phpenabled = '1';
}
if ($perlenabled != '0') {
$perlenabled = '1';
}
if ($dnsenabled != '0') {
$dnsenabled = '1';
}
if ($phpenabled != $result['phpenabled'] || $perlenabled != $result['perlenabled']) {
\Froxlor\System\Cronjob::inserttask('1');
}
if ($logviewenabled != '0') {
$logviewenabled = '1';
}
// activate/deactivate customer services
if ($deactivated != $result['deactivated']) {
@@ -1061,6 +1035,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$dbm = new \Froxlor\Database\DbManager($this->logger());
// For each of them
$priv_changed = false;
while ($row_database = $databases_stmt->fetch(\PDO::FETCH_ASSOC)) {
if ($last_dbserver != $row_database['dbserver']) {
@@ -1081,10 +1056,13 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$dbm->getManager()->enableUser($row_database['databasename'], $mysql_access_host);
}
}
$priv_changed = true;
}
// At last flush the new privileges
$dbm->getManager()->flushPrivileges();
if ($priv_changed) {
$dbm->getManager()->flushPrivileges();
}
Database::needRoot(false);
// reactivate/deactivate api-keys
@@ -1156,7 +1134,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'dnsenabled' => $dnsenabled,
'logviewenabled' => $logviewenabled,
'custom_notes' => $custom_notes,
'custom_notes_show' => $custom_notes_show
'custom_notes_show' => $custom_notes_show,
'api_allowed' => $api_allowed
);
$upd_data = $upd_data + $admin_upd_data;
}
@@ -1197,7 +1176,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
`dnsenabled` = :dnsenabled,
`logviewenabled` = :logviewenabled,
`custom_notes` = :custom_notes,
`custom_notes_show` = :custom_notes_show";
`custom_notes_show` = :custom_notes_show,
`api_allowed` = :api_allowed";
$upd_query .= $admin_upd_query;
}
$upd_query .= " WHERE `customerid` = :customerid";
@@ -1337,7 +1317,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function delete()
{
@@ -1365,6 +1345,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$dbm = new \Froxlor\Database\DbManager($this->logger());
$priv_changed = false;
while ($row_database = $databases_stmt->fetch(\PDO::FETCH_ASSOC)) {
if ($last_dbserver != $row_database['dbserver']) {
Database::needRoot(true, $row_database['dbserver']);
@@ -1372,8 +1353,11 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$last_dbserver = $row_database['dbserver'];
}
$dbm->getManager()->deleteDatabase($row_database['databasename']);
$priv_changed = true;
}
if ($priv_changed) {
$dbm->getManager()->flushPrivileges();
}
$dbm->getManager()->flushPrivileges();
Database::needRoot(false);
// delete customer itself
@@ -1561,7 +1545,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function unlock()
{
@@ -1606,7 +1590,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function move()
{

View File

@@ -44,7 +44,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
@@ -139,7 +139,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function get()
{
@@ -214,7 +214,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function update()
{
@@ -288,7 +288,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
*
* @access admin, customer
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{
@@ -321,7 +321,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function delete()
{
@@ -394,7 +394,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
{
if ($errdoc !== null && $errdoc != '') {
// not a URL
if ((strtoupper(substr($errdoc, 0, 5)) != 'HTTP:' && strtoupper(substr($errdoc, 0, 6)) != 'HTTPS:') || ! \Froxlor\Validate\Form\Data::validateUrl($errdoc)) {
if ((strtoupper(substr($errdoc, 0, 5)) != 'HTTP:' && strtoupper(substr($errdoc, 0, 6)) != 'HTTPS:') || ! \Froxlor\Validate\Validate::validateUrl($errdoc)) {
// a file
if (substr($errdoc, 0, 1) != '"') {
$errdoc = \Froxlor\FileDir::makeCorrectFile($errdoc);

View File

@@ -37,7 +37,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
@@ -124,7 +124,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function get()
{
@@ -197,7 +197,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function update()
{
@@ -271,7 +271,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
*
* @access admin, customer
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{
@@ -306,7 +306,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function delete()
{

View File

@@ -42,7 +42,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
@@ -138,6 +138,43 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$errors[] = $this->lng['error']['dns_arec_noipv4'];
} elseif ($type == 'AAAA' && filter_var($content, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
$errors[] = $this->lng['error']['dns_aaaarec_noipv6'];
} 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);
if (empty($matches)) {
$errors[] = $this->lng['error']['dns_content_invalid'];
} elseif (($matches['type'] == 'issue' || $matches['type'] == 'issuewild') && ! \Froxlor\Validate\Validate::validateDomain($matches['domain'])) {
$errors[] = $this->lng['error']['dns_content_invalid'];
} elseif ($matches['type'] == 'iodef' && ! \Froxlor\Validate\Validate::validateUrl($matches['url'])) {
$errors[] = $this->lng['error']['dns_content_invalid'];
} else {
$content = $matches[0];
}
} elseif ($type == 'CNAME' || $type == 'DNAME') {
// check for trailing dot
if (substr($content, - 1) == '.') {
// remove it for checks
$content = substr($content, 0, - 1);
} else {
// add domain name
$content .= '.' . $domain;
}
if (! \Froxlor\Validate\Validate::validateDomain($content, true)) {
$errors[] = $this->lng['error']['dns_cname_invaliddom'];
} else {
// check whether there are RR-records for the same resource
foreach ($dom_entries as $existing_entries) {
if (($existing_entries['type'] == 'A' || $existing_entries['type'] == 'AAAA' || $existing_entries['type'] == 'MX' || $existing_entries['type'] == 'NS') && $existing_entries['record'] == $record) {
$errors[] = $this->lng['error']['dns_cname_nomorerr'];
break;
}
}
}
// append trailing dot (again)
$content .= '.';
} elseif ($type == 'LOC' && ! empty($content)) {
$content = $content;
} elseif ($type == 'MX') {
if ($prio === null || $prio < 0) {
$errors[] = $this->lng['error']['dns_mx_prioempty'];
@@ -161,28 +198,6 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
}
// append trailing dot (again)
$content .= '.';
} elseif ($type == 'CNAME') {
// check for trailing dot
if (substr($content, - 1) == '.') {
// remove it for checks
$content = substr($content, 0, - 1);
} else {
// add domain name
$content .= '.' . $domain;
}
if (! \Froxlor\Validate\Validate::validateDomain($content, true)) {
$errors[] = $this->lng['error']['dns_cname_invaliddom'];
} else {
// check whether there are RR-records for the same resource
foreach ($dom_entries as $existing_entries) {
if (($existing_entries['type'] == 'A' || $existing_entries['type'] == 'AAAA' || $existing_entries['type'] == 'MX' || $existing_entries['type'] == 'NS') && $existing_entries['record'] == $record) {
$errors[] = $this->lng['error']['dns_cname_nomorerr'];
break;
}
}
}
// append trailing dot (again)
$content .= '.';
} elseif ($type == 'NS') {
// check for trailing dot
if (substr($content, - 1) == '.') {
@@ -194,9 +209,8 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
}
// append trailing dot (again)
$content .= '.';
} elseif ($type == 'TXT' && ! empty($content)) {
// check that TXT content is enclosed in " "
$content = \Froxlor\Dns\Dns::encloseTXTContent($content);
} elseif ($type == 'RP' && ! empty($content)) {
$content = $content;
} elseif ($type == 'SRV') {
if ($prio === null || $prio < 0) {
$errors[] = $this->lng['error']['dns_srv_prioempty'];
@@ -232,6 +246,11 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
if (substr($content, - 1) != '.') {
$content .= '.';
}
} elseif ($type == 'SSHFP' && ! empty($content)) {
$content = $content;
} elseif ($type == 'TXT' && ! empty($content)) {
// check that TXT content is enclosed in " "
$content = \Froxlor\Dns\Dns::encloseTXTContent($content);
}
$new_entry = array(
@@ -306,7 +325,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function get()
{
@@ -354,12 +373,50 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
}
/**
* You cannot list dns zones.
* To get all domains use Domains.listing() or SubDomains.listing()
* List all entry records of a given domain by either id or domainname
*
* @param int $id
* optional, the domain id
* @param string $domainname
* optional, the domain name
*
* @access admin, customer
* @throws \Exception
* @return bool
*/
public function listing()
{
throw new \Exception('You cannot list dns zones. To get all domains use Domains.listing() or SubDomains.listing()', 303);
if (Settings::Get('system.dnsenabled') != '1') {
throw new \Exception("DNS service not enabled on this system", 405);
}
if ($this->isAdmin() == false && $this->getUserDetail('dnsenabled') != '1') {
throw new \Exception("You cannot access this resource", 405);
}
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$domainname = $this->getParam('domainname', $dn_optional, '');
// get requested domain
$result = $this->apiCall('SubDomains.get', array(
'id' => $id,
'domainname' => $domainname
));
$id = $result['id'];
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_DOMAIN_DNS . "` WHERE `domain_id` = :did");
Database::pexecute($sel_stmt, array(
'did' => $id
), true, true);
$result = [];
while ($row = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
}
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
/**

View File

@@ -27,7 +27,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
*
* @access admin
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{
@@ -70,7 +70,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function get()
{
@@ -119,8 +119,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional, default is the calling admin's ID
* @param array $ipandport
* optional list of ip/ports to assign to domain, default is system-default-ips
* @param bool $subcanemaildomain
* optional, allow subdomains of this domain as email domains, default 0 (false)
* @param int $subcanemaildomain
* optional, allow subdomains of this domain as email domains, 1 = choosable (default no), 2 = choosable (default yes), 3 = always, default 0 (never)
* @param bool $isemaildomain
* optional, allow email usage with this domain, default 0 (false)
* @param bool $email_only
@@ -147,6 +147,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional, currently not in use, default 0 (false)
* @param string $specialsettings
* optional, custom webserver vhost-content which is added to the generated vhost, default empty
* @param string $ssl_specialsettings
* optional, custom webserver vhost-content which is added to the generated ssl-vhost, default empty
* @param bool $include_specialsettings
* optional, whether or not to include non-ssl specialsettings in the generated ssl-vhost, default false
* @param bool $notryfiles
* optional, [nginx only] do not generate the default try-files directive, default 0 (false)
* @param bool $writeaccesslog
@@ -170,7 +174,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* @param bool $letsencrypt
* optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled
* @param array $ssl_ipandport
* optional, list of ssl-enabled ip/port id's to assign to this domain
* optional, list of ssl-enabled ip/port id's to assign to this domain, default empty
* @param bool $dont_use_default_ssl_ipandport_if_empty
* optional, do NOT set the systems default ssl ip addresses if none are given via $ssl_ipandport parameter
* @param bool $http2
* optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default 0 (false)
* @param int $hsts_maxage
@@ -181,10 +187,18 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional whether or not to preload HSTS header value
* @param bool $ocsp_stapling
* optional whether to enable ocsp-stapling for this domain. default 0 (false), requires SSL
* @param bool $override_tls
* optional whether or not to override system-tls settings like protocol, ssl-ciphers and if applicable tls-1.3 ciphers, requires change_serversettings flag for the admin, default false
* @param array $ssl_protocols
* optional list of allowed/used ssl/tls protocols, see system.ssl_protocols setting, only used/required if $override_tls is true, default empty or system.ssl_protocols setting if $override_tls is true
* @param string $ssl_cipher_list
* 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
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
@@ -212,6 +226,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$zonefile = $this->getParam('zonefile', true, '');
$dkim = $this->getBoolParam('dkim', true, 0);
$specialsettings = $this->getParam('specialsettings', true, '');
$ssl_specialsettings = $this->getParam('ssl_specialsettings', true, '');
$include_specialsettings = $this->getBoolParam('include_specialsettings', true, 0);
$notryfiles = $this->getBoolParam('notryfiles', true, 0);
$writeaccesslog = $this->getBoolParam('writeaccesslog', true, 1);
$writeerrorlog = $this->getBoolParam('writeerrorlog', true, 1);
@@ -223,13 +239,27 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, - 1);
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, 0);
$letsencrypt = $this->getBoolParam('letsencrypt', true, 0);
$p_ssl_ipandports = $this->getParam('ssl_ipandport', true, explode(',', Settings::Get('system.defaultsslip')));
$dont_use_default_ssl_ipandport_if_empty = $this->getBoolParam('dont_use_default_ssl_ipandport_if_empty', true, 0);
$p_ssl_ipandports = $this->getParam('ssl_ipandport', true, $dont_use_default_ssl_ipandport_if_empty ? array() : explode(',', Settings::Get('system.defaultsslip')));
$http2 = $this->getBoolParam('http2', true, 0);
$hsts_maxage = $this->getParam('hsts_maxage', true, 0);
$hsts_sub = $this->getBoolParam('hsts_sub', true, 0);
$hsts_preload = $this->getBoolParam('hsts_preload', true, 0);
$ocsp_stapling = $this->getBoolParam('ocsp_stapling', true, 0);
$override_tls = $this->getBoolParam('override_tls', true, 0);
$p_ssl_protocols = array();
$ssl_cipher_list = "";
$tlsv13_cipher_list = "";
if ($this->getUserDetail('change_serversettings') == '1') {
if ($override_tls) {
$p_ssl_protocols = $this->getParam('ssl_protocols', true, explode(',', Settings::Get('system.ssl_protocols')));
$ssl_cipher_list = $this->getParam('ssl_cipher_list', true, Settings::Get('system.ssl_cipher_list'));
$tlsv13_cipher_list = $this->getParam('tlsv13_cipher_list', true, Settings::Get('system.tlsv13_cipher_list'));
}
}
// validation
if ($p_domain == Settings::Get('system.hostname')) {
\Froxlor\UI\Response::standard_error('admin_domain_emailsystemhostname', '', true);
@@ -283,7 +313,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
'0',
''
), true);
if ($registration_date == '0000-00-00') {
if ($registration_date == '0000-00-00' || empty($registration_date)) {
$registration_date = null;
}
@@ -292,7 +322,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
'0',
''
), true);
if ($termination_date == '0000-00-00') {
if ($termination_date == '0000-00-00' || empty($termination_date)) {
$termination_date = null;
}
@@ -316,6 +346,34 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
} else {
$documentroot = $_documentroot;
}
$ssl_protocols = array();
if (! empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) {
$p_ssl_protocols = array(
$p_ssl_protocols
);
}
if (! empty($p_ssl_protocols) && ! is_array($p_ssl_protocols)) {
$p_ssl_protocols = json_decode($p_ssl_protocols, true);
}
if (! empty($p_ssl_protocols) && is_array($p_ssl_protocols)) {
$protocols_available = array(
'TLSv1',
'TLSv1.1',
'TLSv1.2',
'TLSv1.3'
);
foreach ($p_ssl_protocols as $ssl_protocol) {
if (! in_array(trim($ssl_protocol), $protocols_available)) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_DEBUG, "[API] unknown SSL protocol '" . trim($ssl_protocol) . "'");
continue;
}
$ssl_protocols[] = $ssl_protocol;
}
}
if (empty($ssl_protocols)) {
$override_tls = '0';
}
} else {
$isbinddomain = '0';
if (Settings::Get('system.bind_enable') == '1') {
@@ -325,10 +383,14 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$zonefile = '';
$dkim = '0';
$specialsettings = '';
$ssl_specialsettings = '';
$include_specialsettings = 0;
$notryfiles = '0';
$writeaccesslog = '1';
$writeerrorlog = '1';
$documentroot = $_documentroot;
$override_tls = '0';
$ssl_protocols = array();
}
if ($this->getUserDetail('caneditphpsettings') == '1' || $this->getUserDetail('change_serversettings') == '1') {
@@ -388,6 +450,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$ssl_ipandports = array();
if (Settings::Get('system.use_ssl') == "1" && ! empty($p_ssl_ipandports)) {
$ssl_ipandports = $this->validateIpAddresses($p_ssl_ipandports, true);
if ($this->getUserDetail('change_serversettings') == '1') {
$ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $ssl_specialsettings), 'ssl_specialsettings', '/^[^\0]*$/', '', array(), true);
}
}
if (Settings::Get('system.use_ssl') == "0" || empty($ssl_ipandports)) {
$ssl_redirect = 0;
@@ -404,17 +470,16 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
// OCSP stapling
$ocsp_stapling = 0;
// vhost container settings
$ssl_specialsettings = '';
$include_specialsettings = 0;
}
// We can't enable let's encrypt for wildcard - domains if using acme-v1
if ($serveraliasoption == '0' && $letsencrypt == '1' && Settings::Get('system.leapiversion') == '1') {
// We can't enable let's encrypt for wildcard-domains
if ($serveraliasoption == '0' && $letsencrypt == '1') {
\Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true);
}
// if using acme-v2 we cannot issue wildcard-certificates
// because they currently only support the dns-01 challenge
if ($serveraliasoption == '0' && $letsencrypt == '1' && Settings::Get('system.leapiversion') == '2') {
\Froxlor\UI\Response::standard_error('nowildcardwithletsencryptv2', '', true);
}
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
if ($ssl_redirect > 0 && $letsencrypt == 1) {
@@ -542,6 +607,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
'openbasedir' => $openbasedir,
'speciallogfile' => $speciallogfile,
'specialsettings' => $specialsettings,
'ssl_specialsettings' => $ssl_specialsettings,
'include_specialsettings' => $include_specialsettings,
'notryfiles' => $notryfiles,
'writeaccesslog' => $writeaccesslog,
'writeerrorlog' => $writeerrorlog,
@@ -558,7 +625,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
'hsts' => $hsts_maxage,
'hsts_sub' => $hsts_sub,
'hsts_preload' => $hsts_preload,
'ocsp_stapling' => $ocsp_stapling
'ocsp_stapling' => $ocsp_stapling,
'override_tls' => $override_tls,
'ssl_protocols' => implode(",", $ssl_protocols),
'ssl_cipher_list' => $ssl_cipher_list,
'tlsv13_cipher_list' => $tlsv13_cipher_list
);
$ins_stmt = Database::prepare("
@@ -584,6 +655,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
`openbasedir` = :openbasedir,
`speciallogfile` = :speciallogfile,
`specialsettings` = :specialsettings,
`ssl_specialsettings` = :ssl_specialsettings,
`include_specialsettings` = :include_specialsettings,
`notryfiles` = :notryfiles,
`writeaccesslog` = :writeaccesslog,
`writeerrorlog` = :writeerrorlog,
@@ -600,7 +673,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
`hsts` = :hsts,
`hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload,
`ocsp_stapling` = :ocsp_stapling
`ocsp_stapling` = :ocsp_stapling,
`override_tls` = :override_tls,
`ssl_protocols` = :ssl_protocols,
`ssl_cipher_list` = :ssl_cipher_list,
`tlsv13_cipher_list` = :tlsv13_cipher_list
");
Database::pexecute($ins_stmt, $ins_data, true, true);
$domainid = Database::lastInsertId();
@@ -670,8 +747,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional, default is the calling admin's ID
* @param array $ipandport
* optional list of ip/ports to assign to domain, default is system-default-ips
* @param bool $subcanemaildomain
* optional, allow subdomains of this domain as email domains, default 0 (false)
* @param int $subcanemaildomain
* optional, allow subdomains of this domain as email domains, 1 = choosable (default no), 2 = choosable (default yes), 3 = always, default 0 (never)
* @param bool $isemaildomain
* optional, allow email usage with this domain, default 0 (false)
* @param bool $email_only
@@ -700,6 +777,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional, currently not in use, default 0 (false)
* @param string $specialsettings
* optional, custom webserver vhost-content which is added to the generated vhost, default empty
* @param string $ssl_specialsettings
* optional, custom webserver vhost-content which is added to the generated ssl-vhost, default empty
* @param bool $include_specialsettings
* optional, whether or not to include non-ssl specialsettings in the generated ssl-vhost, default false
* @param bool $specialsettingsforsubdomains
* optional, whether to apply specialsettings to all subdomains of this domain, default 0 (false)
* @param bool $notryfiles
@@ -741,7 +822,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function update()
{
@@ -764,7 +845,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$customerid = intval($this->getParam('customerid', true, $result['customerid']));
$adminid = intval($this->getParam('adminid', true, $result['adminid']));
$subcanemaildomain = $this->getBoolParam('subcanemaildomain', true, $result['subcanemaildomain']);
$subcanemaildomain = $this->getParam('subcanemaildomain', true, $result['subcanemaildomain']);
$isemaildomain = $this->getBoolParam('isemaildomain', true, $result['isemaildomain']);
$email_only = $this->getBoolParam('email_only', true, $result['email_only']);
$p_serveraliasoption = $this->getParam('selectserveralias', true, - 1);
@@ -779,6 +860,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$zonefile = $this->getParam('zonefile', true, $result['zonefile']);
$dkim = $this->getBoolParam('dkim', true, $result['dkim']);
$specialsettings = $this->getParam('specialsettings', true, $result['specialsettings']);
$ssl_specialsettings = $this->getParam('ssl_specialsettings', true, $result['ssl_specialsettings']);
$include_specialsettings = $this->getBoolParam('include_specialsettings', true, $result['include_specialsettings']);
$ssfs = $this->getBoolParam('specialsettingsforsubdomains', true, 0);
$notryfiles = $this->getBoolParam('notryfiles', true, $result['notryfiles']);
$writeaccesslog = $this->getBoolParam('writeaccesslog', true, $result['writeaccesslog']);
@@ -799,6 +882,24 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$hsts_preload = $this->getBoolParam('hsts_preload', true, $result['hsts_preload']);
$ocsp_stapling = $this->getBoolParam('ocsp_stapling', true, $result['ocsp_stapling']);
$override_tls = $this->getBoolParam('override_tls', true, $result['override_tls']);
if ($this->getUserDetail('change_serversettings') == '1') {
if ($override_tls) {
$p_ssl_protocols = $this->getParam('ssl_protocols', true, explode(',', $result['ssl_protocols']));
$ssl_cipher_list = $this->getParam('ssl_cipher_list', true, $result['ssl_cipher_list']);
$tlsv13_cipher_list = $this->getParam('tlsv13_cipher_list', true, $result['tlsv13_cipher_list']);
} else {
$p_ssl_protocols = array();
$ssl_cipher_list = "";
$tlsv13_cipher_list = "";
}
} else {
$p_ssl_protocols = explode(',', $result['ssl_protocols']);
$ssl_cipher_list = $result['ssl_cipher_list'];
$tlsv13_cipher_list = $result['tlsv13_cipher_list'];
}
// count subdomain usage of source-domain
$subdomains_stmt = Database::prepare("
SELECT COUNT(`id`) AS count FROM `" . TABLE_PANEL_DOMAINS . "` WHERE
@@ -905,7 +1006,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
'0',
''
), true);
if ($registration_date == '0000-00-00') {
if ($registration_date == '0000-00-00' || empty($registration_date)) {
$registration_date = null;
}
$termination_date = \Froxlor\Validate\Validate::validate($termination_date, 'termination_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', array(
@@ -913,7 +1014,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
'0',
''
), true);
if ($termination_date == '0000-00-00') {
if ($termination_date == '0000-00-00' || empty($termination_date)) {
$termination_date = null;
}
@@ -968,16 +1069,48 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
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)) {
$p_ssl_protocols = array(
$p_ssl_protocols
);
}
if (! empty($p_ssl_protocols) && ! is_array($p_ssl_protocols)) {
$p_ssl_protocols = json_decode($p_ssl_protocols, true);
}
if (! empty($p_ssl_protocols) && is_array($p_ssl_protocols)) {
$protocols_available = array(
'TLSv1',
'TLSv1.1',
'TLSv1.2',
'TLSv1.3'
);
foreach ($p_ssl_protocols as $ssl_protocol) {
if (! in_array(trim($ssl_protocol), $protocols_available)) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_DEBUG, "[API] unknown SSL protocol '" . trim($ssl_protocol) . "'");
continue;
}
$ssl_protocols[] = $ssl_protocol;
}
}
if (empty($ssl_protocols)) {
$override_tls = '0';
}
} else {
$isbinddomain = $result['isbinddomain'];
$zonefile = $result['zonefile'];
$dkim = $result['dkim'];
$specialsettings = $result['specialsettings'];
$ssl_specialsettings = $result['ssl_specialsettings'];
$include_specialsettings = $result['include_specialsettings'];
$ssfs = (empty($specialsettings) ? 0 : 1);
$notryfiles = $result['notryfiles'];
$writeaccesslog = $result['writeaccesslog'];
$writeerrorlog = $result['writeerrorlog'];
$documentroot = $result['documentroot'];
$override_tls = $result['override_tls'];
}
if ($this->getUserDetail('caneditphpsettings') == '1' || $this->getUserDetail('change_serversettings') == '1') {
@@ -1028,6 +1161,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$ssl_ipandports = array();
if (Settings::Get('system.use_ssl') == "1" && ! empty($p_ssl_ipandports)) {
$ssl_ipandports = $this->validateIpAddresses($p_ssl_ipandports, true, $result['id']);
if ($this->getUserDetail('change_serversettings') == '1') {
$ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $ssl_specialsettings), 'ssl_specialsettings', '/^[^\0]*$/', '', array(), true);
}
}
if (Settings::Get('system.use_ssl') == "0" || empty($ssl_ipandports)) {
$ssl_redirect = 0;
@@ -1044,17 +1181,16 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
// OCSP stapling
$ocsp_stapling = 0;
// vhost container settings
$ssl_specialsettings = '';
$include_specialsettings = 0;
}
// We can't enable let's encrypt for wildcard domains when using acme-v1
if ($serveraliasoption == '0' && $letsencrypt == '1' && Settings::Get('system.leapiversion') == '1') {
// We can't enable let's encrypt for wildcard-domains
if ($serveraliasoption == '0' && $letsencrypt == '1') {
\Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true);
}
// if using acme-v2 we cannot issue wildcard-certificates
// because they currently only support the dns-01 challenge
if ($serveraliasoption == '0' && $letsencrypt == '1' && Settings::Get('system.leapiversion') == '2') {
\Froxlor\UI\Response::standard_error('nowildcardwithletsencryptv2', '', true);
}
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
if ($ssl_redirect > 0 && $letsencrypt == 1 && $result['letsencrypt'] != $letsencrypt) {
@@ -1252,12 +1388,16 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
if ($ssfs == 1) {
$_update_data['specialsettings'] = $specialsettings;
$upd_specialsettings = ", `specialsettings` = :specialsettings ";
$_update_data['ssl_specialsettings'] = $ssl_specialsettings;
$_update_data['include_specialsettings'] = $include_specialsettings;
$upd_specialsettings = ", `specialsettings` = :specialsettings, `ssl_specialsettings` = :ssl_specialsettings, `include_specialsettings` = :include_specialsettings ";
} else {
$upd_specialsettings = '';
unset($_update_data['specialsettings']);
unset($_update_data['ssl_specialsettings']);
unset($_update_data['include_specialsettings']);
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `specialsettings`='' WHERE `parentdomainid` = :id
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `specialsettings`='', `ssl_specialsettings`='', `include_specialsettings`='0' WHERE `parentdomainid` = :id
");
Database::pexecute($upd_stmt, array(
'id' => $id
@@ -1290,6 +1430,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$update_data['mod_fcgid_starter'] = $mod_fcgid_starter;
$update_data['mod_fcgid_maxrequests'] = $mod_fcgid_maxrequests;
$update_data['specialsettings'] = $specialsettings;
$update_data['ssl_specialsettings'] = $ssl_specialsettings;
$update_data['include_specialsettings'] = $include_specialsettings;
$update_data['notryfiles'] = $notryfiles;
$update_data['writeaccesslog'] = $writeaccesslog;
$update_data['writeerrorlog'] = $writeerrorlog;
@@ -1302,6 +1444,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$update_data['hsts_sub'] = $hsts_sub;
$update_data['hsts_preload'] = $hsts_preload;
$update_data['ocsp_stapling'] = $ocsp_stapling;
$update_data['override_tls'] = $override_tls;
$update_data['ssl_protocols'] = implode(",", $ssl_protocols);
$update_data['ssl_cipher_list'] = $ssl_cipher_list;
$update_data['tlsv13_cipher_list'] = $tlsv13_cipher_list;
$update_data['id'] = $id;
$update_stmt = Database::prepare("
@@ -1327,6 +1473,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
`mod_fcgid_starter` = :mod_fcgid_starter,
`mod_fcgid_maxrequests` = :mod_fcgid_maxrequests,
`specialsettings` = :specialsettings,
`ssl_specialsettings` = :ssl_specialsettings,
`include_specialsettings` = :include_specialsettings,
`notryfiles` = :notryfiles,
`writeaccesslog` = :writeaccesslog,
`writeerrorlog` = :writeerrorlog,
@@ -1338,7 +1486,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
`hsts` = :hsts,
`hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload,
`ocsp_stapling` = :ocsp_stapling
`ocsp_stapling` = :ocsp_stapling,
`override_tls` = :override_tls,
`ssl_protocols` = :ssl_protocols,
`ssl_cipher_list` = :ssl_cipher_list,
`tlsv13_cipher_list` = :tlsv13_cipher_list
WHERE `id` = :id
");
Database::pexecute($update_stmt, $update_data, true, true);
@@ -1349,6 +1501,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$_update_data['openbasedir'] = $openbasedir;
$_update_data['mod_fcgid_starter'] = $mod_fcgid_starter;
$_update_data['mod_fcgid_maxrequests'] = $mod_fcgid_maxrequests;
$_update_data['override_tls'] = $override_tls;
$_update_data['ssl_protocols'] = implode(",", $ssl_protocols);
$_update_data['ssl_cipher_list'] = $ssl_cipher_list;
$_update_data['tlsv13_cipher_list'] = $tlsv13_cipher_list;
$_update_data['parentdomainid'] = $id;
// if php config is to be set for all subdomains, check here
@@ -1373,7 +1529,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
`phpenabled` = :phpenabled,
`openbasedir` = :openbasedir,
`mod_fcgid_starter` = :mod_fcgid_starter,
`mod_fcgid_maxrequests` = :mod_fcgid_maxrequests
`mod_fcgid_maxrequests` = :mod_fcgid_maxrequests,
`override_tls` = :override_tls,
`ssl_protocols` = :ssl_protocols,
`ssl_cipher_list` = :ssl_cipher_list,
`tlsv13_cipher_list` = :tlsv13_cipher_list
" . $update_phpconfig . $upd_specialsettings . $updatechildren . $update_sslredirect . "
WHERE `parentdomainid` = :parentdomainid
");
@@ -1447,14 +1607,15 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
}
}
}
if ($result['aliasdomain'] != $aliasdomain) {
if ($result['aliasdomain'] != $aliasdomain && is_numeric($result['aliasdomain'])) {
// trigger when domain id for alias destination has changed: both for old and new destination
\Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger());
\Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger());
} elseif ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) {
}
if ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) {
// or when wwwserveralias or letsencrypt was changed
\Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger());
if ($aliasdomain === 0) {
if ((int) $aliasdomain === 0) {
// in case the wwwserveralias is set on a main domain, $aliasdomain is 0
// --> the call just above to triggerLetsEncryptCSRForAliasDestinationDomain
// is a noop...let's repeat it with the domain id of the main domain
@@ -1462,7 +1623,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
}
}
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated domain '" . $result['domain'] . "'");
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated domain '" . $idna_convert->decode($result['domain']) . "'");
return $this->response(200, "successfull", $update_data);
}
throw new \Exception("Not allowed to execute given command.", 403);
@@ -1482,7 +1644,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function delete()
{
@@ -1616,6 +1778,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
// remove domains DNS from powerDNS if used, #581
\Froxlor\System\Cronjob::inserttask('11', $result['domain']);
// remove domain from acme.sh / lets encrypt if used
\Froxlor\System\Cronjob::inserttask('12', $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');
@@ -1629,11 +1794,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
/**
* validate given ips
*
* @param int|string|array $p_ipsandports
* @param boolean $edit
* default false
* @param int|string|array $p_ipandports
* @param boolean $ssl
* default false
* @param int $edit_id
* default 0
*
* @throws \Exception
* @return array

View File

@@ -44,7 +44,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
@@ -81,9 +81,9 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
));
$id = $result['id'];
$email_full = $result['email_full'];
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$username = $idna_convert->decode($email_full);
$email_full = $result['email_full'];
$username = $email_full;
$password = \Froxlor\Validate\Validate::validate($email_password, 'password', '', '', array(), true);
$password = \Froxlor\System\Crypt::validatePassword($password, true);
@@ -300,7 +300,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function update()
{
@@ -412,7 +412,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function delete()
{

View File

@@ -38,7 +38,7 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
*
* @access admin,customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
@@ -150,7 +150,7 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
*
* @access admin,customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function delete()
{

View File

@@ -38,7 +38,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
@@ -152,7 +152,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function get()
{
@@ -195,7 +195,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function update()
{
@@ -268,7 +268,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*
* @access admin, customer
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{
@@ -308,7 +308,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function delete()
{
@@ -340,26 +340,12 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
}
// check whether this address is an account
if ($result['popaccountid'] != 0) {
// Free the Quota used by the email account
if (Settings::Get('system.mail_quota_enabled') == 1) {
$stmt = Database::prepare("SELECT `quota` FROM `" . TABLE_MAIL_USERS . "` WHERE `customerid`= :customerid AND `id`= :id");
$res_quota = Database::pexecute_first($stmt, array(
"customerid" => $customer['customerid'],
"id" => $result['popaccountid']
), true, true);
Customers::decreaseUsage($customer['customerid'], 'email_quota_used', '', $res_quota['quota']);
Admins::decreaseUsage($customer['customerid'], 'email_quota_used', '', $res_quota['quota']);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted quota entries for email address '" . $result['email_full'] . "'");
}
// delete account
$stmt = Database::prepare("DELETE FROM `" . TABLE_MAIL_USERS . "` WHERE `customerid`= :customerid AND `id`= :id");
Database::pexecute($stmt, array(
"customerid" => $customer['customerid'],
"id" => $result['popaccountid']
), true, true);
Customers::decreaseUsage($customer['customerid'], 'email_accounts_used');
Admins::decreaseUsage($customer['customerid'], 'email_accounts_used');
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted email account '" . $result['email_full'] . "'");
// use EmailAccounts.delete
$this->apiCall('EmailAccounts.delete', array(
'id' => $result['id'],
'customerid' => $customer['customerid'],
'delete_userfiles' => $delete_userfiles
));
$number_forwarders --;
}

View File

@@ -26,7 +26,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
*
* @access admin
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{
@@ -80,7 +80,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function get()
{
@@ -126,7 +126,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
@@ -237,7 +237,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function update()
{
@@ -332,7 +332,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function delete()
{

View File

@@ -27,7 +27,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand
*
* @access admin
* @throws \Exception
* @return string
* @return string json-encoded array
*/
public function checkUpdate()
{
@@ -39,7 +39,11 @@ class Froxlor extends \Froxlor\Api\ApiCommand
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] checking for updates");
// check for new version
$latestversion = \Froxlor\Http\HttpClient::urlGet(UPDATE_URI);
try {
$latestversion = \Froxlor\Http\HttpClient::urlGet(UPDATE_URI, true, 3);
} catch (\Exception $e) {
$latestversion = \Froxlor\Froxlor::getVersion()."|Version-check currently unavailable, please try again later";
}
$latestversion = explode('|', $latestversion);
if (is_array($latestversion) && count($latestversion) >= 1) {
@@ -110,7 +114,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand
*
* @access admin
* @throws \Exception
* @return bool
* @return string json-encoded bool
*/
public function importSettings()
{
@@ -155,7 +159,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand
*
* @access admin
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listSettings()
{
@@ -236,7 +240,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function listFunctions()
{

View File

@@ -41,10 +41,14 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
* optional if customer.ftpatdomain is allowed, specify a domain (customer must be owner)
* @param int $customerid
* required when called as admin, not needed when called as customer
* @param array $additional_members
* optional whether to add additional usernames to the group
* @param bool $is_defaultuser
* optional whether this is the standard default ftp user which is being added so no usage is decreased
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
@@ -52,7 +56,9 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
throw new \Exception("You cannot access this resource", 405);
}
if ($this->getUserDetail('ftps_used') < $this->getUserDetail('ftps') || $this->getUserDetail('ftps') == '-1') {
$is_defaultuser = $this->getBoolParam('is_defaultuser', true, 0);
if (($this->getUserDetail('ftps_used') < $this->getUserDetail('ftps') || $this->getUserDetail('ftps') == '-1') || $this->isAdmin() && $is_defaultuser == 1) {
// required paramters
$path = $this->getParam('path');
@@ -66,6 +72,8 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
$ftpusername = $this->getParam('ftp_username', true, '');
$ftpdomain = $this->getParam('ftp_domain', true, '');
$additional_members = $this->getParam('additional_members', true, array());
// validation
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
$password = \Froxlor\System\Crypt::validatePassword($password, true);
@@ -87,13 +95,18 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
$params = array();
// get needed customer info to reduce the ftp-user-counter by one
$customer = $this->getCustomerData('ftps');
if ($is_defaultuser) {
// no resource check for default user
$customer = $this->getCustomerData();
} else {
$customer = $this->getCustomerData('ftps');
}
if ($sendinfomail != 1) {
$sendinfomail = 0;
}
if (Settings::Get('customer.ftpatdomain') == '1') {
if (Settings::Get('customer.ftpatdomain') == '1' && ! $is_defaultuser) {
if ($ftpusername == '') {
\Froxlor\UI\Response::standard_error(array(
'stringisempty',
@@ -113,7 +126,11 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
}
$username = $ftpusername . "@" . $ftpdomain;
} else {
$username = $customer['loginname'] . Settings::Get('customer.ftpprefix') . (intval($customer['ftp_lastaccountnumber']) + 1);
if ($is_defaultuser) {
$username = $customer['loginname'];
} else {
$username = $customer['loginname'] . Settings::Get('customer.ftpprefix') . (intval($customer['ftp_lastaccountnumber']) + 1);
}
}
$username_check_stmt = Database::prepare("
@@ -163,7 +180,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
), true, true);
}
$stmt = Database::prepare("
$group_upd_stmt = Database::prepare("
UPDATE `" . TABLE_FTP_GROUPS . "`
SET `members` = CONCAT_WS(',',`members`, :username)
WHERE `customerid`= :customerid AND `gid`= :guid
@@ -173,12 +190,35 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
"customerid" => $customer['customerid'],
"guid" => $customer['guid']
);
Database::pexecute($stmt, $params, true, true);
// update customer usage
Customers::increaseUsage($customer['customerid'], 'ftps_used');
Customers::increaseUsage($customer['customerid'], 'ftp_lastaccountnumber');
if ($is_defaultuser) {
// add the new group
$group_ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_FTP_GROUPS . "`
SET `customerid`= :customerid, `gid`= :guid, `groupname` = :username, `members` = :username
");
Database::pexecute($group_ins_stmt, $params, true, true);
} else {
// just update
Database::pexecute($group_upd_stmt, $params, true, true);
}
if (count($additional_members) > 0) {
foreach ($additional_members as $add_member) {
$params = array(
"username" => $add_member,
"customerid" => $customer['customerid'],
"guid" => $customer['guid']
);
Database::pexecute($group_upd_stmt, $params, true, true);
}
}
if (! $is_defaultuser) {
// update customer usage
Customers::increaseUsage($customer['customerid'], 'ftps_used');
Customers::increaseUsage($customer['customerid'], 'ftp_lastaccountnumber');
}
$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);
@@ -240,7 +280,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function get()
{
@@ -311,7 +351,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function update()
{
@@ -423,7 +463,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
*
* @access admin, customer
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{
@@ -456,7 +496,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function delete()
{
@@ -502,6 +542,9 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
"username" => $customer_data['loginname']
);
Database::pexecute($stmt, $params, true, true);
} else {
// do not allow removing default ftp-account
\Froxlor\UI\Response::standard_error('ftp_cantdeletemainaccount', '', true);
}
// remove all quotatallies

View File

@@ -1,6 +1,9 @@
<?php
namespace Froxlor\Api\Commands;
use Froxlor\Settings;
use Froxlor\Database\Database;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
@@ -19,28 +22,380 @@ namespace Froxlor\Api\Commands;
class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity
{
public function add()
{
throw new \Exception('noop', 303);
}
public function get()
{
throw new \Exception('noop', 303);
}
public function update()
{
throw new \Exception('noop', 303);
}
/**
* list all available hosting plans
*
* @access admin
* @throws \Exception
* @return string json-encoded array count|list
*/
public function listing()
{
throw new \Exception('noop', 303);
if ($this->isAdmin()) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list hosting-plans");
$result_stmt = Database::prepare("
SELECT p.*, a.loginname as adminname
FROM `" . TABLE_PANEL_PLANS . "` p, `" . TABLE_PANEL_ADMINS . "` a
WHERE `p`.`adminid` = `a`.`adminid`" . ($this->getUserDetail('customers_see_all') ? '' : " AND `p`.`adminid` = :adminid "));
$params = array();
if ($this->getUserDetail('customers_see_all') == '0') {
$params['adminid'] = $this->getUserDetail('adminid');
}
Database::pexecute($result_stmt, $params);
$result = array();
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
}
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* return a hosting-plan entry by either id or plan-name
*
* @param int $id
* optional, the hosting-plan-id
* @param string $planname
* optional, the hosting-plan-name
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function get()
{
if ($this->isAdmin()) {
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$planname = $this->getParam('planname', $dn_optional, '');
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_PLANS . "` WHERE " . ($id > 0 ? "`id` = :iddn" : "`name` = :iddn") . ($this->getUserDetail('customers_see_all') ? '' : " AND `adminid` = :adminid"));
$params = array(
'iddn' => ($id <= 0 ? $planname : $id)
);
if ($this->getUserDetail('customers_see_all') == '0') {
$params['adminid'] = $this->getUserDetail('adminid');
}
$result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get hosting-plan '" . $result['name'] . "'");
return $this->response(200, "successfull", $result);
}
$key = ($id > 0 ? "id #" . $id : "planname '" . $planname . "'");
throw new \Exception("Hosting-plan with " . $key . " could not be found", 404);
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* add new hosting-plan
*
* @param string $name
* name of the plan
* @param string $description
* optional, description for hosting-plan
* @param int $diskspace
* optional disk-space available for customer in MB, default 0
* @param bool $diskspace_ul
* optional, whether customer should have unlimited diskspace, default 0 (false)
* @param int $traffic
* optional traffic available for customer in GB, default 0
* @param bool $traffic_ul
* optional, whether customer should have unlimited traffic, default 0 (false)
* @param int $subdomains
* optional amount of subdomains available for customer, default 0
* @param bool $subdomains_ul
* optional, whether customer should have unlimited subdomains, default 0 (false)
* @param int $emails
* optional amount of emails available for customer, default 0
* @param bool $emails_ul
* optional, whether customer should have unlimited emails, default 0 (false)
* @param int $email_accounts
* optional amount of email-accounts available for customer, default 0
* @param bool $email_accounts_ul
* optional, whether customer should have unlimited email-accounts, default 0 (false)
* @param int $email_forwarders
* optional amount of email-forwarders available for customer, default 0
* @param bool $email_forwarders_ul
* optional, whether customer should have unlimited email-forwarders, default 0 (false)
* @param int $email_quota
* optional size of email-quota available for customer in MB, default is system-setting mail_quota
* @param bool $email_quota_ul
* optional, whether customer should have unlimited email-quota, default 0 (false)
* @param bool $email_imap
* optional, whether to allow IMAP access, default 0 (false)
* @param bool $email_pop3
* optional, whether to allow POP3 access, default 0 (false)
* @param int $ftps
* optional amount of ftp-accounts available for customer, default 0
* @param bool $ftps_ul
* optional, whether customer should have unlimited ftp-accounts, default 0 (false)
* @param int $mysqls
* optional amount of mysql-databases available for customer, default 0
* @param bool $mysqls_ul
* optional, whether customer should have unlimited mysql-databases, default 0 (false)
* @param bool $phpenabled
* optional, whether to allow usage of PHP, default 0 (false)
* @param array $allowed_phpconfigs
* optional, array of IDs of php-config that the customer is allowed to use, default empty (none)
* @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)
* @param bool $logviewenabled
* optional, ether to allow acccess to webserver access/error-logs, default 0 (false)
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function add()
{
if ($this->isAdmin()) {
$name = $this->getParam('name');
$description = $this->getParam('description', true, '');
$value_arr = array();
$value_arr['diskspace'] = $this->getUlParam('diskspace', 'diskspace_ul', true, 0);
$value_arr['traffic'] = $this->getUlParam('traffic', 'traffic_ul', true, 0);
$value_arr['subdomains'] = $this->getUlParam('subdomains', 'subdomains_ul', true, 0);
$value_arr['emails'] = $this->getUlParam('emails', 'emails_ul', true, 0);
$value_arr['email_accounts'] = $this->getUlParam('email_accounts', 'email_accounts_ul', true, 0);
$value_arr['email_forwarders'] = $this->getUlParam('email_forwarders', 'email_forwarders_ul', true, 0);
$value_arr['email_quota'] = $this->getUlParam('email_quota', 'email_quota_ul', true, Settings::Get('system.mail_quota'));
$value_arr['email_imap'] = $this->getBoolParam('email_imap', true, 0);
$value_arr['email_pop3'] = $this->getBoolParam('email_pop3', true, 0);
$value_arr['ftps'] = $this->getUlParam('ftps', 'ftps_ul', true, 0);
$value_arr['mysqls'] = $this->getUlParam('mysqls', 'mysqls_ul', true, 0);
$value_arr['phpenabled'] = $this->getBoolParam('phpenabled', true, 0);
$p_allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, array());
$value_arr['perlenabled'] = $this->getBoolParam('perlenabled', true, 0);
$value_arr['dnsenabled'] = $this->getBoolParam('dnsenabled', true, 0);
$value_arr['logviewenabled'] = $this->getBoolParam('logviewenabled', true, 0);
// validation
$name = \Froxlor\Validate\Validate::validate(trim($name), 'name', '', '', array(), true);
$description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $description), 'description', '/^[^\0]*$/');
if (Settings::Get('system.mail_quota_enabled') != '1') {
$value_arr['email_quota'] = - 1;
}
$value_arr['allowed_phpconfigs'] = array();
if (! empty($p_allowed_phpconfigs) && is_array($p_allowed_phpconfigs)) {
foreach ($p_allowed_phpconfigs as $allowed_phpconfig) {
$allowed_phpconfig = intval($allowed_phpconfig);
$value_arr['allowed_phpconfigs'][] = $allowed_phpconfig;
}
}
$value_arr['allowed_phpconfigs'] = array_map('intval', $value_arr['allowed_phpconfigs']);
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_PLANS . "`
SET `adminid` = :adminid, `name` = :name, `description` = :desc, `value` = :valuearr, `ts` = UNIX_TIMESTAMP();
");
$ins_data = array(
'adminid' => $this->getUserDetail('adminid'),
'name' => $name,
'desc' => $description,
'valuearr' => json_encode($value_arr)
);
Database::pexecute($ins_stmt, $ins_data, true, true);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added hosting-plan '" . $name . "'");
$result = $this->apiCall('HostingPlans.get', array(
'planname' => $name
));
return $this->response(200, "successfull", $result);
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* update hosting-plan by either id or plan-name
*
* @param int $id
* optional the hosting-plan-id
* @param string $planname
* optional the hosting-plan-name
* @param string $name
* optional name of the plan
* @param string $description
* optional description for hosting-plan
* @param int $diskspace
* optional disk-space available for customer in MB, default 0
* @param bool $diskspace_ul
* optional, whether customer should have unlimited diskspace, default 0 (false)
* @param int $traffic
* optional traffic available for customer in GB, default 0
* @param bool $traffic_ul
* optional, whether customer should have unlimited traffic, default 0 (false)
* @param int $subdomains
* optional amount of subdomains available for customer, default 0
* @param bool $subdomains_ul
* optional, whether customer should have unlimited subdomains, default 0 (false)
* @param int $emails
* optional amount of emails available for customer, default 0
* @param bool $emails_ul
* optional, whether customer should have unlimited emails, default 0 (false)
* @param int $email_accounts
* optional amount of email-accounts available for customer, default 0
* @param bool $email_accounts_ul
* optional, whether customer should have unlimited email-accounts, default 0 (false)
* @param int $email_forwarders
* optional amount of email-forwarders available for customer, default 0
* @param bool $email_forwarders_ul
* optional, whether customer should have unlimited email-forwarders, default 0 (false)
* @param int $email_quota
* optional size of email-quota available for customer in MB, default is system-setting mail_quota
* @param bool $email_quota_ul
* optional, whether customer should have unlimited email-quota, default 0 (false)
* @param bool $email_imap
* optional, whether to allow IMAP access, default 0 (false)
* @param bool $email_pop3
* optional, whether to allow POP3 access, default 0 (false)
* @param int $ftps
* optional amount of ftp-accounts available for customer, default 0
* @param bool $ftps_ul
* optional, whether customer should have unlimited ftp-accounts, default 0 (false)
* @param int $mysqls
* optional amount of mysql-databases available for customer, default 0
* @param bool $mysqls_ul
* optional, whether customer should have unlimited mysql-databases, default 0 (false)
* @param bool $phpenabled
* optional, whether to allow usage of PHP, default 0 (false)
* @param array $allowed_phpconfigs
* optional, array of IDs of php-config that the customer is allowed to use, default empty (none)
* @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)
* @param bool $logviewenabled
* optional, ether to allow acccess to webserver access/error-logs, default 0 (false)
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function update()
{
if ($this->isAdmin()) {
// parameters
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$planname = $this->getParam('planname', $dn_optional, '');
// get requested hosting-plan
$result = $this->apiCall('HostingPlans.get', array(
'id' => $id,
'planname' => $planname
));
$id = $result['id'];
$result['value'] = json_decode($result['value'], true);
foreach ($result['value'] as $index => $value) {
$result[$index] = $value;
}
$name = $this->getParam('name', true, $result['name']);
$description = $this->getParam('description', true, $result['description']);
$value_arr = array();
$value_arr['diskspace'] = $this->getUlParam('diskspace', 'diskspace_ul', true, $result['diskspace']);
$value_arr['traffic'] = $this->getUlParam('traffic', 'traffic_ul', true, $result['traffic']);
$value_arr['subdomains'] = $this->getUlParam('subdomains', 'subdomains_ul', true, $result['subdomains']);
$value_arr['emails'] = $this->getUlParam('emails', 'emails_ul', true, $result['emails']);
$value_arr['email_accounts'] = $this->getUlParam('email_accounts', 'email_accounts_ul', true, $result['email_accounts']);
$value_arr['email_forwarders'] = $this->getUlParam('email_forwarders', 'email_forwarders_ul', true, $result['email_forwarders']);
$value_arr['email_quota'] = $this->getUlParam('email_quota', 'email_quota_ul', true, $result['email_quota']);
$value_arr['email_imap'] = $this->getParam('email_imap', true, $result['email_imap']);
$value_arr['email_pop3'] = $this->getParam('email_pop3', true, $result['email_pop3']);
$value_arr['ftps'] = $this->getUlParam('ftps', 'ftps_ul', true, $result['ftps']);
$value_arr['mysqls'] = $this->getUlParam('mysqls', 'mysqls_ul', true, $result['mysqls']);
$value_arr['phpenabled'] = $this->getBoolParam('phpenabled', true, $result['phpenabled']);
$p_allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, $result['allowed_phpconfigs']);
$value_arr['perlenabled'] = $this->getBoolParam('perlenabled', true, $result['perlenabled']);
$value_arr['dnsenabled'] = $this->getBoolParam('dnsenabled', true, $result['dnsenabled']);
$value_arr['logviewenabled'] = $this->getBoolParam('logviewenabled', true, $result['logviewenabled']);
// validation
$name = \Froxlor\Validate\Validate::validate(trim($name), 'name', '', '', array(), true);
$description = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $description), 'description', '/^[^\0]*$/');
if (Settings::Get('system.mail_quota_enabled') != '1') {
$value_arr['email_quota'] = - 1;
}
if (empty($name)) {
$name = $result['name'];
}
$value_arr['allowed_phpconfigs'] = array();
if (! empty($p_allowed_phpconfigs) && is_array($p_allowed_phpconfigs)) {
foreach ($p_allowed_phpconfigs as $allowed_phpconfig) {
$allowed_phpconfig = intval($allowed_phpconfig);
$value_arr['allowed_phpconfigs'][] = $allowed_phpconfig;
}
}
$value_arr['allowed_phpconfigs'] = array_map('intval', $value_arr['allowed_phpconfigs']);
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_PLANS . "`
SET `name` = :name, `description` = :desc, `value` = :valuearr, `ts` = UNIX_TIMESTAMP()
WHERE `id` = :id
");
$update_data = array(
'name' => $name,
'desc' => $description,
'valuearr' => json_encode($value_arr),
'id' => $id
);
Database::pexecute($upd_stmt, $update_data, true, true);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated hosting-plan '" . $result['name'] . "'");
return $this->response(200, "successfull", $update_data);
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* delete hosting-plan by either id or plan-name
*
* @param int $id
* optional the hosting-plan-id
* @param string $planname
* optional the hosting-plan-name
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function delete()
{
throw new \Exception('noop', 303);
if ($this->isAdmin()) {
$id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true);
$planname = $this->getParam('planname', $dn_optional, '');
// get requested hosting-plan
$result = $this->apiCall('HostingPlans.get', array(
'id' => $id,
'planname' => $planname
));
$id = $result['id'];
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_PLANS . "` WHERE `id` = :id
");
Database::pexecute($del_stmt, array(
'id' => $id
), true, true);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted hosting-plan '" . $result['name'] . "'");
return $this->response(200, "successfull", $result);
}
throw new \Exception("Not allowed to execute given command.", 403);
}
}

View File

@@ -27,7 +27,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
*
* @access admin
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{
@@ -61,7 +61,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function get()
{
@@ -118,16 +118,24 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
* optional, requires $ssl = 1, default empty
* @param string $ssl_cert_chainfile
* optional, requires $ssl = 1, default empty
* @param string $ssl_specialsettings
* optional, requires $ssl = 1, default empty
* @param bool $include_specialsettings
* optional, requires $ssl = 1, whether or not to include non-ssl specialsettings, default false
* @param string $ssl_default_vhostconf_domain
* optional, requires $ssl = 1, defatul empty
* @param bool $include_default_vhostconf_domain
* optional, requires $ssl = 1, whether or not to include non-ssl default_vhostconf_domain, default false
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
$ip = \Froxlor\Validate\Validate::validate_ip2($this->getParam('ip'), false, 'invalidip', false, false, false, true);
$ip = \Froxlor\Validate\Validate::validate_ip2($this->getParam('ip'), false, 'invalidip', false, false, false, false, true);
$port = \Froxlor\Validate\Validate::validate($this->getParam('port', true, 80), 'port', '/^(([1-9])|([1-9][0-9])|([1-9][0-9][0-9])|([1-9][0-9][0-9][0-9])|([1-5][0-9][0-9][0-9][0-9])|(6[0-4][0-9][0-9][0-9])|(65[0-4][0-9][0-9])|(655[0-2][0-9])|(6553[0-5]))$/Di', array(
'stringisempty',
'myport'
@@ -146,12 +154,20 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$ssl_key_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_key_file', $ssl, ''), 'ssl_key_file', '', '', array(), true);
$ssl_ca_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_ca_file', true, ''), 'ssl_ca_file', '', '', array(), true);
$ssl_cert_chainfile = \Froxlor\Validate\Validate::validate($this->getParam('ssl_cert_chainfile', true, ''), 'ssl_cert_chainfile', '', '', array(), true);
$ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, '')), 'ssl_specialsettings', '/^[^\0]*$/', '', array(), true);
$include_specialsettings = ! empty($this->getBoolParam('include_specialsettings', true, 0)) ? 1 : 0;
$ssl_default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, '')), 'ssl_default_vhostconf_domain', '/^[^\0]*$/', '', array(), true);
$include_default_vhostconf_domain = ! empty($this->getBoolParam('include_default_vhostconf_domain', true, 0)) ? 1 : 0;
} else {
$ssl = 0;
$ssl_cert_file = '';
$ssl_key_file = '';
$ssl_ca_file = '';
$ssl_cert_chainfile = '';
$ssl_specialsettings = '';
$include_specialsettings = 0;
$ssl_default_vhostconf_domain = '';
$include_default_vhostconf_domain = 0;
}
if ($listen_statement != '1') {
@@ -217,7 +233,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
`specialsettings` = :ss, `ssl` = :ssl,
`ssl_cert_file` = :ssl_cert, `ssl_key_file` = :ssl_key,
`ssl_ca_file` = :ssl_ca, `ssl_cert_chainfile` = :ssl_chain,
`default_vhostconf_domain` = :dvhd, `docroot` = :docroot;
`default_vhostconf_domain` = :dvhd, `docroot` = :docroot,
`ssl_specialsettings` = :ssl_ss, `include_specialsettings` = :incss,
`ssl_default_vhostconf_domain` = :ssl_dvhd, `include_default_vhostconf_domain` = :incdvhd;
");
$ins_data = array(
'ip' => $ip,
@@ -233,7 +251,11 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
'ssl_ca' => $ssl_ca_file,
'ssl_chain' => $ssl_cert_chainfile,
'dvhd' => $default_vhostconf_domain,
'docroot' => $docroot
'docroot' => $docroot,
'ssl_ss' => $ssl_specialsettings,
'incss' => $include_specialsettings,
'ssl_dvhd' => $ssl_default_vhostconf_domain,
'incdvhd' => $include_default_vhostconf_domain
);
Database::pexecute($ins_stmt, $ins_data);
$ins_data['id'] = Database::lastInsertId();
@@ -287,11 +309,19 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
* optional, requires $ssl = 1, default empty
* @param string $ssl_cert_chainfile
* optional, requires $ssl = 1, default empty
* @param string $ssl_specialsettings
* optional, requires $ssl = 1, default empty
* @param bool $include_specialsettings
* optional, requires $ssl = 1, whether or not to include non-ssl specialsettings, default false
* @param string $ssl_default_vhostconf_domain
* optional, requires $ssl = 1, defatul empty
* @param bool $include_default_vhostconf_domain
* optional, requires $ssl = 1, whether or not to include non-ssl default_vhostconf_domain, default false
*
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function update()
{
@@ -302,7 +332,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
'id' => $id
));
$ip = \Froxlor\Validate\Validate::validate_ip2($this->getParam('ip', true, $result['ip']), false, 'invalidip', false, false, false, true);
$ip = \Froxlor\Validate\Validate::validate_ip2($this->getParam('ip', true, $result['ip']), false, 'invalidip', false, false, false, false, true);
$port = \Froxlor\Validate\Validate::validate($this->getParam('port', true, $result['port']), 'port', '/^(([1-9])|([1-9][0-9])|([1-9][0-9][0-9])|([1-9][0-9][0-9][0-9])|([1-5][0-9][0-9][0-9][0-9])|(6[0-4][0-9][0-9][0-9])|(65[0-4][0-9][0-9])|(655[0-2][0-9])|(6553[0-5]))$/Di', array(
'stringisempty',
'myport'
@@ -321,12 +351,20 @@ 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', '/^[^\0]*$/', '', 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', '/^[^\0]*$/', '', array(), true);
$include_default_vhostconf_domain = $this->getBoolParam('include_default_vhostconf_domain', true, $result['include_default_vhostconf_domain']);
} else {
$ssl = 0;
$ssl_cert_file = '';
$ssl_key_file = '';
$ssl_ca_file = '';
$ssl_cert_chainfile = '';
$ssl_specialsettings = '';
$include_specialsettings = 0;
$ssl_default_vhostconf_domain = '';
$include_default_vhostconf_domain = 0;
}
$result_checkfordouble_stmt = Database::prepare("
@@ -404,7 +442,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
`specialsettings` = :ss, `ssl` = :ssl,
`ssl_cert_file` = :ssl_cert, `ssl_key_file` = :ssl_key,
`ssl_ca_file` = :ssl_ca, `ssl_cert_chainfile` = :ssl_chain,
`default_vhostconf_domain` = :dvhd, `docroot` = :docroot
`default_vhostconf_domain` = :dvhd, `docroot` = :docroot,
`ssl_specialsettings` = :ssl_ss, `include_specialsettings` = :incss,
`ssl_default_vhostconf_domain` = :ssl_dvhd, `include_default_vhostconf_domain` = :incdvhd
WHERE `id` = :id;
");
$upd_data = array(
@@ -422,6 +462,10 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
'ssl_chain' => $ssl_cert_chainfile,
'dvhd' => $default_vhostconf_domain,
'docroot' => $docroot,
'ssl_ss' => $ssl_specialsettings,
'incss' => $include_specialsettings,
'ssl_dvhd' => $ssl_default_vhostconf_domain,
'incdvhd' => $include_default_vhostconf_domain,
'id' => $id
);
Database::pexecute($upd_stmt, $upd_data);
@@ -449,7 +493,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function delete()
{

View File

@@ -33,12 +33,12 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, description for database
* @param bool $sendinfomail
* optional, send created resource-information to customer, default: false
* @param int $customer_id
* @param int $customerid
* required when called as admin, not needed when called as customer
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
@@ -183,7 +183,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function get()
{
@@ -279,7 +279,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function update()
{
@@ -362,7 +362,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*
* @access admin, customer
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{
@@ -428,7 +428,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function delete()
{

View File

@@ -30,7 +30,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
*
* @access admin
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{
@@ -123,7 +123,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function get()
{
@@ -192,7 +192,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
@@ -393,7 +393,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function update()
{
@@ -548,7 +548,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
*
* @access admin
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function delete()
{

View File

@@ -45,6 +45,8 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled
* @param bool $letsencrypt
* optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled
* @param bool $http2
* optional, whether to enable http/2 for this subdomain (requires to be enabled in the settings), default 0 (false)
* @param int $hsts_maxage
* optional max-age value for HSTS header, default 0
* @param bool $hsts_sub
@@ -56,7 +58,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function add()
{
@@ -76,12 +78,14 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
if (Settings::Get('system.use_ssl')) {
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, 0);
$letsencrypt = $this->getBoolParam('letsencrypt', true, 0);
$http2 = $this->getBoolParam('http2', true, 0);
$hsts_maxage = $this->getParam('hsts_maxage', true, 0);
$hsts_sub = $this->getBoolParam('hsts_sub', true, 0);
$hsts_preload = $this->getBoolParam('hsts_preload', true, 0);
} else {
$ssl_redirect = 0;
$letsencrypt = 0;
$http2 = 0;
$hsts_maxage = 0;
$hsts_sub = 0;
$hsts_preload = 0;
@@ -241,7 +245,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$phpsid_result['phpsettingid'] = intval($phpsettingid);
}
// acutall insert domain
// actually insert domain
$stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_DOMAINS . "` SET
`customerid` = :customerid,
@@ -258,12 +262,20 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
`openbasedir_path` = :openbasedir_path,
`speciallogfile` = :speciallogfile,
`specialsettings` = :specialsettings,
`ssl_specialsettings` = :ssl_specialsettings,
`include_specialsettings` = :include_specialsettings,
`ssl_redirect` = :ssl_redirect,
`phpsettingid` = :phpsettingid,
`letsencrypt` = :letsencrypt,
`http2` = :http2,
`hsts` = :hsts,
`hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload
`hsts_preload` = :hsts_preload,
`ocsp_stapling` = :ocsp_stapling,
`override_tls` = :override_tls,
`ssl_protocols` = :ssl_protocols,
`ssl_cipher_list` = :ssl_cipher_list,
`tlsv13_cipher_list` = :tlsv13_cipher_list
");
$params = array(
"customerid" => $customer['customerid'],
@@ -280,12 +292,20 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
"phpenabled" => $domain_check['phpenabled'],
"speciallogfile" => $domain_check['speciallogfile'],
"specialsettings" => $domain_check['specialsettings'],
"ssl_specialsettings" => $domain_check['ssl_specialsettings'],
"include_specialsettings" => $domain_check['include_specialsettings'],
"ssl_redirect" => $ssl_redirect,
"phpsettingid" => $phpsid_result['phpsettingid'],
"letsencrypt" => $letsencrypt,
"http2" => $http2,
"hsts" => $hsts_maxage,
"hsts_sub" => $hsts_sub,
"hsts_preload" => $hsts_preload
"hsts_preload" => $hsts_preload,
"ocsp_stapling" => $domain_check['ocsp_stapling'],
"override_tls" => $domain_check['override_tls'],
"ssl_protocols" => $domain_check['ssl_protocols'],
"ssl_cipher_list" => $domain_check['ssl_cipher_list'],
"tlsv13_cipher_list" => $domain_check['tlsv13_cipher_list']
);
Database::pexecute($stmt, $params, true, true);
$subdomain_id = Database::lastInsertId();
@@ -331,7 +351,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function get()
{
@@ -430,6 +450,8 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled
* @param bool $letsencrypt
* optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled
* @param bool $http2
* optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default 0 (false)
* @param int $hsts_maxage
* optional max-age value for HSTS header
* @param bool $hsts_sub
@@ -441,7 +463,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function update()
{
@@ -473,12 +495,14 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
if (Settings::Get('system.use_ssl')) {
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, $result['ssl_redirect']);
$letsencrypt = $this->getBoolParam('letsencrypt', true, $result['letsencrypt']);
$http2 = $this->getBoolParam('http2', true, $result['http2']);
$hsts_maxage = $this->getParam('hsts_maxage', true, $result['hsts']);
$hsts_sub = $this->getBoolParam('hsts_sub', true, $result['hsts_sub']);
$hsts_preload = $this->getBoolParam('hsts_preload', true, $result['hsts_preload']);
} else {
$ssl_redirect = 0;
$letsencrypt = 0;
$http2 = 0;
$hsts_maxage = 0;
$hsts_sub = 0;
$hsts_preload = 0;
@@ -554,15 +578,10 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
}
}
// We can't enable let's encrypt for wildcard - domains when using acme-v1
if ($iswildcarddomain == '1' && $letsencrypt == '1' && Settings::Get('system.leapiversion') == '1') {
// We can't enable let's encrypt for wildcard-domains
if ($iswildcarddomain == '1' && $letsencrypt == '1') {
\Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt');
}
// if using acme-v2 we cannot issue wildcard-certificates
// because they currently only support the dns-01 challenge
if ($iswildcarddomain == '0' && $letsencrypt == '1' && Settings::Get('system.leapiversion') == '2') {
\Froxlor\UI\Response::standard_error('nowildcardwithletsencryptv2');
}
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
if ($ssl_redirect > 0 && $letsencrypt == 1 && $result['letsencrypt'] != $letsencrypt) {
@@ -599,6 +618,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
`openbasedir_path`= :openbasedir_path,
`ssl_redirect`= :ssl_redirect,
`letsencrypt`= :letsencrypt,
`http2` = :http2,
`hsts` = :hsts,
`hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload,
@@ -614,6 +634,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
"openbasedir_path" => $openbasedir_path,
"ssl_redirect" => $ssl_redirect,
"letsencrypt" => $letsencrypt,
"http2" => $http2,
"hsts" => $hsts_maxage,
"hsts_sub" => $hsts_sub,
"hsts_preload" => $hsts_preload,
@@ -623,13 +644,20 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
);
Database::pexecute($stmt, $params, true, true);
if ($result['aliasdomain'] != $aliasdomain) {
if ($result['aliasdomain'] != $aliasdomain && is_numeric($result['aliasdomain'])) {
// trigger when domain id for alias destination has changed: both for old and new destination
\Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger());
\Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger());
} elseif ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) {
}
if ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) {
// or when wwwserveralias or letsencrypt was changed
\Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $this->logger());
if ((int) $aliasdomain === 0) {
// in case the wwwserveralias is set on a main domain, $aliasdomain is 0
// --> the call just above to triggerLetsEncryptCSRForAliasDestinationDomain
// is a noop...let's repeat it with the domain id of the main domain
\Froxlor\Domain\Domain::triggerLetsEncryptCSRForAliasDestinationDomain($id, $this->logger());
}
}
// check whether LE has been disabled, so we remove the certificate
@@ -658,7 +686,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
*
* @access admin, customer
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{
@@ -735,7 +763,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
*
* @access admin, customer
* @throws \Exception
* @return array
* @return string json-encoded array
*/
public function delete()
{
@@ -828,6 +856,8 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
\Froxlor\System\Cronjob::inserttask('4');
// remove domains DNS from powerDNS if used, #581
\Froxlor\System\Cronjob::inserttask('11', $result['domain']);
// remove domain from acme.sh / lets encrypt if used
\Froxlor\System\Cronjob::inserttask('12', $result['domain']);
// reduce subdomain-usage-counter
Customers::decreaseUsage($customer['customerid'], 'subdomains_used');
@@ -852,7 +882,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
{
// check whether an URL was specified
$_doredirect = false;
if (! empty($url) && \Froxlor\Validate\Form\Data::validateUrl($url)) {
if (! empty($url) && \Froxlor\Validate\Validate::validateUrl($url)) {
$path = $url;
$_doredirect = true;
} else {
@@ -860,7 +890,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
}
// check whether path is a real path
if (! preg_match('/^https?\:\/\//', $path) || ! \Froxlor\Validate\Form\Data::validateUrl($path)) {
if (! preg_match('/^https?\:\/\//', $path) || ! \Froxlor\Validate\Validate::validateUrl($path)) {
if (strstr($path, ":") !== false) {
\Froxlor\UI\Response::standard_error('pathmaynotcontaincolon', '', true);
}

View File

@@ -69,7 +69,7 @@ class Traffic extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
*
* @access admin, customer
* @throws \Exception
* @return array count|list
* @return string json-encoded array count|list
*/
public function listing()
{

View File

@@ -55,13 +55,20 @@ class FroxlorRPC
*/
private static function validateAuth($key, $secret)
{
$sel_stmt = \Froxlor\Database\Database::prepare("SELECT * FROM `api_keys` WHERE `apikey` = :ak AND `secret` = :as");
$sel_stmt = \Froxlor\Database\Database::prepare("
SELECT ak.*, a.api_allowed as admin_api_allowed, c.api_allowed as cust_api_allowed
FROM `api_keys` ak
LEFT JOIN `panel_admins` a ON a.adminid = ak.adminid
LEFT JOIN `panel_customers` c ON c.customerid = ak.customerid
WHERE `apikey` = :ak AND `secret` = :as
");
$result = \Froxlor\Database\Database::pexecute_first($sel_stmt, array(
'ak' => $key,
'as' => $secret
), true, true);
if ($result) {
if ($result['apikey'] == $key && $result['secret'] == $secret && ($result['valid_until'] == - 1 || $result['valid_until'] >= time())) {
if ($result['apikey'] == $key && $result['secret'] == $secret && ($result['valid_until'] == - 1 || $result['valid_until'] >= time()) && (($result['customerid'] == 0 && $result['admin_api_allowed'] == 1) || ($result['customerid'] > 0 && $result['cust_api_allowed'] == 1))) {
// get user to check whether api call is allowed
if (! empty($result['allowed_from'])) {
// @todo allow specification and validating of whole subnets later
$ip_list = explode(",", $result['allowed_from']);

View File

@@ -103,7 +103,7 @@ class ConfigServicesAction extends \Froxlor\Cli\Action
echo PHP_EOL;
while (! in_array($_daemons_config['distro'], $distributions_select_data)) {
$_daemons_config['distro'] = ConfigServicesCmd::getInput("choose distribution", "stretch");
$_daemons_config['distro'] = ConfigServicesCmd::getInput("choose distribution", "buster");
}
// go through all services and let user check whether to include it or not

0
lib/Froxlor/Cli/ConfigServicesCmd.php Executable file → Normal file
View File

0
lib/Froxlor/Cli/SwitchServerIpCmd.php Executable file → Normal file
View File

View File

@@ -61,6 +61,7 @@ class CronConfig
$month_delay = 7;
while ($row_cronentry = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
// create cron.d-entry
$matches = array();
if (preg_match("/(\d+) (MINUTE|HOUR|DAY|WEEK|MONTH)/", $row_cronentry['interval'], $matches)) {
if ($matches[1] == 1) {
$minvalue = "*";
@@ -101,7 +102,7 @@ class CronConfig
$binpath = "/usr/bin/nice -n 5 /usr/bin/php5 -q";
}
$cronfile .= "root " . $binpath . " " . \Froxlor\Froxlor::getInstallDir() . "/scripts/froxlor_master_cronjob.php --" . $row_cronentry['cronfile'] . " 1> /dev/null\n";
$cronfile .= "root " . $binpath . " " . \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . "/scripts/froxlor_master_cronjob.php") . " --" . $row_cronentry['cronfile'] . " 1> /dev/null\n";
}
}

View File

@@ -111,7 +111,7 @@ class PowerDNS extends DnsBase
private function insertZone($domainname, $serial = 0)
{
$ins_stmt = PowerDNS::getDB()->prepare("
$ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("
INSERT INTO domains set `name` = :domainname, `notified_serial` = :serial, `type` = 'NATIVE'
");
$ins_stmt->execute(array(
@@ -124,7 +124,7 @@ class PowerDNS extends DnsBase
private function insertRecords($domainid = 0, $records = array(), $origin = "")
{
$ins_stmt = PowerDNS::getDB()->prepare("
$ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("
INSERT INTO records set
`domain_id` = :did,
`name` = :rec,
@@ -161,7 +161,7 @@ class PowerDNS extends DnsBase
private function insertAllowedTransfers($domainid)
{
$ins_stmt = PowerDNS::getDB()->prepare("
$ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("
INSERT INTO domainmetadata set `domain_id` = :did, `kind` = 'ALLOW-AXFR-FROM', `content` = :value
");

View File

@@ -3,7 +3,6 @@ namespace Froxlor\Cron\Http;
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Cron\Http\Php\Fpm;
use Froxlor\Cron\Http\Php\PhpInterface;
/**
@@ -46,30 +45,6 @@ class Apache extends HttpConfigBase
*/
private $deactivated = false;
public function reload()
{
if ((int) Settings::Get('phpfpm.enabled') == 1) {
// get all start/stop commands
$startstop_sel = Database::prepare("SELECT reload_cmd, config_dir FROM `" . TABLE_PANEL_FPMDAEMONS . "`");
Database::pexecute($startstop_sel);
$restart_cmds = $startstop_sel->fetchAll(\PDO::FETCH_ASSOC);
// restart all php-fpm instances
foreach ($restart_cmds as $restart_cmd) {
// check whether the config dir is empty (no domains uses this daemon)
// so we need to create a dummy
$_conffiles = glob(\Froxlor\FileDir::makeCorrectFile($restart_cmd['config_dir'] . "/*.conf"));
if ($_conffiles === false || empty($_conffiles)) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'apache::reload: fpm config directory "' . $restart_cmd['config_dir'] . '" is empty. Creating dummy.');
Fpm::createDummyPool($restart_cmd['config_dir']);
}
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'apache::reload: running ' . $restart_cmd['reload_cmd']);
\Froxlor\FileDir::safe_exec(escapeshellcmd($restart_cmd['reload_cmd']));
}
}
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'apache::reload: reloading apache');
\Froxlor\FileDir::safe_exec(escapeshellcmd(Settings::Get('system.apachereload_command')));
}
/**
* define a standard <Directory>-statement, bug #32
*/
@@ -144,7 +119,7 @@ class Apache extends HttpConfigBase
foreach ($statusCodes as $statusCode) {
if (Settings::Get('defaultwebsrverrhandler.err' . $statusCode) != '') {
$defhandler = Settings::Get('defaultwebsrverrhandler.err' . $statusCode);
if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
if (substr($defhandler, 0, 1) != '"' && substr($defhandler, - 1, 1) != '"') {
$defhandler = '"' . \Froxlor\FileDir::makeCorrectFile($defhandler) . '"';
}
@@ -203,7 +178,7 @@ class Apache extends HttpConfigBase
$this->virtualhosts_data[$vhosts_filename] .= ' ServerName ' . Settings::Get('system.hostname') . "\n";
$froxlor_aliases = Settings::Get('system.froxloraliases');
if (!empty($froxlor_aliases)) {
if (! empty($froxlor_aliases)) {
$froxlor_aliases = explode(",", $froxlor_aliases);
$aliases = "";
foreach ($froxlor_aliases as $falias) {
@@ -212,7 +187,7 @@ class Apache extends HttpConfigBase
}
}
$aliases = trim($aliases);
if (!empty($aliases)) {
if (! empty($aliases)) {
$this->virtualhosts_data[$vhosts_filename] .= ' ServerAlias ' . $aliases . "\n";
}
}
@@ -428,11 +403,16 @@ class Apache extends HttpConfigBase
* end of dirprotection
*/
if ($row_ipsandports['specialsettings'] != '') {
if ($row_ipsandports['specialsettings'] != '' && ($row_ipsandports['ssl'] == '0' || ($row_ipsandports['ssl'] == '1' && Settings::Get('system.use_ssl') == '1' && $row_ipsandports['include_specialsettings'] == '1'))) {
$this->virtualhosts_data[$vhosts_filename] .= $this->processSpecialConfigTemplate($row_ipsandports['specialsettings'], $domain, $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n";
}
if ($row_ipsandports['ssl'] == '1' && Settings::Get('system.use_ssl') == '1') {
if ($row_ipsandports['ssl_specialsettings'] != '') {
$this->virtualhosts_data[$vhosts_filename] .= $this->processSpecialConfigTemplate($row_ipsandports['ssl_specialsettings'], $domain, $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n";
}
if ($row_ipsandports['ssl_cert_file'] == '') {
$row_ipsandports['ssl_cert_file'] = Settings::Get('system.ssl_cert_file');
if (! file_exists($row_ipsandports['ssl_cert_file'])) {
@@ -502,6 +482,10 @@ class Apache extends HttpConfigBase
// this makes it more secure, thx to Marcel (08/2013)
$this->virtualhosts_data[$vhosts_filename] .= ' SSLHonorCipherOrder On' . "\n";
$this->virtualhosts_data[$vhosts_filename] .= ' SSLCipherSuite ' . Settings::Get('system.ssl_cipher_list') . "\n";
$protocols = array_map('trim', explode(",", Settings::Get('system.ssl_protocols')));
if (in_array("TLSv1.3", $protocols) && ! empty(Settings::Get('system.tlsv13_cipher_list')) && Settings::Get('system.apache24') == 1) {
$this->virtualhosts_data[$vhosts_filename] .= ' SSLCipherSuite TLSv1.3 ' . Settings::Get('system.tlsv13_cipher_list') . "\n";
}
$this->virtualhosts_data[$vhosts_filename] .= ' SSLVerifyDepth 10' . "\n";
$this->virtualhosts_data[$vhosts_filename] .= ' SSLCertificateFile ' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_cert_file']) . "\n";
@@ -921,9 +905,12 @@ class Apache extends HttpConfigBase
$ipport = $domain['ip'] . ':' . $domain['port'] . ' ';
}
if ($ipandport['default_vhostconf_domain'] != '') {
if ($ipandport['default_vhostconf_domain'] != '' && ($ssl_vhost == false || ($ssl_vhost == true && $ipandport['include_default_vhostconf_domain'] == '1'))) {
$_vhost_content .= $this->processSpecialConfigTemplate($ipandport['default_vhostconf_domain'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
if ($ipandport['ssl_default_vhostconf_domain'] != '' && $ssl_vhost == true) {
$_vhost_content .= $this->processSpecialConfigTemplate($ipandport['ssl_default_vhostconf_domain'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
$ipportlist .= $ipport;
}
@@ -949,7 +936,7 @@ class Apache extends HttpConfigBase
'domainid' => $domain['id']
));
if ($ssldestport['port'] != '') {
if ($ssldestport && $ssldestport['port'] != '') {
$_sslport = ":" . $ssldestport['port'];
}
@@ -980,11 +967,16 @@ class Apache extends HttpConfigBase
}
if ($domain['ssl_cert_file'] != '') {
$ssl_protocols = ($domain['override_tls'] == '1' && ! empty($domain['ssl_protocols'])) ? $domain['ssl_protocols'] : Settings::Get('system.ssl_protocols');
$ssl_cipher_list = ($domain['override_tls'] == '1' && ! empty($domain['ssl_cipher_list'])) ? $domain['ssl_cipher_list'] : Settings::Get('system.ssl_cipher_list');
$tlsv13_cipher_list = ($domain['override_tls'] == '1' && ! empty($domain['tlsv13_cipher_list'])) ? $domain['tlsv13_cipher_list'] : Settings::Get('system.tlsv13_cipher_list');
$vhost_content .= ' SSLEngine On' . "\n";
$vhost_content .= ' SSLProtocol -ALL +' . str_replace(",", " +", Settings::Get('system.ssl_protocols')) . "\n";
$vhost_content .= ' SSLProtocol -ALL +' . str_replace(",", " +", $ssl_protocols) . "\n";
if (Settings::Get('system.apache24') == '1') {
if (isset($domain['http2']) && $domain['http2'] == '1' && Settings::Get('system.http2_support') == '1') {
$vhost_content .= ' Protocols h2 http/1.1' . "\n";
$vhost_content .= ' Protocols h2 http/1.1' . "\n";
}
if (! empty(Settings::Get('system.dhparams_file'))) {
$dhparams = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.dhparams_file'));
@@ -997,7 +989,11 @@ class Apache extends HttpConfigBase
}
// this makes it more secure, thx to Marcel (08/2013)
$vhost_content .= ' SSLHonorCipherOrder On' . "\n";
$vhost_content .= ' SSLCipherSuite ' . Settings::Get('system.ssl_cipher_list') . "\n";
$vhost_content .= ' SSLCipherSuite ' . $ssl_cipher_list . "\n";
$protocols = array_map('trim', explode(",", $ssl_protocols));
if (in_array("TLSv1.3", $protocols) && ! empty($tlsv13_cipher_list) && Settings::Get('system.apache24') == 1) {
$vhost_content .= ' SSLCipherSuite TLSv1.3 ' . $tlsv13_cipher_list . "\n";
}
$vhost_content .= ' SSLVerifyDepth 10' . "\n";
$vhost_content .= ' SSLCertificateFile ' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_cert_file']) . "\n";
@@ -1074,17 +1070,25 @@ class Apache extends HttpConfigBase
}
$vhost_content .= $this->getLogfiles($domain);
if ($domain['specialsettings'] != '') {
if ($domain['specialsettings'] != '' && ($ssl_vhost == false || ($ssl_vhost == true && $domain['include_specialsettings'] == 1))) {
$vhost_content .= $this->processSpecialConfigTemplate($domain['specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
if ($domain['ssl_specialsettings'] != '' && $ssl_vhost == true) {
$vhost_content .= $this->processSpecialConfigTemplate($domain['ssl_specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
if ($_vhost_content != '') {
$vhost_content .= $_vhost_content;
}
if (Settings::Get('system.default_vhostconf') != '') {
if (Settings::Get('system.default_vhostconf') != '' && ($ssl_vhost == false || ($ssl_vhost == true && Settings::Get('system.include_default_vhostconf') == 1))) {
$vhost_content .= $this->processSpecialConfigTemplate(Settings::Get('system.default_vhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
if (Settings::Get('system.default_sslvhostconf') != '' && $ssl_vhost == true) {
$vhost_content .= $this->processSpecialConfigTemplate(Settings::Get('system.default_sslvhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
}
$vhost_content .= '</VirtualHost>' . "\n";
@@ -1209,7 +1213,7 @@ class Apache extends HttpConfigBase
foreach ($statusCodes as $statusCode) {
if (isset($row_diroptions['error' . $statusCode . 'path']) && $row_diroptions['error' . $statusCode . 'path'] != '') {
$defhandler = $row_diroptions['error' . $statusCode . 'path'];
if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
if (substr($defhandler, 0, 1) != '"' && substr($defhandler, - 1, 1) != '"') {
$defhandler = '"' . \Froxlor\FileDir::makeCorrectFile($defhandler) . '"';
}

View File

@@ -128,7 +128,7 @@ class ConfigIO
// iterate through all subdirs,
// look for vhost/diroption files
// and delete them
foreach ($its as $fullFileName => $it) {
foreach ($its as $it) {
if ($it->isFile() && preg_match($pattern, $it->getFilename())) {
// remove file
\Froxlor\FileDir::safe_exec('rm -f ' . escapeshellarg(\Froxlor\FileDir::makeCorrectFile($its->getPathname())));
@@ -191,7 +191,7 @@ class ConfigIO
/**
* don't do anything if the file does not exist
*/
if (@file_exists($awstatsclean['fullentry'])) {
if (@file_exists($awstatsclean['fullentry']) && $awstatsclean['entry'] != '.' && $awstatsclean['entry'] != '..') {
$awstatsclean['fh'] = fopen($awstatsclean['fullentry'], 'r');
$awstatsclean['headerRead'] = fgets($awstatsclean['fh'], strlen($awstatsclean['header']) + 1);
fclose($awstatsclean['fh']);
@@ -232,7 +232,7 @@ class ConfigIO
// look for php-fcgi-starter files
// and take immutable-flag away from them
// so we can delete them :)
foreach ($its as $fullFileName => $it) {
foreach ($its as $it) {
if ($it->isFile() && $it->getFilename() == 'php-fcgi-starter') {
// set chattr -i
\Froxlor\FileDir::removeImmutable($its->getPathname());

View File

@@ -3,6 +3,7 @@ namespace Froxlor\Cron\Http;
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Cron\Http\Php\Fpm;
/**
* This file is part of the Froxlor project.
@@ -27,6 +28,51 @@ use Froxlor\Settings;
class HttpConfigBase
{
public function init()
{
// if Let's Encrypt is activated, run it before regeneration of webserver configfiles
if (Settings::Get('system.leenabled') == 1) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Running Let\'s Encrypt cronjob prior to regenerating webserver config files');
\Froxlor\Cron\Http\LetsEncrypt\AcmeSh::$no_inserttask = true;
\Froxlor\Cron\Http\LetsEncrypt\AcmeSh::run(true);
// set last run timestamp of cronjob
\Froxlor\System\Cronjob::updateLastRunOfCron('letsencrypt');
}
}
public function reload()
{
$called_class = get_called_class();
if ((int) Settings::Get('phpfpm.enabled') == 1) {
// get all start/stop commands
$startstop_sel = Database::prepare("SELECT reload_cmd, config_dir FROM `" . TABLE_PANEL_FPMDAEMONS . "`");
Database::pexecute($startstop_sel);
$restart_cmds = $startstop_sel->fetchAll(\PDO::FETCH_ASSOC);
// restart all php-fpm instances
foreach ($restart_cmds as $restart_cmd) {
// check whether the config dir is empty (no domains uses this daemon)
// so we need to create a dummy
$_conffiles = glob(\Froxlor\FileDir::makeCorrectFile($restart_cmd['config_dir'] . "/*.conf"));
if ($_conffiles === false || empty($_conffiles)) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: fpm config directory "' . $restart_cmd['config_dir'] . '" is empty. Creating dummy.');
Fpm::createDummyPool($restart_cmd['config_dir']);
}
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: running ' . $restart_cmd['reload_cmd']);
\Froxlor\FileDir::safe_exec(escapeshellcmd($restart_cmd['reload_cmd']));
}
}
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: reloading ' . $called_class);
\Froxlor\FileDir::safe_exec(escapeshellcmd(Settings::Get('system.apachereload_command')));
/**
* nginx does not auto-spawn fcgi-processes
*/
if (Settings::Get('system.webserver') == "nginx" && Settings::Get('system.phpreload_command') != '' && (int) Settings::Get('phpfpm.enabled') == 0) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, $called_class . '::reload: restarting php processes');
\Froxlor\FileDir::safe_exec(Settings::Get('system.phpreload_command'));
}
}
/**
* process special config as template, by substituting {VARIABLE} with the
* respective value.
@@ -87,7 +133,7 @@ class HttpConfigBase
");
$ssldestport = Database::pexecute_first($ssldestport_stmt);
if ($ssldestport['port'] != '') {
if ($ssldestport && $ssldestport['port'] != '') {
$_sslport = ":" . $ssldestport['port'];
}

View File

@@ -43,19 +43,15 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
private static $do_update = true;
public static function run()
public static $no_inserttask = false;
private static function needRenew()
{
self::checkInstall();
self::$apiserver = 'https://acme-v0' . \Froxlor\Settings::Get('system.leapiversion') . '.api.letsencrypt.org/directory';
FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating Let's Encrypt certificates");
$certificates_stmt = Database::query("
SELECT
domssl.`id`,
domssl.`domainid`,
domssl.expirationdate,
domssl.`expirationdate`,
domssl.`ssl_cert_file`,
domssl.`ssl_key_file`,
domssl.`ssl_ca_file`,
@@ -87,6 +83,46 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
OR domssl.`expirationdate` IS NULL
)
");
$customer_ssl = $certificates_stmt->fetchAll(\PDO::FETCH_ASSOC);
$froxlor_ssl = array();
if (Settings::Get('system.le_froxlor_enabled') == '1') {
$froxlor_ssl_settings_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
WHERE `domainid` = '0' AND
(`expirationdate` < DATE_ADD(NOW(), INTERVAL 30 DAY) OR `expirationdate` IS NULL)
");
$froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt);
}
if (count($customer_ssl) > 0 || count($froxlor_ssl) > 0) {
return array(
'customer_ssl' => $customer_ssl,
'froxlor_ssl' => $froxlor_ssl
);
}
return false;
}
public static function run($internal = false)
{
if (! defined('CRON_IS_FORCED') && ! defined('CRON_DEBUG_FLAG') && $internal == false) {
// Let's Encrypt cronjob is combined with regeneration of webserver configuration files.
// For debugging purposes you can use the --debug switch and the --force switch to run the cron manually.
// check whether we MIGHT need to run although there is no task to regenerate config-files
$needRenew = self::needRenew();
if ($needRenew) {
// insert task to generate certificates and vhost-configs
\Froxlor\System\Cronjob::inserttask(1);
}
return 0;
}
self::checkInstall();
self::$apiserver = 'https://acme-v0' . \Froxlor\Settings::Get('system.leapiversion') . '.api.letsencrypt.org/directory';
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Requesting/renewing Let's Encrypt certificates");
$aliasdomains_stmt = Database::prepare("
SELECT
@@ -120,6 +156,8 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
// flag for re-generation of vhost files
$changedetected = 0;
$needRenew = self::needRenew();
// first - generate LE for system-vhost if enabled
if (Settings::Get('system.le_froxlor_enabled') == '1') {
@@ -140,12 +178,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
'id' => null
);
$froxlor_ssl_settings_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
WHERE `domainid` = '0' AND
(`expirationdate` < DATE_ADD(NOW(), INTERVAL 30 DAY) OR `expirationdate` IS NULL)
");
$froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt);
$froxlor_ssl = $needRenew['froxlor_ssl'];
$cert_mode = 'issue';
if ($froxlor_ssl) {
@@ -174,7 +207,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
);
$froxlor_aliases = Settings::Get('system.froxloraliases');
if (!empty($froxlor_aliases)) {
if (! empty($froxlor_aliases)) {
$froxlor_aliases = explode(",", $froxlor_aliases);
foreach ($froxlor_aliases as $falias) {
if (\Froxlor\Validate\Validate::validateDomain(trim($falias))) {
@@ -185,10 +218,12 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
// Only renew let's encrypt certificate if no broken ssl_redirect is enabled
// - this temp. deactivation of the ssl-redirect is handled by the webserver-cronjob
$do_force = false;
if ($cert_mode == 'renew') {
FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']);
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']);
} else {
FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']);
$do_force = true;
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']);
}
$cronlog = FroxlorLogger::getInstanceOf(array(
@@ -196,12 +231,12 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
'adminsession' => 0
));
self::runAcmeSh($certrow, $domains, $cert_mode, $cronlog, $changedetected);
self::runAcmeSh($certrow, $domains, $cert_mode, $cronlog, $changedetected, $do_force);
}
}
// customer domains
$certrows = $certificates_stmt->fetchAll(\PDO::FETCH_ASSOC);
$certrows = $needRenew['customer_ssl'];
$cert_mode = 'issue';
foreach ($certrows as $certrow) {
@@ -214,20 +249,25 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
// Only renew let's encrypt certificate if no broken ssl_redirect is enabled
if ($certrow['ssl_redirect'] != 2) {
if (! empty($certrow['ssl_cert_file'])) {
$do_force = false;
if (! empty($certrow['ssl_cert_file']) && ! empty($certrow['expirationdate'])) {
$cert_mode = 'renew';
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']);
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']);
} else if (! empty($certrow['ssl_cert_file']) && empty($certrow['expirationdate'])) {
// domain changed (SAN or similar)
$do_force = true;
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Re-creating certificate for " . $certrow['domain']);
} else {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']);
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']);
}
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $certrow['domain']);
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $certrow['domain']);
$domains = array(
$certrow['domain']
);
// add www.<domain> to SAN list
if ($certrow['wwwserveralias'] == 1) {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $certrow['domain']);
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $certrow['domain']);
$domains[] = 'www.' . $certrow['domain'];
}
@@ -237,30 +277,33 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
));
$aliasdomains = $aliasdomains_stmt->fetchAll(\PDO::FETCH_ASSOC);
foreach ($aliasdomains as $aliasdomain) {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $aliasdomain['domain']);
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $aliasdomain['domain']);
$domains[] = $aliasdomain['domain'];
if ($aliasdomain['wwwserveralias'] == 1) {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $aliasdomain['domain']);
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $aliasdomain['domain']);
$domains[] = 'www.' . $aliasdomain['domain'];
}
}
self::runAcmeSh($certrow, $domains, $cert_mode, $cronlog, $changedetected);
self::runAcmeSh($certrow, $domains, $cert_mode, $cronlog, $changedetected, $do_force);
} else {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect");
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect");
}
}
// If we have a change in a certificate, we need to update the webserver - configs
// This is easiest done by just creating a new task ;)
if ($changedetected) {
\Froxlor\System\Cronjob::inserttask(1);
if (self::$no_inserttask == false) {
\Froxlor\System\Cronjob::inserttask(1);
}
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Let's Encrypt certificates have been updated");
} else {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "No new certificates or certificates due for renewal found");
}
FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Let's Encrypt certificates have been updated");
}
private static function runAcmeSh($certrow = array(), $domains = array(), $cert_mode = 'issue', &$cronlog = null, &$changedetected = 0)
private static function runAcmeSh($certrow = array(), $domains = array(), $cert_mode = 'issue', &$cronlog = null, &$changedetected = 0, $force = false)
{
if (! empty($domains)) {
@@ -272,7 +315,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
$acmesh_cmd = self::$acmesh . " --auto-upgrade 0 --server " . self::$apiserver . " --" . $cert_mode . " -d " . implode(" -d ", $domains);
if ($cert_mode == 'issue') {
$acmesh_cmd .= " -w " . \Froxlor\Froxlor::getInstallDir();
$acmesh_cmd .= " -w " . Settings::Get('system.letsencryptchallengepath');
}
if (Settings::Get('system.leecc') > 0) {
$acmesh_cmd .= " --keylength ec-" . Settings::Get('system.leecc');
@@ -282,8 +325,16 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
if (Settings::Get('system.letsencryptreuseold') != '1') {
$acmesh_cmd .= " --always-force-new-domain-key";
}
if (Settings::Get('system.letsencryptca') == 'testing') {
$acmesh_cmd .= " --staging";
}
if ($force) {
$acmesh_cmd .= " --force";
}
$acme_result = \Froxlor\FileDir::safe_exec($acmesh_cmd);
// debug output of acme.sh run
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, implode("\n", $acme_result));
$return = array();
self::readCertificateToVar($certrow['domain'], $return);
@@ -292,29 +343,33 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
$newcert = openssl_x509_parse($return['crt']);
// Store the new data
Database::pexecute(self::$updcert_stmt, array(
'id' => $certrow['id'],
'domainid' => $certrow['domainid'],
'crt' => $return['crt'],
'key' => $return['key'],
'ca' => $return['chain'],
'chain' => $return['chain'],
'csr' => $return['csr'],
'fullchain' => $return['fullchain'],
'expirationdate' => date('Y-m-d H:i:s', $newcert['validTo_time_t'])
));
if ($certrow['ssl_redirect'] == 3) {
Database::pexecute(self::$upddom_stmt, array(
'domainid' => $certrow['domainid']
if ($newcert) {
// Store the new data
Database::pexecute(self::$updcert_stmt, array(
'id' => $certrow['id'],
'domainid' => $certrow['domainid'],
'crt' => $return['crt'],
'key' => $return['key'],
'ca' => $return['chain'],
'chain' => $return['chain'],
'csr' => $return['csr'],
'fullchain' => $return['fullchain'],
'expirationdate' => date('Y-m-d H:i:s', $newcert['validTo_time_t'])
));
}
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificate for " . $certrow['domain']);
$changedetected = 1;
if ($certrow['ssl_redirect'] == 3) {
Database::pexecute(self::$upddom_stmt, array(
'domainid' => $certrow['domainid']
));
}
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificate for " . $certrow['domain']);
$changedetected = 1;
} else {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Got non-successful Let's Encrypt response for " . $certrow['domain'] . ":\n" . implode("\n", $acme_result));
}
} else {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not get Let's Encrypt certificate for " . $certrow['domain'] . ":\n" . implode("\n", $acme_result));
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not get Let's Encrypt certificate for " . $certrow['domain'] . ":\n" . implode("\n", $acme_result));
}
}
}
@@ -328,18 +383,27 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
$certificate_folder = \Froxlor\FileDir::makeCorrectDir($certificate_folder);
if (is_dir($certificate_folder)) {
$return['crt'] = file_get_contents(\Froxlor\FileDir::makeCorrectFile($certificate_folder . '/' . $domain . '.cer'));
$return['key'] = file_get_contents(\Froxlor\FileDir::makeCorrectFile($certificate_folder . '/' . $domain . '.key'));
$return['chain'] = file_get_contents(\Froxlor\FileDir::makeCorrectFile($certificate_folder . '/ca.cer'));
$return['fullchain'] = file_get_contents(\Froxlor\FileDir::makeCorrectFile($certificate_folder . '/fullchain.cer'));
$return['csr'] = file_get_contents(\Froxlor\FileDir::makeCorrectFile($certificate_folder . '/' . $domain . '.csr'));
foreach ([
'crt' => $domain . '.cer',
'key' => $domain . '.key',
'chain' => 'ca.cer',
'fullchain' => 'fullchain.cer',
'csr' => $domain . '.csr'
] as $index => $sslfile) {
$ssl_file = \Froxlor\FileDir::makeCorrectFile($certificate_folder . '/' . $sslfile);
if (file_exists($ssl_file)) {
$return[$index] = file_get_contents($ssl_file);
} else {
$return[$index] = null;
}
}
}
}
private static function checkInstall()
{
if (! file_exists(self::$acmesh)) {
FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Could not find acme.sh - installing it to /root/.acme.sh/");
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Could not find acme.sh - installing it to /root/.acme.sh/");
$return = false;
\Froxlor\FileDir::safe_exec("wget -O - https://get.acme.sh | sh", $return, array(
'|'
@@ -350,6 +414,8 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
private static function checkUpgrade()
{
$acmesh_result = \Froxlor\FileDir::safe_exec(self::$acmesh . " --upgrade");
FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Checking for LetsEncrypt client upgrades before renewing certificates:\n" . implode("\n", $acmesh_result));
// check for activated cron (which is installed automatically) but we don't need it
$acmesh_result2 = \Froxlor\FileDir::safe_exec(self::$acmesh . " --uninstall-cronjob");
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Checking for LetsEncrypt client upgrades before renewing certificates:\n" . implode("\n", $acmesh_result) . "\n" . implode("\n", $acmesh_result2));
}
}

View File

@@ -3,7 +3,6 @@ namespace Froxlor\Cron\Http;
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Cron\Http\Php\Fpm;
use Froxlor\Cron\Http\Php\PhpInterface;
/**
@@ -45,30 +44,6 @@ class Lighttpd extends HttpConfigBase
*/
private $deactivated = false;
public function reload()
{
if ((int) Settings::Get('phpfpm.enabled') == 1) {
// get all start/stop commands
$startstop_sel = Database::prepare("SELECT reload_cmd, config_dir FROM `" . TABLE_PANEL_FPMDAEMONS . "`");
Database::pexecute($startstop_sel);
$restart_cmds = $startstop_sel->fetchAll(\PDO::FETCH_ASSOC);
// restart all php-fpm instances
foreach ($restart_cmds as $restart_cmd) {
// check whether the config dir is empty (no domains uses this daemon)
// so we need to create a dummy
$_conffiles = glob(\Froxlor\FileDir::makeCorrectFile($restart_cmd['config_dir'] . "/*.conf"));
if ($_conffiles === false || empty($_conffiles)) {
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'lighttpd::reload: fpm config directory "' . $restart_cmd['config_dir'] . '" is empty. Creating dummy.');
Fpm::createDummyPool($restart_cmd['config_dir']);
}
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'lighttpd::reload: running ' . $restart_cmd['reload_cmd']);
\Froxlor\FileDir::safe_exec(escapeshellcmd($restart_cmd['reload_cmd']));
}
}
$this->logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'lighttpd::reload: reloading lighttpd');
\Froxlor\FileDir::safe_exec(escapeshellcmd(Settings::Get('system.apachereload_command')));
}
public function createIpPort()
{
$result_ipsandports_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` ORDER BY `ip` ASC, `port` ASC");
@@ -200,7 +175,7 @@ class Lighttpd extends HttpConfigBase
);
}
if ($row_ipsandports['specialsettings'] != '') {
if ($row_ipsandports['specialsettings'] != '' && ($row_ipsandports['ssl'] == '0' || ($row_ipsandports['ssl'] == '1' && Settings::Get('system.use_ssl') == '1' && $row_ipsandports['include_specialsettings'] == '1'))) {
$this->lighttpd_data[$vhost_filename] .= $this->processSpecialConfigTemplate($row_ipsandports['specialsettings'], $domain, $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n";
}
@@ -208,6 +183,11 @@ class Lighttpd extends HttpConfigBase
}
if ($row_ipsandports['ssl'] == '1') {
if ($row_ipsandports['ssl_specialsettings'] != '') {
$this->lighttpd_data[$vhost_filename] .= $this->processSpecialConfigTemplate($row_ipsandports['ssl_specialsettings'], $domain, $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n";
}
if ($row_ipsandports['ssl_cert_file'] == '') {
$row_ipsandports['ssl_cert_file'] = Settings::Get('system.ssl_cert_file');
if (! file_exists($row_ipsandports['ssl_cert_file'])) {
@@ -316,7 +296,7 @@ class Lighttpd extends HttpConfigBase
}
$defhandler = Settings::Get('defaultwebsrverrhandler.err404');
if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
$defhandler = \Froxlor\FileDir::makeCorrectFile($defhandler);
}
$this->lighttpd_data[$vhost_filename] = 'server.error-handler-404 = "' . $defhandler . '"';
@@ -396,6 +376,7 @@ class Lighttpd extends HttpConfigBase
protected function createLighttpdHosts($ipid, $ssl, $vhost_filename)
{
$domains = WebserverBase::getVhostsToCreate();
$included_vhosts = array();
foreach ($domains as $domain) {
if (is_dir(Settings::Get('system.apacheconf_vhost'))) {
@@ -475,7 +456,7 @@ class Lighttpd extends HttpConfigBase
'domainid' => $domain['id']
));
if ($ssldestport['port'] != '') {
if ($ssldestport && $ssldestport['port'] != '') {
$_sslport = ":" . $ssldestport['port'];
}
@@ -536,17 +517,29 @@ class Lighttpd extends HttpConfigBase
$vhost_content .= $this->getSslSettings($domain, $ssl_vhost);
if ($domain['specialsettings'] != "") {
if ($domain['specialsettings'] != '' && ($ssl_vhost == false || ($ssl_vhost == true && $domain['include_specialsettings'] == 1))) {
$vhost_content .= $this->processSpecialConfigTemplate($domain['specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
if ($ipandport['default_vhostconf_domain'] != '') {
if ($domain['ssl_specialsettings'] != '' && $ssl_vhost == true) {
$vhost_content .= $this->processSpecialConfigTemplate($domain['ssl_specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
if ($ipandport['default_vhostconf_domain'] != '' && ($ssl_vhost == false || ($ssl_vhost == true && $ipandport['include_default_vhostconf_domain'] == '1'))) {
$vhost_content .= $this->processSpecialConfigTemplate($ipandport['default_vhostconf_domain'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
if (Settings::Get('system.default_vhostconf') != '') {
if ($ipandport['ssl_default_vhostconf_domain'] != '' && $ssl_vhost == true) {
$vhost_content .= $this->processSpecialConfigTemplate($ipandport['ssl_default_vhostconf_domain'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
if (Settings::Get('system.default_vhostconf') != '' && ($ssl_vhost == false || ($ssl_vhost == true && Settings::Get('system.include_default_vhostconf') == 1))) {
$vhost_content .= $this->processSpecialConfigTemplate(Settings::Get('system.default_vhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
if (Settings::Get('system.default_sslvhostconf') != '' && $ssl_vhost == true) {
$vhost_content .= $this->processSpecialConfigTemplate(Settings::Get('system.default_sslvhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
}
$vhost_content .= $this->getLogFiles($domain);
}
@@ -577,6 +570,8 @@ class Lighttpd extends HttpConfigBase
if ($domain['ssl_cert_file'] != '') {
$ssl_cipher_list = ($domain['override_tls'] == '1' && ! empty($domain['ssl_cipher_list'])) ? $domain['ssl_cipher_list'] : Settings::Get('system.ssl_cipher_list');
// ssl.engine only necessary once in the ip/port vhost (SERVER['socket'] condition)
// $ssl_settings .= 'ssl.engine = "enable"' . "\n";
$ssl_settings .= 'ssl.use-compression = "disable"' . "\n";
@@ -590,7 +585,7 @@ class Lighttpd extends HttpConfigBase
}
$ssl_settings .= 'ssl.use-sslv2 = "disable"' . "\n";
$ssl_settings .= 'ssl.use-sslv3 = "disable"' . "\n";
$ssl_settings .= 'ssl.cipher-list = "' . Settings::Get('system.ssl_cipher_list') . '"' . "\n";
$ssl_settings .= 'ssl.cipher-list = "' . $ssl_cipher_list . '"' . "\n";
$ssl_settings .= 'ssl.honor-cipher-order = "enable"' . "\n";
$ssl_settings .= 'ssl.pemfile = "' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_cert_file']) . '"' . "\n";
@@ -707,7 +702,7 @@ class Lighttpd extends HttpConfigBase
if (! empty($row['error404path'])) {
$defhandler = $row['error404path'];
if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
$defhandler = \Froxlor\FileDir::makeCorrectFile($domain['documentroot'] . '/' . $defhandler);
}
$error_string .= ' server.error-handler-404 = "' . $defhandler . '"' . "\n\n";
@@ -765,23 +760,21 @@ class Lighttpd extends HttpConfigBase
));
while ($row_htpasswds = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
if ($auth_backend_loaded[$domain['ipandport']] != 'yes' && $auth_backend_loaded[$domain['ssl_ipandport']] != 'yes') {
if ($this->auth_backend_loaded[$domain['ipandport']] != 'yes' && $this->auth_backend_loaded[$domain['ssl_ipandport']] != 'yes') {
$filename = $domain['customerid'] . '.htpasswd';
if ($this->auth_backend_loaded[$domain['ipandport']] != 'yes') {
$auth_backend_loaded[$domain['ipandport']] = 'yes';
$this->auth_backend_loaded[$domain['ipandport']] = 'yes';
$diroption_text .= 'auth.backend = "htpasswd"' . "\n";
$diroption_text .= 'auth.backend.htpasswd.userfile = "' . \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n";
$this->needed_htpasswds[$filename] = $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n";
$diroption_text .= 'auth.require = ( ' . "\n";
$previous_domain_id = '1';
} elseif ($this->auth_backend_loaded[$domain['ssl_ipandport']] != 'yes') {
$auth_backend_loaded[$domain['ssl_ipandport']] = 'yes';
$this->auth_backend_loaded[$domain['ssl_ipandport']] = 'yes';
$diroption_text .= 'auth.backend= "htpasswd"' . "\n";
$diroption_text .= 'auth.backend.htpasswd.userfile = "' . \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $filename) . '"' . "\n";
$this->needed_htpasswds[$filename] = $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n";
$diroption_text .= 'auth.require = ( ' . "\n";
$previous_domain_id = '1';
}
}

View File

@@ -3,7 +3,6 @@ namespace Froxlor\Cron\Http;
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\Cron\Http\Php\Fpm;
use Froxlor\Cron\Http\Php\PhpInterface;
/**
@@ -55,39 +54,6 @@ class Nginx extends HttpConfigBase
$this->nginx_server = $nginx_server;
}
public function reload()
{
if ((int) Settings::Get('phpfpm.enabled') == 1) {
// get all start/stop commands
$startstop_sel = Database::prepare("SELECT reload_cmd, config_dir FROM `" . TABLE_PANEL_FPMDAEMONS . "`");
Database::pexecute($startstop_sel);
$restart_cmds = $startstop_sel->fetchAll(\PDO::FETCH_ASSOC);
// restart all php-fpm instances
foreach ($restart_cmds as $restart_cmd) {
// check whether the config dir is empty (no domains uses this daemon)
// so we need to create a dummy
$_conffiles = glob(\Froxlor\FileDir::makeCorrectFile($restart_cmd['config_dir'] . "/*.conf"));
if ($_conffiles === false || empty($_conffiles)) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'nginx::reload: fpm config directory "' . $restart_cmd['config_dir'] . '" is empty. Creating dummy.');
Fpm::createDummyPool($restart_cmd['config_dir']);
}
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'nginx::reload: running ' . $restart_cmd['reload_cmd']);
\Froxlor\FileDir::safe_exec(escapeshellcmd($restart_cmd['reload_cmd']));
}
}
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'nginx::reload: reloading nginx');
\Froxlor\FileDir::safe_exec(Settings::Get('system.apachereload_command'));
/**
* nginx does not auto-spawn fcgi-processes
*/
if (Settings::Get('system.phpreload_command') != '' && (int) Settings::Get('phpfpm.enabled') == 0) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'nginx::reload: restarting php processes');
\Froxlor\FileDir::safe_exec(Settings::Get('system.phpreload_command'));
}
}
private function createLogformatEntry()
{
if (Settings::Get('system.logfiles_format') != '') {
@@ -137,7 +103,7 @@ class Nginx extends HttpConfigBase
foreach ($statusCodes as $statusCode) {
if (Settings::Get('defaultwebsrverrhandler.err' . $statusCode) != '') {
$defhandler = Settings::Get('defaultwebsrverrhandler.err' . $statusCode);
if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
$defhandler = \Froxlor\FileDir::makeCorrectFile($defhandler);
}
$this->nginx_data[$vhosts_filename] .= 'error_page ' . $statusCode . ' ' . $defhandler . ';' . "\n";
@@ -250,7 +216,7 @@ class Nginx extends HttpConfigBase
$aliases = "";
$froxlor_aliases = Settings::Get('system.froxloraliases');
if (!empty($froxlor_aliases)) {
if (! empty($froxlor_aliases)) {
$froxlor_aliases = explode(",", $froxlor_aliases);
foreach ($froxlor_aliases as $falias) {
if (\Froxlor\Validate\Validate::validateDomain(trim($falias))) {
@@ -278,7 +244,7 @@ class Nginx extends HttpConfigBase
$is_redirect = false;
} else {
$_sslport = $this->checkAlternativeSslPort();
$mypath = 'https://' . Settings::Get('system.hostname') . $_sslport . '/';
$mypath = 'https://' . Settings::Get('system.hostname') . $_sslport;
$this->nginx_data[$vhost_filename] .= "\t" . 'location / {' . "\n";
$this->nginx_data[$vhost_filename] .= "\t\t" . 'return 301 ' . $mypath . '$request_uri;' . "\n";
$this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n";
@@ -292,7 +258,7 @@ class Nginx extends HttpConfigBase
$this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n";
}
if ($row_ipsandports['specialsettings'] != '') {
if ($row_ipsandports['specialsettings'] != '' && ($row_ipsandports['ssl'] == '0' || ($row_ipsandports['ssl'] == '1' && Settings::Get('system.use_ssl') == '1' && $row_ipsandports['include_specialsettings'] == '1'))) {
$this->nginx_data[$vhost_filename] .= $this->processSpecialConfigTemplate($row_ipsandports['specialsettings'], array(
'domain' => Settings::Get('system.hostname'),
'loginname' => Settings::Get('phpfpm.vhost_httpuser'),
@@ -307,13 +273,21 @@ class Nginx extends HttpConfigBase
if ($row_ipsandports['ssl'] == '1') {
$row_ipsandports['domain'] = Settings::Get('system.hostname');
$this->nginx_data[$vhost_filename] .= $this->composeSslSettings($row_ipsandports);
if ($row_ipsandports['ssl_specialsettings'] != '') {
$this->nginx_data[$vhost_filename] .= $this->processSpecialConfigTemplate($row_ipsandports['ssl_specialsettings'], array(
'domain' => Settings::Get('system.hostname'),
'loginname' => Settings::Get('phpfpm.vhost_httpuser'),
'documentroot' => $mypath,
'customerroot' => $mypath
), $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n";
}
}
if (! $is_redirect) {
$this->nginx_data[$vhost_filename] .= "\tlocation ~ \.php {\n";
$this->nginx_data[$vhost_filename] .= "\t\tfastcgi_split_path_info ^(.+\.php)(/.+)\$;\n";
$this->nginx_data[$vhost_filename] .= "\t\tfastcgi_split_path_info ^(.+?\.php)(/.*)$;\n";
$this->nginx_data[$vhost_filename] .= "\t\tinclude " . Settings::Get('nginx.fastcgiparams') . ";\n";
$this->nginx_data[$vhost_filename] .= "\t\tfastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;\n";
$this->nginx_data[$vhost_filename] .= "\t\tfastcgi_param SCRIPT_FILENAME \$request_filename;\n";
$this->nginx_data[$vhost_filename] .= "\t\tfastcgi_param PATH_INFO \$fastcgi_path_info;\n";
$this->nginx_data[$vhost_filename] .= "\t\ttry_files \$fastcgi_script_name =404;\n";
@@ -481,10 +455,12 @@ class Nginx extends HttpConfigBase
$ipport = $domain['ip'] . ':' . $domain['port'];
}
if ($ipandport['default_vhostconf_domain'] != '') {
if ($ipandport['default_vhostconf_domain'] != '' && ($ssl_vhost == false || ($ssl_vhost == true && $ipandport['include_default_vhostconf_domain'] == '1'))) {
$_vhost_content .= $this->processSpecialConfigTemplate($ipandport['default_vhostconf_domain'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
if ($ipandport['ssl_default_vhostconf_domain'] != '' && $ssl_vhost == true) {
$_vhost_content .= $this->processSpecialConfigTemplate($ipandport['ssl_default_vhostconf_domain'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
$http2 = $ssl_vhost == true && (isset($domain['http2']) && $domain['http2'] == '1' && Settings::Get('system.http2_support') == '1');
$vhost_content .= "\t" . 'listen ' . $ipport . ($ssl_vhost == true ? ' ssl' : '') . ($http2 == true ? ' http2' : '') . ';' . "\n";
@@ -510,7 +486,7 @@ class Nginx extends HttpConfigBase
'domainid' => $domain['id']
));
if ($ssldestport['port'] != '') {
if ($ssldestport && $ssldestport['port'] != '') {
$_sslport = ":" . $ssldestport['port'];
}
@@ -556,17 +532,25 @@ class Nginx extends HttpConfigBase
$vhost_content .= isset($this->needed_htpasswds[$domain['id']]) ? $this->needed_htpasswds[$domain['id']] . "\n" : '';
if ($domain['specialsettings'] != "") {
if ($domain['specialsettings'] != '' && ($ssl_vhost == false || ($ssl_vhost == true && $domain['include_specialsettings'] == 1))) {
$vhost_content = $this->mergeVhostCustom($vhost_content, $this->processSpecialConfigTemplate($domain['specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost));
}
if ($domain['ssl_specialsettings'] != '' && $ssl_vhost == true) {
$vhost_content .= $this->processSpecialConfigTemplate($domain['ssl_specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
if ($_vhost_content != '') {
$vhost_content = $this->mergeVhostCustom($vhost_content, $_vhost_content);
}
if (Settings::Get('system.default_vhostconf') != '') {
if (Settings::Get('system.default_vhostconf') != '' && ($ssl_vhost == false || ($ssl_vhost == true && Settings::Get('system.include_default_vhostconf') == 1))) {
$vhost_content = $this->mergeVhostCustom($vhost_content, $this->processSpecialConfigTemplate(Settings::Get('system.default_vhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n");
}
if (Settings::Get('system.default_sslvhostconf') != '' && $ssl_vhost == true) {
$vhost_content .= $this->processSpecialConfigTemplate(Settings::Get('system.default_sslvhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
}
}
$vhost_content .= "\n}\n\n";
@@ -574,26 +558,38 @@ class Nginx extends HttpConfigBase
return $vhost_content;
}
private function cleanVhostStruct($vhost = null)
{
// Remove windows linebreaks
$vhost = str_replace("\r", "\n", $vhost);
// Break blocks into lines
$vhost = str_replace(array(
"{",
"}"
), array(
" {\n",
"\n}"
), $vhost);
// Break into array items
$vhost = explode("\n", preg_replace('/[ \t]+/', ' ', trim(preg_replace('/\t+/', '', $vhost))));
// Remove empty lines
$vhost = array_filter($vhost, function ($a) {
return preg_match("#\S#", $a);
});
// remove unnecessary whitespaces
$vhost = array_map("trim", $vhost);
// re-number array keys
$vhost = array_values($vhost);
return $vhost;
}
protected function mergeVhostCustom($vhost_frx, $vhost_usr)
{
// Clean froxlor defined settings
$vhost_frx = explode("\n", preg_replace('/[ \t]+/', ' ', trim(preg_replace('/\t+/', '', $vhost_frx)))); // Break into array items
$vhost_frx = array_map("trim", $vhost_frx); // remove unnecessary whitespaces
$vhost_frx = $this->cleanVhostStruct($vhost_frx);
// Clean user defined settings
$vhost_usr = str_replace("\r", "\n", $vhost_usr); // Remove windows linebreaks
$vhost_usr = str_replace(array(
"{ ",
" }"
), array(
"{\n",
"\n}"
), $vhost_usr); // Break blocks into lines
$vhost_usr = explode("\n", preg_replace('/[ \t]+/', ' ', trim(preg_replace('/\t+/', '', $vhost_usr)))); // Break into array items
// Remove empty lines
$vhost_usr = array_filter($vhost_usr, function ($a) {
return preg_match("#\S#", $a);
});
$vhost_usr = $this->cleanVhostStruct($vhost_usr);
// Cycle through the user defined settings
$currentBlock = array();
@@ -682,10 +678,14 @@ class Nginx extends HttpConfigBase
if (! file_exists($domain_or_ip['ssl_cert_file'])) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, $domain_or_ip['domain'] . ' :: certificate file "' . $domain_or_ip['ssl_cert_file'] . '" does not exist! Cannot create ssl-directives');
} else {
$ssl_protocols = (isset($domain_or_ip['override_tls']) && $domain_or_ip['override_tls'] == '1' && ! empty($domain_or_ip['ssl_protocols'])) ? $domain_or_ip['ssl_protocols'] : Settings::Get('system.ssl_protocols');
$ssl_cipher_list = (isset($domain_or_ip['override_tls']) && $domain_or_ip['override_tls'] == '1' && ! empty($domain_or_ip['ssl_cipher_list'])) ? $domain_or_ip['ssl_cipher_list'] : Settings::Get('system.ssl_cipher_list');
// obsolete: ssl on now belongs to the listen block as 'ssl' at the end
// $sslsettings .= "\t" . 'ssl on;' . "\n";
$sslsettings .= "\t" . 'ssl_protocols ' . str_replace(",", " ", Settings::Get('system.ssl_protocols')) . ';' . "\n";
$sslsettings .= "\t" . 'ssl_ciphers ' . Settings::Get('system.ssl_cipher_list') . ';' . "\n";
$sslsettings .= "\t" . 'ssl_protocols ' . str_replace(",", " ", $ssl_protocols) . ';' . "\n";
$sslsettings .= "\t" . 'ssl_ciphers ' . $ssl_cipher_list . ';' . "\n";
if (! empty(Settings::Get('system.dhparams_file'))) {
$dhparams = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.dhparams_file'));
if (! file_exists($dhparams)) {
@@ -693,8 +693,13 @@ class Nginx extends HttpConfigBase
}
$sslsettings .= 'ssl_dhparam ' . $dhparams . ';' . "\n";
}
$sslsettings .= "\t" . 'ssl_ecdh_curve secp384r1;' . "\n";
// When <1.11.0: Defaults to prime256v1, similar to first curve recommendation by Mozilla.
// (When specifyng just one, there's no fallback when specific curve is not supported by client.)
// When >1.11.0: Defaults to auto, using recommended curves provided by OpenSSL.
// see https://github.com/Froxlor/Froxlor/issues/652
// $sslsettings .= "\t" . 'ssl_ecdh_curve secp384r1;' . "\n";
$sslsettings .= "\t" . 'ssl_prefer_server_ciphers on;' . "\n";
$sslsettings .= "\t" . 'ssl_session_cache shared:SSL:10m;' . "\n";
$sslsettings .= "\t" . 'ssl_certificate ' . \Froxlor\FileDir::makeCorrectFile($domain_or_ip['ssl_cert_file']) . ';' . "\n";
if ($domain_or_ip['ssl_key_file'] != '') {
@@ -745,7 +750,7 @@ class Nginx extends HttpConfigBase
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
if (! empty($row['error404path'])) {
$defhandler = $row['error404path'];
if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
$defhandler = \Froxlor\FileDir::makeCorrectFile($defhandler);
}
$path_options .= "\t" . 'error_page 404 ' . $defhandler . ';' . "\n";
@@ -753,7 +758,7 @@ class Nginx extends HttpConfigBase
if (! empty($row['error403path'])) {
$defhandler = $row['error403path'];
if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
$defhandler = \Froxlor\FileDir::makeCorrectFile($defhandler);
}
$path_options .= "\t" . 'error_page 403 ' . $defhandler . ';' . "\n";
@@ -761,7 +766,7 @@ class Nginx extends HttpConfigBase
if (! empty($row['error500path'])) {
$defhandler = $row['error500path'];
if (! \Froxlor\Validate\Form\Data::validateUrl($defhandler)) {
if (! \Froxlor\Validate\Validate::validateUrl($defhandler)) {
$defhandler = \Froxlor\FileDir::makeCorrectFile($defhandler);
}
$path_options .= "\t" . 'error_page 500 502 503 504 ' . $defhandler . ';' . "\n";
@@ -911,6 +916,7 @@ class Nginx extends HttpConfigBase
$path = \Froxlor\FileDir::makeCorrectDir(substr($row_htpasswds['path'], strlen($domain['documentroot']) - 1));
} else {
// if the website contents is located in a subdirectory of the user
$matches = array();
preg_match('/^([\/[:print:]]*\/)([[:print:]\/]+){1}$/i', $row_htpasswds['path'], $matches);
$path = \Froxlor\FileDir::makeCorrectDir(substr($row_htpasswds['path'], strlen($matches[1]) - 1));
}
@@ -949,9 +955,9 @@ class Nginx extends HttpConfigBase
$phpopts .= "\t" . '}' . "\n\n";
$phpopts .= "\tlocation @php {\n";
$phpopts .= "\t\tfastcgi_split_path_info ^(.+\.php)(/.+)\$;\n";
$phpopts .= "\t\tfastcgi_split_path_info ^(.+?\.php)(/.*)$;\n";
$phpopts .= "\t\tinclude " . Settings::Get('nginx.fastcgiparams') . ";\n";
$phpopts .= "\t\tfastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;\n";
$phpopts .= "\t\tfastcgi_param SCRIPT_FILENAME \$request_filename;\n";
$phpopts .= "\t\tfastcgi_param PATH_INFO \$fastcgi_path_info;\n";
$phpopts .= "\t\ttry_files \$fastcgi_script_name =404;\n";
$phpopts .= "\t\tfastcgi_pass " . Settings::Get('system.nginx_php_backend') . ";\n";

View File

@@ -35,10 +35,10 @@ class NginxFcgi extends Nginx
$php_options_text .= "\t" . '}' . "\n\n";
$php_options_text .= "\t" . 'location @php {' . "\n";
$php_options_text .= "\t\t" . 'try_files $1 = 404;' . "\n\n";
$php_options_text .= "\t\t" . 'try_files $1 =404;' . "\n\n";
$php_options_text .= "\t\t" . 'include ' . Settings::Get('nginx.fastcgiparams') . ";\n";
$php_options_text .= "\t\t" . 'fastcgi_split_path_info ^(.+\.php)(/.+)\$;' . "\n";
$php_options_text .= "\t\t" . 'fastcgi_param SCRIPT_FILENAME $document_root$1;' . "\n";
$php_options_text .= "\t\t" . 'fastcgi_split_path_info ^(.+?\.php)(/.*)$;' . "\n";
$php_options_text .= "\t\t" . 'fastcgi_param SCRIPT_FILENAME $request_filename;' . "\n";
$php_options_text .= "\t\t" . 'fastcgi_param PATH_INFO $2;' . "\n";
if ($domain['ssl'] == '1' && $ssl_vhost) {
$php_options_text .= "\t\t" . 'fastcgi_param HTTPS on;' . "\n";

View File

@@ -36,9 +36,7 @@ class WebserverBase
`d`.`phpsettingid`, `c`.`adminid`, `c`.`guid`, `c`.`email`,
`c`.`documentroot` AS `customerroot`, `c`.`deactivated`,
`c`.`phpenabled` AS `phpenabled_customer`,
`d`.`phpenabled` AS `phpenabled_vhost`,
`d`.`mod_fcgid_starter`,`d`.`mod_fcgid_maxrequests`,
`d`.`ocsp_stapling`
`d`.`phpenabled` AS `phpenabled_vhost`
FROM `" . TABLE_PANEL_DOMAINS . "` `d`
LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`)

View File

@@ -44,8 +44,9 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
echo "Below are possible parameters for this file\n\n";
echo "--[cronname]\t\tincludes the given cron-file\n";
echo "--force\t\t\tforces re-generating of config-files (webserver, nameserver, etc.)\n";
echo "--run-task\t\trun a specific task [1 = re-generate configs, 4 = re-generate dns zones, 10 = re-set quotas, 99 = re-create cron.d-file]\n";
echo "--debug\t\t\toutput debug information about what is going on to STDOUT.\n";
echo "--no-fork\t\t\tdo not fork to backkground (traffic cron only).\n\n";
echo "--no-fork\t\tdo not fork to backkground (traffic cron only).\n\n";
}
/**
@@ -70,10 +71,19 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
// also regenerate cron.d-file
\Froxlor\System\Cronjob::inserttask('99');
array_push($jobs_to_run, 'tasks');
define('CRON_IS_FORCED', 1);
} elseif (strtolower($argv[$x]) == '--debug') {
define('CRON_DEBUG_FLAG', 1);
} elseif (strtolower($argv[$x]) == '--no-fork') {
define('CRON_NOFORK_FLAG', 1);
} elseif (strtolower($argv[$x]) == '--run-task') {
if (isset($argv[$x+1]) && in_array($argv[$x+1], [1,4,10,99])) {
\Froxlor\System\Cronjob::inserttask($argv[$x+1]);
array_push($jobs_to_run, 'tasks');
} else {
echo "Invalid argument for --run-task\n";
exit;
}
} elseif (substr(strtolower($argv[$x]), 0, 2) == '--') {
// --[cronname]
if (strlen($argv[$x]) > 3) {
@@ -90,34 +100,18 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
$tasks_cnt_stmt = \Froxlor\Database\Database::query("SELECT COUNT(*) as jobcnt FROM `panel_tasks`");
$tasks_cnt = $tasks_cnt_stmt->fetch(\PDO::FETCH_ASSOC);
// do we have anything to include?
if (count($jobs_to_run) > 0) {
// include all jobs we want to execute
foreach ($jobs_to_run as $cron) {
self::updateLastRunOfCron($cron);
\Froxlor\System\Cronjob::updateLastRunOfCron($cron);
$cronfile = self::getCronModule($cron);
if ($cronfile && class_exists($cronfile)) {
$cronfile::run();
}
}
if ($tasks_cnt['jobcnt'] > 0) {
if (\Froxlor\Settings::Get('system.nssextrausers') == 1) {
\Froxlor\Cron\System\Extrausers::generateFiles(self::$cronlog);
}
// clear NSCD cache if using fcgid or fpm, #1570
if (\Froxlor\Settings::Get('system.mod_fcgid') == 1 || (int) \Froxlor\Settings::Get('phpfpm.enabled') == 1) {
$false_val = false;
\Froxlor\FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, array(
'>'
));
\Froxlor\FileDir::safe_exec('nscd -i group 1> /dev/null', $false_val, array(
'>'
));
}
}
self::refreshUsers($tasks_cnt['jobcnt']);
}
/**
@@ -132,6 +126,26 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
self::shutdown();
}
private static function refreshUsers($jobcount = 0)
{
if ($jobcount > 0) {
if (\Froxlor\Settings::Get('system.nssextrausers') == 1) {
\Froxlor\Cron\System\Extrausers::generateFiles(self::$cronlog);
}
// clear NSCD cache if using fcgid or fpm, #1570 - not needed for nss-extrausers
if ((\Froxlor\Settings::Get('system.mod_fcgid') == 1 || (int) \Froxlor\Settings::Get('phpfpm.enabled') == 1) && \Froxlor\Settings::Get('system.nssextrausers') == 0) {
$false_val = false;
\Froxlor\FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, array(
'>'
));
\Froxlor\FileDir::safe_exec('nscd -i group 1> /dev/null', $false_val, array(
'>'
));
}
}
}
private static function init()
{
if (@php_sapi_name() != 'cli' && @php_sapi_name() != 'cgi' && @php_sapi_name() != 'cgi-fcgi') {
@@ -335,16 +349,6 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron
}
}
private static function updateLastRunOfCron($cronname)
{
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_CRONRUNS . "` SET `lastrun` = UNIX_TIMESTAMP() WHERE `cronfile` = :cron;
");
Database::pexecute($upd_stmt, array(
'cron' => $cronname
));
}
private static function getCronModule($cronname)
{
$upd_stmt = Database::prepare("

View File

@@ -38,26 +38,45 @@ class MailboxsizeCron extends \Froxlor\Cron\FroxlorCron
$_maildir = \Froxlor\FileDir::makeCorrectDir($maildir['maildirpath']);
if (file_exists($_maildir) && is_dir($_maildir)) {
// mail-address allows many special characters, see http://en.wikipedia.org/wiki/Email_address#Local_part
$return = false;
$back = \Froxlor\FileDir::safe_exec('du -sk ' . escapeshellarg($_maildir), $return, array(
'|',
'&',
'`',
'$',
'~',
'?'
));
foreach ($back as $backrow) {
$emailusage = explode(' ', $backrow);
$maildirsize = \Froxlor\FileDir::makeCorrectFile($_maildir . '/maildirsize');
// When quota is enabled and maildirsize file exists, use that to calculate size
if (\Froxlor\Settings::Get('system.mail_quota_enabled') == 1 && file_exists($maildirsize)) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'found maildirsize file in ' . $_maildir);
$file = file($maildirsize, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
// Remove header
array_shift($file);
$emailusage = 0;
// Sum up all the changes (line 2 -> end)
foreach ($file as $line) {
$parts = explode(' ', $line);
if (!empty($parts[0])) {
$emailusage += floatval($parts[0]);
}
}
} else {
// if quota is disabled or maildirsize file does not exist, compute with du
// mail-address allows many special characters, see http://en.wikipedia.org/wiki/Email_address#Local_part
$return = false;
$back = \Froxlor\FileDir::safe_exec('du -sk ' . escapeshellarg($_maildir), $return, array(
'|',
'&',
'`',
'$',
'~',
'?'
));
foreach ($back as $backrow) {
$emailusage = explode(' ', $backrow);
}
$emailusage = floatval($emailusage['0']);
// as freebsd does not have the -b flag for 'du' which gives
// the size in bytes, we use "-sk" for all and calculate from KiB
$emailusage *= 1024;
unset($back);
}
$emailusage = floatval($emailusage['0']);
// as freebsd does not have the -b flag for 'du' which gives
// the size in bytes, we use "-sk" for all and calculate from KiB
$emailusage *= 1024;
unset($back);
\Froxlor\Database\Database::pexecute($upd_stmt, array(
'size' => $emailusage,
'id' => $maildir['id']

View File

@@ -30,8 +30,9 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
*/
self::$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "TasksCron: Searching for tasks to do");
// no type 99 (regenerate cron.d-file) and no type 20 (customer backup)
// order by type descending to re-create bind and then webserver at the end
$result_tasks_stmt = Database::query("
SELECT `id`, `type`, `data` FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` <> '99' AND `type` <> '20' ORDER BY `id` ASC
SELECT `id`, `type`, `data` FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` <> '99' AND `type` <> '20' ORDER BY `type` DESC, `id` ASC
");
$num_results = Database::num_rows();
$resultIDs = array();
@@ -92,6 +93,12 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
*/
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Removing PowerDNS entries for domain " . $row['data']['domain']);
\Froxlor\Dns\PowerDNS::cleanDomainZone($row['data']['domain']);
} elseif ($row['type'] == '12') {
/**
* TYPE=12 domain has been deleted, remove from acme.sh/let's encrypt directory if used
*/
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Removing Let's Encrypt entries for domain " . $row['data']['domain']);
\Froxlor\Domain\Domain::doLetsEncryptCleanUp($row['data']['domain']);
}
}
@@ -102,7 +109,7 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
$where[] = "`id` = :id_" . (int) $id;
$where_data['id_' . $id] = $id;
}
$where = implode($where, ' OR ');
$where = implode(' OR ', $where);
$del_stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_TASKS . "` WHERE " . $where);
Database::pexecute($del_stmt, $where_data);
unset($resultIDs);
@@ -114,10 +121,6 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
private static function rebuildWebserverConfigs()
{
// get configuration-I/O object
$configio = new \Froxlor\Cron\Http\ConfigIO();
// clean up old configs
$configio->cleanUp();
if (Settings::Get('system.webserver') == "apache2") {
$websrv = '\\Froxlor\\Cron\\Http\\Apache';
@@ -136,9 +139,15 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
}
}
// get configuration-I/O object
$configio = new \Froxlor\Cron\Http\ConfigIO();
// get webserver object
$webserver = new $websrv();
if (isset($webserver)) {
$webserver->init();
// clean up old configs
$configio->cleanUp();
$webserver->createIpPort();
$webserver->createVirtualHosts();
$webserver->createFileDirOptions();
@@ -231,8 +240,8 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron
Extrausers::generateFiles($extrausers_log);
}
// clear NSCD cache if using fcgid or fpm, #1570
if (Settings::Get('system.mod_fcgid') == 1 || (int) Settings::Get('phpfpm.enabled') == 1) {
// clear NSCD cache if using fcgid or fpm, #1570 - not needed for nss-extrausers
if ((Settings::Get('system.mod_fcgid') == 1 || (int) Settings::Get('phpfpm.enabled') == 1) && Settings::Get('system.nssextrausers') == 0) {
$false_val = false;
\Froxlor\FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, array(
'>'

View File

@@ -183,6 +183,21 @@ class Database
return $return;
}
/**
* return number of characters that are allowed to use as username
*
* @return int
*/
public static function getSqlUsernameLength()
{
// MySQL user names can be up to 32 characters long (16 characters before MySQL 5.7.8).
$mysql_max = 32;
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.8', '<')) {
$mysql_max = 16;
}
return $mysql_max;
}
/**
* let's us interact with the PDO-Object by using static
* call like "Database::function()"

View File

@@ -82,9 +82,11 @@ class DbManagerMySQL
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '8.0.11', '>=')) {
// create user
$stmt = Database::prepare("
CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY 'password'
CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY :password
");
Database::pexecute($stmt);
Database::pexecute($stmt, array(
"password" => $password
));
// grant privileges
$stmt = Database::prepare("
GRANT ALL ON `" . $username . "`.* TO :username@:host
@@ -96,29 +98,31 @@ class DbManagerMySQL
} else {
// grant privileges
$stmt = Database::prepare("
GRANT ALL PRIVILEGES ON `" . $username . "`.* TO :username@:host IDENTIFIED BY 'password'
GRANT ALL PRIVILEGES ON `" . $username . "`.* TO :username@:host IDENTIFIED BY :password
");
Database::pexecute($stmt, array(
"username" => $username,
"host" => $access_host
"host" => $access_host,
"password" => $password
));
}
}
// set passoword
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.6', '<')) {
if ($p_encrypted) {
$stmt = Database::prepare("SET PASSWORD FOR :username@:host = :password");
} else {
$stmt = Database::prepare("SET PASSWORD FOR :username@:host = PASSWORD(:password)");
}
} else {
$stmt = Database::prepare("ALTER USER :username@:host IDENTIFIED BY :password");
// set passoword
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.6', '<')) {
if ($p_encrypted) {
$stmt = Database::prepare("SET PASSWORD FOR :username@:host = :password");
} else {
$stmt = Database::prepare("SET PASSWORD FOR :username@:host = PASSWORD(:password)");
}
} else {
$stmt = Database::prepare("ALTER USER :username@:host IDENTIFIED BY :password");
}
Database::pexecute($stmt, array(
"username" => $username,
"host" => $access_host,
"password" => $password
));
}
Database::pexecute($stmt, array(
"username" => $username,
"host" => $access_host,
"password" => $password
));
}
/**
@@ -142,7 +146,11 @@ class DbManagerMySQL
));
// as of MySQL 5.0.2 this also revokes privileges. (requires MySQL 4.1.2+)
$drop_stmt = Database::prepare("DROP USER IF EXISTS :dbname@:host");
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.0', '<')) {
$drop_stmt = Database::prepare("DROP USER :dbname@:host");
} else {
$drop_stmt = Database::prepare("DROP USER IF EXISTS :dbname@:host");
}
while ($host = $host_res_stmt->fetch(\PDO::FETCH_ASSOC)) {
Database::pexecute($drop_stmt, array(
'dbname' => $dbname,
@@ -150,6 +158,7 @@ class DbManagerMySQL
), false);
}
$drop_stmt = Database::prepare("DROP DATABASE IF EXISTS `" . $dbname . "`");
Database::pexecute($drop_stmt);
}
@@ -168,7 +177,11 @@ class DbManagerMySQL
Database::pexecute($stmt);
}
// as of MySQL 5.0.2 this also revokes privileges. (requires MySQL 4.1.2+)
$stmt = Database::prepare("DROP USER :username@:host");
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.0', '<')) {
$stmt = Database::prepare("DROP USER :username@:host");
} else {
$stmt = Database::prepare("DROP USER IF EXISTS :username@:host");
}
Database::pexecute($stmt, array(
"username" => $username,
"host" => $host

View File

@@ -130,6 +130,12 @@ class Dns
}
}
// additional required records for CAA if activated
if (Settings::Get('system.dns_createcaaentry') && Settings::Get('system.use_ssl') == "1" && !empty($domain['p_ssl_ipandports'])) {
// check for CAA content later
self::addRequiredEntry('@CAA@', 'CAA', $required_entries);
}
// additional required records for SPF and DKIM if activated
if ($domain['isemaildomain'] == '1') {
if (Settings::Get('spf.use_spf') == '1') {
@@ -150,6 +156,10 @@ class Dns
if (array_key_exists($entry['type'], $required_entries) && array_key_exists(md5($entry['record']), $required_entries[$entry['type']])) {
unset($required_entries[$entry['type']][md5($entry['record'])]);
}
if (Settings::Get('system.dns_createcaaentry') == '1' && $entry['type'] == 'CAA' && strtolower(substr($entry['content'], 0, 7)) == '"v=caa1') {
// unset special CAA required-entry
unset($required_entries[$entry['type']][md5("@CAA@")]);
}
if (Settings::Get('spf.use_spf') == '1' && $entry['type'] == 'TXT' && $entry['record'] == '@' && strtolower(substr($entry['content'], 0, 7)) == '"v=spf1') {
// unset special spf required-entry
unset($required_entries[$entry['type']][md5("@SPF@")]);
@@ -278,6 +288,31 @@ class Dns
}
}
}
// CAA
if (array_key_exists("CAA", $required_entries)) {
foreach ($required_entries as $type => $records) {
if ($type == 'CAA') {
foreach ($records as $record) {
if ($record == '@CAA@') {
$caa_entries = explode(PHP_EOL, Settings::Get('caa.caa_entry'));
if ($domain['letsencrypt'] == 1) {
$le_entry = $domain['iswildcarddomain'] == '1' ? '0 issuewild "letsencrypt.org"' : '0 issue "letsencrypt.org"';
array_push($caa_entries, $le_entry);
}
foreach ($caa_entries as $entry) {
$zonerecords[] = new DnsEntry('@', 'CAA', $entry);
// additional required records by subdomain setting
if ($domain['wwwserveralias'] == '1') {
$zonerecords[] = new DnsEntry('www', 'CAA', $entry);
}
}
}
}
}
}
}
}
if (empty($primary_ns)) {

View File

@@ -291,6 +291,30 @@ class Domain
}
}
public static function doLetsEncryptCleanUp($domainname = null)
{
// @ see \Froxlor\Cron\Http\LetsEncrypt\AcmeSh.php
$acmesh = "/root/.acme.sh/acme.sh";
if (file_exists($acmesh)) {
$certificate_folder = dirname($acmesh) . "/" . $domainname;
if (\Froxlor\Settings::Get('system.leecc') > 0) {
$certificate_folder .= "_ecc";
}
$certificate_folder = \Froxlor\FileDir::makeCorrectDir($certificate_folder);
if (file_exists($certificate_folder)) {
$params = " --remove -d " . $domainname;
if (\Froxlor\Settings::Get('system.leecc') > 0) {
$params .= " --ecc";
}
// run remove command
\Froxlor\FileDir::safe_exec($acmesh . $params);
// remove certificates directory
@unlink($certificate_folder);
}
}
return true;
}
/**
* checks give path for security issues
* and returns a string that can be appended

View File

@@ -217,7 +217,7 @@ class FileDir
'ADMIN_EMAIL' => $template['admin_email']
);
// @fixme replaceVariables
// replaceVariables
$htmlcontent = PhpHelper::replaceVariables($template['value'], $replace_arr);
$indexhtmlpath = self::makeCorrectFile($destination . '/index.' . Settings::Get('system.index_file_extension'));
$index_html_handler = fopen($indexhtmlpath, 'w');

View File

@@ -7,10 +7,10 @@ final class Froxlor
{
// Main version variable
const VERSION = '0.10.0-rc1';
const VERSION = '0.10.4';
// Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '201904100';
const DBVERSION = '201910200';
// Distribution branding-tag (used for Debian etc.)
const BRANDING = '';

View File

@@ -40,6 +40,13 @@ class FroxlorLogger
*/
private static $userinfo = array();
/**
* whether the logger object has already been initialized
*
* @var bool
*/
private static $is_initialized = false;
const USR_ACTION = '10';
const RES_ACTION = '20';
@@ -72,19 +79,25 @@ class FroxlorLogger
}
}
foreach (self::$logtypes as $logger) {
if (self::$is_initialized == false) {
foreach (self::$logtypes as $logger) {
switch ($logger) {
case 'syslog':
self::$ml->pushHandler(new SyslogHandler('froxlor', LOG_USER, Logger::DEBUG));
break;
case 'file':
self::$ml->pushHandler(new StreamHandler(Settings::Get('logger.logfile'), Logger::DEBUG));
break;
case 'mysql':
self::$ml->pushHandler(new MysqlHandler(Logger::DEBUG));
break;
switch ($logger) {
case 'syslog':
self::$ml->pushHandler(new SyslogHandler('froxlor', LOG_USER, Logger::DEBUG));
break;
case 'file':
if (empty(Settings::Get('logger.logfile')) || ! is_writeable(Settings::Get('logger.logfile'))) {
Settings::Set('logger.logfile', '/tmp/froxlor.log');
}
self::$ml->pushHandler(new StreamHandler(Settings::Get('logger.logfile'), Logger::DEBUG));
break;
case 'mysql':
self::$ml->pushHandler(new MysqlHandler(Logger::DEBUG));
break;
}
}
self::$is_initialized = true;
}
}

View File

@@ -11,7 +11,7 @@ class HttpClient
*
* @return array
*/
public static function urlGet($url, $follow_location = true)
public static function urlGet($url, $follow_location = true, $timeout = 10)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
@@ -19,6 +19,7 @@ class HttpClient
if ($follow_location) {
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
}
curl_setopt($ch, CURLOPT_TIMEOUT, (int)$timeout);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
if ($output === false) {

View File

@@ -101,13 +101,13 @@ class MailLogParser
$timestamp = $this->getLogTimestamp($line);
if ($this->startTime < $timestamp) {
if (preg_match("/postfix\/qmgr.*(?::|\])\s([A-Z\d]+).*from=<?(?:.*\@([a-z\A-Z\d\.\-]+))?>?, size=(\d+),/", $line, $matches)) {
if (preg_match("/postfix\/qmgr.*(?::|\])\s([A-Z\d]+).*from=<?(?:.*\@([a-zA-Z\d\.\-]+))?>?, size=(\d+),/", $line, $matches)) {
// Postfix from
$this->mails[$matches[1]] = array(
"domainFrom" => strtolower($matches[2]),
"size" => $matches[3]
);
} elseif (preg_match("/postfix\/(?:pipe|smtp).*(?::|\])\s([A-Z\d]+).*to=<?(?:.*\@([a-z\A-Z\d\.\-]+))?>?,/", $line, $matches)) {
} elseif (preg_match("/postfix\/(?:pipe|smtp).*(?::|\])\s([A-Z\d]+).*to=<?(?:.*\@([a-zA-Z\d\.\-]+))?>?,/", $line, $matches)) {
// Postfix to
if (array_key_exists($matches[1], $this->mails)) {
$this->mails[$matches[1]]["domainTo"] = strtolower($matches[2]);

View File

@@ -263,6 +263,8 @@ class Settings
self::init();
// empty update array
self::$updatedata = array();
// re-read in all settings
return self::readSettings();
}
public static function loadSettingsInto(&$settings_data)

View File

@@ -27,29 +27,58 @@ class Store
$returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && $fielddata['varname'] == 'defaultip') {
self::updateStdSubdomainDefaultIp($newfieldvalue, $defaultips_old);
}
$customerstddomains_result_stmt = Database::prepare("
SELECT `standardsubdomain` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `standardsubdomain` <> '0'
");
Database::pexecute($customerstddomains_result_stmt);
return $returnvalue;
}
$ids = array();
public static function storeSettingDefaultSslIp($fieldname, $fielddata, $newfieldvalue)
{
$defaultips_old = Settings::Get('system.defaultsslip');
while ($customerstddomains_row = $customerstddomains_result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$ids[] = (int) $customerstddomains_row['standardsubdomain'];
$returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && $fielddata['varname'] == 'defaultsslip') {
self::updateStdSubdomainDefaultIp($newfieldvalue, $defaultips_old);
}
return $returnvalue;
}
private static function updateStdSubdomainDefaultIp($newfieldvalue, $defaultips_old)
{
// update standard-subdomain of customer if exists
$customerstddomains_result_stmt = Database::prepare("
SELECT `standardsubdomain` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `standardsubdomain` <> '0'
");
Database::pexecute($customerstddomains_result_stmt);
$ids = array();
while ($customerstddomains_row = $customerstddomains_result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$ids[] = (int) $customerstddomains_row['standardsubdomain'];
}
if (count($ids) > 0) {
$defaultips_new = explode(',', $newfieldvalue);
if (! empty($defaultips_old) && ! empty($newfieldvalue)) {
$in_value = $defaultips_old . ", " . $newfieldvalue;
} elseif (! empty($defaultips_old) && empty($newfieldvalue)) {
$in_value = $defaultips_old;
} else {
$in_value = $newfieldvalue;
}
if (count($ids) > 0) {
$defaultips_new = explode(',', $newfieldvalue);
// Delete the existing mappings linking to default IPs
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_DOMAINTOIP . "`
WHERE `id_domain` IN (" . implode(', ', $ids) . ")
AND `id_ipandports` IN (" . $defaultips_old . ", " . $newfieldvalue . ")
");
Database::pexecute($del_stmt);
// Delete the existing mappings linking to default IPs
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_DOMAINTOIP . "`
WHERE `id_domain` IN (" . implode(', ', $ids) . ")
AND `id_ipandports` IN (" . $in_value . ")
");
Database::pexecute($del_stmt);
if (count($defaultips_new) > 0) {
// Insert the new mappings
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_DOMAINTOIP . "`
@@ -66,68 +95,6 @@ class Store
}
}
}
return $returnvalue;
}
public static function storeSettingDefaultSslIp($fieldname, $fielddata, $newfieldvalue)
{
$defaultips_old = Settings::Get('system.defaultsslip');
$returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && $fielddata['varname'] == 'defaultsslip') {
$customerstddomains_result_stmt = Database::prepare("
SELECT `standardsubdomain` FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `standardsubdomain` <> '0'
");
Database::pexecute($customerstddomains_result_stmt);
$ids = array();
while ($customerstddomains_row = $customerstddomains_result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$ids[] = (int) $customerstddomains_row['standardsubdomain'];
}
if (count($ids) > 0) {
$defaultips_new = explode(',', $newfieldvalue);
if (! empty($defaultips_old) && ! empty($newfieldvalue)) {
$in_value = $defaultips_old . ", " . $newfieldvalue;
} elseif (! empty($defaultips_old) && empty($newfieldvalue)) {
$in_value = $defaultips_old;
} else {
$in_value = $newfieldvalue;
}
// Delete the existing mappings linking to default IPs
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_DOMAINTOIP . "`
WHERE `id_domain` IN (" . implode(', ', $ids) . ")
AND `id_ipandports` IN (" . $in_value . ")
");
Database::pexecute($del_stmt);
if (count($defaultips_new) > 0) {
// Insert the new mappings
$ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_DOMAINTOIP . "`
SET `id_domain` = :domainid, `id_ipandports` = :ipandportid
");
foreach ($ids as $id) {
foreach ($defaultips_new as $defaultip_new) {
Database::pexecute($ins_stmt, array(
'domainid' => $id,
'ipandportid' => $defaultip_new
));
}
}
}
}
}
return $returnvalue;
}
/**
@@ -143,25 +110,24 @@ class Store
*/
public static function storeSettingDefaultTheme($fieldname, $fielddata, $newfieldvalue)
{
// first save the setting itself
$returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'panel' && isset($fielddata['varname']) && $fielddata['varname'] == 'default_theme') {
// now, if changing themes is disabled we recursivly set
// now, if changing themes is disabled we manually set
// the new theme (customers and admin, depending on settings)
if (Settings::Get('panel.allow_theme_change_customer') == '0') {
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `theme` = :theme
");
UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `theme` = :theme
");
Database::pexecute($upd_stmt, array(
'theme' => $newfieldvalue
));
}
if (Settings::Get('panel.allow_theme_change_admin') == '0') {
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_ADMINS . "` SET `theme` = :theme
");
UPDATE `" . TABLE_PANEL_ADMINS . "` SET `theme` = :theme
");
Database::pexecute($upd_stmt, array(
'theme' => $newfieldvalue
));
@@ -204,17 +170,13 @@ class Store
public static function storeSettingFieldInsertBindTask($fieldname, $fielddata, $newfieldvalue)
{
if (is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] != '' && isset($fielddata['varname']) && $fielddata['varname'] != '') {
if (Settings::Set($fielddata['settinggroup'] . '.' . $fielddata['varname'], $newfieldvalue) !== false) {
return array(
$fielddata['settinggroup'] . '.' . $fielddata['varname'] => $newfieldvalue
);
} else {
return false;
}
} else {
return false;
// first save the setting itself
$returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
if ($returnvalue !== false) {
\Froxlor\System\Cronjob::inserttask('4');
}
return false;
}
public static function storeSettingHostname($fieldname, $fielddata, $newfieldvalue)
@@ -290,6 +252,28 @@ class Store
public static function storeSettingMysqlAccessHost($fieldname, $fielddata, $newfieldvalue)
{
$ips = $newfieldvalue;
// Convert cidr to netmask for mysql, if needed be
if (strpos($ips, ',') !== false) {
$ips = explode(',', $ips);
}
if (is_array($ips) && count($ips) > 0) {
$newfieldvalue = [];
foreach ($ips as $ip) {
$org_ip = $ip;
$ip_cidr = explode("/", $ip);
if (count($ip_cidr) === 2) {
$ip = $ip_cidr[0];
if (strlen($ip_cidr[1]) <= 2) {
$ip_cidr[1] = \Froxlor\Validate\Validate::cidr2NetmaskAddr($org_ip);
}
$newfieldvalue[] = $ip . '/' . $ip_cidr[1];
} else {
$newfieldvalue[] = $org_ip;
}
}
$newfieldvalue = implode(',', $newfieldvalue);
}
$returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && $fielddata['varname'] == 'mysql_access_host') {
@@ -330,25 +314,9 @@ class Store
$returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'catchall' && isset($fielddata['varname']) && $fielddata['varname'] == 'catchall_enabled' && $newfieldvalue == '0') {
$result_stmt = Database::query("
SELECT `id`, `email`, `email_full`, `iscatchall` FROM `" . TABLE_MAIL_VIRTUAL . "`
WHERE `iscatchall` = '1'
Database::query("
UPDATE `" . TABLE_MAIL_VIRTUAL . "` SET `iscatchall` = '0' WHERE `iscatchall` = '1'
");
if (Database::num_rows() > 0) {
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_MAIL_VIRTUAL . "` SET `email` = :email, `iscatchall` = '0' WHERE `id` = :id
");
while ($result_row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
Database::pexecute($upd_stmt, array(
'email' => $result_row['email_full'],
'id' => $result_row['id']
));
}
}
}
return $returnvalue;

View File

@@ -178,6 +178,14 @@ class Cronjob
'type' => '11',
'data' => $data
));
} elseif ($type == '12' && $param1 != '') {
$data = array();
$data['domain'] = $param1;
$data = json_encode($data);
Database::pexecute($ins_stmt, array(
'type' => '12',
'data' => $data
));
} elseif ($type == '20' && is_array($param1)) {
$data = json_encode($param1);
Database::pexecute($ins_stmt, array(
@@ -277,6 +285,9 @@ class Cronjob
} elseif ($row['type'] == '11') {
// remove domain from pdns database if used
$task_desc = sprintf($lng['tasks']['remove_pdns_domain'], $row['data']['domain']);
} elseif ($row['type'] == '12') {
// remove domains ssl files
$task_desc = sprintf($lng['tasks']['remove_ssl_domain'], $row['data']['domain']);
} elseif ($row['type'] == '20') {
// deleting user-files
$loginname = '';
@@ -350,4 +361,14 @@ class Cronjob
die($message);
}
public static function updateLastRunOfCron($cronname)
{
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_CRONRUNS . "` SET `lastrun` = UNIX_TIMESTAMP() WHERE `cronfile` = :cron;
");
Database::pexecute($upd_stmt, array(
'cron' => $cronname
));
}
}

View File

@@ -57,7 +57,7 @@ class MysqlHandler extends AbstractProcessingHandler
{
$this->insert([
':message' => $record['message'],
':contextUser' => (isset($record['context']['loginname']) ? $record['context']['loginname'] : 'unknown'),
':contextUser' => (isset($record['context']['user']) ? $record['context']['user'] : 'unknown'),
':contextAction' => (isset($record['context']['action']) ? $record['context']['action'] : '0'),
':level' => self::$froxlorLevels[$record['level']],
':datetime' => $record['datetime']->format('U')

View File

@@ -282,7 +282,7 @@ class Paging
$field .= '`';
}
if ($field{0} != '`') {
if ($field[0] != '`') {
$field = '`' . $field;
}
@@ -352,7 +352,7 @@ class Paging
$field .= '`';
}
if ($field{0} != '`') {
if ($field[0] != '`') {
$field = '`' . $field;
}

View File

@@ -77,8 +77,7 @@ class Check
$mysql_access_host_array = array_map('trim', explode(',', $newfieldvalue));
foreach ($mysql_access_host_array as $host_entry) {
if (Validate::validate_ip2($host_entry, true, 'invalidip', true, true) == false && Validate::validateDomain($host_entry) == false && Validate::validateLocalHostname($host_entry) == false && $host_entry != '%') {
if (Validate::validate_ip2($host_entry, true, 'invalidip', true, true, true, true, false) == false && Validate::validateDomain($host_entry) == false && Validate::validateLocalHostname($host_entry) == false && $host_entry != '%') {
return array(
self::FORMFIELDS_PLAUSIBILITY_CHECK_ERROR,
'invalidmysqlhost',
@@ -192,7 +191,7 @@ class Check
}
$returnvalue = array();
if (Validate::validateUsername($newfieldvalue, Settings::Get('panel.unix_names'), 14 - strlen($allnewfieldvalues['customer_mysqlprefix'])) === true) {
if (Validate::validateUsername($newfieldvalue, Settings::Get('panel.unix_names'), \Froxlor\Database\Database::getSqlUsernameLength() - strlen($allnewfieldvalues['customer_mysqlprefix'])) === true) {
$returnvalue = array(
self::FORMFIELDS_PLAUSIBILITY_CHECK_OK
);

View File

@@ -33,7 +33,7 @@ class Data
if (isset($fielddata['string_type']) && $fielddata['string_type'] == 'mail') {
$returnvalue = (filter_var($newfieldvalue, FILTER_VALIDATE_EMAIL) == $newfieldvalue);
} elseif (isset($fielddata['string_type']) && $fielddata['string_type'] == 'url') {
$returnvalue = self::validateUrl($newfieldvalue);
$returnvalue = \Froxlor\Validate\Validate::validateUrl($newfieldvalue);
} elseif (isset($fielddata['string_type']) && $fielddata['string_type'] == 'dir') {
// check for empty value (it might be allowed)
if (trim($newfieldvalue) == '') {
@@ -128,62 +128,6 @@ class Data
}
}
/**
* Returns whether a URL is in a correct format or not
*
* @param string $url
* URL to be tested
* @return bool
* @author Christian Hoffmann
* @author Froxlor team <team@froxlor.org> (2010-)
*
*/
public static function validateUrl($url)
{
if (strtolower(substr($url, 0, 7)) != "http://" && strtolower(substr($url, 0, 8)) != "https://") {
$url = 'http://' . $url;
}
// needs converting
try {
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$url = $idna_convert->encode($url);
} catch (\Exception $e) {
return false;
}
$pattern = "/^https?:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,4}(\:[0-9]+)?\/?(.+)?$/i";
if (preg_match($pattern, $url)) {
return true;
}
// not an fqdn
if (strtolower(substr($url, 0, 7)) == "http://" || strtolower(substr($url, 0, 8)) == "https://") {
if (strtolower(substr($url, 0, 7)) == "http://") {
$ip = strtolower(substr($url, 7));
}
if (strtolower(substr($url, 0, 8)) == "https://") {
$ip = strtolower(substr($url, 8));
}
$ip = substr($ip, 0, strpos($ip, '/'));
// possible : in IP (when a port is given), #1173
// but only if there actually IS ONE
if (strpos($ip, ':') !== false) {
$ip = substr($ip, 0, strpos($ip, ':'));
}
if (validate_ip($ip, true) !== false) {
return true;
} else {
return false;
}
} else {
return false;
}
}
public static function validateFormFieldBool($fieldname, $fielddata, $newfieldvalue)
{
if ($newfieldvalue === '1' || $newfieldvalue === 1 || $newfieldvalue === true || strtolower($newfieldvalue) === 'yes' || strtolower($newfieldvalue) === 'ja' || $newfieldvalue === '0' || $newfieldvalue === 0 || $newfieldvalue === false || strtolower($newfieldvalue) === 'no' || strtolower($newfieldvalue) === 'nein' || strtolower($newfieldvalue) === '') {
@@ -252,7 +196,7 @@ class Data
if (isset($fielddata['string_type']) && $fielddata['string_type'] == 'mail') {
$returnvalue = (filter_var($newfieldvalue, FILTER_VALIDATE_EMAIL) == $newfieldvalue);
} elseif (isset($fielddata['string_type']) && $fielddata['string_type'] == 'url') {
$returnvalue = \Froxlor\Validate\Form\Data::validateUrl($newfieldvalue);
$returnvalue = \Froxlor\Validate\Validate::validateUrl($newfieldvalue);
} elseif (isset($fielddata['string_type']) && $fielddata['string_type'] == 'dir') {
// add trailing slash to validate path if needed
// refs #331

View File

@@ -23,8 +23,6 @@ class Validate
*/
public static function validate($str, $fieldname, $pattern = '', $lng = '', $emptydefault = array(), $throw_exception = false)
{
global $log;
if (! is_array($emptydefault)) {
$emptydefault_array = array(
$emptydefault
@@ -35,8 +33,8 @@ class Validate
}
// Check if the $str is one of the values which represent the default for an 'empty' value
if (is_array($emptydefault) && ! empty($emptydefault) && in_array($str, $emptydefault) && isset($emptydefault[0])) {
return $emptydefault[0];
if (is_array($emptydefault) && ! empty($emptydefault) && in_array($str, $emptydefault)) {
return $str;
}
if ($pattern == '') {
@@ -48,6 +46,7 @@ class Validate
// everything else is removed from the string.
$allowed = "/[^a-z0-9\\040\\.\\-\\_\\\\]/i";
$str = preg_replace($allowed, "", $str);
$log = \Froxlor\FroxlorLogger::getInstanceOf();
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "cleaned bad formatted string (" . $str . ")");
}
}
@@ -61,7 +60,38 @@ class Validate
}
\Froxlor\UI\Response::standard_error($lng, $fieldname, $throw_exception);
exit();
}
/**
* Converts CIDR to a netmask address
*
* @thx to https://stackoverflow.com/a/5711080/3020926
* @param string $cidr
*
* @return string
*/
public static function cidr2NetmaskAddr($cidr)
{
$ta = substr($cidr, strpos($cidr, '/') + 1) * 1;
$netmask = str_split(str_pad(str_pad('', $ta, '1'), 32, '0'), 8);
foreach ($netmask as &$element) {
$element = bindec($element);
}
return implode('.', $netmask);
}
/**
* Checks if an $address (IP) is IPv6
*
* @param string $address
*
* @return string|bool ip address on success, false on failure
*/
public static function is_ipv6($address)
{
return filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
}
/**
@@ -79,17 +109,35 @@ class Validate
* whether to allow private network addresses
* @param bool $allow_cidr
* whether to allow CIDR values e.g. 10.10.10.10/16
* @param bool $cidr_as_netmask
* whether to format CIDR nodation to netmask notation
* @param bool $throw_exception
* whether to throw an exception on failure
*
* @return string|bool ip address on success, false on failure
*/
public static function validate_ip2($ip, $return_bool = false, $lng = 'invalidip', $allow_localhost = false, $allow_priv = false, $allow_cidr = false, $throw_exception = false)
public static function validate_ip2($ip, $return_bool = false, $lng = 'invalidip', $allow_localhost = false, $allow_priv = false, $allow_cidr = false, $cidr_as_netmask = false, $throw_exception = false)
{
$cidr = "";
if ($allow_cidr) {
$org_ip = $ip;
$ip_cidr = explode("/", $ip);
if (count($ip_cidr) == 2) {
if (count($ip_cidr) === 2) {
if (strlen($ip_cidr[1]) <= 2 && in_array((int) $ip_cidr[1], array_values(range(1, 32)), true) === false) {
\Froxlor\UI\Response::standard_error($lng, $ip, $throw_exception);
}
if ($cidr_as_netmask && self::is_ipv6($ip_cidr[0])) {
// MySQL does not handle CIDR of IPv6 addresses, return error
if ($return_bool) {
return false;
} else {
\Froxlor\UI\Response::standard_error($lng, $ip, $throw_exception);
}
}
$ip = $ip_cidr[0];
if ($cidr_as_netmask && strlen($ip_cidr[1]) <= 2) {
$ip_cidr[1] = self::cidr2NetmaskAddr($org_ip);
}
$cidr = "/" . $ip_cidr[1];
} else {
$ip = $org_ip;
@@ -99,7 +147,6 @@ class Validate
return false;
} else {
\Froxlor\UI\Response::standard_error($lng, $ip, $throw_exception);
exit();
}
}
@@ -118,10 +165,39 @@ class Validate
return false;
} else {
\Froxlor\UI\Response::standard_error($lng, $ip, $throw_exception);
exit();
}
}
/**
* Returns whether a URL is in a correct format or not
*
* @param string $url
* URL to be tested
*
* @return bool
*/
public static function validateUrl($url)
{
if (strtolower(substr($url, 0, 7)) != "http://" && strtolower(substr($url, 0, 8)) != "https://") {
$url = 'http://' . $url;
}
// needs converting
try {
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$url = $idna_convert->encode($url);
} catch (\Exception $e) {
return false;
}
$pattern = '%^(?:(?:https?)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$%iuS';
if (preg_match($pattern, $url)) {
return true;
}
return false;
}
/**
* Check if the submitted string is a valid domainname
*
@@ -157,7 +233,7 @@ class Validate
*/
public static function validateLocalHostname($hostname)
{
$pattern = '/^([a-zA-Z0-9\-])+$/i';
$pattern = '/^[a-z0-9][a-z0-9\-]{0,62}$/i';
if (preg_match($pattern, $hostname)) {
return $hostname;
}
@@ -180,52 +256,59 @@ class Validate
/**
* Returns if an username is in correct format or not.
*
* @param
* string The username to check
* @return bool Correct or not
* @author Michael Duergner <michael@duergner.com>
*
* @param string $username
* The username to check
* @param bool $unix_names
* optional, default true, checks whether it must be UNIX compatible
* @param int $mysql_max
* optional, number of max mysql username characters, default empty
*
* @return bool
*/
public static function validateUsername($username, $unix_names = 1, $mysql_max = '')
{
if (empty($mysql_max) || ! is_numeric($mysql_max) || $mysql_max <= 0) {
$mysql_max = \Froxlor\Database\Database::getSqlUsernameLength() - 1;
} else {
$mysql_max --;
}
if ($unix_names == 0) {
if (strpos($username, '--') === false) {
return (preg_match('/^[a-z][a-z0-9\-_]{0,' . (int) ($mysql_max - 1) . '}[a-z0-9]{1}$/Di', $username) != false);
} else {
return false;
return (preg_match('/^[a-z][a-z0-9\-_]{0,' . $mysql_max . '}[a-z0-9]{1}$/Di', $username) != false);
}
} else {
return (preg_match('/^[a-z][a-z0-9]{0,' . $mysql_max . '}$/Di', $username) != false);
return false;
}
return (preg_match('/^[a-z][a-z0-9]{0,' . $mysql_max . '}$/Di', $username) != false);
}
/**
* validate sql interval string
*
* @param string $interval
*
* @return boolean
*/
public static function validateSqlInterval($interval = null)
{
if (! $interval === null || $interval != '') {
if (strstr($interval, ' ') !== false) {
/*
* [0] = ([0-9]+)
* [1] = valid SQL-Interval expression
*/
$valid_expr = array(
'SECOND',
'MINUTE',
'HOUR',
'DAY',
'WEEK',
'MONTH',
'YEAR'
);
if (! empty($interval) && strstr($interval, ' ') !== false) {
/*
* [0] = ([0-9]+)
* [1] = valid SQL-Interval expression
*/
$valid_expr = array(
'SECOND',
'MINUTE',
'HOUR',
'DAY',
'WEEK',
'MONTH',
'YEAR'
);
$interval_parts = explode(' ', $interval);
$interval_parts = explode(' ', $interval);
if (is_array($interval_parts) && isset($interval_parts[0]) && isset($interval_parts[1])) {
if (preg_match('/([0-9]+)/i', $interval_parts[0])) {
if (in_array(strtoupper($interval_parts[1]), $valid_expr)) {
return true;
}
}
}
if (count($interval_parts) == 2 && preg_match('/[0-9]+/', $interval_parts[0]) && in_array(strtoupper($interval_parts[1]), $valid_expr)) {
return true;
}
}
return false;

4675
lib/configfiles/bionic.xml Normal file

File diff suppressed because it is too large Load Diff

4877
lib/configfiles/buster.xml Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -405,11 +405,6 @@ allow-axfr-ips=127.0.0.0/8,::1,<NAMESERVERS_IP>
#
# allow-dnsupdate-from=127.0.0.0/8,::1
#################################
# allow-recursion List of subnets that are allowed to recurse
#
allow-recursion=127.0.0.1
#################################
# also-notify When notifying a domain, also notify these nameservers
#
@@ -750,16 +745,6 @@ module-dir=/usr/lib/powerdns/pdns/
#
# receiver-threads=1
#################################
# recursive-cache-ttl Seconds to store packets for recursive queries in the PacketCache
#
# recursive-cache-ttl=10
#################################
# recursor If recursion is desired, IP address of a recursing nameserver
#
# recursor=no
#################################
# retrieval-threads Number of AXFR-retrieval threads for slave operation
#
@@ -949,11 +934,6 @@ allow-axfr-ips=127.0.0.0/8,::1,<NAMESERVERS_IP>
#
# allow-dnsupdate-from=127.0.0.0/8,::1
#################################
# allow-recursion List of subnets that are allowed to recurse
#
allow-recursion=127.0.0.1
#################################
# also-notify When notifying a domain, also notify these nameservers
#
@@ -1294,16 +1274,6 @@ module-dir=/usr/lib/powerdns/pdns/
#
# receiver-threads=1
#################################
# recursive-cache-ttl Seconds to store packets for recursive queries in the PacketCache
#
# recursive-cache-ttl=10
#################################
# recursor If recursion is desired, IP address of a recursing nameserver
#
# recursor=no
#################################
# retrieval-threads Number of AXFR-retrieval threads for slave operation
#
@@ -1504,7 +1474,7 @@ user = <SQL_UNPRIVILEGED_USER>
password = <SQL_UNPRIVILEGED_PASSWORD>
dbname = <SQL_DB>
hosts = <SQL_HOST>
query = SELECT destination FROM mail_virtual WHERE email = '%s' AND trim(destination) <> ''
query = SELECT destination FROM mail_virtual AS v, panel_customers AS c WHERE c.customerid = v.customerid AND c.deactivated = 0 AND v.email = '%s' AND trim(v.destination) <> ''
]]>
</content>
</file>
@@ -3687,21 +3657,7 @@ account required pam_mysql.so user=<SQL_UNPRIVILEGED_USER> passwd=<SQL_UN
<!-- Cronjob -->
<daemon name="cron" title="Cronjob for froxlor"
mandatory="true">
<file name="/etc/cron.d/froxlor" chown="root:0" chmod="0640">
<content><![CDATA[
#
# Set PATH, otherwise restart-scripts won't find start-stop-daemon
#
PATH=/sbin:/bin:/usr/sbin:/usr/bin
#
# Regular cron jobs for the froxlor package
#
# Please check that all following paths are correct
#
*/5 * * * * root /usr/bin/nice -n 5 /usr/bin/php -q <BASE_PATH>scripts/froxlor_master_cronjob.php
]]>
</content>
</file>
<command><![CDATA[/usr/bin/php <BASE_PATH>scripts/froxlor_master_cronjob.php --run-task 99]]></command>
<command><![CDATA[{{settings.system.crondreload}}]]></command>
</daemon>
<!-- AWstats -->

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<froxlor>
<distribution name="Debian" codename="Jessie"
version="8.x" defaulteditor="/usr/bin/nano">
version="8.x" defaulteditor="/usr/bin/nano" deprecated="true">
<services>
<!-- HTTP -->
<service type="http" title="{{lng.admin.configfiles.http}}">
@@ -1504,7 +1504,7 @@ user = <SQL_UNPRIVILEGED_USER>
password = <SQL_UNPRIVILEGED_PASSWORD>
dbname = <SQL_DB>
hosts = <SQL_HOST>
query = SELECT destination FROM mail_virtual WHERE email = '%s' AND trim(destination) <> ''
query = SELECT destination FROM mail_virtual AS v, panel_customers AS c WHERE c.customerid = v.customerid AND c.deactivated = 0 AND v.email = '%s' AND trim(v.destination) <> ''
]]>
</content>
</file>
@@ -3658,7 +3658,7 @@ protocol sieve {
# %m - number of messages (before deletion)
# %s - mailbox size in bytes (before deletion)
# %u - old/new UIDL hash. may help finding out if UIDLs changed unexpectedly
#pop3_logout_format = top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
pop3_logout_format = in=%i out=%o top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
# Workarounds for various client bugs:
# outlook-no-nuls:
@@ -4461,21 +4461,7 @@ UPLOADGID=
<!-- Cronjob -->
<daemon name="cron" title="Cronjob for froxlor"
mandatory="true">
<file name="/etc/cron.d/froxlor" chown="root:0" chmod="0640">
<content><![CDATA[
#
# Set PATH, otherwise restart-scripts won't find start-stop-daemon
#
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
#
# Regular cron jobs for the froxlor package
#
# Please check that all following paths are correct
#
*/5 * * * * root /usr/bin/nice -n 5 /usr/bin/php -q <BASE_PATH>scripts/froxlor_master_cronjob.php
]]>
</content>
</file>
<command><![CDATA[/usr/bin/php <BASE_PATH>scripts/froxlor_master_cronjob.php --run-task 99]]></command>
<command><![CDATA[{{settings.system.crondreload}}]]></command>
</daemon>
<!-- AWstats -->
@@ -4490,7 +4476,7 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
</daemon>
<!-- libnss-mysql -->
<daemon name="libnss"
title="libnss-mysql (required for FCGID/php-fpm/mpm-itk)">
title="libnss-mysql (alternative for libnss-extrausers, required for FCGID/php-fpm/mpm-itk)">
<install><![CDATA[apt-get install nscd
wget http://debian.froxlor.org/pool/main/libn/libnss-mysql-bg/libnss-mysql-bg_1.5-3+frx1_amd64.deb
dpkg -i libnss-mysql-bg_1.5-3+frx1_amd64.deb
@@ -4663,8 +4649,8 @@ aliases: files
</daemon>
<!-- libnss-extrausers -->
<daemon name="libnssextrausers"
title="libnss-extrausers (alternative to libnss-mysql, required for FCGID/php-fpm/mpm-itk)">
<install><![CDATA[apt-get install nscd libnss-extrausers]]></install>
title="libnss-extrausers (required for FCGID/php-fpm/mpm-itk)">
<install><![CDATA[apt-get install libnss-extrausers]]></install>
<commands index="1">
<command><![CDATA[mkdir -p /var/lib/extrausers]]></command>
<command><![CDATA[touch /var/lib/extrausers/passwd]]></command>
@@ -4696,9 +4682,6 @@ aliases: files
]]>
</content>
</file>
<command><![CDATA[/etc/init.d/nscd restart]]></command>
<!-- clear group chache -->
<command><![CDATA[nscd --invalidate=group]]></command>
</daemon>
<!-- Logrotate -->
<daemon name="logrotate" title="Logrotate">

File diff suppressed because it is too large Load Diff

View File

@@ -95,7 +95,7 @@ user = <SQL_UNPRIVILEGED_USER>
password = <SQL_UNPRIVILEGED_PASSWORD>
dbname = <SQL_DB>
hosts = <SQL_HOST>
query = SELECT destination FROM mail_virtual WHERE email = '%s' AND trim(destination) <> ''
query = SELECT destination FROM mail_virtual AS v, panel_customers AS c WHERE c.customerid = v.customerid AND c.deactivated = 0 AND v.email = '%s' AND trim(v.destination) <> ''
]]>
</content>
</file>
@@ -1529,7 +1529,7 @@ protocol sieve {
# %m - number of messages (before deletion)
# %s - mailbox size in bytes (before deletion)
# %u - old/new UIDL hash. may help finding out if UIDLs changed unexpectedly
#pop3_logout_format = top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
pop3_logout_format = in=%i out=%o top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
# Workarounds for various client bugs:
# outlook-no-nuls:
@@ -1826,7 +1826,7 @@ iterate_query = SELECT username AS user FROM mail_users
<daemon name="proftpd" version="1.3" title="ProFTPd"
default="true">
<install><![CDATA[yum install proftpd proftpd-mysql]]></install>
<file name="/etc/proftpd/proftpd.conf" chown="root:0"
<file name="/etc/proftpd.conf" chown="root:0"
chmod="0600" backup="true">
<content><![CDATA[
# This is the ProFTPD configuration file
@@ -2289,21 +2289,7 @@ ControlsLog /var/log/proftpd/controls.log
<!-- Cronjob -->
<daemon name="cron" title="Cronjob for froxlor"
mandatory="true">
<file name="/etc/cron.d/froxlor" chown="root:0" chmod="0640">
<content><![CDATA[
#
# Set PATH, otherwise restart-scripts won't find start-stop-daemon
#
PATH=/sbin:/bin:/usr/sbin:/usr/bin
#
# Regular cron jobs for the froxlor package
#
# Please check that all following paths are correct
#
*/1 * * * * root /usr/bin/php -q <BASE_PATH>scripts/froxlor_master_cronjob.php
]]>
</content>
</file>
<command><![CDATA[/usr/bin/php <BASE_PATH>scripts/froxlor_master_cronjob.php --run-task 99]]></command>
<command><![CDATA[{{settings.system.crondreload}}]]></command>
</daemon>
<!-- AWstats -->

View File

@@ -1493,7 +1493,7 @@ user = <SQL_UNPRIVILEGED_USER>
password = <SQL_UNPRIVILEGED_PASSWORD>
dbname = <SQL_DB>
hosts = <SQL_HOST>
query = SELECT destination FROM mail_virtual WHERE email = '%s' AND trim(destination) <> ''
query = SELECT destination FROM mail_virtual AS v, panel_customers AS c WHERE c.customerid = v.customerid AND c.deactivated = 0 AND v.email = '%s' AND trim(v.destination) <> ''
]]>
</content>
</file>
@@ -3735,7 +3735,7 @@ protocol sieve {
# %m - number of messages (before deletion)
# %s - mailbox size in bytes (before deletion)
# %u - old/new UIDL hash. may help finding out if UIDLs changed unexpectedly
#pop3_logout_format = top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
pop3_logout_format = in=%i out=%o top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
# Workarounds for various client bugs:
# outlook-no-nuls:
@@ -4528,21 +4528,7 @@ UPLOADGID=
<!-- Cronjob -->
<daemon name="cron" title="Cronjob for froxlor"
mandatory="true">
<file name="/etc/cron.d/froxlor" chown="root:0" chmod="0640">
<content><![CDATA[
#
# Set PATH, otherwise restart-scripts won't find start-stop-daemon
#
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
#
# Regular cron jobs for the froxlor package
#
# Please check that all following paths are correct
#
*/5 * * * * root /usr/bin/nice -n 5 /usr/bin/php -q <BASE_PATH>scripts/froxlor_master_cronjob.php
]]>
</content>
</file>
<command><![CDATA[/usr/bin/php <BASE_PATH>scripts/froxlor_master_cronjob.php --run-task 99]]></command>
<command><![CDATA[{{settings.system.crondreload}}]]></command>
</daemon>
<!-- AWstats -->
@@ -4557,8 +4543,8 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
</daemon>
<!-- libnss-extrausers -->
<daemon name="libnssextrausers"
title="libnss-extrausers (alternative to libnss-mysql, required for FCGID/php-fpm/mpm-itk)">
<install><![CDATA[apt-get install nscd libnss-extrausers]]></install>
title="libnss-extrausers (required for FCGID/php-fpm/mpm-itk)">
<install><![CDATA[apt-get install libnss-extrausers]]></install>
<commands index="1">
<command><![CDATA[mkdir -p /var/lib/extrausers]]></command>
<command><![CDATA[touch /var/lib/extrausers/passwd]]></command>
@@ -4590,9 +4576,6 @@ aliases: files
]]>
</content>
</file>
<command><![CDATA[/etc/init.d/nscd restart]]></command>
<!-- clear group chache -->
<command><![CDATA[nscd --invalidate=group]]></command>
</daemon>
<!-- Logrotate -->
<daemon name="logrotate" title="Logrotate">

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<froxlor>
<distribution name="Ubuntu" codename="Trusty"
version="14.04" defaulteditor="/usr/bin/nano">
version="14.04" defaulteditor="/usr/bin/nano" deprecated="true">
<services>
<!-- HTTP -->
<service type="http" title="{{lng.admin.configfiles.http}}">
@@ -502,7 +502,7 @@ user = <SQL_UNPRIVILEGED_USER>
password = <SQL_UNPRIVILEGED_PASSWORD>
dbname = <SQL_DB>
hosts = <SQL_HOST>
query = SELECT destination FROM mail_virtual WHERE email = '%s' AND trim(destination) <> ''
query = SELECT destination FROM mail_virtual AS v, panel_customers AS c WHERE c.customerid = v.customerid AND c.deactivated = 0 AND v.email = '%s' AND trim(v.destination) <> ''
]]>
</content>
</file>
@@ -1546,21 +1546,7 @@ UPLOADGID=
<!-- Cronjob -->
<daemon name="cron" title="Cronjob for froxlor"
mandatory="true">
<file name="/etc/cron.d/froxlor" chown="root:0" chmod="0640">
<content><![CDATA[
#
# Set PATH, otherwise restart-scripts won't find start-stop-daemon
#
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
#
# Regular cron jobs for the froxlor package
#
# Please check that all following paths are correct
#
*/5 * * * * root /usr/bin/nice -n 5 /usr/bin/php -q <BASE_PATH>scripts/froxlor_master_cronjob.php
]]>
</content>
</file>
<command><![CDATA[/usr/bin/php <BASE_PATH>scripts/froxlor_master_cronjob.php --run-task 99]]></command>
<command><![CDATA[{{settings.system.crondreload}}]]></command>
</daemon>
<!-- AWstats -->
@@ -1575,7 +1561,7 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
</daemon>
<!-- libnss-mysql -->
<daemon name="libnss"
title="libnss-mysql (required for FCGID/php-fpm/mpm-itk)">
title="libnss-mysql (alternative to libnss-extrausers, required for FCGID/php-fpm/mpm-itk)">
<install><![CDATA[apt-get install libnss-mysql-bg nscd]]></install>
<file name="/etc/libnss-mysql.cfg" chown="root:root"
chmod="0600" backup="true">
@@ -1671,8 +1657,8 @@ aliases: files
</daemon>
<!-- libnss-extrausers -->
<daemon name="libnssextrausers"
title="libnss-extrausers (alternative to libnss-mysql, required for FCGID/php-fpm/mpm-itk)">
<install><![CDATA[apt-get install nscd libnss-extrausers]]></install>
title="libnss-extrausers (required for FCGID/php-fpm/mpm-itk)">
<install><![CDATA[apt-get install libnss-extrausers]]></install>
<commands index="1">
<command><![CDATA[mkdir -p /var/lib/extrausers]]></command>
<command><![CDATA[touch /var/lib/extrausers/passwd]]></command>
@@ -1704,9 +1690,6 @@ aliases: files
]]>
</content>
</file>
<command><![CDATA[/etc/init.d/nscd restart]]></command>
<!-- clear group chache -->
<command><![CDATA[nscd --invalidate=group]]></command>
</daemon>
<!-- Logrotate -->
<daemon name="logrotate" title="Logrotate">

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<froxlor>
<distribution name="Ubuntu" codename="Xenial"
version="16.04.x" defaulteditor="/bin/nano">
version="16.04" defaulteditor="/bin/nano">
<services>
<!-- HTTP -->
<service type="http" title="{{lng.admin.configfiles.http}}">
@@ -1504,7 +1504,7 @@ user = <SQL_UNPRIVILEGED_USER>
password = <SQL_UNPRIVILEGED_PASSWORD>
dbname = <SQL_DB>
hosts = <SQL_HOST>
query = SELECT destination FROM mail_virtual WHERE email = '%s' AND trim(destination) <> ''
query = SELECT destination FROM mail_virtual AS v, panel_customers AS c WHERE c.customerid = v.customerid AND c.deactivated = 0 AND v.email = '%s' AND trim(v.destination) <> ''
]]>
</content>
</file>
@@ -3746,7 +3746,7 @@ protocol sieve {
# %m - number of messages (before deletion)
# %s - mailbox size in bytes (before deletion)
# %u - old/new UIDL hash. may help finding out if UIDLs changed unexpectedly
#pop3_logout_format = top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
pop3_logout_format = in=%i out=%o top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
# Workarounds for various client bugs:
# outlook-no-nuls:
@@ -4539,21 +4539,7 @@ UPLOADGID=
<!-- Cronjob -->
<daemon name="cron" title="Cronjob for froxlor"
mandatory="true">
<file name="/etc/cron.d/froxlor" chown="root:0" chmod="0640">
<content><![CDATA[
#
# Set PATH, otherwise restart-scripts won't find start-stop-daemon
#
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
#
# Regular cron jobs for the froxlor package
#
# Please check that all following paths are correct
#
*/5 * * * * root /usr/bin/nice -n 5 /usr/bin/php -q <BASE_PATH>scripts/froxlor_master_cronjob.php
]]>
</content>
</file>
<command><![CDATA[/usr/bin/php <BASE_PATH>scripts/froxlor_master_cronjob.php --run-task 99]]></command>
<command><![CDATA[{{settings.system.crondreload}}]]></command>
</daemon>
<!-- AWstats -->
@@ -4568,8 +4554,8 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
</daemon>
<!-- libnss-extrausers -->
<daemon name="libnssextrausers"
title="libnss-extrausers (alternative to libnss-mysql, required for FCGID/php-fpm/mpm-itk)">
<install><![CDATA[apt-get install nscd libnss-extrausers]]></install>
title="libnss-extrausers (required for FCGID/php-fpm/mpm-itk)">
<install><![CDATA[apt-get install libnss-extrausers]]></install>
<commands index="1">
<command><![CDATA[mkdir -p /var/lib/extrausers]]></command>
<command><![CDATA[touch /var/lib/extrausers/passwd]]></command>
@@ -4601,9 +4587,6 @@ aliases: files
]]>
</content>
</file>
<command><![CDATA[/etc/init.d/nscd restart]]></command>
<!-- clear group chache -->
<command><![CDATA[nscd --invalidate=group]]></command>
</daemon>
<!-- Logrotate -->
<daemon name="logrotate" title="Logrotate">

View File

@@ -44,6 +44,21 @@ return array(
'label' => $lng['login']['language'],
'type' => 'select',
'select_var' => $language_options
),
'api_allowed' => array(
'label' => $lng['usersettings']['api_allowed']['title'],
'desc' => $lng['usersettings']['api_allowed']['description'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array(
'1'
),
'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
)
)
),

View File

@@ -59,6 +59,21 @@ return array(
'type' => 'select',
'select_var' => $language_options,
'visible' => ($result['adminid'] == $userinfo['userid'] ? false : true)
),
'api_allowed' => array(
'label' => $lng['usersettings']['api_allowed']['title'],
'desc' => $lng['usersettings']['api_allowed']['description'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array(
$result['api_allowed']
),
'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
)
)
),

View File

@@ -81,6 +81,21 @@ return array(
'label' => $lng['login']['language'],
'type' => 'select',
'select_var' => $language_options
),
'api_allowed' => array(
'label' => $lng['usersettings']['api_allowed']['title'],
'desc' => $lng['usersettings']['api_allowed']['description'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array(
'1'
),
'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
)
)
),
@@ -294,9 +309,9 @@ return array(
'values' => $phpconfigs,
'value' => ((int) \Froxlor\Settings::Get('system.mod_fcgid') == 1 ? array(
\Froxlor\Settings::Get('system.mod_fcgid_defaultini')
) : (int) \Froxlor\Settings::Get('phpfpm.enabled') == 1 ? array(
) : ((int) \Froxlor\Settings::Get('phpfpm.enabled') == 1 ? array(
\Froxlor\Settings::Get('phpfpm.defaultini')
) : array()),
) : array())),
'is_array' => 1
),
'perlenabled' => array(

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