Compare commits

...

500 Commits

Author SHA1 Message Date
Michael Kaufmann
f4d9e64804 set version to 0.10.31 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-12-03 15:30:09 +01:00
Michael Kaufmann
149c0935fa fix Domains.update() with correct path and change_serversettings=0; refs #1001
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-27 22:06:29 +01:00
Michael Kaufmann
cb0b537f6c allow settings/updating documentroot (only relative to customer homedirectory) when change_serversettings permission is not granted; fixes #1000
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-27 18:04:36 +01:00
Michael Kaufmann
b54c012579 respect deactivated flag when createstdsubdomain's default falls back to 'true' if the customer has one (prior to deactivating); refs #998
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-15 20:24:55 +01:00
Michael Kaufmann
389d83f5a3 fix behaviour in Customers.update() in case 'createstdsubdomain' is not set when called via API (wrong default); fixes #998
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-15 20:04:01 +01:00
Michael Kaufmann
00771381e8 set correct php-version numbers for installation dependencies-check; fixes #997
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-13 20:20:05 +01:00
Michael Kaufmann
46df429909 set version to 0.10.30 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-05 09:27:58 +01:00
Michael Kaufmann
eb841da007 avoid possible DivisionByZeroError in APCu info page, fixes #995
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-04 07:44:03 +01:00
Michael Kaufmann
c4a2db03be enable bind for testing-scenarios explicitly
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-03 14:16:21 +01:00
Michael Kaufmann
e5838f00cf add quota-plugin parameters to dovecot-config-templates; update standardcustomer index.html; set nameserver disabled by default
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-11-03 14:08:57 +01:00
Michael Kaufmann
bcde7e93df check whether the domain to clean from pdns actually still exists there; fixes #992
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-21 12:00:36 +02:00
Michael Kaufmann
bd8327afbe soften/correct permissions on pdns configs; fixes #991
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-21 11:56:34 +02:00
Michael Kaufmann
b961eba382 fix api documentation for Domains.add() and Domains.update(); fixes #987
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-20 16:51:16 +02:00
Michael Kaufmann
a552ea878e avoid undefined index of 'wwwserveralias' field if issueing/renewing lets encrypt certificate for froxlor-hostname
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-17 11:48:40 +02:00
Michael Kaufmann
4ad2a1da1c add complete list of nameserver-ips and given axfr-servers to allow-axfr-ips list for PowerDNS; fixes #985
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-14 19:07:05 +02:00
Michael Kaufmann
37ae69f07a correct language strings in phpconfig formfield for new setting; refs #980
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-14 17:13:55 +02:00
Michael Kaufmann
9870db2560 add possibility to assign new/edited php-config to all customer accounts; fixes #980
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-14 17:09:29 +02:00
Michael Kaufmann
724a5e172a don't remove 0-value parameter values from bulk-actions
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-12 16:29:04 +02:00
Michael Kaufmann
8e166cb842 adjust debian 11 config templates, fixes #982
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-12 14:25:42 +02:00
Michael Kaufmann
5e281cf486 fix allowed-phpconfigs check in SubDomains.add() and SubDomains.update()
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-11 19:26:13 +02:00
Michael Kaufmann
5d2f44ecd8 only validate custom database name if used at all
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-11 18:59:26 +02:00
Michael Kaufmann
5009c625d8 prep.statement cannot be used for create database query; regex-validate database_name
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-11 18:55:15 +02:00
Michael Kaufmann
eb592340b0 use prepared statement for creating databases to avoid sql injections in custom db-names
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-11 18:33:48 +02:00
Michael Kaufmann
c6f556c8d9 set version to 0.10.29.1 for bugfix release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-10 14:45:17 +02:00
Michael Kaufmann
db1df84ef1 correct db-exists check in installation-process
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-10 14:32:02 +02:00
Michael Kaufmann
52135a1d3a set version to 0.10.29 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-08 08:46:58 +02:00
Michael Kaufmann
7f13bd09da add optional ssl parameters to powerdns-config-template
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-08 08:39:22 +02:00
Nick Ufer
7ccbb37c4e feat: adds mysql tls support (#979) 2021-10-08 08:28:32 +02:00
Michael Kaufmann
7feddf0aec generate unpredictable unique session ids
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-10-02 12:38:17 +02:00
Michael Kaufmann
e73523531a let user decide whether an existing database should be backup'ed and removed when installing froxlor; dont rely on parse_ini_file for OS check; enhance mysqldump so there is no issues with complex passwords and bash-escaping
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-09-24 10:49:57 +02:00
Michael Kaufmann
a47b790e19 actually integrate the new czech language file; refs #976
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-09-04 09:30:44 +02:00
Michael Kaufmann
319eec6124 fix session for 2fa enabled logins
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-27 13:17:05 +02:00
Michael Kaufmann
21983f27b6 secure commonly used filename-variable against url manipulation
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-25 16:36:09 +02:00
Michael Kaufmann
5d375b784d login action always goes to index.php
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-25 16:30:56 +02:00
Michael Kaufmann
4b22470872 set php session security related settings (correctly in every case)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-25 16:21:33 +02:00
Michael Kaufmann
ec1c37aa06 set version to 0.10.28 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-20 09:23:23 +02:00
Nicolas
67351ec3c2 Adding support for PowerDNS-Replication (#974)
Adding support for powerdns-replication
2021-08-19 12:00:09 +02:00
Michael Kaufmann
f1887aaaf2 enable iterate_query in dovecot by default
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-13 09:28:10 +02:00
Michael Kaufmann
afd2d7b5e9 fix dns-validation in Domains.add() and Domains.update() when using Let's Encrypt DNS-check
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-08 11:14:57 +02:00
Michael Kaufmann
c967e585b5 avoid duplicate entries in mysql-access-host setting
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-06 08:11:06 +02:00
Michael Kaufmann
73e364d4ba fix compare of old/new value of aliasdomain when editing a domain as customer to avoid unnecessary regeneration of configfiles
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-04 14:55:22 +02:00
Michael Kaufmann
eb49331b21 remove superfluous inserttask when editing domain as it will be called when there are actually changes to the domain earlier
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-04 14:06:32 +02:00
Michael Kaufmann
0a1a3e023f check dns for lets encrypt when adding/editing domains and via cron; fixes #971
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-04 13:44:13 +02:00
Michael Kaufmann
bef5cedcd0 only add link to customername when editing domain when panel.allow_domain_change_customer is false
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-08-02 16:58:34 +02:00
Stefan Weil
f8e2bc7bff Fix some typos in code (found by codespell) (#970)
Signed-off-by: Stefan Weil <sw@weilnetz.de>
2021-08-01 19:00:33 +02:00
Stefan Weil
09038ac7aa Fix some typos (found by codespell) (#969)
Signed-off-by: Stefan Weil <sw@weilnetz.de>
2021-07-31 09:51:54 +02:00
Michael Kaufmann
4c507232c7 add setting for a custom system group for all customer-users (required libnss-extrausers); fixes #953
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-30 12:16:37 +02:00
Michael Kaufmann
86939a64da add buypass testing/staging ACME endpoint; create CAA entries accordingly if activated; refs #968
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-29 21:24:43 +02:00
Jens Meißner
926ce427fc Add Buypass to the list of ACME providers. (#968) 2021-07-29 21:15:49 +02:00
Michael Kaufmann
53401eebfb integrity check should allow utf8_* charachter sets and not only 'utf8', thx to lod
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-29 21:04:46 +02:00
Michael Kaufmann
bef580929e Update README.md 2021-07-27 08:14:08 +02:00
Michael Kaufmann
c7b7c67ff4 normalize ipv6 addresses to avoid possible comparison problems; fixes #965
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-26 17:53:44 +02:00
Michael Kaufmann
ed42d4e3df try to fix github action...
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-24 20:31:34 +02:00
Michael Kaufmann
69a2ebce36 create user as froxlor would create it for mysql-8.0
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-24 20:29:56 +02:00
Michael Kaufmann
15f08739fa add github action workflow for mysql
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-24 20:17:42 +02:00
nachtgeist
571690c8c5 admin_customers/edit domain: make customer login name a link (#962) 2021-07-23 16:35:31 +02:00
rex2630
b2005d7f29 [WIP] Czech language (#870)
* Update czech.lng.php
2021-07-21 20:41:07 +02:00
Michael Kaufmann
4354598c64 fix unittests
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-21 10:21:58 +02:00
Michael Kaufmann
05d4bdc499 restore behaviour for unittests as 'create stdsubdomain' default was yes in the settings but no for direct API usage
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-21 10:10:18 +02:00
Michael Kaufmann
25c6a37df2 fix wrong variable-name in Customers.delete()
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-21 10:03:20 +02:00
Michael Kaufmann
41a470fe36 added option to disable creation of default subdomain; fixes #960
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-21 09:53:54 +02:00
Michael Kaufmann
8a4aa2a721 fix lng strings
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-20 23:45:57 +02:00
Michael Kaufmann
1d903770fc have more power over theme logo, custom theme logo and uploaded logo; refs #958
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-20 20:35:54 +02:00
Nicolas
934be5a238 Fix SOA-Record (#959) 2021-07-20 19:29:06 +02:00
Michael Kaufmann
5608f0407f correct heredoc indentation in AcmeSh for php-7.1; fixes #957
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-07-20 08:11:32 +02:00
Kai
ce9d8dad7f Feature-request #672 - database name prefixes + custom name (#956)
* Fix makeoption function call

* Update formfield.mysql_add.php

Added database name

* Update formfield.mysql_add.php

* Update formfield.mysql_add.php

* Update Mysqls.php

* Update DbManager.php

* Update formfield.mysql_add.php

* Update german.lng.php

* Update formfield.mysql_add.php

* Update Mysqls.php

* Added field database_name (Feature #672)

* Added Testfunction for customer choosed database name

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

* Fixed mysql api command add
Removed doubled code

* Set settings for customer choosed db name

* Fixed wrong excepted for database name

* Renamed parameter database_name to custom_suffix

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

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-04 17:43:20 +00:00
Michael Kaufmann
bd48fb7328 catch exception of password-complexity check when changing account password; fixes #935
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-04-14 08:59:44 +02:00
Michael Kaufmann
769525bb56 do not touch/chown error/access log if log is disabled, fixes #934
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-04-12 09:42:25 +02:00
Michael Kaufmann
9195fb3c98 additionally sort by length of username for libnss-extrausers passwd file to have the main user as first in result in any case; fixes #933
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-04-12 09:37:36 +02:00
Michael Kaufmann
82922f7aea add new settings for legal-notes; terms-of-use and privacy-policy; fixes #930
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-24 14:36:48 +01:00
Michael Kaufmann
db1a39b6d9 match composePhpOptions() definition everywhere
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-24 13:49:58 +01:00
Michael Kaufmann
7fbbc2ea0b add vhost replacer {FPMSOCKET} for custom vhost configs; fixes #931
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-24 13:46:24 +01:00
Michael Kaufmann
91d4432108 check rr against possible existing CNAME entries, fixes #927
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-15 17:33:30 +01:00
Michael Kaufmann
c8914312aa Refactoring columns from large table to avoid '1118 Row size too large' error
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-11 09:45:52 +01:00
Michael Kaufmann
3fd89c48e8 set version to 0.10.25 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-05 20:27:55 +01:00
Michael Kaufmann
eceb144a77 also trigger removal of domain in powerdns database if used; refs #923
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-04 12:09:03 +01:00
Michael Kaufmann
1d9651b18a trgger acme.sh removal for domains if customers is being deleted; fixes #923
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-04 12:07:20 +01:00
Michael Kaufmann
49db4e60cb escape passwords for email content (new email-account, new ftp-account and new database); fixes #905
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-03 11:25:58 +01:00
Michael Kaufmann
53e8ccbccb added 'deactivated' parameter to EmailAccounts.update() so admins can disable individual email-accounts, will be overridden if customer is deactivatd and re-enabled; fixes #921
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-03 10:59:16 +01:00
Michael Kaufmann
6d8fc215f1 add description field to panel_domains and mail_virtual table, API parameter 'description' for Domains.add()/Domains.update() and Email.add()/Emails.update(); fixes #910
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-03 10:25:42 +01:00
Michael Kaufmann
f94c303cb3 add API parameter 'show_usages' for Customers.listing() and Customers.get() to return number of domains, and diskspaced used split into webspace_used, mailspace_used and dbspace_used; fixes #912
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-03-03 09:50:30 +01:00
Michael Kaufmann
2be1873354 fix frontend issue with displaying correct options in domain listing when using php8, thx to cscholz
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-24 19:56:26 +01:00
Michael Kaufmann
d1d36c32fe Merge pull request #920 from RipClaw2971/patch-1
lowercase domain names for ssl-certificate file check (fallback)
2021-02-24 13:07:26 +01:00
RipClaw2971
3b3527348f Update AcmeSh.php
Renewed certificates are not recognized if the domain is in upper/lower case.
2021-02-24 13:00:31 +01:00
Michael Kaufmann
036d5f0713 Merge pull request #919 from nachtgeist/soa
dns: make mail address of SOA records configurable
2021-02-21 18:27:57 +01:00
Daniel Reichelt
a1b8807b0f dns: make mail address of SOA records configurable 2021-02-21 13:00:30 +01:00
Michael Kaufmann
356a087b6a Merge pull request #918 from nachtgeist/pns
dns: check NS entry to be used as primary NS
2021-02-21 09:14:37 +01:00
Michael Kaufmann
0a77fd7150 Merge pull request #917 from nachtgeist/pw
system: validatePassword(): also quote the delimiter ('/')
2021-02-21 09:13:02 +01:00
Daniel Reichelt
67d67a287f system: validatePassword(): also quote the delimiter ('/')
Quoting the default regex delimiter is required for the password
complexity check to work if '/' had been specified as special character
in Froxlor's account settings.
2021-02-21 02:33:46 +01:00
Daniel Reichelt
1f792466bf dns: check NS entry to be used as primary NS
Don't just blindly use the first custom NS entry for SOA, actually check
if it pertains to the domain in question
2021-02-21 02:33:23 +01:00
Michael Kaufmann
5a6343b47c php8 compatibility, fixes #916
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-16 12:38:01 +01:00
Michael Kaufmann
841c529107 fix check for required firstname/name/company in Customers.update(), fixes #915
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-15 23:26:18 +01:00
Michael Kaufmann
41c3f21f0b list only phpenabled and http-enabled domains in php-configuration overview; fixes #911
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-11 16:16:04 +01:00
Michael Kaufmann
b8c0688ba0 added possibility to use 'in' sql-operation in sql_where parameter for Api-calls; php-8 compat fix in admin_traffic
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-11 12:09:42 +01:00
Michael Kaufmann
24e02e99fb set version to 0.10.24 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-05 15:46:08 +01:00
Michael Kaufmann
97bb7b6227 add filecontent to allowed form-fields to not be escaped
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-05 15:44:49 +01:00
Michael Kaufmann
5ceddc8c65 remove not (yet) used cli script
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-02-05 15:42:38 +01:00
Michael Kaufmann
3a17d03796 add option to specify (optional) fileextension/suffix for generated dkim-private keys; fixes #907
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-20 12:12:41 +01:00
Michael Kaufmann
57ae195930 for percentage calculation always use bytes so we don't compare KiB with GiB or similar
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-18 21:22:29 +01:00
Michael Kaufmann
9b86d576fa do not display usages on dashboard in fixed size-units but dynamically adjusted
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-18 20:49:55 +01:00
Michael Kaufmann
02a12eda13 add missing field 'include_default_vhostconf' to settings table for new installations
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-16 10:50:49 +01:00
Michael Kaufmann
a31da97d66 exclude some formfields from xss-cleaning as it could alter the wanted content
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-13 10:14:51 +01:00
Michael Kaufmann
9f13aa9a12 only pass binding variable for prepared sql statement if variable exists
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-13 08:52:00 +01:00
Michael Kaufmann
2841051649 correctly read in domain's ssl-ips for CAA entries if enabled, fixes #903
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-12 21:08:10 +01:00
Michael Kaufmann
acfbf55d15 Check return of validateFormField() just for non-falsey values and not expect boolean data-type; fixes #904
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-12 19:17:38 +01:00
Michael Kaufmann
5848df28fd Merge pull request #902 from bashgeek/master
Put in trailing slash to /awstats/ location in nginx config
2021-01-12 12:25:22 +01:00
Michael Kaufmann
21925f48c3 set minimum required php-version to 7.1 and recommended php-version to 7.4
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2021-01-06 13:36:35 +01:00
Daniel
17a64c58c2 Put in a trailing "/" for /awstats/ location 2020-12-31 16:01:42 +08:00
Daniel
0ca38cff31 Merge pull request #1 from Froxlor/master
up
2020-12-31 15:59:07 +08:00
Michael Kaufmann
5efc1849b4 fix hide-incompatible-settings feature
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-12-30 17:16:15 +01:00
Michael Kaufmann
f213d666e2 fix typo
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-12-30 16:46:01 +01:00
Michael Kaufmann
78495b6487 update link to perl-fastcgi wiki on nginx.com; added setting to hide incompatible settings (depending on webserver)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-12-30 16:41:26 +01:00
Michael Kaufmann
ab1c76e104 set version to 0.10.23.1 for bugfix release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-12-28 19:48:31 +01:00
Michael Kaufmann
a671223823 corrected too few arguments to function Froxlor\Cron\Traffic\TrafficCron::callAwstatsGetTraffic(); fixes #901
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-12-28 19:43:40 +01:00
Michael Kaufmann
3a99e10296 set version to 0.10.23 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-12-28 11:09:56 +01:00
Michael Kaufmann
38031aaff9 add missing return-code in DomainZones.add which messes up the error handling when using API
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-12-23 13:42:36 +01:00
Michael Kaufmann
65773bce57 automatically set php-fpm default config to php-version that is used for the installation to avoid confusion
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-12-21 17:15:02 +01:00
Michael Kaufmann
ee5de56a94 also validate existence of ssl-key file in vhost generation
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-12-10 09:47:58 +01:00
Michael Kaufmann
aba97df9b2 added date-range parameters for Traffic.listing(), fixes #878
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-12-10 09:44:43 +01:00
Michael Kaufmann
79e670f797 trigger rebuild of cronjobs also if customer email is changed, fixes #896
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-12-10 09:41:35 +01:00
Michael Kaufmann
8670cb6742 Merge pull request #900 from heptalium/master
Protect only private keys and leave certificates world readable.
2020-12-10 09:29:51 +01:00
Michael Kaufmann
bde87950a5 fix optional parameters of phpErrHandler
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-11-27 14:07:01 +01:00
Jens Meißner
aa1d2ab01d Set certificate files explicitly world readable. 2020-11-24 17:38:49 +01:00
Jens Meißner
2a770a93b1 Protect only private keys and leave certificates world readable. 2020-11-23 20:32:24 +01:00
Michael Kaufmann
5b85a1c183 use Validate::validateEmail() also for PHPMailer::ValidateAddress() call
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-11-17 17:31:49 +01:00
Michael Kaufmann
caf8893558 use Validate::validateEmail() instead of pure filter_var
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-11-17 17:18:23 +01:00
Michael Kaufmann
a280461cf6 add unicode flag for filter-validate-email (>=php7.1)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-11-17 10:39:11 +01:00
Michael Kaufmann
455c655580 corrected validation of idn-tld's, fixes #899
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-11-14 11:59:46 +01:00
Michael Kaufmann
ecd707424f change example of dhparams.pem folder so it does not conflict with default ssl-certificates-folder which gets purged by froxlor regulary
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-11-13 13:01:19 +01:00
Michael Kaufmann
60fe330de1 Merge pull request #875 from negrusti/patch-2
Data integrity - remove default values from some columns
2020-11-12 09:01:03 +01:00
Michael Kaufmann
cdb871b82b fix delete_userfiles flag not being passed via webinterface email-address-overview
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-11-12 08:54:52 +01:00
Michael Kaufmann
35c4e3d1b9 set version to 0.10.22 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-11-06 14:47:20 +01:00
Michael Kaufmann
b3f82f0981 remove duplicate AXFR records as nameserver get added automatically in case they have also been added to the axfr list
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-11-01 21:00:27 +01:00
Michael Kaufmann
b1b68364be do not allow setting www as CNAME record if domain has automatic www-Alias enabled, fixes #895
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-31 16:16:05 +01:00
Michael Kaufmann
ea76ce8fcc secure requests; refs #893
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-31 15:57:59 +01:00
Michael Kaufmann
16eca628dd add Unittest for traffic-filtering by customer-name, refs #894
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-31 15:53:07 +01:00
Michael Kaufmann
6bf5eccc24 update dependencies and add voku\AntiXSS
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-31 15:50:16 +01:00
Michael Kaufmann
63d00cd453 forgot to add the language strings to the commit for avoid deletion of (super)admin
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-31 15:48:01 +01:00
Michael Kaufmann
c79cba26f3 avoid deletion of (super)admin with id 1 due to fallbacks in the code using it; fixes #886
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-31 10:02:11 +01:00
Michael Kaufmann
36eb3cc1aa [domainbulk] remove reqiurement for customer-select in webinterface as it is an API-parameter
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-31 09:45:50 +01:00
Michael Kaufmann
15a13a7783 append file-extension for dkim-private-keys as external tools may require it (rspamd e.g.); thx to rseffner for finding this
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-20 15:28:51 +02:00
Michael Kaufmann
816874872d make given documentroot of domain relative to customerroot of no absolute path if given; fixes #892
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-14 16:58:19 +02:00
Michael Kaufmann
0e8449f28d Merge pull request #891 from andlinger/patch-1
Fixed typo in contribution document
2020-10-14 14:26:48 +02:00
Michael Kaufmann
3dcbbb9e7b do not set description to empty value if not passed as parameter as it is optionally; fixes #890
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-14 14:25:23 +02:00
David Andlinger
5ab9e6865d fixed typo 2020-10-14 14:17:37 +02:00
Michael Kaufmann
3a47b2050e fix awstats/webalizer directory protection when using nginx; fixes #888
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-13 20:18:44 +02:00
Michael Kaufmann
907c475361 create quotatallies entry if it not exists, fixes #885; correction in api-doc for Ftps.update ftp_password parameter, fixes #889
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-13 19:52:29 +02:00
Michael Kaufmann
0dfb4bdcdb list dns entries after add/delete action handling so the table of entries always shows the current state withouth reloading the page; fixes #887
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-12 09:50:48 +02:00
Michael Kaufmann
a5dc7b93a2 unify customerid/loginname api-parameter-descriptions; fixes #883
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-05 19:59:02 +02:00
Michael Kaufmann
244d2823a6 Merge pull request #882 from heavygale/patch-3
Fix for notices "Trying to access array offset on value of type bool" in ReportsCron.php
2020-10-03 13:10:40 +02:00
heavygale
2f0251bb19 Fix for "Trying to access array offset on value of type bool"
Proper check for success of query before accessing the result array. This notices occures if there's no custom mail-template for trafficmaxpercent_subject or trafficmaxpercent_mailbody for the required language.
2020-10-03 12:55:14 +02:00
Michael Kaufmann
a37d795ff3 set version to 0.10.21 for maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-02 18:01:53 +02:00
Michael Kaufmann
d9331cca61 check for fallback of ssl-certificate in ips/ports correctly of lets encrypt is used
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-09-18 11:49:26 +02:00
Michael Kaufmann
f169129e27 remove obsolete/unused table
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-09-07 21:53:18 +02:00
Michael Kaufmann
746548492b output traffic values correctly when not using bcmath and kind of fix wrong unit display on mouseover, fixes #425
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-09-07 21:51:24 +02:00
Michael Kaufmann
4ad8b62576 for ssl-fallback-check not only check for empty value but also for existence of certificate, thx to df8oe
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-09-06 14:12:25 +02:00
Michael Kaufmann
1eed3d1166 remove underscore from dkim-selector when creating the certificates too, refs #619
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-08-13 09:04:58 +02:00
Michael Kaufmann
6a32720c9a remove underscore from dkim-selector in the output certificate files too as (old) dkim-filter read the selector from this filename; refs #619
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-08-09 10:54:22 +02:00
Michael Kaufmann
e389ae4bf8 setting version to 0.10.20 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-08-07 19:43:16 +02:00
Michael Kaufmann
970ecb469e use overridden limit_extensions and idle_timeout in vhost config when using fpm and not mod_proxy
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-08-07 17:16:56 +02:00
Grigory Morozov
92b6914610 Update froxlor.sql
Data integrity - under no circumstances the empty string is a valid value for these fields
2020-08-07 21:58:06 +07:00
Michael Kaufmann
7e57352bc0 remove underscore from dkim-selector, refs #619
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-07-30 07:59:22 +02:00
Michael Kaufmann
e3d42a3f62 show current count of results besides total count in listings, fixes #869
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-07-29 08:46:50 +02:00
Michael Kaufmann
456a287621 fix missing query-parameters for IpsAndPorts.listing() when using sql_search
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-07-29 08:36:55 +02:00
Michael Kaufmann
eff630da8d unset any limit as we do not have pagination when showing search-results, refs #869
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-07-29 08:28:04 +02:00
Michael Kaufmann
aa45a0302e fix permanent rebuilding of vhost configs, refs 0af655f106
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-07-29 08:23:49 +02:00
Michael Kaufmann
aa14487995 update jquery library, fixes #872
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-07-28 13:28:47 +02:00
Michael Kaufmann
10b52486b5 ups, forgot to save the file so it's missing a critical return :P
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-07-25 17:28:46 +02:00
Michael Kaufmann
0af655f106 fix permanent rebuilding of vhost configs due to always-true renew check of let's encrypt certificates
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-07-25 17:21:52 +02:00
Michael Kaufmann
665c87cca7 fix index on longtext field which is not working due to unknown length; fixes #868
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-07-25 17:21:13 +02:00
Michael Kaufmann
1c50838d37 Merge pull request #871 from tczaude/master
issue 868 : Add new performance indexes
2020-07-24 20:37:26 +02:00
tczaude
ac5bc78e12 fix showUpdateStep 2020-07-24 19:32:04 +02:00
tczaude
a5e6ef674f issue 868 : Add new performerce indexes 2020-07-24 14:35:55 +02:00
Michael Kaufmann
03bc94e69c insert task to sync certificates for all cases (issue and renew)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-07-07 12:10:40 +02:00
Michael Kaufmann
37176c94a1 set version to 0.10.19 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-07-03 14:12:48 +02:00
Michael Kaufmann
a141c83ad4 do not call strtotime on the validTo_time_t key of cert_data as it already is an UNIX-timestamp, refs #865
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-06-23 20:35:50 +02:00
Michael Kaufmann
7c3ff95d22 check for possible CNAME overrides of A/AAAA record in dns-editor, fixes #864
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-06-23 09:39:00 +02:00
Michael Kaufmann
d653f6842f check for acme.sh upgrade on every run; fix not running --install-cronjob without having an issue command
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-06-21 19:50:46 +02:00
Michael Kaufmann
35a69fbfe0 add missing parmeter customerid for SubDomains.delete() which is required when called as admin; fixes #862
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-06-18 13:05:17 +02:00
Michael Kaufmann
e733701459 trigger removal cronjob of lets encrypt certificate via acme.sh also when domain update removes letsencrypt flag from domain
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-06-17 14:09:26 +02:00
Michael Kaufmann
70677fced2 fix double-adding of _ecc to certificate folder when deleting let's encrypt certificate
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-06-17 12:08:54 +02:00
Michael Kaufmann
daa223ed42 return full domain object on Domains.update() call, fixes #861
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-06-17 09:29:02 +02:00
Michael Kaufmann
0398f4cdba set version to 0.10.18 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-06-12 15:17:09 +02:00
Michael Kaufmann
1a0953e77e fix typo in response status message, fixes #858
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-06-08 11:42:44 +02:00
Michael Kaufmann
490704f8e1 Heredoc/nowdoc with an indented closing marker is not supported in PHP 7.2 or earlier.
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-06-06 20:57:24 +02:00
Michael Kaufmann
2748f1b633 also display error when domain does not resolv to any A or AAAA record in lets-encrypt-dns-validation
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-06-06 15:37:06 +02:00
Michael Kaufmann
8e60c6b201 update api documentation for Ftps.update(), fixes #857
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-06-05 16:23:41 +02:00
Michael Kaufmann
d4716b2376 correct documentation for Customers.add(), fixes #856
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-06-05 15:33:49 +02:00
Michael Kaufmann
2c98fc4c2d fix wrong certificate folder for fallback ceck (ecc/non-ecc)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-06-04 07:42:13 +02:00
Michael Kaufmann
65e1f633ef Merge pull request #855 from daxara/detect_distr
Auto detection in CLI & checks
2020-05-31 20:59:26 +02:00
Ante de Baas
ed4dbba278 also perform checks in Install class 2020-05-31 20:46:27 +02:00
Ante de Baas
1a6082ca91 complete if statement 2020-05-31 20:36:52 +02:00
Ante de Baas
da1d94149a saet defaults and do some checks 2020-05-31 20:34:47 +02:00
Ante de Baas
e7cfceb65d add comment 2020-05-31 20:18:37 +02:00
Ante de Baas
1f48ca4711 autodeterct distribution in CLI 2020-05-31 20:10:07 +02:00
Michael Kaufmann
fe0fb8dd5f fix non-static method called statically in \Froxlor\FileDir
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-05-31 16:38:53 +02:00
Michael Kaufmann
4a5ab7d95d Merge pull request #854 from daxara/detect_distr
fix bugs in dist detection
2020-05-31 16:36:52 +02:00
Ante de Baas
0d44adf265 fix bugs is dist detection 2020-05-31 16:00:50 +02:00
Michael Kaufmann
0b63b4e110 Merge pull request #853 from daxara/centos7
[centos7] proftp requires epel, awstats needs install and awstats cron moved
2020-05-31 15:02:57 +02:00
Michael Kaufmann
ba7e9688c5 Merge pull request #852 from daxara/centos8
Centos8 config updated
2020-05-31 15:02:31 +02:00
Ante de Baas
443ae1df68 proftp requires epel, awstats needs install and awstats cron moved 2020-05-31 14:57:07 +02:00
Ante de Baas
b59aa6f140 undo dnf -y 2020-05-31 14:28:37 +02:00
Ante de Baas
4e9df61fef awstats cron is moved to cron.hourly 2020-05-31 13:15:55 +02:00
Ante de Baas
b350815aa0 install awstats and requirements 2020-05-31 13:11:58 +02:00
Ante de Baas
b672c722b9 no user interaction on package installation 2020-05-31 13:05:52 +02:00
Ante de Baas
db60606cfa proftpd requires epel 2020-05-31 12:52:31 +02:00
Ante de Baas
2524491883 centos8 uses 'dandified yum' 2020-05-31 12:47:28 +02:00
Ante de Baas
de061e7e36 add missing apacheconf_htpasswddir dir 2020-05-31 12:46:33 +02:00
Michael Kaufmann
9ecd182a91 Merge pull request #851 from daxara/master
rename rhel7 to centos7 for consistency
2020-05-31 11:26:12 +02:00
Ante de Baas
a7934bcb7b rename rhel7 to centos7 for consistancy 2020-05-31 11:17:43 +02:00
Michael Kaufmann
9dc2c09da7 Merge pull request #850 from daxara/rhel8
Add CentOS 8 configuration-templates
2020-05-31 09:30:51 +02:00
Michael Kaufmann
b23e4a4d85 Merge pull request #849 from daxara/detect_distr
Detect distribution upon installation and set setting-defaults (if any) for that distribution
2020-05-31 09:29:42 +02:00
Michael Kaufmann
394ec4cd4a fix ecc certificate paths
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-05-31 09:13:22 +02:00
Ante de Baas
6ccfb7efbb remove old code 2020-05-30 10:10:57 +02:00
Ante de Baas
1454d8d40f get defaults from configparser 2020-05-30 10:08:05 +02:00
Ante de Baas
0fde1ce7e9 remove dev comment 2020-05-30 09:15:15 +02:00
Ante de Baas
86155f7a9c use Distribution in german language 2020-05-30 09:11:43 +02:00
Ante de Baas
60578a5d31 rename to CentOS because its most likely to be used 2020-05-29 17:46:38 +02:00
Ante de Baas
7fcacb4637 rename to centos because its most likey to be used 2020-05-29 17:45:37 +02:00
Ante de Baas
fb35fb9a3a read distribution from xml and selection via selectbox 2020-05-29 17:33:48 +02:00
Ante de Baas
6128954231 rename propery to property 2020-05-29 15:54:37 +02:00
Ante de Baas
f4d4490d08 change property tagnames 2020-05-29 15:45:04 +02:00
Ante de Baas
27f0c4eb53 remove distribution names from language files 2020-05-29 15:42:38 +02:00
Ante de Baas
cb1df3a7e0 show failue as nice red message 2020-05-29 15:29:53 +02:00
Ante de Baas
a572ac3914 add rhel8 config file 2020-05-29 15:10:06 +02:00
Ante de Baas
498ff15e98 add redhat defaults 2020-05-29 14:59:48 +02:00
Ante de Baas
022ed1a9a8 add setting defaults per distribution when given 2020-05-29 14:59:40 +02:00
Ante de Baas
814339cc73 Merge branch 'master' into detect_distr 2020-05-29 13:54:36 +02:00
Ante de Baas
0bb48a3cdf fix nginx capitalisation. 2020-05-29 13:45:46 +02:00
Ante de Baas
67d74406bd add os distribution detection 2020-05-29 13:36:31 +02:00
Michael Kaufmann
d73d8da2fd read certificate data folder from acme.sh.env file, fixes #846
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-05-28 20:08:49 +02:00
Michael Kaufmann
3c7bdcb5e0 Merge pull request #847 from Froxlor/dependabot/composer/phpmailer/phpmailer-6.1.6
Bump phpmailer/phpmailer from 6.1.4 to 6.1.6
2020-05-28 10:47:26 +02:00
dependabot[bot]
c6ac73f74f Bump phpmailer/phpmailer from 6.1.4 to 6.1.6
Bumps [phpmailer/phpmailer](https://github.com/PHPMailer/PHPMailer) from 6.1.4 to 6.1.6.
- [Release notes](https://github.com/PHPMailer/PHPMailer/releases)
- [Changelog](https://github.com/PHPMailer/PHPMailer/blob/master/changelog.md)
- [Commits](https://github.com/PHPMailer/PHPMailer/compare/v6.1.4...v6.1.6)

Signed-off-by: dependabot[bot] <support@github.com>
2020-05-27 17:01:04 +00:00
Michael Kaufmann
fdcb294244 Merge pull request #844 from daxara/dns_rhel7
Named DNS for RHEL7
2020-05-25 22:02:40 +02:00
Ante de Baas
8898c7c165 add named dns config 2020-05-25 21:38:58 +02:00
Michael Kaufmann
d4c0acb353 Merge pull request #843 from rubo77/usage
show disk-usage also on unlimited accounts
2020-05-25 09:28:37 +02:00
Ruben Barkow-Kuder
9ea32b69cb show disk-usage also on unlimited accounts
Signed-off-by: Ruben Barkow-Kuder <github@r.z11.de>
2020-05-25 03:14:38 +02:00
Michael Kaufmann
0524c70d2b add config-templates for ubuntu focal (partly tested only for now)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-05-24 12:16:17 +02:00
Michael Kaufmann
6ca7920147 fix missing language files in config-services cli script; set ubuntu xenial deprecated, remove Ubuntu trusty; fix a2dismod command in buster config-template as php7.3 is default
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-05-24 11:55:20 +02:00
Michael Kaufmann
65b2e4efa7 do not check for mariadb.sys user on mariadb-10.4 when testing with travis
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-05-23 21:17:43 +02:00
Michael Kaufmann
7000fd2c30 Merge pull request #841 from rubo77/patch-1
Don't suggest php5 during update as default
2020-05-23 21:16:39 +02:00
Ruben Barkow-Kuder
3b1ff03b33 Don't suggest php5 during update as default 2020-05-23 20:12:27 +02:00
Michael Kaufmann
ffa9205f95 fix sql query to remove duplicates before setting unique key in updater, fixes #840
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-05-18 20:48:56 +02:00
Michael Kaufmann
bc73ed0c75 adjust tls default value to tlsv1.2; refs #839
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-05-18 20:48:04 +02:00
Michael Kaufmann
17fd350d33 Merge pull request #839 from negrusti/patch-2
TLSv1 is deprecated
2020-05-18 20:07:30 +02:00
Grigory Morozov
c2e57dfd60 TLSv1 is deprecated 2020-05-18 05:18:42 +07:00
Michael Kaufmann
50f2047da3 set version to 0.10.17 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-05-15 20:35:25 +02:00
Michael Kaufmann
ecb9470b65 fix including of language-strings in reports-cron, fixes #836
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-05-15 15:16:24 +02:00
Michael Kaufmann
6d90b5ba80 remove leftover GROUP BY from testing
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-05-15 09:56:24 +02:00
Michael Kaufmann
eb3590dc34 add unique-key domainid to domain_ssl_settings table
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-05-15 09:49:53 +02:00
Michael Kaufmann
bddf9b496c enable internal api-call to bypass customer_hide_options check in certain situations where it is needed, fixes #803
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-05-15 09:35:20 +02:00
Michael Kaufmann
edc702dafa check for required min version of php every time (frontend and cron), fixes #833
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-05-08 10:03:01 +02:00
Michael Kaufmann
85dfc1030a Merge pull request #832 from RipClaw2971/bugfix
Certificate file cannot be read to database
2020-05-04 16:11:42 +02:00
Andreas Grundler
c0dd432916 Certificate file cannot be read to database if the domain contains capital letters. 2020-05-04 12:08:20 +02:00
Michael Kaufmann
b3db4dd887 set version to 0.10.16 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-05-01 16:27:23 +02:00
Michael Kaufmann
14413a3e8d try to fix travis irc notifications again
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-04-30 20:10:52 +02:00
Michael Kaufmann
a02a081c6b try to fix travis irc notifications
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-04-30 20:03:54 +02:00
Michael Kaufmann
43070e4808 remove possible trailing slash of apache DocumentRoot diretives as sugggested by the httpd-docs, thx to jonbert
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-04-30 19:49:20 +02:00
Michael Kaufmann
98c636c282 let send-to-alternative-email be optional if no address is given instead of displaying error that the email address is invalid; fixes #829
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-04-30 13:03:19 +02:00
Michael Kaufmann
8dace6eca5 remove special characters from name when generating extrausers file
add froxlor hostname to 2fa-qrcode; refs #814

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-04-28 07:59:37 +02:00
Michael Kaufmann
78fc4f84b2 add optional dns validation for let's encrypt activated domains; fixes #817
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-04-14 10:28:33 +02:00
Michael Kaufmann
9018404faa Double check whether installation of acme.sh worked when not installed yet and do not continue if not; fixes #823
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-04-14 08:10:36 +02:00
Michael Kaufmann
8bdd843bd9 fix renew of froxlors own letsencrypt certificate; fix only variables should be passed by reference in BackupCron; fix possible notice or double inclusion of language file in ReportsCron
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-04-08 09:07:48 +02:00
Michael Kaufmann
0d35f5cb29 restructure acmesh implementation and let acme.sh take care of renewing the certificates itself; fixes #792, fixes #816
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-04-04 18:04:39 +02:00
Michael Kaufmann
6815c1c20b Merge pull request #821 from chrschn/master
Fix renewal of ECC/ECDSA certificates.
2020-03-29 23:52:34 +02:00
Christian Schneider
048e6c13ae Fix renewal of ECC/ECDSA certificates.
The ACME v2 implementation uses separate directoies for ECC and on-ECC
certificates. The renew command for a domain checks if an ECC directory
exists (having a "_ecc" suffix) and refuses the command unless the
"--ecc" flag was specified.

Confusingly, this flag is only required to *renew* an ECC certificate,
but not to issue it.

This fixes https://github.com/Froxlor/Froxlor/issues/820.
2020-03-29 22:36:26 +02:00
Michael Kaufmann
aedb829a74 Merge pull request #819 from HBerni/hberni-p0002
fixed parsing due to changes in dovecots default mail_log_prefix
2020-03-21 17:36:00 +01:00
HBerni
4745581720 fixed parsing due to changes in dovecots default mail_log_prefix
regex supports old and new default format now
(see https://wiki2.dovecot.org/Upgrading/2.3)
2020-03-21 16:39:01 +01:00
Michael Kaufmann
489ccbe07a fix removing ip address if ip is set as system-ipaddress but there are other entries of that ip with a different port
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-03-12 07:01:26 +01:00
Michael Kaufmann
a46e7a3bc4 set correct umask to create user config in installation
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-03-10 07:48:35 +01:00
Michael Kaufmann
a4431e25d3 remove ssl-certificates connected to domains that are being deleted when deleting a customer; fixes #818
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-03-10 07:36:22 +01:00
Michael Kaufmann
1fe9f1e9d6 fix language strings for cron cmdline setting and fallback to php binary if no setting is found
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-03-08 10:30:33 +01:00
Michael Kaufmann
13767df562 set version to 0.10.15 for bugfix release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-03-08 07:39:39 +01:00
Michael Kaufmann
02c5f80854 correct chmod value for userdata.inc.php file to be written on installation; fixes #815
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-03-08 07:35:19 +01:00
Michael Kaufmann
d7550ae58a fix deactivated check in api
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-03-06 22:10:01 +01:00
Michael Kaufmann
cf2c7fa31c deny api access to deactivated users with valid api-key
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-03-06 22:03:41 +01:00
Michael Kaufmann
32b6285589 set version to 0.10.14 for upcoming release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-03-06 20:47:20 +01:00
Michael Kaufmann
7e361274c5 forgot one escapeshellarg() and enhanced security on userdata.inc.php creation when installing
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-03-06 20:44:17 +01:00
Michael Kaufmann
62ce21c9ec secure shell-execution of mysqldump on installation if given database-name exists
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-03-04 19:35:57 +01:00
Michael Kaufmann
6b09720ef8 use unpredictable tmpfile-name in installation if lib/userdata.inc.php cannot be written due to permission
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-03-04 19:34:18 +01:00
Michael Kaufmann
8807ae7dad allow private ip ranges in ips-and-ports as some configurations require that; fixes #802
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-03-02 09:51:44 +01:00
Michael Kaufmann
5f3f208534 remove superfluous comma in sql query which causes invalid sql
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-03-01 09:16:47 +01:00
Michael Kaufmann
f11ceacf89 store ace-string of domain besides idn-converted string to have correct sorting in the frontend; fixes #809
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-02-29 09:50:29 +01:00
Michael Kaufmann
26e43077c2 make customer firstname,name,company and customer-no available for all templates; fixes #808
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-02-29 08:16:55 +01:00
Michael Kaufmann
d6c8b92523 add Froxlor.integrityCheck() API call to externally run integrity/consistency check, fixes #801
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-02-15 07:30:56 +01:00
Michael Kaufmann
03450dcfa2 fix listing of customer email addresses if 'domain' section is hidden via settings, fixes #803
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-02-15 07:25:23 +01:00
Michael Kaufmann
f39aab6f32 disable sslsessiontickets-option in domain-add/edit if globally disabled in the settings
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-02-15 07:11:28 +01:00
Michael Kaufmann
7f999302fa do not require enabled vhost-container for froxlor-vhost to change sslsessiontickets-setting
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-02-14 19:26:06 +01:00
Michael Kaufmann
8294985588 require set password complexity for admins too when resetting password; display correct error message if password complexity is not satisfied
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-02-08 10:03:41 +01:00
Michael Kaufmann
a7653551b2 set version to 0.10.13 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-02-07 16:37:06 +01:00
Michael Kaufmann
734c02e33f update php-fpm defaults; update paths for current stable php-7.3; read froxlor default php.ini from file rather then using phpconfig with id=1; fixes #796
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-31 13:17:49 +01:00
Michael Kaufmann
ace18cb7c9 use correct default-versions for configuration-step to disable mod_php for debian buster and ubuntu bionic
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-31 12:58:04 +01:00
Michael Kaufmann
1270204cd9 fix wrongly initialized resource-usage when re-calculating it; fixes #797
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-31 09:49:29 +01:00
Michael Kaufmann
2831923708 Merge pull request #795 from lpedretti/master
Fixed the case that the spf record is not inserted with it's quotes, and so the condition fails and 2 spf records are inserted in the domain
2020-01-24 16:58:10 +01:00
Leonardo Pedretti
6b1ae648b4 Fixed the case that the spf record is not inserted with it's quotes, and so the condition fails and 2 spf records are inserted in the domain 2020-01-23 11:59:28 -03:00
Michael Kaufmann
6c43f1bc56 fix Domains.update() if called as admin/reseller without change_serversettings privileges, thx to rseffner
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-22 09:14:07 +01:00
Michael Kaufmann
2e273a41b5 fix IpsAndPorts when checking for system.ipaddress in update() and delete()
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-19 10:45:48 +01:00
Michael Kaufmann
2004bbe38d dont access db result arrays directly without checking whether it's false due to an error (php7.4 related)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-19 10:13:28 +01:00
Michael Kaufmann
e44e07784f validate nameserver ip-addresses for binds allow-transfer block; fixes #791
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-19 10:08:06 +01:00
Michael Kaufmann
8d6275e1aa set version to 0.10.12 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-10 17:41:20 +01:00
Michael Kaufmann
f21d4f8770 when not using awstats, disable awstats-related settings; add minor tweaks to unit-tests
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-10 16:44:13 +01:00
Michael Kaufmann
fc97b4d4e9 Merge pull request #786 from patschi/logformat-awstats
Allow configuring awstats LogFormat
2020-01-10 16:32:33 +01:00
Patrik Kernstock
05051309c7 Merge branch 'master' into logformat-awstats 2020-01-09 23:24:26 +00:00
Patrik Kernstock
0f025a6627 Language file update
Signed-off-by: Patrik Kernstock <patrik@kernstock.net>
2020-01-09 23:21:11 +00:00
Michael Kaufmann
f6f5765b54 avoid settig more than one catchall address for one domain in Emails.update(), thx to mrairstone
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-09 14:45:51 +01:00
Michael Kaufmann
ac82aa80d2 correct logfiles_format migration; only needed if setting is non-empty
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-09 14:14:04 +01:00
Michael Kaufmann
57503d9c6e try to touch logfile from settings in order for is_writable to work correctly, thx to rubberduck
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-09 14:10:50 +01:00
Michael Kaufmann
f55ad16d82 Merge pull request #785 from patschi/logformat
Allow using more advanced webserver LogFormat
2020-01-09 09:16:03 +01:00
Patrik Kernstock
ea7834c1d1 Added small notice to lng for awstats LogFormat
Signed-off-by: Patrik Kernstock <patrik@kernstock.net>
2020-01-08 22:08:15 +00:00
Patrik Kernstock
b355711de9 Improvements as suggested by @d00p
Signed-off-by: Patrik Kernstock <patrik@kernstock.net>
2020-01-08 22:08:15 +00:00
Michael Kaufmann
a5287726a4 fix issue in PhpHelper::trimArray() returning an empty array, fixes #751
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-03 23:32:21 +01:00
Patrik Kernstock
b393c7d6e6 Merge branch 'master' into logformat 2020-01-03 22:32:45 +01:00
Michael Kaufmann
dd2782771a set version to 0.10.11 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-03 13:24:31 +01:00
Michael Kaufmann
25d0bbb766 switch from algo26-matthias/idna-covert to our own fork as we cannot update to >2.1 without having a minimum requirement for php-7.2 but we need a few fixes for php-7.4 support later on
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-03 12:48:01 +01:00
Michael Kaufmann
b4dedca3db Update README.md 2020-01-02 13:53:22 +01:00
Patrik Kernstock
09aed61dbf Merge branch 'master' into logformat-awstats 2020-01-02 12:44:35 +01:00
Patrik Kernstock
ca39501530 Fixed awstats_logformat field for new installs
Signed-off-by: Patrik Kernstock <patrik@kernstock.net>
2020-01-02 12:39:25 +01:00
Patrik Kernstock
28fd88e53e Merge branch 'master' into logformat 2020-01-02 12:31:51 +01:00
Michael Kaufmann
e01c2e02fb fix update query for new fpm-custom_config value, refs #783
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-01-02 12:28:48 +01:00
Michael Kaufmann
762bfae61a Merge pull request #783 from patschi/phpfpm-custom-settings
Ability to add custom config to PHPFPM version
2020-01-02 10:19:19 +01:00
Patrik Kernstock
a4d4e16efc Small comment added to escaping double-quote
Signed-off-by: Patrik Kernstock <patrik@kernstock.net>
2019-12-31 22:46:03 +01:00
Patrik Kernstock
7f83ad31f4 Fixed dbversion in SQL/Froxlor.php
Signed-off-by: Patrik Kernstock <patrik@kernstock.net>
2019-12-31 22:30:54 +01:00
Patrik Kernstock
e143ba4577 Allow configuring awstats LogFormat
Signed-off-by: Patrik Kernstock <patrik@kernstock.net>
2019-12-31 22:29:29 +01:00
Patrik Kernstock
6799a56ba1 Allow using more advanced LogFormat
Signed-off-by: Patrik Kernstock <patrik@kernstock.net>
2019-12-31 20:18:52 +01:00
Patrik Kernstock
484fe8acbc Fixed db_DBVERISON in Froxlor.php
Signed-off-by: Patrik Kernstock <patrik@kernstock.net>
2019-12-31 17:22:37 +01:00
Patrik Kernstock
550af5b943 Fixed german lng, fixed db_version in SQL
Signed-off-by: Patrik Kernstock <patrik@kernstock.net>
2019-12-31 17:18:17 +01:00
Patrik Kernstock
7ae59477af New update step, changed order of lang strings
Signed-off-by: Patrik Kernstock <patrik@kernstock.net>
2019-12-31 16:14:26 +01:00
Michael Kaufmann
acefa41806 Merge pull request #781 from patschi/accesslog-logtype
Use logtype for access_log for IPsAndPorts too
2019-12-31 16:01:42 +01:00
Patrik Kernstock
b39c8029cd Merge branch 'master' into phpfpm-custom-settings 2019-12-31 15:51:27 +01:00
Patrik Kernstock
69ff416361 Fixed SQL, minor comments/lng updates
Signed-off-by: Patrik Kernstock <patrik@kernstock.net>
2019-12-31 15:34:46 +01:00
Michael Kaufmann
3eb1718fe0 add option to disable SSL sessiontickets globally for older systems, fixes #784
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-12-31 12:27:35 +01:00
Michael Kaufmann
37c434d4fc testsystem does not listen on socket for mysql
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-12-31 09:29:09 +01:00
Michael Kaufmann
1eb14d7564 update composer-dependencies; add connection-test to Mysqls.update() when changing passwords; validate ssl-certificates to avoid private/public key mismatch and a failed webserver start, fixes #778
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-12-31 09:23:28 +01:00
Michael Kaufmann
1c17df69d2 Merge pull request #782 from patschi/fix-dhparams-indent
Fix dhparam indent
2019-12-31 08:11:40 +01:00
Patrik Kernstock
c61b3b73bd Ability to add custom config to PHPFPM version
Addresses #643

Signed-off-by: Patrik Kernstock <patrik@kernstock.net>
2019-12-31 05:48:36 +01:00
Patrik Kernstock
18c87baec8 Fix dhparam indent 2019-12-31 03:53:12 +01:00
Patrik Kernstock
631b2b59a5 Use logtype for access_log for IPsAndPorts too 2019-12-31 03:51:19 +01:00
Michael Kaufmann
1e0510a43d fix SysLog.delete(), SysLog.listing() and SysLog.listingCount() when called as admin/reseller withouth customers_see_all permission
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-12-21 15:12:51 +01:00
Michael Kaufmann
e62f675c4c apply 'notryfiles', 'writeaccesslog' and 'writeerrorlog' flags to subdomains when editing a domain
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-12-18 08:44:02 +01:00
Michael Kaufmann
fe389ab208 setting version to 0.10.10 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-12-13 16:23:43 +01:00
Michael Kaufmann
63d915804a lowercase domainnames when adding new (sub)domain to avoid issues with certificates on filesystem
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-12-11 20:12:51 +01:00
Michael Kaufmann
466c09137b add new 'ssl-enabled' flag for domains and subdomains so ssl can be deactivated (by a customer too) even if there are ssl-ip/ports assigned; introduce new honorcipherorder and sessiontickets flags for more control over ssl-related settings on a per domain base (admin only); fixes #767 and fixes #769
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-12-10 10:21:35 +01:00
Michael Kaufmann
3a738b7070 fix mysql8 issue with group by and sorting within; fixes #774
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-12-08 10:43:12 +01:00
Michael Kaufmann
5ee9d3064a add new API function Froxlor.generatePassword() to return a random password based on froxlor settings regarding min-length, included characters, etc.; fixes #768
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-12-06 11:51:40 +01:00
Michael Kaufmann
adb5c6734a set version to 0.10.9 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-12-06 10:20:01 +01:00
Michael Kaufmann
7dff46b63e set production Lets Encrypt endpoint as default in settings like the installation does; do nat-sorting only on username-related fields, fixes #765
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-12-05 07:52:11 +01:00
Michael Kaufmann
12883bafd6 check for valid result when reading database usage from information_schema; fixes #766
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-12-04 07:15:28 +01:00
Michael Kaufmann
c2b88200f0 Merge pull request #763 from RipClaw2971/bugfix
SQL error in lib/Froxlor/Api/Commands/Certificates.php
2019-11-29 19:52:13 +01:00
Andreas Grundler
634199780b Bugfix 2019-11-29 19:22:43 +01:00
Michael Kaufmann
e0275840ab set version to 0.10.8 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-29 17:14:02 +01:00
Michael Kaufmann
bae8c86901 fix removing of ssl-ip-relation to domain if no ssl-ip is selected via interface, thx to Patient Nr0
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-27 18:32:27 +01:00
Michael Kaufmann
e8be3ee643 use correct apiendpoint for lets encrypt; pass debug-flag onto acme.sh; fixes #762
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-27 07:42:23 +01:00
Michael Kaufmann
35ecdfa2f5 fix searching for alias-domains by link in customer_domains
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-24 12:52:25 +01:00
Michael Kaufmann
3e4a3ef4b0 fix duplicate domain entries in customer-domain-list when domain has aliases, thx to crazy4chrissi
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-24 11:33:10 +01:00
Michael Kaufmann
cdf02ceab6 set version to 0.10.7 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-22 16:14:13 +01:00
Michael Kaufmann
d24056c925 fix vhost-merging of specialsettings in nginx; fixes #757
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-22 16:12:11 +01:00
Michael Kaufmann
d2852fbd5d add new setting to set default value of domain-edit-setting 'Apply specialsettings to all subdomains' and 'Apply php-config to all subdomains'
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-22 16:10:27 +01:00
Michael Kaufmann
d76ebc7c06 fix sort-ordering parameter for pagination
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-20 13:08:36 +01:00
Michael Kaufmann
4fbaacb159 fix domain listing for admin-domains
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-20 12:20:20 +01:00
Michael Kaufmann
2d43a8714d let's try to fix the mysql-user-create/update issue, fingers crossed; refs #758
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-20 11:06:21 +01:00
Michael Kaufmann
620a22bf3e fix listing of subdomains for customers, fixes #759
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-20 09:33:28 +01:00
Michael Kaufmann
5e01018f30 fix typo in SysLog.delete(), thx to Wolfgang
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-18 14:47:56 +01:00
Michael Kaufmann
c84732a0cd fix issue when adding new database users with already-hashed passwords, refs #758
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-18 10:48:31 +01:00
Michael Kaufmann
dfce1fea3c re-add \Froxlor\UI\Paging as it's still required for api_keys.php because they are not (yet) listable via API
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-17 15:20:46 +01:00
Michael Kaufmann
e6dad6c6d0 Use authentication_string for mysql-5.7 and mysql-8 (not password-field) - let's see what happens
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-17 14:29:37 +01:00
Michael Kaufmann
605d2340d1 first unittest for mysql-users and their password, refs #758
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-17 13:42:35 +01:00
Michael Kaufmann
d5df4dd7a4 set version to 0.10.6 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-15 16:43:36 +01:00
Michael Kaufmann
57497bd03f if no ssl IP/port is selected when editing a domain within the webinterface, set the remove_ssl_ipandport parameter to true to not fallback to defaults
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-15 16:36:14 +01:00
Michael Kaufmann
1a3cc52188 fix parameters defaults for Domains.update() and add new parameter 'remove_ssl_ipandport' to clear ssl ip/port instead of defaulting to the current set value; fixes #756
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-15 15:11:24 +01:00
Michael Kaufmann
21f6874a61 check whether there actually is quota read for a user if newly created, thx again to J-BBB
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-15 12:58:28 +01:00
Michael Kaufmann
b34e66dfd6 fix install-dir replacement in configfiles, thx to J-BBB
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-15 08:02:46 +01:00
Michael Kaufmann
a77f890462 Merge branch 'master' of github.com:Froxlor/Froxlor 2019-11-15 07:20:38 +01:00
Michael Kaufmann
3cc5352c01 implement EmailForwarders.listing(); fixes #754
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-15 07:20:16 +01:00
Michael Kaufmann
d01d470119 Merge pull request #755 from danielrona/patch-1
enabled autofocus for 2fa_code
2019-11-14 12:58:18 +01:00
Daniel
a97ce74cc8 enabled autofocus for 2fa_code 2019-11-14 12:31:29 +01:00
Michael Kaufmann
fe7bfcc7c2 fix update of hosting plans via interface; fixes #753
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-13 15:28:08 +01:00
Michael Kaufmann
cff0ac72d0 optimize varchar fields in admin/customer table; fixes #752
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-13 08:57:53 +01:00
Michael Kaufmann
e8dcb29b69 keep searching code in ssl_certificates if something was searched and no results were returned, thx to Ithariel
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-12 12:53:38 +01:00
Michael Kaufmann
2b3b68efa3 remove testing code
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-12 08:17:54 +01:00
Michael Kaufmann
d937029bf7 implement [ApiModule].listing() in frontend-module as sorting/limiting/searching is now possible via API call (partly untested)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-10 18:35:32 +01:00
Michael Kaufmann
1955b5dd32 add task to remove certificate from acme.sh when removed in froxlor; fix issue when mode of certificate generation was not reset to 'issue' and kept trying to 'renew' instead
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-10 18:34:02 +01:00
Michael Kaufmann
c2a9880616 add new Api-Module 'SysLog' to query froxlor logs; set default value for api_allowed to the value of api.enabled setting when adding new customer via frontend to behave like Customers.add() API method
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-09 11:37:45 +01:00
Michael Kaufmann
dfedc478f7 check for given customer loginname/id before anything happens in Mysqls.add/update/delete when called as admin; fixes #749
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-07 15:53:30 +01:00
Michael Kaufmann
6efe500cee validate that the admin/reseller has customers in SubDomains.listing(); return all domain fields for admins/resellers in SubDomains.listing()
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-05 11:21:49 +01:00
Michael Kaufmann
9c3549c604 lowercase domain-names in AcmeSh implementation to avoid https://github.com/Neilpang/acme.sh/issues/2556
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-04 11:39:06 +01:00
Michael Kaufmann
50755f4399 set phpunit to fixed 8.4.1 in favor of https://github.com/sebastianbergmann/phpunit/issues/3793 to not break jenkins testing for now
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-02 13:26:38 +01:00
Michael Kaufmann
ef11ad8da7 fix broke count sql-queries
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-02 11:12:49 +01:00
Michael Kaufmann
1b2c186c07 introduce search, limit, offset and orderby possibilities for (almost) all API listing() functions; added listingCount() function in preparation to replace the old UI\Paging class later on
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-02 10:58:52 +01:00
Michael Kaufmann
b162324ff0 fix renew-check of let's encrypt implementation, set version to 0.10.5 for bugfix release; fixes #747
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2019-11-01 14:19:06 +01:00
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
Pascal
836b6f2fdb Merge remote-tracking branch 'upstream/master' 2019-05-10 02:54:33 +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
254 changed files with 20859 additions and 6062 deletions

View File

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

View File

@@ -48,7 +48,7 @@ strings in
### New settings and database-layout changnes ### New settings and database-layout changes
If you add new settings or layout changes, please make sure you add these to If you add new settings or layout changes, please make sure you add these to
* `install/froxlor.sql` * `install/froxlor.sql`

1
.github/FUNDING.yml vendored
View File

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

View File

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

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

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

View File

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

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

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

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

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

3
.gitignore vendored
View File

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

View File

@@ -52,13 +52,10 @@ install:
- mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI froxlor010 < install/froxlor.sql - mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI froxlor010 < install/froxlor.sql
script: script:
- ant phpunit - ant phpunit-no-coverage
after_success:
- bash <(curl -s https://codecov.io/bash) -f "build/logs/clover.xml"
notifications: notifications:
irc: "irc.freenode.org#froxlor" irc: "irc.libera.chat#froxlor"
webhooks: webhooks:
urls: urls:
- https://webhooks.gitter.im/e/bdf91d1c3f745e51f796 - https://webhooks.gitter.im/e/bdf91d1c3f745e51f796

View File

@@ -38,7 +38,7 @@ if (AREA == 'admin') {
} }
$success_message = ""; $success_message = "";
$tfa = new \Froxlor\FroxlorTwoFactorAuth('Froxlor'); $tfa = new \Froxlor\FroxlorTwoFactorAuth('Froxlor ' . Settings::Get('system.hostname'));
// do the delete and then just show a success-message // do the delete and then just show a success-message
if ($action == 'delete') { if ($action == 'delete') {

View File

@@ -1,4 +1,5 @@
[![Build Status](https://travis-ci.com/Froxlor/Froxlor.svg?branch=master)](https://travis-ci.com/Froxlor/Froxlor) [![Froxlor-CI](https://github.com/Froxlor/Froxlor/actions/workflows/build-mariadb.yml/badge.svg?branch=master)](https://github.com/Froxlor/Froxlor/actions/workflows/build-mariadb.yml)
[![Froxlor-CI](https://github.com/Froxlor/Froxlor/actions/workflows/build-mysql.yml/badge.svg?branch=master)](https://github.com/Froxlor/Froxlor/actions/workflows/build-mysql.yml)
[![Gitter](https://badges.gitter.im/Froxlor/community.svg)](https://gitter.im/Froxlor/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Gitter](https://badges.gitter.im/Froxlor/community.svg)](https://gitter.im/Froxlor/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
# Froxlor # Froxlor
@@ -28,8 +29,8 @@ You may find help in the following places:
### IRC ### IRC
froxlor may be found on freenode.net, channel #froxlor: froxlor may be found on libera.chat, channel #froxlor:
irc://chat.freenode.net/froxlor irc://irc.libera.chat/froxlor
### Forum ### Forum
@@ -53,14 +54,21 @@ https://files.froxlor.org/releases/froxlor-latest.tar.gz [MD5](https://files.fro
[HowTo](https://github.com/Froxlor/Froxlor/wiki/Install-froxlor-on-debian) [HowTo](https://github.com/Froxlor/Froxlor/wiki/Install-froxlor-on-debian)
/etc/apt/sources.list.d/froxlor.list ```
> deb http://debian.froxlor.org {stretch|buster} main apt-get -y install apt-transport-https lsb-release ca-certificates
wget -O - https://deb.froxlor.org/froxlor.gpg | apt-key add -
echo "deb https://deb.froxlor.org/debian $(lsb_release -sc) main" > /etc/apt/sources.list.d/froxlor.list
```
### Gentoo repository ### Ubuntu repository
[HowTo](https://github.com/Froxlor/Froxlor/wiki/Install-froxlor-on-gentoo) [HowTo](https://github.com/Froxlor/Froxlor/wiki/Install-froxlor-on-ubuntu)
https://files.froxlor.org/gentoo/repositories.xml ```
apt-get -y install apt-transport-https lsb-release ca-certificates
wget -O - https://deb.froxlor.org/froxlor.gpg | apt-key add -
echo "deb https://deb.froxlor.org/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/froxlor.list
```
## Contributing ## Contributing

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

View File

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

View File

@@ -253,7 +253,45 @@ return array(
'type' => 'hiddenString', 'type' => 'hiddenString',
'default' => '', 'default' => '',
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField'
) ),
'system_apply_specialsettings_default' => array(
'label' => $lng['serversettings']['apply_specialsettings_default'],
'settinggroup' => 'system',
'varname' => 'apply_specialsettings_default',
'type' => 'bool',
'default' => true,
'save_method' => 'storeSettingField'
),
'system_apply_phpconfigs_default' => array(
'label' => $lng['serversettings']['apply_phpconfigs_default'],
'settinggroup' => 'system',
'varname' => 'apply_phpconfigs_default',
'type' => 'bool',
'default' => true,
'save_method' => 'storeSettingField'
),
'system_domaindefaultalias' => array(
'label' => $lng['admin']['domaindefaultalias'],
'settinggroup' => 'system',
'varname' => 'domaindefaultalias',
'type' => 'option',
'default' => '0',
'option_mode' => 'one',
'option_options' => array(
'0' => $lng['domains']['serveraliasoption_wildcard'],
'1' => $lng['domains']['serveraliasoption_www'],
'2' => $lng['domains']['serveraliasoption_none']
),
'save_method' => 'storeSettingField'
),
'hide_incompatible_settings' => array(
'label' => $lng['serversettings']['hide_incompatible_settings'],
'settinggroup' => 'system',
'varname' => 'hide_incompatible_settings',
'type' => 'bool',
'default' => false,
'save_method' => 'storeSettingField'
),
) )
) )
) )

View File

@@ -105,6 +105,30 @@ return array(
'hasVhostContainerEnabled' 'hasVhostContainerEnabled'
), true) ), true)
), ),
'system_honorcipherorder' => array(
'label' => $lng['admin']['domain_honorcipherorder'],
'settinggroup' => 'system',
'varname' => 'honorcipherorder',
'type' => 'bool',
'default' => false,
'save_method' => 'storeSettingField',
'visible' => \Froxlor\Settings::Get('system.use_ssl') && call_user_func(array(
'\Froxlor\Settings\FroxlorVhostSettings',
'hasVhostContainerEnabled'
), true)
),
'system_sessiontickets' => array(
'label' => $lng['admin']['domain_sessiontickets'],
'settinggroup' => 'system',
'varname' => 'sessiontickets',
'type' => 'bool',
'default' => true,
'save_method' => 'storeSettingField',
'visible' => \Froxlor\Settings::Get('system.use_ssl') && call_user_func(array(
'\Froxlor\Settings\FroxlorVhostSettings',
'hasVhostContainerEnabled'
), true)
),
/** /**
* FCGID * FCGID
*/ */

View File

@@ -173,7 +173,8 @@ return array(
'websrv_avail' => array( 'websrv_avail' => array(
'apache2', 'apache2',
'nginx' 'nginx'
) ),
'visible' => \Froxlor\Settings::Get('system.awstats_enabled') == 1
), ),
'system_logfiles_type' => array( 'system_logfiles_type' => array(
'label' => $lng['serversettings']['logfiles_type'], 'label' => $lng['serversettings']['logfiles_type'],
@@ -250,6 +251,23 @@ return array(
'default' => '', 'default' => '',
'save_method' => 'storeSettingField' '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( 'system_apache_globaldiropt' => array(
'label' => $lng['serversettings']['apache_globaldiropt'], 'label' => $lng['serversettings']['apache_globaldiropt'],
'settinggroup' => 'system', 'settinggroup' => 'system',

View File

@@ -35,7 +35,7 @@ return array(
'settinggroup' => 'system', 'settinggroup' => 'system',
'varname' => 'ssl_protocols', 'varname' => 'ssl_protocols',
'type' => 'option', 'type' => 'option',
'default' => 'TLSv1,TLSv1.2', 'default' => 'TLSv1.2',
'option_mode' => 'multiple', 'option_mode' => 'multiple',
'option_options' => array( 'option_options' => array(
'TLSv1' => 'TLSv1', 'TLSv1' => 'TLSv1',
@@ -62,7 +62,7 @@ return array(
'string_emptyallowed' => true, 'string_emptyallowed' => true,
'default' => '', 'default' => '',
'visible' => \Froxlor\Settings::Get('system.webserver') == "apache2" && \Froxlor\Settings::Get('system.apache24') == 1, 'visible' => \Froxlor\Settings::Get('system.webserver') == "apache2" && \Froxlor\Settings::Get('system.apache24') == 1,
'save_method' => 'storeSettingField', 'save_method' => 'storeSettingField'
), ),
'system_ssl_cert_file' => array( 'system_ssl_cert_file' => array(
'label' => $lng['serversettings']['ssl']['ssl_cert_file'], 'label' => $lng['serversettings']['ssl']['ssl_cert_file'],
@@ -115,6 +115,15 @@ return array(
'visible' => \Froxlor\Settings::Get('system.webserver') == "apache2" && \Froxlor\Settings::Get('system.apache24') == 1, 'visible' => \Froxlor\Settings::Get('system.webserver') == "apache2" && \Froxlor\Settings::Get('system.apache24') == 1,
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField'
), ),
'system_sessionticketsenabled' => array(
'label' => $lng['admin']['domain_sessionticketsenabled'],
'settinggroup' => 'system',
'varname' => 'sessionticketsenabled',
'type' => 'bool',
'default' => true,
'save_method' => 'storeSettingField',
'visible' => \Froxlor\Settings::Get('system.use_ssl') && (\Froxlor\Settings::Get('system.webserver') == "nginx" || (\Froxlor\Settings::Get('system.webserver') == "apache2" && \Froxlor\Settings::Get('system.apache24') == 1))
),
'system_leenabled' => array( 'system_leenabled' => array(
'label' => $lng['serversettings']['leenabled'], 'label' => $lng['serversettings']['leenabled'],
'settinggroup' => 'system', 'settinggroup' => 'system',
@@ -133,6 +142,9 @@ return array(
'default' => '/etc/apache2/conf-enabled/acme.conf', 'default' => '/etc/apache2/conf-enabled/acme.conf',
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField'
), ),
/**
* currently the only option anyway
*
'system_leapiversion' => array( 'system_leapiversion' => array(
'label' => $lng['serversettings']['leapiversion'], 'label' => $lng['serversettings']['leapiversion'],
'settinggroup' => 'system', 'settinggroup' => 'system',
@@ -141,21 +153,24 @@ return array(
'default' => '2', 'default' => '2',
'option_mode' => 'one', 'option_mode' => 'one',
'option_options' => array( 'option_options' => array(
'1' => 'ACME v1',
'2' => 'ACME v2' '2' => 'ACME v2'
), ),
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField'
), ),
*/
'system_letsencryptca' => array( 'system_letsencryptca' => array(
'label' => $lng['serversettings']['letsencryptca'], 'label' => $lng['serversettings']['letsencryptca'],
'settinggroup' => 'system', 'settinggroup' => 'system',
'varname' => 'letsencryptca', 'varname' => 'letsencryptca',
'type' => 'option', 'type' => 'option',
'default' => 'testing', 'default' => 'letsencrypt',
'option_mode' => 'one', 'option_mode' => 'one',
'option_options' => array( 'option_options' => array(
'testing' => 'https://acme-staging' . (\Froxlor\Settings::Get('system.leapiversion') == '2' ? '-v02' : '') . '.api.letsencrypt.org (Test)', 'letsencrypt_test' => 'Let\'s Encrypt (Test / Staging)',
'production' => 'https://acme-v0' . \Froxlor\Settings::Get('system.leapiversion') . '.api.letsencrypt.org (Live)' 'letsencrypt' => 'Let\'s Encrypt (Live)',
'buypass_test' => 'Buypass (Test / Staging)',
'buypass' => 'Buypass (Live)',
'zerossl' => 'ZeroSSL (Live)'
), ),
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField'
), ),
@@ -206,11 +221,11 @@ return array(
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField'
), ),
'system_disable_le_selfcheck' => array( 'system_disable_le_selfcheck' => array(
'label' => $lng['serversettings']['disable_le_selfcheck'], 'label' => $lng['serversettings']['le_domain_dnscheck'],
'settinggroup' => 'system', 'settinggroup' => 'system',
'varname' => 'disable_le_selfcheck', 'varname' => 'le_domain_dnscheck',
'type' => 'bool', 'type' => 'bool',
'default' => false, 'default' => true,
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField'
) )
) )

View File

@@ -33,7 +33,8 @@ return array(
1 => $lng['admin']['webalizer']['quiet'], 1 => $lng['admin']['webalizer']['quiet'],
2 => $lng['admin']['webalizer']['veryquiet'] 2 => $lng['admin']['webalizer']['veryquiet']
), ),
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField',
'visible' => \Froxlor\Settings::Get('system.awstats_enabled') == 0
), ),
'system_awstats_enabled' => array( 'system_awstats_enabled' => array(
'label' => $lng['serversettings']['awstats_enabled'], 'label' => $lng['serversettings']['awstats_enabled'],
@@ -50,7 +51,8 @@ return array(
'type' => 'string', 'type' => 'string',
'string_type' => 'dir', 'string_type' => 'dir',
'default' => '/usr/bin/', 'default' => '/usr/bin/',
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField',
'visible' => \Froxlor\Settings::Get('system.awstats_enabled') == 1
), ),
'system_awstats_awstatspath' => array( 'system_awstats_awstatspath' => array(
'label' => $lng['serversettings']['awstats_awstatspath'], 'label' => $lng['serversettings']['awstats_awstatspath'],
@@ -59,7 +61,8 @@ return array(
'type' => 'string', 'type' => 'string',
'string_type' => 'dir', 'string_type' => 'dir',
'default' => '/usr/bin/', 'default' => '/usr/bin/',
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField',
'visible' => \Froxlor\Settings::Get('system.awstats_enabled') == 1
), ),
'system_awstats_conf' => array( 'system_awstats_conf' => array(
'label' => $lng['serversettings']['awstats_conf'], 'label' => $lng['serversettings']['awstats_conf'],
@@ -68,7 +71,8 @@ return array(
'type' => 'string', 'type' => 'string',
'string_type' => 'dir', 'string_type' => 'dir',
'default' => '/etc/awstats/', 'default' => '/etc/awstats/',
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField',
'visible' => \Froxlor\Settings::Get('system.awstats_enabled') == 1
), ),
'system_awstats_icons' => array( 'system_awstats_icons' => array(
'label' => $lng['serversettings']['awstats_icons'], 'label' => $lng['serversettings']['awstats_icons'],
@@ -77,7 +81,17 @@ return array(
'type' => 'string', 'type' => 'string',
'string_type' => 'dir', 'string_type' => 'dir',
'default' => '/usr/share/awstats/icon/', 'default' => '/usr/share/awstats/icon/',
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField',
'visible' => \Froxlor\Settings::Get('system.awstats_enabled') == 1
),
'system_awstats_logformat' => array(
'label' => $lng['serversettings']['awstats']['logformat'],
'settinggroup' => 'system',
'varname' => 'awstats_logformat',
'type' => 'string',
'default' => '1',
'save_method' => 'storeSettingField',
'visible' => \Froxlor\Settings::Get('system.awstats_enabled') == 1
) )
) )
) )

View File

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

View File

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

View File

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

View File

@@ -43,23 +43,29 @@ if ($page == 'admins' && $userinfo['change_serversettings'] == '1') {
'traffic_used' => $lng['customer']['traffic'] . ' (' . $lng['panel']['used'] . ')', 'traffic_used' => $lng['customer']['traffic'] . ' (' . $lng['panel']['used'] . ')',
'deactivated' => $lng['admin']['deactivated'] 'deactivated' => $lng['admin']['deactivated']
); );
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_ADMINS, $fields); try {
// get total count
$json_result = Admins::getLocal($userinfo)->listingCount();
$result = json_decode($json_result, true)['data'];
// initialize pagination and filtering
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = Admins::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$admins = ''; $admins = '';
$result_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_ADMINS . "` " . $paging->getSqlWhere(false) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
$numrows_admins = Database::num_rows();
$paging->setEntries($numrows_admins);
$sortcode = $paging->getHtmlSortCode($lng, true); $sortcode = $paging->getHtmlSortCode($lng, true);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng); $searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); $pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$i = 0;
$count = 0; $count = 0;
$dec_places = Settings::Get('panel.decimal_places'); $dec_places = Settings::Get('panel.decimal_places');
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { foreach ($result['list'] as $row) {
if ($paging->checkDisplay($i)) {
$row['traffic_used'] = round($row['traffic_used'] / (1024 * 1024), $dec_places); $row['traffic_used'] = round($row['traffic_used'] / (1024 * 1024), $dec_places);
$row['traffic'] = round($row['traffic'] / (1024 * 1024), $dec_places); $row['traffic'] = round($row['traffic'] / (1024 * 1024), $dec_places);
@@ -100,10 +106,8 @@ if ($page == 'admins' && $userinfo['change_serversettings'] == '1') {
eval("\$admins.=\"" . \Froxlor\UI\Template::getTemplate("admins/admins_admin") . "\";"); eval("\$admins.=\"" . \Froxlor\UI\Template::getTemplate("admins/admins_admin") . "\";");
$count ++; $count ++;
} }
$i ++;
}
$admincount = $numrows_admins; $admincount = $result['count'] . " / " . $paging->getEntries();
eval("echo \"" . \Froxlor\UI\Template::getTemplate("admins/admins") . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate("admins/admins") . "\";");
} elseif ($action == 'su') { } elseif ($action == 'su') {
@@ -125,7 +129,7 @@ if ($page == 'admins' && $userinfo['change_serversettings'] == '1') {
'userid' => $userinfo['userid'] 'userid' => $userinfo['userid']
)); ));
$s = md5(uniqid(microtime(), 1)); $s = \Froxlor\Froxlor::genSessionId();
$ins_stmt = Database::prepare(" $ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_SESSIONS . "` SET INSERT INTO `" . TABLE_PANEL_SESSIONS . "` SET
`hash` = :hash, `userid` = :userid, `ipaddress` = :ip, `hash` = :hash, `userid` = :userid, `ipaddress` = :ip,

View File

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

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 // display initial version check
if ($page == 'overview') { if ($page == 'overview') {
@@ -221,5 +230,6 @@ elseif ($page == 'error') {
// 7 = local archive does not exist // 7 = local archive does not exist
// 8 = could not extract archive // 8 = could not extract archive
// 9 = checksum mismatch // 9 = checksum mismatch
// 10 = <php-7.0
\Froxlor\UI\Response::standard_error('autoupdate_' . $errno); \Froxlor\UI\Response::standard_error('autoupdate_' . $errno);
} }

View File

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

View File

@@ -17,8 +17,7 @@
define('AREA', 'admin'); define('AREA', 'admin');
require './lib/init.php'; require './lib/init.php';
use Froxlor\Database\Database; use Froxlor\Api\Commands\Cronjobs;
use Froxlor\Api\Commands\Cronjobs as Cronjobs;
if (isset($_POST['id'])) { if (isset($_POST['id'])) {
$id = intval($_POST['id']); $id = intval($_POST['id']);
@@ -31,47 +30,49 @@ if ($page == 'cronjobs' || $page == 'overview') {
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'viewed admin_cronjobs'); $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'viewed admin_cronjobs');
$fields = array( $fields = array(
'c.module' => 'Module',
'c.lastrun' => $lng['cron']['lastrun'], 'c.lastrun' => $lng['cron']['lastrun'],
'c.interval' => $lng['cron']['interval'], 'c.interval' => $lng['cron']['interval'],
'c.isactive' => $lng['cron']['isactive'] 'c.isactive' => $lng['cron']['isactive']
); );
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_CRONRUNS, $fields); try {
// get total count
$json_result = Cronjobs::getLocal($userinfo)->listingCount();
$result = json_decode($json_result, true)['data'];
// initialize pagination and filtering
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = Cronjobs::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$crons = ''; $crons = '';
$result_stmt = Database::prepare("SELECT `c`.* FROM `" . TABLE_PANEL_CRONRUNS . "` `c` ORDER BY `module` ASC, `cronfile` ASC");
Database::pexecute($result_stmt);
$paging->setEntries(Database::num_rows());
$sortcode = $paging->getHtmlSortCode($lng); $sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng); $searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); $pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$i = 0;
$count = 0; $count = 0;
$cmod = ''; $cmod = '';
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { foreach ($result['list'] as $row) {
if ($cmod != $row['module']) { if ($cmod != $row['module']) {
$_mod = explode("/", $row['module']); $_mod = explode("/", $row['module']);
$module = ucfirst($_mod[1]); $module = ucfirst($_mod[1]);
eval("\$crons.=\"" . \Froxlor\UI\Template::getTemplate('cronjobs/cronjobs_cronjobmodule') . "\";"); eval("\$crons.=\"" . \Froxlor\UI\Template::getTemplate('cronjobs/cronjobs_cronjobmodule') . "\";");
$cmod = $row['module']; $cmod = $row['module'];
} }
if ($paging->checkDisplay($i)) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($row); $row = \Froxlor\PhpHelper::htmlentitiesArray($row);
$row['lastrun'] = date('d.m.Y H:i', $row['lastrun']); $row['lastrun'] = date('d.m.Y H:i', $row['lastrun']);
$row['isactive'] = ((int) $row['isactive'] == 1) ? $lng['panel']['yes'] : $lng['panel']['no']; $row['isactive'] = ((int) $row['isactive'] == 1) ? $lng['panel']['yes'] : $lng['panel']['no'];
$description = $lng['crondesc'][$row['desc_lng_key']]; $description = $lng['crondesc'][$row['desc_lng_key']];
eval("\$crons.=\"" . \Froxlor\UI\Template::getTemplate('cronjobs/cronjobs_cronjob') . "\";"); eval("\$crons.=\"" . \Froxlor\UI\Template::getTemplate('cronjobs/cronjobs_cronjob') . "\";");
$count ++; $count ++;
} }
$i ++;
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate('cronjobs/cronjobs') . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate('cronjobs/cronjobs') . "\";");
} elseif ($action == 'new') { } elseif ($action == 'new') {
/* /*

View File

@@ -35,6 +35,7 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
unset($_SESSION['requestData']); unset($_SESSION['requestData']);
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_customers"); $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_customers");
$fields = array( $fields = array(
'c.loginname' => $lng['login']['username'], 'c.loginname' => $lng['login']['username'],
'a.loginname' => $lng['admin']['admin'], 'a.loginname' => $lng['admin']['admin'],
@@ -47,36 +48,35 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
'c.traffic' => $lng['customer']['traffic'], 'c.traffic' => $lng['customer']['traffic'],
'c.traffic_used' => $lng['customer']['traffic'] . ' (' . $lng['panel']['used'] . ')' 'c.traffic_used' => $lng['customer']['traffic'] . ' (' . $lng['panel']['used'] . ')'
); );
try {
// get total count
$json_result = Customers::getLocal($userinfo)->listingCount();
$result = json_decode($json_result, true)['data'];
// initialize pagination and filtering
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = Customers::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_CUSTOMERS, $fields);
$customers = ''; $customers = '';
$result_stmt = Database::prepare("
SELECT `c`.*, `a`.`loginname` AS `adminname`
FROM `" . TABLE_PANEL_CUSTOMERS . "` `c`, `" . TABLE_PANEL_ADMINS . "` `a`
WHERE " . ($userinfo['customers_see_all'] ? '' : " `c`.`adminid` = :adminid AND ") . "
`c`.`adminid` = `a`.`adminid` " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
Database::pexecute($result_stmt, array(
'adminid' => $userinfo['adminid']
));
$num_rows = Database::num_rows();
$paging->setEntries($num_rows);
$sortcode = $paging->getHtmlSortCode($lng, true); $sortcode = $paging->getHtmlSortCode($lng, true);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng); $searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); $pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$i = 0;
$count = 0; $count = 0;
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { foreach ($result['list'] as $row) {
if ($paging->checkDisplay($i)) {
$domains_stmt = Database::prepare(" $domains_stmt = Database::prepare("
SELECT COUNT(`id`) AS `domains` SELECT COUNT(`id`) AS `domains`
FROM `" . TABLE_PANEL_DOMAINS . "` FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `customerid` = :cid WHERE `customerid` = :cid
AND `parentdomainid` = '0' AND `parentdomainid` = '0'
AND `id`<> :stdd"); AND `id`<> :stdd
");
Database::pexecute($domains_stmt, array( Database::pexecute($domains_stmt, array(
'cid' => $row['customerid'], 'cid' => $row['customerid'],
'stdd' => $row['standardsubdomain'] 'stdd' => $row['standardsubdomain']
@@ -86,13 +86,16 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
$dec_places = Settings::Get('panel.decimal_places'); $dec_places = Settings::Get('panel.decimal_places');
// get disk-space usages for web, mysql and mail // get disk-space usages for web, mysql and mail
$usages_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DISKSPACE . "` WHERE `customerid` = :cid ORDER BY `stamp` DESC LIMIT 1"); $usages_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DISKSPACE . "`
WHERE `customerid` = :cid
ORDER BY `stamp` DESC LIMIT 1
");
$usages = Database::pexecute_first($usages_stmt, array( $usages = Database::pexecute_first($usages_stmt, array(
'cid' => $row['customerid'] 'cid' => $row['customerid']
)); ));
if ($usages) if ($usages) {
{
$row['webspace_used'] = round($usages['webspace'] / 1024, $dec_places); $row['webspace_used'] = round($usages['webspace'] / 1024, $dec_places);
$row['mailspace_used'] = round($usages['mail'] / 1024, $dec_places); $row['mailspace_used'] = round($usages['mail'] / 1024, $dec_places);
$row['dbspace_used'] = round($usages['mysql'] / 1024, $dec_places); $row['dbspace_used'] = round($usages['mysql'] / 1024, $dec_places);
@@ -110,7 +113,6 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
/** /**
* percent-values for progressbar * percent-values for progressbar
*/ */
// For Disk usage
if ($row['diskspace'] > 0) { if ($row['diskspace'] > 0) {
$disk_percent = round(($row['diskspace_used'] * 100) / $row['diskspace'], 0); $disk_percent = round(($row['diskspace_used'] * 100) / $row['diskspace'], 0);
$disk_doublepercent = round($disk_percent * 2, 2); $disk_doublepercent = round($disk_percent * 2, 2);
@@ -118,7 +120,6 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
$disk_percent = 0; $disk_percent = 0;
$disk_doublepercent = 0; $disk_doublepercent = 0;
} }
if ($row['traffic'] > 0) { if ($row['traffic'] > 0) {
$traffic_percent = round(($row['traffic_used'] * 100) / $row['traffic'], 0); $traffic_percent = round(($row['traffic_used'] * 100) / $row['traffic'], 0);
$traffic_doublepercent = round($traffic_percent * 2, 2); $traffic_doublepercent = round($traffic_percent * 2, 2);
@@ -149,10 +150,7 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
$count ++; $count ++;
} }
$i ++; $customercount = $result['count'] . " / " . $paging->getEntries();
}
$customercount = $num_rows;
eval("echo \"" . \Froxlor\UI\Template::getTemplate("customers/customers") . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate("customers/customers") . "\";");
} elseif ($action == 'su' && $id != 0) { } elseif ($action == 'su' && $id != 0) {
try { try {
@@ -180,7 +178,7 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
'hash' => $s 'hash' => $s
)); ));
$s = md5(uniqid(microtime(), 1)); $s = \Froxlor\Froxlor::genSessionId();
$insert = Database::prepare(" $insert = Database::prepare("
INSERT INTO `" . TABLE_PANEL_SESSIONS . "` SET INSERT INTO `" . TABLE_PANEL_SESSIONS . "` SET
`hash` = :hash, `hash` = :hash,

View File

@@ -21,6 +21,7 @@ require './lib/init.php';
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\Api\Commands\Customers as Customers;
use Froxlor\Api\Commands\Domains as Domains; use Froxlor\Api\Commands\Domains as Domains;
if (isset($_POST['id'])) { if (isset($_POST['id'])) {
@@ -31,91 +32,55 @@ if (isset($_POST['id'])) {
if ($page == 'domains' || $page == 'overview') { if ($page == 'domains' || $page == 'overview') {
// Let's see how many customers we have // Let's see how many customers we have
$stmt = Database::prepare(" $json_result = Customers::getLocal($userinfo)->listingCount();
SELECT COUNT(`customerid`) as `countcustomers` FROM `" . TABLE_PANEL_CUSTOMERS . "` " . ($userinfo['customers_see_all'] ? '' : " WHERE `adminid` = :adminid")); $countcustomers = json_decode($json_result, true)['data'];
$params = array();
if ($userinfo['customers_see_all'] == '0') {
$params['adminid'] = $userinfo['adminid'];
}
$countcustomers = Database::pexecute_first($stmt, $params);
$countcustomers = (int) $countcustomers['countcustomers'];
if ($action == '') { if ($action == '') {
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_domains"); $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_domains");
$fields = array( $fields = array(
'd.domain' => $lng['domains']['domainname'], 'd.domain_ace' => $lng['domains']['domainname'],
'c.name' => $lng['customer']['name'], 'c.name' => $lng['customer']['name'],
'c.firstname' => $lng['customer']['firstname'], 'c.firstname' => $lng['customer']['firstname'],
'c.company' => $lng['customer']['company'], 'c.company' => $lng['customer']['company'],
'c.loginname' => $lng['login']['username'], 'c.loginname' => $lng['login']['username'],
'd.aliasdomain' => $lng['domains']['aliasdomain'] 'd.aliasdomain' => $lng['domains']['aliasdomain']
); );
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_DOMAINS, $fields); try {
$domains = ""; // get total count
$result_stmt = Database::prepare(" $json_result = Domains::getLocal($userinfo)->listingCount();
SELECT `d`.*, `c`.`loginname`, `c`.`deactivated`, `c`.`name`, `c`.`firstname`, `c`.`company`, `c`.`standardsubdomain`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain` $result = json_decode($json_result, true)['data'];
FROM `" . TABLE_PANEL_DOMAINS . "` `d` // initialize pagination and filtering
LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`) $paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id` // get list
WHERE `d`.`parentdomainid`='0' " . ($userinfo['customers_see_all'] ? '' : " AND `d`.`adminid` = :adminid ") . " " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit()); $json_result = Domains::getLocal($userinfo, $paging->getApiCommandParams())->listing();
$params = array(); } catch (Exception $e) {
if ($userinfo['customers_see_all'] == '0') { \Froxlor\UI\Response::dynamic_error($e->getMessage());
$params['adminid'] = $userinfo['adminid'];
} }
Database::pexecute($result_stmt, $params); $result = json_decode($json_result, true)['data'];
$numrows_domains = Database::num_rows();
$paging->setEntries($numrows_domains); $domains = '';
$sortcode = $paging->getHtmlSortCode($lng); $sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng); $searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); $pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$domain_array = array();
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
formatDomainEntry($row, $idna_convert);
if (! isset($domain_array[$row['domain']])) {
$domain_array[$row['domain']] = $row;
} else {
$domain_array[$row['domain']] = array_merge($row, $domain_array[$row['domain']]);
}
if (isset($row['aliasdomainid']) && $row['aliasdomainid'] != null && isset($row['aliasdomain']) && $row['aliasdomain'] != '') {
if (! isset($domain_array[$row['aliasdomain']])) {
$domain_array[$row['aliasdomain']] = array();
}
$domain_array[$row['aliasdomain']]['domainaliasid'] = $row['id'];
$domain_array[$row['aliasdomain']]['domainalias'] = $row['domain'];
}
}
/**
* We need ksort/krsort here to make sure idna-domains are also sorted correctly
*/
if ($paging->sortfield == 'd.domain' && $paging->sortorder == 'asc') {
ksort($domain_array);
} elseif ($paging->sortfield == 'd.domain' && $paging->sortorder == 'desc') {
krsort($domain_array);
}
$i = 0;
$count = 0; $count = 0;
foreach ($domain_array as $row) { foreach ($result['list'] as $row) {
formatDomainEntry($row, $idna_convert);
if (isset($row['domain']) && $row['domain'] != '' && $paging->checkDisplay($i)) {
$row['customername'] = \Froxlor\User::getCorrectFullUserDetails($row); $row['customername'] = \Froxlor\User::getCorrectFullUserDetails($row);
$row = \Froxlor\PhpHelper::htmlentitiesArray($row); $row = \Froxlor\PhpHelper::htmlentitiesArray($row);
// display a nice list of IP's // display a nice list of IP's if it's not an alias for another domain
if (isset($row['aliasdomainid']) && $row['aliasdomainid'] != null && isset($row['aliasdomain']) && $row['aliasdomain'] != '') {
$row['ipandport'] = sprintf($lng['domains']['isaliasdomainof'], $row['aliasdomain']);
} else {
$row['ipandport'] = str_replace("\n", "<br />", $row['ipandport']); $row['ipandport'] = str_replace("\n", "<br />", $row['ipandport']);
}
eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_domain") . "\";"); eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_domain") . "\";");
$count++; $count++;
} }
$i ++;
}
$domainscount = $numrows_domains; $domainscount = $result['count'] . " / " . $paging->getEntries();
// Display the list // Display the list
eval("echo \"" . \Froxlor\UI\Template::getTemplate("domains/domains") . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate("domains/domains") . "\";");
@@ -325,9 +290,9 @@ if ($page == 'domains' || $page == 'overview') {
// create serveralias options // create serveralias options
$serveraliasoptions = ""; $serveraliasoptions = "";
$serveraliasoptions .= \Froxlor\UI\HTML::makeoption($lng['domains']['serveraliasoption_wildcard'], '0', '0', true, true); $serveraliasoptions .= \Froxlor\UI\HTML::makeoption($lng['domains']['serveraliasoption_wildcard'], '0', Settings::Get('system.domaindefaultalias'), true, true);
$serveraliasoptions .= \Froxlor\UI\HTML::makeoption($lng['domains']['serveraliasoption_www'], '1', '0', true, true); $serveraliasoptions .= \Froxlor\UI\HTML::makeoption($lng['domains']['serveraliasoption_www'], '1', Settings::Get('system.domaindefaultalias'), true, true);
$serveraliasoptions .= \Froxlor\UI\HTML::makeoption($lng['domains']['serveraliasoption_none'], '2', '0', true, true); $serveraliasoptions .= \Froxlor\UI\HTML::makeoption($lng['domains']['serveraliasoption_none'], '2', Settings::Get('system.domaindefaultalias'), true, true);
$subcanemaildomain = \Froxlor\UI\HTML::makeoption($lng['admin']['subcanemaildomain']['never'], '0', '0', true, true); $subcanemaildomain = \Froxlor\UI\HTML::makeoption($lng['admin']['subcanemaildomain']['never'], '0', '0', true, true);
$subcanemaildomain .= \Froxlor\UI\HTML::makeoption($lng['admin']['subcanemaildomain']['choosableno'], '1', '0', true, true); $subcanemaildomain .= \Froxlor\UI\HTML::makeoption($lng['admin']['subcanemaildomain']['choosableno'], '1', '0', true, true);
@@ -416,6 +381,10 @@ if ($page == 'domains' || $page == 'overview') {
if (isset($_POST['send']) && $_POST['send'] == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
// remove ssl ip/ports if set is empty
if (!isset($_POST['ssl_ipandport']) || empty($_POST['ssl_ipandport'])) {
$_POST['remove_ssl_ipandport'] = true;
}
Domains::getLocal($userinfo, $_POST)->update(); Domains::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage()); \Froxlor\UI\Response::dynamic_error($e->getMessage());
@@ -459,7 +428,7 @@ if ($page == 'domains' || $page == 'overview') {
$customer = Database::pexecute_first($customer_stmt, array( $customer = Database::pexecute_first($customer_stmt, array(
'customerid' => $result['customerid'] 'customerid' => $result['customerid']
)); ));
$result['customername'] = \Froxlor\User::getCorrectFullUserDetails($customer) . ' (' . $customer['loginname'] . ')'; $result['customername'] = \Froxlor\User::getCorrectFullUserDetails($customer);
} }
if ($userinfo['customers_see_all'] == '1') { if ($userinfo['customers_see_all'] == '1') {
@@ -625,6 +594,10 @@ if ($page == 'domains' || $page == 'overview') {
} }
$result = \Froxlor\PhpHelper::htmlentitiesArray($result); $result = \Froxlor\PhpHelper::htmlentitiesArray($result);
if (Settings::Get('panel.allow_domain_change_customer') != '1') {
$result['customername'] .= ' (<a href="' . $linker->getLink(array('section' => 'customers', 'page' => 'customers',
'action' => 'su', 'id' => $customer['customerid'])) . '" rel="external">' . $customer['loginname'] . '</a>)';
}
$domain_edit_data = include_once dirname(__FILE__) . '/lib/formfields/admin/domains/formfield.domains_edit.php'; $domain_edit_data = include_once dirname(__FILE__) . '/lib/formfields/admin/domains/formfield.domains_edit.php';
$domain_edit_form = \Froxlor\UI\HtmlForm::genHTMLForm($domain_edit_data); $domain_edit_form = \Froxlor\UI\HtmlForm::genHTMLForm($domain_edit_data);
@@ -647,7 +620,6 @@ if ($page == 'domains' || $page == 'overview') {
if (isset($_POST['send']) && $_POST['send'] == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$customerid = intval($_POST['customerid']);
$separator = \Froxlor\Validate\Validate::validate($_POST['separator'], 'separator'); $separator = \Froxlor\Validate\Validate::validate($_POST['separator'], 'separator');
$offset = (int) \Froxlor\Validate\Validate::validate($_POST['offset'], 'offset', "/[0-9]/i"); $offset = (int) \Froxlor\Validate\Validate::validate($_POST['offset'], 'offset', "/[0-9]/i");
@@ -656,7 +628,7 @@ if ($page == 'domains' || $page == 'overview') {
$result = array(); $result = array();
try { try {
$bulk = new \Froxlor\Bulk\DomainBulkAction($file_name, $customerid); $bulk = new \Froxlor\Bulk\DomainBulkAction($file_name, $userinfo);
$result = $bulk->doImport($separator, $offset); $result = $bulk->doImport($separator, $offset);
} catch (Exception $e) { } catch (Exception $e) {
\Froxlor\UI\Response::standard_error('domain_import_error', $e->getMessage()); \Froxlor\UI\Response::standard_error('domain_import_error', $e->getMessage());
@@ -678,19 +650,6 @@ if ($page == 'domains' || $page == 'overview') {
'page' => 'domains' 'page' => 'domains'
)); ));
} else { } else {
$customers = \Froxlor\UI\HTML::makeoption($lng['panel']['please_choose'], 0, 0, true);
$result_customers_stmt = Database::prepare("
SELECT `customerid`, `loginname`, `name`, `firstname`, `company`
FROM `" . TABLE_PANEL_CUSTOMERS . "` " . ($userinfo['customers_see_all'] ? '' : " WHERE `adminid` = '" . (int) $userinfo['adminid'] . "' ") . " ORDER BY `name` ASC");
$params = array();
if ($userinfo['customers_see_all'] == '0') {
$params['adminid'] = $userinfo['adminid'];
}
Database::pexecute($result_customers_stmt, $params);
while ($row_customer = $result_customers_stmt->fetch(PDO::FETCH_ASSOC)) {
$customers .= \Froxlor\UI\HTML::makeoption(\Froxlor\User::getCorrectFullUserDetails($row_customer) . ' (' . $row_customer['loginname'] . ')', $row_customer['customerid']);
}
$domain_import_data = include_once dirname(__FILE__) . '/lib/formfields/admin/domains/formfield.domains_import.php'; $domain_import_data = include_once dirname(__FILE__) . '/lib/formfields/admin/domains/formfield.domains_import.php';
$domain_import_form = \Froxlor\UI\HtmlForm::genHTMLForm($domain_import_data); $domain_import_form = \Froxlor\UI\HtmlForm::genHTMLForm($domain_import_data);
@@ -717,18 +676,8 @@ function formatDomainEntry(&$row, &$idna_convert)
$row['domain'] = $idna_convert->decode($row['domain']); $row['domain'] = $idna_convert->decode($row['domain']);
$row['aliasdomain'] = $idna_convert->decode($row['aliasdomain']); $row['aliasdomain'] = $idna_convert->decode($row['aliasdomain']);
$resultips_stmt = Database::prepare("
SELECT `ips`.* FROM `" . TABLE_DOMAINTOIP . "` AS `dti`, `" . TABLE_PANEL_IPSANDPORTS . "` AS `ips`
WHERE `dti`.`id_ipandports` = `ips`.`id` AND `dti`.`id_domain` = :domainid
");
Database::pexecute($resultips_stmt, array(
'domainid' => $row['id']
));
$row['ipandport'] = ''; $row['ipandport'] = '';
while ($rowip = $resultips_stmt->fetch(PDO::FETCH_ASSOC)) { foreach ($row['ipsandports'] as $rowip) {
if (filter_var($rowip['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { if (filter_var($rowip['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
$row['ipandport'] .= '[' . $rowip['ip'] . ']:' . $rowip['port'] . "\n"; $row['ipandport'] .= '[' . $rowip['ip'] . ']:' . $rowip['port'] . "\n";
} else { } else {

View File

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

View File

@@ -19,9 +19,8 @@
define('AREA', 'admin'); define('AREA', 'admin');
require './lib/init.php'; require './lib/init.php';
use Froxlor\Database\Database;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\Api\Commands\IpsAndPorts as IpsAndPorts; use Froxlor\Api\Commands\IpsAndPorts;
if (isset($_POST['id'])) { if (isset($_POST['id'])) {
$id = intval($_POST['id']); $id = intval($_POST['id']);
@@ -43,21 +42,27 @@ if ($page == 'ipsandports' || $page == 'overview') {
'ip' => $lng['admin']['ipsandports']['ip'], 'ip' => $lng['admin']['ipsandports']['ip'],
'port' => $lng['admin']['ipsandports']['port'] 'port' => $lng['admin']['ipsandports']['port']
); );
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_IPSANDPORTS, $fields); try {
// get total count
$json_result = IpsAndPorts::getLocal($userinfo)->listingCount();
$result = json_decode($json_result, true)['data'];
// initialize pagination and filtering
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = IpsAndPorts::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$ipsandports = ''; $ipsandports = '';
$result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` " . $paging->getSqlWhere(false) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
Database::pexecute($result_stmt);
$paging->setEntries(Database::num_rows());
$sortcode = $paging->getHtmlSortCode($lng); $sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng); $searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); $pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$i = 0;
$count = 0; $count = 0;
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { foreach ($result['list'] as $row) {
if ($paging->checkDisplay($i)) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($row); $row = \Froxlor\PhpHelper::htmlentitiesArray($row);
if (filter_var($row['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { if (filter_var($row['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
$row['ip'] = '[' . $row['ip'] . ']'; $row['ip'] = '[' . $row['ip'] . ']';
@@ -65,8 +70,6 @@ if ($page == 'ipsandports' || $page == 'overview') {
eval("\$ipsandports.=\"" . \Froxlor\UI\Template::getTemplate("ipsandports/ipsandports_ipandport") . "\";"); eval("\$ipsandports.=\"" . \Froxlor\UI\Template::getTemplate("ipsandports/ipsandports_ipandport") . "\";");
$count ++; $count ++;
} }
$i ++;
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate("ipsandports/ipsandports") . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate("ipsandports/ipsandports") . "\";");
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
try { try {
@@ -157,5 +160,14 @@ if ($page == 'ipsandports' || $page == 'overview') {
eval("echo \"" . \Froxlor\UI\Template::getTemplate("ipsandports/ipsandports_edit") . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate("ipsandports/ipsandports_edit") . "\";");
} }
} }
} elseif ($action == 'jqCheckIP') {
$ip = $_POST['ip'] ?? "";
if ((filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) || filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) && filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE) == false) {
// returns notice if private network detected so we can display it
echo json_encode($lng['admin']['ipsandports']['ipnote']);
} else {
echo 0;
}
exit();
} }
} }

View File

@@ -19,7 +19,7 @@
define('AREA', 'admin'); define('AREA', 'admin');
require './lib/init.php'; require './lib/init.php';
use Froxlor\Database\Database; use Froxlor\Api\Commands\SysLog;
if ($page == 'log' && $userinfo['change_serversettings'] == '1') { if ($page == 'log' && $userinfo['change_serversettings'] == '1') {
if ($action == '') { if ($action == '') {
@@ -29,20 +29,25 @@ if ($page == 'log' && $userinfo['change_serversettings'] == '1') {
'user' => $lng['logger']['user'], 'user' => $lng['logger']['user'],
'text' => $lng['logger']['action'] 'text' => $lng['logger']['action']
); );
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_LOG, $fields, null, null, 0, 'desc', 30); try {
$query = 'SELECT * FROM `' . TABLE_PANEL_LOG . '` ' . $paging->getSqlWhere(false) . ' ' . $paging->getSqlOrderBy(); // get total count
$result_stmt = Database::query($query . ' ' . $paging->getSqlLimit()); $json_result = SysLog::getLocal($userinfo)->listingCount();
$result_cnt_stmt = Database::query($query); $result = json_decode($json_result, true)['data'];
$logs_count = $result_cnt_stmt->rowCount(); // initialize pagination and filtering
$paging->setEntries($logs_count); $paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = SysLog::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$sortcode = $paging->getHtmlSortCode($lng); $sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng); $searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); $pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$clog = array(); $clog = array();
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { foreach ($result['list'] as $row) {
if (! isset($clog[$row['action']]) || ! is_array($clog[$row['action']])) { if (! isset($clog[$row['action']]) || ! is_array($clog[$row['action']])) {
$clog[$row['action']] = array(); $clog[$row['action']] = array();
} }
@@ -55,7 +60,6 @@ if ($page == 'log' && $userinfo['change_serversettings'] == '1') {
ksort($clog); ksort($clog);
} }
$i = 0;
$count = 0; $count = 0;
$log_count = 0; $log_count = 0;
$log = ''; $log = '';
@@ -100,23 +104,20 @@ if ($page == 'log' && $userinfo['change_serversettings'] == '1') {
eval("\$log.=\"" . \Froxlor\UI\Template::getTemplate('logger/logger_log') . "\";"); eval("\$log.=\"" . \Froxlor\UI\Template::getTemplate('logger/logger_log') . "\";");
$count ++; $count ++;
$_action = $action; $_action = $action;
// }
$i ++;
} }
$i ++;
} }
eval("echo \"" . \Froxlor\UI\Template::getTemplate('logger/logger') . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate('logger/logger') . "\";");
} elseif ($action == 'truncate') { } elseif ($action == 'truncate') {
if (isset($_POST['send']) && $_POST['send'] == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$truncatedate = time() - (60 * 10); try {
$trunc_stmt = Database::prepare(" SysLog::getLocal($userinfo, array(
DELETE FROM `" . TABLE_PANEL_LOG . "` WHERE `date` < :trunc"); 'min_to_keep' => 10
Database::pexecute($trunc_stmt, array( ))->delete();
'trunc' => $truncatedate } catch (Exception $e) {
)); \Froxlor\UI\Response::dynamic_error($e->getMessage());
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, 'truncated the system-log (mysql)'); }
\Froxlor\UI\Response::redirectTo($filename, array( \Froxlor\UI\Response::redirectTo($filename, array(
'page' => $page, 'page' => $page,
's' => $s 's' => $s

View File

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

View File

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

View File

@@ -52,7 +52,7 @@ if ($page == 'overview') {
$domains = ""; $domains = "";
$subdomains_count = count($row['subdomains']); $subdomains_count = count($row['subdomains']);
foreach ($row['domains'] as $configdomain) { foreach ($row['domains'] as $configdomain) {
$domains .= $configdomain . "<br>"; $domains .= $idna_convert->decode($configdomain) . "<br>";
} }
$count ++; $count ++;
if ($subdomains_count == 0 && empty($domains)) { if ($subdomains_count == 0 && empty($domains)) {
@@ -81,8 +81,16 @@ if ($page == 'overview') {
)); ));
} else { } else {
if (file_exists(\Froxlor\Froxlor::getInstallDir() . '/templates/misc/php/default.ini.php')) {
require_once \Froxlor\Froxlor::getInstallDir() . '/templates/misc/php/default.ini.php';
$result = [
'phpsettings' => DEFAULT_PHPINI
];
} else {
// use first php-config as fallback
$result_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = 1"); $result_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = 1");
$result = $result_stmt->fetch(PDO::FETCH_ASSOC); $result = $result_stmt->fetch(PDO::FETCH_ASSOC);
}
$fpmconfigs = ''; $fpmconfigs = '';
$configs = Database::query("SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` ORDER BY `description` ASC"); $configs = Database::query("SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` ORDER BY `description` ASC");
@@ -90,9 +98,9 @@ if ($page == 'overview') {
$fpmconfigs .= \Froxlor\UI\HTML::makeoption($row['description'], $row['id'], 1, true, true); $fpmconfigs .= \Froxlor\UI\HTML::makeoption($row['description'], $row['id'], 1, true, true);
} }
$pm_select = \Froxlor\UI\HTML::makeoption('static', 'static', 'static', true, true); $pm_select = \Froxlor\UI\HTML::makeoption('static', 'static', 'dynamic', true, true);
$pm_select .= \Froxlor\UI\HTML::makeoption('dynamic', 'dynamic', 'static', true, true); $pm_select .= \Froxlor\UI\HTML::makeoption('dynamic', 'dynamic', 'dynamic', true, true);
$pm_select .= \Froxlor\UI\HTML::makeoption('ondemand', 'ondemand', 'static', true, true); $pm_select .= \Froxlor\UI\HTML::makeoption('ondemand', 'ondemand', 'dynamic', true, true);
$phpconfig_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/phpconfig/formfield.phpconfig_add.php'; $phpconfig_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/phpconfig/formfield.phpconfig_add.php';
$phpconfig_add_form = \Froxlor\UI\HtmlForm::genHTMLForm($phpconfig_add_data); $phpconfig_add_form = \Froxlor\UI\HtmlForm::genHTMLForm($phpconfig_add_data);
@@ -234,9 +242,9 @@ if ($page == 'overview') {
)); ));
} else { } else {
$pm_select = \Froxlor\UI\HTML::makeoption('static', 'static', 'static', true, true); $pm_select = \Froxlor\UI\HTML::makeoption('static', 'static', 'dynamic', true, true);
$pm_select .= \Froxlor\UI\HTML::makeoption('dynamic', 'dynamic', 'static', true, true); $pm_select .= \Froxlor\UI\HTML::makeoption('dynamic', 'dynamic', 'dynamic', true, true);
$pm_select .= \Froxlor\UI\HTML::makeoption('ondemand', 'ondemand', 'static', true, true); $pm_select .= \Froxlor\UI\HTML::makeoption('ondemand', 'ondemand', 'dynamic', true, true);
$fpmconfig_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/phpconfig/formfield.fpmconfig_add.php'; $fpmconfig_add_data = include_once dirname(__FILE__) . '/lib/formfields/admin/phpconfig/formfield.fpmconfig_add.php';
$fpmconfig_add_form = \Froxlor\UI\HtmlForm::genHTMLForm($fpmconfig_add_data); $fpmconfig_add_form = \Froxlor\UI\HtmlForm::genHTMLForm($fpmconfig_add_data);

View File

@@ -38,34 +38,32 @@ if ($page == '' || $page == 'overview') {
'adminname' => $lng['admin']['admin'], 'adminname' => $lng['admin']['admin'],
'p.ts' => $lng['admin']['plans']['last_update'] 'p.ts' => $lng['admin']['plans']['last_update']
); );
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_PLANS, $fields); try {
// get total count
$json_result = HostingPlans::getLocal($userinfo)->listingCount();
$result = json_decode($json_result, true)['data'];
// initialize pagination and filtering
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = HostingPlans::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$plans = ''; $plans = '';
$result_stmt = Database::prepare("
SELECT p.*, a.loginname as adminname
FROM `" . TABLE_PANEL_PLANS . "` p, `" . TABLE_PANEL_ADMINS . "` a
WHERE " . ($userinfo['customers_see_all'] ? '' : " `p`.`adminid` = :adminid AND ") . "
`p`.`adminid` = `a`.`adminid` " . $paging->getSqlWhere(false) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
Database::pexecute($result_stmt, array(
'adminid' => $userinfo['adminid']
));
$paging->setEntries(Database::num_rows());
$sortcode = $paging->getHtmlSortCode($lng); $sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng); $searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); $pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$i = 0;
$count = 0; $count = 0;
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { foreach ($result['list'] as $row) {
if ($paging->checkDisplay($i)) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($row); $row = \Froxlor\PhpHelper::htmlentitiesArray($row);
$row['ts_format'] = date("d.m.Y H:i", $row['ts']); $row['ts_format'] = date("d.m.Y H:i", $row['ts']);
eval("\$plans.=\"" . \Froxlor\UI\Template::getTemplate("plans/plans_plan") . "\";"); eval("\$plans.=\"" . \Froxlor\UI\Template::getTemplate("plans/plans_plan") . "\";");
$count ++; $count ++;
} }
$i ++;
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate("plans/plans") . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate("plans/plans") . "\";");
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
@@ -191,9 +189,7 @@ if ($page == '' || $page == 'overview') {
if (isset($_POST['send']) && $_POST['send'] == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
HostingPlans::getLocal($userinfo, array( HostingPlans::getLocal($userinfo, $_POST)->update();
'id' => $id
))->update();
} catch (Exception $e) { } catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage()); \Froxlor\UI\Response::dynamic_error($e->getMessage());
} }
@@ -289,6 +285,7 @@ if ($page == '' || $page == 'overview') {
$result['customernumber'] = null; $result['customernumber'] = null;
$result['custom_notes'] = null; $result['custom_notes'] = null;
$result['custom_notes_show'] = null; $result['custom_notes_show'] = null;
$result['api_allowed'] = null;
$hosting_plans = null; $hosting_plans = null;
$admin_select_cnt = null; $admin_select_cnt = null;
$admin_select = null; $admin_select = null;

View File

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

16
api.php
View File

@@ -1,4 +1,6 @@
<?php <?php
use voku\helper\AntiXSS;
require __DIR__ . '/vendor/autoload.php'; require __DIR__ . '/vendor/autoload.php';
require \Froxlor\Froxlor::getInstallDir() . '/lib/tables.inc.php'; require \Froxlor\Froxlor::getInstallDir() . '/lib/tables.inc.php';
@@ -23,15 +25,22 @@ if (empty($request)) {
} }
// decode json request // decode json request
$decoded_request = json_decode(stripslashes($request), true); $decoded_request = json_decode($request, true);
// is it valid? // is it valid?
if (is_null($decoded_request)) { if (is_null($decoded_request)) {
json_response(400, "Invalid JSON"); json_response(400, "Invalid JSON");
} }
/**
* check for xss attempts and clean request
*/
$antiXss = new AntiXSS();
$request = $antiXss->xss_clean($request);
// validate content // validate content
try { try {
$decoded_request = stripcslashes_deep($decoded_request);
$request = \Froxlor\Api\FroxlorRPC::validateRequest($decoded_request); $request = \Froxlor\Api\FroxlorRPC::validateRequest($decoded_request);
// now actually do it // now actually do it
$cls = "\\Froxlor\\Api\\Commands\\" . $request['command']['class']; $cls = "\\Froxlor\\Api\\Commands\\" . $request['command']['class'];
@@ -72,3 +81,8 @@ function json_response($status, $status_message = '', $data = null)
echo $json_response; echo $json_response;
exit(); exit();
} }
function stripcslashes_deep($value)
{
return is_array($value) ? array_map('stripcslashes_deep', $value) : stripcslashes($value);
}

View File

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

View File

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

View File

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

3136
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -42,148 +42,67 @@ if ($page == 'overview') {
if ($action == '') { if ($action == '') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_domains::domains"); $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_domains::domains");
$fields = array( $fields = array(
'd.domain' => $lng['domains']['domainname'] 'd.domain_ace' => $lng['domains']['domainname'],
'd.aliasdomain' => $lng['domains']['aliasdomain']
); );
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_DOMAINS, $fields); try {
$domains_stmt = Database::prepare("SELECT `d`.`id`, `d`.`customerid`, `d`.`domain`, `d`.`documentroot`, `d`.`isbinddomain`, `d`.`isemaildomain`, `d`.`caneditdomain`, `d`.`iswildcarddomain`, `d`.`parentdomainid`, `d`.`letsencrypt`, `d`.`registration_date`, `d`.`termination_date`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain`, `da`.`id` AS `domainaliasid`, `da`.`domain` AS `domainalias` FROM `" . TABLE_PANEL_DOMAINS . "` `d` // get total count
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id` $json_result = SubDomains::getLocal($userinfo)->listingCount();
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id` $result = json_decode($json_result, true)['data'];
WHERE `d`.`customerid`= :customerid // initialize pagination and filtering
AND `d`.`email_only`='0' $paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
AND `d`.`id` <> :standardsubdomain " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit()); // get list
Database::pexecute($domains_stmt, array( $json_result = SubDomains::getLocal($userinfo, $paging->getApiCommandParams())->listing();
"customerid" => $userinfo['customerid'], } catch (Exception $e) {
"standardsubdomain" => $userinfo['standardsubdomain'] \Froxlor\UI\Response::dynamic_error($e->getMessage());
)); }
$paging->setEntries(Database::num_rows()); $result = json_decode($json_result, true)['data'];
$sortcode = $paging->getHtmlSortCode($lng); $sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng); $searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); $pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$domains = ''; $domains = '';
$parentdomains_count = 0; $parentdomains_count = 0;
$domains_count = 0; $domains_count = $paging->getEntries();
$domain_array = array(); $domain_array = array();
while ($row = $domains_stmt->fetch(PDO::FETCH_ASSOC)) { foreach ($result['list'] as $row) {
$row['domain'] = $idna_convert->decode($row['domain']); formatDomainEntry($row, $idna_convert);
$row['aliasdomain'] = $idna_convert->decode($row['aliasdomain']);
$row['domainalias'] = $idna_convert->decode($row['domainalias']);
if ($row['parentdomainid'] == '0' && $row['caneditdomain'] == '1') { if ($row['parentdomainid'] == '0' && $row['caneditdomain'] == '1') {
$parentdomains_count ++; $parentdomains_count ++;
} }
$domain_array[$row['parentdomainname']][] = $row;
/**
* check for set ssl-certs to show different state-icons
*/
// nothing (ssl_global)
$row['domain_hascert'] = 0;
$ssl_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :domainid");
Database::pexecute($ssl_stmt, array(
"domainid" => $row['id']
));
$ssl_result = $ssl_stmt->fetch(PDO::FETCH_ASSOC);
if (is_array($ssl_result) && isset($ssl_result['ssl_cert_file']) && $ssl_result['ssl_cert_file'] != '') {
// own certificate (ssl_customer_green)
$row['domain_hascert'] = 1;
} else {
// check if it's parent has one set (shared)
if ($row['parentdomainid'] != 0) {
$ssl_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :domainid");
Database::pexecute($ssl_stmt, array(
"domainid" => $row['parentdomainid']
));
$ssl_result = $ssl_stmt->fetch(PDO::FETCH_ASSOC);
if (is_array($ssl_result) && isset($ssl_result['ssl_cert_file']) && $ssl_result['ssl_cert_file'] != '') {
// parent has a certificate (ssl_shared)
$row['domain_hascert'] = 2;
}
}
} }
$row['termination_date'] = str_replace("0000-00-00", "", $row['termination_date']); foreach ($domain_array as $parentdomain => $sdomains) {
if ($row['termination_date'] != "") { // PARENTDOMAIN
$cdate = strtotime($row['termination_date'] . " 23:59:59");
$today = time();
if ($cdate < $today) {
$row['termination_css'] = 'domain-expired';
} else {
$row['termination_css'] = 'domain-canceled';
}
}
$domains_count ++;
$domain_array[$row['domain']] = $row;
}
ksort($domain_array);
$domain_id_array = array();
foreach ($domain_array as $sortkey => $row) {
$domain_id_array[$row['id']] = $sortkey;
}
$domain_sort_array = array();
foreach ($domain_array as $sortkey => $row) {
if ($row['parentdomainid'] == 0) {
$domain_sort_array[$sortkey][$sortkey] = $row;
} else {
// when searching and the results are subdomains only, we need to get
// the parent domain to this subdomain
if (! isset($domain_id_array[$row['parentdomainid']])) {
$domain_id_array[$row['parentdomainid']] = "[parent-domain]";
}
$domain_sort_array[$domain_id_array[$row['parentdomainid']]][$sortkey] = $row;
}
}
$domain_array = array();
if ($paging->sortfield == 'd.domain' && $paging->sortorder == 'asc') {
ksort($domain_sort_array);
} elseif ($paging->sortfield == 'd.domain' && $paging->sortorder == 'desc') {
krsort($domain_sort_array);
}
$i = 0;
foreach ($domain_sort_array as $sortkey => $domain_array) {
if ($paging->checkDisplay($i)) {
if (isset($domain_array[$sortkey])) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($domain_array[$sortkey]);
if (Settings::Get('system.awstats_enabled') == '1') { if (Settings::Get('system.awstats_enabled') == '1') {
$statsapp = 'awstats'; $statsapp = 'awstats';
} else { } else {
$statsapp = 'webalizer'; $statsapp = 'webalizer';
} }
$row = [
'domain' => $idna_convert->decode($parentdomain)
];
eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_delimiter") . "\";"); eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_delimiter") . "\";");
}
if ($paging->sortfield == 'd.domain' && $paging->sortorder == 'asc') { foreach ($sdomains as $domain) {
ksort($domain_array); $row = \Froxlor\PhpHelper::htmlentitiesArray($domain);
} elseif ($paging->sortfield == 'd.domain' && $paging->sortorder == 'desc') {
krsort($domain_array);
}
foreach ($domain_array as $row) { // show docroot nicely
if (strpos($row['documentroot'], $userinfo['documentroot']) === 0) { if (strpos($row['documentroot'], $userinfo['documentroot']) === 0) {
$row['documentroot'] = \Froxlor\FileDir::makeCorrectDir(str_replace($userinfo['documentroot'], "/", $row['documentroot'])); $row['documentroot'] = \Froxlor\FileDir::makeCorrectDir(str_replace($userinfo['documentroot'], "/", $row['documentroot']));
} }
// get ssl-ips if activated // get ssl-ips if activated
$show_ssledit = false; $show_ssledit = false;
if (Settings::Get('system.use_ssl') == '1' && \Froxlor\Domain\Domain::domainHasSslIpPort($row['id']) && $row['caneditdomain'] == '1' && $row['letsencrypt'] == 0) { if (Settings::Get('system.use_ssl') == '1' && \Froxlor\Domain\Domain::domainHasSslIpPort($row['id']) && $row['caneditdomain'] == '1' && $row['letsencrypt'] == 0) {
$show_ssledit = true; $show_ssledit = true;
} }
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_domain") . "\";"); eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_domain") . "\";");
} }
} }
$i += count($domain_array);
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate("domains/domainlist") . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate("domains/domainlist") . "\";");
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
try { try {
@@ -459,7 +378,9 @@ if ($page == 'overview') {
} }
$alias_stmt = Database::prepare("SELECT COUNT(`id`) AS count FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `aliasdomain`= :aliasdomain"); $alias_stmt = Database::prepare("SELECT COUNT(`id`) AS count FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `aliasdomain`= :aliasdomain");
$alias_check = Database::pexecute_first($alias_stmt, array("aliasdomain" => $result['id'])); $alias_check = Database::pexecute_first($alias_stmt, array(
"aliasdomain" => $result['id']
));
$alias_check = $alias_check['count']; $alias_check = $alias_check['count'];
$domainip = $result_ipandport['ip']; $domainip = $result_ipandport['ip'];
@@ -547,3 +468,53 @@ if ($page == 'overview') {
require_once __DIR__ . '/logfiles_viewer.php'; require_once __DIR__ . '/logfiles_viewer.php';
} }
function formatDomainEntry(&$row, &$idna_convert)
{
$row['domain'] = $idna_convert->decode($row['domain']);
$row['aliasdomain'] = $idna_convert->decode($row['aliasdomain']);
$row['domainalias'] = $idna_convert->decode($row['domainalias']);
/**
* check for set ssl-certs to show different state-icons
*/
// nothing (ssl_global)
$row['domain_hascert'] = 0;
$ssl_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :domainid");
Database::pexecute($ssl_stmt, array(
"domainid" => $row['id']
));
$ssl_result = $ssl_stmt->fetch(PDO::FETCH_ASSOC);
if (is_array($ssl_result) && isset($ssl_result['ssl_cert_file']) && $ssl_result['ssl_cert_file'] != '') {
// own certificate (ssl_customer_green)
$row['domain_hascert'] = 1;
} else {
// check if it's parent has one set (shared)
if ($row['parentdomainid'] != 0) {
$ssl_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :domainid");
Database::pexecute($ssl_stmt, array(
"domainid" => $row['parentdomainid']
));
$ssl_result = $ssl_stmt->fetch(PDO::FETCH_ASSOC);
if (is_array($ssl_result) && isset($ssl_result['ssl_cert_file']) && $ssl_result['ssl_cert_file'] != '') {
// parent has a certificate (ssl_shared)
$row['domain_hascert'] = 2;
}
}
}
$row['termination_date'] = str_replace("0000-00-00", "", $row['termination_date']);
$row['termination_css'] = "";
if ($row['termination_date'] != "") {
$cdate = strtotime($row['termination_date'] . " 23:59:59");
$today = time();
if ($cdate < $today) {
$row['termination_css'] = 'domain-expired';
} else {
$row['termination_css'] = 'domain-canceled';
}
}
}

View File

@@ -43,27 +43,31 @@ if ($page == 'overview') {
if ($action == '') { if ($action == '') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_email::emails"); $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_email::emails");
$fields = array( $fields = array(
'd.domain' => $lng['domains']['domainname'], 'd.domain_ace' => $lng['domains']['domainname'],
'm.email_full' => $lng['emails']['emailaddress'], 'm.email_full' => $lng['emails']['emailaddress'],
'm.destination' => $lng['emails']['forwarders'] 'm.destination' => $lng['emails']['forwarders']
); );
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_MAIL_VIRTUAL, $fields); try {
$result_stmt = Database::prepare('SELECT `m`.`id`, `m`.`domainid`, `m`.`email`, `m`.`email_full`, `m`.`iscatchall`, `u`.`quota`, `m`.`destination`, `m`.`popaccountid`, `d`.`domain`, `u`.`mboxsize` FROM `' . TABLE_MAIL_VIRTUAL . '` `m` // get total count
LEFT JOIN `' . TABLE_PANEL_DOMAINS . '` `d` ON (`m`.`domainid` = `d`.`id`) $json_result = Emails::getLocal($userinfo)->listingCount();
LEFT JOIN `' . TABLE_MAIL_USERS . '` `u` ON (`m`.`popaccountid` = `u`.`id`) $result = json_decode($json_result, true)['data'];
WHERE `m`.`customerid`= :customerid ' . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit()); // initialize pagination and filtering
Database::pexecute($result_stmt, array( $paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
"customerid" => $userinfo['customerid'] // get list
)); $json_result = Emails::getLocal($userinfo, $paging->getApiCommandParams())->listing();
$emailscount = Database::num_rows(); } catch (Exception $e) {
$paging->setEntries($emailscount); \Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$sortcode = $paging->getHtmlSortCode($lng); $sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng); $searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); $pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$emails = array(); $emails = array();
$emailscount = $paging->getEntries();
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { foreach ($result['list'] as $row) {
if (! isset($emails[$row['domain']]) || ! is_array($emails[$row['domain']])) { if (! isset($emails[$row['domain']]) || ! is_array($emails[$row['domain']])) {
$emails[$row['domain']] = array(); $emails[$row['domain']] = array();
} }
@@ -71,13 +75,12 @@ if ($page == 'overview') {
$emails[$row['domain']][$row['email_full']] = $row; $emails[$row['domain']][$row['email_full']] = $row;
} }
if ($paging->sortfield == 'd.domain' && $paging->sortorder == 'desc') { if ($paging->sortfield == 'd.domain_ace' && $paging->sortorder == 'desc') {
krsort($emails); krsort($emails);
} else { } else {
ksort($emails); ksort($emails);
} }
$i = 0;
$count = 0; $count = 0;
$accounts = ''; $accounts = '';
$emails_count = 0; $emails_count = 0;
@@ -90,7 +93,6 @@ if ($page == 'overview') {
} }
foreach ($emailaddresses as $row) { foreach ($emailaddresses as $row) {
if ($paging->checkDisplay($i)) {
if ($domainname != $idna_convert->decode($row['domain'])) { if ($domainname != $idna_convert->decode($row['domain'])) {
$domainname = $idna_convert->decode($row['domain']); $domainname = $idna_convert->decode($row['domain']);
eval("\$accounts.=\"" . \Froxlor\UI\Template::getTemplate("email/emails_domain") . "\";"); eval("\$accounts.=\"" . \Froxlor\UI\Template::getTemplate("email/emails_domain") . "\";");
@@ -124,19 +126,17 @@ if ($page == 'overview') {
eval("\$accounts.=\"" . \Froxlor\UI\Template::getTemplate("email/emails_email") . "\";"); eval("\$accounts.=\"" . \Froxlor\UI\Template::getTemplate("email/emails_email") . "\";");
$count ++; $count ++;
} }
$i ++;
}
} }
$emaildomains_count_stmt = Database::prepare("SELECT COUNT(`id`) AS `count` FROM `" . TABLE_PANEL_DOMAINS . "` $result_stmt = Database::prepare("
WHERE `customerid`= :customerid SELECT COUNT(`id`) as emaildomains
AND `isemaildomain`='1' ORDER BY `domain` ASC"); FROM `" . TABLE_PANEL_DOMAINS . "`
Database::pexecute($emaildomains_count_stmt, array( WHERE `customerid`= :cid AND `isemaildomain` = '1'
"customerid" => $userinfo['customerid'] ");
$result2 = Database::pexecute_first($result_stmt, array(
"cid" => $userinfo['customerid']
)); ));
$emaildomains_count = $emaildomains_count_stmt->fetch(PDO::FETCH_ASSOC); $emaildomains_count = $result2['emaildomains'];
$emaildomains_count = $emaildomains_count['count'];
eval("echo \"" . \Froxlor\UI\Template::getTemplate("email/emails") . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate("email/emails") . "\";");
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
@@ -153,7 +153,8 @@ if ($page == 'overview') {
if (isset($_POST['send']) && $_POST['send'] == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
Emails::getLocal($userinfo, array( Emails::getLocal($userinfo, array(
'id' => $id 'id' => $id,
'delete_userfiles' => ($_POST['delete_userfiles'] ?? 0)
))->delete(); ))->delete();
} catch (Exception $e) { } catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage()); \Froxlor\UI\Response::dynamic_error($e->getMessage());
@@ -194,7 +195,7 @@ if ($page == 'overview') {
$result_stmt = Database::prepare("SELECT `id`, `domain`, `customerid` FROM `" . TABLE_PANEL_DOMAINS . "` $result_stmt = Database::prepare("SELECT `id`, `domain`, `customerid` FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `customerid`= :cid WHERE `customerid`= :cid
AND `isemaildomain`='1' AND `isemaildomain`='1'
ORDER BY `domain` ASC"); ORDER BY `domain_ace` ASC");
Database::pexecute($result_stmt, array( Database::pexecute($result_stmt, array(
"cid" => $userinfo['customerid'] "cid" => $userinfo['customerid']
)); ));

View File

@@ -19,7 +19,6 @@
define('AREA', 'customer'); define('AREA', 'customer');
require './lib/init.php'; require './lib/init.php';
use Froxlor\Database\Database;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\Api\Commands\DirOptions as DirOptions; use Froxlor\Api\Commands\DirOptions as DirOptions;
use Froxlor\Api\Commands\DirProtections as DirProtections; use Froxlor\Api\Commands\DirProtections as DirProtections;
@@ -52,23 +51,27 @@ if ($page == 'overview') {
'username' => $lng['login']['username'], 'username' => $lng['login']['username'],
'path' => $lng['panel']['path'] 'path' => $lng['panel']['path']
); );
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_HTPASSWDS, $fields); try {
$result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "` // get total count
WHERE `customerid`= :customerid " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit()); $json_result = DirProtections::getLocal($userinfo)->listingCount();
Database::pexecute($result_stmt, array( $result = json_decode($json_result, true)['data'];
"customerid" => $userinfo['customerid'] // initialize pagination and filtering
)); $paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
$paging->setEntries(Database::num_rows()); // get list
$json_result = DirProtections::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$sortcode = $paging->getHtmlSortCode($lng); $sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng); $searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); $pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$i = 0;
$count = 0; $count = 0;
$htpasswds = ''; $htpasswds = '';
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { foreach ($result['list'] as $row) {
if ($paging->checkDisplay($i)) {
if (strpos($row['path'], $userinfo['documentroot']) === 0) { if (strpos($row['path'], $userinfo['documentroot']) === 0) {
$row['path'] = str_replace($userinfo['documentroot'], "/", $row['path']); $row['path'] = str_replace($userinfo['documentroot'], "/", $row['path']);
} }
@@ -78,9 +81,6 @@ if ($page == 'overview') {
$count ++; $count ++;
} }
$i ++;
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate("extras/htpasswds") . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate("extras/htpasswds") . "\";");
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
try { try {
@@ -192,25 +192,29 @@ if ($page == 'overview') {
'error500path' => $lng['extras']['error500path'], 'error500path' => $lng['extras']['error500path'],
'options_cgi' => $lng['extras']['execute_perl'] 'options_cgi' => $lng['extras']['execute_perl']
); );
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_HTACCESS, $fields); try {
$result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTACCESS . "` // get total count
WHERE `customerid`= :customerid " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit()); $json_result = DirOptions::getLocal($userinfo)->listingCount();
Database::pexecute($result_stmt, array( $result = json_decode($json_result, true)['data'];
"customerid" => $userinfo['customerid'] // initialize pagination and filtering
)); $paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
$paging->setEntries(Database::num_rows()); // get list
$json_result = DirOptions::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$sortcode = $paging->getHtmlSortCode($lng); $sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng); $searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); $pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$i = 0;
$count = 0; $count = 0;
$htaccess = ''; $htaccess = '';
$cperlenabled = \Froxlor\Customer\Customer::customerHasPerlEnabled($userinfo['customerid']); $cperlenabled = \Froxlor\Customer\Customer::customerHasPerlEnabled($userinfo['customerid']);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { foreach ($result['list'] as $row) {
if ($paging->checkDisplay($i)) {
if (strpos($row['path'], $userinfo['documentroot']) === 0) { if (strpos($row['path'], $userinfo['documentroot']) === 0) {
$row['path'] = str_replace($userinfo['documentroot'], "/", $row['path']); $row['path'] = str_replace($userinfo['documentroot'], "/", $row['path']);
} }
@@ -224,9 +228,6 @@ if ($page == 'overview') {
$count ++; $count ++;
} }
$i ++;
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate("extras/htaccess") . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate("extras/htaccess") . "\";");
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
try { try {

View File

@@ -46,41 +46,38 @@ if ($page == 'overview') {
'homedir' => $lng['panel']['path'], 'homedir' => $lng['panel']['path'],
'description' => $lng['panel']['ftpdesc'] 'description' => $lng['panel']['ftpdesc']
); );
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_FTP_USERS, $fields); try {
// get total count
$result_stmt = Database::prepare("SELECT `id`, `username`, `description`, `homedir`, `shell` FROM `" . TABLE_FTP_USERS . "` $json_result = Ftps::getLocal($userinfo)->listingCount();
WHERE `customerid`= :customerid " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit()); $result = json_decode($json_result, true)['data'];
Database::pexecute($result_stmt, array( // initialize pagination and filtering
"customerid" => $userinfo['customerid'] $paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
)); // get list
$ftps_count = Database::num_rows(); $json_result = Ftps::getLocal($userinfo, $paging->getApiCommandParams())->listing();
$paging->setEntries($ftps_count); } catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$ftps_count = $paging->getEntries();
$sortcode = $paging->getHtmlSortCode($lng); $sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng); $searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); $pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$i = 0;
$count = 0; $count = 0;
$accounts = ''; $accounts = '';
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { foreach ($result['list'] as $row) {
if ($paging->checkDisplay($i)) {
if (strpos($row['homedir'], $userinfo['documentroot']) === 0) { if (strpos($row['homedir'], $userinfo['documentroot']) === 0) {
$row['documentroot'] = str_replace($userinfo['documentroot'], "/", $row['homedir']); $row['documentroot'] = str_replace($userinfo['documentroot'], "/", $row['homedir']);
} else { } else {
$row['documentroot'] = $row['homedir']; $row['documentroot'] = $row['homedir'];
} }
$row['documentroot'] = \Froxlor\FileDir::makeCorrectDir($row['documentroot']); $row['documentroot'] = \Froxlor\FileDir::makeCorrectDir($row['documentroot']);
$row = \Froxlor\PhpHelper::htmlentitiesArray($row); $row = \Froxlor\PhpHelper::htmlentitiesArray($row);
eval("\$accounts.=\"" . \Froxlor\UI\Template::getTemplate('ftp/accounts_account') . "\";"); eval("\$accounts.=\"" . \Froxlor\UI\Template::getTemplate('ftp/accounts_account') . "\";");
$count ++; $count ++;
} }
$i ++;
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate('ftp/accounts') . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate('ftp/accounts') . "\";");
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
try { try {

View File

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

View File

@@ -19,6 +19,7 @@
define('AREA', 'customer'); define('AREA', 'customer');
require './lib/init.php'; require './lib/init.php';
use Froxlor\Api\Commands\SysLog;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\Settings; use Froxlor\Settings;
@@ -35,26 +36,25 @@ if ($page == 'log') {
'user' => $lng['logger']['user'], 'user' => $lng['logger']['user'],
'text' => $lng['logger']['action'] 'text' => $lng['logger']['action']
); );
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_LOG, $fields, null, null, 0, 'desc', 30); try {
$query = 'SELECT * FROM `' . TABLE_PANEL_LOG . '` WHERE `user` = :loginname ' . $paging->getSqlWhere(true) . ' ' . $paging->getSqlOrderBy(); // get total count
$result_stmt = Database::prepare($query . ' ' . $paging->getSqlLimit()); $json_result = SysLog::getLocal($userinfo)->listingCount();
Database::pexecute($result_stmt, array( $result = json_decode($json_result, true)['data'];
"loginname" => $userinfo['loginname'] // initialize pagination and filtering
)); $paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
$result_cnt_stmt = Database::prepare($query); // get list
Database::pexecute($result_cnt_stmt, array( $json_result = SysLog::getLocal($userinfo, $paging->getApiCommandParams())->listing();
"loginname" => $userinfo['loginname'] } catch (Exception $e) {
)); \Froxlor\UI\Response::dynamic_error($e->getMessage());
$res_cnt = $result_cnt_stmt->fetch(PDO::FETCH_ASSOC); }
$logs_count = $result_cnt_stmt->rowCount(); $result = json_decode($json_result, true)['data'];
$paging->setEntries($logs_count);
$sortcode = $paging->getHtmlSortCode($lng); $sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng); $searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); $pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$clog = array(); $clog = array();
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { foreach ($result['list'] as $row) {
if (! isset($clog[$row['action']]) || ! is_array($clog[$row['action']])) { if (! isset($clog[$row['action']]) || ! is_array($clog[$row['action']])) {
$clog[$row['action']] = array(); $clog[$row['action']] = array();
@@ -68,7 +68,6 @@ if ($page == 'log') {
ksort($clog); ksort($clog);
} }
$i = 0;
$count = 0; $count = 0;
$log_count = 0; $log_count = 0;
$log = ''; $log = '';
@@ -113,10 +112,7 @@ if ($page == 'log') {
eval("\$log.=\"" . \Froxlor\UI\Template::getTemplate('logger/logger_log') . "\";"); eval("\$log.=\"" . \Froxlor\UI\Template::getTemplate('logger/logger_log') . "\";");
$count ++; $count ++;
$_action = $action; $_action = $action;
// }
$i ++;
} }
$i ++;
} }
eval("echo \"" . \Froxlor\UI\Template::getTemplate('logger/logger') . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate('logger/logger') . "\";");

View File

@@ -53,20 +53,24 @@ if ($page == 'overview') {
'databasename' => $lng['mysql']['databasename'], 'databasename' => $lng['mysql']['databasename'],
'description' => $lng['mysql']['databasedescription'] 'description' => $lng['mysql']['databasedescription']
); );
$paging = new \Froxlor\UI\Paging($userinfo, TABLE_PANEL_DATABASES, $fields); try {
$result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DATABASES . "` // get total count
WHERE `customerid`= :customerid " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit()); $json_result = Mysqls::getLocal($userinfo)->listingCount();
Database::pexecute($result_stmt, array( $result = json_decode($json_result, true)['data'];
"customerid" => $userinfo['customerid'] // initialize pagination and filtering
)); $paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
$mysqls_count = Database::num_rows(); // get list
$paging->setEntries($mysqls_count); $json_result = Mysqls::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$mysqls_count = $paging->getEntries();
$sortcode = $paging->getHtmlSortCode($lng); $sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng); $searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); $pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$i = 0;
$count = 0; $count = 0;
$mysqls = ''; $mysqls = '';
@@ -76,22 +80,21 @@ if ($page == 'overview') {
// Begin root-session // Begin root-session
Database::needRoot(true); Database::needRoot(true);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { foreach ($result['list'] as $row) {
if ($paging->checkDisplay($i)) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($row); $row = \Froxlor\PhpHelper::htmlentitiesArray($row);
$mbdata_stmt = Database::prepare("SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES $mbdata_stmt = Database::prepare("SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES
WHERE table_schema = :table_schema WHERE table_schema = :table_schema
GROUP BY table_schema"); GROUP BY table_schema");
Database::pexecute($mbdata_stmt, array( $mbdata = Database::pexecute_first($mbdata_stmt, array(
"table_schema" => $row['databasename'] "table_schema" => $row['databasename']
)); ));
$mbdata = $mbdata_stmt->fetch(PDO::FETCH_ASSOC); if (!$mbdata) {
$mbdata = array('MB' => 0);
}
$row['size'] = \Froxlor\PhpHelper::sizeReadable($mbdata['MB'], 'GiB', 'bi', '%01.' . (int) Settings::Get('panel.decimal_places') . 'f %s'); $row['size'] = \Froxlor\PhpHelper::sizeReadable($mbdata['MB'], 'GiB', 'bi', '%01.' . (int) Settings::Get('panel.decimal_places') . 'f %s');
eval("\$mysqls.=\"" . \Froxlor\UI\Template::getTemplate('mysql/mysqls_database') . "\";"); eval("\$mysqls.=\"" . \Froxlor\UI\Template::getTemplate('mysql/mysqls_database') . "\";");
$count ++; $count ++;
} }
$i ++;
}
Database::needRoot(false); Database::needRoot(false);
// End root-session // End root-session

View File

@@ -86,22 +86,18 @@ if (! is_null($month) && ! is_null($year)) {
if (extension_loaded('bcmath')) { if (extension_loaded('bcmath')) {
$traf['ftptext'] = bcdiv($row['ftp_up'], 1024, Settings::Get('panel.decimal_places')) . " MiB up/ " . bcdiv($row['ftp_down'], 1024, Settings::Get('panel.decimal_places')) . " MiB down (FTP)"; $traf['ftptext'] = bcdiv($row['ftp_up'], 1024, Settings::Get('panel.decimal_places')) . " MiB up/ " . bcdiv($row['ftp_down'], 1024, Settings::Get('panel.decimal_places')) . " MiB down (FTP)";
$traf['httptext'] = bcdiv($http, 1024, Settings::Get('panel.decimal_places')) . " MiB (HTTP)";
$traf['mailtext'] = bcdiv($mail, 1024, Settings::Get('panel.decimal_places')) . " MiB (Mail)";
$traf['ftp'] = bcdiv($ftp, 1024, Settings::Get('panel.decimal_places')); $traf['ftp'] = bcdiv($ftp, 1024, Settings::Get('panel.decimal_places'));
$traf['http'] = bcdiv($http, 1024, Settings::Get('panel.decimal_places'));
$traf['mail'] = bcdiv($mail, 1024, Settings::Get('panel.decimal_places'));
$traf['byte'] = bcdiv($traf['byte'], 1024, Settings::Get('panel.decimal_places'));
} else { } else {
$traf['ftptext'] = round($row['ftp_up'] / 1024, Settings::Get('panel.decimal_places')) . " MiB up/ " . round($row['ftp_down'] / 1024, Settings::Get('panel.decimal_places')) . " MiB down (FTP)"; $traf['ftptext'] = round($row['ftp_up'] / 1024, Settings::Get('panel.decimal_places')) . " MiB up/ " . round($row['ftp_down'] / 1024, Settings::Get('panel.decimal_places')) . " MiB down (FTP)";
$traf['httptext'] = round($http / 1024, Settings::Get('panel.decimal_places')) . " MiB (HTTP)"; $traf['ftp'] = round($ftp / 1024, Settings::Get('panel.decimal_places'));
$traf['mailtext'] = round($mail / 1024, Settings::Get('panel.decimal_places')) . " MiB (Mail)";
$traf['http'] = round($http, Settings::Get('panel.decimal_places'));
$traf['ftp'] = round($ftp, Settings::Get('panel.decimal_places'));
$traf['mail'] = round($mail, Settings::Get('panel.decimal_places'));
$traf['byte'] = round($traf['byte'] / 1024, Settings::Get('panel.decimal_places'));
} }
getReadableTraffic($traf,'httptext', $http, 1024, "MiB (HTTP)");
getReadableTraffic($traf,'http', $http, 1024);
getReadableTraffic($traf,'mailtext', $mail, 1024, "MiB (Mail)");
getReadableTraffic($traf,'mail', $mail, 1024);
getReadableTraffic($traf,'byte', $traf['byte'], (1024 * 1024));
eval("\$traffic.=\"" . \Froxlor\UI\Template::getTemplate('traffic/traffic_month') . "\";"); eval("\$traffic.=\"" . \Froxlor\UI\Template::getTemplate('traffic/traffic_month') . "\";");
$show = $lng['traffic']['months'][intval($row['month'])] . ' ' . $row['year']; $show = $lng['traffic']['months'][intval($row['month'])] . ' ' . $row['year'];
} }
@@ -112,11 +108,14 @@ if (! is_null($month) && ! is_null($year)) {
eval("echo \"" . \Froxlor\UI\Template::getTemplate('traffic/traffic_details') . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate('traffic/traffic_details') . "\";");
} else { } else {
$result_stmt = Database::prepare("SELECT `month`, `year`, SUM(`http`) AS http, SUM(`ftp_up`) AS ftp_up, SUM(`ftp_down`) AS ftp_down, SUM(`mail`) AS mail $result_stmt = Database::prepare("
SELECT `month`, `year`, SUM(`http`) AS http, SUM(`ftp_up`) AS ftp_up, SUM(`ftp_down`) AS ftp_down, SUM(`mail`) AS mail
FROM `" . TABLE_PANEL_TRAFFIC . "` FROM `" . TABLE_PANEL_TRAFFIC . "`
WHERE `customerid` = :customerid WHERE `customerid` = :customerid
GROUP BY `year` DESC, `month` DESC GROUP BY `year`, `month`
LIMIT 12"); ORDER BY `year` DESC, `month` DESC
LIMIT 12
");
Database::pexecute($result_stmt, array( Database::pexecute($result_stmt, array(
"customerid" => $userinfo['customerid'] "customerid" => $userinfo['customerid']
)); ));
@@ -139,22 +138,18 @@ if (! is_null($month) && ! is_null($year)) {
if (extension_loaded('bcmath')) { if (extension_loaded('bcmath')) {
$traf['ftptext'] = bcdiv($ftp_up, 1024, Settings::Get('panel.decimal_places')) . " MiB up/ " . bcdiv($ftp_down, 1024, Settings::Get('panel.decimal_places')) . " MiB down (FTP)"; $traf['ftptext'] = bcdiv($ftp_up, 1024, Settings::Get('panel.decimal_places')) . " MiB up/ " . bcdiv($ftp_down, 1024, Settings::Get('panel.decimal_places')) . " MiB down (FTP)";
$traf['httptext'] = bcdiv($http, 1024, Settings::Get('panel.decimal_places')) . " MiB (HTTP)";
$traf['mailtext'] = bcdiv($mail, 1024, Settings::Get('panel.decimal_places')) . " MiB (Mail)";
$traf['ftp'] = bcdiv(($ftp_up + $ftp_down), 1024, Settings::Get('panel.decimal_places')); $traf['ftp'] = bcdiv(($ftp_up + $ftp_down), 1024, Settings::Get('panel.decimal_places'));
$traf['http'] = bcdiv($http, 1024, Settings::Get('panel.decimal_places'));
$traf['mail'] = bcdiv($mail, 1024, Settings::Get('panel.decimal_places'));
$traf['byte'] = bcdiv($traf['byte'], 1024 * 1024, Settings::Get('panel.decimal_places'));
} else { } else {
$traf['ftptext'] = round($ftp_up / 1024, Settings::Get('panel.decimal_places')) . " MiB up/ " . round($ftp_down / 1024, Settings::Get('panel.decimal_places')) . " MiB down (FTP)"; $traf['ftptext'] = round($ftp_up / 1024, Settings::Get('panel.decimal_places')) . " MiB up/ " . round($ftp_down / 1024, Settings::Get('panel.decimal_places')) . " MiB down (FTP)";
$traf['httptext'] = round($http / 1024, Settings::Get('panel.decimal_places')) . " MiB (HTTP)";
$traf['mailtext'] = round($mail / 1024, Settings::Get('panel.decimal_places')) . " MiB (Mail)";
$traf['ftp'] = round(($ftp_up + $ftp_down) / 1024, Settings::Get('panel.decimal_places')); $traf['ftp'] = round(($ftp_up + $ftp_down) / 1024, Settings::Get('panel.decimal_places'));
$traf['http'] = round($http / 1024, Settings::Get('panel.decimal_places'));
$traf['mail'] = round($mail / 1024, Settings::Get('panel.decimal_places'));
$traf['byte'] = round($traf['byte'] / (1024 * 1024), Settings::Get('panel.decimal_places'));
} }
getReadableTraffic($traf,'httptext', $http, 1024, "MiB (HTTP)");
getReadableTraffic($traf,'http', $http, 1024);
getReadableTraffic($traf,'mailtext', $mail, 1024, "MiB (Mail)");
getReadableTraffic($traf,'mail', $mail, 1024);
getReadableTraffic($traf,'byte', $traf['byte'], (1024 * 1024));
eval("\$traffic.=\"" . \Froxlor\UI\Template::getTemplate('traffic/traffic_traffic') . "\";"); eval("\$traffic.=\"" . \Froxlor\UI\Template::getTemplate('traffic/traffic_traffic') . "\";");
} }
@@ -164,3 +159,12 @@ if (! is_null($month) && ! is_null($year)) {
eval("echo \"" . \Froxlor\UI\Template::getTemplate('traffic/traffic') . "\";"); eval("echo \"" . \Froxlor\UI\Template::getTemplate('traffic/traffic') . "\";");
} }
function getReadableTraffic(&$traf, $index, $value, $divisor, $desc = "")
{
if (extension_loaded('bcmath')) {
$traf[$index] = bcdiv($value, $divisor,Settings::Get('panel.decimal_places')).(!empty($desc) ? " ".$desc : "");
} else {
$traf[$index] = round($value / $divisor, Settings::Get('panel.decimal_places')).(!empty($desc) ? " ".$desc : "");
}
}

View File

@@ -19,7 +19,6 @@ if (! defined('AREA')) {
* *
*/ */
use Froxlor\Database\Database;
use Froxlor\Api\Commands\DomainZones as DomainZones; use Froxlor\Api\Commands\DomainZones as DomainZones;
// This file is being included in admin_domains and customer_domains // This file is being included in admin_domains and customer_domains
@@ -36,13 +35,6 @@ $ttl = isset($_POST['record']['ttl']) ? (int) $_POST['record']['ttl'] : 18000;
// get domain-name // get domain-name
$domain = \Froxlor\Dns\Dns::getAllowedDomainEntry($domain_id, AREA, $userinfo); $domain = \Froxlor\Dns\Dns::getAllowedDomainEntry($domain_id, AREA, $userinfo);
// select all entries
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_DOMAIN_DNS . "` WHERE domain_id = :did");
Database::pexecute($sel_stmt, array(
'did' => $domain_id
));
$dom_entries = $sel_stmt->fetchAll(PDO::FETCH_ASSOC);
$errors = ""; $errors = "";
$success_message = ""; $success_message = "";
@@ -58,8 +50,9 @@ if ($action == 'add_record' && ! empty($_POST)) {
'ttl' => $ttl 'ttl' => $ttl
))->add(); ))->add();
$success_message = $lng['success']['dns_record_added']; $success_message = $lng['success']['dns_record_added'];
$record = $prio = $content = "";
} catch (Exception $e) { } catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage()); $errors = str_replace("\n", "<br>", $e->getMessage());
} }
} elseif ($action == 'delete') { } elseif ($action == 'delete') {
// remove entry // remove entry
@@ -70,25 +63,25 @@ if ($action == 'add_record' && ! empty($_POST)) {
'entry_id' => $entry_id, 'entry_id' => $entry_id,
'id' => $domain_id 'id' => $domain_id
))->delete(); ))->delete();
// success message (inline)
$success_message = $lng['success']['dns_record_deleted'];
} catch (Exception $e) { } catch (Exception $e) {
$errors = str_replace("\n", "<br>", $e->getMessage()); $errors = str_replace("\n", "<br>", $e->getMessage());
} }
}
}
if (empty($errors)) { // select all entries
// remove deleted entry from internal data array (no reread of DB necessary) try {
$_t = $dom_entries; // get list
foreach ($_t as $idx => $entry) { $json_result = DomainZones::getLocal($userinfo, [
if ($entry['id'] == $entry_id) { 'id' => $domain_id
unset($dom_entries[$idx]); ])->listing();
break; } catch (Exception $e) {
} \Froxlor\UI\Response::dynamic_error($e->getMessage());
}
unset($_t);
// success message (inline)
$success_message = $lng['success']['dns_record_deleted'];
}
}
} }
$result = json_decode($json_result, true)['data'];
$dom_entries = $result['list'];
// show editor // show editor
$record_list = ""; $record_list = "";
@@ -117,7 +110,7 @@ $type_select_values = array(
'RP', 'RP',
'SRV', 'SRV',
'SSHFP', 'SSHFP',
'TXT', 'TXT'
); );
asort($type_select_values); asort($type_select_values);
foreach ($type_select_values as $_type) { foreach ($type_select_values as $_type) {

View File

@@ -28,6 +28,12 @@ if ($action == '') {
} }
if (session_status() == PHP_SESSION_NONE) { if (session_status() == PHP_SESSION_NONE) {
ini_set("session.name", "s");
ini_set("url_rewriter.tags", "");
ini_set("session.use_cookies", false);
ini_set("session.cookie_httponly", true);
ini_set("session.cookie_secure", $is_ssl);
session_id('login');
session_start(); session_start();
} }
@@ -114,7 +120,7 @@ if ($action == '2fa_entercode') {
)); ));
$row = $stmt->fetch(PDO::FETCH_ASSOC); $row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row['customer'] == $loginname) { if ($row && $row['customer'] == $loginname) {
$table = "`" . TABLE_PANEL_CUSTOMERS . "`"; $table = "`" . TABLE_PANEL_CUSTOMERS . "`";
$uid = 'customerid'; $uid = 'customerid';
$adminsession = '0'; $adminsession = '0';
@@ -142,7 +148,7 @@ if ($action == '2fa_entercode') {
"loginname" => $loginname "loginname" => $loginname
)); ));
$row3 = $stmt->fetch(PDO::FETCH_ASSOC); $row3 = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row3['customer'] == $loginname) { if ($row3 && $row3['customer'] == $loginname) {
$table = "`" . TABLE_PANEL_CUSTOMERS . "`"; $table = "`" . TABLE_PANEL_CUSTOMERS . "`";
$uid = 'customerid'; $uid = 'customerid';
$adminsession = '0'; $adminsession = '0';
@@ -181,7 +187,7 @@ if ($action == '2fa_entercode') {
$row = $stmt->fetch(PDO::FETCH_ASSOC); $row = $stmt->fetch(PDO::FETCH_ASSOC);
} }
if ($row['admin'] == $loginname) { if ($row && $row['admin'] == $loginname) {
$table = "`" . TABLE_PANEL_ADMINS . "`"; $table = "`" . TABLE_PANEL_ADMINS . "`";
$uid = 'adminid'; $uid = 'adminid';
$adminsession = '1'; $adminsession = '1';
@@ -393,7 +399,7 @@ if ($action == 'forgotpwd') {
if (isset($_POST['send']) && $_POST['send'] == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$loginname = \Froxlor\Validate\Validate::validate($_POST['loginname'], 'loginname'); $loginname = \Froxlor\Validate\Validate::validate($_POST['loginname'], 'loginname');
$email = \Froxlor\Validate\Validate::validateEmail($_POST['loginemail'], 'email'); $email = \Froxlor\Validate\Validate::validateEmail($_POST['loginemail'], 'email');
$result_stmt = Database::prepare("SELECT `adminid`, `customerid`, `firstname`, `name`, `company`, `email`, `loginname`, `def_language`, `deactivated` FROM `" . TABLE_PANEL_CUSTOMERS . "` $result_stmt = Database::prepare("SELECT `adminid`, `customerid`, `customernumber`, `firstname`, `name`, `company`, `email`, `loginname`, `def_language`, `deactivated` FROM `" . TABLE_PANEL_CUSTOMERS . "`
WHERE `loginname`= :loginname WHERE `loginname`= :loginname
AND `email`= :email"); AND `email`= :email");
Database::pexecute($result_stmt, array( Database::pexecute($result_stmt, array(
@@ -481,6 +487,10 @@ if ($action == 'forgotpwd') {
$replace_arr = array( $replace_arr = array(
'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($user), 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($user),
'NAME' => $user['name'],
'FIRSTNAME' => $user['firstname'] ?? "",
'COMPANY' => $user['company'] ?? "",
'CUSTOMER_NO' => $user['customernumber'] ?? 0,
'USERNAME' => $loginname, 'USERNAME' => $loginname,
'LINK' => $activationlink 'LINK' => $activationlink
); );
@@ -598,21 +608,18 @@ if ($action == 'resetpwd') {
)); ));
if ($result !== false) { if ($result !== false) {
if ($result['admin'] == 1) { try {
$new_password = \Froxlor\Validate\Validate::validate($_POST['new_password'], 'new password'); $new_password = \Froxlor\System\Crypt::validatePassword($_POST['new_password'], true);
$new_password_confirm = \Froxlor\Validate\Validate::validate($_POST['new_password_confirm'], 'new password confirm'); $new_password_confirm = \Froxlor\System\Crypt::validatePassword($_POST['new_password_confirm'], true);
} else { } catch (Exception $e) {
$new_password = \Froxlor\System\Crypt::validatePassword($_POST['new_password'], 'new password'); $message = $e->getMessage();
$new_password_confirm = \Froxlor\System\Crypt::validatePassword($_POST['new_password_confirm'], 'new password confirm');
} }
if ($new_password == '') { if (empty($message) && (empty($new_password) || $new_password != $new_password_confirm)) {
$message = $new_password; $message = $lng['error']['newpasswordconfirmerror'];
} elseif ($new_password_confirm == '') { }
$message = $new_password_confirm;
} elseif ($new_password != $new_password_confirm) { if (empty($message)) {
$message = $new_password . " != " . $new_password_confirm;
} else {
// Update user password // Update user password
if ($result['admin'] == 1) { if ($result['admin'] == 1) {
$stmt = Database::prepare("UPDATE `" . TABLE_PANEL_ADMINS . "` $stmt = Database::prepare("UPDATE `" . TABLE_PANEL_ADMINS . "`
@@ -668,7 +675,7 @@ function finishLogin($userinfo)
global $version, $dbversion, $remote_addr, $http_user_agent, $languages; global $version, $dbversion, $remote_addr, $http_user_agent, $languages;
if (isset($userinfo['userid']) && $userinfo['userid'] != '') { if (isset($userinfo['userid']) && $userinfo['userid'] != '') {
$s = md5(uniqid(microtime(), 1)); $s = \Froxlor\Froxlor::genSessionId();
if (isset($_POST['language'])) { if (isset($_POST['language'])) {
$language = \Froxlor\Validate\Validate::validate($_POST['language'], 'language'); $language = \Froxlor\Validate\Validate::validate($_POST['language'], 'language');

View File

@@ -15,10 +15,10 @@ CREATE TABLE `ftp_groups` (
DROP TABLE IF EXISTS `ftp_users`; DROP TABLE IF EXISTS `ftp_users`;
CREATE TABLE `ftp_users` ( CREATE TABLE `ftp_users` (
`id` int(20) NOT NULL auto_increment, `id` int(20) NOT NULL auto_increment,
`username` varchar(255) NOT NULL default '', `username` varchar(255) NOT NULL,
`uid` int(5) NOT NULL default '0', `uid` int(5) NOT NULL default '0',
`gid` int(5) NOT NULL default '0', `gid` int(5) NOT NULL default '0',
`password` varchar(128) NOT NULL default '', `password` varchar(128) NOT NULL,
`homedir` varchar(255) NOT NULL default '', `homedir` varchar(255) NOT NULL default '',
`shell` varchar(255) NOT NULL default '/bin/false', `shell` varchar(255) NOT NULL default '/bin/false',
`login_enabled` enum('N','Y') NOT NULL default 'N', `login_enabled` enum('N','Y') NOT NULL default 'N',
@@ -71,6 +71,7 @@ CREATE TABLE `mail_virtual` (
`customerid` int(11) NOT NULL default '0', `customerid` int(11) NOT NULL default '0',
`popaccountid` int(11) NOT NULL default '0', `popaccountid` int(11) NOT NULL default '0',
`iscatchall` tinyint(1) unsigned NOT NULL default '0', `iscatchall` tinyint(1) unsigned NOT NULL default '0',
`description` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `email` (`email`) KEY `email` (`email`)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci; ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -90,11 +91,11 @@ CREATE TABLE `panel_activation` (
DROP TABLE IF EXISTS `panel_admins`; DROP TABLE IF EXISTS `panel_admins`;
CREATE TABLE `panel_admins` ( CREATE TABLE `panel_admins` (
`adminid` int(11) unsigned NOT NULL auto_increment, `adminid` int(11) unsigned NOT NULL auto_increment,
`loginname` varchar(50) NOT NULL default '', `loginname` varchar(50) NOT NULL,
`password` varchar(255) NOT NULL default '', `password` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL default '', `name` varchar(255) NOT NULL default '',
`email` varchar(255) NOT NULL default '', `email` varchar(255) NOT NULL default '',
`def_language` varchar(255) NOT NULL default '', `def_language` varchar(100) NOT NULL default '',
`ip` varchar(500) NOT NULL default '-1', `ip` varchar(500) NOT NULL default '-1',
`customers` int(15) NOT NULL default '0', `customers` int(15) NOT NULL default '0',
`customers_used` int(15) NOT NULL default '0', `customers_used` int(15) NOT NULL default '0',
@@ -127,11 +128,11 @@ CREATE TABLE `panel_admins` (
`lastlogin_fail` int(11) unsigned NOT NULL default '0', `lastlogin_fail` int(11) unsigned NOT NULL default '0',
`loginfail_count` int(11) unsigned NOT NULL default '0', `loginfail_count` int(11) unsigned NOT NULL default '0',
`reportsent` tinyint(4) unsigned NOT NULL default '0', `reportsent` tinyint(4) unsigned NOT NULL default '0',
`theme` varchar(255) NOT NULL default 'Sparkle', `theme` varchar(50) NOT NULL default 'Sparkle',
`custom_notes` text, `custom_notes` text,
`custom_notes_show` tinyint(1) NOT NULL default '0', `custom_notes_show` tinyint(1) NOT NULL default '0',
`type_2fa` tinyint(1) NOT NULL default '0', `type_2fa` tinyint(1) NOT NULL default '0',
`data_2fa` varchar(500) NOT NULL default '', `data_2fa` varchar(25) NOT NULL default '',
`api_allowed` tinyint(1) NOT NULL default '1', `api_allowed` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`adminid`), PRIMARY KEY (`adminid`),
UNIQUE KEY `loginname` (`loginname`) UNIQUE KEY `loginname` (`loginname`)
@@ -142,7 +143,7 @@ CREATE TABLE `panel_admins` (
DROP TABLE IF EXISTS `panel_customers`; DROP TABLE IF EXISTS `panel_customers`;
CREATE TABLE `panel_customers` ( CREATE TABLE `panel_customers` (
`customerid` int(11) unsigned NOT NULL auto_increment, `customerid` int(11) unsigned NOT NULL auto_increment,
`loginname` varchar(50) NOT NULL default '', `loginname` varchar(50) NOT NULL,
`password` varchar(255) NOT NULL default '', `password` varchar(255) NOT NULL default '',
`adminid` int(11) unsigned NOT NULL default '0', `adminid` int(11) unsigned NOT NULL default '0',
`name` varchar(255) NOT NULL default '', `name` varchar(255) NOT NULL default '',
@@ -150,13 +151,13 @@ CREATE TABLE `panel_customers` (
`gender` int(1) NOT NULL DEFAULT '0', `gender` int(1) NOT NULL DEFAULT '0',
`company` varchar(255) NOT NULL default '', `company` varchar(255) NOT NULL default '',
`street` varchar(255) NOT NULL default '', `street` varchar(255) NOT NULL default '',
`zipcode` varchar(255) NOT NULL default '', `zipcode` varchar(25) NOT NULL default '',
`city` varchar(255) NOT NULL default '', `city` varchar(255) NOT NULL default '',
`phone` varchar(255) NOT NULL default '', `phone` varchar(50) NOT NULL default '',
`fax` varchar(255) NOT NULL default '', `fax` varchar(50) NOT NULL default '',
`email` varchar(255) NOT NULL default '', `email` varchar(255) NOT NULL default '',
`customernumber` varchar(255) NOT NULL default '', `customernumber` varchar(255) NOT NULL default '',
`def_language` varchar(255) NOT NULL default '', `def_language` varchar(100) NOT NULL default '',
`diskspace` bigint(30) NOT NULL default '0', `diskspace` bigint(30) NOT NULL default '0',
`diskspace_used` bigint(30) NOT NULL default '0', `diskspace_used` bigint(30) NOT NULL default '0',
`mysqls` int(15) NOT NULL default '0', `mysqls` int(15) NOT NULL default '0',
@@ -190,16 +191,15 @@ CREATE TABLE `panel_customers` (
`imap` tinyint(1) NOT NULL default '1', `imap` tinyint(1) NOT NULL default '1',
`perlenabled` tinyint(1) NOT NULL default '0', `perlenabled` tinyint(1) NOT NULL default '0',
`dnsenabled` tinyint(1) NOT NULL default '0', `dnsenabled` tinyint(1) NOT NULL default '0',
`theme` varchar(255) NOT NULL default 'Sparkle', `theme` varchar(50) NOT NULL default 'Sparkle',
`custom_notes` text, `custom_notes` text,
`custom_notes_show` tinyint(1) NOT NULL default '0', `custom_notes_show` tinyint(1) NOT NULL default '0',
`lepublickey` mediumtext default NULL, `lepublickey` mediumtext default NULL,
`leprivatekey` mediumtext default NULL, `leprivatekey` mediumtext default NULL,
`leregistered` tinyint(1) NOT NULL default '0', `leregistered` tinyint(1) NOT NULL default '0',
`leaccount` varchar(255) default '',
`allowed_phpconfigs` varchar(500) NOT NULL default '', `allowed_phpconfigs` varchar(500) NOT NULL default '',
`type_2fa` tinyint(1) NOT NULL default '0', `type_2fa` tinyint(1) NOT NULL default '0',
`data_2fa` varchar(500) NOT NULL default '', `data_2fa` varchar(25) NOT NULL default '',
`api_allowed` tinyint(1) NOT NULL default '1', `api_allowed` tinyint(1) NOT NULL default '1',
`logviewenabled` tinyint(1) NOT NULL default '0', `logviewenabled` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`customerid`), PRIMARY KEY (`customerid`),
@@ -224,7 +224,8 @@ CREATE TABLE `panel_databases` (
DROP TABLE IF EXISTS `panel_domains`; DROP TABLE IF EXISTS `panel_domains`;
CREATE TABLE `panel_domains` ( CREATE TABLE `panel_domains` (
`id` int(11) unsigned NOT NULL auto_increment, `id` int(11) unsigned NOT NULL auto_increment,
`domain` varchar(255) NOT NULL default '', `domain` varchar(255) NOT NULL,
`domain_ace` varchar(255) NOT NULL default '',
`adminid` int(11) unsigned NOT NULL default '0', `adminid` int(11) unsigned NOT NULL default '0',
`customerid` int(11) unsigned NOT NULL default '0', `customerid` int(11) unsigned NOT NULL default '0',
`aliasdomain` int(11) unsigned NULL, `aliasdomain` int(11) unsigned NULL,
@@ -248,6 +249,8 @@ CREATE TABLE `panel_domains` (
`speciallogfile` tinyint(1) NOT NULL default '0', `speciallogfile` tinyint(1) NOT NULL default '0',
`ssl_redirect` tinyint(4) NOT NULL default '0', `ssl_redirect` tinyint(4) NOT NULL default '0',
`specialsettings` text, `specialsettings` text,
`ssl_specialsettings` text,
`include_specialsettings` tinyint(1) NOT NULL default '0',
`deactivated` tinyint(1) NOT NULL default '0', `deactivated` tinyint(1) NOT NULL default '0',
`bindserial` varchar(10) NOT NULL default '2000010100', `bindserial` varchar(10) NOT NULL default '2000010100',
`add_date` int( 11 ) NOT NULL default '0', `add_date` int( 11 ) NOT NULL default '0',
@@ -266,6 +269,14 @@ CREATE TABLE `panel_domains` (
`notryfiles` tinyint(1) DEFAULT '0', `notryfiles` tinyint(1) DEFAULT '0',
`writeaccesslog` tinyint(1) DEFAULT '1', `writeaccesslog` tinyint(1) DEFAULT '1',
`writeerrorlog` tinyint(1) DEFAULT '1', `writeerrorlog` tinyint(1) DEFAULT '1',
`override_tls` tinyint(1) DEFAULT '0',
`ssl_protocols` varchar(255) NOT NULL DEFAULT '',
`ssl_cipher_list` varchar(500) NOT NULL DEFAULT '',
`tlsv13_cipher_list` varchar(500) NOT NULL DEFAULT '',
`ssl_enabled` tinyint(1) DEFAULT '1',
`ssl_honorcipherorder` tinyint(1) DEFAULT '0',
`ssl_sessiontickets` tinyint(1) DEFAULT '1',
`description` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `customerid` (`customerid`), KEY `customerid` (`customerid`),
KEY `parentdomain` (`parentdomainid`), KEY `parentdomain` (`parentdomainid`),
@@ -277,7 +288,7 @@ CREATE TABLE `panel_domains` (
DROP TABLE IF EXISTS `panel_ipsandports`; DROP TABLE IF EXISTS `panel_ipsandports`;
CREATE TABLE `panel_ipsandports` ( CREATE TABLE `panel_ipsandports` (
`id` int(11) unsigned NOT NULL auto_increment, `id` int(11) unsigned NOT NULL auto_increment,
`ip` varchar(39) NOT NULL default '', `ip` varchar(39) NOT NULL,
`port` int(5) NOT NULL default '80', `port` int(5) NOT NULL default '80',
`listen_statement` tinyint(1) NOT NULL default '0', `listen_statement` tinyint(1) NOT NULL default '0',
`namevirtualhost_statement` tinyint(1) NOT NULL default '0', `namevirtualhost_statement` tinyint(1) NOT NULL default '0',
@@ -291,6 +302,10 @@ CREATE TABLE `panel_ipsandports` (
`default_vhostconf_domain` text, `default_vhostconf_domain` text,
`ssl_cert_chainfile` varchar(255) NOT NULL default '', `ssl_cert_chainfile` varchar(255) NOT NULL default '',
`docroot` 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`), PRIMARY KEY (`id`),
UNIQUE KEY `ip_port` (`ip`,`port`) UNIQUE KEY `ip_port` (`ip`,`port`)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci; ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -374,6 +389,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('dkim', 'dkim_domains', 'domains'), ('dkim', 'dkim_domains', 'domains'),
('dkim', 'dkim_dkimkeys', 'dkim-keys.conf'), ('dkim', 'dkim_dkimkeys', 'dkim-keys.conf'),
('dkim', 'dkimrestart_command', '/etc/init.d/dkim-filter restart'), ('dkim', 'dkimrestart_command', '/etc/init.d/dkim-filter restart'),
('dkim', 'privkeysuffix', '.priv'),
('admin', 'show_news_feed', '0'), ('admin', 'show_news_feed', '0'),
('admin', 'show_version_login', '0'), ('admin', 'show_version_login', '0'),
('admin', 'show_version_footer', '0'), ('admin', 'show_version_footer', '0'),
@@ -516,7 +532,7 @@ opcache.interned_strings_buffer'),
('system', 'vmail_gid', '2000'), ('system', 'vmail_gid', '2000'),
('system', 'vmail_homedir', '/var/customers/mail/'), ('system', 'vmail_homedir', '/var/customers/mail/'),
('system', 'vmail_maildirname', 'Maildir'), ('system', 'vmail_maildirname', 'Maildir'),
('system', 'bind_enable', '1'), ('system', 'bind_enable', '0'),
('system', 'bindconf_directory', '/etc/bind/'), ('system', 'bindconf_directory', '/etc/bind/'),
('system', 'bindreload_command', '/etc/init.d/bind9 reload'), ('system', 'bindreload_command', '/etc/init.d/bind9 reload'),
('system', 'hostname', 'SERVERNAME'), ('system', 'hostname', 'SERVERNAME'),
@@ -541,6 +557,7 @@ opcache.interned_strings_buffer'),
('system', 'ssl_cert_file', '/etc/apache2/apache2.pem'), ('system', 'ssl_cert_file', '/etc/apache2/apache2.pem'),
('system', 'use_ssl', '0'), ('system', 'use_ssl', '0'),
('system', 'default_vhostconf', ''), ('system', 'default_vhostconf', ''),
('system', 'default_sslvhostconf', ''),
('system', 'mail_quota_enabled', '0'), ('system', 'mail_quota_enabled', '0'),
('system', 'mail_quota', '100'), ('system', 'mail_quota', '100'),
('system', 'webalizer_enabled', '1'), ('system', 'webalizer_enabled', '1'),
@@ -560,6 +577,7 @@ opcache.interned_strings_buffer'),
('system', 'stdsubdomain', ''), ('system', 'stdsubdomain', ''),
('system', 'awstats_path', '/usr/bin/'), ('system', 'awstats_path', '/usr/bin/'),
('system', 'awstats_conf', '/etc/awstats/'), ('system', 'awstats_conf', '/etc/awstats/'),
('system', 'awstats_logformat', '1'),
('system', 'defaultttl', '604800'), ('system', 'defaultttl', '604800'),
('system', 'mod_fcgid_defaultini', '1'), ('system', 'mod_fcgid_defaultini', '1'),
('system', 'ftpserver', 'proftpd'), ('system', 'ftpserver', 'proftpd'),
@@ -593,6 +611,7 @@ opcache.interned_strings_buffer'),
('system', 'documentroot_use_default_value', '0'), ('system', 'documentroot_use_default_value', '0'),
('system', 'passwordcryptfunc', '3'), ('system', 'passwordcryptfunc', '3'),
('system', 'axfrservers', ''), ('system', 'axfrservers', ''),
('system', 'powerdns_mode', 'Native'),
('system', 'customer_ssl_path', '/etc/ssl/froxlor-custom/'), ('system', 'customer_ssl_path', '/etc/ssl/froxlor-custom/'),
('system', 'allow_error_report_admin', '1'), ('system', 'allow_error_report_admin', '1'),
('system', 'allow_error_report_customer', '0'), ('system', 'allow_error_report_customer', '0'),
@@ -610,7 +629,7 @@ opcache.interned_strings_buffer'),
('system', 'apacheitksupport', '0'), ('system', 'apacheitksupport', '0'),
('system', 'leprivatekey', 'unset'), ('system', 'leprivatekey', 'unset'),
('system', 'lepublickey', 'unset'), ('system', 'lepublickey', 'unset'),
('system', 'letsencryptca', 'production'), ('system', 'letsencryptca', 'letsencrypt'),
('system', 'letsencryptcountrycode', 'DE'), ('system', 'letsencryptcountrycode', 'DE'),
('system', 'letsencryptstate', 'Hessen'), ('system', 'letsencryptstate', 'Hessen'),
('system', 'letsencryptchallengepath', '/var/www/froxlor'), ('system', 'letsencryptchallengepath', '/var/www/froxlor'),
@@ -640,9 +659,12 @@ opcache.interned_strings_buffer'),
('system', 'leregistered', '0'), ('system', 'leregistered', '0'),
('system', 'leaccount', ''), ('system', 'leaccount', ''),
('system', 'nssextrausers', '0'), ('system', 'nssextrausers', '0'),
('system', 'disable_le_selfcheck', '0'), ('system', 'le_domain_dnscheck', '1'),
('system', 'ssl_protocols', 'TLSv1,TLSv1.2'), ('system', 'ssl_protocols', 'TLSv1.2'),
('system', 'tlsv13_cipher_list', ''), ('system', 'tlsv13_cipher_list', ''),
('system', 'honorcipherorder', '0'),
('system', 'sessiontickets', '1'),
('system', 'sessionticketsenabled', '1'),
('system', 'logfiles_format', ''), ('system', 'logfiles_format', ''),
('system', 'logfiles_type', '1'), ('system', 'logfiles_type', '1'),
('system', 'logfiles_piped', '0'), ('system', 'logfiles_piped', '0'),
@@ -651,6 +673,15 @@ opcache.interned_strings_buffer'),
('system', 'errorlog_level', 'warn'), ('system', 'errorlog_level', 'warn'),
('system', 'leecc', '0'), ('system', 'leecc', '0'),
('system', 'froxloraliases', ''), ('system', 'froxloraliases', ''),
('system', 'apply_specialsettings_default', '1'),
('system', 'apply_phpconfigs_default', '1'),
('system', 'hide_incompatible_settings', '0'),
('system', 'include_default_vhostconf', '0'),
('system', 'soaemail', ''),
('system', 'domaindefaultalias', '0'),
('system', 'createstdsubdom_default', '1'),
('system', 'froxlorusergroup', ''),
('system', 'froxlorusergroup_gid', ''),
('api', 'enabled', '0'), ('api', 'enabled', '0'),
('2fa', 'enabled', '1'), ('2fa', 'enabled', '1'),
('panel', 'decimal_places', '4'), ('panel', 'decimal_places', '4'),
@@ -663,7 +694,6 @@ opcache.interned_strings_buffer'),
('panel', 'paging', '20'), ('panel', 'paging', '20'),
('panel', 'natsorting', '1'), ('panel', 'natsorting', '1'),
('panel', 'sendalternativemail', '0'), ('panel', 'sendalternativemail', '0'),
('panel', 'no_robots', '1'),
('panel', 'allow_domain_change_admin', '0'), ('panel', 'allow_domain_change_admin', '0'),
('panel', 'allow_domain_change_customer', '0'), ('panel', 'allow_domain_change_customer', '0'),
('panel', 'frontend', 'froxlor'), ('panel', 'frontend', 'froxlor'),
@@ -685,8 +715,15 @@ opcache.interned_strings_buffer'),
('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'password_special_char', '!?<>§$%+#=@'),
('panel', 'customer_hide_options', ''), ('panel', 'customer_hide_options', ''),
('panel', 'is_configured', '0'), ('panel', 'is_configured', '0'),
('panel', 'version', '0.10.1'), ('panel', 'imprint_url', ''),
('panel', 'db_version', '201910090'); ('panel', 'terms_url', ''),
('panel', 'privacy_url', ''),
('panel', 'logo_image_header', ''),
('panel', 'logo_image_login', ''),
('panel', 'logo_overridetheme', '0'),
('panel', 'logo_overridecustom', '0'),
('panel', 'version', '0.10.31'),
('panel', 'db_version', '202109040');
DROP TABLE IF EXISTS `panel_tasks`; DROP TABLE IF EXISTS `panel_tasks`;
@@ -767,23 +804,6 @@ CREATE TABLE `panel_diskspace` (
DROP TABLE IF EXISTS `panel_diskspace_admins`;
CREATE TABLE `panel_diskspace_admins` (
`id` int(11) unsigned NOT NULL auto_increment,
`adminid` int(11) unsigned NOT NULL default '0',
`year` int(4) unsigned zerofill NOT NULL default '0000',
`month` int(2) unsigned zerofill NOT NULL default '00',
`day` int(2) unsigned zerofill NOT NULL default '00',
`stamp` int(11) unsigned NOT NULL default '0',
`webspace` bigint(30) unsigned NOT NULL default '0',
`mail` bigint(30) unsigned NOT NULL default '0',
`mysql` bigint(30) unsigned NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `adminid` (`adminid`)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
DROP TABLE IF EXISTS `panel_languages`; DROP TABLE IF EXISTS `panel_languages`;
CREATE TABLE `panel_languages` ( CREATE TABLE `panel_languages` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT, `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
@@ -802,7 +822,8 @@ INSERT INTO `panel_languages` (`id`, `language`, `iso`, `file`) VALUES
(4, 'Portugu&ecirc;s', 'pt', 'lng/portugues.lng.php'), (4, 'Portugu&ecirc;s', 'pt', 'lng/portugues.lng.php'),
(5, 'Italiano', 'it', 'lng/italian.lng.php'), (5, 'Italiano', 'it', 'lng/italian.lng.php'),
(6, 'Nederlands', 'nl', 'lng/dutch.lng.php'), (6, 'Nederlands', 'nl', 'lng/dutch.lng.php'),
(7, 'Svenska', 'sv', 'lng/swedish.lng.php'); (7, 'Svenska', 'sv', 'lng/swedish.lng.php'),
(8, '&#268;esk&aacute; republika', 'cs', 'lng/czech.lng.php');
DROP TABLE IF EXISTS `panel_syslog`; DROP TABLE IF EXISTS `panel_syslog`;
@@ -824,14 +845,15 @@ CREATE TABLE `panel_fpmdaemons` (
`description` varchar(50) NOT NULL, `description` varchar(50) NOT NULL,
`reload_cmd` varchar(255) NOT NULL, `reload_cmd` varchar(255) NOT NULL,
`config_dir` varchar(255) NOT NULL, `config_dir` varchar(255) NOT NULL,
`pm` varchar(15) NOT NULL DEFAULT 'static', `pm` varchar(15) NOT NULL DEFAULT 'dynamic',
`max_children` int(4) NOT NULL DEFAULT '1', `max_children` int(4) NOT NULL DEFAULT '5',
`start_servers` int(4) NOT NULL DEFAULT '20', `start_servers` int(4) NOT NULL DEFAULT '2',
`min_spare_servers` int(4) NOT NULL DEFAULT '5', `min_spare_servers` int(4) NOT NULL DEFAULT '1',
`max_spare_servers` int(4) NOT NULL DEFAULT '35', `max_spare_servers` int(4) NOT NULL DEFAULT '3',
`max_requests` int(4) NOT NULL DEFAULT '0', `max_requests` int(4) NOT NULL DEFAULT '0',
`idle_timeout` int(4) NOT NULL DEFAULT '30', `idle_timeout` int(4) NOT NULL DEFAULT '10',
`limit_extensions` varchar(255) NOT NULL default '.php', `limit_extensions` varchar(255) NOT NULL default '.php',
`custom_config` text,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `reload` (`reload_cmd`), UNIQUE KEY `reload` (`reload_cmd`),
UNIQUE KEY `config` (`config_dir`) UNIQUE KEY `config` (`config_dir`)
@@ -840,7 +862,7 @@ CREATE TABLE `panel_fpmdaemons` (
INSERT INTO `panel_fpmdaemons` (`id`, `description`, `reload_cmd`, `config_dir`) VALUES INSERT INTO `panel_fpmdaemons` (`id`, `description`, `reload_cmd`, `config_dir`) VALUES
(1, 'System default', 'service php7.0-fpm restart', '/etc/php/7.0/fpm/pool.d/'); (1, 'System default', 'service php7.3-fpm restart', '/etc/php/7.3/fpm/pool.d/');
@@ -860,13 +882,13 @@ CREATE TABLE `panel_phpconfigs` (
`fpmsettingid` int(11) NOT NULL DEFAULT '1', `fpmsettingid` int(11) NOT NULL DEFAULT '1',
`pass_authorizationheader` tinyint(1) NOT NULL default '0', `pass_authorizationheader` tinyint(1) NOT NULL default '0',
`override_fpmconfig` tinyint(1) NOT NULL DEFAULT '0', `override_fpmconfig` tinyint(1) NOT NULL DEFAULT '0',
`pm` varchar(15) NOT NULL DEFAULT 'static', `pm` varchar(15) NOT NULL DEFAULT 'dynamic',
`max_children` int(4) NOT NULL DEFAULT '1', `max_children` int(4) NOT NULL DEFAULT '5',
`start_servers` int(4) NOT NULL DEFAULT '20', `start_servers` int(4) NOT NULL DEFAULT '2',
`min_spare_servers` int(4) NOT NULL DEFAULT '5', `min_spare_servers` int(4) NOT NULL DEFAULT '1',
`max_spare_servers` int(4) NOT NULL DEFAULT '35', `max_spare_servers` int(4) NOT NULL DEFAULT '3',
`max_requests` int(4) NOT NULL DEFAULT '0', `max_requests` int(4) NOT NULL DEFAULT '0',
`idle_timeout` int(4) NOT NULL DEFAULT '30', `idle_timeout` int(4) NOT NULL DEFAULT '10',
`limit_extensions` varchar(255) NOT NULL default '.php', `limit_extensions` varchar(255) NOT NULL default '.php',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `fpmsettingid` (`fpmsettingid`) KEY `fpmsettingid` (`fpmsettingid`)
@@ -875,8 +897,8 @@ CREATE TABLE `panel_phpconfigs` (
INSERT INTO `panel_phpconfigs` (`id`, `description`, `binary`, `file_extensions`, `mod_fcgid_starter`, `mod_fcgid_maxrequests`, `phpsettings`) VALUES 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'), (1, 'Default Config', '/usr/bin/php-cgi', 'php', '-1', '-1', 'allow_url_fopen = Off\r\nallow_url_include = Off\r\nauto_append_file =\r\nauto_globals_jit = On\r\nauto_prepend_file =\r\nbcmath.scale = 0\r\ncli_server.color = On\r\ndefault_charset = "UTF-8"\r\ndefault_mimetype = "text/html"\r\ndefault_socket_timeout = 60\r\nasp_tags = Off\r\ndisable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,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\ndoc_root =\r\nenable_dl = Off\r\nerror_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE\r\nexpose_php = Off\r\nfile_uploads = On\r\nhtml_errors = On\r\nignore_repeated_errors = Off\r\nignore_repeated_source = Off\r\ninclude_path = ".:{PEAR_DIR}"\r\nimplicit_flush = Off\r\nldap.max_links = -1\r\nlog_errors = On\r\nlog_errors_max_len = 1024\r\nmail.add_x_header = Off\r\nmax_execution_time = 30\r\nmax_file_uploads = 20\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\nreport_memleaks = On\r\nrequest_order = "GP"\r\nsendmail_path = "/usr/sbin/sendmail -t -i -f {CUSTOMER_EMAIL}"\r\nserialize_precision = -1\r\nsession.auto_start = 0\r\nsession.cache_expire = 180\r\nsession.cache_limiter = nocache\r\nsession.cookie_domain =\r\nsession.cookie_httponly =\r\nsession.cookie_lifetime = 0\r\nsession.cookie_path = /\r\nsession.cookie_samesite =\r\nsession.gc_divisor = 1000\r\nsession.gc_maxlifetime = 1440\r\nsession.gc_probability = 0\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.sid_bits_per_character = 5\r\nsession.sid_length = 26\r\nsession.trans_sid_tags = "a=href,area=href,frame=src,form="\r\nsession.use_cookies = 1\r\nsession.use_only_cookies = 1\r\nsession.use_strict_mode = 0\r\nsession.use_trans_sid = 0\r\nshort_open_tag = On\r\nupload_max_filesize = 32M\r\nupload_tmp_dir = "{TMP_DIR}"\r\nvariables_order = "GPCS"\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,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_url_fopen = On\r\nallow_url_include = Off\r\nauto_append_file =\r\nauto_globals_jit = On\r\nauto_prepend_file =\r\nbcmath.scale = 0\r\ncli_server.color = On\r\ndefault_charset = "UTF-8"\r\ndefault_mimetype = "text/html"\r\ndefault_socket_timeout = 60\r\nasp_tags = Off\r\ndisable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,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\ndoc_root =\r\nenable_dl = Off\r\nerror_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE\r\nexpose_php = Off\r\nfile_uploads = On\r\nhtml_errors = On\r\nignore_repeated_errors = Off\r\nignore_repeated_source = Off\r\ninclude_path = ".:{PEAR_DIR}"\r\nimplicit_flush = Off\r\nldap.max_links = -1\r\nlog_errors = On\r\nlog_errors_max_len = 1024\r\nmail.add_x_header = Off\r\nmax_execution_time = 60\r\nmax_file_uploads = 20\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\nreport_memleaks = On\r\nrequest_order = "GP"\r\nsendmail_path = "/usr/sbin/sendmail -t -i -f {CUSTOMER_EMAIL}"\r\nserialize_precision = -1\r\nsession.auto_start = 0\r\nsession.cache_expire = 180\r\nsession.cache_limiter = nocache\r\nsession.cookie_domain =\r\nsession.cookie_httponly =\r\nsession.cookie_lifetime = 0\r\nsession.cookie_path = /\r\nsession.cookie_samesite =\r\nsession.gc_divisor = 1000\r\nsession.gc_maxlifetime = 1440\r\nsession.gc_probability = 0\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.sid_bits_per_character = 5\r\nsession.sid_length = 26\r\nsession.trans_sid_tags = "a=href,area=href,frame=src,form="\r\nsession.use_cookies = 1\r\nsession.use_only_cookies = 1\r\nsession.use_strict_mode = 0\r\nsession.use_trans_sid = 0\r\nshort_open_tag = On\r\nupload_max_filesize = 32M\r\nupload_tmp_dir = "{TMP_DIR}"\r\nvariables_order = "GPCS"\r\nopcache.restrict_api = ""\r\n');
DROP TABLE IF EXISTS `cronjobs_run`; DROP TABLE IF EXISTS `cronjobs_run`;
@@ -977,7 +999,8 @@ CREATE TABLE IF NOT EXISTS `domain_ssl_settings` (
`ssl_csr_file` mediumtext, `ssl_csr_file` mediumtext,
`ssl_fullchain_file` mediumtext, `ssl_fullchain_file` mediumtext,
`expirationdate` datetime DEFAULT NULL, `expirationdate` datetime DEFAULT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`),
UNIQUE KEY (`domainid`)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci; ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;

View File

@@ -123,7 +123,7 @@ class FroxlorInstall
if ((isset($_POST['installstep']) && $_POST['installstep'] == '1') || (isset($_GET['check']) && $_GET['check'] == '1')) { if ((isset($_POST['installstep']) && $_POST['installstep'] == '1') || (isset($_GET['check']) && $_GET['check'] == '1')) {
$pagetitle = $this->_lng['install']['title']; $pagetitle = $this->_lng['install']['title'];
if ($this->_checkPostData()) { if ($this->_checkPostData()) {
// ceck data and create userdata etc.etc.etc. // check data and create userdata etc.etc.etc.
$result = $this->_doInstall(); $result = $this->_doInstall();
} elseif (isset($_GET['check']) && $_GET['check'] == '1') { } elseif (isset($_GET['check']) && $_GET['check'] == '1') {
// gather data // gather data
@@ -159,13 +159,17 @@ class FroxlorInstall
$this->_guessServerName(); $this->_guessServerName();
$this->_guessServerIP(); $this->_guessServerIP();
$this->_guessWebserver(); $this->_guessWebserver();
$this->_guessDistribution();
$this->_getPostField('mysql_host', '127.0.0.1'); $this->_getPostField('mysql_host', '127.0.0.1');
$this->_getPostField('mysql_database', 'froxlor'); $this->_getPostField('mysql_database', 'froxlor');
$this->_getPostField('mysql_forcecreate', '0');
$this->_getPostField('mysql_unpriv_user', 'froxlor'); $this->_getPostField('mysql_unpriv_user', 'froxlor');
$this->_getPostField('mysql_unpriv_pass'); $this->_getPostField('mysql_unpriv_pass');
$this->_getPostField('mysql_root_user', 'root'); $this->_getPostField('mysql_root_user', 'root');
$this->_getPostField('mysql_root_pass'); $this->_getPostField('mysql_root_pass');
$this->_getPostField('mysql_ssl_ca_file');
$this->_getPostField('mysql_ssl_verify_server_certificate', 0);
$this->_getPostField('admin_user', 'admin'); $this->_getPostField('admin_user', 'admin');
$this->_getPostField('admin_pass1'); $this->_getPostField('admin_pass1');
$this->_getPostField('admin_pass2'); $this->_getPostField('admin_pass2');
@@ -211,6 +215,12 @@ class FroxlorInstall
$options = array( $options = array(
'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8' 'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8'
); );
if (!empty($this->_data['mysql_ssl_ca_file'])) {
$options[\PDO::MYSQL_ATTR_SSL_CA] = $this->_data['mysql_ssl_ca_file'];
$options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (bool) $this->_data['mysql_ssl_verify_server_certificate'];
}
$dsn = "mysql:host=" . $this->_data['mysql_host'] . ";"; $dsn = "mysql:host=" . $this->_data['mysql_host'] . ";";
$fatal_fail = false; $fatal_fail = false;
try { try {
@@ -245,15 +255,23 @@ class FroxlorInstall
$content .= $this->_status_message('green', "OK"); $content .= $this->_status_message('green', "OK");
// check for existing db and create backup if so // check for existing db and create backup if so
$content .= $this->_backupExistingDatabase($db_root); $content .= $this->_backupExistingDatabase($db_root);
if (!$this->_abort) {
// create unprivileged user and the database itself // create unprivileged user and the database itself
$content .= $this->_createDatabaseAndUser($db_root); $content .= $this->_createDatabaseAndUser($db_root);
// importing data to new database // importing data to new database
$content .= $this->_importDatabaseData(); $content .= $this->_importDatabaseData();
}
if (! $this->_abort) { if (! $this->_abort) {
// create DB object for new database // create DB object for new database
$options = array( $options = array(
'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8' 'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8'
); );
if (!empty($this->_data['mysql_ssl_ca_file'])) {
$options[\PDO::MYSQL_ATTR_SSL_CA] = $this->_data['mysql_ssl_ca_file'];
$options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (bool) $this->_data['mysql_ssl_verify_server_certificate'];
}
$dsn = "mysql:host=" . $this->_data['mysql_host'] . ";dbname=" . $this->_data['mysql_database'] . ";"; $dsn = "mysql:host=" . $this->_data['mysql_host'] . ";dbname=" . $this->_data['mysql_database'] . ";";
$another_fail = false; $another_fail = false;
try { try {
@@ -323,35 +341,70 @@ class FroxlorInstall
$userdata .= "\$sql['user']='" . addcslashes($this->_data['mysql_unpriv_user'], "'\\") . "';\n"; $userdata .= "\$sql['user']='" . addcslashes($this->_data['mysql_unpriv_user'], "'\\") . "';\n";
$userdata .= "\$sql['password']='" . addcslashes($this->_data['mysql_unpriv_pass'], "'\\") . "';\n"; $userdata .= "\$sql['password']='" . addcslashes($this->_data['mysql_unpriv_pass'], "'\\") . "';\n";
$userdata .= "\$sql['db']='" . addcslashes($this->_data['mysql_database'], "'\\") . "';\n"; $userdata .= "\$sql['db']='" . addcslashes($this->_data['mysql_database'], "'\\") . "';\n";
$userdata .= "\$sql['ssl']['caFile']='" . addcslashes($this->_data['mysql_ssl_ca_file'], "'\\") . "';\n";
$userdata .= "\$sql['ssl']['verifyServerCertificate']='" . addcslashes($this->_data['mysql_ssl_verify_server_certificate'], "'\\") . "';\n";
$userdata .= "\$sql_root[0]['caption']='Default';\n"; $userdata .= "\$sql_root[0]['caption']='Default';\n";
$userdata .= "\$sql_root[0]['host']='" . addcslashes($this->_data['mysql_host'], "'\\") . "';\n"; $userdata .= "\$sql_root[0]['host']='" . addcslashes($this->_data['mysql_host'], "'\\") . "';\n";
$userdata .= "\$sql_root[0]['user']='" . addcslashes($this->_data['mysql_root_user'], "'\\") . "';\n"; $userdata .= "\$sql_root[0]['user']='" . addcslashes($this->_data['mysql_root_user'], "'\\") . "';\n";
$userdata .= "\$sql_root[0]['password']='" . addcslashes($this->_data['mysql_root_pass'], "'\\") . "';\n"; $userdata .= "\$sql_root[0]['password']='" . addcslashes($this->_data['mysql_root_pass'], "'\\") . "';\n";
$userdata .= "\$sql_root[0]['ssl']['caFile']='" . addcslashes($this->_data['mysql_ssl_ca_file'], "'\\") . "';\n";
$userdata .= "\$sql_root[0]['ssl']['verifyServerCertificate']='" . addcslashes($this->_data['mysql_ssl_verify_server_certificate'], "'\\") . "';\n";
$userdata .= "// enable debugging to browser in case of SQL errors\n"; $userdata .= "// enable debugging to browser in case of SQL errors\n";
$userdata .= "\$sql['debug'] = false;\n"; $userdata .= "\$sql['debug'] = false;\n";
$userdata .= "?>"; $userdata .= "?>";
// test if we can store the userdata.inc.php in ../lib // test if we can store the userdata.inc.php in ../lib
$umask = @umask(077);
$userdata_file = dirname(dirname(dirname(__FILE__))) . '/lib/userdata.inc.php'; $userdata_file = dirname(dirname(dirname(__FILE__))) . '/lib/userdata.inc.php';
if ($fp = @fopen($userdata_file, 'w')) { if (@touch($userdata_file) && @is_writable($userdata_file)) {
$result = @fputs($fp, $userdata, strlen($userdata)); $fp = @fopen($userdata_file, 'w');
@fputs($fp, $userdata, strlen($userdata));
@fclose($fp); @fclose($fp);
$content .= $this->_status_message('green', 'OK'); $content .= $this->_status_message('green', 'OK');
chmod($userdata_file, 0440); } else {
} elseif ($fp = @fopen('/tmp/userdata.inc.php', 'w')) { @unlink($userdata_file);
$result = @fputs($fp, $userdata, strlen($userdata)); // try creating it in a temporary file
$temp_file = @tempnam(sys_get_temp_dir(), 'fx');
if ($temp_file) {
$fp = @fopen($temp_file, 'w');
@fputs($fp, $userdata, strlen($userdata));
@fclose($fp); @fclose($fp);
$content .= $this->_status_message('orange', $this->_lng['install']['creating_configfile_temp']); $content .= $this->_status_message('orange', sprintf($this->_lng['install']['creating_configfile_temp'], $temp_file));
chmod('/tmp/userdata.inc.php', 0440);
} else { } else {
$content .= $this->_status_message('red', $this->_lng['install']['creating_configfile_failed']); $content .= $this->_status_message('red', $this->_lng['install']['creating_configfile_failed']);
$escpduserdata = nl2br(htmlspecialchars($userdata)); $escpduserdata = nl2br(htmlspecialchars($userdata));
eval("\$content .= \"" . $this->_getTemplate("textarea") . "\";"); eval("\$content .= \"" . $this->_getTemplate("textarea") . "\";");
} }
}
@umask($umask);
return $content; return $content;
} }
/**
* generate safe unique token
*
* @param int $length
* @return string
*/
private function genUniqueToken(int $length = 16)
{
if(!isset($length) || intval($length) <= 8 ){
$length = 16;
}
if (function_exists('random_bytes')) {
return bin2hex(random_bytes($length));
}
if (function_exists('mcrypt_create_iv')) {
return bin2hex(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM));
}
if (function_exists('openssl_random_pseudo_bytes')) {
return bin2hex(openssl_random_pseudo_bytes($length));
}
// if everything else fails, use unsafe fallback
return md5(uniqid(microtime(), 1));
}
/** /**
* create corresponding entries in froxlor database * create corresponding entries in froxlor database
* *
@@ -396,7 +449,7 @@ class FroxlorInstall
$ins_data = array( $ins_data = array(
'loginname' => $this->_data['admin_user'], 'loginname' => $this->_data['admin_user'],
/* use SHA256 default crypt */ /* use SHA256 default crypt */
'password' => crypt($this->_data['admin_pass1'], '$5$' . md5(uniqid(microtime(), 1)) . md5(uniqid(microtime(), 1))), 'password' => crypt($this->_data['admin_pass1'], '$5$' . $this->genUniqueToken() . $this->genUniqueToken()),
'email' => 'admin@' . $this->_data['servername'], 'email' => 'admin@' . $this->_data['servername'],
'deflang' => $this->_languages[$this->_activelng] 'deflang' => $this->_languages[$this->_activelng]
); );
@@ -497,12 +550,30 @@ class FroxlorInstall
$this->_updateSetting($upd_stmt, 'error', 'system', 'errorlog_level'); $this->_updateSetting($upd_stmt, 'error', 'system', 'errorlog_level');
} }
$distros = glob(\Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . '/lib/configfiles/') . '*.xml');
foreach ($distros as $_distribution) {
if ($this->_data['distribution'] == str_replace(".xml", "", strtolower(basename($_distribution)))) {
$dist = new \Froxlor\Config\ConfigParser($_distribution);
$defaults = $dist->getDefaults();
foreach ($defaults->property as $property) {
$this->_updateSetting($upd_stmt, $property->value, $property->settinggroup, $property->varname);
}
}
}
$this->_updateSetting($upd_stmt, $this->_data['activate_newsfeed'], 'admin', 'show_news_feed'); $this->_updateSetting($upd_stmt, $this->_data['activate_newsfeed'], 'admin', 'show_news_feed');
$this->_updateSetting($upd_stmt, dirname(dirname(dirname(__FILE__))), 'system', 'letsencryptchallengepath'); $this->_updateSetting($upd_stmt, dirname(dirname(dirname(__FILE__))), 'system', 'letsencryptchallengepath');
// insert the lastcronrun to be the installation date // insert the lastcronrun to be the installation date
$this->_updateSetting($upd_stmt, time(), 'system', 'lastcronrun'); $this->_updateSetting($upd_stmt, time(), 'system', 'lastcronrun');
// check currently used php version and set values of fpm/fcgid accordingly
if (defined('PHP_MAJOR_VERSION') && defined('PHP_MINOR_VERSION')) {
$reload = "service php" . PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION . "-fpm restart";
$config_dir = "/etc/php/" . PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION . "/fpm/pool.d/";
$db->query("UPDATE `" . TABLE_PANEL_FPMDAEMONS . "` SET `reload_cmd` = '" . $reload . "', `config_dir` = '" . $config_dir . "' WHERE `id` ='1';");
}
// set specific times for some crons (traffic only at night, etc.) // set specific times for some crons (traffic only at night, etc.)
$ts = mktime(0, 0, 0, date('m', time()), date('d', time()), date('Y', time())); $ts = mktime(0, 0, 0, date('m', time()), date('d', time()), date('Y', time()));
$db->query("UPDATE `" . TABLE_PANEL_CRONRUNS . "` SET `lastrun` = '" . $ts . "' WHERE `cronfile` ='cron_traffic';"); $db->query("UPDATE `" . TABLE_PANEL_CRONRUNS . "` SET `lastrun` = '" . $ts . "' WHERE `cronfile` ='cron_traffic';");
@@ -529,6 +600,12 @@ class FroxlorInstall
$options = array( $options = array(
'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8' 'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8'
); );
if (!empty($this->_data['mysql_ssl_ca_file'])) {
$options[\PDO::MYSQL_ATTR_SSL_CA] = $this->_data['mysql_ssl_ca_file'];
$options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (bool) $this->_data['mysql_ssl_verify_server_certificate'];
}
$dsn = "mysql:host=" . $this->_data['mysql_host'] . ";dbname=" . $this->_data['mysql_database'] . ";"; $dsn = "mysql:host=" . $this->_data['mysql_host'] . ";dbname=" . $this->_data['mysql_database'] . ";";
$fatal_fail = false; $fatal_fail = false;
try { try {
@@ -563,7 +640,7 @@ class FroxlorInstall
for ($i = 0; $i < sizeof($sql_query); $i ++) { for ($i = 0; $i < sizeof($sql_query); $i ++) {
if (trim($sql_query[$i]) != '') { if (trim($sql_query[$i]) != '') {
try { try {
$result = $db->query($sql_query[$i]); $db->query($sql_query[$i]);
} catch (\PDOException $e) { } catch (\PDOException $e) {
$content .= $this->_status_message('red', $e->getMessage()); $content .= $this->_status_message('red', $e->getMessage());
$fatal_fail = true; $fatal_fail = true;
@@ -661,7 +738,7 @@ class FroxlorInstall
if (version_compare($db_root->getAttribute(\PDO::ATTR_SERVER_VERSION), '8.0.11', '>=')) { if (version_compare($db_root->getAttribute(\PDO::ATTR_SERVER_VERSION), '8.0.11', '>=')) {
// create user // create user
$stmt = $db_root->prepare(" $stmt = $db_root->prepare("
CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY :password CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED WITH mysql_native_password BY :password
"); ");
$stmt->execute(array( $stmt->execute(array(
"password" => $password "password" => $password
@@ -707,13 +784,18 @@ class FroxlorInstall
)); ));
$rows = $db_root->query("SELECT FOUND_ROWS()")->fetchColumn(); $rows = $db_root->query("SELECT FOUND_ROWS()")->fetchColumn();
$content .= $this->_status_message('begin', $this->_lng['install']['check_db_exists']);
// check result // check result
if ($result_stmt !== false && $rows > 0) { if ($result_stmt !== false && $rows > 0) {
$tables_exist = true; $tables_exist = true;
} }
if ($tables_exist) { if ($tables_exist) {
// tell whats going on if ((int)$this->_data['mysql_forcecreate'] > 0) {
// set status
$content .= $this->_status_message('orange', 'exists (' . $this->_data['mysql_database'] . ')');
// tell what's going on
$content .= $this->_status_message('begin', $this->_lng['install']['backup_old_db']); $content .= $this->_status_message('begin', $this->_lng['install']['backup_old_db']);
// create temporary backup-filename // create temporary backup-filename
@@ -729,17 +811,32 @@ class FroxlorInstall
$mysql_dump = '/usr/local/bin/mysqldump'; $mysql_dump = '/usr/local/bin/mysqldump';
} }
// create temporary .cnf file
$cnffilename = "/tmp/froxlor_dump.cnf";
$dumpcnf = "[mysqldump]" . PHP_EOL . "password=\"" . $this->_data['mysql_root_pass'] . "\"" . PHP_EOL;
file_put_contents($cnffilename, $dumpcnf);
if ($do_backup) { if ($do_backup) {
$command = $mysql_dump . " " . $this->_data['mysql_database'] . " -u " . $this->_data['mysql_root_user'] . " --password='" . $this->_data['mysql_root_pass'] . "' --result-file=" . $filename; $command = $mysql_dump . " --defaults-extra-file=" . $cnffilename . " " . escapeshellarg($this->_data['mysql_database']) . " -u " . escapeshellarg($this->_data['mysql_root_user']) . " --result-file=" . $filename;
$output = exec($command); $output = [];
if (stristr($output, "error")) { exec($command, $output);
@unlink($cnffilename);
if (stristr(implode(" ", $output), "error") || ! file_exists($filename)) {
$content .= $this->_status_message('red', $this->_lng['install']['backup_failed']); $content .= $this->_status_message('red', $this->_lng['install']['backup_failed']);
$this->_abort = true;
} else { } else {
$content .= $this->_status_message('green', 'OK (' . $filename . ')'); $content .= $this->_status_message('green', 'OK (' . $filename . ')');
} }
} else { } else {
$content .= $this->_status_message('red', $this->_lng['install']['backup_binary_missing']); $content .= $this->_status_message('red', $this->_lng['install']['backup_binary_missing']);
$this->_abort = true;
} }
} else {
$content .= $this->_status_message('red', $this->_lng['install']['db_exists']);
$this->_abort = true;
}
} else {
$content .= $content .= $this->_status_message('green', 'OK');
} }
return $content; return $content;
@@ -758,7 +855,7 @@ class FroxlorInstall
} }
// language selection // language selection
$language_options = ''; $language_options = '';
foreach ($this->_languages as $language_name => $language_file) { foreach ($this->_languages as $language_file => $language_name) {
$language_options .= \Froxlor\UI\HTML::makeoption($language_name, $language_file, $this->_activelng, true, true); $language_options .= \Froxlor\UI\HTML::makeoption($language_name, $language_file, $this->_activelng, true, true);
} }
// get language-form-template // get language-form-template
@@ -775,6 +872,8 @@ class FroxlorInstall
$formdata .= $this->_getSectionItemString('mysql_host', true); $formdata .= $this->_getSectionItemString('mysql_host', true);
// database // database
$formdata .= $this->_getSectionItemString('mysql_database', true); $formdata .= $this->_getSectionItemString('mysql_database', true);
// database overwrite if exists?
$formdata .= $this->_getSectionItemYesNo('mysql_forcecreate', false);
// unpriv-user has to be different from root // unpriv-user has to be different from root
if ($this->_data['mysql_unpriv_user'] == $this->_data['mysql_root_user']) { if ($this->_data['mysql_unpriv_user'] == $this->_data['mysql_root_user']) {
$style = 'blue'; $style = 'blue';
@@ -804,6 +903,9 @@ class FroxlorInstall
} }
$formdata .= $this->_getSectionItemString('mysql_root_pass', true, $style, 'password'); $formdata .= $this->_getSectionItemString('mysql_root_pass', true, $style, 'password');
$formdata .= $this->_getSectionItemString('mysql_ssl_ca_file', false, $style);
$formdata .= $this->_getSectionItemYesNo('mysql_ssl_verify_server_certificate', false, $style);
/** /**
* admin data * admin data
*/ */
@@ -833,6 +935,37 @@ class FroxlorInstall
*/ */
$section = $this->_lng['install']['serversettings']; $section = $this->_lng['install']['serversettings'];
eval("\$formdata .= \"" . $this->_getTemplate("datasection") . "\";"); eval("\$formdata .= \"" . $this->_getTemplate("datasection") . "\";");
// distribution
if (! empty($_POST['installstep']) && $this->_data['distribution'] == '') {
$diststyle = 'color:red;';
} else {
$diststyle = '';
}
// show list of available distro's
$distributions_select_data = [];
$distros = glob(\Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . '/lib/configfiles/') . '*.xml');
foreach ($distros as $_distribution) {
$dist = new \Froxlor\Config\ConfigParser($_distribution);
$dist_display = $dist->distributionName . " " . $dist->distributionCodename . " (" . $dist->distributionVersion . ")";
if (!array_key_exists($dist_display, $distributions_select_data)) {
$distributions_select_data[$dist_display] = '';
}
$distributions_select_data[$dist_display] .= str_replace(".xml", "", strtolower(basename($_distribution)));
}
// sort by distribution name
ksort($distributions_select_data);
$distributions_select = '';
foreach ($distributions_select_data as $dist_display => $dist_index) {
// create select-box-option
$distributions_select .= \Froxlor\UI\HTML::makeoption($dist_display, $dist_index, $this->_data['distribution'] ?? '');
// $this->_data['distribution']
}
$formdata .= $this->_getSectionItemSelectbox('distribution', $distributions_select, $diststyle);
// servername // servername
if (! empty($_POST['installstep']) && $this->_data['servername'] == '') { if (! empty($_POST['installstep']) && $this->_data['servername'] == '') {
$style = 'color:red;'; $style = 'color:red;';
@@ -854,12 +987,12 @@ class FroxlorInstall
$websrvstyle = ''; $websrvstyle = '';
} }
// apache // apache
$formdata .= $this->_getSectionItemCheckbox('apache2', ($this->_data['webserver'] == 'apache2'), $websrvstyle); $formdata .= $this->_getSectionItemCheckbox('webserver', 'apache2', ($this->_data['webserver'] == 'apache2'), $websrvstyle);
$formdata .= $this->_getSectionItemCheckbox('apache24', ($this->_data['webserver'] == 'apache24'), $websrvstyle); $formdata .= $this->_getSectionItemCheckbox('webserver', 'apache24', ($this->_data['webserver'] == 'apache24'), $websrvstyle);
// lighttpd // lighttpd
$formdata .= $this->_getSectionItemCheckbox('lighttpd', ($this->_data['webserver'] == 'lighttpd'), $websrvstyle); $formdata .= $this->_getSectionItemCheckbox('webserver', 'lighttpd', ($this->_data['webserver'] == 'lighttpd'), $websrvstyle);
// nginx // nginx
$formdata .= $this->_getSectionItemCheckbox('nginx', ($this->_data['webserver'] == 'nginx'), $websrvstyle); $formdata .= $this->_getSectionItemCheckbox('webserver', 'nginx', ($this->_data['webserver'] == 'nginx'), $websrvstyle);
// webserver-user // webserver-user
if (! empty($_POST['installstep']) && $this->_data['httpuser'] == '') { if (! empty($_POST['installstep']) && $this->_data['httpuser'] == '') {
$style = 'color:red;'; $style = 'color:red;';
@@ -911,7 +1044,7 @@ class FroxlorInstall
} }
/** /**
* generate form radio field for webserver-selection * generate form radio field
* *
* @param string $fieldname * @param string $fieldname
* @param boolean $checked * @param boolean $checked
@@ -919,8 +1052,9 @@ class FroxlorInstall
* *
* @return string * @return string
*/ */
private function _getSectionItemCheckbox($fieldname = null, $checked = false, $style = "") private function _getSectionItemCheckbox($groupname = null, $fieldname = null, $checked = false, $style = "")
{ {
$groupname = $this->_lng['install'][$groupname];
$fieldlabel = $this->_lng['install'][$fieldname]; $fieldlabel = $this->_lng['install'][$fieldname];
if ($checked) { if ($checked) {
$checked = 'checked="checked"'; $checked = 'checked="checked"';
@@ -930,6 +1064,24 @@ class FroxlorInstall
return $sectionitem; return $sectionitem;
} }
/**
* generate form selectbox
*
* @param string $fieldname
* @param boolean $options
* @param string $style
*
* @return string
*/
private function _getSectionItemSelectbox($fieldname = null, $options = null, $style = "")
{
$fieldlabel = $this->_lng['install'][$fieldname];
$sectionitem = "";
eval("\$sectionitem .= \"" . $this->_getTemplate("dataitemselect") . "\";");
return $sectionitem;
}
/** /**
* generate form checkbox field * generate form checkbox field
* *
@@ -964,11 +1116,11 @@ class FroxlorInstall
// check for correct php version // check for correct php version
$content .= $this->_status_message('begin', $this->_lng['requirements']['phpversion']); $content .= $this->_status_message('begin', $this->_lng['requirements']['phpversion']);
if (version_compare("7.0.0", PHP_VERSION, ">=")) { if (version_compare("7.1.0", PHP_VERSION, ">=")) {
$content .= $this->_status_message('red', $this->_lng['requirements']['notfound'] . ' (' . PHP_VERSION . ')'); $content .= $this->_status_message('red', $this->_lng['requirements']['notfound'] . ' (' . PHP_VERSION . ')');
$_die = true; $_die = true;
} else { } else {
if (version_compare("7.1.0", PHP_VERSION, ">=")) { if (version_compare("7.4.0", PHP_VERSION, ">=")) {
$content .= $this->_status_message('orange', $this->_lng['requirements']['newerphpprefered'] . ' (' . PHP_VERSION . ')'); $content .= $this->_status_message('orange', $this->_lng['requirements']['newerphpprefered'] . ' (' . PHP_VERSION . ')');
} else { } else {
$content .= $this->_status_message('green', PHP_VERSION); $content .= $this->_status_message('green', PHP_VERSION);
@@ -1234,10 +1386,12 @@ class FroxlorInstall
// from form // from form
if (! empty($_POST['serverip'])) { if (! empty($_POST['serverip'])) {
$this->_data['serverip'] = $_POST['serverip']; $this->_data['serverip'] = $_POST['serverip'];
$this->_data['serverip'] = inet_ntop(inet_pton($this->_data['serverip']));
return; return;
// from $_SERVER // from $_SERVER
} elseif (! empty($_SERVER['SERVER_ADDR'])) { } elseif (! empty($_SERVER['SERVER_ADDR'])) {
$this->_data['serverip'] = $_SERVER['SERVER_ADDR']; $this->_data['serverip'] = $_SERVER['SERVER_ADDR'];
$this->_data['serverip'] = inet_ntop(inet_pton($this->_data['serverip']));
return; return;
} }
// empty // empty
@@ -1266,6 +1420,49 @@ class FroxlorInstall
} }
} }
/**
* get/guess linux distribution
*/
private function _guessDistribution()
{
// post
if (! empty($_POST['distribution'])) {
$this->_data['distribution'] = $_POST['distribution'];
} else {
// set default os.
$os_dist = array(
'ID' => 'buster'
);
$os_version = array(
'0' => '10'
);
// read os-release
if (file_exists('/etc/os-release')) {
$os_dist_content = file_get_contents('/etc/os-release');
$os_dist_arr = explode("\n", $os_dist_content);
$os_dist = [];
foreach ($os_dist_arr as $os_dist_line) {
if (empty(trim($os_dist_line))) continue;
$tmp = explode("=", $os_dist_line);
$os_dist[$tmp[0]] = str_replace('"', "", trim($tmp[1]));
}
if (is_array($os_dist) && array_key_exists('ID', $os_dist) && array_key_exists('VERSION_ID', $os_dist)) {
$os_version = explode('.', $os_dist['VERSION_ID'])[0];
}
}
$distros = glob(\Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . '/lib/configfiles/') . '*.xml');
foreach ($distros as $_distribution) {
$dist = new \Froxlor\Config\ConfigParser($_distribution);
$ver = explode('.', $dist->distributionVersion)[0];
if (strtolower($os_dist['ID']) == strtolower($dist->distributionName) && $os_version == $ver) {
$this->_data['distribution'] = str_replace(".xml", "", strtolower(basename($_distribution)));
}
}
}
}
/** /**
* check if POST field is set and get value for the * check if POST field is set and get value for the
* internal data array, if not set use either '' or $default if != null * internal data array, if not set use either '' or $default if != null

View File

@@ -30,6 +30,7 @@
*/ */
function showUpdateStep($task = null, $needs_status = true) function showUpdateStep($task = null, $needs_status = true)
{ {
set_time_limit(30);
if (! $needs_status) if (! $needs_status)
echo "<b>"; echo "<b>";
@@ -41,7 +42,6 @@ function showUpdateStep($task = null, $needs_status = true)
} }
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, $task); \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, $task);
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, $task);
} }
/** /**
@@ -82,7 +82,6 @@ function lastStepStatus($status = -1, $message = '')
if ($status == - 1 || $status == 2) { if ($status == - 1 || $status == 2) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, 'Attention - last update task failed!!!'); \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, 'Attention - last update task failed!!!');
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, 'Attention - last update task failed!!!');
} elseif ($status == 0 || $status == 1) { } elseif ($status == 0 || $status == 1) {
\Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, 'Success'); \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, 'Success');
} }

View File

@@ -22,8 +22,8 @@ $lng['requirements']['not_true'] = 'no';
$lng['requirements']['notfound'] = 'not found'; $lng['requirements']['notfound'] = 'not found';
$lng['requirements']['notinstalled'] = 'not installed'; $lng['requirements']['notinstalled'] = 'not installed';
$lng['requirements']['activated'] = 'enabled'; $lng['requirements']['activated'] = 'enabled';
$lng['requirements']['phpversion'] = 'PHP version >= 7.0'; $lng['requirements']['phpversion'] = 'PHP version >= 7.1';
$lng['requirements']['newerphpprefered'] = 'Good, but php-7.1 is prefered.'; $lng['requirements']['newerphpprefered'] = 'Good, but php-7.4 is preferred.';
$lng['requirements']['phppdo'] = 'PHP PDO extension and PDO-MySQL driver...'; $lng['requirements']['phppdo'] = 'PHP PDO extension and PDO-MySQL driver...';
$lng['requirements']['phpsession'] = 'PHP session-extension...'; $lng['requirements']['phpsession'] = 'PHP session-extension...';
$lng['requirements']['phpctype'] = 'PHP ctype-extension...'; $lng['requirements']['phpctype'] = 'PHP ctype-extension...';
@@ -39,7 +39,7 @@ $lng['requirements']['phpjson'] = 'PHP json-extension...';
$lng['requirements']['bcmathdescription'] = 'Traffic-calculation related functions will not work correctly!'; $lng['requirements']['bcmathdescription'] = 'Traffic-calculation related functions will not work correctly!';
$lng['requirements']['zipdescription'] = 'The auto-update feature requires the zip extension.'; $lng['requirements']['zipdescription'] = 'The auto-update feature requires the zip extension.';
$lng['requirements']['openbasedir'] = 'open_basedir...'; $lng['requirements']['openbasedir'] = 'open_basedir...';
$lng['requirements']['openbasedirenabled'] = 'Froxlor will not work properly with open_basedir enabled. Please disable open_basedir for Froxlor in the coresponding php.ini'; $lng['requirements']['openbasedirenabled'] = 'Froxlor will not work properly with open_basedir enabled. Please disable open_basedir for Froxlor in the corresponding php.ini';
$lng['requirements']['mysqldump'] = 'MySQL dump tool'; $lng['requirements']['mysqldump'] = 'MySQL dump tool';
$lng['requirements']['mysqldumpmissing'] = 'Automatic backup of possible existing database is not possible. Please install mysql-client tools'; $lng['requirements']['mysqldumpmissing'] = 'Automatic backup of possible existing database is not possible. Please install mysql-client tools';
$lng['requirements']['diedbecauseofrequirements'] = 'Cannot install Froxlor without these requirements! Try to fix them and retry.'; $lng['requirements']['diedbecauseofrequirements'] = 'Cannot install Froxlor without these requirements! Try to fix them and retry.';
@@ -53,16 +53,20 @@ $lng['install']['welcometext'] = 'Thank you for choosing Froxlor. Please fill ou
$lng['install']['database'] = 'Database connection'; $lng['install']['database'] = 'Database connection';
$lng['install']['mysql_host'] = 'MySQL-Hostname'; $lng['install']['mysql_host'] = 'MySQL-Hostname';
$lng['install']['mysql_database'] = 'Database name'; $lng['install']['mysql_database'] = 'Database name';
$lng['install']['mysql_forcecreate'] = 'Backup and overwrite database if exists?';
$lng['install']['mysql_unpriv_user'] = 'Username for the unprivileged MySQL-account'; $lng['install']['mysql_unpriv_user'] = 'Username for the unprivileged MySQL-account';
$lng['install']['mysql_unpriv_pass'] = 'Password for the unprivileged MySQL-account'; $lng['install']['mysql_unpriv_pass'] = 'Password for the unprivileged MySQL-account';
$lng['install']['mysql_root_user'] = 'Username for the MySQL-root-account'; $lng['install']['mysql_root_user'] = 'Username for the MySQL-root-account';
$lng['install']['mysql_root_pass'] = 'Password for the MySQL-root-account'; $lng['install']['mysql_root_pass'] = 'Password for the MySQL-root-account';
$lng['install']['mysql_ssl_ca_file'] = 'MySQL server certificate file path';
$lng['install']['mysql_ssl_verify_server_certificate'] = 'Verify MySQL TLS certificate';
$lng['install']['admin_account'] = 'Administrator Account'; $lng['install']['admin_account'] = 'Administrator Account';
$lng['install']['admin_user'] = 'Administrator Username'; $lng['install']['admin_user'] = 'Administrator Username';
$lng['install']['admin_pass1'] = 'Administrator Password'; $lng['install']['admin_pass1'] = 'Administrator Password';
$lng['install']['admin_pass2'] = 'Administrator-Password (confirm)'; $lng['install']['admin_pass2'] = 'Administrator-Password (confirm)';
$lng['install']['activate_newsfeed'] = 'Enable the official newsfeed<br><small>(https://inside.froxlor.org/news/)</small>'; $lng['install']['activate_newsfeed'] = 'Enable the official newsfeed<br><small>(https://inside.froxlor.org/news/)</small>';
$lng['install']['serversettings'] = 'Server settings'; $lng['install']['serversettings'] = 'Server settings';
$lng['install']['distribution'] = 'Distribution';
$lng['install']['servername'] = 'Server name (FQDN, no ip-address)'; $lng['install']['servername'] = 'Server name (FQDN, no ip-address)';
$lng['install']['serverip'] = 'Server IP'; $lng['install']['serverip'] = 'Server IP';
$lng['install']['webserver'] = 'Webserver'; $lng['install']['webserver'] = 'Webserver';
@@ -78,6 +82,8 @@ $lng['install']['testing_mysql_fail'] = 'There seems to be a problem with the da
$lng['install']['backup_old_db'] = 'Creating backup of old database...'; $lng['install']['backup_old_db'] = 'Creating backup of old database...';
$lng['install']['backup_binary_missing'] = 'Could not find mysqldump'; $lng['install']['backup_binary_missing'] = 'Could not find mysqldump';
$lng['install']['backup_failed'] = 'Could not backup database'; $lng['install']['backup_failed'] = 'Could not backup database';
$lng['install']['check_db_exists'] = 'Checking database...';
$lng['install']['db_exists'] = 'Unable to create database. A database with the same name exists and should not be overwritten';
$lng['install']['prepare_db'] = 'Preparing database...'; $lng['install']['prepare_db'] = 'Preparing database...';
$lng['install']['create_mysqluser_and_db'] = 'Creating database and username...'; $lng['install']['create_mysqluser_and_db'] = 'Creating database and username...';
$lng['install']['testing_new_db'] = 'Testing if database and user have been created correctly...'; $lng['install']['testing_new_db'] = 'Testing if database and user have been created correctly...';
@@ -86,7 +92,7 @@ $lng['install']['changing_data'] = 'Adjusting settings...';
$lng['install']['creating_entries'] = 'Inserting new values...'; $lng['install']['creating_entries'] = 'Inserting new values...';
$lng['install']['adding_admin_user'] = 'Creating admin-account...'; $lng['install']['adding_admin_user'] = 'Creating admin-account...';
$lng['install']['creating_configfile'] = 'Creating configfile...'; $lng['install']['creating_configfile'] = 'Creating configfile...';
$lng['install']['creating_configfile_temp'] = 'File was saved in /tmp/userdata.inc.php, please move to ' . dirname(dirname(__DIR__)) . '/lib/.'; $lng['install']['creating_configfile_temp'] = 'File was saved in %s, please move to ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php';
$lng['install']['creating_configfile_failed'] = 'Could not create ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php, please create it manually with the following content:'; $lng['install']['creating_configfile_failed'] = 'Could not create ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php, please create it manually with the following content:';
$lng['install']['froxlor_succ_installed'] = 'Froxlor was installed successfully.'; $lng['install']['froxlor_succ_installed'] = 'Froxlor was installed successfully.';

View File

@@ -22,7 +22,7 @@ $lng['requirements']['not_true'] = 'non';
$lng['requirements']['notfound'] = 'introuvable'; $lng['requirements']['notfound'] = 'introuvable';
$lng['requirements']['notinstalled'] = 'non installé'; $lng['requirements']['notinstalled'] = 'non installé';
$lng['requirements']['activated'] = 'activé'; $lng['requirements']['activated'] = 'activé';
$lng['requirements']['phpversion'] = 'PHP version >= 7.0'; $lng['requirements']['phpversion'] = 'PHP version >= 7.1';
$lng['requirements']['phppdo'] = 'extension PHP PDO et pilote PDO-MySQL ...'; $lng['requirements']['phppdo'] = 'extension PHP PDO et pilote PDO-MySQL ...';
$lng['requirements']['phpxml'] = 'extension PHP XML...'; $lng['requirements']['phpxml'] = 'extension PHP XML...';
$lng['requirements']['phpfilter'] = 'extension PHP filter ...'; $lng['requirements']['phpfilter'] = 'extension PHP filter ...';
@@ -53,6 +53,7 @@ $lng['install']['admin_user'] = 'Nom d\'utilisateur administrateur';
$lng['install']['admin_pass1'] = 'Mot de passe administrateur'; $lng['install']['admin_pass1'] = 'Mot de passe administrateur';
$lng['install']['admin_pass2'] = 'Mot de passe administrateur (confirmez)'; $lng['install']['admin_pass2'] = 'Mot de passe administrateur (confirmez)';
$lng['install']['serversettings'] = 'Réglages serveur'; $lng['install']['serversettings'] = 'Réglages serveur';
$lng['install']['distribution'] = 'Distribution';
$lng['install']['servername'] = 'Nom du serveur (FQDN, pas d\'adresse IP)'; $lng['install']['servername'] = 'Nom du serveur (FQDN, pas d\'adresse IP)';
$lng['install']['serverip'] = 'Adresse IP du serveur'; $lng['install']['serverip'] = 'Adresse IP du serveur';
$lng['install']['webserver'] = 'Serveur Web'; $lng['install']['webserver'] = 'Serveur Web';
@@ -76,7 +77,7 @@ $lng['install']['changing_data'] = 'Ajustement des paramètres...';
$lng['install']['creating_entries'] = 'Insertion des nouvelles valeurs...'; $lng['install']['creating_entries'] = 'Insertion des nouvelles valeurs...';
$lng['install']['adding_admin_user'] = 'Création du compte administrateur...'; $lng['install']['adding_admin_user'] = 'Création du compte administrateur...';
$lng['install']['creating_configfile'] = 'Création du fichier de configuration...'; $lng['install']['creating_configfile'] = 'Création du fichier de configuration...';
$lng['install']['creating_configfile_temp'] = 'Le fichier a été enregistré dans /tmp/userdata.inc.php, merci de le déplacer dans ' . dirname(dirname(__DIR__)) . '/lib/.'; $lng['install']['creating_configfile_temp'] = 'Le fichier a été enregistré dans %s, merci de le déplacer dans ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php';
$lng['install']['creating_configfile_failed'] = 'Impossible de créer ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php, merci de le créer manuellement avec le contenu suivant:'; $lng['install']['creating_configfile_failed'] = 'Impossible de créer ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php, merci de le créer manuellement avec le contenu suivant:';
$lng['install']['froxlor_succ_installed'] = 'Froxlor a été installé avec succès.'; $lng['install']['froxlor_succ_installed'] = 'Froxlor a été installé avec succès.';

View File

@@ -22,8 +22,8 @@ $lng['requirements']['not_true'] = 'nein';
$lng['requirements']['notfound'] = 'nicht gefunden'; $lng['requirements']['notfound'] = 'nicht gefunden';
$lng['requirements']['notinstalled'] = 'nicht installiert'; $lng['requirements']['notinstalled'] = 'nicht installiert';
$lng['requirements']['activated'] = 'ist aktiviert.'; $lng['requirements']['activated'] = 'ist aktiviert.';
$lng['requirements']['phpversion'] = 'PHP Version >= 7.0'; $lng['requirements']['phpversion'] = 'PHP Version >= 7.1';
$lng['requirements']['newerphpprefered'] = 'Passt, aber php-7.1 wird bevorzugt.'; $lng['requirements']['newerphpprefered'] = 'Passt, aber php-7.4 wird bevorzugt.';
$lng['requirements']['phppdo'] = 'PHP PDO Erweiterung und PDO-MySQL Treiber...'; $lng['requirements']['phppdo'] = 'PHP PDO Erweiterung und PDO-MySQL Treiber...';
$lng['requirements']['phpsession'] = 'PHP session-Erweiterung...'; $lng['requirements']['phpsession'] = 'PHP session-Erweiterung...';
$lng['requirements']['phpctype'] = 'PHP ctype-Erweiterung...'; $lng['requirements']['phpctype'] = 'PHP ctype-Erweiterung...';
@@ -53,16 +53,20 @@ $lng['install']['welcometext'] = 'Vielen Dank dass Sie sich für Froxlor entschi
$lng['install']['database'] = 'Datenbankverbindung'; $lng['install']['database'] = 'Datenbankverbindung';
$lng['install']['mysql_host'] = 'MySQL-Hostname'; $lng['install']['mysql_host'] = 'MySQL-Hostname';
$lng['install']['mysql_database'] = 'Datenbank Name'; $lng['install']['mysql_database'] = 'Datenbank Name';
$lng['install']['mysql_forcecreate'] = 'Datenbank sichern und überschreiben wenn vorhanden?';
$lng['install']['mysql_unpriv_user'] = 'Benutzername für den unprivilegierten MySQL-Account'; $lng['install']['mysql_unpriv_user'] = 'Benutzername für den unprivilegierten MySQL-Account';
$lng['install']['mysql_unpriv_pass'] = 'Passwort für den unprivilegierten MySQL-Account'; $lng['install']['mysql_unpriv_pass'] = 'Passwort für den unprivilegierten MySQL-Account';
$lng['install']['mysql_root_user'] = 'Benutzername für den MySQL-Root-Account'; $lng['install']['mysql_root_user'] = 'Benutzername für den MySQL-Root-Account';
$lng['install']['mysql_root_pass'] = 'Passwort für den MySQL-Root-Account'; $lng['install']['mysql_root_pass'] = 'Passwort für den MySQL-Root-Account';
$lng['install']['mysql_ssl_ca_file'] = 'MySQL-Server Zertifikatspfad';
$lng['install']['mysql_ssl_verify_server_certificate'] = 'Validieren des MySQL-Server Zertifikats';
$lng['install']['admin_account'] = 'Admin-Zugang'; $lng['install']['admin_account'] = 'Admin-Zugang';
$lng['install']['admin_user'] = 'Administrator-Benutzername'; $lng['install']['admin_user'] = 'Administrator-Benutzername';
$lng['install']['admin_pass1'] = 'Administrator-Passwort'; $lng['install']['admin_pass1'] = 'Administrator-Passwort';
$lng['install']['admin_pass2'] = 'Administrator-Passwort (Bestätigung)'; $lng['install']['admin_pass2'] = 'Administrator-Passwort (Bestätigung)';
$lng['install']['activate_newsfeed'] = 'Aktiviere das offizielle Newsfeed<br><small>(https://inside.froxlor.org/news/)</small>'; $lng['install']['activate_newsfeed'] = 'Aktiviere das offizielle Newsfeed<br><small>(https://inside.froxlor.org/news/)</small>';
$lng['install']['serversettings'] = 'Servereinstellungen'; $lng['install']['serversettings'] = 'Servereinstellungen';
$lng['install']['distribution'] = 'Distribution';
$lng['install']['servername'] = 'Servername (FQDN, keine IP-Adresse)'; $lng['install']['servername'] = 'Servername (FQDN, keine IP-Adresse)';
$lng['install']['serverip'] = 'Server-IP'; $lng['install']['serverip'] = 'Server-IP';
$lng['install']['webserver'] = 'Webserver'; $lng['install']['webserver'] = 'Webserver';
@@ -78,6 +82,8 @@ $lng['install']['testing_mysql_fail'] = 'Bei der Verwendung der Datenbank gibt e
$lng['install']['backup_old_db'] = 'Sicherung vorheriger Datenbank...'; $lng['install']['backup_old_db'] = 'Sicherung vorheriger Datenbank...';
$lng['install']['backup_binary_missing'] = 'Konnte mysqldump nicht finden'; $lng['install']['backup_binary_missing'] = 'Konnte mysqldump nicht finden';
$lng['install']['backup_failed'] = 'Sicherung fehlgeschlagen'; $lng['install']['backup_failed'] = 'Sicherung fehlgeschlagen';
$lng['install']['check_db_exists'] = 'Databenbank wird geprüft...';
$lng['install']['db_exists'] = 'Datenbank kann nicht erstellt werden. Eine Datenbank mit dem selben Namen existiert bereits und soll nicht überschrieben werden.';
$lng['install']['prepare_db'] = 'Datenbank wird vorbereitet...'; $lng['install']['prepare_db'] = 'Datenbank wird vorbereitet...';
$lng['install']['create_mysqluser_and_db'] = 'Erstelle Datenbank und Benutzer...'; $lng['install']['create_mysqluser_and_db'] = 'Erstelle Datenbank und Benutzer...';
$lng['install']['testing_new_db'] = 'Teste, ob Datenbank und Benutzer korrekt angelegt wurden...'; $lng['install']['testing_new_db'] = 'Teste, ob Datenbank und Benutzer korrekt angelegt wurden...';
@@ -86,7 +92,7 @@ $lng['install']['changing_data'] = 'Einstellungen anpassen...';
$lng['install']['creating_entries'] = 'Trage neue Werte ein...'; $lng['install']['creating_entries'] = 'Trage neue Werte ein...';
$lng['install']['adding_admin_user'] = 'Erstelle Admin-Benutzer...'; $lng['install']['adding_admin_user'] = 'Erstelle Admin-Benutzer...';
$lng['install']['creating_configfile'] = 'Erstelle Konfigurationsdatei...'; $lng['install']['creating_configfile'] = 'Erstelle Konfigurationsdatei...';
$lng['install']['creating_configfile_temp'] = 'Datei wurde in /tmp/userdata.inc.php gespeichert, bitte nach ' . dirname(dirname(__DIR__)) . '/lib/ verschieben.'; $lng['install']['creating_configfile_temp'] = 'Datei wurde in %s gespeichert, bitte nach ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php verschieben.';
$lng['install']['creating_configfile_failed'] = 'Konnte ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php nicht erstellen, bitte manuell mit folgendem Inhalt anlegen:'; $lng['install']['creating_configfile_failed'] = 'Konnte ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php nicht erstellen, bitte manuell mit folgendem Inhalt anlegen:';
$lng['install']['froxlor_succ_installed'] = 'Froxlor wurde erfolgreich installiert.'; $lng['install']['froxlor_succ_installed'] = 'Froxlor wurde erfolgreich installiert.';

View File

@@ -1,4 +1,4 @@
<p> <p>
<label for="{$fieldname}" class="install-block {$style}">{$this->_lng['install']['webserver']} {$fieldlabel}:</label> <label for="{$fieldname}" class="install-block {$style}">{$groupname} {$fieldlabel}:</label>
<input type="radio" name="webserver" id="{$fieldname}" value="{$fieldname}" {$checked} /><span>{$fieldlabel}</span> <input type="radio" name="{$groupname}" id="{$fieldname}" value="{$fieldname}" {$checked} /><span>{$fieldlabel}</span>
</p> </p>

View File

@@ -0,0 +1,6 @@
<p>
<label for="{$fieldname}" class="install-block {$style}">{$fieldlabel}:</label>
<select name="{$fieldname}" id="{$fieldname}" class="dropdown">
{$options}
</select>
</p>

View File

@@ -1,6 +1,7 @@
<?php <?php
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\Validate\Validate;
/** /**
* This file is part of the Froxlor project. * This file is part of the Froxlor project.
@@ -359,3 +360,596 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.0')) {
showUpdateStep("Updating from 0.10.0 to 0.10.1 final", false); showUpdateStep("Updating from 0.10.0 to 0.10.1 final", false);
\Froxlor\Froxlor::updateToVersion('0.10.1'); \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');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.4')) {
showUpdateStep("Updating from 0.10.4 to 0.10.5", false);
\Froxlor\Froxlor::updateToVersion('0.10.5');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201910200')) {
showUpdateStep("Optimizing customer and admin table for size");
// ALTER TABLE `panel_customers` CHANGE `name` `name` VARCHAR(250) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '';
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE `zipcode` `zipcode` varchar(25) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE `phone` `phone` varchar(50) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE `fax` `fax` varchar(50) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE `def_language` `def_language` varchar(100) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE `theme` `theme` varchar(50) NOT NULL default 'Sparkle';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE `data_2fa` `data_2fa` varchar(25) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE `def_language` `def_language` varchar(100) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` DROP `leaccount`;");
Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` CHANGE `def_language` `def_language` varchar(100) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` CHANGE `theme` `theme` varchar(50) NOT NULL default 'Sparkle';");
Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` CHANGE `data_2fa` `data_2fa` varchar(25) NOT NULL default '';");
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201911130');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.5')) {
showUpdateStep("Updating from 0.10.5 to 0.10.6", false);
\Froxlor\Froxlor::updateToVersion('0.10.6');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201911130')) {
showUpdateStep("Adding new settings for domain edit form default values");
Settings::AddNew("system.apply_specialsettings_default", '1');
Settings::AddNew("system.apply_phpconfigs_default", '1');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201911220');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.6')) {
showUpdateStep("Updating from 0.10.6 to 0.10.7", false);
\Froxlor\Froxlor::updateToVersion('0.10.7');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.7')) {
showUpdateStep("Updating from 0.10.7 to 0.10.8", false);
\Froxlor\Froxlor::updateToVersion('0.10.8');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.8')) {
showUpdateStep("Updating from 0.10.8 to 0.10.9", false);
\Froxlor\Froxlor::updateToVersion('0.10.9');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201911220')) {
showUpdateStep("Adding enhanced SSL control over domains");
// customer domains
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `ssl_enabled` tinyint(1) DEFAULT '1';");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `ssl_honorcipherorder` tinyint(1) DEFAULT '0' AFTER `ssl_enabled`;");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `ssl_sessiontickets` tinyint(1) DEFAULT '1' AFTER `ssl_honorcipherorder`;");
// as setting for froxlor vhost
Settings::AddNew("system.honorcipherorder", '0');
Settings::AddNew("system.sessiontickets", '1');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201912100');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.9')) {
showUpdateStep("Updating from 0.10.9 to 0.10.10", false);
\Froxlor\Froxlor::updateToVersion('0.10.10');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201912100')) {
showUpdateStep("Adding option to disable SSL sessiontickets for older systems");
Settings::AddNew("system.sessionticketsenabled", '1');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201912310');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201912310')) {
showUpdateStep("Adding custom phpfpm pool configuration field");
Database::query("ALTER TABLE `" . TABLE_PANEL_FPMDAEMONS . "` ADD `custom_config` text AFTER `limit_extensions`;");
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201912311');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.10')) {
showUpdateStep("Updating from 0.10.10 to 0.10.11", false);
\Froxlor\Froxlor::updateToVersion('0.10.11');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201912311')) {
showUpdateStep("Migrate logfiles_format setting");
$current_format = Settings::Set('system.logfiles_format');
if (! empty($current_format)) {
Settings::Set('system.logfiles_format', '"' . Settings::Get('system.logfiles_format') . '"');
lastStepStatus(0);
} else {
lastStepStatus(0, 'not needed');
}
\Froxlor\Froxlor::updateToDbVersion('201912312');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201912312')) {
showUpdateStep("Adding option change awstats LogFormat");
Settings::AddNew("system.awstats_logformat", '1');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201912313');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.11')) {
showUpdateStep("Updating from 0.10.11 to 0.10.12", false);
\Froxlor\Froxlor::updateToVersion('0.10.12');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.12')) {
showUpdateStep("Updating from 0.10.12 to 0.10.13", false);
\Froxlor\Froxlor::updateToVersion('0.10.13');
}
if (\Froxlor\Froxlor::isDatabaseVersion('201912313')) {
showUpdateStep("Adding new field to domains table");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `domain_ace` varchar(255) NOT NULL default '' AFTER `domain`;");
lastStepStatus(0);
showUpdateStep("Updating domain entries");
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `domain_ace` = :ace WHERE `id` = :domainid");
$sel_stmt = Database::prepare("SELECT id, domain FROM `" . TABLE_PANEL_DOMAINS . "` ORDER BY id ASC");
Database::pexecute($sel_stmt);
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
while ($domain = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
Database::pexecute($upd_stmt, [
'ace' => $idna_convert->decode($domain['domain']),
'domainid' => $domain['id']
]);
}
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202002290');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.13')) {
showUpdateStep("Updating from 0.10.13 to 0.10.14", false);
\Froxlor\Froxlor::updateToVersion('0.10.14');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.14')) {
showUpdateStep("Updating from 0.10.14 to 0.10.15", false);
\Froxlor\Froxlor::updateToVersion('0.10.15');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202002290')) {
showUpdateStep("Adding new setting to validate DNS when using Let's Encrypt");
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'system' AND `varname` = 'disable_le_selfcheck'");
$le_domain_dnscheck = isset($_POST['system_le_domain_dnscheck']) ? (int) $_POST['system_le_domain_dnscheck'] : '1';
Settings::AddNew("system.le_domain_dnscheck", $le_domain_dnscheck);
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202004140');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.15')) {
showUpdateStep("Updating from 0.10.15 to 0.10.16", false);
\Froxlor\Froxlor::updateToVersion('0.10.16');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202004140')) {
showUpdateStep("Adding unique key on domainid field in domain ssl table");
// check for duplicate entries prior to set a unique key to avoid errors on update
Database::query("
DELETE a.* FROM domain_ssl_settings AS a
LEFT JOIN domain_ssl_settings AS b ON
((b.`domainid`=a.`domainid` AND UNIX_TIMESTAMP(b.`expirationdate`) > UNIX_TIMESTAMP(a.`expirationdate`))
OR (UNIX_TIMESTAMP(b.`expirationdate`) = UNIX_TIMESTAMP(a.`expirationdate`) AND b.`id`>a.`id`))
WHERE b.`id` IS NOT NULL
");
Database::query("ALTER TABLE `domain_ssl_settings` ADD UNIQUE(`domainid`)");
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202005150');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.16')) {
showUpdateStep("Updating from 0.10.16 to 0.10.17", false);
\Froxlor\Froxlor::updateToVersion('0.10.17');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.17')) {
showUpdateStep("Updating from 0.10.17 to 0.10.18", false);
\Froxlor\Froxlor::updateToVersion('0.10.18');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.18')) {
showUpdateStep("Updating from 0.10.18 to 0.10.19", false);
\Froxlor\Froxlor::updateToVersion('0.10.19');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202005150')) {
showUpdateStep("Add new performance indexes", true);
Database::query("ALTER TABLE panel_customers ADD INDEX guid (guid);");
Database::query("ALTER TABLE panel_tasks ADD INDEX type (type);");
Database::query("ALTER TABLE mail_users ADD INDEX username (username);");
Database::query("ALTER TABLE mail_users ADD INDEX imap (imap);");
Database::query("ALTER TABLE mail_users ADD INDEX pop3 (pop3);");
Database::query("ALTER TABLE ftp_groups ADD INDEX gid (gid);");
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202007240');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.19')) {
showUpdateStep("Updating from 0.10.19 to 0.10.20", false);
\Froxlor\Froxlor::updateToVersion('0.10.20');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202007240')) {
showUpdateStep("Removing old unused table", true);
Database::query("DROP TABLE IF EXISTS `panel_diskspace_admins`;");
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202009070');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.20')) {
showUpdateStep("Updating from 0.10.20 to 0.10.21", false);
\Froxlor\Froxlor::updateToVersion('0.10.21');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.21')) {
showUpdateStep("Adding settings for ssl-vhost default content if not updated from db-version 201910110", true);
Settings::AddNew("system.default_sslvhostconf", '');
lastStepStatus(0);
showUpdateStep("Updating from 0.10.21 to 0.10.22", false);
\Froxlor\Froxlor::updateToVersion('0.10.22');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.22')) {
showUpdateStep("Updating from 0.10.22 to 0.10.23", false);
\Froxlor\Froxlor::updateToVersion('0.10.23');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.23')) {
showUpdateStep("Updating from 0.10.23 to 0.10.23.1", false);
\Froxlor\Froxlor::updateToVersion('0.10.23.1');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202009070')) {
showUpdateStep("Adding setting to hide incompatible settings", true);
Settings::AddNew("system.hide_incompatible_settings", '0');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202012300');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202012300')) {
showUpdateStep("Adding setting for DKIM private key extension/suffix", true);
Settings::AddNew("dkim.privkeysuffix", '.priv');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202101200');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.23.1')) {
showUpdateStep("Updating from 0.10.23.1 to 0.10.24", false);
\Froxlor\Froxlor::updateToVersion('0.10.24');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202101200')) {
showUpdateStep("Adding setting for mail address used in SOA records", true);
Settings::AddNew("system.soaemail", '');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202102200');
}
/*
* skip due to potential "1118 Row size too large" error
*
if (\Froxlor\Froxlor::isDatabaseVersion('202102200')) {
showUpdateStep("Add new description fields to mail and domain table", true);
Database::query("ALTER TABLE panel_domains ADD `description` varchar(255) NOT NULL DEFAULT '' AFTER `ssl_sessiontickets`;");
Database::query("ALTER TABLE mail_virtual ADD `description` varchar(255) NOT NULL DEFAULT '' AFTER `iscatchall`");
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202103030');
}
*/
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.24')) {
showUpdateStep("Updating from 0.10.24 to 0.10.25", false);
\Froxlor\Froxlor::updateToVersion('0.10.25');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202102200') || \Froxlor\Froxlor::isDatabaseVersion('202103030')) {
showUpdateStep("Refactoring columns from large tables", true);
Database::query("ALTER TABLE panel_domains CHANGE `ssl_protocols` `ssl_protocols` varchar(255) NOT NULL DEFAULT '';");
Database::query("ALTER TABLE panel_domains CHANGE `ssl_cipher_list` `ssl_cipher_list` varchar(500) NOT NULL DEFAULT '';");
Database::query("ALTER TABLE panel_domains CHANGE `tlsv13_cipher_list` `tlsv13_cipher_list` varchar(500) NOT NULL DEFAULT '';");
lastStepStatus(0);
showUpdateStep("Add new description fields to mail and domain table", true);
$result = Database::query("DESCRIBE `panel_domains`");
$columnfound = 0;
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
if ($row['Field'] == 'description') {
$columnfound = 1;
}
}
if (! $columnfound) {
Database::query("ALTER TABLE panel_domains ADD `description` varchar(255) NOT NULL DEFAULT '' AFTER `ssl_sessiontickets`;");
}
$result = Database::query("DESCRIBE `mail_virtual`");
$columnfound = 0;
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
if ($row['Field'] == 'description') {
$columnfound = 1;
}
}
if (! $columnfound) {
Database::query("ALTER TABLE mail_virtual ADD `description` varchar(255) NOT NULL DEFAULT '' AFTER `iscatchall`");
}
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202103110');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202103110')) {
showUpdateStep("Adding settings for imprint, terms of use and privacy policy URLs", true);
Settings::AddNew("panel.imprint_url", '');
Settings::AddNew("panel.terms_url", '');
Settings::AddNew("panel.privacy_url", '');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202103240');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.25')) {
showUpdateStep("Updating from 0.10.25 to 0.10.26", false);
\Froxlor\Froxlor::updateToVersion('0.10.26');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202103240')) {
showUpdateStep("Adding setting for default serveralias value for new domains", true);
Settings::AddNew("system.domaindefaultalias", '0');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202106160');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202106160')) {
showUpdateStep("Adjusting Let's Encrypt endpoint configuration to support ZeroSSL", true);
if (Settings::Get('system.letsencryptca') == 'testing') {
Settings::Set("system.letsencryptca", 'letsencrypt_test');
} else {
Settings::Set("system.letsencryptca", 'letsencrypt');
}
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202106270');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202106270')) {
showUpdateStep("Adding custom logo image settings", true);
Settings::AddNew("panel.logo_image_header", '');
Settings::AddNew("panel.logo_image_login", '');
lastStepStatus(0);
// Migrating old custom logo over, if exists
$custom_logo_file_old = \Froxlor\Froxlor::getInstallDir() . '/templates/Sparkle/assets/img/logo_custom.png';
if (file_exists($custom_logo_file_old)) {
showUpdateStep("Migrating existing custom logo to new settings", true);
$path = \Froxlor\Froxlor::getInstallDir().'/img/';
if (!is_dir($path) && !mkdir($path, 0775)) {
throw new \Exception("img directory does not exist and cannot be created");
}
if (!is_writable($path)) {
if (!chmod($path, '0775')) {
throw new \Exception("Cannot write to img directory");
}
}
// Save as new custom logo header
$save_to = 'logo_header.png';
copy($custom_logo_file_old, $path.$save_to);
Settings::Set("panel.logo_image_header", "img/{$save_to}?v=".time());
// Save as new custom logo login
$save_to = 'logo_login.png';
copy($custom_logo_file_old, $path.$save_to);
Settings::Set("panel.logo_image_login", "img/{$save_to}?v=".time());
lastStepStatus(0);
}
\Froxlor\Froxlor::updateToDbVersion('202107070');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.26')) {
showUpdateStep("Updating from 0.10.26 to 0.10.27", false);
\Froxlor\Froxlor::updateToVersion('0.10.27');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202107070')) {
showUpdateStep("Adding settings to overwrite theme- or custom theme-logo with the new logo settings", true);
Settings::AddNew("panel.logo_overridetheme", '0');
Settings::AddNew("panel.logo_overridecustom", '0');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202107200');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202107200')) {
showUpdateStep("Adding settings to define default value of 'create std-subdomain' when creating a customer", true);
Settings::AddNew("system.createstdsubdom_default", '1');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202107210');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202107210')) {
showUpdateStep("Normalizing ipv6 for correct comparison", true);
$result_stmt = Database::prepare("
SELECT `id`, `ip` FROM `" . TABLE_PANEL_IPSANDPORTS . "`"
);
Database::pexecute($result_stmt);
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_IPSANDPORTS . "` SET `ip` = :ip WHERE `id` = :id");
while ($iprow = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
if (Validate::is_ipv6($iprow['ip'])) {
$ip = inet_ntop(inet_pton($iprow['ip']));
Database::pexecute($upd_stmt, [
'ip' => $ip,
'id' => $iprow['id']
]);
}
}
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202107260');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202107260')) {
showUpdateStep("Removing setting for search-engine allow yes/no", true);
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'panel' AND `varname` = 'no_robots'");
lastStepStatus(0);
showUpdateStep("Adding setting to have all froxlor customers in a local group", true);
Settings::AddNew("system.froxlorusergroup", '');
Settings::AddNew("system.froxlorusergroup_gid", '');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202107300');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202107300')) {
showUpdateStep("Adds the possibility to select the PowerDNS Operation Mode", true);
Settings::AddNew("system.powerdns_mode", 'Native');
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202108180');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.27')) {
showUpdateStep("Updating from 0.10.27 to 0.10.28", false);
\Froxlor\Froxlor::updateToVersion('0.10.28');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202108180')) {
showUpdateStep("Adding czech language file", true);
Database::query("INSERT INTO `" . TABLE_PANEL_LANGUAGE . "` SET `language` = '&#268;esk&aacute; republika', `iso` = 'cs', `file` = 'lng/czech.lng.php'");
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('202109040');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.28')) {
showUpdateStep("Updating from 0.10.28 to 0.10.29", false);
\Froxlor\Froxlor::updateToVersion('0.10.29');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.29')) {
showUpdateStep("Updating from 0.10.29 to 0.10.29.1", false);
\Froxlor\Froxlor::updateToVersion('0.10.29.1');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.29.1')) {
showUpdateStep("Updating from 0.10.29.1 to 0.10.30", false);
\Froxlor\Froxlor::updateToVersion('0.10.30');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.30')) {
showUpdateStep("Updating from 0.10.30 to 0.10.31", false);
\Froxlor\Froxlor::updateToVersion('0.10.31');
}

View File

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

View File

@@ -19,7 +19,7 @@
* Function getPreConfig * Function getPreConfig
* *
* outputs various content before the update process * outputs various content before the update process
* can be continued (askes for agreement whatever is being asked) * can be continued (asks for agreement whatever is being asked)
* *
* @param string $current_version * @param string $current_version
* @param int $current_db_version * @param int $current_db_version
@@ -34,6 +34,9 @@ function getPreConfig($current_version, $current_db_version)
include_once \Froxlor\FileDir::makeCorrectFile(dirname(__FILE__) . '/preconfig/0.9/preconfig_0.9.inc.php'); include_once \Froxlor\FileDir::makeCorrectFile(dirname(__FILE__) . '/preconfig/0.9/preconfig_0.9.inc.php');
parseAndOutputPreconfig($has_preconfig, $return, $current_version, $current_db_version); parseAndOutputPreconfig($has_preconfig, $return, $current_version, $current_db_version);
include_once \Froxlor\FileDir::makeCorrectFile(dirname(__FILE__) . '/preconfig/0.10/preconfig_0.10.inc.php');
parseAndOutputPreconfig2($has_preconfig, $return, $current_version, $current_db_version);
$return .= '<br /><br />' . \Froxlor\UI\HTML::makecheckbox('update_changesagreed', '<strong>I have read the update notifications above and I am aware of the changes made to my system.</strong>', '1', true, '0', true); $return .= '<br /><br />' . \Froxlor\UI\HTML::makecheckbox('update_changesagreed', '<strong>I have read the update notifications above and I am aware of the changes made to my system.</strong>', '1', true, '0', true);
$return .= '</div>'; $return .= '</div>';
$return .= '<input type="hidden" name="update_preconfig" value="1" />'; $return .= '<input type="hidden" name="update_preconfig" value="1" />';

View File

@@ -0,0 +1,42 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Updater
*
*/
/**
* checks if the new-version has some updating to do
*
* @param boolean $has_preconfig
* pointer to check if any preconfig has to be output
* @param string $return
* pointer to output string
* @param string $current_version
* current froxlor version
*
* @return null
*/
function parseAndOutputPreconfig2(&$has_preconfig, &$return, $current_version, $current_db_version)
{
global $lng;
if (versionInUpdate($current_db_version, '202004140')) {
$has_preconfig = true;
$description = 'Froxlor can now optionally validate the dns entries of domains that request Lets Encrypt certificates to reduce dns-related problems (e.g. freshly registered domain or updated a-record).<br />';
$question = '<strong>Validate DNS of domains when using Lets Encrypt&nbsp;';
$question .= \Froxlor\UI\HTML::makeyesno('system_le_domain_dnscheck', '1', '0', '1');
eval("\$return.=\"" . \Froxlor\UI\Template::getTemplate("update/preconfigitem") . "\";");
}
}

View File

@@ -414,7 +414,7 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
if (Settings::Get('system.webserver') == 'apache2') { if (Settings::Get('system.webserver') == 'apache2') {
$has_preconfig = true; $has_preconfig = true;
$description = 'Froxlor now supports the new Apache 2.4. Please be aware that you need to load additional apache-modules in ordner to use it.<br />'; $description = 'Froxlor now supports the new Apache 2.4. Please be aware that you need to load additional apache-modules in order to use it.<br />';
$description .= '<pre>LoadModule authz_core_module modules/mod_authz_core.so $description .= '<pre>LoadModule authz_core_module modules/mod_authz_core.so
LoadModule authz_host_module modules/mod_authz_host.so</pre><br />'; LoadModule authz_host_module modules/mod_authz_host.so</pre><br />';
$question = '<strong>Do you want to enable the Apache-2.4 modification?:</strong>&nbsp;'; $question = '<strong>Do you want to enable the Apache-2.4 modification?:</strong>&nbsp;';
@@ -600,8 +600,8 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
if (versionInUpdate($current_version, '0.9.32-rc2')) { if (versionInUpdate($current_version, '0.9.32-rc2')) {
$has_preconfig = true; $has_preconfig = true;
$description = 'To customize the command which executes the cronjob (php - basically) change the path below according to your system.<br /><br />'; $description = 'To customize the command which executes the cronjob (php - basically) change the path below according to your system.<br /><br />';
$question = '<strong>Please specify the command to execute cronscripts</strong> (default: "/usr/bin/nice -n 5 /usr/bin/php5 -q")<br />'; $question = '<strong>Please specify the command to execute cronscripts</strong> (default: "/usr/bin/nice -n 5 /usr/bin/php -q")<br />';
$question .= '<input type="text" class="text" name="croncmdline" value="/usr/bin/nice -n 5 /usr/bin/php5 -q" /><br />'; $question .= '<input type="text" class="text" name="croncmdline" value="/usr/bin/nice -n 5 /usr/bin/php -q" /><br />';
eval("\$return.=\"" . \Froxlor\UI\Template::getTemplate("update/preconfigitem") . "\";"); eval("\$return.=\"" . \Froxlor\UI\Template::getTemplate("update/preconfigitem") . "\";");
} }

4
js/html5shiv.min.js vendored
View File

@@ -1,4 +1,4 @@
/** /**
* @preserve HTML5 Shiv 3.7.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
*/ */
!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.2",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b)}(this,document); !function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document);

4
js/jquery.min.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -54,6 +54,13 @@ abstract class ApiCommand extends ApiParameter
*/ */
private $mail = null; private $mail = null;
/**
* whether the call is an internal one or not
*
* @var boolean
*/
private $internal_call = false;
/** /**
* language strings array * language strings array
* *
@@ -90,10 +97,12 @@ abstract class ApiCommand extends ApiParameter
* optional, array of parameters (var=>value) for the command * optional, array of parameters (var=>value) for the command
* @param array $userinfo * @param array $userinfo
* optional, passed via WebInterface (instead of $header) * optional, passed via WebInterface (instead of $header)
* @param boolean $internal
* optional whether called internally, default false
* *
* @throws \Exception * @throws \Exception
*/ */
public function __construct($header = null, $params = null, $userinfo = null) public function __construct($header = null, $params = null, $userinfo = null, $internal = false)
{ {
parent::__construct($params); parent::__construct($params);
@@ -127,6 +136,9 @@ abstract class ApiCommand extends ApiParameter
if ($this->debug) { if ($this->debug) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::LOG_ERROR, LOG_DEBUG, "[API] " . get_called_class() . ": " . json_encode($params, JSON_UNESCAPED_SLASHES)); $this->logger()->logAction(\Froxlor\FroxlorLogger::LOG_ERROR, LOG_DEBUG, "[API] " . get_called_class() . ": " . json_encode($params, JSON_UNESCAPED_SLASHES));
} }
// set internal call flag
$this->internal_call = $internal;
} }
/** /**
@@ -191,13 +203,15 @@ abstract class ApiCommand extends ApiParameter
* array of user-data * array of user-data
* @param array $params * @param array $params
* array of parameters for the command * array of parameters for the command
* @param boolean $internal
* optional whether called internally, default false
* *
* @return ApiCommand * @return ApiCommand
* @throws \Exception * @throws \Exception
*/ */
public static function getLocal($userinfo = null, $params = null) public static function getLocal($userinfo = null, $params = null, $internal = false)
{ {
return new static(null, $params, $userinfo); return new static(null, $params, $userinfo, $internal);
} }
/** /**
@@ -210,6 +224,16 @@ abstract class ApiCommand extends ApiParameter
return $this->is_admin; return $this->is_admin;
} }
/**
* internal call flag
*
* @return boolean
*/
protected function isInternal()
{
return $this->internal_call;
}
/** /**
* return field from user-table * return field from user-table
* *
@@ -232,6 +256,173 @@ abstract class ApiCommand extends ApiParameter
return $this->user_data; return $this->user_data;
} }
/**
* return SQL when parameter $sql_search is given via API
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param array $query_fields
* optional array of placeholders mapped to the actual value which is used in the API commands when executing the statement [internal]
* @param boolean $append
* optional append to WHERE clause rather then create new one, default false [internal]
*
* @return string
*/
protected function getSearchWhere(&$query_fields = array(), $append = false)
{
$search = $this->getParam('sql_search', true, array());
$condition = '';
if (! empty($search)) {
if ($append == true) {
$condition = ' AND ';
} else {
$condition = ' WHERE ';
}
$ops = array(
'<',
'>',
'='
);
$first = true;
foreach ($search as $field => $valoper) {
$cleanfield = str_replace(".", "", $field);
$sortfield = explode('.', $field);
foreach ($sortfield as $id => $sfield) {
if (substr($sfield, - 1, 1) != '`') {
$sfield .= '`';
}
if ($sfield[0] != '`') {
$sfield = '`' . $sfield;
}
$sortfield[$id] = $sfield;
}
$field = implode('.', $sortfield);
if (! $first) {
$condition .= ' AND ';
}
if (! is_array($valoper) || ! isset($valoper['op']) || empty($valoper['op'])) {
$condition .= $field . ' LIKE :' . $cleanfield;
if (! is_array($valoper)) {
$query_fields[':' . $cleanfield] = '%' . $valoper . '%';
} else {
$query_fields[':' . $cleanfield] = '%' . $valoper['value'] . '%';
}
} elseif (in_array($valoper['op'], $ops)) {
$condition .= $field . ' ' . $valoper['op'] . ':' . $cleanfield;
$query_fields[':' . $cleanfield] = $valoper['value'] ?? '';
} elseif (strtolower($valoper['op']) == 'in' && is_array($valoper['value']) && count($valoper['value']) > 0) {
$condition .= $field . ' ' . $valoper['op'] . ' (';
foreach ($valoper['value'] as $incnt => $invalue) {
$condition .= ":" . $cleanfield . $incnt . ", ";
$query_fields[':' . $cleanfield . $incnt] = $invalue ?? '';
}
$condition = substr($condition, 0, - 2) . ')';
} else {
continue;
}
if ($first) {
$first = false;
}
}
}
return $condition;
}
/**
* return LIMIT clause when at least $sql_limit parameter is given via API
*
* @param int $sql_limit
* optional, limit resultset, default 0
* @param int $sql_offset
* optional, offset for limitation, default 0
*
* @return string
*/
protected function getLimit()
{
$limit = $this->getParam('sql_limit', true, 0);
$offset = $this->getParam('sql_offset', true, 0);
if (! is_numeric($limit)) {
$limit = 0;
}
if (! is_numeric($offset)) {
$offset = 0;
}
if ($limit > 0) {
return ' LIMIT ' . $offset . ',' . $limit;
}
return '';
}
/**
* return ORDER BY clause if parameter $sql_orderby parameter is given via API
*
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC
* @param boolean $append
* optional append to ORDER BY clause rather then create new one, default false [internal]
*
* @return string
*/
protected function getOrderBy($append = false)
{
$orderby = $this->getParam('sql_orderby', true, array());
$order = "";
if (! empty($orderby)) {
if ($append) {
$order .= ", ";
} else {
$order .= " ORDER BY ";
}
$nat_fields = [
'`c`.`loginname`',
'`a`.`loginname`',
'`adminname`',
'`databasename`',
'`username`'
];
foreach ($orderby as $field => $by) {
$sortfield = explode('.', $field);
foreach ($sortfield as $id => $sfield) {
if (substr($sfield, - 1, 1) != '`') {
$sfield .= '`';
}
if ($sfield[0] != '`') {
$sfield = '`' . $sfield;
}
$sortfield[$id] = $sfield;
}
$field = implode('.', $sortfield);
$by = strtoupper($by);
if (! in_array($by, [
'ASC',
'DESC'
])) {
$by = 'ASC';
}
if (\Froxlor\Settings::Get('panel.natsorting') == 1 && in_array($field, $nat_fields)) {
// Acts similar to php's natsort(), found in one comment at http://my.opera.com/cpr/blog/show.dml/160556
$order .= "CONCAT( IF( ASCII( LEFT( " . $field . ", 5 ) ) > 57,
LEFT( " . $field . ", 1 ), 0 ),
IF( ASCII( RIGHT( " . $field . ", 1 ) ) > 57,
LPAD( " . $field . ", 255, '0' ),
LPAD( CONCAT( " . $field . ", '-' ), 255, '0' )
)) " . $by . ", ";
} else {
$order .= $field . " " . $by . ", ";
}
}
$order = substr($order, 0, - 2);
}
return $order;
}
/** /**
* return logger instance * return logger instance
* *
@@ -257,15 +448,18 @@ abstract class ApiCommand extends ApiParameter
* *
* @param string $command * @param string $command
* @param array|null $params * @param array|null $params
* @param boolean $internal
* optional whether called internally, default false
*
* *
* @return array * @return array
*/ */
protected function apiCall($command = null, $params = null) protected function apiCall($command = null, $params = null, $internal = false)
{ {
$_command = explode(".", $command); $_command = explode(".", $command);
$module = __NAMESPACE__ . "\Commands\\" . $_command[0]; $module = __NAMESPACE__ . "\Commands\\" . $_command[0];
$function = $_command[1]; $function = $_command[1];
$json_result = $module::getLocal($this->getUserData(), $params)->{$function}(); $json_result = $module::getLocal($this->getUserData(), $params, $internal)->{$function}();
return json_decode($json_result, true)['data']; return json_decode($json_result, true)['data'];
} }
@@ -331,7 +525,7 @@ abstract class ApiCommand extends ApiParameter
$customer_ids[] = $customer['customerid']; $customer_ids[] = $customer['customerid'];
} }
} else { } else {
if (! empty($customer_hide_option) && \Froxlor\Settings::IsInList('panel.customer_hide_options', $customer_hide_option)) { if (! $this->isInternal() && ! empty($customer_hide_option) && \Froxlor\Settings::IsInList('panel.customer_hide_options', $customer_hide_option)) {
throw new \Exception("You cannot access this resource", 405); throw new \Exception("You cannot access this resource", 405);
} }
$customer_ids = array( $customer_ids = array(
@@ -423,8 +617,12 @@ abstract class ApiCommand extends ApiParameter
"group" => $group, "group" => $group,
"var" => $varname "var" => $varname
), true, true); ), true, true);
$content = $default;
if ($result) {
$content = $result['value'] ?? $default;
}
// @fixme html_entity_decode // @fixme html_entity_decode
$content = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result['value'] != '') ? $result['value'] : $default), $replace_arr)); $content = html_entity_decode(\Froxlor\PhpHelper::replaceVariables($content, $replace_arr));
return $content; return $content;
} }

View File

@@ -25,6 +25,15 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
/** /**
* lists all admin entries * lists all admin entries
* *
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin * @access admin
* @throws \Exception * @throws \Exception
* @return string json-encoded array count|list * @return string json-encoded array count|list
@@ -33,17 +42,16 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
{ {
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) { if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list admins"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list admins");
$query_fields = array();
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT * SELECT *
FROM `" . TABLE_PANEL_ADMINS . "` FROM `" . TABLE_PANEL_ADMINS . "`" . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit());
ORDER BY `loginname` ASC Database::pexecute($result_stmt, $query_fields, true, true);
");
Database::pexecute($result_stmt, null, true, true);
$result = array(); $result = array();
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row; $result[] = $row;
} }
return $this->response(200, "successfull", array( return $this->response(200, "successful", array(
'count' => count($result), 'count' => count($result),
'list' => $result 'list' => $result
)); ));
@@ -51,6 +59,28 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
/**
* returns the total number of admins for the given admin
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_admins
FROM `" . TABLE_PANEL_ADMINS . "`
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successful", $result['num_admins']);
}
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/** /**
* return an admin entry by either id or loginname * return an admin entry by either id or loginname
* *
@@ -79,7 +109,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$result = Database::pexecute_first($result_stmt, $params, true, true); $result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) { if ($result) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get admin '" . $result['loginname'] . "'"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get admin '" . $result['loginname'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
$key = ($id > 0 ? "id #" . $id : "loginname '" . $loginname . "'"); $key = ($id > 0 ? "id #" . $id : "loginname '" . $loginname . "'");
throw new \Exception("Admin with " . $key . " could not be found", 404); throw new \Exception("Admin with " . $key . " could not be found", 404);
@@ -201,7 +231,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$idna_convert = new \Froxlor\Idna\IdnaWrapper(); $idna_convert = new \Froxlor\Idna\IdnaWrapper();
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true)); $email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true));
$def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true); $def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true);
$custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', '/^[^\0]*$/', '', array(), true); $custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
if (Settings::Get('system.mail_quota_enabled') != '1') { if (Settings::Get('system.mail_quota_enabled') != '1') {
$email_quota = - 1; $email_quota = - 1;
@@ -235,7 +265,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
'login' => $loginname 'login' => $loginname
), true, true); ), true, true);
if (strtolower($loginname_check['loginname']) == strtolower($loginname) || strtolower($loginname_check_admin['loginname']) == strtolower($loginname)) { if (($loginname_check && strtolower($loginname_check['loginname']) == strtolower($loginname)) || ($loginname_check_admin && strtolower($loginname_check_admin['loginname']) == strtolower($loginname))) {
\Froxlor\UI\Response::standard_error('loginnameexists', $loginname, true); \Froxlor\UI\Response::standard_error('loginnameexists', $loginname, true);
} elseif (preg_match('/^' . preg_quote(Settings::Get('customer.accountprefix'), '/') . '([0-9]+)/', $loginname)) { } elseif (preg_match('/^' . preg_quote(Settings::Get('customer.accountprefix'), '/') . '([0-9]+)/', $loginname)) {
// Accounts which match systemaccounts are not allowed, filtering them // Accounts which match systemaccounts are not allowed, filtering them
@@ -334,7 +364,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$result = $this->apiCall('Admins.get', array( $result = $this->apiCall('Admins.get', array(
'id' => $adminid 'id' => $adminid
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
@@ -501,7 +531,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$idna_convert = new \Froxlor\Idna\IdnaWrapper(); $idna_convert = new \Froxlor\Idna\IdnaWrapper();
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true)); $email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true));
$def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true); $def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true);
$custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', '/^[^\0]*$/', '', array(), true); $custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$theme = \Froxlor\Validate\Validate::validate($theme, 'theme', '', '', array(), true); $theme = \Froxlor\Validate\Validate::validate($theme, 'theme', '', '', array(), true);
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
@@ -647,7 +677,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$result = $this->apiCall('Admins.get', array( $result = $this->apiCall('Admins.get', array(
'id' => $result['adminid'] 'id' => $result['adminid']
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
} }
} }
@@ -683,6 +713,10 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
if ($id == $this->getUserDetail('adminid')) { if ($id == $this->getUserDetail('adminid')) {
\Froxlor\UI\Response::standard_error('youcantdeleteyourself', '', true); \Froxlor\UI\Response::standard_error('youcantdeleteyourself', '', true);
} }
// can't delete the first superadmin
if ($id == 1) {
\Froxlor\UI\Response::standard_error('cannotdeletesuperadmin', '', true);
}
// delete admin // delete admin
$del_stmt = Database::prepare(" $del_stmt = Database::prepare("
@@ -700,14 +734,6 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
'adminid' => $id 'adminid' => $id
), true, true); ), true, true);
// delete the diskspace usage
$del_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_DISKSPACE_ADMINS . "` WHERE `adminid` = :adminid
");
Database::pexecute($del_stmt, array(
'adminid' => $id
), true, true);
// set admin-id of the old admin's customer to current admins // set admin-id of the old admin's customer to current admins
$upd_stmt = Database::prepare(" $upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET
@@ -749,7 +775,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted admin '" . $result['loginname'] . "'"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted admin '" . $result['loginname'] . "'");
\Froxlor\User::updateCounters(); \Froxlor\User::updateCounters();
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -791,7 +817,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$result['loginfail_count'] = 0; $result['loginfail_count'] = 0;
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] unlocked admin '" . $result['loginname'] . "'"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] unlocked admin '" . $result['loginname'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }

View File

@@ -0,0 +1,30 @@
<?php
namespace Froxlor\Api\Commands;
use Froxlor\Database\Database;
use Froxlor\Settings;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.0
*
*/
class ApiKeys extends \Froxlor\Api\ApiCommand
{
public function listing()
{}
public function listingCount()
{}
}

View File

@@ -81,7 +81,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
$result = $this->apiCall('Certificates.get', array( $result = $this->apiCall('Certificates.get', array(
'id' => $domain['id'] 'id' => $domain['id']
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Domain '" . $domain['domain'] . "' already has a certificate. Did you mean to call update?", 406); throw new \Exception("Domain '" . $domain['domain'] . "' already has a certificate. Did you mean to call update?", 406);
} }
@@ -122,7 +122,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
if (! $result) { if (! $result) {
throw new \Exception("Domain '" . $domain['domain'] . "' does not have a certificate.", 412); throw new \Exception("Domain '" . $domain['domain'] . "' does not have a certificate.", 412);
} }
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
/** /**
@@ -168,19 +168,28 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
$result = $this->apiCall('Certificates.get', array( $result = $this->apiCall('Certificates.get', array(
'id' => $domain['id'] 'id' => $domain['id']
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
/** /**
* lists all certificate entries * lists all certificate entries
* *
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
* @return string json-encoded array count|list * @return string json-encoded array count|list
*/ */
public function listing() public function listing()
{ {
// select all my (accessable) certificates // select all my (accessible) certificates
$certs_stmt_query = "SELECT s.*, d.domain, d.letsencrypt, c.customerid, c.loginname $certs_stmt_query = "SELECT s.*, d.domain, d.letsencrypt, c.customerid, c.loginname
FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON `d`.`id` = `s`.`domainid` LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON `d`.`id` = `s`.`domainid`
@@ -188,7 +197,53 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
WHERE "; WHERE ";
$qry_params = array(); $qry_params = array();
$query_fields = array();
if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '0') {
// admin with only customer-specific permissions
$certs_stmt_query .= "d.adminid = :adminid ";
$qry_params['adminid'] = $this->getUserDetail('adminid');
} elseif ($this->isAdmin() == false) {
// customer-area
$certs_stmt_query .= "d.customerid = :cid ";
$qry_params['cid'] = $this->getUserDetail('customerid');
} else {
$certs_stmt_query .= "1 ";
}
$certs_stmt = Database::prepare($certs_stmt_query . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
$qry_params = array_merge($qry_params, $query_fields);
Database::pexecute($certs_stmt, $qry_params, true, true);
$result = array();
while ($cert = $certs_stmt->fetch(\PDO::FETCH_ASSOC)) {
// respect froxlor-hostname
if ($cert['domainid'] == 0) {
$cert['domain'] = Settings::Get('system.hostname');
$cert['letsencrypt'] = Settings::Get('system.le_froxlor_enabled');
$cert['loginname'] = 'froxlor.panel';
}
$result[] = $cert;
}
return $this->response(200, "successful", array(
'count' => count($result),
'list' => $result
));
}
/**
* returns the total number of certificates for the given user
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
// select all my (accessible) certificates
$certs_stmt_query = "SELECT COUNT(*) as num_certs
FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON `d`.`id` = `s`.`domainid`
LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` c ON `c`.`customerid` = `d`.`customerid`
WHERE ";
$qry_params = array();
if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '0') { if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '0') {
// admin with only customer-specific permissions // admin with only customer-specific permissions
$certs_stmt_query .= "d.adminid = :adminid "; $certs_stmt_query .= "d.adminid = :adminid ";
@@ -201,21 +256,10 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
$certs_stmt_query .= "1 "; $certs_stmt_query .= "1 ";
} }
$certs_stmt = Database::prepare($certs_stmt_query); $certs_stmt = Database::prepare($certs_stmt_query);
Database::pexecute($certs_stmt, $qry_params, true, true); $result = Database::pexecute_first($certs_stmt, $qry_params, true, true);
$result = array(); if ($result) {
while ($cert = $certs_stmt->fetch(\PDO::FETCH_ASSOC)) { return $this->response(200, "successful", $result['num_certs']);
// respect froxlor-hostname
if ($cert['domainid'] == 0) {
$cert['domain'] = Settings::Get('system.hostname');
$cert['letsencrypt'] = Settings::Get('system.le_froxlor_enabled');
$cert['loginname'] = 'froxlor.panel';
} }
$result[] = $cert;
}
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
} }
/** /**
@@ -232,7 +276,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
if ($this->isAdmin() == false) { if ($this->isAdmin() == false) {
$chk_stmt = Database::prepare(" $chk_stmt = Database::prepare("
SELECT d.domain FROM `" . TABLE_PANEL_DOMAINS . "` d SELECT d.domain, d.letsencrypt FROM `" . TABLE_PANEL_DOMAINS . "` d
LEFT JOIN `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s ON s.domainid = d.id LEFT JOIN `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s ON s.domainid = d.id
WHERE s.`id` = :id AND d.`customerid` = :cid WHERE s.`id` = :id AND d.`customerid` = :cid
"); ");
@@ -242,7 +286,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
)); ));
} elseif ($this->isAdmin()) { } elseif ($this->isAdmin()) {
$chk_stmt = Database::prepare(" $chk_stmt = Database::prepare("
SELECT d.domain FROM `" . TABLE_PANEL_DOMAINS . "` d SELECT d.domain, d.letsencrypt FROM `" . TABLE_PANEL_DOMAINS . "` d
LEFT JOIN `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s ON s.domainid = d.id LEFT JOIN `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s ON s.domainid = d.id
WHERE s.`id` = :id" . ($this->getUserDetail('customers_see_all') == '0' ? " AND d.`adminid` = :aid" : "")); WHERE s.`id` = :id" . ($this->getUserDetail('customers_see_all') == '0' ? " AND d.`adminid` = :aid" : ""));
$params = array( $params = array(
@@ -255,7 +299,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
if ($chk == false && $this->getUserDetail('change_serversettings')) { if ($chk == false && $this->getUserDetail('change_serversettings')) {
// check whether it might be the froxlor-vhost certificate // check whether it might be the froxlor-vhost certificate
$chk_stmt = Database::prepare(" $chk_stmt = Database::prepare("
SELECT \"" . Settings::Get('system.hostname') . "\" as domain FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` SELECT \"" . Settings::Get('system.hostname') . "\" as domain, \"" . Settings::Get('system.le_froxlor_enabled') . "\" as letsencrypt FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
WHERE `id` = :id AND `domainid` = '0'"); WHERE `id` = :id AND `domainid` = '0'");
$params = array( $params = array(
'id' => $id 'id' => $id
@@ -277,13 +321,16 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
Database::pexecute($del_stmt, array( Database::pexecute($del_stmt, array(
'id' => $id 'id' => $id
)); ));
// trigger removing of certificate from acme.sh if let's encrypt
if ($chk['letsencrypt'] == '1') {
\Froxlor\System\Cronjob::inserttask('12', $chk['domain']);
}
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] removed ssl-certificate for '" . $chk['domain'] . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] removed ssl-certificate for '" . $chk['domain'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Unable to determine SSL certificate. Maybe no access?", 406); throw new \Exception("Unable to determine SSL certificate. Maybe no access?", 406);
} }
/** /**
* insert or update certificates entry * insert or update certificates entry
* *

View File

@@ -51,7 +51,7 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE
'id' => $id 'id' => $id
), true, true); ), true, true);
if ($result) { if ($result) {
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("cronjob with id #" . $id . " could not be found", 404); throw new \Exception("cronjob with id #" . $id . " could not be found", 404);
} }
@@ -119,7 +119,7 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE
$result = $this->apiCall('Cronjobs.get', array( $result = $this->apiCall('Cronjobs.get', array(
'id' => $id 'id' => $id
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -127,6 +127,15 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE
/** /**
* lists all cronjob entries * lists all cronjob entries
* *
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin * @access admin
* @throws \Exception * @throws \Exception
* @return string json-encoded array count|list * @return string json-encoded array count|list
@@ -135,15 +144,15 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE
{ {
if ($this->isAdmin()) { if ($this->isAdmin()) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list cronjobs"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list cronjobs");
$query_fields = array();
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT `c`.* FROM `" . TABLE_PANEL_CRONRUNS . "` `c` ORDER BY `module` ASC, `cronfile` ASC SELECT `c`.* FROM `" . TABLE_PANEL_CRONRUNS . "` `c` " . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit());
"); Database::pexecute($result_stmt, $query_fields, true, true);
Database::pexecute($result_stmt);
$result = array(); $result = array();
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row; $result[] = $row;
} }
return $this->response(200, "successfull", array( return $this->response(200, "successful", array(
'count' => count($result), 'count' => count($result),
'list' => $result 'list' => $result
)); ));
@@ -151,6 +160,27 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
/**
* returns the total number of cronjobs
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin()) {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_crons FROM `" . TABLE_PANEL_CRONRUNS . "` `c`
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successful", $result['num_crons']);
}
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/** /**
* You cannot delete system cronjobs. * You cannot delete system cronjobs.
*/ */

View File

@@ -23,7 +23,7 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
{ {
/** /**
* check whether backup is enabled systemwide and if accessable for customer (hide_options) * check whether backup is enabled systemwide and if accessible for customer (hide_options)
* *
* @throws \Exception * @throws \Exception
*/ */
@@ -52,7 +52,9 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
* @param bool $backup_web * @param bool $backup_web
* optional whether to backup web-data, default is 0 (false) * optional whether to backup web-data, default is 0 (false)
* @param int $customerid * @param int $customerid
* required when called as admin, not needed when called as customer * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -109,7 +111,7 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
\Froxlor\System\Cronjob::inserttask('20', $task_data); \Froxlor\System\Cronjob::inserttask('20', $task_data);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added customer-backup job for '" . $customer['loginname'] . "'. Target directory: " . $userpath); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added customer-backup job for '" . $customer['loginname'] . "'. Target directory: " . $userpath);
return $this->response(200, "successfull", $task_data); return $this->response(200, "successful", $task_data);
} }
/** /**
@@ -137,6 +139,14 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
* optional, admin-only, select backup-jobs of a specific customer by id * optional, admin-only, select backup-jobs of a specific customer by id
* @param string $loginname * @param string $loginname
* optional, admin-only, select backup-jobs of a specific customer by loginname * optional, admin-only, select backup-jobs of a specific customer by loginname
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -149,8 +159,9 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
$customer_ids = $this->getAllowedCustomerIds('extras.backup'); $customer_ids = $this->getAllowedCustomerIds('extras.backup');
// check whether there is a backup-job for this customer // check whether there is a backup-job for this customer
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20'"); $query_fields = array();
Database::pexecute($sel_stmt); $sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20'" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
Database::pexecute($sel_stmt, $query_fields, true, true);
$result = array(); $result = array();
while ($entry = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) { while ($entry = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
$entry['data'] = json_decode($entry['data'], true); $entry['data'] = json_decode($entry['data'], true);
@@ -159,12 +170,43 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
} }
} }
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list customer-backups"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list customer-backups");
return $this->response(200, "successfull", array( return $this->response(200, "successful", array(
'count' => count($result), 'count' => count($result),
'list' => $result 'list' => $result
)); ));
} }
/**
* returns the total number of planned backups
*
* @param int $customerid
* optional, admin-only, select backup-jobs of a specific customer by id
* @param string $loginname
* optional, admin-only, select backup-jobs of a specific customer by loginname
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
$this->validateAccess();
$customer_ids = $this->getAllowedCustomerIds('extras.backup');
// check whether there is a backup-job for this customer
$result_count = 0;
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20'");
Database::pexecute($sel_stmt, null, true, true);
while ($entry = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
$entry['data'] = json_decode($entry['data'], true);
if (in_array($entry['data']['customerid'], $customer_ids)) {
$result_count ++;
}
}
return $this->response(200, "successful", $result_count);
}
/** /**
* delete a planned backup-jobs by id, if called from an admin you need to specify the customerid/loginname * delete a planned backup-jobs by id, if called from an admin you need to specify the customerid/loginname
* *
@@ -195,9 +237,9 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
if ($backupjob['id'] == $entry && in_array($backupjob['data']['customerid'], $customer_ids)) { if ($backupjob['id'] == $entry && in_array($backupjob['data']['customerid'], $customer_ids)) {
Database::pexecute($del_stmt, array( Database::pexecute($del_stmt, array(
'tid' => $entry 'tid' => $entry
)); ), true, true);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] deleted planned customer-backup #" . $entry); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] deleted planned customer-backup #" . $entry);
return $this->response(200, "successfull", true); return $this->response(200, "successful", true);
} }
} }
} }

View File

@@ -25,6 +25,17 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
/** /**
* lists all customer entries * lists all customer entries
* *
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
* @param bool $show_usages
* optional, default false
*
* @access admin * @access admin
* @throws \Exception * @throws \Exception
* @return string json-encoded array count|list * @return string json-encoded array count|list
@@ -32,26 +43,67 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
public function listing() public function listing()
{ {
if ($this->isAdmin()) { if ($this->isAdmin()) {
$show_usages = $this->getBoolParam('show_usages', true, false);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list customers"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list customers");
$query_fields = array();
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT `c`.*, `a`.`loginname` AS `adminname` SELECT `c`.*, `a`.`loginname` AS `adminname`
FROM `" . TABLE_PANEL_CUSTOMERS . "` `c`, `" . TABLE_PANEL_ADMINS . "` `a` FROM `" . TABLE_PANEL_CUSTOMERS . "` `c`, `" . TABLE_PANEL_ADMINS . "` `a`
WHERE " . ($this->getUserDetail('customers_see_all') ? '' : " `c`.`adminid` = :adminid AND ") . " WHERE " . ($this->getUserDetail('customers_see_all') ? '' : " `c`.`adminid` = :adminid AND ") . "
`c`.`adminid` = `a`.`adminid` `c`.`adminid` = `a`.`adminid`" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
ORDER BY `c`.`loginname` ASC
");
$params = array(); $params = array();
if ($this->getUserDetail('customers_see_all') == '0') { if ($this->getUserDetail('customers_see_all') == '0') {
$params = array( $params = array(
'adminid' => $this->getUserDetail('adminid') 'adminid' => $this->getUserDetail('adminid')
); );
} }
$params = array_merge($params, $query_fields);
Database::pexecute($result_stmt, $params, true, true); Database::pexecute($result_stmt, $params, true, true);
$result = array(); $result = array();
$domains_stmt = null;
$usages_stmt = null;
if ($show_usages) {
$domains_stmt = Database::prepare("
SELECT COUNT(`id`) AS `domains`
FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `customerid` = :cid
AND `parentdomainid` = '0'
AND `id`<> :stdd
");
$usages_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DISKSPACE . "`
WHERE `customerid` = :cid
ORDER BY `stamp` DESC LIMIT 1
");
}
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
if ($show_usages) {
// get number of domains
Database::pexecute($domains_stmt, array(
'cid' => $row['customerid'],
'stdd' => $row['standardsubdomain']
));
$domains = $domains_stmt->fetch(\PDO::FETCH_ASSOC);
$row['domains'] = intval($domains['domains']);
// get disk-space usages for web, mysql and mail
$usages = Database::pexecute_first($usages_stmt, array(
'cid' => $row['customerid']
));
if ($usages) {
$row['webspace_used'] = $usages['webspace'];
$row['mailspace_used'] = $usages['mail'];
$row['dbspace_used'] = $usages['mysql'];
} else {
$row['webspace_used'] = 0;
$row['mailspace_used'] = 0;
$row['dbspace_used'] = 0;
}
}
$result[] = $row; $result[] = $row;
} }
return $this->response(200, "successfull", array( return $this->response(200, "successful", array(
'count' => count($result), 'count' => count($result),
'list' => $result 'list' => $result
)); ));
@@ -59,6 +111,34 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
/**
* returns the total number of customers for the given admin
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin()) {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_customers
FROM `" . TABLE_PANEL_CUSTOMERS . "`
WHERE " . ($this->getUserDetail('customers_see_all') ? "1" : " `adminid` = :adminid "));
$params = array();
if ($this->getUserDetail('customers_see_all') == '0') {
$params = array(
'adminid' => $this->getUserDetail('adminid')
);
}
$result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) {
return $this->response(200, "successful", $result['num_customers']);
}
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/** /**
* return a customer entry by either id or loginname * return a customer entry by either id or loginname
* *
@@ -66,6 +146,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* optional, the customer-id * optional, the customer-id
* @param string $loginname * @param string $loginname
* optional, the loginname * optional, the loginname
* @param bool $show_usages
* optional, default false
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -76,6 +158,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$id = $this->getParam('id', true, 0); $id = $this->getParam('id', true, 0);
$ln_optional = ($id <= 0 ? false : true); $ln_optional = ($id <= 0 ? false : true);
$loginname = $this->getParam('loginname', $ln_optional, ''); $loginname = $this->getParam('loginname', $ln_optional, '');
$show_usages = $this->getBoolParam('show_usages', true, false);
if ($this->isAdmin()) { if ($this->isAdmin()) {
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
@@ -105,8 +188,42 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
if (! $this->isAdmin() && $result['custom_notes_show'] != 1) { if (! $this->isAdmin() && $result['custom_notes_show'] != 1) {
$result['custom_notes'] = ""; $result['custom_notes'] = "";
} }
if ($show_usages) {
// get number of domains
$domains_stmt = Database::prepare("
SELECT COUNT(`id`) AS `domains`
FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `customerid` = :cid
AND `parentdomainid` = '0'
AND `id`<> :stdd
");
Database::pexecute($domains_stmt, array(
'cid' => $result['customerid'],
'stdd' => $result['standardsubdomain']
));
$domains = $domains_stmt->fetch(\PDO::FETCH_ASSOC);
$result['domains'] = intval($domains['domains']);
// get disk-space usages for web, mysql and mail
$usages_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DISKSPACE . "`
WHERE `customerid` = :cid
ORDER BY `stamp` DESC LIMIT 1
");
$usages = Database::pexecute_first($usages_stmt, array(
'cid' => $result['customerid']
));
if ($usages) {
$result['webspace_used'] = $usages['webspace'];
$result['mailspace_used'] = $usages['mail'];
$result['dbspace_used'] = $usages['mysql'];
} else {
$result['webspace_used'] = 0;
$result['mailspace_used'] = 0;
$result['dbspace_used'] = 0;
}
}
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get customer '" . $result['loginname'] . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get customer '" . $result['loginname'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
$key = ($id > 0 ? "id #" . $id : "loginname '" . $loginname . "'"); $key = ($id > 0 ? "id #" . $id : "loginname '" . $loginname . "'");
throw new \Exception("Customer with " . $key . " could not be found", 404); throw new \Exception("Customer with " . $key . " could not be found", 404);
@@ -146,7 +263,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* optional, whether to show the content of custom_notes to the customer, default 0 (false) * optional, whether to show the content of custom_notes to the customer, default 0 (false)
* @param string $new_loginname * @param string $new_loginname
* optional, if empty generated automatically using customer-prefix and increasing number * optional, if empty generated automatically using customer-prefix and increasing number
* @param string $password * @param string $new_customer_password
* optional, if empty generated automatically and send to the customer's email if $sendpassword is 1 * optional, if empty generated automatically and send to the customer's email if $sendpassword is 1
* @param bool $sendpassword * @param bool $sendpassword
* optional, whether to send the password to the customer after creation, default 0 (false) * optional, whether to send the password to the customer after creation, default 0 (false)
@@ -191,7 +308,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* @param bool $mysqls_ul * @param bool $mysqls_ul
* optional, whether customer should have unlimited mysql-databases, default 0 (false) * optional, whether customer should have unlimited mysql-databases, default 0 (false)
* @param bool $createstdsubdomain * @param bool $createstdsubdomain
* optional, whether to create a standard-subdomain ([loginname].froxlor-hostname.tld), default 0 (false) * optional, whether to create a standard-subdomain ([loginname].froxlor-hostname.tld), default [system.createstdsubdom_default]
* @param bool $phpenabled * @param bool $phpenabled
* optional, whether to allow usage of PHP, default 0 (false) * optional, whether to allow usage of PHP, default 0 (false)
* @param array $allowed_phpconfigs * @param array $allowed_phpconfigs
@@ -199,9 +316,9 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* @param bool $perlenabled * @param bool $perlenabled
* optional, whether to allow usage of Perl/CGI, default 0 (false) * optional, whether to allow usage of Perl/CGI, default 0 (false)
* @param bool $dnsenabled * @param bool $dnsenabled
* optional, wether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false) * optional, whether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false)
* @param bool $logviewenabled * @param bool $logviewenabled
* optional, wether to allow acccess to webserver access/error-logs, default 0 (false) * optional, whether to allow access to webserver access/error-logs, default 0 (false)
* @param bool $store_defaultindex * @param bool $store_defaultindex
* optional, whether to store the default index file to customers homedir * optional, whether to store the default index file to customers homedir
* @param int $hosting_plan_id * @param int $hosting_plan_id
@@ -235,7 +352,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$gender = (int) $this->getParam('gender', true, 0); $gender = (int) $this->getParam('gender', true, 0);
$custom_notes = $this->getParam('custom_notes', true, ''); $custom_notes = $this->getParam('custom_notes', true, '');
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0); $custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
$createstdsubdomain = $this->getBoolParam('createstdsubdomain', true, 0); $createstdsubdomain = $this->getBoolParam('createstdsubdomain', true, Settings::Get('system.createstdsubdom_default'));
$password = $this->getParam('new_customer_password', true, ''); $password = $this->getParam('new_customer_password', true, '');
$sendpassword = $this->getBoolParam('sendpassword', true, 0); $sendpassword = $this->getBoolParam('sendpassword', true, 0);
$store_defaultindex = $this->getBoolParam('store_defaultindex', true, 0); $store_defaultindex = $this->getBoolParam('store_defaultindex', true, 0);
@@ -299,7 +416,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true)); $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); $customernumber = \Froxlor\Validate\Validate::validate($customernumber, 'customer number', '/^[A-Za-z0-9 \-]*$/Di', '', array(), true);
$def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true); $def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true);
$custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', '/^[^\0]*$/', '', array(), true); $custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
if (Settings::Get('system.mail_quota_enabled') != '1') { if (Settings::Get('system.mail_quota_enabled') != '1') {
$email_quota = - 1; $email_quota = - 1;
@@ -374,7 +491,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
), true, true); ), true, true);
$mysql_maxlen = \Froxlor\Database\Database::getSqlUsernameLength() - strlen(Settings::Get('customer.mysqlprefix')); $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)) { if (($loginname_check && strtolower($loginname_check['loginname']) == strtolower($loginname)) || ($loginname_check_admin && strtolower($loginname_check_admin['loginname']) == strtolower($loginname))) {
\Froxlor\UI\Response::standard_error('loginnameexists', $loginname, true); \Froxlor\UI\Response::standard_error('loginnameexists', $loginname, true);
} elseif (! \Froxlor\Validate\Validate::validateUsername($loginname, Settings::Get('panel.unix_names'), $mysql_maxlen)) { } elseif (! \Froxlor\Validate\Validate::validateUsername($loginname, Settings::Get('panel.unix_names'), $mysql_maxlen)) {
if (strlen($loginname) > $mysql_maxlen) { if (strlen($loginname) > $mysql_maxlen) {
@@ -652,6 +769,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'name' => $name, 'name' => $name,
'company' => $company 'company' => $company
)), )),
'CUSTOMER_NO' => $customernumber,
'USERNAME' => $loginname, 'USERNAME' => $loginname,
'PASSWORD' => $password, 'PASSWORD' => $password,
'SERVER_HOSTNAME' => $srv_hostname, 'SERVER_HOSTNAME' => $srv_hostname,
@@ -705,7 +823,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$result = $this->apiCall('Customers.get', array( $result = $this->apiCall('Customers.get', array(
'loginname' => $loginname 'loginname' => $loginname
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("No more resources available", 406); throw new \Exception("No more resources available", 406);
} }
@@ -797,7 +915,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* @param bool $mysqls_ul * @param bool $mysqls_ul
* optional, whether customer should have unlimited mysql-databases, default 0 (false) * optional, whether customer should have unlimited mysql-databases, default 0 (false)
* @param bool $createstdsubdomain * @param bool $createstdsubdomain
* optional, whether to create a standard-subdomain ([loginname].froxlor-hostname.tld), default 0 (false) * optional, whether to create a standard-subdomain ([loginname].froxlor-hostname.tld), default 1 (if customer has std-subdomain) else 0 (false)
* @param bool $phpenabled * @param bool $phpenabled
* optional, whether to allow usage of PHP, default 0 (false) * optional, whether to allow usage of PHP, default 0 (false)
* @param array $allowed_phpconfigs * @param array $allowed_phpconfigs
@@ -805,9 +923,9 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* @param bool $perlenabled * @param bool $perlenabled
* optional, whether to allow usage of Perl/CGI, default 0 (false) * optional, whether to allow usage of Perl/CGI, default 0 (false)
* @param bool $dnsenabled * @param bool $dnsenabled
* optional, ether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false) * optional, whether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false)
* @param bool $logviewenabled * @param bool $logviewenabled
* optional, ether to allow acccess to webserver access/error-logs, default 0 (false) * optional, whether to allow access to webserver access/error-logs, default 0 (false)
* @param string $theme * @param string $theme
* optional, change theme * optional, change theme
* *
@@ -835,7 +953,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$email = $this->getParam('email', true, $idna_convert->decode($result['email'])); $email = $this->getParam('email', true, $idna_convert->decode($result['email']));
$name = $this->getParam('name', true, $result['name']); $name = $this->getParam('name', true, $result['name']);
$firstname = $this->getParam('firstname', true, $result['firstname']); $firstname = $this->getParam('firstname', true, $result['firstname']);
$company_required = (! empty($name) && empty($firstname)) || (empty($name) && ! empty($firstname)) || (empty($name) && empty($firstname)); $company_required = empty($result['company']) && ((! empty($name) && empty($firstname)) || (empty($name) && ! empty($firstname)) || (empty($name) && empty($firstname)));
$company = $this->getParam('company', ($company_required ? false : true), $result['company']); $company = $this->getParam('company', ($company_required ? false : true), $result['company']);
$street = $this->getParam('street', true, $result['street']); $street = $this->getParam('street', true, $result['street']);
$zipcode = $this->getParam('zipcode', true, $result['zipcode']); $zipcode = $this->getParam('zipcode', true, $result['zipcode']);
@@ -861,7 +979,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$email_pop3 = $this->getParam('email_pop3', true, $result['pop3']); $email_pop3 = $this->getParam('email_pop3', true, $result['pop3']);
$ftps = $this->getUlParam('ftps', 'ftps_ul', true, $result['ftps']); $ftps = $this->getUlParam('ftps', 'ftps_ul', true, $result['ftps']);
$mysqls = $this->getUlParam('mysqls', 'mysqls_ul', true, $result['mysqls']); $mysqls = $this->getUlParam('mysqls', 'mysqls_ul', true, $result['mysqls']);
$createstdsubdomain = $this->getBoolParam('createstdsubdomain', true, 0); $createstdsubdomain = $this->getBoolParam('createstdsubdomain', true, ($result['standardsubdomain'] != 0 ? 1 : 0));
$password = $this->getParam('new_customer_password', true, ''); $password = $this->getParam('new_customer_password', true, '');
$phpenabled = $this->getBoolParam('phpenabled', true, $result['phpenabled']); $phpenabled = $this->getBoolParam('phpenabled', true, $result['phpenabled']);
$allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, json_decode($result['allowed_phpconfigs'], true)); $allowed_phpconfigs = $this->getParam('allowed_phpconfigs', true, json_decode($result['allowed_phpconfigs'], true));
@@ -890,7 +1008,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$fax = \Froxlor\Validate\Validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', array(), true); $fax = \Froxlor\Validate\Validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', array(), true);
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true)); $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); $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); $custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
if (! empty($allowed_phpconfigs)) { if (! empty($allowed_phpconfigs)) {
$allowed_phpconfigs = array_map('intval', $allowed_phpconfigs); $allowed_phpconfigs = array_map('intval', $allowed_phpconfigs);
} }
@@ -933,7 +1051,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
} }
if ($this->isAdmin()) { if ($this->isAdmin()) {
if ($createstdsubdomain != '1') { if ($createstdsubdomain != '1' || $deactivated) {
$createstdsubdomain = '0'; $createstdsubdomain = '0';
} }
@@ -987,7 +1105,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
\Froxlor\System\Cronjob::inserttask('1'); \Froxlor\System\Cronjob::inserttask('1');
} }
if ($phpenabled != $result['phpenabled'] || $perlenabled != $result['perlenabled']) { if ($phpenabled != $result['phpenabled'] || $perlenabled != $result['perlenabled'] || $email != $result['email']) {
\Froxlor\System\Cronjob::inserttask('1'); \Froxlor\System\Cronjob::inserttask('1');
} }
@@ -1302,7 +1420,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$result = $this->apiCall('Customers.get', array( $result = $this->apiCall('Customers.get', array(
'id' => $result['customerid'] 'id' => $result['customerid']
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
/** /**
@@ -1372,8 +1490,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'id' => $id 'id' => $id
), true, true); ), true, true);
// first gather all domain-id's to clean up panel_domaintoip and dns-entries accordingly // first gather all domain-id's to clean up panel_domaintoip, dns-entries and certificates accordingly
$did_stmt = Database::prepare("SELECT `id` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :id"); $did_stmt = Database::prepare("SELECT `id`, `domain` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :id");
Database::pexecute($did_stmt, array( Database::pexecute($did_stmt, array(
'id' => $id 'id' => $id
), true, true); ), true, true);
@@ -1388,6 +1506,15 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
Database::pexecute($stmt, array( Database::pexecute($stmt, array(
'did' => $row['id'] 'did' => $row['id']
), true, true); ), true, true);
// remove domain->certificates entries
$stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :did");
Database::pexecute($stmt, array(
'did' => $row['id']
), true, true);
// remove domains DNS from powerDNS if used, #581
\Froxlor\System\Cronjob::inserttask('11', $row['domain']);
// remove domain from acme.sh / lets encrypt if used
\Froxlor\System\Cronjob::inserttask('12', $row['domain']);
} }
// remove customer domains // remove customer domains
$stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :id"); $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :id");
@@ -1530,7 +1657,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
\Froxlor\System\Cronjob::inserttask('10'); \Froxlor\System\Cronjob::inserttask('10');
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted customer '" . $result['loginname'] . "'"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted customer '" . $result['loginname'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -1572,7 +1699,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$result['loginfail_count'] = 0; $result['loginfail_count'] = 0;
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] unlocked customer '" . $result['loginname'] . "'"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] unlocked customer '" . $result['loginname'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -1642,7 +1769,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$result = $this->apiCall('Customers.get', array( $result = $this->apiCall('Customers.get', array(
'id' => $c_result['customerid'] 'id' => $c_result['customerid']
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }

View File

@@ -26,9 +26,9 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* add options for a given directory * add options for a given directory
* *
* @param int $customerid * @param int $customerid
* optional, admin-only, the customer-id * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname * @param string $loginname
* optional, admin-only, the loginname * optional, required when called as admin (if $customerid is not specified)
* @param string $path * @param string $path
* path relative to the customer's home-Directory * path relative to the customer's home-Directory
* @param bool $options_indexes * @param bool $options_indexes
@@ -69,7 +69,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$error500path = $this->getParam('error500path', true, ''); $error500path = $this->getParam('error500path', true, '');
// validation // validation
$path = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Validate\Validate::validate($path, 'path', '', '', array(), true)); $path = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Validate\Validate::validate($path, 'path', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true));
$userpath = $path; $userpath = $path;
$path = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path); $path = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path);
@@ -96,7 +96,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
), true, true); ), true, true);
// duplicate check // duplicate check
if ($path_dupe_check['path'] == $path) { if ($path_dupe_check && $path_dupe_check['path'] == $path) {
\Froxlor\UI\Response::standard_error('errordocpathdupe', $userpath, true); \Froxlor\UI\Response::standard_error('errordocpathdupe', $userpath, true);
} }
@@ -128,7 +128,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$result = $this->apiCall('DirOptions.get', array( $result = $this->apiCall('DirOptions.get', array(
'id' => $id 'id' => $id
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
/** /**
@@ -186,7 +186,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$result = Database::pexecute_first($result_stmt, $params, true, true); $result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) { if ($result) {
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get directory options for '" . $result['path'] . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get directory options for '" . $result['path'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
$key = "id #" . $id; $key = "id #" . $id;
throw new \Exception("Directory option with " . $key . " could not be found", 404); throw new \Exception("Directory option with " . $key . " could not be found", 404);
@@ -198,9 +198,9 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* @param int $id * @param int $id
* id of dir-protection entry * id of dir-protection entry
* @param int $customerid * @param int $customerid
* optional, admin-only, the customer-id * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname * @param string $loginname
* optional, admin-only, the loginname * optional, required when called as admin (if $customerid is not specified)
* @param bool $options_indexes * @param bool $options_indexes
* optional, activate directory-listing for this path, default 0 (false) * optional, activate directory-listing for this path, default 0 (false)
* @param bool $options_cgi * @param bool $options_cgi
@@ -275,7 +275,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$result = $this->apiCall('DirOptions.get', array( $result = $this->apiCall('DirOptions.get', array(
'id' => $id 'id' => $id
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
/** /**
@@ -285,6 +285,14 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* optional, admin-only, select directory-protections of a specific customer by id * optional, admin-only, select directory-protections of a specific customer by id
* @param string $loginname * @param string $loginname
* optional, admin-only, select directory-protections of a specific customer by loginname * optional, admin-only, select directory-protections of a specific customer by loginname
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -298,21 +306,51 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$customer_ids = $this->getAllowedCustomerIds('extras.pathoptions'); $customer_ids = $this->getAllowedCustomerIds('extras.pathoptions');
$result = array(); $result = array();
$query_fields = array();
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_HTACCESS . "` SELECT * FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `customerid` IN (" . implode(', ', $customer_ids) . ") WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
"); Database::pexecute($result_stmt, $query_fields, true, true);
Database::pexecute($result_stmt, null, true, true);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row; $result[] = $row;
} }
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list directory-options"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list directory-options");
return $this->response(200, "successfull", array( return $this->response(200, "successful", array(
'count' => count($result), 'count' => count($result),
'list' => $result 'list' => $result
)); ));
} }
/**
* returns the total number of accessible directory options
*
* @param int $customerid
* optional, admin-only, select directory-protections of a specific customer by id
* @param string $loginname
* optional, admin-only, select directory-protections of a specific customer by loginname
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array count|list
*/
public function listingCount()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) {
throw new \Exception("You cannot access this resource", 405);
}
$customer_ids = $this->getAllowedCustomerIds('extras.pathoptions');
$result = array();
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_htaccess FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successful", $result['num_htaccess']);
}
}
/** /**
* delete a directory-options by id * delete a directory-options by id
* *
@@ -373,10 +411,10 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
Database::pexecute($stmt, array( Database::pexecute($stmt, array(
"customerid" => $customer_data['customerid'], "customerid" => $customer_data['customerid'],
"id" => $id "id" => $id
)); ), true, true);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted directory-option for '" . str_replace($customer_data['documentroot'], '/', $result['path']) . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted directory-option for '" . str_replace($customer_data['documentroot'], '/', $result['path']) . "'");
\Froxlor\System\Cronjob::inserttask('1'); \Froxlor\System\Cronjob::inserttask('1');
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
/** /**

View File

@@ -26,9 +26,9 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
* add htaccess protection to a given directory * add htaccess protection to a given directory
* *
* @param int $customerid * @param int $customerid
* optional, admin-only, the customer-id * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname * @param string $loginname
* optional, admin-only, the loginname * optional, required when called as admin (if $customerid is not specified)
* @param string $path * @param string $path
* @param string $username * @param string $username
* @param string $directory_password * @param string $directory_password
@@ -60,7 +60,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
$authname = $this->getParam('directory_authname', true, ''); $authname = $this->getParam('directory_authname', true, '');
// validation // validation
$path = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Validate\Validate::validate($path, 'path', '', '', array(), true)); $path = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Validate\Validate::validate($path, 'path', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true));
$path = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path); $path = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path);
$username = \Froxlor\Validate\Validate::validate($username, 'username', '/^[a-zA-Z0-9][a-zA-Z0-9\-_]+\$?$/', '', array(), true); $username = \Froxlor\Validate\Validate::validate($username, 'username', '/^[a-zA-Z0-9][a-zA-Z0-9\-_]+\$?$/', '', array(), true);
$authname = \Froxlor\Validate\Validate::validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', array(), true); $authname = \Froxlor\Validate\Validate::validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', array(), true);
@@ -81,7 +81,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
$password_enc = \Froxlor\System\Crypt::makeCryptPassword($password, true); $password_enc = \Froxlor\System\Crypt::makeCryptPassword($password, true);
// duplicate check // duplicate check
if ($username_path_check['username'] == $username && $username_path_check['path'] == $path) { if ($username_path_check && $username_path_check['username'] == $username && $username_path_check['path'] == $path) {
\Froxlor\UI\Response::standard_error('userpathcombinationdupe', '', true); \Froxlor\UI\Response::standard_error('userpathcombinationdupe', '', true);
} elseif ($password == $username) { } elseif ($password == $username) {
\Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true); \Froxlor\UI\Response::standard_error('passwordshouldnotbeusername', '', true);
@@ -111,7 +111,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
$result = $this->apiCall('DirProtections.get', array( $result = $this->apiCall('DirProtections.get', array(
'id' => $id 'id' => $id
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
/** /**
@@ -173,7 +173,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
$result = Database::pexecute_first($result_stmt, $params, true, true); $result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) { if ($result) {
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get directory protection for '" . $result['path'] . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get directory protection for '" . $result['path'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
$key = ($id > 0 ? "id #" . $id : "username '" . $username . "'"); $key = ($id > 0 ? "id #" . $id : "username '" . $username . "'");
throw new \Exception("Directory protection with " . $key . " could not be found", 404); throw new \Exception("Directory protection with " . $key . " could not be found", 404);
@@ -187,9 +187,9 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
* @param string $username * @param string $username
* optional, the username * optional, the username
* @param int $customerid * @param int $customerid
* optional, admin-only, the customer-id * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname * @param string $loginname
* optional, admin-only, the loginname * optional, required when called as admin (if $customerid is not specified)
* @param string $directory_password * @param string $directory_password
* optional, leave empty for no change * optional, leave empty for no change
* @param string $directory_authname * @param string $directory_authname
@@ -258,7 +258,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
$result = $this->apiCall('DirProtections.get', array( $result = $this->apiCall('DirProtections.get', array(
'id' => $result['id'] 'id' => $result['id']
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
/** /**
@@ -268,6 +268,14 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
* optional, admin-only, select directory-protections of a specific customer by id * optional, admin-only, select directory-protections of a specific customer by id
* @param string $loginname * @param string $loginname
* optional, admin-only, select directory-protections of a specific customer by loginname * optional, admin-only, select directory-protections of a specific customer by loginname
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -281,21 +289,51 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
$customer_ids = $this->getAllowedCustomerIds('extras.directoryprotection'); $customer_ids = $this->getAllowedCustomerIds('extras.directoryprotection');
$result = array(); $result = array();
$query_fields = array();
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "` SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "`
WHERE `customerid` IN (" . implode(', ', $customer_ids) . ") WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
"); Database::pexecute($result_stmt, $query_fields, true, true);
Database::pexecute($result_stmt, null, true, true);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row; $result[] = $row;
} }
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list directory-protections"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list directory-protections");
return $this->response(200, "successfull", array( return $this->response(200, "successful", array(
'count' => count($result), 'count' => count($result),
'list' => $result 'list' => $result
)); ));
} }
/**
* returns the total number of accessible directory protections
*
* @param int $customerid
* optional, admin-only, select directory-protections of a specific customer by id
* @param string $loginname
* optional, admin-only, select directory-protections of a specific customer by loginname
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array count|list
*/
public function listingCount()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) {
throw new \Exception("You cannot access this resource", 405);
}
$customer_ids = $this->getAllowedCustomerIds('extras.directoryprotection');
$result = array();
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_htpasswd FROM `" . TABLE_PANEL_HTPASSWDS . "`
WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successful", $result['num_htpasswd']);
}
}
/** /**
* delete a directory-protection by either id or username * delete a directory-protection by either id or username
* *
@@ -348,6 +386,6 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted htpasswd for '" . $result['username'] . " (" . $result['path'] . ")'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted htpasswd for '" . $result['username'] . " (" . $result['path'] . ")'");
\Froxlor\System\Cronjob::inserttask('1'); \Froxlor\System\Cronjob::inserttask('1');
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
} }

View File

@@ -136,8 +136,24 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
// types // types
if ($type == 'A' && filter_var($content, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) { if ($type == 'A' && filter_var($content, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) {
$errors[] = $this->lng['error']['dns_arec_noipv4']; $errors[] = $this->lng['error']['dns_arec_noipv4'];
} elseif ($type == 'A') {
// check whether there is a CNAME-record for the same resource
foreach ($dom_entries as $existing_entries) {
if ($existing_entries['type'] == 'CNAME' && $existing_entries['record'] == $record) {
$errors[] = $this->lng['error']['dns_other_nomorerr'];
break;
}
}
} elseif ($type == 'AAAA' && filter_var($content, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) { } elseif ($type == 'AAAA' && filter_var($content, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
$errors[] = $this->lng['error']['dns_aaaarec_noipv6']; $errors[] = $this->lng['error']['dns_aaaarec_noipv6'];
} elseif ($type == 'AAAA') {
// check whether there is a CNAME-record for the same resource
foreach ($dom_entries as $existing_entries) {
if ($existing_entries['type'] == 'CNAME' && $existing_entries['record'] == $record) {
$errors[] = $this->lng['error']['dns_other_nomorerr'];
break;
}
}
} elseif ($type == 'CAA' && ! empty($content)) { } 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:\/\/.*))"))/'; $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); preg_match($re, $content, $matches);
@@ -170,6 +186,10 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
break; break;
} }
} }
// check www-alias setting
if ($result['wwwserveralias'] == '1' && $result['iswildcarddomain'] == '0' && $record == 'www') {
$errors[] = $this->lng['error']['no_wwwcnamae_ifwwwalias'];
}
} }
// append trailing dot (again) // append trailing dot (again)
$content .= '.'; $content .= '.';
@@ -194,6 +214,10 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$errors[] = $this->lng['error']['dns_mx_noalias']; $errors[] = $this->lng['error']['dns_mx_noalias'];
break; break;
} }
elseif ($existing_entries['type'] == 'CNAME' && $existing_entries['record'] == $record) {
$errors[] = $this->lng['error']['dns_other_nomorerr'];
break;
}
} }
} }
// append trailing dot (again) // append trailing dot (again)
@@ -206,6 +230,14 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
} }
if (! \Froxlor\Validate\Validate::validateDomain($content)) { if (! \Froxlor\Validate\Validate::validateDomain($content)) {
$errors[] = $this->lng['error']['dns_ns_invaliddom']; $errors[] = $this->lng['error']['dns_ns_invaliddom'];
} else {
// check whether there is a CNAME-record for the same resource
foreach ($dom_entries as $existing_entries) {
if ($existing_entries['type'] == 'CNAME' && $existing_entries['record'] == $record) {
$errors[] = $this->lng['error']['dns_other_nomorerr'];
break;
}
}
} }
// append trailing dot (again) // append trailing dot (again)
$content .= '.'; $content .= '.';
@@ -309,10 +341,10 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$result = $this->apiCall('DomainZones.get', array( $result = $this->apiCall('DomainZones.get', array(
'id' => $id 'id' => $id
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
// return $errors // return $errors
throw new \Exception(implode("\n", $errors)); throw new \Exception(implode("\n", $errors), 406);
} }
/** /**
@@ -360,7 +392,7 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$zonefile = (string) $zone; $zonefile = (string) $zone;
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get dns-zone for '" . $result['domain'] . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get dns-zone for '" . $result['domain'] . "'");
return $this->response(200, "successfull", explode("\n", $zonefile)); return $this->response(200, "successful", explode("\n", $zonefile));
} }
/** /**
@@ -373,12 +405,99 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
} }
/** /**
* You cannot list dns zones. * List all entry records of a given domain by either id or domainname
* To get all domains use Domains.listing() or SubDomains.listing() *
* @param int $id
* optional, the domain id
* @param string $domainname
* optional, the domain name
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin, customer
* @throws \Exception
* @return bool
*/ */
public function listing() 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'];
$query_fields = array();
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_DOMAIN_DNS . "` WHERE `domain_id` = :did" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
$query_fields['did'] = $id;
Database::pexecute($sel_stmt, $query_fields, true, true);
$result = [];
while ($row = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
}
return $this->response(200, "successful", array(
'count' => count($result),
'list' => $result
));
}
/**
* returns the total number of domainzone-entries for given domain
*
* @param int $id
* optional, the domain id
* @param string $domainname
* optional, the domain name
*
* @access admin, customer
* @throws \Exception
* @return bool
*/
public function listingCount()
{
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 COUNT(*) as num_dns FROM `" . TABLE_DOMAIN_DNS . "` WHERE `domain_id` = :did");
$result = Database::pexecute_first($sel_stmt, array(
'did' => $id
), true, true);
if ($result) {
return $this->response(200, "successful", $result['num_dns']);
}
} }
/** /**
@@ -424,8 +543,8 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
if ($del_stmt->rowCount() > 0) { if ($del_stmt->rowCount() > 0) {
// re-generate bind configs // re-generate bind configs
\Froxlor\System\Cronjob::inserttask('4'); \Froxlor\System\Cronjob::inserttask('4');
return $this->response(200, "successfull", true); return $this->response(200, "successful", true);
} }
return $this->response(304, "successfull", true); return $this->response(304, "successful", true);
} }
} }

View File

@@ -25,6 +25,17 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
/** /**
* lists all domain entries * lists all domain entries
* *
* @param bool $with_ips
* optional, default true
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin * @access admin
* @throws \Exception * @throws \Exception
* @return string json-encoded array count|list * @return string json-encoded array count|list
@@ -32,7 +43,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
public function listing() public function listing()
{ {
if ($this->isAdmin()) { if ($this->isAdmin()) {
$with_ips = $this->getParam('with_ips', true, true);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list domains"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list domains");
$query_fields = array();
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT SELECT
`d`.*, `c`.`loginname`, `c`.`deactivated`, `c`.`name`, `c`.`firstname`, `c`.`company`, `c`.`standardsubdomain`, `d`.*, `c`.`loginname`, `c`.`deactivated`, `c`.`name`, `c`.`firstname`, `c`.`company`, `c`.`standardsubdomain`,
@@ -40,20 +53,55 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
FROM `" . TABLE_PANEL_DOMAINS . "` `d` FROM `" . TABLE_PANEL_DOMAINS . "` `d`
LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`) LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`)
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id` LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id`
WHERE `d`.`parentdomainid`='0' " . ($this->getUserDetail('customers_see_all') ? '' : " AND `d`.`adminid` = :adminid ") . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
$params = array();
if ($this->getUserDetail('customers_see_all') == '0') {
$params['adminid'] = $this->getUserDetail('adminid');
}
$params = array_merge($params, $query_fields);
Database::pexecute($result_stmt, $params, true, true);
$result = array();
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$row['ipsandports'] = array();
if ($with_ips) {
$row['ipsandports'] = $this->getIpsForDomain($row['id']);
}
$result[] = $row;
}
return $this->response(200, "successful", array(
'count' => count($result),
'list' => $result
));
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* returns the total number of accessible domains
*
* @access admin
* @throws \Exception
* @return string json-encoded array count|list
*/
public function listingCount()
{
if ($this->isAdmin()) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list domains");
$result_stmt = Database::prepare("
SELECT
COUNT(*) as num_domains
FROM `" . TABLE_PANEL_DOMAINS . "` `d`
LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`)
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id`
WHERE `d`.`parentdomainid`='0' " . ($this->getUserDetail('customers_see_all') ? '' : " AND `d`.`adminid` = :adminid ")); WHERE `d`.`parentdomainid`='0' " . ($this->getUserDetail('customers_see_all') ? '' : " AND `d`.`adminid` = :adminid "));
$params = array(); $params = array();
if ($this->getUserDetail('customers_see_all') == '0') { if ($this->getUserDetail('customers_see_all') == '0') {
$params['adminid'] = $this->getUserDetail('adminid'); $params['adminid'] = $this->getUserDetail('adminid');
} }
Database::pexecute($result_stmt, $params); $result = Database::pexecute_first($result_stmt, $params, true, true);
$result = array(); if ($result) {
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { return $this->response(200, "successful", $result['num_domains']);
$result[] = $row;
} }
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -65,6 +113,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional, the domain-id * optional, the domain-id
* @param string $domainname * @param string $domainname
* optional, the domainname * optional, the domainname
* @param bool $with_ips
* optional, default true
* @param bool $no_std_subdomain * @param bool $no_std_subdomain
* optional, default false * optional, default false
* *
@@ -78,6 +128,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$id = $this->getParam('id', true, 0); $id = $this->getParam('id', true, 0);
$dn_optional = ($id <= 0 ? false : true); $dn_optional = ($id <= 0 ? false : true);
$domainname = $this->getParam('domainname', $dn_optional, ''); $domainname = $this->getParam('domainname', $dn_optional, '');
$with_ips = $this->getParam('with_ips', true, true);
$no_std_subdomain = $this->getParam('no_std_subdomain', true, false); $no_std_subdomain = $this->getParam('no_std_subdomain', true, false);
// convert possible idn domain to punycode // convert possible idn domain to punycode
@@ -100,8 +151,12 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
} }
$result = Database::pexecute_first($result_stmt, $params, true, true); $result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) { if ($result) {
$result['ipsandports'] = array();
if ($with_ips) {
$result['ipsandports'] = $this->getIpsForDomain($result['id']);
}
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get domain '" . $result['domain'] . "'"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get domain '" . $result['domain'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
$key = ($id > 0 ? "id #" . $id : "domainname '" . $domainname . "'"); $key = ($id > 0 ? "id #" . $id : "domainname '" . $domainname . "'");
throw new \Exception("Domain with " . $key . " could not be found", 404); throw new \Exception("Domain with " . $key . " could not be found", 404);
@@ -109,12 +164,65 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
/**
* get ips connected to given domain as array
*
* @param number $domain_id
* @param bool $ssl_only
* optional, return only ssl enabled ip's, default false
* @return array
*/
private function getIpsForDomain($domain_id = 0, $ssl_only = false)
{
$resultips_stmt = Database::prepare("
SELECT `ips`.* FROM `" . TABLE_DOMAINTOIP . "` AS `dti`, `" . TABLE_PANEL_IPSANDPORTS . "` AS `ips`
WHERE `dti`.`id_ipandports` = `ips`.`id` AND `dti`.`id_domain` = :domainid " . ($ssl_only ? " AND `ips`.`ssl` = '1'" : ""));
Database::pexecute($resultips_stmt, array(
'domainid' => $domain_id
));
$ipandports = array();
while ($rowip = $resultips_stmt->fetch(\PDO::FETCH_ASSOC)) {
if (filter_var($rowip['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
$rowip['is_ipv6'] = true;
}
$ipandports[] = $rowip;
}
return $ipandports;
}
/**
* get ips from array of id's
*
* @param array $ips
* @return array
*/
private function getIpsFromIdArray(array $ids)
{
$resultips_stmt = Database::prepare("
SELECT `ip` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE id = :id
");
$result = [];
foreach ($ids as $id) {
$entry = Database::pexecute_first($resultips_stmt, array(
'id' => $id
));
$result[] = $entry['ip'];
}
return $result;
}
/** /**
* add new domain entry * add new domain entry
* *
* @param string $domain * @param string $domain
* domain-name * domain-name
* @param int $customerid * @param int $customerid
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
* @param int $adminid * @param int $adminid
* optional, default is the calling admin's ID * optional, default is the calling admin's ID
* @param array $ipandport * @param array $ipandport
@@ -126,12 +234,12 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* @param bool $email_only * @param bool $email_only
* optional, restrict domain to email usage, default 0 (false) * optional, restrict domain to email usage, default 0 (false)
* @param int $selectserveralias * @param int $selectserveralias
* optional, 0 = wildcard, 1 = www-alias, 2 = none, default 0 * optional, 0 = wildcard, 1 = www-alias, 2 = none, default [system.domaindefaultalias]
* @param bool $speciallogfile * @param bool $speciallogfile
* optional, whether to create an exclusive web-logfile for this domain, default 0 (false) * optional, whether to create an exclusive web-logfile for this domain, default 0 (false)
* @param int $alias * @param int $alias
* optional, domain-id of a domain that the new domain should be an alias of, default 0 (none) * optional, domain-id of a domain that the new domain should be an alias of, default 0 (none)
* @param bool $issubof * @param int $issubof
* optional, domain-id of a domain this domain is a subdomain of (required for webserver-cronjob to generate the correct order), default 0 (none) * optional, domain-id of a domain this domain is a subdomain of (required for webserver-cronjob to generate the correct order), default 0 (none)
* @param string $registration_date * @param string $registration_date
* optional, date of domain registration in form of YYYY-MM-DD, default empty (none) * optional, date of domain registration in form of YYYY-MM-DD, default empty (none)
@@ -147,6 +255,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional, currently not in use, default 0 (false) * optional, currently not in use, default 0 (false)
* @param string $specialsettings * @param string $specialsettings
* optional, custom webserver vhost-content which is added to the generated vhost, default empty * 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 * @param bool $notryfiles
* optional, [nginx only] do not generate the default try-files directive, default 0 (false) * optional, [nginx only] do not generate the default try-files directive, default 0 (false)
* @param bool $writeaccesslog * @param bool $writeaccesslog
@@ -171,8 +283,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled * optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled
* @param array $ssl_ipandport * @param array $ssl_ipandport
* optional, list of ssl-enabled ip/port id's to assign to this domain, default empty * optional, list of ssl-enabled ip/port id's to assign to this domain, default empty
* @param bool $use_default_ssl_ipandport_if_empty * @param bool $dont_use_default_ssl_ipandport_if_empty
* optional, set the systems default ssl ip addresses if none are given via $ssl_ipandport parameter * optional, do NOT set the systems default ssl ip addresses if none are given via $ssl_ipandport parameter
* @param bool $sslenabled
* optional, whether or not SSL is enabled for this domain, regardless of the assigned ssl-ips, default 1 (true)
* @param bool $http2 * @param bool $http2
* optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default 0 (false) * optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default 0 (false)
* @param int $hsts_maxage * @param int $hsts_maxage
@@ -183,6 +297,20 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional whether or not to preload HSTS header value * optional whether or not to preload HSTS header value
* @param bool $ocsp_stapling * @param bool $ocsp_stapling
* optional whether to enable ocsp-stapling for this domain. default 0 (false), requires SSL * optional whether to enable ocsp-stapling for this domain. default 0 (false), requires SSL
* @param bool $honorcipherorder
* optional whether to honor the (server) cipher order for this domain. default 0 (false), requires SSL
* @param bool $sessiontickets
* optional whether to enable or disable TLS sessiontickets (RFC 5077) for this domain. default 1 (true), requires SSL
* @param 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
* @param string $description
* optional custom description (currently not used/shown in the frontend), default empty
* *
* @access admin * @access admin
* @throws \Exception * @throws \Exception
@@ -195,7 +323,6 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
// parameters // parameters
$p_domain = $this->getParam('domain'); $p_domain = $this->getParam('domain');
$customerid = intval($this->getParam('customerid'));
// optional parameters // optional parameters
$p_ipandports = $this->getParam('ipandport', true, explode(',', Settings::Get('system.defaultip'))); $p_ipandports = $this->getParam('ipandport', true, explode(',', Settings::Get('system.defaultip')));
@@ -203,7 +330,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$subcanemaildomain = $this->getParam('subcanemaildomain', true, 0); $subcanemaildomain = $this->getParam('subcanemaildomain', true, 0);
$isemaildomain = $this->getBoolParam('isemaildomain', true, 0); $isemaildomain = $this->getBoolParam('isemaildomain', true, 0);
$email_only = $this->getBoolParam('email_only', true, 0); $email_only = $this->getBoolParam('email_only', true, 0);
$serveraliasoption = $this->getParam('selectserveralias', true, 0); $serveraliasoption = $this->getParam('selectserveralias', true, Settings::Get('system.domaindefaultalias'));
$speciallogfile = $this->getBoolParam('speciallogfile', true, 0); $speciallogfile = $this->getBoolParam('speciallogfile', true, 0);
$aliasdomain = intval($this->getParam('alias', true, 0)); $aliasdomain = intval($this->getParam('alias', true, 0));
$issubof = $this->getParam('issubof', true, 0); $issubof = $this->getParam('issubof', true, 0);
@@ -214,6 +341,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$zonefile = $this->getParam('zonefile', true, ''); $zonefile = $this->getParam('zonefile', true, '');
$dkim = $this->getBoolParam('dkim', true, 0); $dkim = $this->getBoolParam('dkim', true, 0);
$specialsettings = $this->getParam('specialsettings', true, ''); $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); $notryfiles = $this->getBoolParam('notryfiles', true, 0);
$writeaccesslog = $this->getBoolParam('writeaccesslog', true, 1); $writeaccesslog = $this->getBoolParam('writeaccesslog', true, 1);
$writeerrorlog = $this->getBoolParam('writeerrorlog', true, 1); $writeerrorlog = $this->getBoolParam('writeerrorlog', true, 1);
@@ -225,16 +354,34 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, - 1); $mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, - 1);
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, 0); $ssl_redirect = $this->getBoolParam('ssl_redirect', true, 0);
$letsencrypt = $this->getBoolParam('letsencrypt', true, 0); $letsencrypt = $this->getBoolParam('letsencrypt', true, 0);
$use_default_ssl_ipandport_if_empty = $this->getBoolParam('use_default_ssl_ipandport_if_empty', true, 0); $dont_use_default_ssl_ipandport_if_empty = $this->getBoolParam('dont_use_default_ssl_ipandport_if_empty', true, 0);
$p_ssl_ipandports = $this->getParam('ssl_ipandport', true, $use_default_ssl_ipandport_if_empty ? explode(',', Settings::Get('system.defaultsslip')) : array()); $p_ssl_ipandports = $this->getParam('ssl_ipandport', true, $dont_use_default_ssl_ipandport_if_empty ? array() : explode(',', Settings::Get('system.defaultsslip')));
$sslenabled = $this->getBoolParam('sslenabled', true, 1);
$http2 = $this->getBoolParam('http2', true, 0); $http2 = $this->getBoolParam('http2', true, 0);
$hsts_maxage = $this->getParam('hsts_maxage', true, 0); $hsts_maxage = $this->getParam('hsts_maxage', true, 0);
$hsts_sub = $this->getBoolParam('hsts_sub', true, 0); $hsts_sub = $this->getBoolParam('hsts_sub', true, 0);
$hsts_preload = $this->getBoolParam('hsts_preload', true, 0); $hsts_preload = $this->getBoolParam('hsts_preload', true, 0);
$ocsp_stapling = $this->getBoolParam('ocsp_stapling', true, 0); $ocsp_stapling = $this->getBoolParam('ocsp_stapling', true, 0);
$honorcipherorder = $this->getBoolParam('honorcipherorder', true, 0);
$sessiontickets = $this->getBoolParam('sessiontickets', true, 1);
$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'));
}
}
$description = $this->getParam('description', true, '');
// validation // validation
if ($p_domain == Settings::Get('system.hostname')) { $p_domain = strtolower($p_domain);
if ($p_domain == strtolower(Settings::Get('system.hostname'))) {
\Froxlor\UI\Response::standard_error('admin_domain_emailsystemhostname', '', true); \Froxlor\UI\Response::standard_error('admin_domain_emailsystemhostname', '', true);
} }
@@ -256,9 +403,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
), '', true); ), '', true);
} }
$customer = $this->apiCall('Customers.get', array( $customer = $this->getCustomerData();
'id' => $customerid $customerid = $customer['customerid'];
));
if ($this->getUserDetail('customers_see_all') == '1' && $adminid != $this->getUserDetail('adminid')) { if ($this->getUserDetail('customers_see_all') == '1' && $adminid != $this->getUserDetail('adminid')) {
$admin_stmt = Database::prepare(" $admin_stmt = Database::prepare("
@@ -281,12 +427,26 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
} }
$_documentroot = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . $path_suffix); $_documentroot = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . $path_suffix);
$documentroot = \Froxlor\Validate\Validate::validate($documentroot, 'documentroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
// If path is empty and 'Use domain name as default value for DocumentRoot path' is enabled in settings,
// set default path to subdomain or domain name
if (! empty($documentroot)) {
if (substr($documentroot, 0, 1) != '/' && ! preg_match('/^https?\:\/\//', $documentroot)) {
$documentroot = $_documentroot . '/' . $documentroot;
} elseif (substr($documentroot, 0, 1) == '/' && $this->getUserDetail('change_serversettings') != '1') {
\Froxlor\UI\Response::standard_error('pathmustberelative', '', true);
}
} else {
$documentroot = $_documentroot;
}
$registration_date = \Froxlor\Validate\Validate::validate($registration_date, 'registration_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', array( $registration_date = \Froxlor\Validate\Validate::validate($registration_date, 'registration_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', array(
'0000-00-00', '0000-00-00',
'0', '0',
'' ''
), true); ), true);
if ($registration_date == '0000-00-00') { if ($registration_date == '0000-00-00' || empty($registration_date)) {
$registration_date = null; $registration_date = null;
} }
@@ -295,7 +455,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
'0', '0',
'' ''
), true); ), true);
if ($termination_date == '0000-00-00') { if ($termination_date == '0000-00-00' || empty($termination_date)) {
$termination_date = null; $termination_date = null;
} }
@@ -307,17 +467,34 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$zonefile = ''; $zonefile = '';
} }
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', '/^[^\0]*$/', '', array(), true); $specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
\Froxlor\Validate\Validate::validate($documentroot, 'documentroot', '', '', array(), true);
// If path is empty and 'Use domain name as default value for DocumentRoot path' is enabled in settings, $ssl_protocols = array();
// set default path to subdomain or domain name if (! empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) {
if (! empty($documentroot)) { $p_ssl_protocols = array(
if (substr($documentroot, 0, 1) != '/' && ! preg_match('/^https?\:\/\//', $documentroot)) { $p_ssl_protocols
$documentroot = $_documentroot . '/' . $documentroot; );
} }
} else { if (! empty($p_ssl_protocols) && ! is_array($p_ssl_protocols)) {
$documentroot = $_documentroot; $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 { } else {
$isbinddomain = '0'; $isbinddomain = '0';
@@ -328,10 +505,13 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$zonefile = ''; $zonefile = '';
$dkim = '0'; $dkim = '0';
$specialsettings = ''; $specialsettings = '';
$ssl_specialsettings = '';
$include_specialsettings = 0;
$notryfiles = '0'; $notryfiles = '0';
$writeaccesslog = '1'; $writeaccesslog = '1';
$writeerrorlog = '1'; $writeerrorlog = '1';
$documentroot = $_documentroot; $override_tls = '0';
$ssl_protocols = array();
} }
if ($this->getUserDetail('caneditphpsettings') == '1' || $this->getUserDetail('change_serversettings') == '1') { if ($this->getUserDetail('caneditphpsettings') == '1' || $this->getUserDetail('change_serversettings') == '1') {
@@ -391,6 +571,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$ssl_ipandports = array(); $ssl_ipandports = array();
if (Settings::Get('system.use_ssl') == "1" && ! empty($p_ssl_ipandports)) { if (Settings::Get('system.use_ssl') == "1" && ! empty($p_ssl_ipandports)) {
$ssl_ipandports = $this->validateIpAddresses($p_ssl_ipandports, true); $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)) { if (Settings::Get('system.use_ssl') == "0" || empty($ssl_ipandports)) {
$ssl_redirect = 0; $ssl_redirect = 0;
@@ -407,16 +591,24 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
// OCSP stapling // OCSP stapling
$ocsp_stapling = 0; $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 // validate dns if lets encrypt is enabled to check whether we can use it at all
if ($serveraliasoption == '0' && $letsencrypt == '1' && Settings::Get('system.leapiversion') == '1') { if ($letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
\Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true); $domain_ips = \Froxlor\PhpHelper::gethostbynamel6($domain);
$selected_ips = $this->getIpsFromIdArray($ssl_ipandports);
if ($domain_ips == false || count(array_intersect($selected_ips, $domain_ips)) <= 0) {
\Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true);
} }
// 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') { // We can't enable let's encrypt for wildcard-domains
\Froxlor\UI\Response::standard_error('nowildcardwithletsencryptv2', '', true); if ($serveraliasoption == '0' && $letsencrypt == '1') {
\Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true);
} }
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated // Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
@@ -518,9 +710,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
), '', true); ), '', true);
} elseif ($customerid == 0) { } elseif ($customerid == 0) {
\Froxlor\UI\Response::standard_error('adduserfirst', '', true); \Froxlor\UI\Response::standard_error('adduserfirst', '', true);
} elseif (strtolower($domain_check['domain']) == strtolower($domain)) { } elseif ($domain_check && strtolower($domain_check['domain']) == strtolower($domain)) {
\Froxlor\UI\Response::standard_error('domainalreadyexists', $idna_convert->decode($domain), true); \Froxlor\UI\Response::standard_error('domainalreadyexists', $idna_convert->decode($domain), true);
} elseif ($aliasdomain_check['id'] != $aliasdomain) { } elseif ($aliasdomain_check && $aliasdomain_check['id'] != $aliasdomain) {
\Froxlor\UI\Response::standard_error('domainisaliasorothercustomer', '', true); \Froxlor\UI\Response::standard_error('domainisaliasorothercustomer', '', true);
} else { } else {
$wwwserveralias = ($serveraliasoption == '1') ? '1' : '0'; $wwwserveralias = ($serveraliasoption == '1') ? '1' : '0';
@@ -528,6 +720,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$ins_data = array( $ins_data = array(
'domain' => $domain, 'domain' => $domain,
'domain_ace' => $idna_convert->decode($domain),
'customerid' => $customerid, 'customerid' => $customerid,
'adminid' => $adminid, 'adminid' => $adminid,
'documentroot' => $documentroot, 'documentroot' => $documentroot,
@@ -545,6 +738,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
'openbasedir' => $openbasedir, 'openbasedir' => $openbasedir,
'speciallogfile' => $speciallogfile, 'speciallogfile' => $speciallogfile,
'specialsettings' => $specialsettings, 'specialsettings' => $specialsettings,
'ssl_specialsettings' => $ssl_specialsettings,
'include_specialsettings' => $include_specialsettings,
'notryfiles' => $notryfiles, 'notryfiles' => $notryfiles,
'writeaccesslog' => $writeaccesslog, 'writeaccesslog' => $writeaccesslog,
'writeerrorlog' => $writeerrorlog, 'writeerrorlog' => $writeerrorlog,
@@ -561,12 +756,21 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
'hsts' => $hsts_maxage, 'hsts' => $hsts_maxage,
'hsts_sub' => $hsts_sub, 'hsts_sub' => $hsts_sub,
'hsts_preload' => $hsts_preload, '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,
'sslenabled' => $sslenabled,
'honorcipherorder' => $honorcipherorder,
'sessiontickets' => $sessiontickets,
'description' => $description
); );
$ins_stmt = Database::prepare(" $ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_DOMAINS . "` SET INSERT INTO `" . TABLE_PANEL_DOMAINS . "` SET
`domain` = :domain, `domain` = :domain,
`domain_ace` = :domain_ace,
`customerid` = :customerid, `customerid` = :customerid,
`adminid` = :adminid, `adminid` = :adminid,
`documentroot` = :documentroot, `documentroot` = :documentroot,
@@ -587,6 +791,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
`openbasedir` = :openbasedir, `openbasedir` = :openbasedir,
`speciallogfile` = :speciallogfile, `speciallogfile` = :speciallogfile,
`specialsettings` = :specialsettings, `specialsettings` = :specialsettings,
`ssl_specialsettings` = :ssl_specialsettings,
`include_specialsettings` = :include_specialsettings,
`notryfiles` = :notryfiles, `notryfiles` = :notryfiles,
`writeaccesslog` = :writeaccesslog, `writeaccesslog` = :writeaccesslog,
`writeerrorlog` = :writeerrorlog, `writeerrorlog` = :writeerrorlog,
@@ -603,7 +809,15 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
`hsts` = :hsts, `hsts` = :hsts,
`hsts_sub` = :hsts_sub, `hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload, `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,
`ssl_enabled` = :sslenabled,
`ssl_honorcipherorder` = :honorcipherorder,
`ssl_sessiontickets` = :sessiontickets,
`description` = :description
"); ");
Database::pexecute($ins_stmt, $ins_data, true, true); Database::pexecute($ins_stmt, $ins_data, true, true);
$domainid = Database::lastInsertId(); $domainid = Database::lastInsertId();
@@ -652,7 +866,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$result = $this->apiCall('Domains.get', array( $result = $this->apiCall('Domains.get', array(
'domainname' => $domain 'domainname' => $domain
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
} }
throw new \Exception("No more resources available", 406); throw new \Exception("No more resources available", 406);
@@ -668,7 +882,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* @param string $domainname * @param string $domainname
* optional, the domainname * optional, the domainname
* @param int $customerid * @param int $customerid
* optional customer-id * required (if $loginname is not specified)
* @param string $loginname
* required (if $customerid is not specified)
* @param int $adminid * @param int $adminid
* optional, default is the calling admin's ID * optional, default is the calling admin's ID
* @param array $ipandport * @param array $ipandport
@@ -687,7 +903,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional, when setting $speciallogfile to false, this needs to be set to true to confirm the action, default 0 (false) * optional, when setting $speciallogfile to false, this needs to be set to true to confirm the action, default 0 (false)
* @param int $alias * @param int $alias
* optional, domain-id of a domain that the new domain should be an alias of, default 0 (none) * optional, domain-id of a domain that the new domain should be an alias of, default 0 (none)
* @param bool $issubof * @param int $issubof
* optional, domain-id of a domain this domain is a subdomain of (required for webserver-cronjob to generate the correct order), default 0 (none) * optional, domain-id of a domain this domain is a subdomain of (required for webserver-cronjob to generate the correct order), default 0 (none)
* @param string $registration_date * @param string $registration_date
* optional, date of domain registration in form of YYYY-MM-DD, default empty (none) * optional, date of domain registration in form of YYYY-MM-DD, default empty (none)
@@ -703,8 +919,12 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional, currently not in use, default 0 (false) * optional, currently not in use, default 0 (false)
* @param string $specialsettings * @param string $specialsettings
* optional, custom webserver vhost-content which is added to the generated vhost, default empty * 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 * @param bool $specialsettingsforsubdomains
* optional, whether to apply specialsettings to all subdomains of this domain, default 0 (false) * optional, whether to apply specialsettings to all subdomains of this domain, default is read from setting system.apply_specialsettings_default
* @param bool $notryfiles * @param bool $notryfiles
* optional, [nginx only] do not generate the default try-files directive, default 0 (false) * optional, [nginx only] do not generate the default try-files directive, default 0 (false)
* @param bool $writeaccesslog * @param bool $writeaccesslog
@@ -716,7 +936,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* @param bool $phpenabled * @param bool $phpenabled
* optional, whether php is enabled for this domain, default 0 (false) * optional, whether php is enabled for this domain, default 0 (false)
* @param bool $phpsettingsforsubdomains * @param bool $phpsettingsforsubdomains
* optional, whether to apply php-setting to apply to all subdomains of this domain, default 0 (false) * optional, whether to apply php-setting to apply to all subdomains of this domain, default is read from setting system.apply_phpconfigs_default
* @param bool $openbasedir * @param bool $openbasedir
* optional, whether to activate openbasedir restriction for this domain, default 0 (false) * optional, whether to activate openbasedir restriction for this domain, default 0 (false)
* @param int $phpsettingid * @param int $phpsettingid
@@ -730,7 +950,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* @param bool $letsencrypt * @param bool $letsencrypt
* optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled * optional, whether to generate a Let's Encrypt certificate for this domain, default false; requires SSL to be enabled
* @param array $ssl_ipandport * @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, if left empty, the current set value is being used, to remove all ssl ips use $remove_ssl_ipandport
* @param bool $remove_ssl_ipandport
* optional, if set to true and no $ssl_ipandport value is given, the ip's get removed, otherwise, the currently set value is used, default false
* @param bool $sslenabled
* optional, whether or not SSL is enabled for this domain, regardless of the assigned ssl-ips, default 1 (true)
* @param bool $http2 * @param bool $http2
* optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default 0 (false) * optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default 0 (false)
* @param int $hsts_maxage * @param int $hsts_maxage
@@ -741,6 +965,12 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional whether or not to preload HSTS header value * optional whether or not to preload HSTS header value
* @param bool $ocsp_stapling * @param bool $ocsp_stapling
* optional whether to enable ocsp-stapling for this domain. default 0 (false), requires SSL * optional whether to enable ocsp-stapling for this domain. default 0 (false), requires SSL
* @param bool $honorcipherorder
* optional whether to honor the (server) cipher order for this domain. default 0 (false), requires SSL
* @param bool $sessiontickets
* optional whether to enable or disable TLS sessiontickets (RFC 5077) for this domain. default 1 (true), requires SSL
* @param string $description
* optional custom description (currently not used/shown in the frontend), default empty
* *
* @access admin * @access admin
* @throws \Exception * @throws \Exception
@@ -764,9 +994,18 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
// optional parameters // optional parameters
$p_ipandports = $this->getParam('ipandport', true, array()); $p_ipandports = $this->getParam('ipandport', true, array());
$customerid = intval($this->getParam('customerid', true, $result['customerid']));
$adminid = intval($this->getParam('adminid', true, $result['adminid'])); $adminid = intval($this->getParam('adminid', true, $result['adminid']));
if ($this->getParam('customerid', true, 0) == 0 && $this->getParam('loginname', true, '') == '') {
$customerid = $result['customerid'];
$customer = $this->apiCall('Customers.get', array(
'id' => $customerid
));
} else {
$customer = $this->getCustomerData();
$customerid = $customer['customerid'];
}
$subcanemaildomain = $this->getParam('subcanemaildomain', true, $result['subcanemaildomain']); $subcanemaildomain = $this->getParam('subcanemaildomain', true, $result['subcanemaildomain']);
$isemaildomain = $this->getBoolParam('isemaildomain', true, $result['isemaildomain']); $isemaildomain = $this->getBoolParam('isemaildomain', true, $result['isemaildomain']);
$email_only = $this->getBoolParam('email_only', true, $result['email_only']); $email_only = $this->getBoolParam('email_only', true, $result['email_only']);
@@ -782,25 +1021,52 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$zonefile = $this->getParam('zonefile', true, $result['zonefile']); $zonefile = $this->getParam('zonefile', true, $result['zonefile']);
$dkim = $this->getBoolParam('dkim', true, $result['dkim']); $dkim = $this->getBoolParam('dkim', true, $result['dkim']);
$specialsettings = $this->getParam('specialsettings', true, $result['specialsettings']); $specialsettings = $this->getParam('specialsettings', true, $result['specialsettings']);
$ssfs = $this->getBoolParam('specialsettingsforsubdomains', true, 0); $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, \Froxlor\Settings::Get('system.apply_specialsettings_default'));
$notryfiles = $this->getBoolParam('notryfiles', true, $result['notryfiles']); $notryfiles = $this->getBoolParam('notryfiles', true, $result['notryfiles']);
$writeaccesslog = $this->getBoolParam('writeaccesslog', true, $result['writeaccesslog']); $writeaccesslog = $this->getBoolParam('writeaccesslog', true, $result['writeaccesslog']);
$writeerrorlog = $this->getBoolParam('writeerrorlog', true, $result['writeerrorlog']); $writeerrorlog = $this->getBoolParam('writeerrorlog', true, $result['writeerrorlog']);
$documentroot = $this->getParam('documentroot', true, $result['documentroot']); $documentroot = $this->getParam('documentroot', true, $result['documentroot']);
$phpenabled = $this->getBoolParam('phpenabled', true, $result['phpenabled']); $phpenabled = $this->getBoolParam('phpenabled', true, $result['phpenabled']);
$phpfs = $this->getBoolParam('phpsettingsforsubdomains', true, 0); $phpfs = $this->getBoolParam('phpsettingsforsubdomains', true, \Froxlor\Settings::Get('system.apply_phpconfigs_default'));
$openbasedir = $this->getBoolParam('openbasedir', true, $result['openbasedir']); $openbasedir = $this->getBoolParam('openbasedir', true, $result['openbasedir']);
$phpsettingid = $this->getParam('phpsettingid', true, $result['phpsettingid']); $phpsettingid = $this->getParam('phpsettingid', true, $result['phpsettingid']);
$mod_fcgid_starter = $this->getParam('mod_fcgid_starter', true, $result['mod_fcgid_starter']); $mod_fcgid_starter = $this->getParam('mod_fcgid_starter', true, $result['mod_fcgid_starter']);
$mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, $result['mod_fcgid_maxrequests']); $mod_fcgid_maxrequests = $this->getParam('mod_fcgid_maxrequests', true, $result['mod_fcgid_maxrequests']);
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, $result['ssl_redirect']); $ssl_redirect = $this->getBoolParam('ssl_redirect', true, $result['ssl_redirect']);
$letsencrypt = $this->getBoolParam('letsencrypt', true, $result['letsencrypt']); $letsencrypt = $this->getBoolParam('letsencrypt', true, $result['letsencrypt']);
$p_ssl_ipandports = $this->getParam('ssl_ipandport', true, array()); $remove_ssl_ipandport = $this->getBoolParam('remove_ssl_ipandport', true, 0);
$p_ssl_ipandports = $this->getParam('ssl_ipandport', true, $remove_ssl_ipandport ? array(
- 1
) : null);
$sslenabled = $this->getBoolParam('sslenabled', true, $result['ssl_enabled']);
$http2 = $this->getBoolParam('http2', true, $result['http2']); $http2 = $this->getBoolParam('http2', true, $result['http2']);
$hsts_maxage = $this->getParam('hsts_maxage', true, $result['hsts']); $hsts_maxage = $this->getParam('hsts_maxage', true, $result['hsts']);
$hsts_sub = $this->getBoolParam('hsts_sub', true, $result['hsts_sub']); $hsts_sub = $this->getBoolParam('hsts_sub', true, $result['hsts_sub']);
$hsts_preload = $this->getBoolParam('hsts_preload', true, $result['hsts_preload']); $hsts_preload = $this->getBoolParam('hsts_preload', true, $result['hsts_preload']);
$ocsp_stapling = $this->getBoolParam('ocsp_stapling', true, $result['ocsp_stapling']); $ocsp_stapling = $this->getBoolParam('ocsp_stapling', true, $result['ocsp_stapling']);
$honorcipherorder = $this->getBoolParam('honorcipherorder', true, $result['ssl_honorcipherorder']);
$sessiontickets = $this->getBoolParam('sessiontickets', true, $result['ssl_sessiontickets']);
$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'];
}
$description = $this->getParam('description', true, $result['description']);
// count subdomain usage of source-domain // count subdomain usage of source-domain
$subdomains_stmt = Database::prepare(" $subdomains_stmt = Database::prepare("
@@ -871,13 +1137,6 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
if (empty($customer) || $customer['customerid'] != $customerid) { if (empty($customer) || $customer['customerid'] != $customerid) {
\Froxlor\UI\Response::standard_error('customerdoesntexist', '', true); \Froxlor\UI\Response::standard_error('customerdoesntexist', '', true);
} }
} else {
$customerid = $result['customerid'];
// get customer
$customer = $this->apiCall('Customers.get', array(
'id' => $customerid
));
} }
// handle change of admin (move domain from admin to admin) // handle change of admin (move domain from admin to admin)
@@ -908,7 +1167,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
'0', '0',
'' ''
), true); ), true);
if ($registration_date == '0000-00-00') { if ($registration_date == '0000-00-00' || empty($registration_date)) {
$registration_date = null; $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( $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(
@@ -916,7 +1175,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
'0', '0',
'' ''
), true); ), true);
if ($termination_date == '0000-00-00') { if ($termination_date == '0000-00-00' || empty($termination_date)) {
$termination_date = null; $termination_date = null;
} }
@@ -930,22 +1189,12 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$serveraliasoption = $p_serveraliasoption; $serveraliasoption = $p_serveraliasoption;
} }
if ($this->getUserDetail('change_serversettings') == '1') { $documentroot = \Froxlor\Validate\Validate::validate($documentroot, 'documentroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
if (Settings::Get('system.bind_enable') == '1') { if (! empty($documentroot) && $documentroot != $result['documentroot'] && substr($documentroot, 0, 1) == '/' && substr($documentroot, 0, strlen($customer['documentroot'])) != $customer['documentroot'] && $this->getUserDetail('change_serversettings') != '1') {
$zonefile = \Froxlor\Validate\Validate::validate($zonefile, 'zonefile', '', '', array(), true); \Froxlor\UI\Response::standard_error('pathmustberelative', '', true);
} else {
$isbinddomain = $result['isbinddomain'];
$zonefile = $result['zonefile'];
} }
if (Settings::Get('dkim.use_dkim') != '1') {
$dkim = $result['dkim'];
}
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', '/^[^\0]*$/', '', array(), true);
$documentroot = \Froxlor\Validate\Validate::validate($documentroot, 'documentroot', '', '', array(), true);
// when moving customer and no path is specified, update would normally reuse the current document-root // when moving customer and no path is specified, update would normally reuse the current document-root
// which would point to the wrong customer, therefore we will re-create that directory // which would point to the wrong customer, therefore we will re-create that directory
if (! empty($documentroot) && $customerid > 0 && $customerid != $result['customerid'] && Settings::Get('panel.allow_domain_change_customer') == '1') { if (! empty($documentroot) && $customerid > 0 && $customerid != $result['customerid'] && Settings::Get('panel.allow_domain_change_customer') == '1') {
@@ -971,16 +1220,62 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
if (! preg_match('/^https?\:\/\//', $documentroot) && strstr($documentroot, ":") !== false) { if (! preg_match('/^https?\:\/\//', $documentroot) && strstr($documentroot, ":") !== false) {
\Froxlor\UI\Response::standard_error('pathmaynotcontaincolon', '', true); \Froxlor\UI\Response::standard_error('pathmaynotcontaincolon', '', true);
} }
if ($this->getUserDetail('change_serversettings') == '1') {
if (Settings::Get('system.bind_enable') == '1') {
$zonefile = \Froxlor\Validate\Validate::validate($zonefile, 'zonefile', '', '', array(), true);
} else {
$isbinddomain = $result['isbinddomain'];
$zonefile = $result['zonefile'];
}
if (Settings::Get('dkim.use_dkim') != '1') {
$dkim = $result['dkim'];
}
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$ssl_protocols = array();
if (! empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) {
$p_ssl_protocols = array(
$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 { } else {
$isbinddomain = $result['isbinddomain']; $isbinddomain = $result['isbinddomain'];
$zonefile = $result['zonefile']; $zonefile = $result['zonefile'];
$dkim = $result['dkim']; $dkim = $result['dkim'];
$specialsettings = $result['specialsettings']; $specialsettings = $result['specialsettings'];
$ssl_specialsettings = $result['ssl_specialsettings'];
$include_specialsettings = $result['include_specialsettings'];
$ssfs = (empty($specialsettings) ? 0 : 1); $ssfs = (empty($specialsettings) ? 0 : 1);
$notryfiles = $result['notryfiles']; $notryfiles = $result['notryfiles'];
$writeaccesslog = $result['writeaccesslog']; $writeaccesslog = $result['writeaccesslog'];
$writeerrorlog = $result['writeerrorlog']; $writeerrorlog = $result['writeerrorlog'];
$documentroot = $result['documentroot']; $ssl_protocols = $p_ssl_protocols;
$override_tls = $result['override_tls'];
} }
if ($this->getUserDetail('caneditphpsettings') == '1' || $this->getUserDetail('change_serversettings') == '1') { if ($this->getUserDetail('caneditphpsettings') == '1' || $this->getUserDetail('change_serversettings') == '1') {
@@ -1028,9 +1323,23 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
// check non-ssl IP // check non-ssl IP
$ipandports = $this->validateIpAddresses($p_ipandports, false, $result['id']); $ipandports = $this->validateIpAddresses($p_ipandports, false, $result['id']);
// check ssl IP // check ssl IP
if (empty($p_ssl_ipandports) || (! is_array($p_ssl_ipandports) && is_null($p_ssl_ipandports))) {
foreach ($result['ipsandports'] as $ip) {
if ($ip['ssl'] == 1) {
$p_ssl_ipandports[] = $ip['id'];
}
}
}
$ssl_ipandports = array(); $ssl_ipandports = array();
if (Settings::Get('system.use_ssl') == "1" && ! empty($p_ssl_ipandports)) { if (Settings::Get('system.use_ssl') == "1" && ! empty($p_ssl_ipandports) && $p_ssl_ipandports[0] != - 1) {
$ssl_ipandports = $this->validateIpAddresses($p_ssl_ipandports, true, $result['id']); $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 ($remove_ssl_ipandport || (! empty($p_ssl_ipandports) && $p_ssl_ipandports[0] == - 1)) {
$ssl_ipandports = array();
} }
if (Settings::Get('system.use_ssl') == "0" || empty($ssl_ipandports)) { if (Settings::Get('system.use_ssl') == "0" || empty($ssl_ipandports)) {
$ssl_redirect = 0; $ssl_redirect = 0;
@@ -1047,16 +1356,24 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
// OCSP stapling // OCSP stapling
$ocsp_stapling = 0; $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 // validate dns if lets encrypt is enabled to check whether we can use it at all
if ($serveraliasoption == '0' && $letsencrypt == '1' && Settings::Get('system.leapiversion') == '1') { if ($letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
\Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true); $domain_ips = \Froxlor\PhpHelper::gethostbynamel6($result['domain']);
$selected_ips = $this->getIpsFromIdArray($ssl_ipandports);
if ($domain_ips == false || count(array_intersect($selected_ips, $domain_ips)) <= 0) {
\Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true);
} }
// 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') { // We can't enable let's encrypt for wildcard-domains
\Froxlor\UI\Response::standard_error('nowildcardwithletsencryptv2', '', true); if ($serveraliasoption == '0' && $letsencrypt == '1') {
\Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true);
} }
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated // Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
@@ -1065,8 +1382,13 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
} }
if (! preg_match('/^https?\:\/\//', $documentroot)) { if (! preg_match('/^https?\:\/\//', $documentroot)) {
if ($documentroot != $result['documentroot']) {
if (substr($documentroot, 0, 1) != "/") {
$documentroot = $customer['documentroot'] . '/' . $documentroot;
}
$documentroot = \Froxlor\FileDir::makeCorrectDir($documentroot); $documentroot = \Froxlor\FileDir::makeCorrectDir($documentroot);
} }
}
if ($email_only == '1') { if ($email_only == '1') {
$isemaildomain = '1'; $isemaildomain = '1';
@@ -1183,6 +1505,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
Database::pexecute($del_stmt, array( Database::pexecute($del_stmt, array(
'id' => $id 'id' => $id
), true, true); ), true, true);
// remove domain from acme.sh / lets encrypt if used
\Froxlor\System\Cronjob::inserttask('12', $result['domain']);
} }
$updatechildren = ''; $updatechildren = '';
@@ -1255,12 +1579,16 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
if ($ssfs == 1) { if ($ssfs == 1) {
$_update_data['specialsettings'] = $specialsettings; $_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 { } else {
$upd_specialsettings = ''; $upd_specialsettings = '';
unset($_update_data['specialsettings']); unset($_update_data['specialsettings']);
unset($_update_data['ssl_specialsettings']);
unset($_update_data['include_specialsettings']);
$upd_stmt = Database::prepare(" $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( Database::pexecute($upd_stmt, array(
'id' => $id 'id' => $id
@@ -1293,6 +1621,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$update_data['mod_fcgid_starter'] = $mod_fcgid_starter; $update_data['mod_fcgid_starter'] = $mod_fcgid_starter;
$update_data['mod_fcgid_maxrequests'] = $mod_fcgid_maxrequests; $update_data['mod_fcgid_maxrequests'] = $mod_fcgid_maxrequests;
$update_data['specialsettings'] = $specialsettings; $update_data['specialsettings'] = $specialsettings;
$update_data['ssl_specialsettings'] = $ssl_specialsettings;
$update_data['include_specialsettings'] = $include_specialsettings;
$update_data['notryfiles'] = $notryfiles; $update_data['notryfiles'] = $notryfiles;
$update_data['writeaccesslog'] = $writeaccesslog; $update_data['writeaccesslog'] = $writeaccesslog;
$update_data['writeerrorlog'] = $writeerrorlog; $update_data['writeerrorlog'] = $writeerrorlog;
@@ -1305,6 +1635,14 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$update_data['hsts_sub'] = $hsts_sub; $update_data['hsts_sub'] = $hsts_sub;
$update_data['hsts_preload'] = $hsts_preload; $update_data['hsts_preload'] = $hsts_preload;
$update_data['ocsp_stapling'] = $ocsp_stapling; $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['sslenabled'] = $sslenabled;
$update_data['honorcipherorder'] = $honorcipherorder;
$update_data['sessiontickets'] = $sessiontickets;
$update_data['description'] = $description;
$update_data['id'] = $id; $update_data['id'] = $id;
$update_stmt = Database::prepare(" $update_stmt = Database::prepare("
@@ -1330,6 +1668,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
`mod_fcgid_starter` = :mod_fcgid_starter, `mod_fcgid_starter` = :mod_fcgid_starter,
`mod_fcgid_maxrequests` = :mod_fcgid_maxrequests, `mod_fcgid_maxrequests` = :mod_fcgid_maxrequests,
`specialsettings` = :specialsettings, `specialsettings` = :specialsettings,
`ssl_specialsettings` = :ssl_specialsettings,
`include_specialsettings` = :include_specialsettings,
`notryfiles` = :notryfiles, `notryfiles` = :notryfiles,
`writeaccesslog` = :writeaccesslog, `writeaccesslog` = :writeaccesslog,
`writeerrorlog` = :writeerrorlog, `writeerrorlog` = :writeerrorlog,
@@ -1341,7 +1681,15 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
`hsts` = :hsts, `hsts` = :hsts,
`hsts_sub` = :hsts_sub, `hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload, `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,
`ssl_enabled` = :sslenabled,
`ssl_honorcipherorder` = :honorcipherorder,
`ssl_sessiontickets` = :sessiontickets,
`description` = :description
WHERE `id` = :id WHERE `id` = :id
"); ");
Database::pexecute($update_stmt, $update_data, true, true); Database::pexecute($update_stmt, $update_data, true, true);
@@ -1352,6 +1700,15 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$_update_data['openbasedir'] = $openbasedir; $_update_data['openbasedir'] = $openbasedir;
$_update_data['mod_fcgid_starter'] = $mod_fcgid_starter; $_update_data['mod_fcgid_starter'] = $mod_fcgid_starter;
$_update_data['mod_fcgid_maxrequests'] = $mod_fcgid_maxrequests; $_update_data['mod_fcgid_maxrequests'] = $mod_fcgid_maxrequests;
$_update_data['notryfiles'] = $notryfiles;
$_update_data['writeaccesslog'] = $writeaccesslog;
$_update_data['writeerrorlog'] = $writeerrorlog;
$_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['honorcipherorder'] = $honorcipherorder;
$_update_data['sessiontickets'] = $sessiontickets;
$_update_data['parentdomainid'] = $id; $_update_data['parentdomainid'] = $id;
// if php config is to be set for all subdomains, check here // if php config is to be set for all subdomains, check here
@@ -1360,7 +1717,6 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$_update_data['phpsettingid'] = $phpsettingid; $_update_data['phpsettingid'] = $phpsettingid;
$update_phpconfig = ", `phpsettingid` = :phpsettingid"; $update_phpconfig = ", `phpsettingid` = :phpsettingid";
} }
// if we have no more ssl-ip's for this domain, // if we have no more ssl-ip's for this domain,
// all its subdomains must have "ssl-redirect = 0" // all its subdomains must have "ssl-redirect = 0"
// and disable let's encrypt // and disable let's encrypt
@@ -1376,15 +1732,21 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
`phpenabled` = :phpenabled, `phpenabled` = :phpenabled,
`openbasedir` = :openbasedir, `openbasedir` = :openbasedir,
`mod_fcgid_starter` = :mod_fcgid_starter, `mod_fcgid_starter` = :mod_fcgid_starter,
`mod_fcgid_maxrequests` = :mod_fcgid_maxrequests `mod_fcgid_maxrequests` = :mod_fcgid_maxrequests,
`notryfiles` = :notryfiles,
`writeaccesslog` = :writeaccesslog,
`writeerrorlog` = :writeerrorlog,
`override_tls` = :override_tls,
`ssl_protocols` = :ssl_protocols,
`ssl_cipher_list` = :ssl_cipher_list,
`tlsv13_cipher_list` = :tlsv13_cipher_list,
`ssl_honorcipherorder` = :honorcipherorder,
`ssl_sessiontickets` = :sessiontickets
" . $update_phpconfig . $upd_specialsettings . $updatechildren . $update_sslredirect . " " . $update_phpconfig . $upd_specialsettings . $updatechildren . $update_sslredirect . "
WHERE `parentdomainid` = :parentdomainid WHERE `parentdomainid` = :parentdomainid
"); ");
Database::pexecute($_update_stmt, $_update_data, true, true); Database::pexecute($_update_stmt, $_update_data, true, true);
// insert a rebuild-task
\Froxlor\System\Cronjob::inserttask('1');
// Cleanup domain <-> ip mapping // Cleanup domain <-> ip mapping
$del_stmt = Database::prepare(" $del_stmt = Database::prepare("
DELETE FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :id DELETE FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :id
@@ -1468,7 +1830,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$idna_convert = new \Froxlor\Idna\IdnaWrapper(); $idna_convert = new \Froxlor\Idna\IdnaWrapper();
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated domain '" . $idna_convert->decode($result['domain']) . "'"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated domain '" . $idna_convert->decode($result['domain']) . "'");
return $this->response(200, "successfull", $update_data); $result = $this->apiCall('Domains.get', array(
'domainname' => $result['domain']
));
return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -1629,7 +1994,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
\Froxlor\System\Cronjob::inserttask('1'); \Froxlor\System\Cronjob::inserttask('1');
// Using nameserver, insert a task which rebuilds the server config // Using nameserver, insert a task which rebuilds the server config
\Froxlor\System\Cronjob::inserttask('4'); \Froxlor\System\Cronjob::inserttask('4');
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -1701,8 +2066,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
} elseif ($edit_id > 0) { } elseif ($edit_id > 0) {
// set currently used ip's // set currently used ip's
$ipsresult_stmt = Database::prepare(" $ipsresult_stmt = Database::prepare("
SELECT `id_ipandports` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :id SELECT d2i.`id_ipandports`
"); FROM `" . TABLE_DOMAINTOIP . "` d2i
LEFT JOIN `" . TABLE_PANEL_IPSANDPORTS . "` i ON i.id = d2i.id_ipandports
WHERE d2i.`id_domain` = :id AND i.`ssl` = " . ($ssl ? "'1'" : "'0'"));
Database::pexecute($ipsresult_stmt, array( Database::pexecute($ipsresult_stmt, array(
'id' => $edit_id 'id' => $edit_id
), true, true); ), true, true);

View File

@@ -30,9 +30,9 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
* @param string $emailaddr * @param string $emailaddr
* optional email-address to add the account for * optional email-address to add the account for
* @param int $customerid * @param int $customerid
* optional, admin-only, the customer-id * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname * @param string $loginname
* optional, admin-only, the loginname * optional, required when called as admin (if $customerid is not specified)
* @param string $email_password * @param string $email_password
* password for the account * password for the account
* @param string $alternative_email * @param string $alternative_email
@@ -100,8 +100,8 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
// alternative email address to send info to // alternative email address to send info to
if (Settings::Get('panel.sendalternativemail') == 1) { if (Settings::Get('panel.sendalternativemail') == 1) {
$alternative_email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($alternative_email, 'alternative_email', '', '', array(), true)); $alternative_email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($alternative_email, 'alternative_email', '', '', array(), true));
if (! \Froxlor\Validate\Validate::validateEmail($alternative_email)) { if (! empty($alternative_email) && ! \Froxlor\Validate\Validate::validateEmail($alternative_email)) {
\Froxlor\UI\Response::standard_error('emailiswrong', $alternative_email, true); \Froxlor\UI\Response::standard_error('alternativeemailiswrong', $alternative_email, true);
} }
} else { } else {
$alternative_email = ''; $alternative_email = '';
@@ -192,7 +192,12 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
$replace_arr = array( $replace_arr = array(
'EMAIL' => $email_full, 'EMAIL' => $email_full,
'USERNAME' => $username, 'USERNAME' => $username,
'PASSWORD' => $password 'PASSWORD' => htmlentities(htmlentities($password)),
'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($customer),
'NAME' => $customer['name'],
'FIRSTNAME' => $customer['firstname'],
'COMPANY' => $customer['company'],
'CUSTOMER_NO' => $customer['customernumber']
); );
// get the customers admin // get the customers admin
@@ -231,7 +236,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
$this->mailer()->clearAddresses(); $this->mailer()->clearAddresses();
// customer wants to send the e-mail to an alternative email address too // customer wants to send the e-mail to an alternative email address too
if (Settings::Get('panel.sendalternativemail') == 1) { if (Settings::Get('panel.sendalternativemail') == 1 && ! empty($alternative_email)) {
// get template for mail subject // get template for mail subject
$mail_subject = $this->getMailTemplate($customer, 'mails', 'pop_success_alternative_subject', $replace_arr, $this->lng['mails']['pop_success_alternative']['subject']); $mail_subject = $this->getMailTemplate($customer, 'mails', 'pop_success_alternative_subject', $replace_arr, $this->lng['mails']['pop_success_alternative']['subject']);
// get template for mail body // get template for mail body
@@ -268,7 +273,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
$result = $this->apiCall('Emails.get', array( $result = $this->apiCall('Emails.get', array(
'emailaddr' => $result['email_full'] 'emailaddr' => $result['email_full']
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("No more resources available", 406); throw new \Exception("No more resources available", 406);
} }
@@ -290,13 +295,15 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
* @param string $emailaddr * @param string $emailaddr
* optional, the email-address to update * optional, the email-address to update
* @param int $customerid * @param int $customerid
* optional, admin-only, the customer-id * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname * @param string $loginname
* optional, admin-only, the loginname * optional, required when called as admin (if $customerid is not specified)
* @param int $email_quota * @param int $email_quota
* optional, update quota * optional, update quota
* @param string $email_password * @param string $email_password
* optional, update password * optional, update password
* @param bool $deactivated
* optional, admin-only
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -326,6 +333,7 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
$password = $this->getParam('email_password', true, ''); $password = $this->getParam('email_password', true, '');
$quota = $this->getParam('email_quota', true, $result['quota']); $quota = $this->getParam('email_quota', true, $result['quota']);
$deactivated = $this->getBoolParam('deactivated', true, (strtolower($result['postfix']) == 'n' ? true : false));
// get needed customer info to reduce the email-account-counter by one // get needed customer info to reduce the email-account-counter by one
$customer = $this->getCustomerData(); $customer = $this->getCustomerData();
@@ -367,6 +375,18 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
$quota = 0; $quota = 0;
} }
if ($this->isAdmin()) {
if (($deactivated == true && strtolower($result['postfix']) == 'y') || ($deactivated == false && strtolower($result['postfix']) == 'n')) {
if (! empty($upd_query)) {
$upd_query .= ", ";
}
$upd_query .= "`postfix` = :postfix, `imap` = :imap, `pop3` = :pop3";
$upd_params['postfix'] = $deactivated ? 'N' : 'Y';
$upd_params['imap'] = $deactivated ? '0' : '1';
$upd_params['pop3'] = $deactivated ? '0' : '1';
}
}
// build update query // build update query
if (! empty($upd_query)) { if (! empty($upd_query)) {
$upd_stmt = Database::prepare(" $upd_stmt = Database::prepare("
@@ -384,16 +404,25 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
$result = $this->apiCall('Emails.get', array( $result = $this->apiCall('Emails.get', array(
'emailaddr' => $result['email_full'] 'emailaddr' => $result['email_full']
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
/** /**
* You cannot directly list email forwarders. * You cannot directly list email accounts.
* You need to call Emails.listing() * You need to call Emails.listing()
*/ */
public function listing() public function listing()
{ {
throw new \Exception('You cannot directly list email forwarders. You need to call Emails.listing()', 303); throw new \Exception('You cannot directly list email accounts. You need to call Emails.listing()', 303);
}
/**
* You cannot directly count email accounts.
* You need to call Emails.listingCount()
*/
public function listingCount()
{
throw new \Exception('You cannot directly count email accounts. You need to call Emails.listingCount()', 303);
} }
/** /**
@@ -404,9 +433,9 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
* @param string $emailaddr * @param string $emailaddr
* optional, the email-address to delete the account for * optional, the email-address to delete the account for
* @param int $customerid * @param int $customerid
* optional, admin-only, the customer-id * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname * @param string $loginname
* optional, admin-only, the loginname * optional, required when called as admin (if $customerid is not specified)
* @param bool $delete_userfiles * @param bool $delete_userfiles
* optional, default false * optional, default false
* *
@@ -478,6 +507,6 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
Customers::decreaseUsage($customer['customerid'], 'email_quota_used', '', $quota); Customers::decreaseUsage($customer['customerid'], 'email_quota_used', '', $quota);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted email account for '" . $result['email_full'] . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted email account for '" . $result['email_full'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
} }

View File

@@ -30,9 +30,9 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
* @param string $emailaddr * @param string $emailaddr
* optional, the email-address to add the forwarder for * optional, the email-address to add the forwarder for
* @param int $customerid * @param int $customerid
* optional, admin-only, the customer-id * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname * @param string $loginname
* optional, admin-only, the loginname * optional, required when called as admin (if $customerid is not specified)
* @param string $destination * @param string $destination
* email-address to add as forwarder * email-address to add as forwarder
* *
@@ -102,18 +102,18 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
$result = $this->apiCall('Emails.get', array( $result = $this->apiCall('Emails.get', array(
'emailaddr' => $result['email_full'] 'emailaddr' => $result['email_full']
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("No more resources available", 406); throw new \Exception("No more resources available", 406);
} }
/** /**
* You cannot directly get an email forwarder. * You cannot directly get an email forwarder.
* You need to call Emails.get() * Try EmailForwarders.listing()
*/ */
public function get() public function get()
{ {
throw new \Exception('You cannot directly get an email forwarder. You need to call Emails.get()', 303); throw new \Exception('You cannot directly get an email forwarder. Try EmailForwarders.listing()', 303);
} }
/** /**
@@ -126,12 +126,91 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
} }
/** /**
* You cannot directly list email forwarders. * List email forwarders for a given email address
* You need to call Emails.listing() *
* @param int $id
* optional, the email-address-id
* @param string $emailaddr
* optional, the email-address to delete the forwarder from
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
*
* @access admin,customer
* @throws \Exception
* @return string json-encoded array count|list
*/ */
public function listing() public function listing()
{ {
throw new \Exception('You cannot directly list email forwarders. You need to call Emails.listing()', 303); if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
throw new \Exception("You cannot access this resource", 405);
}
// parameter
$id = $this->getParam('id', true, 0);
$ea_optional = ($id <= 0 ? false : true);
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
// validation
$result = $this->apiCall('Emails.get', array(
'id' => $id,
'emailaddr' => $emailaddr
));
$id = $result['id'];
$result['destination'] = explode(' ', $result['destination']);
$destination = array();
foreach ($result['destination'] as $index => $address) {
$destination[] = [
'id' => $index,
'address' => $address
];
}
return $this->response(200, "successful", [
'count' => count($destination),
'list' => $destination
]);
}
/**
* count email forwarders for a given email address
*
* @param int $id
* optional, the email-address-id
* @param string $emailaddr
* optional, the email-address to delete the forwarder from
* @param int $customerid
* optional, admin-only, the customer-id
* @param string $loginname
* optional, admin-only, the loginname
*
* @access admin,customer
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
throw new \Exception("You cannot access this resource", 405);
}
// parameter
$id = $this->getParam('id', true, 0);
$ea_optional = ($id <= 0 ? false : true);
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
// validation
$result = $this->apiCall('Emails.get', array(
'id' => $id,
'emailaddr' => $emailaddr
));
$id = $result['id'];
$result['destination'] = explode(' ', $result['destination']);
return $this->response(200, "successful", count($result['destination']));
} }
/** /**
@@ -142,9 +221,9 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
* @param string $emailaddr * @param string $emailaddr
* optional, the email-address to delete the forwarder from * optional, the email-address to delete the forwarder from
* @param int $customerid * @param int $customerid
* optional, admin-only, the customer-id * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname * @param string $loginname
* optional, admin-only, the loginname * optional, required when called as admin (if $customerid is not specified)
* @param int $forwarderid * @param int $forwarderid
* id of the forwarder to delete * id of the forwarder to delete
* *
@@ -201,7 +280,7 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
$result = $this->apiCall('Emails.get', array( $result = $this->apiCall('Emails.get', array(
'emailaddr' => $result['email_full'] 'emailaddr' => $result['email_full']
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Unknown forwarder id", 404); throw new \Exception("Unknown forwarder id", 404);
} }

View File

@@ -32,9 +32,11 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* @param boolean $iscatchall * @param boolean $iscatchall
* optional, make this address a catchall address, default: no * optional, make this address a catchall address, default: no
* @param int $customerid * @param int $customerid
* optional, admin-only, the customer-id * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname * @param string $loginname
* optional, admin-only, the loginname * optional, required when called as admin (if $customerid is not specified)
* @param string $description
* optional custom description (currently not used/shown in the frontend), default empty
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -54,6 +56,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// parameters // parameters
$iscatchall = $this->getBoolParam('iscatchall', true, 0); $iscatchall = $this->getBoolParam('iscatchall', true, 0);
$description = $this->getParam('description', true, '');
// validation // validation
if (substr($domain, 0, 4) != 'xn--') { if (substr($domain, 0, 4) != 'xn--') {
@@ -62,9 +65,10 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
} }
// check domain and whether it's an email-enabled domain // check domain and whether it's an email-enabled domain
// use internal call because the customer might have 'domains' in customer_hide_options
$domain_check = $this->apiCall('SubDomains.get', array( $domain_check = $this->apiCall('SubDomains.get', array(
'domainname' => $domain 'domainname' => $domain
)); ), true);
if ($domain_check['isemaildomain'] == 0) { if ($domain_check['isemaildomain'] == 0) {
\Froxlor\UI\Response::standard_error('maindomainnonexist', $domain, true); \Froxlor\UI\Response::standard_error('maindomainnonexist', $domain, true);
} }
@@ -106,11 +110,13 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
); );
$email_check = Database::pexecute_first($stmt, $params, true, true); $email_check = Database::pexecute_first($stmt, $params, true, true);
if ($email_check) {
if (strtolower($email_check['email_full']) == strtolower($email_full)) { if (strtolower($email_check['email_full']) == strtolower($email_full)) {
\Froxlor\UI\Response::standard_error('emailexistalready', $email_full, true); \Froxlor\UI\Response::standard_error('emailexistalready', $email_full, true);
} elseif ($email_check['email'] == $email) { } elseif ($email_check['email'] == $email) {
\Froxlor\UI\Response::standard_error('youhavealreadyacatchallforthisdomain', '', true); \Froxlor\UI\Response::standard_error('youhavealreadyacatchallforthisdomain', '', true);
} }
}
$stmt = Database::prepare(" $stmt = Database::prepare("
INSERT INTO `" . TABLE_MAIL_VIRTUAL . "` SET INSERT INTO `" . TABLE_MAIL_VIRTUAL . "` SET
@@ -118,14 +124,16 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
`email` = :email, `email` = :email,
`email_full` = :email_full, `email_full` = :email_full,
`iscatchall` = :iscatchall, `iscatchall` = :iscatchall,
`domainid` = :domainid `domainid` = :domainid,
`description` = :description
"); ");
$params = array( $params = array(
"cid" => $customer['customerid'], "cid" => $customer['customerid'],
"email" => $email, "email" => $email,
"email_full" => $email_full, "email_full" => $email_full,
"iscatchall" => $iscatchall, "iscatchall" => $iscatchall,
"domainid" => $domain_check['id'] "domainid" => $domain_check['id'],
"description" => $description
); );
Database::pexecute($stmt, $params, true, true); Database::pexecute($stmt, $params, true, true);
@@ -137,7 +145,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$result = $this->apiCall('Emails.get', array( $result = $this->apiCall('Emails.get', array(
'emailaddr' => $email_full 'emailaddr' => $email_full
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("No more resources available", 406); throw new \Exception("No more resources available", 406);
} }
@@ -164,7 +172,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$customer_ids = $this->getAllowedCustomerIds('email'); $customer_ids = $this->getAllowedCustomerIds('email');
$params['idea'] = ($id <= 0 ? $emailaddr : $id); $params['idea'] = ($id <= 0 ? $emailaddr : $id);
$result_stmt = Database::prepare("SELECT v.`id`, v.`email`, v.`email_full`, v.`iscatchall`, v.`destination`, v.`customerid`, v.`popaccountid`, v.`domainid`, u.`quota` $result_stmt = Database::prepare("SELECT v.`id`, v.`email`, v.`email_full`, v.`iscatchall`, v.`destination`, v.`customerid`, v.`popaccountid`, v.`domainid`, v.`description`, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize`
FROM `" . TABLE_MAIL_VIRTUAL . "` v FROM `" . TABLE_MAIL_VIRTUAL . "` v
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON v.`popaccountid` = u.`id` LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON v.`popaccountid` = u.`id`
WHERE v.`customerid` IN (" . implode(", ", $customer_ids) . ") WHERE v.`customerid` IN (" . implode(", ", $customer_ids) . ")
@@ -173,7 +181,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$result = Database::pexecute_first($result_stmt, $params, true, true); $result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) { if ($result) {
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get email address '" . $result['email_full'] . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get email address '" . $result['email_full'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
$key = ($id > 0 ? "id #" . $id : "emailaddr '" . $emailaddr . "'"); $key = ($id > 0 ? "id #" . $id : "emailaddr '" . $emailaddr . "'");
throw new \Exception("Email address with " . $key . " could not be found", 404); throw new \Exception("Email address with " . $key . " could not be found", 404);
@@ -187,11 +195,13 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* @param string $emailaddr * @param string $emailaddr
* optional, the email-address * optional, the email-address
* @param int $customerid * @param int $customerid
* optional, admin-only, the customer-id * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname * @param string $loginname
* optional, admin-only, the loginname * optional, required when called as admin (if $customerid is not specified)
* @param boolean $iscatchall * @param boolean $iscatchall
* optional * optional
* @param string $description
* optional custom description (currently not used/shown in the frontend), default empty
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -224,6 +234,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// parameters // parameters
$iscatchall = $this->getBoolParam('iscatchall', true, $result['iscatchall']); $iscatchall = $this->getBoolParam('iscatchall', true, $result['iscatchall']);
$description = $this->getParam('description', true, $result['description']);
// get needed customer info to reduce the email-address-counter by one // get needed customer info to reduce the email-address-counter by one
$customer = $this->getCustomerData(); $customer = $this->getCustomerData();
@@ -233,6 +244,19 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$iscatchall = '1'; $iscatchall = '1';
$email_parts = explode('@', $result['email_full']); $email_parts = explode('@', $result['email_full']);
$email = '@' . $email_parts[1]; $email = '@' . $email_parts[1];
// catchall check
$stmt = Database::prepare("
SELECT `email_full` FROM `" . TABLE_MAIL_VIRTUAL . "`
WHERE `email` = :email AND `customerid` = :cid AND `iscatchall` = '1'
");
$params = array(
"email" => $email,
"cid" => $customer['customerid']
);
$email_check = Database::pexecute_first($stmt, $params, true, true);
if ($email_check) {
\Froxlor\UI\Response::standard_error('youhavealreadyacatchallforthisdomain', '', true);
}
} else { } else {
$iscatchall = '0'; $iscatchall = '0';
$email = $result['email_full']; $email = $result['email_full'];
@@ -240,12 +264,13 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$stmt = Database::prepare(" $stmt = Database::prepare("
UPDATE `" . TABLE_MAIL_VIRTUAL . "` UPDATE `" . TABLE_MAIL_VIRTUAL . "`
SET `email` = :email , `iscatchall` = :caflag SET `email` = :email , `iscatchall` = :caflag, `description` = :description
WHERE `customerid`= :cid AND `id`= :id WHERE `customerid`= :cid AND `id`= :id
"); ");
$params = array( $params = array(
"email" => $email, "email" => $email,
"caflag" => $iscatchall, "caflag" => $iscatchall,
"description" => $description,
"cid" => $customer['customerid'], "cid" => $customer['customerid'],
"id" => $id "id" => $id
); );
@@ -255,7 +280,7 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$result = $this->apiCall('Emails.get', array( $result = $this->apiCall('Emails.get', array(
'emailaddr' => $result['email_full'] 'emailaddr' => $result['email_full']
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
/** /**
@@ -265,6 +290,14 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, admin-only, select email addresses of a specific customer by id * optional, admin-only, select email addresses of a specific customer by id
* @param string $loginname * @param string $loginname
* optional, admin-only, select email addresses of a specific customer by loginname * optional, admin-only, select email addresses of a specific customer by loginname
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -274,22 +307,50 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
{ {
$customer_ids = $this->getAllowedCustomerIds('email'); $customer_ids = $this->getAllowedCustomerIds('email');
$result = array(); $result = array();
$query_fields = array();
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT m.`id`, m.`domainid`, m.`email`, m.`email_full`, m.`iscatchall`, u.`quota`, m.`destination`, m.`popaccountid`, d.`domain`, u.`mboxsize` SELECT m.`id`, m.`domainid`, m.`email`, m.`email_full`, m.`iscatchall`, m.`destination`, m.`popaccountid`, d.`domain`, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize`
FROM `" . TABLE_MAIL_VIRTUAL . "` m
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON (m.`domainid` = d.`id`)
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON (m.`popaccountid` = u.`id`)
WHERE m.`customerid` IN (" . implode(", ", $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
Database::pexecute($result_stmt, $query_fields, true, true);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
}
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list email-addresses");
return $this->response(200, "successful", array(
'count' => count($result),
'list' => $result
));
}
/**
* returns the total number of accessible email addresses
*
* @param int $customerid
* optional, admin-only, select email addresses of a specific customer by id
* @param string $loginname
* optional, admin-only, select email addresses of a specific customer by loginname
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
$customer_ids = $this->getAllowedCustomerIds('email');
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_emails
FROM `" . TABLE_MAIL_VIRTUAL . "` m FROM `" . TABLE_MAIL_VIRTUAL . "` m
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON (m.`domainid` = d.`id`) LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON (m.`domainid` = d.`id`)
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON (m.`popaccountid` = u.`id`) LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON (m.`popaccountid` = u.`id`)
WHERE m.`customerid` IN (" . implode(", ", $customer_ids) . ") WHERE m.`customerid` IN (" . implode(", ", $customer_ids) . ")
"); ");
Database::pexecute($result_stmt, null, true, true); $result = Database::pexecute_first($result_stmt, null, true, true);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { if ($result) {
$result[] = $row; return $this->response(200, "successful", $result['num_emails']);
} }
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list email-addresses");
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
} }
/** /**
@@ -300,9 +361,9 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* @param string $emailaddr * @param string $emailaddr
* optional, the email-address * optional, the email-address
* @param int $customerid * @param int $customerid
* optional, admin-only, the customer-id * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname * @param string $loginname
* optional, admin-only, the loginname * optional, required when called as admin (if $customerid is not specified)
* @param boolean $delete_userfiles * @param boolean $delete_userfiles
* optional, delete email data from filesystem, default: 0 (false) * optional, delete email data from filesystem, default: 0 (false)
* *
@@ -353,10 +414,6 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
Customers::decreaseUsage($customer['customerid'], 'email_forwarders_used', '', $number_forwarders); Customers::decreaseUsage($customer['customerid'], 'email_forwarders_used', '', $number_forwarders);
Admins::decreaseUsage($customer['customerid'], 'email_forwarders_used', '', $number_forwarders); Admins::decreaseUsage($customer['customerid'], 'email_forwarders_used', '', $number_forwarders);
if ($delete_userfiles) {
\Froxlor\System\Cronjob::inserttask('7', $customer['loginname'], $result['email_full']);
}
// delete address // delete address
$stmt = Database::prepare("DELETE FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE `customerid`= :customerid AND `id`= :id"); $stmt = Database::prepare("DELETE FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE `customerid`= :customerid AND `id`= :id");
Database::pexecute($stmt, array( Database::pexecute($stmt, array(
@@ -366,6 +423,6 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
Customers::decreaseUsage($customer['customerid'], 'emails_used'); Customers::decreaseUsage($customer['customerid'], 'emails_used');
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted email address '" . $result['email_full'] . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted email address '" . $result['email_full'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
} }

View File

@@ -24,6 +24,15 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
/** /**
* lists all fpm-daemon entries * lists all fpm-daemon entries
* *
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin * @access admin
* @throws \Exception * @throws \Exception
* @return string json-encoded array count|list * @return string json-encoded array count|list
@@ -32,21 +41,18 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
{ {
if ($this->isAdmin()) { if ($this->isAdmin()) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list fpm-daemons"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list fpm-daemons");
$query_fields = array();
$result = Database::query(" $result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` ORDER BY `description` ASC SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "`" . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit());
"); Database::pexecute($result_stmt, $query_fields, true, true);
$fpmdaemons = array(); $fpmdaemons = array();
while ($row = $result->fetch(\PDO::FETCH_ASSOC)) { while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$query_params = array( $query_params = array(
'id' => $row['id'] 'id' => $row['id']
); );
$query = "SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `fpmsettingid` = :id"; $configresult_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `fpmsettingid` = :id");
$configresult_stmt = Database::prepare($query);
Database::pexecute($configresult_stmt, $query_params, true, true); Database::pexecute($configresult_stmt, $query_params, true, true);
$configs = array(); $configs = array();
@@ -64,7 +70,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$fpmdaemons[] = $row; $fpmdaemons[] = $row;
} }
return $this->response(200, "successfull", array( return $this->response(200, "successful", array(
'count' => count($fpmdaemons), 'count' => count($fpmdaemons),
'list' => $fpmdaemons 'list' => $fpmdaemons
)); ));
@@ -72,6 +78,27 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
/**
* returns the total number of accessible fpm daemons
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin()) {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_fpms FROM `" . TABLE_PANEL_FPMDAEMONS . "`
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successful", $result['num_fpms']);
}
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/** /**
* return a fpm-daemon entry by id * return a fpm-daemon entry by id
* *
@@ -94,7 +121,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
'id' => $id 'id' => $id
), true, true); ), true, true);
if ($result) { if ($result) {
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("fpm-daemon with id #" . $id . " could not be found", 404); throw new \Exception("fpm-daemon with id #" . $id . " could not be found", 404);
} }
@@ -108,21 +135,23 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* @param string $reload_cmd * @param string $reload_cmd
* @param string $config_dir * @param string $config_dir
* @param string $pm * @param string $pm
* optional, process-manager, one of 'static', 'dynamic' or 'ondemand', default 'static' * optional, process-manager, one of 'static', 'dynamic' or 'ondemand', default 'dynamic'
* @param int $max_children * @param int $max_children
* optional, default 0 * optional, default 5
* @param int $start_servers * @param int $start_servers
* optional, default 0 * optional, default 2
* @param int $min_spare_servers * @param int $min_spare_servers
* optional, default 0 * optional, default 1
* @param int $max_spare_servers * @param int $max_spare_servers
* optional, default 0 * optional, default 3
* @param int $max_requests * @param int $max_requests
* optional, default 0 * optional, default 0
* @param int $idle_timeout * @param int $idle_timeout
* optional, default 0 * optional, default 10
* @param string $limit_extensions * @param string $limit_extensions
* optional, limit execution to the following extensions, default '.php' * optional, limit execution to the following extensions, default '.php'
* @param string $custom_config
* optional, custom settings appended to phpfpm pool configuration
* *
* @access admin * @access admin
* @throws \Exception * @throws \Exception
@@ -138,14 +167,15 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$config_dir = $this->getParam('config_dir'); $config_dir = $this->getParam('config_dir');
// parameters // parameters
$pmanager = $this->getParam('pm', true, 'static'); $pmanager = $this->getParam('pm', true, 'dynamic');
$max_children = $this->getParam('max_children', true, 0); $max_children = $this->getParam('max_children', true, 5);
$start_servers = $this->getParam('start_servers', true, 0); $start_servers = $this->getParam('start_servers', true, 2);
$min_spare_servers = $this->getParam('min_spare_servers', true, 0); $min_spare_servers = $this->getParam('min_spare_servers', true, 1);
$max_spare_servers = $this->getParam('max_spare_servers', true, 0); $max_spare_servers = $this->getParam('max_spare_servers', true, 3);
$max_requests = $this->getParam('max_requests', true, 0); $max_requests = $this->getParam('max_requests', true, 0);
$idle_timeout = $this->getParam('idle_timeout', true, 0); $idle_timeout = $this->getParam('idle_timeout', true, 10);
$limit_extensions = $this->getParam('limit_extensions', true, '.php'); $limit_extensions = $this->getParam('limit_extensions', true, '.php');
$custom_config = $this->getParam('custom_config', true, '');
// validation // validation
$description = \Froxlor\Validate\Validate::validate($description, 'description', '', '', array(), true); $description = \Froxlor\Validate\Validate::validate($description, 'description', '', '', array(), true);
@@ -179,7 +209,8 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
`max_spare_servers` = :max_spare_servers, `max_spare_servers` = :max_spare_servers,
`max_requests` = :max_requests, `max_requests` = :max_requests,
`idle_timeout` = :idle_timeout, `idle_timeout` = :idle_timeout,
`limit_extensions` = :limit_extensions `limit_extensions` = :limit_extensions,
`custom_config` = :custom_config
"); ");
$ins_data = array( $ins_data = array(
'desc' => $description, 'desc' => $description,
@@ -192,7 +223,8 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
'max_spare_servers' => $max_spare_servers, 'max_spare_servers' => $max_spare_servers,
'max_requests' => $max_requests, 'max_requests' => $max_requests,
'idle_timeout' => $idle_timeout, 'idle_timeout' => $idle_timeout,
'limit_extensions' => $limit_extensions 'limit_extensions' => $limit_extensions,
'custom_config' => $custom_config
); );
Database::pexecute($ins_stmt, $ins_data); Database::pexecute($ins_stmt, $ins_data);
$id = Database::lastInsertId(); $id = Database::lastInsertId();
@@ -202,7 +234,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$result = $this->apiCall('FpmDaemons.get', array( $result = $this->apiCall('FpmDaemons.get', array(
'id' => $id 'id' => $id
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -219,21 +251,23 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* @param string $config_dir * @param string $config_dir
* optional * optional
* @param string $pm * @param string $pm
* optional, process-manager, one of 'static', 'dynamic' or 'ondemand', default 'static' * optional, process-manager, one of 'static', 'dynamic' or 'ondemand', default 'dynamic'
* @param int $max_children * @param int $max_children
* optional, default 0 * optional, default 5
* @param int $start_servers * @param int $start_servers
* optional, default 0 * optional, default 2
* @param int $min_spare_servers * @param int $min_spare_servers
* optional, default 0 * optional, default 1
* @param int $max_spare_servers * @param int $max_spare_servers
* optional, default 0 * optional, default 3
* @param int $max_requests * @param int $max_requests
* optional, default 0 * optional, default 0
* @param int $idle_timeout * @param int $idle_timeout
* optional, default 0 * optional, default 10
* @param string $limit_extensions * @param string $limit_extensions
* optional, limit execution to the following extensions, default '.php' * optional, limit execution to the following extensions, default '.php'
* @param string $custom_config
* optional, custom settings appended to phpfpm pool configuration
* *
* @access admin * @access admin
* @throws \Exception * @throws \Exception
@@ -262,6 +296,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$max_requests = $this->getParam('max_requests', true, $result['max_requests']); $max_requests = $this->getParam('max_requests', true, $result['max_requests']);
$idle_timeout = $this->getParam('idle_timeout', true, $result['idle_timeout']); $idle_timeout = $this->getParam('idle_timeout', true, $result['idle_timeout']);
$limit_extensions = $this->getParam('limit_extensions', true, $result['limit_extensions']); $limit_extensions = $this->getParam('limit_extensions', true, $result['limit_extensions']);
$custom_config = $this->getParam('custom_config', true, $result['custom_config']);
// validation // validation
$description = \Froxlor\Validate\Validate::validate($description, 'description', '', '', array(), true); $description = \Froxlor\Validate\Validate::validate($description, 'description', '', '', array(), true);
@@ -295,7 +330,8 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
`max_spare_servers` = :max_spare_servers, `max_spare_servers` = :max_spare_servers,
`max_requests` = :max_requests, `max_requests` = :max_requests,
`idle_timeout` = :idle_timeout, `idle_timeout` = :idle_timeout,
`limit_extensions` = :limit_extensions `limit_extensions` = :limit_extensions,
`custom_config` = :custom_config
WHERE `id` = :id WHERE `id` = :id
"); ");
$upd_data = array( $upd_data = array(
@@ -310,6 +346,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
'max_requests' => $max_requests, 'max_requests' => $max_requests,
'idle_timeout' => $idle_timeout, 'idle_timeout' => $idle_timeout,
'limit_extensions' => $limit_extensions, 'limit_extensions' => $limit_extensions,
'custom_config' => $custom_config,
'id' => $id 'id' => $id
); );
Database::pexecute($upd_stmt, $upd_data, true, true); Database::pexecute($upd_stmt, $upd_data, true, true);
@@ -319,7 +356,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$result = $this->apiCall('FpmDaemons.get', array( $result = $this->apiCall('FpmDaemons.get', array(
'id' => $id 'id' => $id
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -365,7 +402,7 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
\Froxlor\System\Cronjob::inserttask('1'); \Froxlor\System\Cronjob::inserttask('1');
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] fpm-daemon setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] fpm-daemon setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }

View File

@@ -74,7 +74,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand
// zum update schritt #1 -> download // zum update schritt #1 -> download
if ($isnewerversion == 1) { if ($isnewerversion == 1) {
$text = 'There is a newer version available: "' . $_version . '" (Your current version is: ' . $this->version . ')'; $text = 'There is a newer version available: "' . $_version . '" (Your current version is: ' . $this->version . ')';
return $this->response(200, "successfull", array( return $this->response(200, "successful", array(
'isnewerversion' => $isnewerversion, 'isnewerversion' => $isnewerversion,
'version' => $_version, 'version' => $_version,
'message' => $text, 'message' => $text,
@@ -83,7 +83,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand
)); ));
} elseif ($isnewerversion == 0) { } elseif ($isnewerversion == 0) {
// all good // all good
return $this->response(200, "successfull", array( return $this->response(200, "successful", array(
'isnewerversion' => $isnewerversion, 'isnewerversion' => $isnewerversion,
'version' => $version_label, 'version' => $version_label,
'message' => "", 'message' => "",
@@ -95,7 +95,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand
} }
} }
} }
return $this->response(300, "successfull", array( return $this->response(300, "successful", array(
'isnewerversion' => 0, 'isnewerversion' => 0,
'version' => $this->version . $this->branding, 'version' => $this->version . $this->branding,
'message' => 'Version-check not available due to missing php-curl extension', 'message' => 'Version-check not available due to missing php-curl extension',
@@ -129,7 +129,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand
\Froxlor\System\Cronjob::inserttask('4'); \Froxlor\System\Cronjob::inserttask('4');
// cron.d file // cron.d file
\Froxlor\System\Cronjob::inserttask('99'); \Froxlor\System\Cronjob::inserttask('99');
return $this->response(200, "successfull", true); return $this->response(200, "successful", true);
} catch (\Exception $e) { } catch (\Exception $e) {
throw new \Exception($e->getMessage(), 406); throw new \Exception($e->getMessage(), 406);
} }
@@ -149,7 +149,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) { if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "User " . $this->getUserDetail('loginname') . " exported settings"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "User " . $this->getUserDetail('loginname') . " exported settings");
$json_export = \Froxlor\SImExporter::export(); $json_export = \Froxlor\SImExporter::export();
return $this->response(200, "successfull", $json_export); return $this->response(200, "successful", $json_export);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -175,7 +175,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand
'value' => $row['value'] 'value' => $row['value']
); );
} }
return $this->response(200, "successfull", array( return $this->response(200, "successful", array(
'count' => count($result), 'count' => count($result),
'list' => $result 'list' => $result
)); ));
@@ -197,7 +197,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand
{ {
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) { if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
$setting = $this->getParam('key'); $setting = $this->getParam('key');
return $this->response(200, "successfull", Settings::Get($setting)); return $this->response(200, "successful", Settings::Get($setting));
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -216,7 +216,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand
*/ */
public function updateSetting() public function updateSetting()
{ {
// currently not implemented as it required validation too so no wrong settings are being stored via API // currently not implemented as it requires validation too so no wrong settings are being stored via API
throw new \Exception("Not available yet.", 501); throw new \Exception("Not available yet.", 501);
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) { if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
@@ -227,7 +227,38 @@ class Froxlor extends \Froxlor\Api\ApiCommand
throw new \Exception("Setting '" . $setting . "' could not be found"); throw new \Exception("Setting '" . $setting . "' could not be found");
} }
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] Changing setting '" . $setting . "' from '" . $oldvalue . "' to '" . $value . "'"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] Changing setting '" . $setting . "' from '" . $oldvalue . "' to '" . $value . "'");
return $this->response(200, "successfull", Settings::Set($setting, $value, true)); return $this->response(200, "successful", Settings::Set($setting, $value, true));
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* returns a random password based on froxlor settings for min-length, included characters, etc.
*
* @access admin, customer
* @return string
*/
public function generatePassword()
{
return $this->response(200, "successful", \Froxlor\System\Crypt::generatePassword());
}
/**
* can be used to remotely run the integritiy checks froxlor implements
*
* @access admin
* @throws \Exception
* @return string
*/
public function integrityCheck()
{
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
$integrity = new \Froxlor\Database\IntegrityCheck();
$result = $integrity->checkAll();
if ($result) {
return $this->response(200, "successful", "OK");
}
throw new \Exception("Some checks failed.", 406);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -302,7 +333,7 @@ class Froxlor extends \Froxlor\Api\ApiCommand
} }
// return the list // return the list
return $this->response(200, "successfull", $functions); return $this->response(200, "successful", $functions);
} }
/** /**

View File

@@ -40,7 +40,9 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
* @param string $ftp_domain * @param string $ftp_domain
* optional if customer.ftpatdomain is allowed, specify a domain (customer must be owner) * optional if customer.ftpatdomain is allowed, specify a domain (customer must be owner)
* @param int $customerid * @param int $customerid
* required when called as admin, not needed when called as customer * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
* @param array $additional_members * @param array $additional_members
* optional whether to add additional usernames to the group * optional whether to add additional usernames to the group
* @param bool $is_defaultuser * @param bool $is_defaultuser
@@ -56,9 +58,11 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
throw new \Exception("You cannot access this resource", 405); 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);
// required paramters if (($this->getUserDetail('ftps_used') < $this->getUserDetail('ftps') || $this->getUserDetail('ftps') == '-1') || $this->isAdmin() && $is_defaultuser == 1) {
// required parameters
$path = $this->getParam('path'); $path = $this->getParam('path');
$password = $this->getParam('ftp_password'); $password = $this->getParam('ftp_password');
@@ -71,7 +75,6 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
$ftpdomain = $this->getParam('ftp_domain', true, ''); $ftpdomain = $this->getParam('ftp_domain', true, '');
$additional_members = $this->getParam('additional_members', true, array()); $additional_members = $this->getParam('additional_members', true, array());
$is_defaultuser = $this->getBoolParam('is_defaultuser', true, 0);
// validation // validation
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
@@ -179,6 +182,17 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
), true, true); ), true, true);
} }
// create quotatallies entry if it not exists, refs #885
if ($result_stmt->rowCount() == 0) {
$stmt = Database::prepare("INSERT INTO `" . TABLE_FTP_QUOTATALLIES . "`
(`name`, `quota_type`, `bytes_in_used`, `bytes_out_used`, `bytes_xfer_used`, `files_in_used`, `files_out_used`, `files_xfer_used`)
VALUES (:name, 'user', '0', '0', '0', '0', '0', '0')
");
Database::pexecute($stmt, array(
"name" => $username
), true, true);
}
$group_upd_stmt = Database::prepare(" $group_upd_stmt = Database::prepare("
UPDATE `" . TABLE_FTP_GROUPS . "` UPDATE `" . TABLE_FTP_GROUPS . "`
SET `members` = CONCAT_WS(',',`members`, :username) SET `members` = CONCAT_WS(',',`members`, :username)
@@ -226,8 +240,12 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
$replace_arr = array( $replace_arr = array(
'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($customer), 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($customer),
'CUST_NAME' => \Froxlor\User::getCorrectUserSalutation($customer), // < keep this for compatibility 'CUST_NAME' => \Froxlor\User::getCorrectUserSalutation($customer), // < keep this for compatibility
'NAME' => $customer['name'],
'FIRSTNAME' => $customer['firstname'],
'COMPANY' => $customer['company'],
'CUSTOMER_NO' => $customer['customernumber'],
'USR_NAME' => $username, 'USR_NAME' => $username,
'USR_PASS' => $password, 'USR_PASS' => htmlentities(htmlentities($password)),
'USR_PATH' => \Froxlor\FileDir::makeCorrectDir(str_replace($customer['documentroot'], "/", $path)) 'USR_PATH' => \Froxlor\FileDir::makeCorrectDir(str_replace($customer['documentroot'], "/", $path))
); );
// get template for mail subject // get template for mail subject
@@ -263,7 +281,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
$result = $this->apiCall('Ftps.get', array( $result = $this->apiCall('Ftps.get', array(
'username' => $username 'username' => $username
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
} }
throw new \Exception("No more resources available", 406); throw new \Exception("No more resources available", 406);
@@ -324,7 +342,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
$result = Database::pexecute_first($result_stmt, $params, true, true); $result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) { if ($result) {
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get ftp-user '" . $result['username'] . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get ftp-user '" . $result['username'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
$key = ($id > 0 ? "id #" . $id : "username '" . $username . "'"); $key = ($id > 0 ? "id #" . $id : "username '" . $username . "'");
throw new \Exception("FTP user with " . $key . " could not be found", 404); throw new \Exception("FTP user with " . $key . " could not be found", 404);
@@ -334,11 +352,11 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
* update a given ftp-user by id or username * update a given ftp-user by id or username
* *
* @param int $id * @param int $id
* optional, the customer-id * optional, the ftp-user-id
* @param string $username * @param string $username
* optional, the username * optional, the username
* @param string $ftp_password * @param string $ftp_password
* password for the created database and database-user * optional, update password if specified
* @param string $path * @param string $path
* destination path relative to the customers-homedir * destination path relative to the customers-homedir
* @param string $ftp_description * @param string $ftp_description
@@ -346,7 +364,9 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
* @param string $shell * @param string $shell
* optional, default /bin/false (not changeable when deactivated) * optional, default /bin/false (not changeable when deactivated)
* @param int $customerid * @param int $customerid
* required when called as admin, not needed when called as customer * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -449,7 +469,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
'username' => $result['username'] 'username' => $result['username']
)); ));
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] updated ftp-user '" . $result['username'] . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] updated ftp-user '" . $result['username'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
/** /**
@@ -459,6 +479,14 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
* optional, admin-only, select ftp-users of a specific customer by id * optional, admin-only, select ftp-users of a specific customer by id
* @param string $loginname * @param string $loginname
* optional, admin-only, select ftp-users of a specific customer by loginname * optional, admin-only, select ftp-users of a specific customer by loginname
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -468,21 +496,47 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
{ {
$customer_ids = $this->getAllowedCustomerIds('ftp'); $customer_ids = $this->getAllowedCustomerIds('ftp');
$result = array(); $result = array();
$query_fields = array();
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_FTP_USERS . "` SELECT * FROM `" . TABLE_FTP_USERS . "`
WHERE `customerid` IN (" . implode(", ", $customer_ids) . ") WHERE `customerid` IN (" . implode(", ", $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
"); Database::pexecute($result_stmt, $query_fields, true, true);
Database::pexecute($result_stmt, null, true, true);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row; $result[] = $row;
} }
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list ftp-users"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list ftp-users");
return $this->response(200, "successfull", array( return $this->response(200, "successful", array(
'count' => count($result), 'count' => count($result),
'list' => $result 'list' => $result
)); ));
} }
/**
* returns the total number of accessible ftp accounts
*
* @param int $customerid
* optional, admin-only, select ftp-users of a specific customer by id
* @param string $loginname
* optional, admin-only, select ftp-users of a specific customer by loginname
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
$customer_ids = $this->getAllowedCustomerIds('ftp');
$result = array();
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_ftps FROM `" . TABLE_FTP_USERS . "`
WHERE `customerid` IN (" . implode(", ", $customer_ids) . ")
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successful", $result['num_ftps']);
}
}
/** /**
* delete a ftp-user by either id or username * delete a ftp-user by either id or username
* *
@@ -541,6 +595,9 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
"username" => $customer_data['loginname'] "username" => $customer_data['loginname']
); );
Database::pexecute($stmt, $params, true, true); 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 // remove all quotatallies
@@ -584,6 +641,6 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
Customers::decreaseUsage($customer_data['customerid'], 'ftps_used', $resetaccnumber); Customers::decreaseUsage($customer_data['customerid'], 'ftps_used', $resetaccnumber);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted ftp-user '" . $result['username'] . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted ftp-user '" . $result['username'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
} }

View File

@@ -25,6 +25,15 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
/** /**
* list all available hosting plans * list all available hosting plans
* *
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin * @access admin
* @throws \Exception * @throws \Exception
* @return string json-encoded array count|list * @return string json-encoded array count|list
@@ -33,23 +42,51 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
{ {
if ($this->isAdmin()) { if ($this->isAdmin()) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list hosting-plans"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list hosting-plans");
$query_fields = array();
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT p.*, a.loginname as adminname SELECT p.*, a.loginname as adminname
FROM `" . TABLE_PANEL_PLANS . "` p, `" . TABLE_PANEL_ADMINS . "` a FROM `" . TABLE_PANEL_PLANS . "` p, `" . TABLE_PANEL_ADMINS . "` a
WHERE `p`.`adminid` = `a`.`adminid`" . ($this->getUserDetail('customers_see_all') ? '' : " AND `p`.`adminid` = :adminid ") . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
$params = array();
if ($this->getUserDetail('customers_see_all') == '0') {
$params['adminid'] = $this->getUserDetail('adminid');
}
$params = array_merge($params, $query_fields);
Database::pexecute($result_stmt, $params, true, true);
$result = array();
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
}
return $this->response(200, "successful", array(
'count' => count($result),
'list' => $result
));
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/**
* returns the total number of accessible hosting plans
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin()) {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_plans
FROM `" . TABLE_PANEL_PLANS . "` p, `" . TABLE_PANEL_ADMINS . "` a
WHERE `p`.`adminid` = `a`.`adminid`" . ($this->getUserDetail('customers_see_all') ? '' : " AND `p`.`adminid` = :adminid ")); WHERE `p`.`adminid` = `a`.`adminid`" . ($this->getUserDetail('customers_see_all') ? '' : " AND `p`.`adminid` = :adminid "));
$params = array(); $params = array();
if ($this->getUserDetail('customers_see_all') == '0') { if ($this->getUserDetail('customers_see_all') == '0') {
$params['adminid'] = $this->getUserDetail('adminid'); $params['adminid'] = $this->getUserDetail('adminid');
} }
Database::pexecute($result_stmt, $params); $result = Database::pexecute_first($result_stmt, $params, true, true);
$result = array(); if ($result) {
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { return $this->response(200, "successful", $result['num_plans']);
$result[] = $row;
} }
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -83,7 +120,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
$result = Database::pexecute_first($result_stmt, $params, true, true); $result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) { if ($result) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get hosting-plan '" . $result['name'] . "'"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get hosting-plan '" . $result['name'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
$key = ($id > 0 ? "id #" . $id : "planname '" . $planname . "'"); $key = ($id > 0 ? "id #" . $id : "planname '" . $planname . "'");
throw new \Exception("Hosting-plan with " . $key . " could not be found", 404); throw new \Exception("Hosting-plan with " . $key . " could not be found", 404);
@@ -145,9 +182,9 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
* @param bool $perlenabled * @param bool $perlenabled
* optional, whether to allow usage of Perl/CGI, default 0 (false) * optional, whether to allow usage of Perl/CGI, default 0 (false)
* @param bool $dnsenabled * @param bool $dnsenabled
* optional, ether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false) * optional, whether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false)
* @param bool $logviewenabled * @param bool $logviewenabled
* optional, ether to allow acccess to webserver access/error-logs, default 0 (false) * optional, whether to allow access to webserver access/error-logs, default 0 (false)
* *
* @access admin * @access admin
* @throws \Exception * @throws \Exception
@@ -209,7 +246,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
$result = $this->apiCall('HostingPlans.get', array( $result = $this->apiCall('HostingPlans.get', array(
'planname' => $name 'planname' => $name
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -272,9 +309,9 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
* @param bool $perlenabled * @param bool $perlenabled
* optional, whether to allow usage of Perl/CGI, default 0 (false) * optional, whether to allow usage of Perl/CGI, default 0 (false)
* @param bool $dnsenabled * @param bool $dnsenabled
* optional, ether to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false) * optional, either to allow usage of the DNS editor (requires activated nameserver in settings), default 0 (false)
* @param bool $logviewenabled * @param bool $logviewenabled
* optional, ether to allow acccess to webserver access/error-logs, default 0 (false) * optional, either to allow access to webserver access/error-logs, default 0 (false)
* *
* @access admin * @access admin
* @throws \Exception * @throws \Exception
@@ -356,7 +393,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
); );
Database::pexecute($upd_stmt, $update_data, true, true); Database::pexecute($upd_stmt, $update_data, true, true);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated hosting-plan '" . $result['name'] . "'"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] updated hosting-plan '" . $result['name'] . "'");
return $this->response(200, "successfull", $update_data); return $this->response(200, "successful", $update_data);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -394,7 +431,7 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou
'id' => $id 'id' => $id
), true, true); ), true, true);
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted hosting-plan '" . $result['name'] . "'"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted hosting-plan '" . $result['name'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }

View File

@@ -25,6 +25,15 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
/** /**
* lists all ip/port entries * lists all ip/port entries
* *
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin * @access admin
* @throws \Exception * @throws \Exception
* @return string json-encoded array count|list * @return string json-encoded array count|list
@@ -34,18 +43,20 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || ! empty($this->getUserDetail('ip')))) { if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || ! empty($this->getUserDetail('ip')))) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list ips and ports"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list ips and ports");
$ip_where = ""; $ip_where = "";
$append_where = false;
if (! empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != - 1) { if (! empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != - 1) {
$ip_where = "WHERE `id` IN (" . implode(", ", json_decode($this->getUserDetail('ip'), true)) . ")"; $ip_where = "WHERE `id` IN (" . implode(", ", json_decode($this->getUserDetail('ip'), true)) . ")";
$append_where = true;
} }
$query_fields = array();
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` " . $ip_where . " ORDER BY `ip` ASC, `port` ASC SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` " . $ip_where . $this->getSearchWhere($query_fields, $append_where) . $this->getOrderBy() . $this->getLimit());
"); Database::pexecute($result_stmt, $query_fields, true, true);
Database::pexecute($result_stmt, null, true, true);
$result = array(); $result = array();
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row; $result[] = $row;
} }
return $this->response(200, "successfull", array( return $this->response(200, "successful", array(
'count' => count($result), 'count' => count($result),
'list' => $result 'list' => $result
)); ));
@@ -53,6 +64,30 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
/**
* returns the total number of accessible ip/port entries
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || ! empty($this->getUserDetail('ip')))) {
$ip_where = "";
if (! empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != - 1) {
$ip_where = "WHERE `id` IN (" . implode(", ", json_decode($this->getUserDetail('ip'), true)) . ")";
}
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_ips FROM `" . TABLE_PANEL_IPSANDPORTS . "` " . $ip_where);
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successful", $result['num_ips']);
}
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/** /**
* return an ip/port entry by id * return an ip/port entry by id
* *
@@ -81,7 +116,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
), true, true); ), true, true);
if ($result) { if ($result) {
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get ip " . $result['ip'] . " " . $result['port']); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] get ip " . $result['ip'] . " " . $result['port']);
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("IP/port with id #" . $id . " could not be found", 404); throw new \Exception("IP/port with id #" . $id . " could not be found", 404);
} }
@@ -118,6 +153,14 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
* optional, requires $ssl = 1, default empty * optional, requires $ssl = 1, default empty
* @param string $ssl_cert_chainfile * @param string $ssl_cert_chainfile
* optional, requires $ssl = 1, default empty * 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 * @access admin
* @throws \Exception * @throws \Exception
@@ -127,18 +170,18 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
{ {
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) { 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, true, 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( $port = \Froxlor\Validate\Validate::validate($this->getParam('port', true, 80), 'port', \Froxlor\Validate\Validate::REGEX_PORT, array(
'stringisempty', 'stringisempty',
'myport' 'myport'
), array(), true); ), array(), true);
$listen_statement = ! empty($this->getBoolParam('listen_statement', true, 0)) ? 1 : 0; $listen_statement = ! empty($this->getBoolParam('listen_statement', true, 0)) ? 1 : 0;
$namevirtualhost_statement = ! empty($this->getBoolParam('namevirtualhost_statement', true, 0)) ? 1 : 0; $namevirtualhost_statement = ! empty($this->getBoolParam('namevirtualhost_statement', true, 0)) ? 1 : 0;
$vhostcontainer = ! empty($this->getBoolParam('vhostcontainer', true, 0)) ? 1 : 0; $vhostcontainer = ! empty($this->getBoolParam('vhostcontainer', true, 0)) ? 1 : 0;
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, '')), 'specialsettings', '/^[^\0]*$/', '', array(), true); $specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, '')), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$vhostcontainer_servername_statement = ! empty($this->getBoolParam('vhostcontainer_servername_statement', true, 1)) ? 1 : 0; $vhostcontainer_servername_statement = ! empty($this->getBoolParam('vhostcontainer_servername_statement', true, 1)) ? 1 : 0;
$default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, '')), 'default_vhostconf_domain', '/^[^\0]*$/', '', array(), true); $default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, '')), 'default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$docroot = \Froxlor\Validate\Validate::validate($this->getParam('docroot', true, ''), 'docroot', '', '', array(), true); $docroot = \Froxlor\Validate\Validate::validate($this->getParam('docroot', true, ''), 'docroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
if ((int) Settings::Get('system.use_ssl') == 1) { if ((int) Settings::Get('system.use_ssl') == 1) {
$ssl = ! empty($this->getBoolParam('ssl', true, 0)) ? intval($this->getBoolParam('ssl', true, 0)) : 0; $ssl = ! empty($this->getBoolParam('ssl', true, 0)) ? intval($this->getBoolParam('ssl', true, 0)) : 0;
@@ -146,12 +189,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_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_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_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', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', 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', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$include_default_vhostconf_domain = ! empty($this->getBoolParam('include_default_vhostconf_domain', true, 0)) ? 1 : 0;
} else { } else {
$ssl = 0; $ssl = 0;
$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_specialsettings = '';
$include_specialsettings = 0;
$ssl_default_vhostconf_domain = '';
$include_default_vhostconf_domain = 0;
} }
if ($listen_statement != '1') { if ($listen_statement != '1') {
@@ -196,6 +247,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$docroot = ''; $docroot = '';
} }
// always use compressed ipv6 format
$ip = inet_ntop(inet_pton($ip));
$result_checkfordouble_stmt = Database::prepare(" $result_checkfordouble_stmt = Database::prepare("
SELECT `id` FROM `" . TABLE_PANEL_IPSANDPORTS . "` SELECT `id` FROM `" . TABLE_PANEL_IPSANDPORTS . "`
WHERE `ip` = :ip AND `port` = :port"); WHERE `ip` = :ip AND `port` = :port");
@@ -204,7 +258,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
'port' => $port 'port' => $port
)); ));
if ($result_checkfordouble['id'] != '') { if ($result_checkfordouble && $result_checkfordouble['id'] != '') {
\Froxlor\UI\Response::standard_error('myipnotdouble', '', true); \Froxlor\UI\Response::standard_error('myipnotdouble', '', true);
} }
@@ -217,7 +271,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
`specialsettings` = :ss, `ssl` = :ssl, `specialsettings` = :ss, `ssl` = :ssl,
`ssl_cert_file` = :ssl_cert, `ssl_key_file` = :ssl_key, `ssl_cert_file` = :ssl_cert, `ssl_key_file` = :ssl_key,
`ssl_ca_file` = :ssl_ca, `ssl_cert_chainfile` = :ssl_chain, `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( $ins_data = array(
'ip' => $ip, 'ip' => $ip,
@@ -233,7 +289,11 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
'ssl_ca' => $ssl_ca_file, 'ssl_ca' => $ssl_ca_file,
'ssl_chain' => $ssl_cert_chainfile, 'ssl_chain' => $ssl_cert_chainfile,
'dvhd' => $default_vhostconf_domain, '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); Database::pexecute($ins_stmt, $ins_data);
$ins_data['id'] = Database::lastInsertId(); $ins_data['id'] = Database::lastInsertId();
@@ -250,7 +310,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$result = $this->apiCall('IpsAndPorts.get', array( $result = $this->apiCall('IpsAndPorts.get', array(
'id' => $ins_data['id'] 'id' => $ins_data['id']
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -287,6 +347,14 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
* optional, requires $ssl = 1, default empty * optional, requires $ssl = 1, default empty
* @param string $ssl_cert_chainfile * @param string $ssl_cert_chainfile
* optional, requires $ssl = 1, default empty * 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 * @access admin
@@ -302,18 +370,18 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
'id' => $id '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, true, 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( $port = \Froxlor\Validate\Validate::validate($this->getParam('port', true, $result['port']), 'port', \Froxlor\Validate\Validate::REGEX_PORT, array(
'stringisempty', 'stringisempty',
'myport' 'myport'
), array(), true); ), array(), true);
$listen_statement = $this->getBoolParam('listen_statement', true, $result['listen_statement']); $listen_statement = $this->getBoolParam('listen_statement', true, $result['listen_statement']);
$namevirtualhost_statement = $this->getBoolParam('namevirtualhost_statement', true, $result['namevirtualhost_statement']); $namevirtualhost_statement = $this->getBoolParam('namevirtualhost_statement', true, $result['namevirtualhost_statement']);
$vhostcontainer = $this->getBoolParam('vhostcontainer', true, $result['vhostcontainer']); $vhostcontainer = $this->getBoolParam('vhostcontainer', true, $result['vhostcontainer']);
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, $result['specialsettings'])), 'specialsettings', '/^[^\0]*$/', '', array(), true); $specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, $result['specialsettings'])), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$vhostcontainer_servername_statement = $this->getParam('vhostcontainer_servername_statement', true, $result['vhostcontainer_servername_statement']); $vhostcontainer_servername_statement = $this->getParam('vhostcontainer_servername_statement', true, $result['vhostcontainer_servername_statement']);
$default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, $result['default_vhostconf_domain'])), 'default_vhostconf_domain', '/^[^\0]*$/', '', array(), true); $default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, $result['default_vhostconf_domain'])), 'default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$docroot = \Froxlor\Validate\Validate::validate($this->getParam('docroot', true, $result['docroot']), 'docroot', '', '', array(), true); $docroot = \Froxlor\Validate\Validate::validate($this->getParam('docroot', true, $result['docroot']), 'docroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
if ((int) Settings::Get('system.use_ssl') == 1) { if ((int) Settings::Get('system.use_ssl') == 1) {
$ssl = $this->getBoolParam('ssl', true, $result['ssl']); $ssl = $this->getBoolParam('ssl', true, $result['ssl']);
@@ -321,12 +389,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_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_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_cert_chainfile = \Froxlor\Validate\Validate::validate($this->getParam('ssl_cert_chainfile', true, $result['ssl_cert_chainfile']), 'ssl_cert_chainfile', '', '', array(), true);
$ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, $result['ssl_specialsettings'])), 'ssl_specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$include_specialsettings = $this->getBoolParam('include_specialsettings', true, $result['include_specialsettings']);
$ssl_default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, $result['ssl_default_vhostconf_domain'])), 'ssl_default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$include_default_vhostconf_domain = $this->getBoolParam('include_default_vhostconf_domain', true, $result['include_default_vhostconf_domain']);
} else { } else {
$ssl = 0; $ssl = 0;
$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_specialsettings = '';
$include_specialsettings = 0;
$ssl_default_vhostconf_domain = '';
$include_default_vhostconf_domain = 0;
} }
$result_checkfordouble_stmt = Database::prepare(" $result_checkfordouble_stmt = Database::prepare("
@@ -389,9 +465,12 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$docroot = ''; $docroot = '';
} }
if ($result['ip'] != $ip && $result['ip'] == Settings::Get('system.ipaddress') && $result_sameipotherport['id'] == '') { // always use compressed ipv6 format
$ip = inet_ntop(inet_pton($ip));
if ($result['ip'] != $ip && $result['ip'] == Settings::Get('system.ipaddress') && $result_sameipotherport == false) {
\Froxlor\UI\Response::standard_error('cantchangesystemip', '', true); \Froxlor\UI\Response::standard_error('cantchangesystemip', '', true);
} elseif ($result_checkfordouble['id'] != '' && $result_checkfordouble['id'] != $id) { } elseif ($result_checkfordouble && $result_checkfordouble['id'] != '' && $result_checkfordouble['id'] != $id) {
\Froxlor\UI\Response::standard_error('myipnotdouble', '', true); \Froxlor\UI\Response::standard_error('myipnotdouble', '', true);
} else { } else {
@@ -404,7 +483,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
`specialsettings` = :ss, `ssl` = :ssl, `specialsettings` = :ss, `ssl` = :ssl,
`ssl_cert_file` = :ssl_cert, `ssl_key_file` = :ssl_key, `ssl_cert_file` = :ssl_cert, `ssl_key_file` = :ssl_key,
`ssl_ca_file` = :ssl_ca, `ssl_cert_chainfile` = :ssl_chain, `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; WHERE `id` = :id;
"); ");
$upd_data = array( $upd_data = array(
@@ -422,6 +503,10 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
'ssl_chain' => $ssl_cert_chainfile, 'ssl_chain' => $ssl_cert_chainfile,
'dvhd' => $default_vhostconf_domain, '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,
'id' => $id 'id' => $id
); );
Database::pexecute($upd_stmt, $upd_data); Database::pexecute($upd_stmt, $upd_data);
@@ -435,7 +520,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$result = $this->apiCall('IpsAndPorts.get', array( $result = $this->apiCall('IpsAndPorts.get', array(
'id' => $result['id'] 'id' => $result['id']
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
@@ -461,7 +546,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
)); ));
$result_checkdomain_stmt = Database::prepare(" $result_checkdomain_stmt = Database::prepare("
SELECT `id_domain` as `id` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_ipandports` = :id SELECT `id_domain` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_ipandports` = :id
"); ");
$result_checkdomain = Database::pexecute_first($result_checkdomain_stmt, array( $result_checkdomain = Database::pexecute_first($result_checkdomain_stmt, array(
'id' => $id 'id' => $id
@@ -481,7 +566,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
'ip' => $result['ip'] 'ip' => $result['ip']
)); ));
if (($result['ip'] != Settings::Get('system.ipaddress')) || ($result['ip'] == Settings::Get('system.ipaddress') && $result_sameipotherport['id'] != '')) { if (($result['ip'] != Settings::Get('system.ipaddress')) || ($result['ip'] == Settings::Get('system.ipaddress') && $result_sameipotherport != false)) {
$del_stmt = Database::prepare(" $del_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_IPSANDPORTS . "` DELETE FROM `" . TABLE_PANEL_IPSANDPORTS . "`
@@ -504,7 +589,7 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
\Froxlor\System\Cronjob::inserttask('4'); \Froxlor\System\Cronjob::inserttask('4');
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted IP/port '" . $result['ip'] . ":" . $result['port'] . "'"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] deleted IP/port '" . $result['ip'] . ":" . $result['port'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} else { } else {
\Froxlor\UI\Response::standard_error('cantdeletesystemip', '', true); \Froxlor\UI\Response::standard_error('cantdeletesystemip', '', true);
} }

View File

@@ -31,10 +31,14 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, default is 0 * optional, default is 0
* @param string $description * @param string $description
* optional, description for database * optional, description for database
* @param string $custom_suffix
* optional, name for database
* @param bool $sendinfomail * @param bool $sendinfomail
* optional, send created resource-information to customer, default: false * optional, send created resource-information to customer, default: false
* @param int $customerid * @param int $customerid
* required when called as admin, not needed when called as customer * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -42,20 +46,24 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
*/ */
public function add() public function add()
{ {
if ($this->getUserDetail('mysqls_used') < $this->getUserDetail('mysqls') || $this->getUserDetail('mysqls') == '-1') { // required parameters
// required paramters
$password = $this->getParam('mysql_password'); $password = $this->getParam('mysql_password');
// parameters // parameters
$dbserver = $this->getParam('mysql_server', true, 0); $dbserver = $this->getParam('mysql_server', true, 0);
$databasedescription = $this->getParam('description', true, ''); $databasedescription = $this->getParam('description', true, '');
$databasename = $this->getParam('custom_suffix', true, '');
$sendinfomail = $this->getBoolParam('sendinfomail', true, 0); $sendinfomail = $this->getBoolParam('sendinfomail', true, 0);
// get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData('mysqls');
// validation // validation
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
$password = \Froxlor\System\Crypt::validatePassword($password, true); $password = \Froxlor\System\Crypt::validatePassword($password, true);
$databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true); $databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true);
if (!empty($databasename)) {
$databasename = \Froxlor\Validate\Validate::validate(trim($databasename), 'database_name', '/^[A-Za-z0-9][A-Za-z0-9\-_]+$/i', '', array(), true);
}
// validate whether the dbserver exists // validate whether the dbserver exists
$dbserver = \Froxlor\Validate\Validate::validate($dbserver, html_entity_decode($this->lng['mysql']['mysql_server']), '', '', 0, true); $dbserver = \Froxlor\Validate\Validate::validate($dbserver, html_entity_decode($this->lng['mysql']['mysql_server']), '', '', 0, true);
@@ -71,16 +79,18 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$sendinfomail = 0; $sendinfomail = 0;
} }
// get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData('mysqls');
$newdb_params = array( $newdb_params = array(
'loginname' => ($this->isAdmin() ? $customer['loginname'] : $this->getUserDetail('loginname')), 'loginname' => ($this->isAdmin() ? $customer['loginname'] : $this->getUserDetail('loginname')),
'mysql_lastaccountnumber' => ($this->isAdmin() ? $customer['mysql_lastaccountnumber'] : $this->getUserDetail('mysql_lastaccountnumber')) 'mysql_lastaccountnumber' => ($this->isAdmin() ? $customer['mysql_lastaccountnumber'] : $this->getUserDetail('mysql_lastaccountnumber'))
); );
// create database, user, set permissions, etc.pp. // create database, user, set permissions, etc.pp.
$dbm = new \Froxlor\Database\DbManager($this->logger()); $dbm = new \Froxlor\Database\DbManager($this->logger());
if(strtoupper(Settings::Get('customer.mysqlprefix')) == 'DBNAME' && !empty($databasename)) {
$username = $dbm->createDatabase($newdb_params['loginname'].'_'.$databasename, $password);
} else {
$username = $dbm->createDatabase($newdb_params['loginname'], $password, $newdb_params['mysql_lastaccountnumber']); $username = $dbm->createDatabase($newdb_params['loginname'], $password, $newdb_params['mysql_lastaccountnumber']);
}
// we've checked against the password in dbm->createDatabase // we've checked against the password in dbm->createDatabase
if ($username == false) { if ($username == false) {
@@ -126,8 +136,12 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$replace_arr = array( $replace_arr = array(
'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($userinfo), 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($userinfo),
'CUST_NAME' => \Froxlor\User::getCorrectUserSalutation($userinfo), // < keep this for compatibility 'CUST_NAME' => \Froxlor\User::getCorrectUserSalutation($userinfo), // < keep this for compatibility
'NAME' => $userinfo['name'],
'FIRSTNAME' => $userinfo['firstname'],
'COMPANY' => $userinfo['company'],
'CUSTOMER_NO' => $userinfo['customernumber'],
'DB_NAME' => $username, 'DB_NAME' => $username,
'DB_PASS' => $password, 'DB_PASS' => htmlentities(htmlentities($password)),
'DB_DESC' => $databasedescription, 'DB_DESC' => $databasedescription,
'DB_SRV' => $sql_root['host'], 'DB_SRV' => $sql_root['host'],
'PMA_URI' => $pma 'PMA_URI' => $pma
@@ -166,9 +180,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$result = $this->apiCall('Mysqls.get', array( $result = $this->apiCall('Mysqls.get', array(
'dbname' => $username 'dbname' => $username
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
}
throw new \Exception("No more resources available", 406);
} }
/** /**
@@ -255,9 +267,9 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
), true, true); ), true, true);
$mbdata = $mbdata_stmt->fetch(\PDO::FETCH_ASSOC); $mbdata = $mbdata_stmt->fetch(\PDO::FETCH_ASSOC);
Database::needRoot(false); Database::needRoot(false);
$result['size'] = $mbdata['MB']; $result['size'] = $mbdata['MB'] ?? 0;
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get database '" . $result['databasename'] . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get database '" . $result['databasename'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
$key = ($id > 0 ? "id #" . $id : "dbname '" . $dbname . "'"); $key = ($id > 0 ? "id #" . $id : "dbname '" . $dbname . "'");
throw new \Exception("MySQL database with " . $key . " could not be found", 404); throw new \Exception("MySQL database with " . $key . " could not be found", 404);
@@ -276,6 +288,10 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, update password for the database * optional, update password for the database
* @param string $description * @param string $description
* optional, description for database * optional, description for database
* @param int $customerid
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -287,6 +303,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$dn_optional = ($id <= 0 ? false : true); $dn_optional = ($id <= 0 ? false : true);
$dbname = $this->getParam('dbname', $dn_optional, ''); $dbname = $this->getParam('dbname', $dn_optional, '');
$dbserver = $this->getParam('mysql_server', true, - 1); $dbserver = $this->getParam('mysql_server', true, - 1);
$customer = $this->getCustomerData();
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) {
throw new \Exception("You cannot access this resource", 405); throw new \Exception("You cannot access this resource", 405);
@@ -299,17 +316,14 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
)); ));
$id = $result['id']; $id = $result['id'];
// paramters // parameters
$password = $this->getParam('mysql_password', true, ''); $password = $this->getParam('mysql_password', true, '');
$databasedescription = $this->getParam('description', true, ''); $databasedescription = $this->getParam('description', true, $result['description']);
// validation // validation
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true); $password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
$databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true); $databasedescription = \Froxlor\Validate\Validate::validate(trim($databasedescription), 'description', '', '', array(), true);
// get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData();
if ($password != '') { if ($password != '') {
// validate password // validate password
$password = \Froxlor\System\Crypt::validatePassword($password, true); $password = \Froxlor\System\Crypt::validatePassword($password, true);
@@ -347,7 +361,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$result = $this->apiCall('Mysqls.get', array( $result = $this->apiCall('Mysqls.get', array(
'dbname' => $result['databasename'] 'dbname' => $result['databasename']
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
/** /**
@@ -359,6 +373,14 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, admin-only, select dbs of a specific customer by id * optional, admin-only, select dbs of a specific customer by id
* @param string $loginname * @param string $loginname
* optional, admin-only, select dbs of a specific customer by loginname * optional, admin-only, select dbs of a specific customer by loginname
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -369,10 +391,10 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$result = array(); $result = array();
$dbserver = $this->getParam('mysql_server', true, - 1); $dbserver = $this->getParam('mysql_server', true, - 1);
$customer_ids = $this->getAllowedCustomerIds('mysql'); $customer_ids = $this->getAllowedCustomerIds('mysql');
$query_fields = array();
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DATABASES . "` SELECT * FROM `" . TABLE_PANEL_DATABASES . "`
WHERE `customerid`= :customerid AND `dbserver` = :dbserver WHERE `customerid`= :customerid AND `dbserver` = :dbserver" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
");
if ($dbserver < 0) { if ($dbserver < 0) {
// use all dbservers // use all dbservers
$dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`"); $dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`");
@@ -388,10 +410,10 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
foreach ($customer_ids as $customer_id) { foreach ($customer_ids as $customer_id) {
foreach ($dbservers as $_dbserver) { foreach ($dbservers as $_dbserver) {
Database::pexecute($result_stmt, array( Database::pexecute($result_stmt, array_merge(array(
'customerid' => $customer_id, 'customerid' => $customer_id,
'dbserver' => $_dbserver['dbserver'] 'dbserver' => $_dbserver['dbserver']
), true, true); ), $query_fields), true, true);
// Begin root-session // Begin root-session
Database::needRoot(true, $_dbserver['dbserver']); Database::needRoot(true, $_dbserver['dbserver']);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
@@ -404,18 +426,43 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
"table_schema" => $row['databasename'] "table_schema" => $row['databasename']
), true, true); ), true, true);
$mbdata = $mbdata_stmt->fetch(\PDO::FETCH_ASSOC); $mbdata = $mbdata_stmt->fetch(\PDO::FETCH_ASSOC);
$row['size'] = $mbdata['MB']; $row['size'] = $mbdata['MB'] ?? 0;
$result[] = $row; $result[] = $row;
} }
Database::needRoot(false); Database::needRoot(false);
} }
} }
return $this->response(200, "successfull", array( return $this->response(200, "successful", array(
'count' => count($result), 'count' => count($result),
'list' => $result 'list' => $result
)); ));
} }
/**
* returns the total number of accessible databases
*
* @param int $customerid
* optional, admin-only, select dbs of a specific customer by id
* @param string $loginname
* optional, admin-only, select dbs of a specific customer by loginname
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
$customer_ids = $this->getAllowedCustomerIds('mysql');
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_dbs FROM `" . TABLE_PANEL_DATABASES . "`
WHERE `customerid` IN (" . implode(", ", $customer_ids) . ")
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successful", $result['num_dbs']);
}
}
/** /**
* delete a mysql database by either id or dbname * delete a mysql database by either id or dbname
* *
@@ -425,6 +472,10 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, the databasename * optional, the databasename
* @param int $mysql_server * @param int $mysql_server
* optional, specify database-server, default is none * optional, specify database-server, default is none
* @param int $customerid
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -436,6 +487,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$dn_optional = ($id <= 0 ? false : true); $dn_optional = ($id <= 0 ? false : true);
$dbname = $this->getParam('dbname', $dn_optional, ''); $dbname = $this->getParam('dbname', $dn_optional, '');
$dbserver = $this->getParam('mysql_server', true, - 1); $dbserver = $this->getParam('mysql_server', true, - 1);
$customer = $this->getCustomerData();
if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) { if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'mysql')) {
throw new \Exception("You cannot access this resource", 405); throw new \Exception("You cannot access this resource", 405);
@@ -462,7 +514,6 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
), true, true); ), true, true);
// get needed customer info to reduce the mysql-usage-counter by one // get needed customer info to reduce the mysql-usage-counter by one
$customer = $this->getCustomerData();
$mysql_used = $customer['mysqls_used']; $mysql_used = $customer['mysqls_used'];
// reduce mysql-usage-counter // reduce mysql-usage-counter
@@ -470,6 +521,6 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
Customers::decreaseUsage($customer['customerid'], 'mysqls_used', $resetaccnumber); Customers::decreaseUsage($customer['customerid'], 'mysqls_used', $resetaccnumber);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted database '" . $result['databasename'] . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted database '" . $result['databasename'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
} }

View File

@@ -27,6 +27,14 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
* *
* @param bool $with_subdomains * @param bool $with_subdomains
* optional, also include subdomains to the list domains that use the config, default 0 (false) * optional, also include subdomains to the list domains that use the config, default 0 (false)
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
* *
* @access admin * @access admin
* @throws \Exception * @throws \Exception
@@ -38,22 +46,20 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list php-configs"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list php-configs");
$with_subdomains = $this->getBoolParam('with_subdomains', true, false); $with_subdomains = $this->getBoolParam('with_subdomains', true, false);
$query_fields = array();
$result = Database::query(" $result_stmt = Database::prepare("
SELECT c.*, fd.description as fpmdesc SELECT c.*, fd.description as fpmdesc
FROM `" . TABLE_PANEL_PHPCONFIGS . "` c FROM `" . TABLE_PANEL_PHPCONFIGS . "` c
LEFT JOIN `" . TABLE_PANEL_FPMDAEMONS . "` fd ON fd.id = c.fpmsettingid LEFT JOIN `" . TABLE_PANEL_FPMDAEMONS . "` fd ON fd.id = c.fpmsettingid" . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit());
ORDER BY c.description ASC Database::pexecute($result_stmt, $query_fields, true, true);
");
$phpconfigs = array(); $phpconfigs = array();
while ($row = $result->fetch(\PDO::FETCH_ASSOC)) { while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$query_params = array( $query_params = array(
'id' => $row['id'] 'id' => $row['id']
); );
$query = "SELECT * FROM `" . TABLE_PANEL_DOMAINS . "` $query = "SELECT * FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `phpsettingid` = :id"; WHERE `phpsettingid` = :id AND `email_only` = '0' AND `phpenabled` = '1'";
if (! $with_subdomains) { if (! $with_subdomains) {
$query .= " AND `parentdomainid` = '0'"; $query .= " AND `parentdomainid` = '0'";
@@ -107,7 +113,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$phpconfigs[] = $row; $phpconfigs[] = $row;
} }
return $this->response(200, "successfull", array( return $this->response(200, "successful", array(
'count' => count($phpconfigs), 'count' => count($phpconfigs),
'list' => $phpconfigs 'list' => $phpconfigs
)); ));
@@ -115,6 +121,28 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
/**
* returns the total number of accessible php-setting entries
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin()) {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_phps
FROM `" . TABLE_PANEL_PHPCONFIGS . "` c
");
$result = Database::pexecute_first($result_stmt, null, true, true);
if ($result) {
return $this->response(200, "successful", $result['num_phps']);
}
}
throw new \Exception("Not allowed to execute given command.", 403);
}
/** /**
* return a php-setting entry by id * return a php-setting entry by id
* *
@@ -137,7 +165,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
'id' => $id 'id' => $id
), true, true); ), true, true);
if ($result) { if ($result) {
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("php-config with id #" . $id . " could not be found", 404); throw new \Exception("php-config with id #" . $id . " could not be found", 404);
} }
@@ -189,6 +217,8 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
* optional number of seconds for idle-timeout if FPM is used, default is fpm-daemon-value * optional number of seconds for idle-timeout if FPM is used, default is fpm-daemon-value
* @param string $limit_extensions * @param string $limit_extensions
* optional limitation of php-file-extensions if FPM is used, default is fpm-daemon-value * optional limitation of php-file-extensions if FPM is used, default is fpm-daemon-value
* @param bool $allow_all_customers
* optional add this configuration to the list of every existing customer's allowed-fpm-config list, default is false (no)
* *
* @access admin * @access admin
* @throws \Exception * @throws \Exception
@@ -233,6 +263,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$max_requests = $this->getParam('max_requests', true, $def_fpmconfig['max_requests']); $max_requests = $this->getParam('max_requests', true, $def_fpmconfig['max_requests']);
$idle_timeout = $this->getParam('idle_timeout', true, $def_fpmconfig['idle_timeout']); $idle_timeout = $this->getParam('idle_timeout', true, $def_fpmconfig['idle_timeout']);
$limit_extensions = $this->getParam('limit_extensions', true, $def_fpmconfig['limit_extensions']); $limit_extensions = $this->getParam('limit_extensions', true, $def_fpmconfig['limit_extensions']);
$allow_all_customers = $this->getBoolParam('allow_all_customers', true, 0);
// validation // validation
$description = \Froxlor\Validate\Validate::validate($description, 'description', '', '', array(), true); $description = \Froxlor\Validate\Validate::validate($description, 'description', '', '', array(), true);
@@ -339,7 +370,9 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$result = $this->apiCall('PhpSettings.get', array( $result = $this->apiCall('PhpSettings.get', array(
'id' => $ins_data['id'] 'id' => $ins_data['id']
)); ));
return $this->response(200, "successfull", $result);
$this->addForAllCustomers($allow_all_customers, $ins_data['id']);
return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -390,6 +423,8 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
* optional number of seconds for idle-timeout if FPM is used, default is fpm-daemon-value * optional number of seconds for idle-timeout if FPM is used, default is fpm-daemon-value
* @param string $limit_extensions * @param string $limit_extensions
* optional limitation of php-file-extensions if FPM is used, default is fpm-daemon-value * optional limitation of php-file-extensions if FPM is used, default is fpm-daemon-value
* @param bool $allow_all_customers
* optional add this configuration to the list of every existing customer's allowed-fpm-config list, default is false (no)
* *
* @access admin * @access admin
* @throws \Exception * @throws \Exception
@@ -428,6 +463,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$max_requests = $this->getParam('max_requests', true, $result['max_requests']); $max_requests = $this->getParam('max_requests', true, $result['max_requests']);
$idle_timeout = $this->getParam('idle_timeout', true, $result['idle_timeout']); $idle_timeout = $this->getParam('idle_timeout', true, $result['idle_timeout']);
$limit_extensions = $this->getParam('limit_extensions', true, $result['limit_extensions']); $limit_extensions = $this->getParam('limit_extensions', true, $result['limit_extensions']);
$allow_all_customers = $this->getBoolParam('allow_all_customers', true, 0);
// validation // validation
$description = \Froxlor\Validate\Validate::validate($description, 'description', '', '', array(), true); $description = \Froxlor\Validate\Validate::validate($description, 'description', '', '', array(), true);
@@ -535,7 +571,9 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$result = $this->apiCall('PhpSettings.get', array( $result = $this->apiCall('PhpSettings.get', array(
'id' => $id 'id' => $id
)); ));
return $this->response(200, "successfull", $result);
$this->addForAllCustomers($allow_all_customers, $id);
return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
@@ -586,8 +624,42 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
\Froxlor\System\Cronjob::inserttask('1'); \Froxlor\System\Cronjob::inserttask('1');
$this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] php setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'"); $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] php setting '" . $result['description'] . "' has been deleted by '" . $this->getUserDetail('loginname') . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("Not allowed to execute given command.", 403); throw new \Exception("Not allowed to execute given command.", 403);
} }
/**
* add given php-config id to the list of allowed php-config to all currently existing customers
* if allow_all_customers parameter is true in PhpSettings::add() or PhpSettings::update()
*
* @param bool $allow_all_customers
* @param int $config_id
*/
private function addForAllCustomers(bool $allow_all_customers, int $config_id)
{
// should this config be added to the allowed list of all existing customers?
if ($allow_all_customers) {
$sel_stmt = Database::prepare("SELECT customerid, allowed_phpconfigs FROM `" . TABLE_PANEL_CUSTOMERS . "`");
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET allowed_phpconfigs = :ap WHERE customerid = :cid");
Database::pexecute($sel_stmt);
while ($cust = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
// get existing entries of customer
$ap = json_decode($cust['allowed_phpconfigs'], true);
// initialize array if it's empty
if (empty($ap)) {
$ap = [];
}
// add this config
$ap[] = $config_id;
// check for duplicates and force value-type to be int
$ap = array_map('intval', array_unique($ap));
// update customer-entry
Database::pexecute($upd_stmt, [
'ap' => json_encode($ap),
'cid' => $cust['customerid']
]);
}
}
}
} }

View File

@@ -2,6 +2,7 @@
namespace Froxlor\Api\Commands; namespace Froxlor\Api\Commands;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\Domain\Domain;
use Froxlor\Settings; use Froxlor\Settings;
/** /**
@@ -36,11 +37,13 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* @param string $url * @param string $url
* optional, overwrites path value with an URL to generate a redirect, alternatively use the path parameter also for URLs * optional, overwrites path value with an URL to generate a redirect, alternatively use the path parameter also for URLs
* @param int $openbasedir_path * @param int $openbasedir_path
* optional, either 0 for customers-homedir or 1 for domains-docroot * optional, either 0 for domains-docroot or 1 for customers-homedir
* @param int $phpsettingid * @param int $phpsettingid
* optional, php-settings-id, if empty the $domain value is used * optional, php-settings-id, if empty the $domain value is used
* @param int $redirectcode * @param int $redirectcode
* optional, redirect-code-id from TABLE_PANEL_REDIRECTCODES * optional, redirect-code-id from TABLE_PANEL_REDIRECTCODES
* @param bool $sslenabled
* optional, whether or not SSL is enabled for this domain, regardless of the assigned ssl-ips, default 1 (true)
* @param bool $ssl_redirect * @param bool $ssl_redirect
* optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled * optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled
* @param bool $letsencrypt * @param bool $letsencrypt
@@ -54,7 +57,9 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* @param bool $hsts_preload * @param bool $hsts_preload
* optional whether or not to preload HSTS header value, default 0 * optional whether or not to preload HSTS header value, default 0
* @param int $customerid * @param int $customerid
* required when called as admin, not needed when called as customer * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -76,6 +81,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$redirectcode = $this->getParam('redirectcode', true, Settings::Get('customredirect.default')); $redirectcode = $this->getParam('redirectcode', true, Settings::Get('customredirect.default'));
$isemaildomain = $this->getParam('isemaildomain', true, 0); $isemaildomain = $this->getParam('isemaildomain', true, 0);
if (Settings::Get('system.use_ssl')) { if (Settings::Get('system.use_ssl')) {
$sslenabled = $this->getBoolParam('sslenabled', true, 1);
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, 0); $ssl_redirect = $this->getBoolParam('ssl_redirect', true, 0);
$letsencrypt = $this->getBoolParam('letsencrypt', true, 0); $letsencrypt = $this->getBoolParam('letsencrypt', true, 0);
$http2 = $this->getBoolParam('http2', true, 0); $http2 = $this->getBoolParam('http2', true, 0);
@@ -83,6 +89,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$hsts_sub = $this->getBoolParam('hsts_sub', true, 0); $hsts_sub = $this->getBoolParam('hsts_sub', true, 0);
$hsts_preload = $this->getBoolParam('hsts_preload', true, 0); $hsts_preload = $this->getBoolParam('hsts_preload', true, 0);
} else { } else {
$sslenabled = 0;
$ssl_redirect = 0; $ssl_redirect = 0;
$letsencrypt = 0; $letsencrypt = 0;
$http2 = 0; $http2 = 0;
@@ -95,6 +102,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$customer = $this->getCustomerData('subdomains'); $customer = $this->getCustomerData('subdomains');
// validation // validation
$subdomain = strtolower($subdomain);
if (substr($subdomain, 0, 4) == 'xn--') { if (substr($subdomain, 0, 4) == 'xn--') {
\Froxlor\UI\Response::standard_error('domain_nopunycode', '', true); \Froxlor\UI\Response::standard_error('domain_nopunycode', '', true);
} }
@@ -114,7 +122,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
'mydomain' 'mydomain'
), '', true); ), '', true);
} }
if ($completedomain == Settings::Get('system.hostname')) { if ($completedomain == strtolower(Settings::Get('system.hostname'))) {
\Froxlor\UI\Response::standard_error('admin_domain_emailsystemhostname', '', true); \Froxlor\UI\Response::standard_error('admin_domain_emailsystemhostname', '', true);
} }
@@ -190,7 +198,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
} elseif ($subdomain == 'www' && $domain_check['wwwserveralias'] == '1') { } elseif ($subdomain == 'www' && $domain_check['wwwserveralias'] == '1') {
// you cannot add 'www' as subdomain when the maindomain generates a www-alias // you cannot add 'www' as subdomain when the maindomain generates a www-alias
\Froxlor\UI\Response::standard_error('wwwnotallowed', '', true); \Froxlor\UI\Response::standard_error('wwwnotallowed', '', true);
} elseif (strtolower($completedomain_check['domain']) == strtolower($completedomain)) { } elseif ($completedomain_check && strtolower($completedomain_check['domain']) == strtolower($completedomain)) {
// the domain does already exist as main-domain // the domain does already exist as main-domain
\Froxlor\UI\Response::standard_error('domainexistalready', $completedomain, true); \Froxlor\UI\Response::standard_error('domainexistalready', $completedomain, true);
} }
@@ -223,6 +231,15 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
} }
} }
// validate dns if lets encrypt is enabled to check whether we can use it at all
if ($letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
$our_ips = Domain::getIpsOfDomain($domain_check['id']);
$domain_ips = \Froxlor\PhpHelper::gethostbynamel6($completedomain);
if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) {
\Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true);
}
}
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated // Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
if ($ssl_redirect > 0 && $letsencrypt == 1) { if ($ssl_redirect > 0 && $letsencrypt == 1) {
$ssl_redirect = 2; $ssl_redirect = 2;
@@ -245,12 +262,23 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$phpsid_result['phpsettingid'] = intval($phpsettingid); $phpsid_result['phpsettingid'] = intval($phpsettingid);
} }
$allowed_phpconfigs = $customer['allowed_phpconfigs'];
if (! empty($allowed_phpconfigs)) {
$allowed_phpconfigs = json_decode($allowed_phpconfigs, true);
} else {
$allowed_phpconfigs = [];
}
if (! in_array($phpsid_result['phpsettingid'], $allowed_phpconfigs)) {
\Froxlor\UI\Response::standard_error('notallowedphpconfigused', '', true);
}
// actually insert domain // actually insert domain
$stmt = Database::prepare(" $stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_DOMAINS . "` SET INSERT INTO `" . TABLE_PANEL_DOMAINS . "` SET
`customerid` = :customerid, `customerid` = :customerid,
`adminid` = :adminid, `adminid` = :adminid,
`domain` = :domain, `domain` = :domain,
`domain_ace` = :domain_ace,
`documentroot` = :documentroot, `documentroot` = :documentroot,
`aliasdomain` = :aliasdomain, `aliasdomain` = :aliasdomain,
`parentdomainid` = :parentdomainid, `parentdomainid` = :parentdomainid,
@@ -262,18 +290,27 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
`openbasedir_path` = :openbasedir_path, `openbasedir_path` = :openbasedir_path,
`speciallogfile` = :speciallogfile, `speciallogfile` = :speciallogfile,
`specialsettings` = :specialsettings, `specialsettings` = :specialsettings,
`ssl_specialsettings` = :ssl_specialsettings,
`include_specialsettings` = :include_specialsettings,
`ssl_redirect` = :ssl_redirect, `ssl_redirect` = :ssl_redirect,
`phpsettingid` = :phpsettingid, `phpsettingid` = :phpsettingid,
`letsencrypt` = :letsencrypt, `letsencrypt` = :letsencrypt,
`http2` = :http2, `http2` = :http2,
`hsts` = :hsts, `hsts` = :hsts,
`hsts_sub` = :hsts_sub, `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,
`ssl_enabled` = :sslenabled
"); ");
$params = array( $params = array(
"customerid" => $customer['customerid'], "customerid" => $customer['customerid'],
"adminid" => $customer['adminid'], "adminid" => $customer['adminid'],
"domain" => $completedomain, "domain" => $completedomain,
"domain_ace" => $idna_convert->decode($completedomain),
"documentroot" => $path, "documentroot" => $path,
"aliasdomain" => $aliasdomain != 0 ? $aliasdomain : null, "aliasdomain" => $aliasdomain != 0 ? $aliasdomain : null,
"parentdomainid" => $domain_check['id'], "parentdomainid" => $domain_check['id'],
@@ -285,13 +322,21 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
"phpenabled" => $domain_check['phpenabled'], "phpenabled" => $domain_check['phpenabled'],
"speciallogfile" => $domain_check['speciallogfile'], "speciallogfile" => $domain_check['speciallogfile'],
"specialsettings" => $domain_check['specialsettings'], "specialsettings" => $domain_check['specialsettings'],
"ssl_specialsettings" => $domain_check['ssl_specialsettings'],
"include_specialsettings" => $domain_check['include_specialsettings'],
"ssl_redirect" => $ssl_redirect, "ssl_redirect" => $ssl_redirect,
"phpsettingid" => $phpsid_result['phpsettingid'], "phpsettingid" => $phpsid_result['phpsettingid'],
"letsencrypt" => $letsencrypt, "letsencrypt" => $letsencrypt,
"http2" => $http2, "http2" => $http2,
"hsts" => $hsts_maxage, "hsts" => $hsts_maxage,
"hsts_sub" => $hsts_sub, "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'],
"sslenabled" => $sslenabled
); );
Database::pexecute($stmt, $params, true, true); Database::pexecute($stmt, $params, true, true);
$subdomain_id = Database::lastInsertId(); $subdomain_id = Database::lastInsertId();
@@ -322,7 +367,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$result = $this->apiCall('SubDomains.get', array( $result = $this->apiCall('SubDomains.get', array(
'id' => $subdomain_id 'id' => $subdomain_id
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
throw new \Exception("No more resources available", 406); throw new \Exception("No more resources available", 406);
} }
@@ -386,7 +431,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
); );
} }
} else { } else {
if (Settings::IsInList('panel.customer_hide_options', 'domains')) { if (! $this->isInternal() && Settings::IsInList('panel.customer_hide_options', 'domains')) {
throw new \Exception("You cannot access this resource", 405); throw new \Exception("You cannot access this resource", 405);
} }
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
@@ -403,7 +448,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$result = Database::pexecute_first($result_stmt, $params, true, true); $result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) { if ($result) {
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get subdomain '" . $result['domain'] . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] get subdomain '" . $result['domain'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
$key = ($id > 0 ? "id #" . $id : "domainname '" . $domainname . "'"); $key = ($id > 0 ? "id #" . $id : "domainname '" . $domainname . "'");
throw new \Exception("Subdomain with " . $key . " could not be found", 404); throw new \Exception("Subdomain with " . $key . " could not be found", 404);
@@ -427,11 +472,13 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* @param bool $isemaildomain * @param bool $isemaildomain
* optional * optional
* @param int $openbasedir_path * @param int $openbasedir_path
* optional, either 0 for customers-homedir or 1 for domains-docroot * optional, either 0 for domains-docroot or 1 for customers-homedir
* @param int $phpsettingid * @param int $phpsettingid
* optional, php-settings-id, if empty the $domain value is used * optional, php-settings-id, if empty the $domain value is used
* @param int $redirectcode * @param int $redirectcode
* optional, redirect-code-id from TABLE_PANEL_REDIRECTCODES * optional, redirect-code-id from TABLE_PANEL_REDIRECTCODES
* @param bool $sslenabled
* optional, whether or not SSL is enabled for this domain, regardless of the assigned ssl-ips, default 1 (true)
* @param bool $ssl_redirect * @param bool $ssl_redirect
* optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled * optional, whether to generate a https-redirect or not, default false; requires SSL to be enabled
* @param bool $letsencrypt * @param bool $letsencrypt
@@ -445,7 +492,9 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* @param bool $hsts_preload * @param bool $hsts_preload
* optional whether or not to preload HSTS header value * optional whether or not to preload HSTS header value
* @param int $customerid * @param int $customerid
* required when called as admin, not needed when called as customer * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -479,6 +528,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$phpsettingid = $this->getParam('phpsettingid', true, $result['phpsettingid']); $phpsettingid = $this->getParam('phpsettingid', true, $result['phpsettingid']);
$redirectcode = $this->getParam('redirectcode', true, \Froxlor\Domain\Domain::getDomainRedirectId($id)); $redirectcode = $this->getParam('redirectcode', true, \Froxlor\Domain\Domain::getDomainRedirectId($id));
if (Settings::Get('system.use_ssl')) { if (Settings::Get('system.use_ssl')) {
$sslenabled = $this->getBoolParam('sslenabled', true, $result['ssl_enabled']);
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, $result['ssl_redirect']); $ssl_redirect = $this->getBoolParam('ssl_redirect', true, $result['ssl_redirect']);
$letsencrypt = $this->getBoolParam('letsencrypt', true, $result['letsencrypt']); $letsencrypt = $this->getBoolParam('letsencrypt', true, $result['letsencrypt']);
$http2 = $this->getBoolParam('http2', true, $result['http2']); $http2 = $this->getBoolParam('http2', true, $result['http2']);
@@ -486,6 +536,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$hsts_sub = $this->getBoolParam('hsts_sub', true, $result['hsts_sub']); $hsts_sub = $this->getBoolParam('hsts_sub', true, $result['hsts_sub']);
$hsts_preload = $this->getBoolParam('hsts_preload', true, $result['hsts_preload']); $hsts_preload = $this->getBoolParam('hsts_preload', true, $result['hsts_preload']);
} else { } else {
$sslenabled = 0;
$ssl_redirect = 0; $ssl_redirect = 0;
$letsencrypt = 0; $letsencrypt = 0;
$http2 = 0; $http2 = 0;
@@ -564,14 +615,18 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
} }
} }
// We can't enable let's encrypt for wildcard - domains when using acme-v1 // validate dns if lets encrypt is enabled to check whether we can use it at all
if ($iswildcarddomain == '1' && $letsencrypt == '1' && Settings::Get('system.leapiversion') == '1') { if ($result['letsencrypt'] != $letsencrypt && $letsencrypt == '1' && Settings::Get('system.le_domain_dnscheck') == '1') {
\Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt'); $our_ips = Domain::getIpsOfDomain($result['parentdomainid']);
$domain_ips = \Froxlor\PhpHelper::gethostbynamel6($result['domain']);
if ($domain_ips == false || count(array_intersect($our_ips, $domain_ips)) <= 0) {
\Froxlor\UI\Response::standard_error('invaliddnsforletsencrypt', '', true);
} }
// if using acme-v2 we cannot issue wildcard-certificates }
// because they currently only support the dns-01 challenge
if ($iswildcarddomain == '1' && $letsencrypt == '1' && Settings::Get('system.leapiversion') == '2') { // We can't enable let's encrypt for wildcard-domains
\Froxlor\UI\Response::standard_error('nowildcardwithletsencryptv2'); if ($iswildcarddomain == '1' && $letsencrypt == '1') {
\Froxlor\UI\Response::standard_error('nowildcardwithletsencrypt', '', true);
} }
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated // Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
@@ -593,12 +648,22 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] automatically deleted mail-table entries for '" . $idna_convert->decode($result['domain']) . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] automatically deleted mail-table entries for '" . $idna_convert->decode($result['domain']) . "'");
} }
$allowed_phpconfigs = $customer['allowed_phpconfigs'];
if (! empty($allowed_phpconfigs)) {
$allowed_phpconfigs = json_decode($allowed_phpconfigs, true);
} else {
$allowed_phpconfigs = [];
}
if (! in_array($phpsettingid, $allowed_phpconfigs)) {
\Froxlor\UI\Response::standard_error('notallowedphpconfigused', '', true);
}
// handle redirect // handle redirect
if ($_doredirect) { if ($_doredirect) {
\Froxlor\Domain\Domain::updateRedirectOfDomain($id, $redirectcode); \Froxlor\Domain\Domain::updateRedirectOfDomain($id, $redirectcode);
} }
if ($path != $result['documentroot'] || $isemaildomain != $result['isemaildomain'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $aliasdomain != $result['aliasdomain'] || $openbasedir_path != $result['openbasedir_path'] || $ssl_redirect != $result['ssl_redirect'] || $letsencrypt != $result['letsencrypt'] || $hsts_maxage != $result['hsts'] || $hsts_sub != $result['hsts_sub'] || $hsts_preload != $result['hsts_preload'] || $phpsettingid != $result['phpsettingid']) { if ($path != $result['documentroot'] || $isemaildomain != $result['isemaildomain'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $aliasdomain != (int)$result['aliasdomain'] || $openbasedir_path != $result['openbasedir_path'] || $ssl_redirect != $result['ssl_redirect'] || $letsencrypt != $result['letsencrypt'] || $hsts_maxage != $result['hsts'] || $hsts_sub != $result['hsts_sub'] || $hsts_preload != $result['hsts_preload'] || $phpsettingid != $result['phpsettingid']) {
$stmt = Database::prepare(" $stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET UPDATE `" . TABLE_PANEL_DOMAINS . "` SET
`documentroot` = :documentroot, `documentroot` = :documentroot,
@@ -607,6 +672,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
`iswildcarddomain` = :iswildcarddomain, `iswildcarddomain` = :iswildcarddomain,
`aliasdomain` = :aliasdomain, `aliasdomain` = :aliasdomain,
`openbasedir_path` = :openbasedir_path, `openbasedir_path` = :openbasedir_path,
`ssl_enabled` = :sslenabled,
`ssl_redirect` = :ssl_redirect, `ssl_redirect` = :ssl_redirect,
`letsencrypt` = :letsencrypt, `letsencrypt` = :letsencrypt,
`http2` = :http2, `http2` = :http2,
@@ -623,6 +689,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
"iswildcarddomain" => $iswildcarddomain, "iswildcarddomain" => $iswildcarddomain,
"aliasdomain" => ($aliasdomain != 0 && $alias_check == 0) ? $aliasdomain : null, "aliasdomain" => ($aliasdomain != 0 && $alias_check == 0) ? $aliasdomain : null,
"openbasedir_path" => $openbasedir_path, "openbasedir_path" => $openbasedir_path,
"sslenabled" => $sslenabled,
"ssl_redirect" => $ssl_redirect, "ssl_redirect" => $ssl_redirect,
"letsencrypt" => $letsencrypt, "letsencrypt" => $letsencrypt,
"http2" => $http2, "http2" => $http2,
@@ -659,6 +726,8 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
Database::pexecute($del_stmt, array( Database::pexecute($del_stmt, array(
'id' => $id 'id' => $id
), true, true); ), true, true);
// remove domain from acme.sh / lets encrypt if used
\Froxlor\System\Cronjob::inserttask('12', $result['domain']);
} }
\Froxlor\System\Cronjob::inserttask('1'); \Froxlor\System\Cronjob::inserttask('1');
@@ -669,12 +738,25 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$result = $this->apiCall('SubDomains.get', array( $result = $this->apiCall('SubDomains.get', array(
'id' => $id 'id' => $id
)); ));
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
/** /**
* lists all subdomain entries * lists all subdomain entries
* *
* @param int $customerid
* optional, admin-only, select (sub)domains of a specific customer by id
* @param string $loginname
* optional, admin-only, select (sub)domains of a specific customer by loginname
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
* @return string json-encoded array count|list * @return string json-encoded array count|list
@@ -687,6 +769,105 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$customerid = $this->getParam('customerid', true, 0); $customerid = $this->getParam('customerid', true, 0);
$loginname = $this->getParam('loginname', true, ''); $loginname = $this->getParam('loginname', true, '');
if (! empty($customerid) || ! empty($loginname)) {
$result = $this->apiCall('Customers.get', array(
'id' => $customerid,
'loginname' => $loginname
));
$custom_list_result = array(
$result
);
} else {
$_custom_list_result = $this->apiCall('Customers.listing');
$custom_list_result = $_custom_list_result['list'];
}
$customer_ids = array();
$customer_stdsubs = array();
foreach ($custom_list_result as $customer) {
$customer_ids[] = $customer['customerid'];
$customer_stdsubs[$customer['customerid']] = $customer['standardsubdomain'];
}
if (empty($customer_ids)) {
throw new \Exception("Required resource unsatisfied.", 405);
}
if (empty($customer_stdsubs)) {
throw new \Exception("Required resource unsatisfied.", 405);
}
$select_fields = [
'`d`.*'
];
} else {
if (Settings::IsInList('panel.customer_hide_options', 'domains')) {
throw new \Exception("You cannot access this resource", 405);
}
$customer_ids = array(
$this->getUserDetail('customerid')
);
$customer_stdsubs = array(
$this->getUserDetail('customerid') => $this->getUserDetail('standardsubdomain')
);
$select_fields = [
'`d`.`id`',
'`d`.`customerid`',
'`d`.`domain`',
'`d`.`domain_ace`',
'`d`.`documentroot`',
'`d`.`isbinddomain`',
'`d`.`isemaildomain`',
'`d`.`caneditdomain`',
'`d`.`iswildcarddomain`',
'`d`.`parentdomainid`',
'`d`.`letsencrypt`',
'`d`.`registration_date`',
'`d`.`termination_date`'
];
}
$query_fields = array();
// prepare select statement
$domains_stmt = Database::prepare("
SELECT " . implode(",", $select_fields) . ", IF(`d`.`parentdomainid` > 0, `pd`.`domain_ace`, `d`.`domain_ace`) AS `parentdomainname`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain`, `da`.`id` AS `domainaliasid`, `da`.`domain` AS `domainalias`
FROM `" . TABLE_PANEL_DOMAINS . "` `d`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `pd` ON `pd`.`id`=`d`.`parentdomainid`
WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ")
AND `d`.`email_only` = '0'
AND `d`.`id` NOT IN (" . implode(', ', $customer_stdsubs) . ")" . $this->getSearchWhere($query_fields, true) . " GROUP BY `d`.`id` ORDER BY `parentdomainname` " . $this->getOrderBy(true) . $this->getLimit());
$result = array();
Database::pexecute($domains_stmt, $query_fields, true, true);
while ($row = $domains_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
}
return $this->response(200, "successful", array(
'count' => count($result),
'list' => $result
));
}
/**
* returns the total number of accessible subdomain entries
*
* @param int $customerid
* optional, admin-only, select (sub)domains of a specific customer by id
* @param string $loginname
* optional, admin-only, select (sub)domains of a specific customer by loginname
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
if ($this->isAdmin()) {
// if we're an admin, list all databases of all the admins customers
// or optionally for one specific customer identified by id or loginname
$customerid = $this->getParam('customerid', true, 0);
$loginname = $this->getParam('loginname', true, '');
if (! empty($customerid) || ! empty($loginname)) { if (! empty($customerid) || ! empty($loginname)) {
$result = $this->apiCall('Customers.get', array( $result = $this->apiCall('Customers.get', array(
'id' => $customerid, 'id' => $customerid,
@@ -716,33 +897,19 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$this->getUserDetail('customerid') => $this->getUserDetail('standardsubdomain') $this->getUserDetail('customerid') => $this->getUserDetail('standardsubdomain')
); );
} }
// prepare select statement // prepare select statement
$domains_stmt = Database::prepare(" $domains_stmt = Database::prepare("
SELECT `d`.`id`, `d`.`customerid`, `d`.`domain`, `d`.`documentroot`, `d`.`isbinddomain`, `d`.`isemaildomain`, `d`.`caneditdomain`, `d`.`iswildcarddomain`, `d`.`parentdomainid`, `d`.`letsencrypt`, `d`.`termination_date`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain`, `da`.`id` AS `domainaliasid`, `da`.`domain` AS `domainalias` SELECT COUNT(*) as num_subdom
FROM `" . TABLE_PANEL_DOMAINS . "` `d` FROM `" . TABLE_PANEL_DOMAINS . "` `d`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id` WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ")
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id`
WHERE `d`.`customerid`= :customerid
AND `d`.`email_only` = '0' AND `d`.`email_only` = '0'
AND `d`.`id` <> :standardsubdomain AND `d`.`id` NOT IN (" . implode(', ', $customer_stdsubs) . ")
"); ");
$result = Database::pexecute_first($domains_stmt, null, true, true);
$result = array(); if ($result) {
foreach ($customer_ids as $customer_id) { return $this->response(200, "successful", $result['num_subdom']);
Database::pexecute($domains_stmt, array(
"customerid" => $customer_id,
"standardsubdomain" => $customer_stdsubs[$customer_id]
), true, true);
while ($row = $domains_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
} }
} }
return $this->response(200, "successfull", array(
'count' => count($result),
'list' => $result
));
}
/** /**
* delete a subdomain by either id or domainname * delete a subdomain by either id or domainname
@@ -751,6 +918,10 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* optional, the domain-id * optional, the domain-id
* @param string $domainname * @param string $domainname
* optional, the domainname * optional, the domainname
* @param int $customerid
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
* *
* @access admin, customer * @access admin, customer
* @throws \Exception * @throws \Exception
@@ -854,7 +1025,7 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
Customers::decreaseUsage($customer['customerid'], 'subdomains_used'); Customers::decreaseUsage($customer['customerid'], 'subdomains_used');
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted subdomain '" . $result['domain'] . "'"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] deleted subdomain '" . $result['domain'] . "'");
return $this->response(200, "successfull", $result); return $this->response(200, "successful", $result);
} }
/** /**

View File

@@ -0,0 +1,211 @@
<?php
namespace Froxlor\Api\Commands;
use Froxlor\Database\Database;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API
* @since 0.10.6
*
*/
class SysLog extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntity
{
/**
* list all log-entries
*
* @param array $sql_search
* optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue
* @param int $sql_limit
* optional specify number of results to be returned
* @param int $sql_offset
* optional specify offset for resultset
* @param array $sql_orderby
* optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields
*
* @access admin, customer
* @throws \Exception
* @return string json-encoded array count|list
*/
public function listing()
{
$result = array();
$query_fields = array();
if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '1') {
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_LOG . "` " . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit());
} elseif ($this->isAdmin()) {
// get all admin customers
$_custom_list_result = $this->apiCall('Customers.listing');
$custom_list_result = $_custom_list_result['list'];
$customer_names = array();
foreach ($custom_list_result as $customer) {
$customer_names[] = $customer['loginname'];
}
if (count($customer_names) > 0) {
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_LOG . "`
WHERE `user` = :loginname OR `user` IN ('" . implode("', '", $customer_names) . "')" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
} else {
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_LOG . "`
WHERE `user` = :loginname" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
}
$query_fields['loginname'] = $this->getUserDetail('loginname');
} else {
// every one else just sees their logs
$result_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_LOG . "`
WHERE `user` = :loginname AND `action` <> 99 " . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit());
$query_fields['loginname'] = $this->getUserDetail('loginname');
}
Database::pexecute($result_stmt, $query_fields, true, true);
while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) {
$result[] = $row;
}
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list log-entries");
return $this->response(200, "successful", array(
'count' => count($result),
'list' => $result
));
}
/**
* returns the total number of log-entries
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function listingCount()
{
$params = null;
if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '1') {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_logs FROM `" . TABLE_PANEL_LOG . "`
");
} elseif ($this->isAdmin()) {
// get all admin customers
$_custom_list_result = $this->apiCall('Customers.listing');
$custom_list_result = $_custom_list_result['list'];
$customer_names = array();
foreach ($custom_list_result as $customer) {
$customer_names[] = $customer['loginname'];
}
if (count($customer_names) > 0) {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_logs FROM `" . TABLE_PANEL_LOG . "`
WHERE `user` = :loginname OR `user` IN ('" . implode("', '", $customer_names) . "')
");
} else {
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_logs FROM `" . TABLE_PANEL_LOG . "`
WHERE `user` = :loginname
");
}
$params = [
'loginname' => $this->getUserDetail('loginname')
];
} else {
// every one else just sees their logs
$result_stmt = Database::prepare("
SELECT COUNT(*) as num_logs FROM `" . TABLE_PANEL_LOG . "`
WHERE `user` = :loginname AND `action` <> 99
");
$params = [
'loginname' => $this->getUserDetail('loginname')
];
}
$result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) {
return $this->response(200, "successful", $result['num_logs']);
}
}
/**
* You cannot get log entries
*/
public function get()
{
throw new \Exception('You cannot get log entries', 303);
}
/**
* You cannot add log entries
*/
public function add()
{
throw new \Exception('You cannot add log entries', 303);
}
/**
* You cannot update log entries
*/
public function update()
{
throw new \Exception('You cannot update log entries', 303);
}
/**
* delete log entries
*
* @param int $min_to_keep
* optional minutes to keep, default is 10
*
* @access admin
* @throws \Exception
* @return string json-encoded array
*/
public function delete()
{
if ($this->isAdmin()) {
$min_to_keep = self::getParam('min_to_keep', true, 10);
if ($min_to_keep < 0) {
$min_to_keep = 0;
}
$truncatedate = time() - (60 * $min_to_keep);
$params = array();
if ($this->getUserDetail('customers_see_all') == '1') {
$result_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_LOG . "` WHERE `date` < :trunc
");
} else {
// get all admin customers
$_custom_list_result = $this->apiCall('Customers.listing');
$custom_list_result = $_custom_list_result['list'];
$customer_names = array();
foreach ($custom_list_result as $customer) {
$customer_names[] = $customer['loginname'];
}
if (count($customer_names) > 0) {
$result_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_LOG . "` WHERE `date` < :trunc AND `user` = :loginname OR `user` IN ('" . implode("', '", $customer_names) . "')
");
} else {
$result_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_LOG . "` WHERE `date` < :trunc AND `user` = :loginname
");
}
$params = [
'loginname' => $this->getUserDetail('loginname')
];
}
$params['trunc'] = $truncatedate;
Database::pexecute($result_stmt, $params, true, true);
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "[API] truncated the froxlor syslog");
return $this->response(200, "successful", true);
}
throw new \Exception("Not allowed to execute given command.", 403);
}
}

View File

@@ -60,6 +60,10 @@ class Traffic extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* optional, default empty * optional, default empty
* @param int $day * @param int $day
* optional, default empty * optional, default empty
* @param int $date_from
* optional timestamp, default empty, if specified, $year, $month and $day will be ignored
* @param int $date_until
* optional timestamp, default empty, if specified, $year, $month and $day will be ignored
* @param bool $customer_traffic * @param bool $customer_traffic
* optional, admin-only, whether to output ones own traffic or all of ones customers, default is 0 (false) * optional, admin-only, whether to output ones own traffic or all of ones customers, default is 0 (false)
* @param int $customerid * @param int $customerid
@@ -76,10 +80,29 @@ class Traffic extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$year = $this->getParam('year', true, ""); $year = $this->getParam('year', true, "");
$month = $this->getParam('month', true, ""); $month = $this->getParam('month', true, "");
$day = $this->getParam('day', true, ""); $day = $this->getParam('day', true, "");
$date_from = $this->getParam('date_from', true, - 1);
$date_until = $this->getParam('date_until', true, - 1);
$customer_traffic = $this->getBoolParam('customer_traffic', true, 0); $customer_traffic = $this->getBoolParam('customer_traffic', true, 0);
$customer_ids = $this->getAllowedCustomerIds(); $customer_ids = $this->getAllowedCustomerIds();
$result = array(); $result = array();
$params = array(); $params = array();
// validate parameters
if ($date_from >= 0 || $date_until >= 0) {
$year = "";
$month = "";
$day = "";
if ($date_from == $date_until) {
$date_until = -1;
}
if ($date_from >= 0 && $date_until >= 0 && $date_until < $date_from) {
// switch
$temp_ts = $date_from;
$date_from = $date_until;
$date_until = $temp_ts;
}
}
// check for year/month/day // check for year/month/day
$where_str = ""; $where_str = "";
if (! empty($year) && is_numeric($year)) { if (! empty($year) && is_numeric($year)) {
@@ -94,6 +117,17 @@ class Traffic extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$where_str .= " AND `day` = :day"; $where_str .= " AND `day` = :day";
$params['day'] = $day; $params['day'] = $day;
} }
if ($date_from >= 0 && $date_until >= 0) {
$where_str .= " AND `stamp` BETWEEN :df AND :du";
$params['df'] = $date_from;
$params['du'] = $date_until;
} elseif ($date_from >= 0 && $date_until < 0) {
$where_str .= " AND `stamp` > :df";
$params['df'] = $date_from;
} elseif ($date_from < 0 && $date_until >= 0) {
$where_str .= " AND `stamp` < :du";
$params['du'] = $date_until;
}
if (! $this->isAdmin() || ($this->isAdmin() && $customer_traffic)) { if (! $this->isAdmin() || ($this->isAdmin() && $customer_traffic)) {
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
@@ -110,12 +144,22 @@ class Traffic extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$result[] = $row; $result[] = $row;
} }
$this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list traffic"); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list traffic");
return $this->response(200, "successfull", array( return $this->response(200, "successful", array(
'count' => count($result), 'count' => count($result),
'list' => $result 'list' => $result
)); ));
} }
/**
* You cannot count the traffic data list
*
* @throws \Exception
*/
public function listingCount()
{
throw new \Exception('You cannot count the traffic data list', 303);
}
/** /**
* You cannot delete traffic data * You cannot delete traffic data
* *

View File

@@ -56,7 +56,7 @@ class FroxlorRPC
private static function validateAuth($key, $secret) private static function validateAuth($key, $secret)
{ {
$sel_stmt = \Froxlor\Database\Database::prepare(" $sel_stmt = \Froxlor\Database\Database::prepare("
SELECT ak.*, a.api_allowed as admin_api_allowed, c.api_allowed as cust_api_allowed SELECT ak.*, a.api_allowed as admin_api_allowed, c.api_allowed as cust_api_allowed, c.deactivated
FROM `api_keys` ak FROM `api_keys` ak
LEFT JOIN `panel_admins` a ON a.adminid = ak.adminid LEFT JOIN `panel_admins` a ON a.adminid = ak.adminid
LEFT JOIN `panel_customers` c ON c.customerid = ak.customerid LEFT JOIN `panel_customers` c ON c.customerid = ak.customerid
@@ -67,7 +67,7 @@ class FroxlorRPC
'as' => $secret 'as' => $secret
), true, true); ), true, true);
if ($result) { if ($result) {
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))) { 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 && $result['deactivated'] == 0))) {
// get user to check whether api call is allowed // get user to check whether api call is allowed
if (! empty($result['allowed_from'])) { if (! empty($result['allowed_from'])) {
// @todo allow specification and validating of whole subnets later // @todo allow specification and validating of whole subnets later

View File

@@ -21,6 +21,8 @@ interface ResourceEntity
public function listing(); public function listing();
public function listingCount();
public function get(); public function get();
public function add(); public function add();

View File

@@ -35,20 +35,6 @@ abstract class BulkAction
*/ */
private $impFile = null; private $impFile = null;
/**
* customer id of the user the entity is being added to
*
* @var int
*/
private $custId = null;
/**
* array of customer data read from the database
*
* @var array
*/
private $custData = null;
/** /**
* api-function to call for addingg entity * api-function to call for addingg entity
* *
@@ -70,20 +56,27 @@ abstract class BulkAction
*/ */
private $errors = array(); private $errors = array();
/**
* logged in user
*
* @var array
*/
protected $userinfo = array();
/** /**
* class constructor, optionally sets file and customer-id * class constructor, optionally sets file and customer-id
* *
* @param string $import_file * @param string $import_file
* @param int $customer_id * @param array $userinfo
* *
* @return object BulkAction instance * @return object BulkAction instance
*/ */
protected function __construct($import_file = null, $customer_id = 0) protected function __construct($import_file = null, $userinfo = array())
{ {
if (! empty($import_file)) { if (! empty($import_file)) {
$this->impFile = \Froxlor\FileDir::makeCorrectFile($import_file); $this->impFile = \Froxlor\FileDir::makeCorrectFile($import_file);
} }
$this->custId = $customer_id; $this->userinfo = $userinfo;
} }
/** /**
@@ -109,18 +102,6 @@ abstract class BulkAction
$this->impFile = \Froxlor\FileDir::makeCorrectFile($import_file); $this->impFile = \Froxlor\FileDir::makeCorrectFile($import_file);
} }
/**
* setter for customer-id
*
* @param int $customer_id
*
* @return void
*/
public function setCustomer($customer_id = 0)
{
$this->custId = $customer_id;
}
/** /**
* return the list of errors * return the list of errors
* *
@@ -145,21 +126,21 @@ abstract class BulkAction
protected function importEntity($data_array = null) protected function importEntity($data_array = null)
{ {
global $userinfo; if (empty($data_array)) return null;
$module = '\\Froxlor\\Api\\Commands\\' . substr($this->api_call, 0, strpos($this->api_call, ".")); $module = '\\Froxlor\\Api\\Commands\\' . substr($this->api_call, 0, strpos($this->api_call, "."));
$function = substr($this->api_call, strpos($this->api_call, ".") + 1); $function = substr($this->api_call, strpos($this->api_call, ".") + 1);
$new_data = array(); $new_data = array();
foreach ($this->api_params as $idx => $param) { foreach ($this->api_params as $idx => $param) {
if (isset($data_array[$idx]) && ! empty($data_array[$idx])) { if (isset($data_array[$idx])) {
$new_data[$param] = $data_array[$idx]; $new_data[$param] = $data_array[$idx];
} }
} }
$result = null; $result = null;
try { try {
$json_result = $module::getLocal($userinfo, $new_data)->$function(); $json_result = $module::getLocal($this->userinfo, $new_data)->$function();
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
} catch (\Exception $e) { } catch (\Exception $e) {
$this->errors[] = $e->getMessage(); $this->errors[] = $e->getMessage();
@@ -169,7 +150,7 @@ abstract class BulkAction
/** /**
* reads in the csv import file and returns an array with * reads in the csv import file and returns an array with
* all the entites to be imported * all the entities to be imported
* *
* @param string $separator * @param string $separator
* *
@@ -189,6 +170,10 @@ abstract class BulkAction
throw new \Exception("Unable to read file '" . $this->impFile . "'"); throw new \Exception("Unable to read file '" . $this->impFile . "'");
} }
if (empty($separator) || strlen($separator) != 1) {
throw new \Exception("Invalid separator specified: '" . $separator . "'");
}
$file_data = array(); $file_data = array();
$is_params_line = true; $is_params_line = true;
$fh = @fopen($this->impFile, "r"); $fh = @fopen($this->impFile, "r");
@@ -218,37 +203,4 @@ abstract class BulkAction
return $file_data; return $file_data;
} }
/**
* to be called first in doImport() to read in customer and entity data
*/
protected function preImport()
{
$this->readCustomerData();
if ($this->custId <= 0) {
throw new \Exception("Invalid customer selected");
}
if (is_null($this->custData)) {
throw new \Exception("Failed to read customer data");
}
}
/**
* reads customer data from panel_customer by $_custId
*
* @return bool
*/
protected function readCustomerData()
{
$cust_stmt = \Froxlor\Database\Database::prepare("SELECT * FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `customerid` = :cid");
$this->custData = \Froxlor\Database\Database::pexecute_first($cust_stmt, array(
'cid' => $this->custId
));
if (is_array($this->custData) && isset($this->custData['customerid']) && $this->custData['customerid'] == $this->custId) {
return true;
}
$this->custData = null;
return false;
}
} }

View File

@@ -32,9 +32,9 @@ class DomainBulkAction extends BulkAction
* *
* @return object DomainBulkAction instance * @return object DomainBulkAction instance
*/ */
public function __construct($import_file = null, $customer_id = 0) public function __construct($import_file = null, $userinfo)
{ {
parent::__construct($import_file, $customer_id); parent::__construct($import_file, $userinfo);
$this->setApiCall('Domains.add'); $this->setApiCall('Domains.add');
} }
@@ -49,23 +49,14 @@ class DomainBulkAction extends BulkAction
*/ */
public function doImport($separator = ";", $offset = 0) public function doImport($separator = ";", $offset = 0)
{ {
$this->preImport(); if ($this->userinfo['domains'] == "-1") {
// get the admins userinfo to check for domains_used, etc.
global $userinfo;
if ($userinfo['domains'] == "-1") {
$dom_unlimited = true; $dom_unlimited = true;
} else { } else {
$dom_unlimited = false; $dom_unlimited = false;
} }
$domains_used = (int) $userinfo['domains_used']; $domains_used = (int) $this->userinfo['domains_used'];
$domains_avail = (int) $userinfo['domains']; $domains_avail = (int) $this->userinfo['domains'];
if (empty($separator) || strlen($separator) != 1) {
throw new \Exception("Invalid separator specified: '" . $separator . "'");
}
if (! is_int($offset) || $offset < 0) { if (! is_int($offset) || $offset < 0) {
throw new \Exception("Invalid offset specified"); throw new \Exception("Invalid offset specified");

View File

@@ -26,11 +26,16 @@ class ConfigServicesAction extends \Froxlor\Cli\Action
*/ */
private function validate() private function validate()
{ {
global $lng;
$this->checkConfigParam(true); $this->checkConfigParam(true);
$this->parseConfig(); $this->parseConfig();
require FROXLOR_INSTALL_DIR . '/lib/tables.inc.php'; require FROXLOR_INSTALL_DIR . '/lib/tables.inc.php';
include_once FROXLOR_INSTALL_DIR . '/lng/english.lng.php';
include_once FROXLOR_INSTALL_DIR . '/lng/lng_references.php';
if (array_key_exists("import-settings", $this->_args)) { if (array_key_exists("import-settings", $this->_args)) {
$this->importSettings(); $this->importSettings();
} }
@@ -78,6 +83,20 @@ class ConfigServicesAction extends \Froxlor\Cli\Action
$distros = glob($config_dir . '*.xml'); $distros = glob($config_dir . '*.xml');
// tmp array // tmp array
$distributions_select_data = array(); $distributions_select_data = array();
//set default os.
$os_dist = array('ID' => 'buster');
$os_version = array('0' => '10');
$os_default = $os_dist['ID'];
//read os-release
if(file_exists('/etc/os-release')) {
$os_dist = parse_ini_file('/etc/os-release', false);
if(is_array($os_dist) && array_key_exists('ID', $os_dist) && array_key_exists('VERSION_ID', $os_dist)) {
$os_version = explode('.',$os_dist['VERSION_ID'])[0];
}
}
// read in all the distros // read in all the distros
foreach ($distros as $_distribution) { foreach ($distros as $_distribution) {
// get configparser object // get configparser object
@@ -86,6 +105,12 @@ class ConfigServicesAction extends \Froxlor\Cli\Action
$dist_display = $this->getCompleteDistroName($dist); $dist_display = $this->getCompleteDistroName($dist);
// store in tmp array // store in tmp array
$distributions_select_data[$dist_display] = str_replace(".xml", "", strtolower(basename($_distribution))); $distributions_select_data[$dist_display] = str_replace(".xml", "", strtolower(basename($_distribution)));
//guess if this is the current distro.
$ver = explode('.', $dist->distributionVersion)[0];
if (strtolower($os_dist['ID']) == strtolower($dist->distributionName) && $os_version == $ver) {
$os_default = str_replace(".xml", "", strtolower(basename($_distribution)));
}
} }
// sort by distribution name // sort by distribution name
@@ -103,7 +128,7 @@ class ConfigServicesAction extends \Froxlor\Cli\Action
echo PHP_EOL; echo PHP_EOL;
while (! in_array($_daemons_config['distro'], $distributions_select_data)) { while (! in_array($_daemons_config['distro'], $distributions_select_data)) {
$_daemons_config['distro'] = ConfigServicesCmd::getInput("choose distribution", "buster"); $_daemons_config['distro'] = ConfigServicesCmd::getInput("choose distribution", $os_default);
} }
// go through all services and let user check whether to include it or not // go through all services and let user check whether to include it or not
@@ -316,15 +341,45 @@ class ConfigServicesAction extends \Froxlor\Cli\Action
// try to convert namserver hosts to ip's // try to convert namserver hosts to ip's
$ns_ips = ""; $ns_ips = "";
$known_ns_ips = [];
if (Settings::Get('system.nameservers') != '') { if (Settings::Get('system.nameservers') != '') {
$nameservers = explode(',', Settings::Get('system.nameservers')); $nameservers = explode(',', Settings::Get('system.nameservers'));
foreach ($nameservers as $nameserver) { foreach ($nameservers as $nameserver) {
$nameserver = trim($nameserver); $nameserver = trim($nameserver);
// DNS servers might be multi homed; allow transfer from all ip
// addresses of the DNS server
$nameserver_ips = \Froxlor\PhpHelper::gethostbynamel6($nameserver); $nameserver_ips = \Froxlor\PhpHelper::gethostbynamel6($nameserver);
if (is_array($nameserver_ips) && count($nameserver_ips) > 0) { // append dot to hostname
if (substr($nameserver, - 1, 1) != '.') {
$nameserver .= '.';
}
// ignore invalid responses
if (! is_array($nameserver_ips)) {
// act like \Froxlor\PhpHelper::gethostbynamel6() and return unmodified hostname on error
$nameserver_ips = array(
$nameserver
);
} else {
$known_ns_ips = array_merge($known_ns_ips, $nameserver_ips);
}
if (!empty($ns_ips)) {
$ns_ips .= ',';
}
$ns_ips .= implode(",", $nameserver_ips); $ns_ips .= implode(",", $nameserver_ips);
} }
} }
// AXFR server
if (Settings::Get('system.axfrservers') != '') {
$axfrservers = explode(',', Settings::Get('system.axfrservers'));
foreach ($axfrservers as $axfrserver) {
if (!in_array(trim($axfrserver), $known_ns_ips)) {
if (!empty($ns_ips)) {
$ns_ips .= ',';
}
$ns_ips .= trim($axfrserver);
}
}
} }
Database::needSqlData(); Database::needSqlData();
@@ -340,7 +395,6 @@ class ConfigServicesAction extends \Froxlor\Cli\Action
'<SERVERIP>' => Settings::Get('system.ipaddress'), '<SERVERIP>' => Settings::Get('system.ipaddress'),
'<NAMESERVERS>' => Settings::Get('system.nameservers'), '<NAMESERVERS>' => Settings::Get('system.nameservers'),
'<NAMESERVERS_IP>' => $ns_ips, '<NAMESERVERS_IP>' => $ns_ips,
'<AXFRSERVERS>' => Settings::Get('system.axfrservers'),
'<VIRTUAL_MAILBOX_BASE>' => Settings::Get('system.vmail_homedir'), '<VIRTUAL_MAILBOX_BASE>' => Settings::Get('system.vmail_homedir'),
'<VIRTUAL_UID_MAPS>' => Settings::Get('system.vmail_uid'), '<VIRTUAL_UID_MAPS>' => Settings::Get('system.vmail_uid'),
'<VIRTUAL_GID_MAPS>' => Settings::Get('system.vmail_gid'), '<VIRTUAL_GID_MAPS>' => Settings::Get('system.vmail_gid'),
@@ -377,7 +431,7 @@ class ConfigServicesAction extends \Froxlor\Cli\Action
} elseif (! file_exists($this->_args["froxlor-dir"])) { } elseif (! file_exists($this->_args["froxlor-dir"])) {
throw new \Exception("Given froxlor directory cannot be found ('" . $this->_args["froxlor-dir"] . "')"); throw new \Exception("Given froxlor directory cannot be found ('" . $this->_args["froxlor-dir"] . "')");
} elseif (! is_readable($this->_args["froxlor-dir"])) { } elseif (! is_readable($this->_args["froxlor-dir"])) {
throw new \Exception("Given froxlor direcotry cannot be read ('" . $this->_args["froxlor-dir"] . "')"); throw new \Exception("Given froxlor directory cannot be read ('" . $this->_args["froxlor-dir"] . "')");
} }
} }
} }

View File

@@ -62,7 +62,7 @@ class SwitchServerIpAction extends \Froxlor\Cli\Action
$ip_list = $this->_args['switch']; $ip_list = $this->_args['switch'];
if (empty($ip_list) || is_bool($ip_list)) { if (empty($ip_list) || is_bool($ip_list)) {
throw new \Exception("No paramters given for --switch action."); throw new \Exception("No parameters given for --switch action.");
} }
$ips_to_switch = array(); $ips_to_switch = array();
@@ -179,7 +179,7 @@ class SwitchServerIpAction extends \Froxlor\Cli\Action
} elseif (! file_exists($this->_args["froxlor-dir"])) { } elseif (! file_exists($this->_args["froxlor-dir"])) {
throw new \Exception("Given froxlor directory cannot be found ('" . $this->_args["froxlor-dir"] . "')"); throw new \Exception("Given froxlor directory cannot be found ('" . $this->_args["froxlor-dir"] . "')");
} elseif (! is_readable($this->_args["froxlor-dir"])) { } elseif (! is_readable($this->_args["froxlor-dir"])) {
throw new \Exception("Given froxlor direcotry cannot be read ('" . $this->_args["froxlor-dir"] . "')"); throw new \Exception("Given froxlor directory cannot be read ('" . $this->_args["froxlor-dir"] . "')");
} }
} }
} }

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

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

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