Explorar el Código

Merge branch 'main' into release

Jaap Marcus hace 3 años
padre
commit
d1da916656
Se han modificado 85 ficheros con 1021 adiciones y 807 borrados
  1. 21 1
      CHANGELOG.md
  2. 1 1
      bin/v-add-backup-host
  3. 2 0
      bin/v-add-dns-record
  4. 7 2
      bin/v-add-remote-dns-domain
  5. 2 1
      bin/v-add-sys-firewall
  6. 11 1
      bin/v-change-dns-domain-dnssec
  7. 2 0
      bin/v-change-dns-domain-ip
  8. 2 0
      bin/v-change-dns-domain-soa
  9. 2 0
      bin/v-change-dns-domain-tpl
  10. 2 0
      bin/v-change-dns-domain-ttl
  11. 2 0
      bin/v-change-dns-record
  12. 2 0
      bin/v-change-dns-record-id
  13. 4 0
      bin/v-change-sys-webmail
  14. 2 0
      bin/v-delete-dns-record
  15. 9 0
      bin/v-list-sys-config
  16. 2 2
      bin/v-restore-user
  17. 7 2
      bin/v-sync-dns-cluster
  18. 28 2
      docs/docs/introduction/getting-started.md
  19. 45 2
      docs/docs/server-administration/backup-restore.md
  20. 4 4
      docs/docs/server-administration/dns.md
  21. 6 0
      docs/docs/server-administration/email.md
  22. 27 0
      docs/docs/server-administration/troubleshooting.md
  23. 12 10
      func/backup.sh
  24. 3 0
      func/main.sh
  25. 1 1
      func/rebuild.sh
  26. 1 1
      func/syshealth.sh
  27. 22 21
      func/upgrade.sh
  28. 1 0
      install/deb/apache2/apache2.conf
  29. 66 60
      install/hst-install-debian.sh
  30. 46 42
      install/hst-install-ubuntu.sh
  31. 2 2
      install/hst-install.sh
  32. 1 0
      install/rpm/httpd/httpd.conf
  33. 40 28
      install/upgrade/manual/upgrade_mariadb.sh
  34. 0 27
      install/upgrade/versions/1.6.15.sh
  35. 1 1
      install/upgrade/versions/1.7.0.sh
  36. 46 0
      install/upgrade/versions/1.7.1.sh
  37. 13 13
      package.json
  38. 1 1
      src/deb/hestia/control
  39. 4 0
      web/css/src/themes/default.css
  40. 0 0
      web/css/themes/default.min.css
  41. 5 1
      web/delete/log/index.php
  42. 5 7
      web/edit/web/index.php
  43. 3 0
      web/inc/main.php
  44. BIN
      web/locale/hu/LC_MESSAGES/hestiacp.mo
  45. 1 1
      web/locale/languages.json
  46. BIN
      web/locale/pt-br/LC_MESSAGES/hestiacp.mo
  47. BIN
      web/locale/pt/LC_MESSAGES/hestiacp.mo
  48. BIN
      web/locale/ru/LC_MESSAGES/hestiacp.mo
  49. BIN
      web/locale/tr/LC_MESSAGES/hestiacp.mo
  50. BIN
      web/locale/zh-cn/LC_MESSAGES/hestiacp.mo
  51. 1 1
      web/src/app/System/HestiaApp.php
  52. 2 0
      web/templates/pages/add_dns.php
  53. 8 8
      web/templates/pages/add_firewall_ipset.php
  54. 10 10
      web/templates/pages/add_user.php
  55. 2 0
      web/templates/pages/edit_dns.php
  56. 3 3
      web/templates/pages/edit_mail.php
  57. 11 11
      web/templates/pages/edit_server.php
  58. 15 34
      web/templates/pages/edit_user.php
  59. 3 3
      web/templates/pages/list_access_keys.php
  60. 10 10
      web/templates/pages/list_backup.php
  61. 16 16
      web/templates/pages/list_backup_detail.php
  62. 20 20
      web/templates/pages/list_cron.php
  63. 13 13
      web/templates/pages/list_db.php
  64. 19 19
      web/templates/pages/list_dns.php
  65. 4 4
      web/templates/pages/list_dns_public.php
  66. 14 14
      web/templates/pages/list_dns_rec.php
  67. 3 3
      web/templates/pages/list_firewall.php
  68. 9 9
      web/templates/pages/list_firewall_banlist.php
  69. 2 2
      web/templates/pages/list_ip.php
  70. 9 9
      web/templates/pages/list_key.php
  71. 15 15
      web/templates/pages/list_log.php
  72. 5 5
      web/templates/pages/list_log_auth.php
  73. 4 4
      web/templates/pages/list_rrd.php
  74. 27 29
      web/templates/pages/list_search.php
  75. 4 4
      web/templates/pages/list_ssl.php
  76. 1 1
      web/templates/pages/login/login.php
  77. 1 1
      web/templates/pages/login/login_1.php
  78. 1 1
      web/templates/pages/login/login_2.php
  79. 2 2
      web/templates/pages/login/login_a.php
  80. 2 2
      web/templates/pages/login/reset2fa.php
  81. 2 2
      web/templates/pages/login/reset_1.php
  82. 1 1
      web/templates/pages/login/reset_2.php
  83. 2 2
      web/templates/pages/login/reset_3.php
  84. 1 1
      web/templates/pages/setup_webapp.php
  85. 315 314
      yarn.lock

+ 21 - 1
CHANGELOG.md

@@ -2,7 +2,27 @@
 
 All notable changes to this project will be documented in this file.
 
-## [Development] - Service release
+## [1.7.1] - Service release
+
+### Bugfixes
+
+- Fixed an issue with wildcard overruling webmail.domain.com config in Apache2 (#3400 #1631)
+- Removed delete button edit user page (#3997)
+- Fixed an issue with serial not increasing (#3396)
+- Fixed an issue with new hestia-zone sync and servers behind NAT or with multiple IPs (#3388 #3396)
+- Remove option to enable DNSSEC when DNSSEC is not supported (#3372 #3396)
+- Fix toolbar items on locales with long words (#3380 #3395)
+- Only count \*.tar files in rotate routine (#3393 #3385)
+- Fixed broken upgrade_mariadb.sh (#3391 @myrevery)
+- Improve add_firewall_ipset.php (#3390 @myrevery)
+- Update Path change of IPset blacklist.sh (#3389 @myrevery)
+- Improve upgrade script Cloudflare ips (#3388 @myrevery)
+- Update supported message hst-install.sh (#3377 @shizualand)
+- Fixed an issue with adding own ssl certificated to website config (#3374 #3371)
+- Fixed javascript logic edit mail domains (#3373)
+- Add required attribute to login forms (#3376)
+
+## [1.7.0] - Feature / Major release
 
 ### Note
 

+ 1 - 1
bin/v-add-backup-host

@@ -298,7 +298,7 @@ if [ "$type" = 'rclone' ]; then
 			rclone delete $host:$path/hestia-backup.txt
 		fi
 	else
-		check_result "$E_CONNECT" "Rclone config does not exits"
+		check_result "$E_CONNECT" "Rclone config does not exist"
 	fi
 fi
 

+ 2 - 0
bin/v-add-dns-record

@@ -132,6 +132,8 @@ chmod 660 $zone
 # Sorting records
 sort_dns_records
 
+# Update serial
+update_domain_serial
 # Updating zone
 if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
 	# Do full rebuild due DNS SEC

+ 7 - 2
bin/v-add-remote-dns-domain

@@ -58,8 +58,13 @@ fi
 if [ "$DNS_CLUSTER_SYSTEM" = "hestia-zone" ]; then
 	str=$(echo "$str" | sed "s/SLAVE='no'/SLAVE='yes'/g")
 	str=$(echo "$str" | sed "s/SLAVE=''/SLAVE='yes'/g")
-	ip=$($BIN/v-list-sys-ips plain | cut -f1 | head -n1)
-	str=$(echo "$str" | sed "s/MASTER=''/MASTER='$ip'/g")
+	ip=$(ip addr | grep 'inet ' | grep global | head -n1 | awk '{print $2}' | cut -f1 -d/)
+	source_conf $HESTIA/data/ips/$ip
+	if [ -z $NAT ]; then
+		str=$(echo "$str" | sed "s/MASTER=''/MASTER='$ip'/g")
+	else
+		str=$(echo "$str" | sed "s/MASTER=''/MASTER='$NAT'/g")
+	fi
 fi
 
 IFS=$'\n'

+ 2 - 1
bin/v-add-sys-firewall

@@ -35,7 +35,8 @@ check_hestia_demo_mode
 
 # Adding default ruleset
 if [ -z "$(ls -A $HESTIA/data/firewall 2> /dev/null)" ]; then
-	cp -rf $HESTIA_INSTALL_DIR/firewall $HESTIA/data/
+	cp -rf $HESTIA_COMMON_DIR/firewall $HESTIA/data/
+	rm -f $HESTIA/data/firewall/ipset/blacklist.sh $HESTIA/data/firewall/ipset/blacklist.ipv6.sh
 fi
 
 # Updating FIREWAL_SYSTEM value

+ 11 - 1
bin/v-change-dns-domain-dnssec

@@ -51,6 +51,15 @@ fi
 # Perform verification if read-only mode is enabled
 check_hestia_demo_mode
 
+if [ "$DNS_CLUSTER_SYSTEM" != 'hestia-zone' ]; then
+	check_result "$E_DISABLED" "DNSSEC is not supported when DNS_CLUSTER_SYSTEM is not set to hestia-zone"
+fi
+
+version=$(named -v | awk 'NR==1{print $2}')
+if version_ge '9.18' $version; then
+	check_result "$E_DISABLED" "DNSSEC is not supported when bind / named < 9.18"
+fi
+
 #----------------------------------------------------------#
 #                       Action                             #
 #----------------------------------------------------------#
@@ -64,8 +73,9 @@ syshealth_repair_dns_config
 # Changing exp
 update_object_value 'dns' 'DOMAIN' "$domain" '$DNSSEC' "$status"
 
+# Update serial
+update_domain_serial
 # Rebuild DNS config
-
 rebuild_dns_domain_conf
 
 if [ $status = "no" ]; then

+ 2 - 0
bin/v-change-dns-domain-ip

@@ -63,6 +63,8 @@ update_object_value 'dns' 'DOMAIN' "$domain" '$IP' "$ip"
 # Changing records
 sed -i "s/$old/$ip/g" $USER_DATA/dns/$domain.conf
 
+# Update serial
+update_domain_serial
 # Updating zone
 if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
 	rebuild_dns_domain_conf

+ 2 - 0
bin/v-change-dns-domain-soa

@@ -57,6 +57,8 @@ check_hestia_demo_mode
 # Changing soa
 update_object_value 'dns' 'DOMAIN' "$domain" '$SOA' "$soa"
 
+# Update serial
+update_domain_serial
 # Updating zone
 if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
 	rebuild_dns_domain_conf

+ 2 - 0
bin/v-change-dns-domain-tpl

@@ -131,6 +131,8 @@ if [ "$template" = "office365" ]; then
 	fi
 fi
 
+# Update serial
+update_domain_serial
 # Updating zone
 if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
 	rebuild_dns_domain_conf

+ 2 - 0
bin/v-change-dns-domain-ttl

@@ -56,6 +56,8 @@ check_hestia_demo_mode
 # Changing ttl
 update_object_value 'dns' 'DOMAIN' "$domain" '$TTL' "$ttl"
 
+# Update serial
+update_domain_serial
 # Updating zone
 if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
 	rebuild_dns_domain_conf

+ 2 - 0
bin/v-change-dns-record

@@ -136,6 +136,8 @@ echo "$dns_rec" >> $USER_DATA/dns/$domain.conf
 # Sorting records
 sort_dns_records
 
+# Update serial
+update_domain_serial
 # Updating zone
 if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
 	rebuild_dns_domain_conf

+ 2 - 0
bin/v-change-dns-record-id

@@ -62,6 +62,8 @@ sed -i "s/^ID='$id'/ID='$newid'/" $USER_DATA/dns/$domain.conf
 # Sorting records
 sort_dns_records
 
+# Update serial
+update_domain_serial
 # Updating zone
 if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
 	rebuild_dns_domain_conf

+ 4 - 0
bin/v-change-sys-webmail

@@ -51,6 +51,10 @@ for user in $($BIN/v-list-sys-users plain); do
 	done
 done
 
+if [ -d /etc/apache2/ ]; then
+	sed -i "s/IncludeOptional conf.d\/domains\/$WEBMAIL_ALIAS.*.conf/IncludeOptional conf.d\/domains\/$NEW_ALIAS.*.conf/g" /etc/apache2/apache2.conf
+fi
+
 #----------------------------------------------------------#
 #                       Hestia                             #
 #----------------------------------------------------------#

+ 2 - 0
bin/v-delete-dns-record

@@ -56,6 +56,8 @@ check_hestia_demo_mode
 # Deleting record
 sed -i "/^ID='$id'/d" $USER_DATA/dns/$domain.conf
 
+# Update serial
+update_domain_serial
 # Updating zone
 if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
 	rebuild_dns_domain_conf

+ 9 - 0
bin/v-list-sys-config

@@ -44,6 +44,8 @@ json_list() {
         "DB_SYSTEM": "'$DB_SYSTEM'",
         "DNS_SYSTEM": "'$DNS_SYSTEM'",
         "DNS_CLUSTER": "'$DNS_CLUSTER'",
+		"DNS_CLUSTER_SYSTEM": "'$DNS_CLUSTER_SYSTEM'",
+		"SUPPORT_DNSSEC": "'$SUPPORT_DNSSEC'",
         "STATS_SYSTEM": "'$STATS_SYSTEM'",
         "BACKUP_SYSTEM": "'$BACKUP_SYSTEM'",
         "CRON_SYSTEM": "'$CRON_SYSTEM'",
@@ -266,6 +268,13 @@ csv_list() {
 #                       Action                             #
 #----------------------------------------------------------#
 
+version=$(named -v | awk 'NR==1{print $2}')
+if version_ge '9.18' $version; then
+	SUPPORT_DNSSEC="yes"
+else
+	SUPPORT_DNSSEC="no"
+fi
+
 # Listing data
 case $format in
 	json) json_list ;;

+ 2 - 2
bin/v-restore-user

@@ -350,11 +350,11 @@ if [ "$web" != 'no' ] && [ -n "$WEB_SYSTEM" ]; then
 			if [[ "$file" == *.ca ]] || [[ "$file" == *.crt ]] || [[ "$file" == *.key ]] || [[ "$file" == *.pem ]] || [[ "$file" == *.conf ]]; then
 				continue
 			fi
-			if grep "fastcgi_pass" file; then
+			if grep "fastcgi_pass" "$file"; then
 				# Do not allow to run php under a different user
 				continue
 			fi
-			filename=$(basename $file)
+			filename=$(basename "$file")
 			cp -f "$file" "$HOMEDIR/$user/conf/web/$domain/$filename"
 		done
 

+ 7 - 2
bin/v-sync-dns-cluster

@@ -86,8 +86,13 @@ for cluster in $hosts; do
 						str=$(echo "$str" | sed "s/SLAVE='no'/SLAVE='yes'/g")
 						str=$(echo "$str" | sed "s/SLAVE=''/SLAVE='yes'/g")
 
-						ip=$($BIN/v-list-sys-ips plain | cut -f1 | head -n1)
-						str=$(echo "$str" | sed "s/MASTER=''/MASTER='$ip'/g")
+						ip=$(ip addr | grep 'inet ' | grep global | head -n1 | awk '{print $2}' | cut -f1 -d/)
+						source_conf $HESTIA/data/ips/$ip
+						if [ -z $NAT ]; then
+							str=$(echo "$str" | sed "s/MASTER=''/MASTER='$ip'/g")
+						else
+							str=$(echo "$str" | sed "s/MASTER=''/MASTER='$NAT'/g")
+						fi
 
 						# Syncing domain data
 						cluster_cmd v-insert-dns-domain $DNS_USER "$str" $HOSTNAME $flush 'no'

+ 28 - 2
docs/docs/introduction/getting-started.md

@@ -37,14 +37,40 @@ Hestia does not support non-LTS Operating systems. If you install it on, for exa
 
 Interactive installer that will install the default Hestia software configuration.
 
+### Step 1: Download
+
+Download the installation script for the latest release:
+
+```bash
+wget https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh
+```
+
+If the download fails due to an SSL validation error, please be sure you've installed the ca-certificate package on your system - you can do this with the following command:
+
+```bash
+apt-get update && apt-get install ca-certificates
+```
+
+### Step 2: Run
+
+To begin the installation process, simply run the script and follow the on-screen prompts:
+
 ```bash
-wget -qO - https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh | bash
+bash hst-install.sh
 ```
 
+You will receive a welcome email at the address specified during installation (if applicable) and on-screen instructions after the installation is completed to log in and access your server.
+
 ## Custom installation
 
 If you want to customise which software gets installed, or want to run an unattended installation, you will need to run a custom installation.
 
+To view a list of available options, run
+
+```bash
+bash hst-install.sh -h
+```
+
 ### List of installation options
 
 ::: tip
@@ -86,7 +112,7 @@ To choose what software gets installed, you can provide flags to the installatio
 #### Example
 
 ```bash
-wget -qO - https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh | bash -s -- \
+bash hst-install.sh \
 	--interactive no \
 	--hostname host.domain.tld \
 	--email email@domain.tld \

+ 45 - 2
docs/docs/server-administration/backup-restore.md

@@ -105,16 +105,59 @@ curl https://rclone.org/install.sh | sudo bash
 
 Once the download and installation is complete, run `rclone config` and then `n`. Follow the instruction on the screen, then save when completed.
 
+To verify if it is working run as intended:
+
+```bash
+echo "test" > /tmp/backuptest.txt
+rclone cp /tmp/backuptest.txt $HOST:$FOLDER/backuptest.txt
+rclone lsf $HOST:$FOLDER
+```
+
+And see the file has been uploaded
+
+```bash
+rclone delete $HOST:$FOLDER/backuptest.txt
+```
+
 Once the config has been saved you can setup Hestia with the following command:
 
 ```bash
-v-add-backup-host 'rclone' 'config_name' '' '' 'Bucket or Folder name' ''
+v-add-backup-host 'rclone' 'remote-name' '' '' 'Bucket or Folder name' ''
 ```
 
 ::: tip
-B2 requires you to setup a bucket during the `v-add-backup-host` stage. S3 or R2 storage will work fine during the setup stage.
+Configuration per endpoint might be different! Make sure to test it is working before relying on it. To verify it works run
+
+```bash
+v-backup-user admin
+```
+
 :::
 
+For example:
+
+```bash
+rclone config
+
+Current remotes:
+
+Name Type
+==== ====
+r2 s3
+```
+
+To use the "R2" endpoint use
+
+```bash
+v-add-backup-host 'rclone' 'r2' '' '' 'folder'
+```
+
+For Blackblaze use
+
+```bash
+v-add-backup-host 'rclone' 'b2' '' '' 'hestiacp'
+```
+
 ## How to change default backup folder
 
 For security reasons, symlinks are not allowed. To change the default backup folder, you can do the following:

+ 4 - 4
docs/docs/server-administration/dns.md

@@ -22,13 +22,13 @@ With the release of 1.6.0, we have implemented a new API authentication system.
 If you still want to use the legacy API to authenticate with **admin** username and the password make sure **Enable legacy API** access is set to **yes**.
 :::
 
-### DNS Cluster with the Hestia API (Master <-> Master)
+### DNS Cluster with the Hestia API (Master <-> Master) "Default setup!"
 
 ::: warning
 This method does not support DNSSEC!
 :::
 
-1. Create a new user on the Hestia server that will act as a “Slave”.
+1. Create a new user on the Hestia server that will act as a “Slave”. Make sure it uses the username of "dns-user" or has the role `dns-cluster`
 2. Run the following command to enable the DNS server.
 
 ```bash
@@ -47,7 +47,7 @@ There is no limitation on how to chain DNS servers.
 
 ### DNS Cluster with the Hestia API (Master -> Slave)
 
-1. Create a new user on the Hestia server that will act as a “Slave”.
+1. Create a new user on the Hestia server that will act as a “Slave”. Make sure it uses the username of "dns-user" or has the role `dns-cluster`
 2. In `/usr/local/hestia/conf/hestia.conf`, change `DNS_CLUSTER_SYSTEM='hestia'` to `DNS_CLUSTER_SYSTEM='hestia-zone'`.
 3. On the master server, open `/etc/bind/named.options`, do the following changes, then restart bind9 with `systemctl restart bind9`.
 
@@ -147,7 +147,7 @@ v-add-remote-dns-host slave.yourhost.com 8083 api_key '' '' useraccount
 With the new API system, you can also replace `api_key` with `access_key:secret_key`
 
 ::: info
-Please note that currently, only the user `dns-user` is exempted from syncing to other servers. If you have a DNS cluster with multiple master slaves you might run in issues.
+By default the user `dns-user` or user with the role `dns-cluster` are exempted from syncing to other DNS servers!
 :::
 
 ## I am not able to add a server as DNS host

+ 6 - 0
docs/docs/server-administration/email.md

@@ -37,6 +37,12 @@ If not, you have 2 options:
    - [SMTP2GO](https://www.smtp2go.com)
    - [Sendinblue](https://www.sendinblue.com)
 
+## What is an SMTP relay service and how to set it up
+
+SMTP mail relay is the process of transferring an email from one server to another for delivery. Often email from a server is blocked by de service provider due to fear of spam. Or the IP reputation is so low that all email go straight into the spam box. To prevent such issues a lot of companies offer a SMTP relay that takes care of the delivery part. As they send a lot email via the same ip addresses they have a better reputation.
+
+To setup create a account by the provider you want or use and follow their instruction to update your DNS. When completed you can enter the SMTP user account they provider in the settings under "Global SMTP" or under the "Edit mail domain" -> "SMTP relay"
+
 ## I am unable to receive email
 
 If you are unable to receive emails, make sure you have setup your DNS properly. If you are using Cloudflare, disable the use of the proxy for `mail.domain.tld`.

+ 27 - 0
docs/docs/server-administration/troubleshooting.md

@@ -28,3 +28,30 @@ v-change-user-config-value admin LOGIN_ALLOW_IPS ''
 ## Can I update my cronjobs via `crontab -e`?
 
 No, you cannot. When you update HestiaCP, the crontab will simply get overwritten. The changes will not get saved in backups either.
+
+## After update Apache2 I am not able to restart Apache2 or Nginx
+
+The error message states (98) Address already in use: AG0072: make_sock: could not bind to address 0.0.0.0:80
+
+When a package update sometimes comes with a new config and probally it has been overwritten...
+
+```batch
+Configuration file '/etc/apache2/apache2.conf'
+ ==> Modified (by you or by a script) since installation.
+ ==> Package distributor has shipped an updated version.
+   What would you like to do about it ?  Your options are:
+	Y or I  : install the package maintainer's version
+	N or O  : keep your currently-installed version
+	  D     : show the differences between the versions
+	  Z     : start a shell to examine the situation
+ The default action is to keep your current version.
+*** apache2.conf (Y/I/N/O/D/Z) [default=N] ?
+```
+
+If you see this message **ALWAYS** press "N" or **ENTER** to select the default value!
+
+How ever if you entered Y or I. Then replace the config that can be found in /root/hst_backups/xxxxx/conf/apache2/ folder and copy over apache2.conf and ports.conf to /etc/apache2/ folder
+
+xxxxxx is the date/time the backup is made during the last update of HestiaCP
+
+If you don't have have a backup made you can also copy the config in /usr/local/hestia/install/deb/apache2/apache2.conf to /etc/apache2.conf and also empty /etc/apache2/ports.conf

+ 12 - 10
func/backup.sh

@@ -124,11 +124,11 @@ ftp_backup() {
 		return "$E_FTP"
 	fi
 
-	# Checking retention
+	# Checking retention (Only include .tar files)
 	if [ -z $BPATH ]; then
-		backup_list=$(ftpc "ls" | awk '{print $9}' | grep "^$user\.")
+		backup_list=$(ftpc "ls" | awk '{print $9}' | grep "^$user\." | grep ".tar")
 	else
-		backup_list=$(ftpc "cd $BPATH" "ls" | awk '{print $9}' | grep "^$user\.")
+		backup_list=$(ftpc "cd $BPATH" "ls" | awk '{print $9}' | grep "^$user\." | grep ".tar")
 	fi
 	backups_count=$(echo "$backup_list" | wc -l)
 	if [ "$backups_count" -ge "$BACKUPS" ]; then
@@ -399,11 +399,11 @@ sftp_backup() {
 		return "$rc"
 	fi
 
-	# Checking retention
+	# Checking retention (Only include .tar files)
 	if [ -z $BPATH ]; then
-		backup_list=$(sftpc "ls -l" | awk '{print $9}' | grep "^$user\.")
+		backup_list=$(sftpc "ls -l" | awk '{print $9}' | grep "^$user\." | grep ".tar")
 	else
-		backup_list=$(sftpc "cd $BPATH" "ls -l" | awk '{print $9}' | grep "^$user\.")
+		backup_list=$(sftpc "cd $BPATH" "ls -l" | awk '{print $9}' | grep "^$user\." | grep ".tar")
 	fi
 	backups_count=$(echo "$backup_list" | wc -l)
 	if [ "$backups_count" -ge "$BACKUPS" ]; then
@@ -510,7 +510,7 @@ b2_delete() {
 rclone_backup() {
 	# Define rclone config
 	source_conf "$HESTIA/conf/rclone.backup.conf"
-	echo -e "$(date "+%F %T") Upload With Rclone: $user.$backup_new_date.tar"
+	echo -e "$(date "+%F %T") Upload With Rclone to $HOST: $user.$backup_new_date.tar"
 	if [ "$localbackup" != 'yes' ]; then
 		cd $tmpdir
 		tar -cf $BACKUP/$user.$backup_new_date.tar .
@@ -518,12 +518,13 @@ rclone_backup() {
 	cd $BACKUP/
 
 	if [ -z "$BPATH" ]; then
-		rclone copy -v $user.$backup_new_date.tar $HOST
+		rclone copy -v $user.$backup_new_date.tar $HOST:$backup
 		if [ "$?" -ne 0 ]; then
 			check_result "$E_CONNECT" "Unable to upload backup"
 		fi
 
-		backup_list=$(rclone lsf $HOST | cut -d' ' -f1 | grep "^$user\.")
+		# Only include *.tar files
+		backup_list=$(rclone lsf $HOST: | cut -d' ' -f1 | grep "^$user\." | grep ".tar")
 		backups_count=$(echo "$backup_list" | wc -l)
 		backups_rm_number=$((backups_count - BACKUPS))
 		if [ "$backups_count" -ge "$BACKUPS" ]; then
@@ -538,7 +539,8 @@ rclone_backup() {
 			check_result "$E_CONNECT" "Unable to upload backup"
 		fi
 
-		backup_list=$(rclone lsf $HOST:$BPATH | cut -d' ' -f1 | grep "^$user\.")
+		# Only include *.tar files
+		backup_list=$(rclone lsf $HOST:$BPATH | cut -d' ' -f1 | grep "^$user\." | grep ".tar")
 		backups_count=$(echo "$backup_list" | wc -l)
 		backups_rm_number=$(($backups_count - $BACKUPS))
 		if [ "$backups_count" -ge "$BACKUPS" ]; then

+ 3 - 0
func/main.sh

@@ -169,6 +169,9 @@ check_args() {
 	fi
 }
 
+# Define version check function
+version_ge() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1" -o -n "$1" -a "$1" = "$2"; }
+
 # Subsystem checker
 is_system_enabled() {
 	if [ -z "$1" ] || [ "$1" = no ]; then

+ 1 - 1
func/rebuild.sh

@@ -170,7 +170,7 @@ rebuild_user_conf() {
 		else
 			dns_group='bind'
 		fi
-		chown root:$dns_group $HOMEDIR/$user/conf/dns
+		chown $dns_group:$dns_group $HOMEDIR/$user/conf/dns
 		if [ "$create_user" = "yes" ]; then
 			$BIN/v-rebuild-dns-domains $user $restart
 		fi

+ 1 - 1
func/syshealth.sh

@@ -52,7 +52,7 @@ function syshealth_update_web_config_format() {
 	# WEB DOMAINS
 	# Create array of known keys in configuration file
 	system="web"
-	known_keys="DOMAIN IP IP6 CUSTOM_DOCROOT CUSTOM_PHPROOT FASTCGI_CACHE FASTCGI_DURATION ALIAS TPL SSL SSL_FORCE SSL_HOME LETSENCRYPT FTP_USER FTP_MD5 FTP_PATH BACKEND PROXY PROXY_EXT STATS STATS_USER STATS_CRYPT REDIRECT REDIRECT_CODE AUTH_USER AUTH_HASH SUSPENDED TIME DATE"
+	known_keys="DOMAIN IP IP6 CUSTOM_DOCROOT CUSTOM_PHPROOT FASTCGI_CACHE FASTCGI_DURATION ALIAS TPL SSL SSL_FORCE SSL_HSTS SSL_HOME LETSENCRYPT FTP_USER FTP_MD5 FTP_PATH BACKEND PROXY PROXY_EXT STATS STATS_USER STATS_CRYPT REDIRECT REDIRECT_CODE AUTH_USER AUTH_HASH SUSPENDED TIME DATE"
 	write_kv_config_file
 	unset system
 	unset known_keys

+ 22 - 21
func/upgrade.sh

@@ -14,9 +14,6 @@ source $HESTIA/func/syshealth.sh
 #######                Functions & Initialization             #######
 #####################################################################
 
-# Define version check function
-function version_ge() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1" -o -n "$1" -a "$1" = "$2"; }
-
 add_upgrade_message() {
 	if [ -f "$HESTIA_BACKUP/message.log" ]; then
 		echo -e $1 >> $HESTIA_BACKUP/message.log
@@ -551,24 +548,28 @@ upgrade_b2_tool() {
 }
 
 upgrade_cloudflare_ip() {
-	echo "[ * ] Update Cloudflare IP"
-	# https://github.com/ergin/nginx-cloudflare-real-ip/
-	CLOUDFLARE_FILE_PATH='/etc/nginx/conf.d/cloudflare.inc'
-	echo "#Cloudflare" > $CLOUDFLARE_FILE_PATH
-	echo "" >> $CLOUDFLARE_FILE_PATH
-
-	echo "# - IPv4" >> $CLOUDFLARE_FILE_PATH
-	for i in $(curl -s -L https://www.cloudflare.com/ips-v4); do
-		echo "set_real_ip_from $i;" >> $CLOUDFLARE_FILE_PATH
-	done
-	echo "" >> $CLOUDFLARE_FILE_PATH
-	echo "# - IPv6" >> $CLOUDFLARE_FILE_PATH
-	for i in $(curl -s -L https://www.cloudflare.com/ips-v6); do
-		echo "set_real_ip_from $i;" >> $CLOUDFLARE_FILE_PATH
-	done
-
-	echo "" >> $CLOUDFLARE_FILE_PATH
-	echo "real_ip_header CF-Connecting-IP;" >> $CLOUDFLARE_FILE_PATH
+	if [ "$WEB_SYSTEM" = "nginx" ] || [ "$PROXY_SYSTEM" = "nginx" ]; then
+		cf_ips="$(curl -fsLm2 --retry 1 https://api.cloudflare.com/client/v4/ips)"
+
+		if [ -n "$cf_ips" ] && [ "$(echo "$cf_ips" | jq -r '.success//""')" = "true" ]; then
+			cf_inc="/etc/nginx/conf.d/cloudflare.inc"
+
+			echo "[ * ] Updating Cloudflare IP Ranges for Nginx..."
+			echo "# Cloudflare IP Ranges" > $cf_inc
+			echo "" >> $cf_inc
+			echo "# IPv4" >> $cf_inc
+			for ipv4 in $(echo "$cf_ips" | jq -r '.result.ipv4_cidrs[]//""' | sort); do
+				echo "set_real_ip_from $ipv4;" >> $cf_inc
+			done
+			echo "" >> $cf_inc
+			echo "# IPv6" >> $cf_inc
+			for ipv6 in $(echo "$cf_ips" | jq -r '.result.ipv6_cidrs[]//""' | sort); do
+				echo "set_real_ip_from $ipv6;" >> $cf_inc
+			done
+			echo "" >> $cf_inc
+			echo "real_ip_header CF-Connecting-IP;" >> $cf_inc
+		fi
+	fi
 }
 
 upgrade_phppgadmin() {

+ 1 - 0
install/deb/apache2/apache2.conf

@@ -81,6 +81,7 @@ LogFormat "%{User-agent}i" agent
 LogFormat "%b" bytes
 
 IncludeOptional conf.d/*.conf
+IncludeOptional conf.d/domains/webmail.*.conf
 IncludeOptional conf.d/domains/*.conf
 
 # Include the virtual host configurations:

+ 66 - 60
install/hst-install-debian.sh

@@ -24,38 +24,32 @@ memory=$(grep 'MemTotal' /proc/meminfo | tr ' ' '\n' | grep [0-9])
 hst_backups="/root/hst_install_backups/$(date +%d%m%Y%H%M)"
 spinner="/-\|"
 os='debian'
-architecture="$(arch)"
-release=$(cat /etc/debian_version | tr "." "\n" | head -n1)
+release="$(cat /etc/debian_version | tr "." "\n" | head -n1)"
 codename="$(cat /etc/os-release | grep VERSION= | cut -f 2 -d \( | cut -f 1 -d \))"
+architecture="$(arch)"
 HESTIA_INSTALL_DIR="$HESTIA/install/deb"
 HESTIA_COMMON_DIR="$HESTIA/install/common"
 VERBOSE='no'
 
 # Define software versions
-HESTIA_INSTALL_VER='1.7.0'
+HESTIA_INSTALL_VER='1.7.1'
 # Dependencies
 multiphp_v=("5.6" "7.0" "7.1" "7.2" "7.3" "7.4" "8.0" "8.1" "8.2")
 fpm_v="8.1"
 mariadb_v="10.11"
 
-software="nginx apache2 apache2-utils apache2-suexec-custom
-  apache2-suexec-pristine libapache2-mod-fcgid libapache2-mod-php$fpm_v
-  php$fpm_v php$fpm_v-common php$fpm_v-cgi php$fpm_v-mysql php$fpm_v-curl
-  php$fpm_v-pgsql php$fpm_v-imagick php$fpm_v-imap php$fpm_v-ldap
-  php$fpm_v-apcu php$fpm_v-zip php$fpm_v-bz2 php$fpm_v-cli
-  php$fpm_v-gd php$fpm_v-intl php$fpm_v-mbstring
-  php$fpm_v-opcache php$fpm_v-pspell php$fpm_v-readline php$fpm_v-xml
-  awstats vsftpd proftpd-basic bind9 exim4 exim4-daemon-heavy
-  clamav-daemon spamassassin dovecot-imapd dovecot-pop3d dovecot-sieve dovecot-managesieved
-  net-tools mariadb-client mariadb-common mariadb-server mysql-client mysql-common mysql-server postgresql
-  postgresql-contrib mc flex whois git idn2 unzip zip sudo bc ftp lsof
-  rrdtool quota e2fslibs bsdutils e2fsprogs curl imagemagick fail2ban
-  dnsutils bsdmainutils cron hestia=${HESTIA_INSTALL_VER} hestia-nginx
-  hestia-php expect libmail-dkim-perl unrar-free vim-common acl sysstat
-  rsyslog openssh-server util-linux ipset libapache2-mpm-itk zstd
-  lsb-release jq"
-
-installer_dependencies="apt-transport-https curl dirmngr gnupg wget ca-certificates"
+# Defining software pack for all distros
+software="acl apache2 apache2-suexec-custom apache2-suexec-pristine apache2-utils awstats bc bind9 bsdmainutils bsdutils
+  clamav-daemon cron curl dnsutils dovecot-imapd dovecot-managesieved dovecot-pop3d dovecot-sieve e2fslibs e2fsprogs
+  exim4 exim4-daemon-heavy expect fail2ban flex ftp git hestia=${HESTIA_INSTALL_VER} hestia-nginx hestia-php idn2
+  imagemagick ipset jq libapache2-mod-fcgid libapache2-mod-php$fpm_v libapache2-mpm-itk libmail-dkim-perl lsb-release
+  lsof mariadb-client mariadb-common mariadb-server mc mysql-client mysql-common mysql-server net-tools nginx openssh-server
+  php$fpm_v php$fpm_v-apcu php$fpm_v-bz2 php$fpm_v-cgi php$fpm_v-cli php$fpm_v-common php$fpm_v-curl php$fpm_v-gd
+  php$fpm_v-imagick php$fpm_v-imap php$fpm_v-intl php$fpm_v-ldap php$fpm_v-mbstring php$fpm_v-mysql php$fpm_v-opcache
+  php$fpm_v-pgsql php$fpm_v-pspell php$fpm_v-readline php$fpm_v-xml php$fpm_v-zip postgresql postgresql-contrib
+  proftpd-basic quota rrdtool rsyslog spamassassin sudo sysstat unrar-free unzip util-linux vim-common vsftpd whois zip zstd"
+
+installer_dependencies="apt-transport-https ca-certificates curl dirmngr gnupg wget"
 
 # Defining help function
 help() {
@@ -313,13 +307,13 @@ if [ "$exim" = 'no' ]; then
 	spamd='no'
 	dovecot='no'
 fi
-if [ "$dovecot" = "no" ]; then
+if [ "$dovecot" = 'no' ]; then
 	sieve='no'
 fi
 if [ "$iptables" = 'no' ]; then
 	fail2ban='no'
 fi
-if [ "$apache" = "no" ]; then
+if [ "$apache" = 'no' ]; then
 	phpfpm='yes'
 fi
 if [ "$mysql" = 'yes' ] && [ "$mysqlclassic" = 'yes' ]; then
@@ -375,7 +369,7 @@ else
 	apparmor='yes'
 fi
 
-# Checking repository availability
+# Check repository availability
 wget --quiet "https://$GPG/deb_signing.key" -O /dev/null
 check_result $? "Unable to connect to the Hestia APT repository"
 
@@ -519,7 +513,6 @@ clear
 install_welcome_message
 
 # Web stack
-
 echo '   - NGINX Web / Proxy Server'
 if [ "$apache" = 'yes' ]; then
 	echo '   - Apache Web Server (as backend)'
@@ -554,7 +547,7 @@ if [ "$exim" = 'yes' ]; then
 	fi
 	echo
 	if [ "$dovecot" = 'yes' ]; then
-		echo -n '   - Dovecot POP3/IMAP Server '
+		echo -n '   - Dovecot POP3/IMAP Server'
 		if [ "$sieve" = 'yes' ]; then
 			echo -n '+ Sieve'
 		fi
@@ -562,6 +555,7 @@ if [ "$exim" = 'yes' ]; then
 fi
 
 echo
+
 # Database stack
 if [ "$mysql" = 'yes' ]; then
 	echo '   - MariaDB Database Server'
@@ -695,7 +689,7 @@ fi
 # Define apt conf location
 apt=/etc/apt/sources.list.d
 
-#create new folder if not all-ready exists
+# Create new folder if not all-ready exists
 mkdir -p /root/.gnupg/ && chmod 700 /root/.gnupg/
 
 # Updating system
@@ -938,7 +932,6 @@ if [ "$phpfpm" = 'yes' ]; then
 	software=$(echo "$software" | sed -e "s/libapache2-mpm-itk//")
 	software=$(echo "$software" | sed -e "s/libapache2-mod-ruid2//")
 	software=$(echo "$software" | sed -e "s/libapache2-mod-php$fpm_v//")
-
 fi
 if [ -d "$withdebs" ]; then
 	software=$(echo "$software" | sed -e "s/hestia-nginx//")
@@ -1137,9 +1130,7 @@ if [ "$apache" = 'no' ]; then
 	write_config_value "WEB_SSL_PORT" "443"
 	write_config_value "WEB_SSL" "openssl"
 	write_config_value "STATS_SYSTEM" "awstats"
-
 fi
-
 if [ "$phpfpm" = 'yes' ]; then
 	write_config_value "WEB_BACKEND" "php-fpm"
 fi
@@ -1148,11 +1139,9 @@ fi
 if [ "$mysql" = 'yes' ] || [ "$mysqlclassic" = 'yes' ]; then
 	installed_db_types='mysql'
 fi
-
 if [ "$postgresql" = 'yes' ]; then
 	installed_db_types="$installed_db_types,pgsql"
 fi
-
 if [ -n "$installed_db_types" ]; then
 	db=$(echo "$installed_db_types" \
 		| sed "s/,/\n/g" \
@@ -1259,6 +1248,7 @@ cp -rf $HESTIA_COMMON_DIR/templates/web/skel/document_errors/* /var/www/document
 
 # Installing firewall rules
 cp -rf $HESTIA_COMMON_DIR/firewall $HESTIA/data/
+rm -f $HESTIA/data/firewall/ipset/blacklist.sh $HESTIA/data/firewall/ipset/blacklist.ipv6.sh
 
 # Installing apis
 cp -rf $HESTIA_COMMON_DIR/api $HESTIA/data/
@@ -1306,6 +1296,7 @@ $HESTIA/bin/v-add-sys-sftp-jail > /dev/null 2>&1
 check_result $? "can't enable sftp jail"
 
 # Adding Hestia admin account
+echo "[ * ] Create admin account..."
 $HESTIA/bin/v-add-user admin $vpass $email "system" "System Administrator"
 check_result $? "can't create admin user"
 $HESTIA/bin/v-change-user-shell admin nologin
@@ -1314,6 +1305,7 @@ $HESTIA/bin/v-change-user-language admin $lang
 $HESTIA/bin/v-change-sys-config-value 'POLICY_SYSTEM_PROTECTED_ADMIN' 'yes'
 
 locale-gen "en_US.utf8" > /dev/null 2>&1
+
 #----------------------------------------------------------#
 #                     Configure Nginx                      #
 #----------------------------------------------------------#
@@ -1388,6 +1380,7 @@ if [ "$apache" = 'yes' ]; then
 	a2dismod --quiet status > /dev/null 2>&1
 	a2enmod --quiet hestia-status > /dev/null 2>&1
 
+	# Enable mod_ruid/mpm_itk or mpm_event
 	if [ "$phpfpm" = 'yes' ]; then
 		# Disable prefork and php, enable event
 		a2dismod php$fpm_v > /dev/null 2>&1
@@ -1454,7 +1447,7 @@ if [ -z "$ZONE" ]; then
 	ZONE='UTC'
 fi
 for pconf in $(find /etc/php* -name php.ini); do
-	sed -i "s/;date.timezone =/date.timezone = $ZONE/g" $pconf
+	sed -i "s%;date.timezone =%date.timezone = $ZONE%g" $pconf
 	sed -i 's%_open_tag = Off%_open_tag = On%g' $pconf
 done
 
@@ -1478,9 +1471,8 @@ if [ "$vsftpd" = 'yes' ]; then
 	chown root:adm /var/log/xferlog
 	chmod 640 /var/log/xferlog
 	update-rc.d vsftpd defaults
-	systemctl start vsftpd
+	systemctl start vsftpd >> $LOG
 	check_result $? "vsftpd start failed"
-
 fi
 
 #----------------------------------------------------------#
@@ -1540,9 +1532,19 @@ if [ "$mysql" = 'yes' ] || [ "$mysqlclassic" = 'yes' ]; then
 		sed -i 's|mariadb.conf.d|mysql.conf.d|g' /etc/mysql/my.cnf
 	fi
 
-	update-rc.d mysql defaults > /dev/null 2>&1
-	systemctl start mysql >> $LOG
-	check_result $? "${mysql_type,,} start failed"
+	if [ "$mysql_type" = 'MariaDB' ]; then
+		update-rc.d mariadb defaults > /dev/null 2>&1
+		systemctl -q enable mariadb 2> /dev/null
+		systemctl start mariadb >> $LOG
+		check_result $? "${mysql_type,,} start failed"
+	fi
+
+	if [ "$mysql_type" = 'MySQL' ]; then
+		update-rc.d mysql defaults > /dev/null 2>&1
+		systemctl -q enable mysql 2> /dev/null
+		systemctl start mysql >> $LOG
+		check_result $? "${mysql_type,,} start failed"
+	fi
 
 	# Securing MariaDB/MySQL installation
 	mpass=$(gen_pass)
@@ -1644,16 +1646,16 @@ if [ "$postgresql" = 'yes' ]; then
 	ppass=$(gen_pass)
 	cp -f $HESTIA_INSTALL_DIR/postgresql/pg_hba.conf /etc/postgresql/*/main/
 	systemctl restart postgresql
-	sudo -iu postgres psql -c "ALTER USER postgres WITH PASSWORD '$ppass'"
+	sudo -iu postgres psql -c "ALTER USER postgres WITH PASSWORD '$ppass'" > /dev/null 2>&1
 
 	mkdir -p /etc/phppgadmin/
 	mkdir -p /usr/share/phppgadmin/
 
-	cp -f $HESTIA_INSTALL_DIR/pga/config.inc.php /etc/phppgadmin/
-
 	wget --retry-connrefused --quiet https://github.com/hestiacp/phppgadmin/releases/download/v$pga_v/phppgadmin-v$pga_v.tar.gz
 	tar xzf phppgadmin-v$pga_v.tar.gz -C /usr/share/phppgadmin/
 
+	cp -f $HESTIA_INSTALL_DIR/pga/config.inc.php /etc/phppgadmin/
+
 	ln -s /etc/phppgadmin/config.inc.php /usr/share/phppgadmin/conf/
 
 	# Configuring phpPgAdmin
@@ -1684,7 +1686,7 @@ if [ "$named" = 'yes' ]; then
 		echo "/home/** rwm," >> /etc/apparmor.d/local/usr.sbin.named 2> /dev/null
 		systemctl status apparmor > /dev/null 2>&1
 		if [ $? -ne 0 ]; then
-			systemctl restart apparmor
+			systemctl restart apparmor >> $LOG
 		fi
 	fi
 	update-rc.d bind9 defaults > /dev/null 2>&1
@@ -1734,7 +1736,7 @@ if [ "$exim" = 'yes' ]; then
 	update-rc.d -f postfix remove > /dev/null 2>&1
 	systemctl stop postfix > /dev/null 2>&1
 	update-rc.d exim4 defaults
-	systemctl start exim4
+	systemctl start exim4 >> $LOG
 	check_result $? "exim4 start failed"
 fi
 
@@ -1747,8 +1749,8 @@ if [ "$dovecot" = 'yes' ]; then
 	gpasswd -a dovecot mail > /dev/null 2>&1
 	cp -rf $HESTIA_COMMON_DIR/dovecot /etc/
 	cp -f $HESTIA_INSTALL_DIR/logrotate/dovecot /etc/logrotate.d/
-	chown -R root:root /etc/dovecot*
 	rm -f /etc/dovecot/conf.d/15-mailboxes.conf
+	chown -R root:root /etc/dovecot*
 
 	#Alter config for 2.2
 	version=$(dovecot --version | cut -f -2 -d .)
@@ -1760,7 +1762,7 @@ if [ "$dovecot" = 'yes' ]; then
 	fi
 
 	update-rc.d dovecot defaults
-	systemctl start dovecot
+	systemctl start dovecot >> $LOG
 	check_result $? "dovecot start failed"
 fi
 
@@ -1793,7 +1795,7 @@ if [ "$clamd" = 'yes' ]; then
 		sleep 0.5
 	done
 	echo
-	systemctl start clamav-daemon
+	systemctl start clamav-daemon >> $LOG
 	check_result $? "clamav-daemon start failed"
 fi
 
@@ -1832,7 +1834,7 @@ if [ "$fail2ban" = 'yes' ]; then
 		sed -i "${fline}s/true/false/" /etc/fail2ban/jail.local
 	fi
 	if [ "$vsftpd" = 'yes' ]; then
-		#Create vsftpd Log File
+		# Create vsftpd Log File
 		if [ ! -f "/var/log/vsftpd.log" ]; then
 			touch /var/log/vsftpd.log
 		fi
@@ -1849,8 +1851,9 @@ if [ "$fail2ban" = 'yes' ]; then
 	if [ -f /etc/fail2ban/jail.d/defaults-debian.conf ]; then
 		rm -f /etc/fail2ban/jail.d/defaults-debian.conf
 	fi
+
 	update-rc.d fail2ban defaults
-	systemctl start fail2ban
+	systemctl start fail2ban >> $LOG
 	check_result $? "fail2ban start failed"
 fi
 
@@ -1867,6 +1870,7 @@ fi
 #----------------------------------------------------------#
 #                       Install Roundcube                  #
 #----------------------------------------------------------#
+
 # Min requirements Dovecot + Exim + Mysql
 if ([ "$mysql" == 'yes' ] || [ "$mysqlclassic" == 'yes' ]) && [ "$dovecot" == "yes" ]; then
 	echo "[ * ] Install Roundcube..."
@@ -1880,6 +1884,7 @@ fi
 #----------------------------------------------------------#
 #                     Install Sieve                        #
 #----------------------------------------------------------#
+
 # Min requirements Dovecot + Exim + Mysql + Roundcube
 if [ "$sieve" = 'yes' ]; then
 	# Folder paths
@@ -1891,7 +1896,7 @@ if [ "$sieve" = 'yes' ]; then
 	# dovecot.conf install
 	sed -i "s/namespace/service stats \{\n  unix_listener stats-writer \{\n    group = mail\n    mode = 0660\n    user = dovecot\n  \}\n\}\n\nnamespace/g" /etc/dovecot/dovecot.conf
 
-	# dovecot conf files
+	# Dovecot conf files
 	#  10-master.conf
 	sed -i -E -z "s/  }\n  user = dovecot\n}/  \}\n  unix_listener auth-master \{\n    group = mail\n    mode = 0660\n    user = dovecot\n  \}\n  user = dovecot\n\}/g" /etc/dovecot/conf.d/10-master.conf
 	#  15-lda.conf
@@ -1899,14 +1904,15 @@ if [ "$sieve" = 'yes' ]; then
 	#  20-imap.conf
 	sed -i "s/mail_plugins = quota imap_quota/mail_plugins = quota imap_quota imap_sieve/g" /etc/dovecot/conf.d/20-imap.conf
 
-	# replace dovecot-sieve config files
+	# Replace dovecot-sieve config files
 	cp -f $HESTIA_COMMON_DIR/dovecot/sieve/* /etc/dovecot/conf.d
 
+	# Dovecot default file install
 	echo -e "require [\"fileinto\"];\n# rule:[SPAM]\nif header :contains \"X-Spam-Flag\" \"YES\" {\n    fileinto \"INBOX.Spam\";\n}\n" > /etc/dovecot/sieve/default
 
 	# exim4 install
 	sed -i "s/\stransport = local_delivery/ transport = dovecot_virtual_delivery/" /etc/exim4/exim4.conf.template
-	sed -i "s/address_pipe:/dovecot_virtual_delivery:\n  driver = pipe\n  command = \/usr\/lib\/dovecot\/dovecot-lda -e -d \$local_part@\$domain -f \$sender_address -a \$original_local_part@\$original_domain\n  delivery_date_add\n  envelope_to_add\n  return_path_add\n  log_output = true\n  log_defer_output = true\n  user = \${extract{2}{:}{\${lookup{\$local_part}lsearch{\/etc\/exim4\/domains\/\${lookup{\$domain}dsearch{\/etc\/exim4\/domains\/}}\/passwd}}}}\n group = mail\n  return_output\n\naddress_pipe:/g" /etc/exim4/exim4.conf.template
+	sed -i "s/address_pipe:/dovecot_virtual_delivery:\n  driver = pipe\n  command = \/usr\/lib\/dovecot\/dovecot-lda -e -d \$local_part@\$domain -f \$sender_address -a \$original_local_part@\$original_domain\n  delivery_date_add\n  envelope_to_add\n  return_path_add\n  log_output = true\n  log_defer_output = true\n  user = \${extract{2}{:}{\${lookup{\$local_part}lsearch{\/etc\/exim4\/domains\/\${lookup{\$domain}dsearch{\/etc\/exim4\/domains\/}}\/passwd}}}}\n  group = mail\n  return_output\n\naddress_pipe:/g" /etc/exim4/exim4.conf.template
 
 	# Permission changes
 	chown -R dovecot:mail /var/log/dovecot.log
@@ -1923,18 +1929,18 @@ if [ "$sieve" = 'yes' ]; then
 		chmod 644 $RC_CONFIG_DIR/plugins/managesieve/config.inc.php
 		sed -i "s/'archive'/'archive', 'managesieve'/g" $RC_CONFIG_DIR/config.inc.php
 	fi
+
 	# Restart Dovecot and exim4
 	systemctl restart dovecot > /dev/null 2>&1
 	systemctl restart exim4 > /dev/null 2>&1
 fi
 
 #----------------------------------------------------------#
-#                   Comfigure API                         #
+#                       Configure API                      #
 #----------------------------------------------------------#
 
-# Configuring system IPs
 if [ "$api" = "yes" ]; then
-	# keep legacy api enabled until transition is complete
+	# Keep legacy api enabled until transition is complete
 	write_config_value "API" "yes"
 	write_config_value "API_SYSTEM" "1"
 	write_config_value "API_ALLOWED_IP" ""
@@ -1981,7 +1987,6 @@ fi
 
 # Get public IP
 pub_ip=$(curl --ipv4 -s https://ip.hestiacp.com/)
-
 if [ -n "$pub_ip" ] && [ "$pub_ip" != "$ip" ]; then
 	$HESTIA/bin/v-change-sys-ip-nat $ip $pub_ip > /dev/null 2>&1
 	ip=$pub_ip
@@ -2072,7 +2077,7 @@ chown admin:admin $HESTIA/data/sessions
 mkdir -p /backup/
 chmod 755 /backup/
 
-# create cronjob to generate ssl
+# Create cronjob to generate ssl
 echo "@reboot root sleep 10 && rm /etc/cron.d/hestia-ssl && PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:' && /usr/local/hestia/bin/v-add-letsencrypt-host" > /etc/cron.d/hestia-ssl
 
 #----------------------------------------------------------#
@@ -2090,7 +2095,7 @@ write_config_value "POLICY_USER_DELETE_LOGS" "yes"
 write_config_value "POLICY_USER_CHANGE_THEME" "yes"
 write_config_value "POLICY_SYSTEM_PROTECTED_ADMIN" "no"
 write_config_value "POLICY_SYSTEM_PASSWORD_RESET" "yes"
-write_config_value "POLICY_SYSTEM_HIDE_SERVICES" "yes"
+write_config_value "POLICY_SYSTEM_HIDE_SERVICES" "no"
 write_config_value "POLICY_SYSTEM_ENABLE_BACON" "no"
 write_config_value "PLUGIN_APP_INSTALLER" "true"
 write_config_value "DEBUG_MODE" "no"
@@ -2104,6 +2109,7 @@ write_config_value "SERVER_SMTP_PASSWD" ""
 write_config_value "SERVER_SMTP_ADDR" ""
 write_config_value "POLICY_CSRF_STRICTNESS" "1"
 write_config_value "DISABLE_IP_CHECK" "no"
+write_config_value "DNS_CLUSTER_SYSTEM" "hestia"
 
 # Add /usr/local/hestia/bin/ to path variable
 echo 'if [ "${PATH#*/usr/local/hestia/bin*}" = "$PATH" ]; then
@@ -2131,9 +2137,9 @@ You have successfully installed Hestia Control Panel on your server.
 
 Ready to get started? Log in using the following credentials:
 
-	Admin URL:  https://$servername:$port"
+	Admin URL:  https://$servername:$port" > $tmpfile
 if [ "$host_ip" != "$ip" ]; then
-	echo -n "	Backup URL: https://$ip:$port"
+	echo "	Backup URL: https://$ip:$port" >> $tmpfile
 fi
 echo -e -n " 	Username:   admin
 	Password:   $displaypass
@@ -2160,7 +2166,7 @@ Sincerely yours,
 The Hestia Control Panel development team
 
 Made with love & pride by the open-source community around the world.
-" > $tmpfile
+" >> $tmpfile
 
 send_mail="$HESTIA/web/inc/mail-wrapper.php"
 cat $tmpfile | $send_mail -s "Hestia Control Panel" $email

+ 46 - 42
install/hst-install-ubuntu.sh

@@ -32,29 +32,24 @@ HESTIA_COMMON_DIR="$HESTIA/install/common"
 VERBOSE='no'
 
 # Define software versions
-HESTIA_INSTALL_VER='1.7.0'
+HESTIA_INSTALL_VER='1.7.1'
 # Dependencies
 multiphp_v=("5.6" "7.0" "7.1" "7.2" "7.3" "7.4" "8.0" "8.1" "8.2")
 fpm_v="8.1"
 mariadb_v="10.11"
 
 # Defining software pack for all distros
-software="apache2 apache2.2-common apache2-suexec-custom apache2-utils
-    apparmor-utils awstats bc bind9 bsdmainutils bsdutils clamav-daemon
-    cron curl dnsutils dovecot-imapd dovecot-pop3d dovecot-sieve dovecot-managesieved
-    e2fslibs e2fsprogs exim4 exim4-daemon-heavy expect fail2ban flex ftp git idn2
-    imagemagick libapache2-mod-fcgid libapache2-mod-php$fpm_v libapache2-mod-rpaf
-    lsof mc mariadb-client mariadb-common mariadb-server mysql-client mysql-common mysql-server nginx
-    php$fpm_v php$fpm_v-cgi php$fpm_v-common php$fpm_v-curl
-    php$fpm_v-mysql php$fpm_v-imap php$fpm_v-ldap php$fpm_v-apcu
-    php$fpm_v-pgsql php$fpm_v-zip php$fpm_v-bz2 php$fpm_v-cli php$fpm_v-gd
-    php$fpm_v-imagick php$fpm_v-intl php$fpm_v-mbstring
-    php$fpm_v-opcache php$fpm_v-pspell php$fpm_v-readline php$fpm_v-xml
-    postgresql postgresql-contrib proftpd-basic quota rrdtool spamassassin sudo hestia=${HESTIA_INSTALL_VER}
-    hestia-nginx hestia-php vim-common vsftpd whois unzip zip acl sysstat setpriv rsyslog
-    ipset libonig5 libzip4 openssh-server lsb-release zstd jq"
-
-installer_dependencies="apt-transport-https curl dirmngr gnupg wget software-properties-common ca-certificates"
+software="acl apache2 apache2.2-common apache2-suexec-custom apache2-utils apparmor-utils awstats bc bind9 bsdmainutils bsdutils
+  clamav-daemon cron curl dnsutils dovecot-imapd dovecot-managesieved dovecot-pop3d dovecot-sieve e2fslibs e2fsprogs
+  exim4 exim4-daemon-heavy expect fail2ban flex ftp git hestia=${HESTIA_INSTALL_VER} hestia-nginx hestia-php idn2
+  imagemagick ipset jq libapache2-mod-fcgid libapache2-mod-php$fpm_v libapache2-mod-rpaf libonig5 libzip4 lsb-release
+  lsof mariadb-client mariadb-common mariadb-server mc mysql-client mysql-common mysql-server nginx openssh-server
+  php$fpm_v php$fpm_v-apcu php$fpm_v-bz2 php$fpm_v-cgi php$fpm_v-cli php$fpm_v-common php$fpm_v-curl php$fpm_v-gd
+  php$fpm_v-imagick php$fpm_v-imap php$fpm_v-intl php$fpm_v-ldap php$fpm_v-mbstring php$fpm_v-mysql php$fpm_v-opcache
+  php$fpm_v-pgsql php$fpm_v-pspell php$fpm_v-readline php$fpm_v-xml php$fpm_v-zip postgresql postgresql-contrib
+  proftpd-basic quota rrdtool rsyslog setpriv spamassassin sudo sysstat unzip vim-common vsftpd whois zip zstd"
+
+installer_dependencies="apt-transport-https ca-certificates curl dirmngr gnupg software-properties-common wget"
 
 # Defining help function
 help() {
@@ -311,7 +306,6 @@ if [ "$exim" = 'no' ]; then
 	clamd='no'
 	spamd='no'
 	dovecot='no'
-	sieve='no'
 fi
 if [ "$dovecot" = 'no' ]; then
 	sieve='no'
@@ -319,7 +313,7 @@ fi
 if [ "$iptables" = 'no' ]; then
 	fail2ban='no'
 fi
-if [ "$apache" = "no" ]; then
+if [ "$apache" = 'no' ]; then
 	phpfpm='yes'
 fi
 if [ "$mysql" = 'yes' ] && [ "$mysqlclassic" = 'yes' ]; then
@@ -474,6 +468,7 @@ case $architecture in
 		check_result 1 "Installation aborted"
 		;;
 esac
+
 #----------------------------------------------------------#
 #                       Brief Info                         #
 #----------------------------------------------------------#
@@ -553,6 +548,7 @@ if [ "$exim" = 'yes' ]; then
 fi
 
 echo
+
 # Database stack
 if [ "$mysql" = 'yes' ]; then
 	echo '   - MariaDB Database Server'
@@ -699,8 +695,8 @@ echo "[ * ] NGINX"
 echo "deb [arch=$ARCH signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://nginx.org/packages/mainline/$VERSION/ $codename nginx" > $apt/nginx.list
 curl -s https://nginx.org/keys/nginx_signing.key | gpg --dearmor | tee /usr/share/keyrings/nginx-keyring.gpg > /dev/null 2>&1
 
-#add-apt-repository  does not support it yet see #https://bugs.launchpad.net/ubuntu/+source/software-properties/+bug/1862764
 # Installing sury PHP repo
+# add-apt-repository does not yet support signed-by see: https://bugs.launchpad.net/ubuntu/+source/software-properties/+bug/1862764
 echo "[ * ] PHP"
 LC_ALL=C.UTF-8 add-apt-repository -y ppa:ondrej/php > /dev/null 2>&1
 
@@ -1044,7 +1040,7 @@ if [ -z "$(grep 'LS_COLORS="$LS_COLORS:di=00;33"' /etc/profile)" ]; then
 	echo 'LS_COLORS="$LS_COLORS:di=00;33"' >> /etc/profile
 fi
 
-# Registering /usr/sbin/nologin
+# Register /usr/sbin/nologin
 if [ -z "$(grep nologin /etc/shells)" ]; then
 	echo "/usr/sbin/nologin" >> /etc/shells
 fi
@@ -1168,7 +1164,6 @@ if [ "$apache" = 'yes' ]; then
 	write_config_value "PROXY_SSL_PORT" "443"
 	write_config_value "STATS_SYSTEM" "awstats"
 fi
-
 if [ "$apache" = 'no' ]; then
 	write_config_value "WEB_SYSTEM" "nginx"
 	write_config_value "WEB_PORT" "80"
@@ -1176,7 +1171,6 @@ if [ "$apache" = 'no' ]; then
 	write_config_value "WEB_SSL" "openssl"
 	write_config_value "STATS_SYSTEM" "awstats"
 fi
-
 if [ "$phpfpm" = 'yes' ] || [ "$multiphp" = 'yes' ]; then
 	write_config_value "WEB_BACKEND" "php-fpm"
 fi
@@ -1185,11 +1179,9 @@ fi
 if [ "$mysql" = 'yes' ] || [ "$mysqlclassic" = 'yes' ]; then
 	installed_db_types='mysql'
 fi
-
 if [ "$postgresql" = 'yes' ]; then
 	installed_db_types="$installed_db_types,pgsql"
 fi
-
 if [ -n "$installed_db_types" ]; then
 	db=$(echo "$installed_db_types" \
 		| sed "s/,/\n/g" \
@@ -1296,6 +1288,7 @@ cp -rf $HESTIA_COMMON_DIR/templates/web/skel/document_errors/* /var/www/document
 
 # Installing firewall rules
 cp -rf $HESTIA_COMMON_DIR/firewall $HESTIA/data/
+rm -f $HESTIA/data/firewall/ipset/blacklist.sh $HESTIA/data/firewall/ipset/blacklist.ipv6.sh
 
 # Installing apis
 cp -rf $HESTIA_COMMON_DIR/api $HESTIA/data/
@@ -1341,6 +1334,7 @@ fi
 if [ -n "$(grep ^admin: /etc/group)" ] && [ "$force" = 'yes' ]; then
 	groupdel admin > /dev/null 2>&1
 fi
+
 # Remove sudo "default" sudo permission admin user group should not exists any way
 sed -i "s/%admin ALL=(ALL) ALL/#%admin ALL=(ALL) ALL/g" /etc/sudoers
 
@@ -1538,12 +1532,15 @@ if [ "$proftpd" = 'yes' ]; then
 	echo "127.0.0.1 $servername" >> /etc/hosts
 	cp -f $HESTIA_INSTALL_DIR/proftpd/proftpd.conf /etc/proftpd/
 	cp -f $HESTIA_INSTALL_DIR/proftpd/tls.conf /etc/proftpd/
+
 	if [ "$release" = '22.04' ]; then
 		sed -i 's|IdentLookups                  off|#IdentLookups                  off|g' /etc/proftpd/proftpd.conf
 	fi
+
 	update-rc.d proftpd defaults > /dev/null 2>&1
 	systemctl start proftpd >> $LOG
 	check_result $? "proftpd start failed"
+
 	if [ "$release" = '22.04' ]; then
 		unit_files="$(systemctl list-unit-files | grep proftpd)"
 		if [[ "$unit_files" =~ "disabled" ]]; then
@@ -1583,9 +1580,19 @@ if [ "$mysql" = 'yes' ] || [ "$mysqlclassic" = 'yes' ]; then
 		sed -i 's|mariadb.conf.d|mysql.conf.d|g' /etc/mysql/my.cnf
 	fi
 
-	update-rc.d mysql defaults > /dev/null 2>&1
-	systemctl start mysql >> $LOG
-	check_result $? "${mysql_type,,} start failed"
+	if [ "$mysql_type" = 'MariaDB' ]; then
+		update-rc.d mariadb defaults > /dev/null 2>&1
+		systemctl -q enable mariadb 2> /dev/null
+		systemctl start mariadb >> $LOG
+		check_result $? "${mysql_type,,} start failed"
+	fi
+
+	if [ "$mysql_type" = 'MySQL' ]; then
+		update-rc.d mysql defaults > /dev/null 2>&1
+		systemctl -q enable mysql 2> /dev/null
+		systemctl start mysql >> $LOG
+		check_result $? "${mysql_type,,} start failed"
+	fi
 
 	# Securing MariaDB/MySQL installation
 	mpass=$(gen_pass)
@@ -1624,7 +1631,7 @@ if [ "$mysql" = 'yes' ] || [ "$mysqlclassic" = 'yes' ]; then
 	echo "[ * ] Installing phpMyAdmin version v$pma_v..."
 
 	# Download latest phpmyadmin release
-	wget --retry-connrefused --quiet https://files.phpmyadmin.net/phpMyAdmin/$pma_v/phpMyAdmin-$pma_v-all-languages.tar.gz
+	wget --quiet --retry-connrefused https://files.phpmyadmin.net/phpMyAdmin/$pma_v/phpMyAdmin-$pma_v-all-languages.tar.gz
 
 	# Unpack files
 	tar xzf phpMyAdmin-$pma_v-all-languages.tar.gz
@@ -1655,6 +1662,7 @@ if [ "$mysql" = 'yes' ] || [ "$mysqlclassic" = 'yes' ]; then
 	# Create temporary folder and change permission
 	chmod 770 /usr/share/phpmyadmin/tmp
 	chown root:www-data /usr/share/phpmyadmin/tmp
+
 	# Generate blow fish
 	blowfish=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 32)
 	sed -i "s|%blowfish_secret%|$blowfish|" /etc/phpmyadmin/config.inc.php
@@ -1731,7 +1739,6 @@ if [ "$named" = 'yes' ]; then
 	fi
 	update-rc.d bind9 defaults > /dev/null 2>&1
 	systemctl start bind9
-
 	check_result $? "bind9 start failed"
 
 	# Workaround for OpenVZ/Virtuozzo
@@ -1776,7 +1783,6 @@ if [ "$exim" = 'yes' ]; then
 	systemctl stop sendmail > /dev/null 2>&1
 	update-rc.d -f postfix remove > /dev/null 2>&1
 	systemctl stop postfix > /dev/null 2>&1
-
 	update-rc.d exim4 defaults
 	systemctl start exim4 >> $LOG
 	check_result $? "exim4 start failed"
@@ -1792,7 +1798,6 @@ if [ "$dovecot" = 'yes' ]; then
 	cp -rf $HESTIA_COMMON_DIR/dovecot /etc/
 	cp -f $HESTIA_INSTALL_DIR/logrotate/dovecot /etc/logrotate.d/
 	rm -f /etc/dovecot/conf.d/15-mailboxes.conf
-
 	chown -R root:root /etc/dovecot*
 
 	#Alter config for 2.2
@@ -1845,7 +1850,6 @@ if [ "$spamd" = 'yes' ]; then
 	if [[ "$unit_files" =~ "disabled" ]]; then
 		systemctl enable spamassassin > /dev/null 2>&1
 	fi
-
 	sed -i "s/#CRON=1/CRON=1/" /etc/default/spamassassin
 fi
 
@@ -1867,7 +1871,7 @@ if [ "$fail2ban" = 'yes' ]; then
 		sed -i "${fline}s/true/false/" /etc/fail2ban/jail.local
 	fi
 	if [ "$vsftpd" = 'yes' ]; then
-		#Create vsftpd Log File
+		# Create vsftpd Log File
 		if [ ! -f "/var/log/vsftpd.log" ]; then
 			touch /var/log/vsftpd.log
 		fi
@@ -1882,7 +1886,6 @@ if [ "$fail2ban" = 'yes' ]; then
 	update-rc.d fail2ban defaults
 	# Ubuntu 22.04 doesn't start F2B by default on boot
 	update-rc.d fail2ban enable
-
 	systemctl start fail2ban >> $LOG
 	check_result $? "fail2ban start failed"
 fi
@@ -1900,6 +1903,7 @@ fi
 #----------------------------------------------------------#
 #                       Install Roundcube                  #
 #----------------------------------------------------------#
+
 # Min requirements Dovecot + Exim + Mysql
 if ([ "$mysql" == 'yes' ] || [ "$mysqlclassic" == 'yes' ]) && [ "$dovecot" == "yes" ]; then
 	echo "[ * ] Install Roundcube..."
@@ -1925,7 +1929,7 @@ if [ "$sieve" = 'yes' ]; then
 	# dovecot.conf install
 	sed -i "s/namespace/service stats \{\n  unix_listener stats-writer \{\n    group = mail\n    mode = 0660\n    user = dovecot\n  \}\n\}\n\nnamespace/g" /etc/dovecot/dovecot.conf
 
-	# dovecot conf files
+	# Dovecot conf files
 	#  10-master.conf
 	sed -i -E -z "s/  }\n  user = dovecot\n}/  \}\n  unix_listener auth-master \{\n    group = mail\n    mode = 0660\n    user = dovecot\n  \}\n  user = dovecot\n\}/g" /etc/dovecot/conf.d/10-master.conf
 	#  15-lda.conf
@@ -1933,7 +1937,7 @@ if [ "$sieve" = 'yes' ]; then
 	#  20-imap.conf
 	sed -i "s/mail_plugins = quota imap_quota/mail_plugins = quota imap_quota imap_sieve/g" /etc/dovecot/conf.d/20-imap.conf
 
-	# replace dovecot-sieve config files
+	# Replace dovecot-sieve config files
 	cp -f $HESTIA_COMMON_DIR/dovecot/sieve/* /etc/dovecot/conf.d
 
 	# Dovecot default file install
@@ -1959,8 +1963,6 @@ if [ "$sieve" = 'yes' ]; then
 		sed -i "s/'archive'/'archive', 'managesieve'/g" $RC_CONFIG_DIR/config.inc.php
 	fi
 
-	sed -i "s/'archive'/'archive', 'managesieve'/g" $RC_CONFIG_DIR/config.inc.php
-
 	# Restart Dovecot and exim4
 	systemctl restart dovecot > /dev/null 2>&1
 	systemctl restart exim4 > /dev/null 2>&1
@@ -1971,7 +1973,7 @@ fi
 #----------------------------------------------------------#
 
 if [ "$api" = "yes" ]; then
-	# keep legacy api enabled until transition is complete
+	# Keep legacy api enabled until transition is complete
 	write_config_value "API" "yes"
 	write_config_value "API_SYSTEM" "1"
 	write_config_value "API_ALLOWED_IP" ""
@@ -2003,8 +2005,8 @@ curl -s https://rclone.org/install.sh | bash > /dev/null 2>&1
 #                   Configure IP                           #
 #----------------------------------------------------------#
 
-echo "[ * ] Configuring System IP..."
 # Configuring system IPs
+echo "[ * ] Configuring System IP..."
 $HESTIA/bin/v-update-sys-ip > /dev/null 2>&1
 
 # Get main IP
@@ -2123,7 +2125,7 @@ chown admin:admin $HESTIA/data/sessions
 mkdir -p /backup/
 chmod 755 /backup/
 
-# create cronjob to generate ssl
+# Create cronjob to generate ssl
 echo "@reboot root sleep 10 && rm /etc/cron.d/hestia-ssl && PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:' && /usr/local/hestia/bin/v-add-letsencrypt-host" > /etc/cron.d/hestia-ssl
 
 #----------------------------------------------------------#
@@ -2155,6 +2157,7 @@ write_config_value "SERVER_SMTP_PASSWD" ""
 write_config_value "SERVER_SMTP_ADDR" ""
 write_config_value "POLICY_CSRF_STRICTNESS" "1"
 write_config_value "DISABLE_IP_CHECK" "no"
+write_config_value "DNS_CLUSTER_SYSTEM" "hestia"
 
 # Add /usr/local/hestia/bin/ to path variable
 echo 'if [ "${PATH#*/usr/local/hestia/bin*}" = "$PATH" ]; then
@@ -2165,6 +2168,7 @@ fi' >> /root/.bashrc
 #                   Hestia Access Info                     #
 #----------------------------------------------------------#
 
+# Comparing hostname and IP
 host_ip=$(host $servername | head -n 1 | awk '{print $NF}')
 if [ "$host_ip" = "$ip" ]; then
 	ip="$servername"

+ 2 - 2
install/hst-install.sh

@@ -8,7 +8,7 @@
 #
 # Currently Supported Operating Systems:
 #
-# Debian 9, 10, 11
+# Debian 10, 11
 # Ubuntu 20.04, 22.04
 # AlmaLinux, EuroLinux, Red Hat EnterPrise Linux, Rocky Linux 8, 9
 #
@@ -82,7 +82,7 @@ no_support_message() {
 	echo "Hestia Control Panel. Officially supported releases:"
 	echo "****************************************************"
 	echo "  Debian 10, 11"
-	echo "  Ubuntu 18.04, 20.04, 22.04 LTS"
+	echo "  Ubuntu 20.04, 22.04 LTS"
 	# Commenting this out for now
 	# echo "  AlmaLinux, EuroLinux, Red Hat EnterPrise Linux, Rocky Linux 8,9"
 	echo ""

+ 1 - 0
install/rpm/httpd/httpd.conf

@@ -70,6 +70,7 @@ LogFormat "%{User-agent}i" agent
 LogFormat "%b" bytes
 
 Include conf.d/*.conf
+IncludeOptional conf.d/domains/webmail.*.conf
 IncludeOptional conf.d/domains/*.conf
 
 ErrorDocument 403 /error/403.html

+ 40 - 28
install/upgrade/manual/upgrade_mariadb.sh

@@ -1,57 +1,69 @@
 #!/bin/bash
 
-# This script validates and upgrades the MariaDB version to 10.5
+# This script validates and upgrades the MariaDB version
 
 #----------------------------------------------------------#
-#                    Variable&Function                     #
+#                   Variable & Function                    #
 #----------------------------------------------------------#
 
 # Set MariaDB Target Version
 mariadb_v='10.11'
 
-# Load OS informations
-source /etc/os-release
-
 #----------------------------------------------------------#
-#                    Verifications                         #
+#                      Verifications                       #
 #----------------------------------------------------------#
 
-# Detect installed mariadb version
-IFS=' ' read -r -a mysql_v <<< $(mysqld -V)
-mysql_v=$(echo "${mysql_v[2]}" | cut -c1-4)
+# Detect installed MariaDB version
+mysql_v="$(mysqld -V | awk '{print $3}' | cut -d: -f1)"
 
-if [ "$mysql_v" = "$mariadb_v" ]; then
-	echo "Version is already up to date, cancelling."
+if [ "${mysql_v%.*}" = "$mariadb_v" ]; then
+	echo "[ ! ] MariaDB version ($mariadb_v) is already up to date."
 	exit 0
+else
+	echo "[ * ] Upgrading MariaDB version to ($mariadb_v)..."
 fi
 
-#Get OS details
-os=$(grep "^ID=" /etc/os-release | cut -f 2 -d '=')
+# Get OS details
+os="$(grep "^ID=" /etc/os-release | cut -d= -f2)"
 codename="$(lsb_release -s -c)"
-release="$(lsb_release -s -r)"
-RHOST='apt.hestiacp.com'
+
+case $(arch) in
+	x86_64)
+		arch="amd64"
+		;;
+	aarch64)
+		arch="arm64"
+		;;
+	*)
+		echo "[ ! ] Error: $(arch) is currently not supported!"
+		exit 1
+		;;
+esac
 
 #----------------------------------------------------------#
-#                       Action                             #
+#                         Action                           #
 #----------------------------------------------------------#
 
-# Installing MariaDB repo
-apt="/etc/apt/sources.list.d/"
-echo "[ * ] MariaDB"
-echo "deb [arch=$ARCH signed-by=/usr/share/keyrings/mariadb-keyring.gpg] https://dlm.mariadb.com/repo/mariadb-server/$mariadb_v/repo/$VERSION $codename main" > $apt/mariadb.list
+# Installing MariaDB repository
+apt="/etc/apt/sources.list.d"
+echo "[ * ] Installing MariaDB repository..."
+echo "deb [arch=$arch signed-by=/usr/share/keyrings/mariadb-keyring.gpg] https://dlm.mariadb.com/repo/mariadb-server/$mariadb_v/repo/$os $codename main" > $apt/mariadb.list
 curl -s https://mariadb.org/mariadb_release_signing_key.asc | gpg --dearmor | tee /usr/share/keyrings/mariadb-keyring.gpg > /dev/null 2>&1
 
 # Update repository
-echo "Update apt repository..."
+echo "[ * ] Update apt repository..."
 apt update -qq > /dev/null 2>&1
 
-# Stop and uninstall mysql server
-echo "Stop and remove old MariaDB server..."
-systemctl stop mysql > /dev/null 2>&1
+# Stop and uninstall old version
+echo "[ * ] Stop and remove old MariaDB Server (${mysql_v%.*})..."
+systemctl -q stop mariadb mysql 2> /dev/null
 apt remove -qq mariadb-server -y > /dev/null 2>&1
 
-# Install new version and run upgrader
-echo "Installing new MariaDB Server, start and run upgrade..."
+# Install new version and run upgrade
+echo "[ * ] Installing new MariaDB Server, start and run upgrade..."
 apt install -qq mariadb-server -y
-systemctl start mysql > /dev/null 2>&1
-mysql_upgrade
+update-rc.d mariadb defaults > /dev/null 2>&1
+systemctl -q daemon-reload
+systemctl -q enable mariadb
+systemctl -q start mariadb
+mariadb-upgrade

+ 0 - 27
install/upgrade/versions/1.6.15.sh

@@ -1,27 +0,0 @@
-#!/bin/bash
-
-# Hestia Control Panel upgrade script for target version 1.6.15
-
-#######################################################################################
-#######                      Place additional commands below.                   #######
-#######################################################################################
-####### Pass through information to the end user in case of a issue or problem  #######
-#######                                                                         #######
-####### Use add_upgrade_message "My message here" to include a message          #######
-####### in the upgrade notification email. Example:                             #######
-#######                                                                         #######
-####### add_upgrade_message "My message here"                                   #######
-#######                                                                         #######
-####### You can use \n within the string to create new lines.                   #######
-#######################################################################################
-
-upgrade_config_set_value 'UPGRADE_UPDATE_WEB_TEMPLATES' 'no'
-upgrade_config_set_value 'UPGRADE_UPDATE_DNS_TEMPLATES' 'no'
-upgrade_config_set_value 'UPGRADE_UPDATE_MAIL_TEMPLATES' 'no'
-upgrade_config_set_value 'UPGRADE_REBUILD_USERS' 'no'
-upgrade_config_set_value 'UPGRADE_UPDATE_FILEMANAGER_CONFIG' 'false'
-
-grep 'v-change-user-password' $HESTIA/data/api/billing
-if [ $? -ne 0 ]; then
-	sed -i "s/v-make-tmp-file'/v-make-tmp-file,v-change-user-password'/g" $HESTIA/data/api/billing
-fi

+ 1 - 1
install/upgrade/versions/1.7.0.sh

@@ -1,6 +1,6 @@
 #!/bin/bash
 
-# Hestia Control Panel upgrade script for target version unreleased
+# Hestia Control Panel upgrade script for target version 1.7.0
 
 #######################################################################################
 #######                      Place additional commands below.                   #######

+ 46 - 0
install/upgrade/versions/1.7.1.sh

@@ -0,0 +1,46 @@
+#!/bin/bash
+
+# Hestia Control Panel upgrade script for target version 1.7.1
+
+#######################################################################################
+#######                      Place additional commands below.                   #######
+#######################################################################################
+####### upgrade_config_set_value only accepts true or false.                    #######
+#######                                                                         #######
+####### Pass through information to the end user in case of a issue or problem  #######
+#######                                                                         #######
+####### Use add_upgrade_message "My message here" to include a message          #######
+####### in the upgrade notification email. Example:                             #######
+#######                                                                         #######
+####### add_upgrade_message "My message here"                                   #######
+#######                                                                         #######
+####### You can use \n within the string to create new lines.                   #######
+#######################################################################################
+
+upgrade_config_set_value 'UPGRADE_UPDATE_WEB_TEMPLATES' 'true'
+upgrade_config_set_value 'UPGRADE_UPDATE_DNS_TEMPLATES' 'false'
+upgrade_config_set_value 'UPGRADE_UPDATE_MAIL_TEMPLATES' 'false'
+upgrade_config_set_value 'UPGRADE_REBUILD_USERS' 'true'
+upgrade_config_set_value 'UPGRADE_UPDATE_FILEMANAGER_CONFIG' 'false'
+
+# Moved from 1.6.15.sh
+if ! (grep -q 'v-change-user-password' $HESTIA/data/api/billing); then
+	sed -i "s|v-make-tmp-file'|v-make-tmp-file,v-change-user-password'|g" $HESTIA/data/api/billing
+fi
+
+# Apply update for path change of built-in IPset blacklist.sh
+if [ "$FIREWALL_SYSTEM" = "iptables" ]; then
+	rm -f $HESTIA/data/firewall/ipset/blacklist.sh
+
+	if ($BIN/v-list-firewall-ipset plain | grep -q '/install/deb/firewall/ipset/blacklist.sh'); then
+		echo "[ * ] Update the path of IPset blacklist.sh..."
+		sed -i 's|/install/deb/firewall/ipset/blacklist.sh|/install/common/firewall/ipset/blacklist.sh|g' $HESTIA/data/firewall/ipset.conf
+	fi
+fi
+
+if [ "$WEB_SYSTEM" = "apache2" ]; then
+	if ! (grep -q "$WEBMAIL_ALIAS.*.conf" /etc/apache2/apache2.conf); then
+		echo "[ * ] Update /etc/apache2/apache2.conf..."
+		sed -i "s/IncludeOptional conf.d\/domains\/\*.conf/IncludeOptional conf.d\/domains\/$WEBMAIL_ALIAS.*.conf\nIncludeOptional conf.d\/domains\/\*.conf/g" /etc/apache2/apache2.conf
+	fi
+fi

+ 13 - 13
package.json

@@ -1,7 +1,7 @@
 {
 	"name": "hestia",
 	"private": true,
-	"version": "1.7.0",
+	"version": "1.7.1",
 	"description": "An open-source Linux web server control panel.",
 	"repository": "https://github.com/hestiacp/hestiacp",
 	"license": "GPL-3.0-or-later",
@@ -22,15 +22,15 @@
 		"normalize.css": "^8.0.1"
 	},
 	"devDependencies": {
-		"@prettier/plugin-php": "^0.19.3",
-		"@typescript-eslint/eslint-plugin": "^5.54.1",
-		"@typescript-eslint/parser": "^5.54.1",
+		"@prettier/plugin-php": "^0.19.4",
+		"@typescript-eslint/eslint-plugin": "^5.56.0",
+		"@typescript-eslint/parser": "^5.56.0",
 		"cssnano": "^5.1.15",
-		"eslint": "^8.35.0",
-		"eslint-config-prettier": "^8.7.0",
+		"eslint": "^8.36.0",
+		"eslint-config-prettier": "^8.8.0",
 		"eslint-plugin-editorconfig": "^4.0.2",
 		"husky": "^8.0.3",
-		"lint-staged": "^13.1.2",
+		"lint-staged": "^13.2.0",
 		"markdownlint-cli2": "^0.6.0",
 		"postcss": "^8.4.21",
 		"postcss-cli": "^10.1.0",
@@ -38,14 +38,14 @@
 		"postcss-path-replace": "^1.0.4",
 		"postcss-preset-env": "^8.0.1",
 		"postcss-size": "^4.0.1",
-		"prettier": "^2.8.4",
-		"prettier-plugin-nginx": "^1.0.2",
+		"prettier": "^2.8.6",
+		"prettier-plugin-nginx": "^1.0.3",
 		"prettier-plugin-sh": "^0.12.8",
 		"prettier-plugin-sql": "^0.13.0",
-		"stylelint": "^15.2.0",
-		"stylelint-config-standard": "^30.0.1",
-		"typescript": "^4.9.5",
-		"vitepress": "1.0.0-alpha.50",
+		"stylelint": "^15.3.0",
+		"stylelint-config-standard": "^31.0.0",
+		"typescript": "^5.0.2",
+		"vitepress": "1.0.0-alpha.61",
 		"vue": "^3.2.47"
 	}
 }

+ 1 - 1
src/deb/hestia/control

@@ -1,7 +1,7 @@
 Source: hestia
 Package: hestia
 Priority: optional
-Version: 1.7.0
+Version: 1.7.1
 Section: admin
 Maintainer: HestiaCP <info@hestiacp.com>
 Homepage: https://www.hestiacp.com

+ 4 - 0
web/css/src/themes/default.css

@@ -568,6 +568,10 @@
 		&.active {
 			box-shadow: 0 4px 6px rgb(0 0 0 / 10%);
 		}
+
+		& .form-select {
+			max-width: 200px;
+		}
 	}
 }
 

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
web/css/themes/default.min.css


+ 5 - 1
web/delete/log/index.php

@@ -22,7 +22,11 @@ if ($return_var > 0) {
 } else {
 	// Set correct page reload target
 	if ($_SESSION["userContext"] === "admin" && !empty($_GET["user"])) {
-		header("Location: /list/log/?user=$user&token=$token");
+		if ($_GET["user"] != "system") {
+			header("Location: /list/log/?user=$user&token=$token");
+		} else {
+			header("Location: /list/log/?user=system&token=$token");
+		}
 	} else {
 		header("Location: /list/log/");
 	}

+ 5 - 7
web/edit/web/index.php

@@ -69,8 +69,8 @@ $v_letsencrypt = $data[$v_domain]["LETSENCRYPT"];
 if (empty($v_letsencrypt)) {
 	$v_letsencrypt = "no";
 }
-$v_ssl_home = $data[$v_domain]["SSL_HOME"];
-$v_backend_template = $data[$v_domain]["BACKEND"];
+$v_ssl_home = $data[$v_domain]["SSL_HOME"] ?? "";
+$v_backend_template = $data[$v_domain]["BACKEND"] ?? "";
 $v_nginx_cache = $data[$v_domain]["FASTCGI_CACHE"] ?? "";
 $v_nginx_cache_duration = $data[$v_domain]["FASTCGI_DURATION"] ?? "";
 $v_nginx_cache_check = "";
@@ -848,10 +848,7 @@ if (!empty($_POST["save"])) {
 		if (empty($_POST["v_ssl_key"])) {
 			$errors[] = "ssl key";
 		}
-		if (empty($_POST["v_ssl_home"])) {
-			$errors[] = "ssl home";
-		}
-		$v_ssl_home = quoteshellarg($_POST["v_ssl_home"]);
+
 		if (!empty($errors[0])) {
 			foreach ($errors as $i => $error) {
 				if ($i == 0) {
@@ -885,6 +882,7 @@ if (!empty($_POST["save"])) {
 				fwrite($fp, str_replace("\r\n", "\n", $_POST["v_ssl_ca"]));
 				fclose($fp);
 			}
+			//keep using the original value for v_ssl_home
 			exec(
 				HESTIA_CMD .
 					"v-add-web-domain-ssl " .
@@ -894,7 +892,7 @@ if (!empty($_POST["save"])) {
 					" " .
 					$tmpdir .
 					" " .
-					$v_ssl_home .
+					quoteshellarg($v_ssl_home) .
 					" 'no'",
 				$output,
 				$return_var,

+ 3 - 0
web/inc/main.php

@@ -145,6 +145,9 @@ if (isset($_SESSION["look"]) && $_SESSION["look"] != "" && $_SESSION["userContex
 	$user = quoteshellarg($_SESSION["look"]);
 	$user_plain = htmlentities($_SESSION["look"]);
 }
+if (empty($user_plain)) {
+	$user_plain = "";
+}
 
 require_once dirname(__FILE__) . "/i18n.php";
 

BIN
web/locale/hu/LC_MESSAGES/hestiacp.mo


+ 1 - 1
web/locale/languages.json

@@ -54,7 +54,7 @@
 	"hu": ["Hungarian"],
 	"hr_locale": ["Hravtski"],
 	"hr": ["Croatian"],
-	"fr_locale": ["Fran\u00e7ais "],
+	"fr_locale": ["Fran\u00e7ais"],
 	"fr": ["French"],
 	"fi_locale": ["Suomi"],
 	"fi": ["Finnish"],

BIN
web/locale/pt-br/LC_MESSAGES/hestiacp.mo


BIN
web/locale/pt/LC_MESSAGES/hestiacp.mo


BIN
web/locale/ru/LC_MESSAGES/hestiacp.mo


BIN
web/locale/tr/LC_MESSAGES/hestiacp.mo


BIN
web/locale/zh-cn/LC_MESSAGES/hestiacp.mo


+ 1 - 1
web/src/app/System/HestiaApp.php

@@ -234,7 +234,7 @@ class HestiaApp {
 			}
 		} else {
 			$supported = $this->run("v-list-sys-php", "json", $result);
-			return $this->$result->json[0];
+			return $result->json[0];
 		}
 	}
 

+ 2 - 0
web/templates/pages/add_dns.php

@@ -88,12 +88,14 @@
 					</button>
 				</div>
 				<div x-cloak  x-show="showAdvanced" id="advtable">
+					<?php if ($_SESSION['DNS_CLUSTER_SYSTEM'] == 'hestia-zone' && $_SESSION['SUPPORT_DNSSEC'] == 'yes'){?>
 					<div class="form-check u-mb10">
 						<input class="form-check-input" type="checkbox" name="v_dnssec" id="v_dnssec" value="yes" <?php if($v_dnssec === 'yes'){ echo ' checked'; } ?>>
 						<label for="v_dnssec">
 							<?= _("Enable DNSSEC") ?>
 						</label>
 					</div>
+					<?php } ?>
 					<div class="u-mb10">
 						<label for="v_exp" class="form-label">
 							<?= _("Expiration Date") ?> <span class="optional">(<?= _("YYYY-MM-DD") ?>)</span>

+ 8 - 8
web/templates/pages/add_firewall_ipset.php

@@ -34,7 +34,7 @@
 				</label>
 				<div class="u-pos-relative">
 					<select class="form-select" tabindex="-1" id="datasource_list" onchange="this.nextElementSibling.value=this.value">
-						<option value="">clear</option>
+						<option value=""><?= _("Clear") ?></option>
 					</select>
 					<input type="text" class="form-control list-editor" name="v_datasource" id="v_datasource" maxlength="255" value="<?= htmlentities(trim($v_datasource, "'")) ?>">
 				</div>
@@ -62,25 +62,25 @@
 <script>
 	var country_iplists = [
 		<?php
-			$country = array('ca' => 'Canada', 'cn' => 'China', 'fr' => 'French', 'de' => 'Germany', 'in' => 'India', 'nl' => 'Netherlands', 'ro' => 'Romania', 'ru' => 'Russia', 'es' => 'Spain', 'ch' => 'Switzerland', 'tr' => 'Turkey', 'ua' => 'Ukraine',	'gb' => 'United Kingdom', 'us' => 'United States');
-			foreach($country as $iso =>$name){
-				echo '{name: "[IPv4] Country - '.$name.'",	source:"https://raw.githubusercontent.com/ipverse/rir-ip/master/country/'.$iso.'/ipv4-aggregated.txt"},'."\n";
+			$country = array('br' => 'Brazil', 'ca' => 'Canada', 'cn' => 'China', 'fr' => 'French', 'de' => 'Germany', 'in' => 'India', 'id' => 'Indonesia', 'nl' => 'Netherlands', 'ro' => 'Romania', 'ru' => 'Russia', 'es' => 'Spain', 'ch' => 'Switzerland', 'tr' => 'Turkey', 'ua' => 'Ukraine', 'gb' => 'United Kingdom', 'us' => 'United States');
+			foreach($country as $iso => $name){
+				echo '{name: "[IPv4] ' . _("Country") . ' - ' . $name . '", source: "https://raw.githubusercontent.com/ipverse/rir-ip/master/country/' . $iso . '/ipv4-aggregated.txt"},' . "\n";
 			}
 		?>
 		// Define IPv6 country lists
 		/*
 		<?php
-			foreach($country as $iso =>$name){
-				echo '{name: "[IPv6] Country - '.$name.'",	source:"https://raw.githubusercontent.com/ipverse/rir-ip/master/country/'.$iso.'/ipv6-aggregated.txt"},'."\n";
+			foreach($country as $iso => $name){
+				echo '{name: "[IPv6] ' . _("Country") . ' - ' . $name . '", source: "https://raw.githubusercontent.com/ipverse/rir-ip/master/country/' . $iso . '/ipv6-aggregated.txt"},' . "\n";
 			}
 		?>
 		*/
 	];
 
 	var blacklist_iplists = [
-		{ name: "[IPv4] Block Malicious IPs", source: "script:/usr/local/hestia/install/common/firewall/ipset/blacklist.sh" },
+		{name: "[IPv4] Block Malicious IPs", source: "script:/usr/local/hestia/install/common/firewall/ipset/blacklist.sh"},
 		/*
-		{name: "[IPv6] Block Malicious IPs",			 source:"script:/usr/local/hestia/install/common/firewall/ipset/blacklist.ipv6.sh"},
+		{name: "[IPv6] Block Malicious IPs", source: "script:/usr/local/hestia/install/common/firewall/ipset/blacklist.ipv6.sh"},
 		*/
 	];
 

+ 10 - 10
web/templates/pages/add_user.php

@@ -33,15 +33,15 @@
 			<?php show_alert_message($_SESSION); ?>
 			<div class="u-mb10">
 				<label for="v_username" class="form-label"><?= _("Username") ?></label>
-				<input type="text" class="form-control" name="v_username" id="v_username" value="<?= htmlentities(trim($v_username, "'")) ?>" tabindex="1">
+				<input type="text" class="form-control" name="v_username" id="v_username" value="<?= htmlentities(trim($v_username, "'")) ?>" tabindex="1" required>
 			</div>
 			<div class="u-mb10">
 				<label for="v_name" class="form-label"><?= _("Contact") ?></label>
-				<input type="text" class="form-control" name="v_name" id="v_name" value="<?= htmlentities(trim($v_name, "'")) ?>" tabindex="2">
+				<input type="text" class="form-control" name="v_name" id="v_name" value="<?= htmlentities(trim($v_name, "'")) ?>" tabindex="2" required>
 			</div>
 			<div class="u-mb10">
 				<label for="v_email" class="form-label"><?= _("Email") ?></label>
-				<input type="email" class="form-control" name="v_email" id="v_email" value="<?= htmlentities(trim($v_email, "'")) ?>" tabindex="3">
+				<input type="email" class="form-control" name="v_email" id="v_email" value="<?= htmlentities(trim($v_email, "'")) ?>" tabindex="3" required>
 			</div>
 			<div class="u-mb10">
 				<label for="v_password" class="form-label">
@@ -49,7 +49,7 @@
 					<a href="javascript:applyRandomPassword();" title="<?= _("generate") ?>" class="u-ml5"><i class="fas fa-arrows-rotate icon-green"></i></a>
 				</label>
 				<div class="u-pos-relative u-mb10">
-					<input type="text" class="form-control js-password-input" name="v_password" id="v_password" value="<?= htmlentities(trim($v_password, "'")) ?>" tabindex="4">
+					<input type="text" class="form-control js-password-input" name="v_password" id="v_password" value="<?= htmlentities(trim($v_password, "'")) ?>" tabindex="4" required>
 					<div class="password-meter">
 						<meter max="4" class="password-meter-input js-password-meter"></meter>
 					</div>
@@ -77,7 +77,7 @@
 			</div>
 			<div class="u-mb10">
 				<label for="v_language" class="form-label"><?= _("Language") ?></label>
-				<select class="form-select" name="v_language" id="v_language" tabindex="6">
+				<select class="form-select" name="v_language" id="v_language" tabindex="6" required>
 					<?php
 						foreach ($languages as $key => $value) {
 							echo "\n\t\t\t\t\t\t\t\t\t<option value=\"".htmlentities($key)."\"";
@@ -96,15 +96,15 @@
 			</div>
 			<div class="u-mb10">
 				<label for="v_role" class="form-label"><?= _("Role") ?></label>
-				<select class="form-select" name="v_role" id="v_role">
-					<option value="user"><?= _("User") ?>
-					<option value="admin" <?php if($v_role == "admin" ){ echo "selected"; } ?>><?= _("Administrator") ?>
-					<option value="dns-cluster" <?php if($v_role == "dns-cluster" ){ echo "selected"; } ?>><?= _("DNS Sync user") ?>
+				<select class="form-select" name="v_role" id="v_role" required>
+					<option value="user"><?= _("User") ?></option>
+					<option value="admin" <?= $v_role == "admin" ? "selected" : "" ?>><?= _("Administrator") ?></option>
+					<option value="dns-cluster" <?= $v_role == "dns-cluster" ? "selected" : "" ?>><?= _("DNS Sync user") ?></option>
 				</select>
 			</div>
 			<div class="u-mb10">
 				<label for="v_package" class="form-label"><?= _("Package") ?></label>
-				<select class="form-select" name="v_package" id="v_package" tabindex="8">
+				<select class="form-select" name="v_package" id="v_package" tabindex="8" required>
 					<?php
 						foreach ($data as $key => $value) {
 							echo "\n\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"".htmlentities($key)."\"";

+ 2 - 0
web/templates/pages/edit_dns.php

@@ -64,12 +64,14 @@
 					</select>
 				</div>
 			<?php } ?>
+			<?php if ($_SESSION['DNS_CLUSTER_SYSTEM'] == 'hestia-zone' && $_SESSION['SUPPORT_DNSSEC'] == 'yes'){?>
 			<div class="form-check u-mb10">
 				<input class="form-check-input" type="checkbox" name="v_dnssec" id="v_dnssec" value="yes" <?php if($v_dnssec === 'yes'){ echo ' checked'; } ?>>
 				<label for="v_dnssec">
 					<?= _("Enable DNSSEC") ?>
 				</label>
 			</div>
+			<?php } ?>
 			<div class="u-mb10">
 				<label for="v_exp" class="form-label">
 					<?= _("Expiration Date") ?><span class="optional">(<?= _("YYYY-MM-DD") ?>)</span>

+ 3 - 3
web/templates/pages/edit_mail.php

@@ -121,17 +121,17 @@
 							<?= _("SSL Certificate") ?>
 							<span x-cloak x-show="!letsEncryptEnabled" id="generate-csr" > / <a class="form-link" target="_blank" href="/generate/ssl/?domain=<?= htmlentities($v_domain) ?>"><?= _("Generate CSR") ?></a></span>
 						</label>
-						<textarea x-bind:disabled="!letsEncryptEnabled" class="form-control u-min-height100 u-console" name="v_ssl_crt" id="v_ssl_crt"><?= htmlentities(trim($v_ssl_crt, "'")) ?></textarea>
+						<textarea x-bind:disabled="letsEncryptEnabled" class="form-control u-min-height100 u-console" name="v_ssl_crt" id="v_ssl_crt"><?= htmlentities(trim($v_ssl_crt, "'")) ?></textarea>
 					</div>
 					<div class="u-mb10">
 						<label for="v_ssl_key" class="form-label"><?= _("SSL Key") ?></label>
-						<textarea x-bind:disabled="!letsEncryptEnabled" class="form-control u-min-height100 u-console" name="v_ssl_key" id="v_ssl_key"><?= htmlentities(trim($v_ssl_key, "'")) ?></textarea>
+						<textarea x-bind:disabled="letsEncryptEnabled" class="form-control u-min-height100 u-console" name="v_ssl_key" id="v_ssl_key"><?= htmlentities(trim($v_ssl_key, "'")) ?></textarea>
 					</div>
 					<div class="u-mb20">
 						<label for="v_ssl_ca" class="form-label">
 							<?= _("SSL Certificate Authority / Intermediate") ?> <span class="optional">(<?= _("optional") ?>)</span>
 						</label>
-						<textarea x-bind:disabled="!letsEncryptEnabled" class="form-control u-min-height100 u-console" name="v_ssl_ca" id="v_ssl_ca"><?= htmlentities(trim($v_ssl_ca, "'")) ?></textarea>
+						<textarea x-bind:disabled="letsEncryptEnabled" class="form-control u-min-height100 u-console" name="v_ssl_ca" id="v_ssl_ca"><?= htmlentities(trim($v_ssl_ca, "'")) ?></textarea>
 					</div>
 				</div>
 				<?php if ($v_ssl != "no") { ?>

+ 11 - 11
web/templates/pages/edit_server.php

@@ -55,7 +55,7 @@
 			<h1 class="form-title">
 				<?= _("Configuring Server") ?>
 			</h1>
-			<?php show_alert_message($_SESSION) ?>
+			<?php show_alert_message($_SESSION); ?>
 
 			<!-- Basic options section -->
 			<details class="collapse u-mb10">
@@ -106,7 +106,7 @@
 							type="checkbox"
 							name="v_policy_user_change_theme"
 							id="v_policy_user_change_theme"
-							<?= $_SESSION["POLICY_USER_CHANGE_THEME"] == "no"  ? "checked" : "" ?>
+							<?= $_SESSION["POLICY_USER_CHANGE_THEME"] == "no" ? "checked" : "" ?>
 						>
 						<label for="v_policy_user_change_theme">
 							<?= _("Set as selected theme for all users") ?>
@@ -178,7 +178,7 @@
 							type="checkbox"
 							name="v_experimental_features"
 							id="v_experimental_features"
-							<?= $_SESSION["POLICY_SYSTEM_ENABLE_BACON"] == "true" ?  "checked" : "" ?>
+							<?= $_SESSION["POLICY_SYSTEM_ENABLE_BACON"] == "true" ? "checked" : "" ?>
 						>
 						<label for="v_experimental_features">
 							<?= _("Enable preview features") ?>
@@ -353,7 +353,7 @@
 							?>
 							<div>
 								<label for="v_dns_remote_host" class="form-label">
-									<?= _("Host"). " #" . $i ?>
+									<?= _("Host") . " #" . $i ?>
 								</label>
 								<input
 									type="text"
@@ -543,7 +543,7 @@
 									class="form-select"
 									name="v_phpmyadmin_key"
 									id="v_phpmyadmin_key"
-									<?php $_SESSION["API"] != "yes" ? "disabled" : "" ?>
+									<?php $_SESSION["API"] != "yes" ? "disabled" : ""; ?>
 								>
 									<option value="no">
 										<?= _("Disabled") ?>
@@ -696,7 +696,7 @@
 							<option value="gzip">
 								gzip
 							</option>
-							<option value="zstd" <?= $v_backup_mode == "zstd" ? "selected" :"" ?>>
+							<option value="zstd" <?= $v_backup_mode == "zstd" ? "selected" : "" ?>>
 								zstd
 							</option>
 						</select>
@@ -934,7 +934,7 @@
 								/
 								<a
 									class="form-link"
-									href="/generate/ssl/?domain=<?= htmlentities(trim($v_hostname,'"')) ?>"
+									href="/generate/ssl/?domain=<?= htmlentities(trim($v_hostname, '"')) ?>"
 									target="_blank"
 								>
 									<?= _("Generate CSR") ?>
@@ -1122,7 +1122,7 @@
 						</div>
 					</div>
 
-					<?php if (($_SESSION["userContext"] === "admin") && ($_SESSION["user"] === "admin")) { ?>
+					<?php if ($_SESSION["userContext"] === "admin" && $_SESSION["user"] === "admin") { ?>
 						<h2 x-on:click="showProtectionOptions = !showProtectionOptions" class="section-title">
 							<?= _("System Protection") ?>
 							<i
@@ -1146,7 +1146,7 @@
 									<option value="yes">
 										<?= _("Yes") ?>
 									</option>
-									<option value="no" <?= $_SESSION["POLICY_SYSTEM_PROTECTED_ADMIN"] !== "yes" ?"selected" : "" ?>>
+									<option value="no" <?= $_SESSION["POLICY_SYSTEM_PROTECTED_ADMIN"] !== "yes" ? "selected" : "" ?>>
 										<?= _("No") ?>
 									</option>
 								</select>
@@ -1163,7 +1163,7 @@
 									<option value="yes">
 										<?= _("Yes") ?>
 									</option>
-									<option value="no" <?= $_SESSION["POLICY_SYSTEM_HIDE_ADMIN"] !== "yes" ?"selected" : "" ?>>
+									<option value="no" <?= $_SESSION["POLICY_SYSTEM_HIDE_ADMIN"] !== "yes" ? "selected" : "" ?>>
 										<?= _("No") ?>
 									</option>
 								</select>
@@ -1180,7 +1180,7 @@
 									<option value="yes">
 										<?= _("Yes") ?>
 									</option>
-									<option value="no" <?= $_SESSION["POLICY_SYSTEM_HIDE_SERVICES"] !== "yes" ?"selected" : "" ?>>
+									<option value="no" <?= $_SESSION["POLICY_SYSTEM_HIDE_SERVICES"] !== "yes" ? "selected" : "" ?>>
 										<?= _("No") ?>
 									</option>
 								</select>

+ 15 - 34
web/templates/pages/edit_user.php

@@ -33,21 +33,6 @@
 			<?php } ?>
 		</div>
 		<div class="toolbar-buttons">
-			<?php if ($_SESSION["user"] == $v_username || isset($_SESSION["look"])) { ?>
-				<!-- Do not show delete button for currently logged in user-->
-			<?} else {?>
-				<a href="/login/?loginas=<?= htmlentities($v_username) ?>&token=<?= $_SESSION["token"] ?>" class="button button-secondary" id="btn-create" title="<?= _("login as") ?>">
-					<i class="fas fa-right-to-bracket icon-maroon"></i><?= _("login as") ?>
-				</a>
-				<a class="data-controls do_delete button button-secondary button-danger">
-					<i class="do_delete fas fa-circle-xmark icon-red"></i>
-					<?= _("Delete") ?>
-					<input type="hidden" name="delete_url" value="/delete/user/?user=<?= htmlentities($v_username) ?>&token=<?= $_SESSION["token"] ?>">
-					<div class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
-						<p><?= sprintf(_("DELETE_USER_CONFIRMATION"), htmlentities($v_username)) ?></p>
-					</div>
-				</a>
-			<?php } ?>
 			<button type="submit" class="button" form="vstobjects">
 				<i class="fas fa-floppy-disk icon-purple"></i><?= _("Save") ?>
 			</button>
@@ -77,19 +62,19 @@
 			<?php show_alert_message($_SESSION); ?>
 			<div class="u-mb10">
 				<label for="v_user" class="form-label"><?= _("Username") ?></label>
-				<input type="text" class="form-control" name="v_user" id="v_user" value="<?= htmlentities(trim($v_username, "'")) ?>" disabled>
+				<input type="text" class="form-control" name="v_user" id="v_user" value="<?= htmlentities(trim($v_username, "'")) ?>" disabled required>
 				<input type="hidden" name="v_username" value="<?= htmlentities(trim($v_username, "'")) ?>">
 			</div>
 			<div class="u-mb10">
 				<label for="v_name" class="form-label"><?= _("Contact") ?></label>
-				<input type="text" class="form-control" name="v_name" id="v_name" value="<?=htmlentities(trim($v_name, "'"))?>" <?php if (($_SESSION['userContext'] !=='admin' ) && ($_SESSION['POLICY_USER_EDIT_DETAILS'] !=='yes' )) { echo 'disabled' ; }?> >
+				<input type="text" class="form-control" name="v_name" id="v_name" value="<?=htmlentities(trim($v_name, "'"))?>" <?php if (($_SESSION['userContext'] !=='admin' ) && ($_SESSION['POLICY_USER_EDIT_DETAILS'] !=='yes' )) { echo 'disabled' ; }?> required>
 				<?php if (($_SESSION['userContext'] !== 'admin') && ($_SESSION['POLICY_USER_EDIT_DETAILS'] !== 'yes')) {?>
 					<input type="hidden" name="v_name" value="<?=htmlentities(trim($v_name, "'"))?>">
 				<?php } ?>
 			</div>
 			<div class="u-mb10">
 				<label for="v_email" class="form-label"><?= _("Email") ?></label>
-				<input type="email" class="form-control" name="v_email" id="v_email" value="<?=htmlentities(trim($v_email, "'"))?>" <?php if (($_SESSION['userContext'] !=='admin' ) && ($_SESSION['POLICY_USER_EDIT_DETAILS'] !=='yes' )) { echo 'disabled' ; }?>>
+				<input type="email" class="form-control" name="v_email" id="v_email" value="<?=htmlentities(trim($v_email, "'"))?>" <?php if (($_SESSION['userContext'] !=='admin' ) && ($_SESSION['POLICY_USER_EDIT_DETAILS'] !=='yes' )) { echo 'disabled' ; }?> required>
 				<?php if (($_SESSION['userContext'] !== 'admin') && ($_SESSION['POLICY_USER_EDIT_DETAILS'] !== 'yes')) {?>
 					<input type="hidden" name="v_email" value="<?=htmlentities(trim($v_email, "'"))?>">
 				<?php } ?>
@@ -150,7 +135,7 @@
 			</div>
 			<div class="u-mb10">
 				<label for="v_language" class="form-label"><?= _("Language") ?></label>
-				<select class="form-select" name="v_language" id="v_language">
+				<select class="form-select" name="v_language" id="v_language" required>
 					<?php
 						foreach ($languages as $key => $value) {
 							echo "\n\t\t\t\t\t\t\t\t\t<option value=\"".$key."\"";
@@ -166,20 +151,16 @@
 					?>
 				</select>
 			</div>
-			<?php if ($v_username == "admin") { ?>
-				<!-- Hide option to change 'admin' user's role-->
-			<?php } else { ?>
-				<?php if ($_SESSION["userContext"] === "admin" && $_SESSION["user"] != $v_username) { ?>
-					<div class="u-mb10">
-						<label for="v_role" class="form-label"><?= _("Role") ?></label>
-						<select class="form-select" name="v_role" id="v_role">
-							<option value="user"><?= _("User") ?>
-							<option value="admin" <?php if($v_role == "admin" ){ echo "selected"; } ?>><?= _("Administrator") ?>
-							<option value="dns-cluster" <?php if($v_role == "dns-cluster" ){ echo "selected"; } ?>><?= _("DNS Sync user") ?>
-						</select>
-					</div>
-				<?php } ?>
-			<?php } ?>
+			<?php if ($v_username != "admin" && $_SESSION["userContext"] === "admin" && $_SESSION["user"] != $v_username): ?>
+				<div class="u-mb10">
+					<label for="v_role" class="form-label"><?= _("Role") ?></label>
+					<select class="form-select" name="v_role" id="v_role" required>
+						<option value="user"><?= _("User") ?></option>
+						<option value="admin" <?= $v_role == "admin" ? "selected" : "" ?>><?= _("Administrator") ?></option>
+						<option value="dns-cluster" <?= $v_role == "dns-cluster" ? "selected" : "" ?>><?= _("DNS Sync user") ?></option>
+					</select>
+				</div>
+			<?php endif; ?>
 			<?php if ($_SESSION["POLICY_USER_CHANGE_THEME"] !== "no") { ?>
 			<div class="u-mb10">
 				<label for="v_user_theme" class="form-label"><?= _("Theme") ?></label>
@@ -209,7 +190,7 @@
 			<?php if ($_SESSION['userContext'] === 'admin') {?>
 				<div class="u-mb20">
 					<label for="v_package" class="form-label"><?= _("Package") ?></label>
-					<select class="form-select" name="v_package" id="v_package">
+					<select class="form-select" name="v_package" id="v_package" required>
 						<?php
 							foreach ($packages as $key => $value) {
 								echo "\n\t\t\t\t\t\t\t\t\t<option value=\"".htmlentities($key)."\"";

+ 3 - 3
web/templates/pages/list_access_keys.php

@@ -16,7 +16,7 @@
 					<li entity="sort-comment"><span class="name"><?= _("Comment") ?> <i class="fas fa-arrow-down-a-z"></i></span><span class="up"><i class="fas fa-arrow-up-a-z"></i></span></li>
 				</ul>
 				<form x-data x-bind="BulkEdit" action="/bulk/access-key/" method="post">
-					<input type="hidden" name="token" value="<?=$_SESSION['token']?>">
+					<input type="hidden" name="token" value="<?= $_SESSION["token"] ?>">
 					<select class="form-select" name="action">
 						<option value=""><?= _("apply to selected") ?></option>
 						<option value="delete"><?= _("delete") ?></option>
@@ -66,10 +66,10 @@
 
 			<div class="l-unit__col l-unit__col--right">
 				<div class="clearfix l-unit__stat-col--left super-compact">
-					<input id="check<?=$i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="key[]" value="<?=$key?>">
+					<input id="check<?= $i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="key[]" value="<?= $key ?>">
 				</div>
 				<div class="clearfix l-unit__stat-col--left wide-6">
-					<b><a href="/list/access-key/?key=<?=htmlentities($key);?>&token=<?=$_SESSION['token']?>" title="<?= _("Access Key") ?>: <?=$key;?>"><?=$key;?></a></b>
+					<b><a href="/list/access-key/?key=<?= htmlentities($key) ?>&token=<?= $_SESSION["token"] ?>" title="<?= _("Access Key") ?>: <?= $key ?>"><?= $key ?></a></b>
 				</div>
 
 				<!-- START QUICK ACTION TOOLBAR AREA -->

+ 10 - 10
web/templates/pages/list_backup.php

@@ -39,7 +39,7 @@
 		<div class="l-unit__col l-unit__col--right">
 			<div>
 				<div class="clearfix l-unit__stat-col--left super-compact">
-					<input type="checkbox" class="js-toggle-all" title="<?= _("Select all") ?>" <?=$display_mode;?>>
+					<input type="checkbox" class="js-toggle-all" title="<?= _("Select all") ?>" <?= $display_mode ?>>
 				</div>
 				<div class="clearfix l-unit__stat-col--left wide-4"><b><?= _("File Name") ?></b></div>
 				<div class="clearfix l-unit__stat-col--left compact-4 u-text-right"><b>&nbsp;</b></div>
@@ -73,14 +73,14 @@
 			<div class="l-unit__col l-unit__col--right">
 				<div>
 					<div class="clearfix l-unit__stat-col--left super-compact">
-						<input id="check<?=$i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="backup[]" value="<?=$key?>" <?=$display_mode;?>>
+						<input id="check<?= $i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="backup[]" value="<?= $key ?>" <?= $display_mode ?>>
 					</div>
 					<div class="clearfix l-unit__stat-col--left wide-4 truncate">
 						<b>
-							<?php if ($read_only === 'true') {?>
-								<?=$key?>
+							<?php if ($read_only === "true") { ?>
+								<?= $key ?>
 							<?php } else { ?>
-								<a href="/list/backup/?backup=<?=$key?>&token=<?=$_SESSION['token']?>" title="<?= _("restore") ?>"><?=$key?></a>
+								<a href="/list/backup/?backup=<?= $key ?>&token=<?= $_SESSION["token"] ?>" title="<?= _("restore") ?>"><?= $key ?></a>
 							<?php } ?>
 						</b>
 					</div>
@@ -88,7 +88,7 @@
 					<div class="clearfix l-unit__stat-col--left compact-4 u-text-right">
 						<div class="l-unit-toolbar__col l-unit-toolbar__col--right u-noselect">
 							<div class="actions-panel clearfix">
-								<?php if (($_SESSION['userContext'] === 'admin') && ($_SESSION['look'] === 'admin') && ($read_only === 'true')) {?>
+								<?php if ($_SESSION["userContext"] === "admin" && $_SESSION["look"] === "admin" && $read_only === "true") { ?>
 									<!-- Restrict ability to restore or delete backups when impersonating 'admin' account -->
 									&nbsp;
 								<?php } else { ?>
@@ -96,11 +96,11 @@
 									<?php if ($read_only !== 'true') {?>
 										<div class="actions-panel__col actions-panel__list shortcut-enter" key-action="href"><a href="/list/backup/?backup=<?=$key?>&token=<?=$_SESSION['token']?>" title="<?= _("restore") ?>"><i class="fas fa-arrow-rotate-left icon-green icon-dim"></i></a></div>
 										<div class="actions-panel__col actions-panel__delete shortcut-delete" key-action="js">
-											<a id="delete_link_<?=$i?>" class="data-controls do_delete" title="<?= _("delete") ?>">
+											<a id="delete_link_<?= $i ?>" class="data-controls do_delete" title="<?= _("delete") ?>">
 												<i class="fas fa-trash icon-red icon-dim do_delete"></i>
-												<input type="hidden" name="delete_url" value="/delete/backup/?backup=<?=$key?>&token=<?=$_SESSION['token']?>">
-												<div id="delete_dialog_<?=$i?>" class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
-													<p><?=sprintf(_('DELETE_BACKUP_CONFIRMATION'),$key)?></p>
+												<input type="hidden" name="delete_url" value="/delete/backup/?backup=<?= $key ?>&token=<?= $_SESSION["token"] ?>">
+												<div id="delete_dialog_<?= $i ?>" class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
+													<p><?= sprintf(_("DELETE_BACKUP_CONFIRMATION"), $key) ?></p>
 												</div>
 											</a>
 										</div>

+ 16 - 16
web/templates/pages/list_backup_detail.php

@@ -54,19 +54,19 @@
 		<div class="l-unit animate__animated animate__fadeIn">
 			<div class="l-unit__col l-unit__col--right">
 				<div class="clearfix l-unit__stat-col--left super-compact">
-					<input id="check<?=$i?>" class="ch-toggle" type="checkbox" name="web[]" value="<?=$key?>">
+					<input id="check<?= $i ?>" class="ch-toggle" type="checkbox" name="web[]" value="<?= $key ?>">
 				</div>
 				<div class="clearfix l-unit__stat-col--left compact-4">
 					<div class="l-unit__stat-col l-unit__stat-col--left"><?= _("Web domain") ?></div>
 				</div>
 				<div class="clearfix l-unit__stat-col--left wide-7">
-					<div class="l-unit__stat-col l-unit__stat-col--left wide-7"><b><?=$key?></b></div>
+					<div class="l-unit__stat-col l-unit__stat-col--left wide-7"><b><?= $key ?></b></div>
 				</div>
 				<div class="clearfix l-unit__stat-col--left compact-4 u-text-right">
 					<div class="l-unit-toolbar__col l-unit-toolbar__col--right u-noselect">
 						<div class="actions-panel clearfix">
 							<div class="actions-panel__col actions-panel__list shortcut-enter" key-action="href">
-								<a href="/schedule/restore/?backup=<?=$backup?>&type=web&object=<?=$key?>&token=<?=$_SESSION['token']?>" title="<?= _("Restore") ?>">
+								<a href="/schedule/restore/?backup=<?= $backup ?>&type=web&object=<?= $key ?>&token=<?= $_SESSION["token"] ?>" title="<?= _("Restore") ?>">
 									<i class="fas fa-arrow-rotate-left icon-green icon-dim u-mr5"></i>
 								</a>
 							</div>
@@ -86,19 +86,19 @@
 		<div class="l-unit">
 			<div class="l-unit__col l-unit__col--right">
 				<div class="clearfix l-unit__stat-col--left super-compact">
-					<input id="check2<?=$i?>" class="ch-toggle" type="checkbox" name="mail[]" value="<?=$key?>">
+					<input id="check2<?= $i ?>" class="ch-toggle" type="checkbox" name="mail[]" value="<?= $key ?>">
 				</div>
 				<div class="clearfix l-unit__stat-col--left compact-4">
 					<div class="l-unit__stat-col l-unit__stat-col--left"><?= _("Mail domain") ?></div>
 				</div>
 				<div class="clearfix l-unit__stat-col--left wide-7">
-					<div class="l-unit__stat-col l-unit__stat-col--left wide-7"><b><?=$key?></b></div>
+					<div class="l-unit__stat-col l-unit__stat-col--left wide-7"><b><?= $key ?></b></div>
 				</div>
 				<div class="clearfix l-unit__stat-col--left compact-4 u-text-right">
 					<div class="l-unit-toolbar__col l-unit-toolbar__col--right u-noselect">
 						<div class="actions-panel clearfix">
 							<div class="actions-panel__col actions-panel__list shortcut-enter" key-action="href">
-								<a href="/schedule/restore/?backup=<?=$backup?>&type=mail&object=<?=$key?>&token=<?=$_SESSION['token']?>" title="<?= _("Restore") ?>">
+								<a href="/schedule/restore/?backup=<?= $backup ?>&type=mail&object=<?= $key ?>&token=<?= $_SESSION["token"] ?>" title="<?= _("Restore") ?>">
 									<i class="fas fa-arrow-rotate-left icon-green icon-dim"></i>
 								</a>
 							</div>
@@ -118,19 +118,19 @@
 		<div class="l-unit">
 			<div class="l-unit__col l-unit__col--right">
 				<div class="clearfix l-unit__stat-col--left super-compact">
-					<input id="check3<?=$i?>" class="ch-toggle" type="checkbox" name="dns[]" value="<?=$key?>">
+					<input id="check3<?= $i ?>" class="ch-toggle" type="checkbox" name="dns[]" value="<?= $key ?>">
 				</div>
 				<div class="clearfix l-unit__stat-col--left compact-4">
 					<div class="l-unit__stat-col l-unit__stat-col--left"><?= _("DNS domain") ?></div>
 				</div>
 				<div class="clearfix l-unit__stat-col--left wide-7">
-					<div class="l-unit__stat-col l-unit__stat-col--left wide-7"><b><?=$key?></b></div>
+					<div class="l-unit__stat-col l-unit__stat-col--left wide-7"><b><?= $key ?></b></div>
 				</div>
 				<div class="clearfix l-unit__stat-col--left compact-4 u-text-right">
 					<div class="l-unit-toolbar__col l-unit-toolbar__col--right u-noselect">
 						<div class="actions-panel clearfix">
 							<div class="actions-panel__col actions-panel__list shortcut-enter" key-action="href">
-								<a href="/schedule/restore/?backup=<?=$backup?>&type=dns&object=<?=$key?>&token=<?=$_SESSION['token']?>" title="<?= _("Restore") ?>">
+								<a href="/schedule/restore/?backup=<?= $backup ?>&type=dns&object=<?= $key ?>&token=<?= $_SESSION["token"] ?>" title="<?= _("Restore") ?>">
 									<i class="fas fa-arrow-rotate-left icon-green icon-dim"></i>
 								</a>
 							</div>
@@ -150,19 +150,19 @@
 		<div class="l-unit">
 			<div class="l-unit__col l-unit__col--right">
 				<div class="clearfix l-unit__stat-col--left super-compact">
-					<input id="check4<?=$i?>" class="ch-toggle" type="checkbox" name="db[]" value="<?=$key?>">
+					<input id="check4<?= $i ?>" class="ch-toggle" type="checkbox" name="db[]" value="<?= $key ?>">
 				</div>
 				<div class="clearfix l-unit__stat-col--left compact-4">
 					<div class="l-unit__stat-col l-unit__stat-col--left"><?= _("Database") ?></div>
 				</div>
 				<div class="clearfix l-unit__stat-col--left wide-7">
-					<div class="l-unit__stat-col l-unit__stat-col--left wide-7"><b><?=$key?></b></div>
+					<div class="l-unit__stat-col l-unit__stat-col--left wide-7"><b><?= $key ?></b></div>
 				</div>
 				<div class="clearfix l-unit__stat-col--left compact-4 u-text-right">
 					<div class="l-unit-toolbar__col l-unit-toolbar__col--right u-noselect">
 						<div class="actions-panel clearfix">
 							<div class="actions-panel__col actions-panel__list shortcut-enter" key-action="href">
-								<a href="/schedule/restore/?backup=<?=$backup?>&type=db&object=<?=$key?>&token=<?=$_SESSION['token']?>" title="<?= _("Restore") ?>">
+								<a href="/schedule/restore/?backup=<?= $backup ?>&type=db&object=<?= $key ?>&token=<?= $_SESSION["token"] ?>" title="<?= _("Restore") ?>">
 									<i class="fas fa-arrow-rotate-left icon-green icon-dim"></i>
 								</a>
 							</div>
@@ -211,19 +211,19 @@
 		<div class="l-unit">
 			<div class="l-unit__col l-unit__col--right">
 				<div class="clearfix l-unit__stat-col--left super-compact">
-					<input id="check6<?=$i?>" class="ch-toggle" type="checkbox" name="udir[]" value="<?=$key?>">
+					<input id="check6<?= $i ?>" class="ch-toggle" type="checkbox" name="udir[]" value="<?= $key ?>">
 				</div>
 				<div class="clearfix l-unit__stat-col--left compact-4">
 					<div class="l-unit__stat-col l-unit__stat-col--left"><?= _("user dir") ?></div>
 				</div>
 				<div class="clearfix l-unit__stat-col--left wide-7">
-					<div class="l-unit__stat-col l-unit__stat-col--left wide-7"><b><?=$key?></b></div>
+					<div class="l-unit__stat-col l-unit__stat-col--left wide-7"><b><?= $key ?></b></div>
 				</div>
 				<div class="clearfix l-unit__stat-col--left compact-4 u-text-right">
 					<div class="l-unit-toolbar__col l-unit-toolbar__col--right u-noselect">
 						<div class="actions-panel clearfix">
 							<div class="actions-panel__col actions-panel__list shortcut-enter" key-action="href">
-								<a href="/schedule/restore/?backup=<?=$backup?>&type=udir&object=<?=$key?>&token=<?=$_SESSION['token']?>" title="<?= _("Restore") ?>">
+								<a href="/schedule/restore/?backup=<?= $backup ?>&type=udir&object=<?= $key ?>&token=<?= $_SESSION["token"] ?>" title="<?= _("Restore") ?>">
 									<i class="fas fa-arrow-rotate-left icon-green icon-dim"></i>
 								</a>
 							</div>
@@ -238,7 +238,7 @@
 <footer class="app-footer">
 	<div class="container app-footer-inner">
 		<p>
-			<?php printf(ngettext('%d item', '%d items', $i),$i); ?>
+			<?php printf(ngettext("%d item", "%d items", $i), $i); ?>
 		</p>
 	</div>
 </footer>

+ 20 - 20
web/templates/pages/list_cron.php

@@ -2,12 +2,12 @@
 <div class="toolbar">
 	<div class="toolbar-inner">
 		<div class="toolbar-buttons">
-			<?php if ($read_only !== 'true') {?>
+			<?php if ($read_only !== "true") { ?>
 				<a href="/add/cron/" class="button button-secondary" id="btn-create"><i class="fas fa-circle-plus icon-green"></i><?= _("Add Cron Job") ?></a>
-				<?php if($panel[$user_plain]['CRON_REPORTS'] == 'yes') { ?>
-					<a class="button button-secondary" href="/delete/cron/reports/?token=<?=$_SESSION['token'];?>"><i class="fas fa-toggle-off icon-green"></i><?= _("turn off notifications") ?></a>
+				<?php if ($panel[$user_plain]["CRON_REPORTS"] == "yes") { ?>
+					<a class="button button-secondary" href="/delete/cron/reports/?token=<?= $_SESSION["token"] ?>"><i class="fas fa-toggle-off icon-green"></i><?= _("turn off notifications") ?></a>
 				<?php } else { ?>
-					<a class="button button-secondary" href="/add/cron/reports/?token=<?=$_SESSION['token'];?>"><i class="fas fa-toggle-off"></i><?= _("turn on notifications") ?></a>
+					<a class="button button-secondary" href="/add/cron/reports/?token=<?= $_SESSION["token"] ?>"><i class="fas fa-toggle-off"></i><?= _("turn on notifications") ?></a>
 				<?php } ?>
 			<?php } ?>
 		</div>
@@ -24,9 +24,9 @@
 					<li entity="sort-name"><span class="name <?php if ($_SESSION['userSortOrder'] === 'name') { echo 'active'; } ?>"><?= _("Command") ?> <i class="fas fa-arrow-down-a-z"></i></span><span class="up"><i class="fas fa-arrow-up-a-z"></i></span></li>
 					<li entity="sort-date" sort_as_int="1"><span class="name <?php if ($_SESSION['userSortOrder'] === 'date') { echo 'active'; } ?>"><?= _("Date") ?> <i class="fas fa-arrow-down-a-z"></i></span><span class="up"><i class="fas fa-arrow-up-a-z"></i></span></li>
 				</ul>
-				<?php if ($read_only !== 'true') {?>
+				<?php if ($read_only !== "true") { ?>
 					<form x-data x-bind="BulkEdit" action="/bulk/cron/" method="post">
-						<input type="hidden" name="token" value="<?=$_SESSION['token']?>">
+						<input type="hidden" name="token" value="<?= $_SESSION["token"] ?>">
 						<select class="form-select" name="action">
 							<option value=""><?= _("apply to selected") ?></option>
 							<?php if($panel[$user_plain]['CRON_REPORTS'] == 'yes') echo '<option value="delete-cron-reports">'._('turn off notifications').'</option>'; ?>
@@ -59,7 +59,7 @@
 	<div class="header table-header">
 		<div class="l-unit__col l-unit__col--right">
 			<div class="clearfix l-unit__stat-col--left super-compact">
-				<input type="checkbox" class="js-toggle-all" title="<?= _("Select all") ?>" <?=$display_mode;?>>
+				<input type="checkbox" class="js-toggle-all" title="<?= _("Select all") ?>" <?= $display_mode ?>>
 			</div>
 			<div class="clearfix l-unit__stat-col--left wide-5"><b><?= _("Command") ?></b></div>
 			<div class="clearfix l-unit__stat-col--left compact-2 u-text-right"><b>&nbsp;</b></div>
@@ -91,11 +91,11 @@
 			sort-date="<?=strtotime($data[$key]['DATE'].' '.$data[$key]['TIME'])?>" sort-name="<?=htmlspecialchars($data[$key]['CMD'], ENT_NOQUOTES)?>">
 			<div class="l-unit__col l-unit__col--right">
 				<div class="clearfix l-unit__stat-col--left super-compact">
-					<input id="check<?=$i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="job[]" value="<?=$key?>" <?=$display_mode;?>>
+					<input id="check<?= $i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="job[]" value="<?= $key ?>" <?= $display_mode ?>>
 				</div>
 				<div class="clearfix l-unit__stat-col--left wide-5 truncate">
-					<?php if (($read_only === 'true') || ($data[$key]['SUSPENDED'] == 'yes')) {?>
-						<b><?=htmlspecialchars($data[$key]['CMD'], ENT_NOQUOTES)?></b>
+					<?php if ($read_only === "true" || $data[$key]["SUSPENDED"] == "yes") { ?>
+						<b><?= htmlspecialchars($data[$key]["CMD"], ENT_NOQUOTES) ?></b>
 					<?php } else { ?>
 						<b><a href="/edit/cron/?job=<?=$data[$key]['JOB']?>&token=<?=$_SESSION['token']?>" title="<?= _("Editing Cron Job") ?>: <?=htmlspecialchars($data[$key]['CMD'], ENT_NOQUOTES)?>"><?=htmlspecialchars($data[$key]['CMD'], ENT_NOQUOTES)?></a></b>
 					<?php } ?>
@@ -104,7 +104,7 @@
 				<div class="clearfix l-unit__stat-col--left compact-2 u-text-right">
 					<div class="l-unit-toolbar__col l-unit-toolbar__col--right u-noselect">
 						<div class="actions-panel clearfix">
-							<?php if ($read_only === 'true') {?>
+							<?php if ($read_only === "true") { ?>
 								<!-- Restrict other administrators from editing, deleting, or suspending 'admin' user cron jobs -->
 								&nbsp;
 							<?php } else { ?>
@@ -112,20 +112,20 @@
 									<div class="actions-panel__col actions-panel__download shortcut-enter" key-action="href"><a href="/edit/cron/?job=<?=$data[$key]['JOB']?>&token=<?=$_SESSION['token']?>" title="<?= _("Editing Cron Job") ?>"><i class="fas fa-pencil icon-orange icon-dim"></i></a></div>
 								<?php } ?>
 								<div class="actions-panel__col actions-panel__suspend shortcut-s" key-action="js">
-									<a id="<?=$spnd_action ?>_link_<?=$i?>" class="data-controls do_<?=$spnd_action?>" title="<?=_($spnd_action)?>">
-										<i class="fas <?=$spnd_icon?> icon-highlight icon-dim do_<?=$spnd_action?>"></i>
-										<input type="hidden" name="<?=$spnd_action?>_url" value="/<?=$spnd_action?>/cron/?job=<?=$data[$key]['JOB']?>&token=<?=$_SESSION['token']?>">
-										<div id="<?=$spnd_action?>_dialog_<?=$i?>" class="dialog js-confirm-dialog-suspend" title="<?= _("Confirmation") ?>">
-											<p><?=sprintf($spnd_confirmation,$key)?></p>
+									<a id="<?= $spnd_action ?>_link_<?= $i ?>" class="data-controls do_<?= $spnd_action ?>" title="<?= _($spnd_action) ?>">
+										<i class="fas <?= $spnd_icon ?> icon-highlight icon-dim do_<?= $spnd_action ?>"></i>
+										<input type="hidden" name="<?= $spnd_action ?>_url" value="/<?= $spnd_action ?>/cron/?job=<?= $data[$key]["JOB"] ?>&token=<?= $_SESSION["token"] ?>">
+										<div id="<?= $spnd_action ?>_dialog_<?= $i ?>" class="dialog js-confirm-dialog-suspend" title="<?= _("Confirmation") ?>">
+											<p><?= sprintf($spnd_confirmation, $key) ?></p>
 										</div>
 									</a>
 								</div>
 								<div class="actions-panel__col actions-panel__delete shortcut-delete" key-action="js">
-									<a id="delete_link_<?=$i?>" class="data-controls do_delete" title="<?= _("delete") ?>">
+									<a id="delete_link_<?= $i ?>" class="data-controls do_delete" title="<?= _("delete") ?>">
 										<i class="fas fa-trash icon-red icon-dim do_delete"></i>
-										<input type="hidden" name="delete_url" value="/delete/cron/?job=<?=$data[$key]['JOB']?>&token=<?=$_SESSION['token']?>">
-										<div id="delete_dialog_<?=$i?>" class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
-											<p><?=sprintf(_('DELETE_CRON_CONFIRMATION'),$key)?></p>
+										<input type="hidden" name="delete_url" value="/delete/cron/?job=<?= $data[$key]["JOB"] ?>&token=<?= $_SESSION["token"] ?>">
+										<div id="delete_dialog_<?= $i ?>" class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
+											<p><?= sprintf(_("DELETE_CRON_CONFIRMATION"), $key) ?></p>
 										</div>
 									</a>
 								</div>

+ 13 - 13
web/templates/pages/list_db.php

@@ -53,12 +53,12 @@ if (!empty($_SESSION["DB_PGA_ALIAS"])) {
 					<li entity="sort-server"><span class="name"><?= _("Host") ?> <i class="fas fa-arrow-down-a-z"></i></span><span class="up"><i class="fas fa-arrow-up-a-z"></i></span></li>
 					<li entity="sort-user"><span class="name"><?= _("Username") ?> <i class="fas fa-arrow-down-a-z"></i></span><span class="up"><i class="fas fa-arrow-up-a-z"></i></span></li>
 				</ul>
-				<?php if ($read_only !== 'true') {?>
+				<?php if ($read_only !== "true") { ?>
 					<form x-data x-bind="BulkEdit" action="/bulk/db/" method="post">
-						<input type="hidden" name="token" value="<?=$_SESSION['token']?>">
+						<input type="hidden" name="token" value="<?= $_SESSION["token"] ?>">
 						<select class="form-select" name="action">
 							<option value=""><?= _("apply to selected") ?></option>
-							<?php if ($_SESSION['userContext'] === 'admin') {?>
+							<?php if ($_SESSION["userContext"] === "admin") { ?>
 								<option value="rebuild"><?= _("rebuild") ?></option>
 								<option value="suspend"><?= _("suspend") ?></option>
 								<option value="unsuspend"><?= _("unsuspend") ?></option>
@@ -89,7 +89,7 @@ if (!empty($_SESSION["DB_PGA_ALIAS"])) {
 	<div class="header table-header">
 		<div class="l-unit__col l-unit__col--right">
 			<div class="clearfix l-unit__stat-col--left super-compact">
-				<input type="checkbox" class="js-toggle-all" title="<?= _("Select all") ?>" <?=$display_mode;?>>
+				<input type="checkbox" class="js-toggle-all" title="<?= _("Select all") ?>" <?= $display_mode ?>>
 			</div>
 			<div class="clearfix l-unit__stat-col--left wide-3"><b><?= _("Name") ?></b></div>
 			<div class="clearfix l-unit__stat-col--left u-text-right compact-3"><b>&nbsp;</b></div>
@@ -131,20 +131,20 @@ if (!empty($_SESSION["DB_PGA_ALIAS"])) {
 			<div class="l-unit__col l-unit__col--right">
 				<div>
 					<div class="clearfix l-unit__stat-col--left super-compact">
-						<input id="check<?=$i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="database[]" value="<?=$key?>" <?=$display_mode;?>>
+						<input id="check<?= $i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="database[]" value="<?= $key ?>" <?= $display_mode ?>>
 					</div>
 					<div class="clearfix l-unit__stat-col--left wide-3 truncate">
-						<?php if (($read_only === 'true') || ($data[$key]['SUSPENDED'] == 'yes')) {?>
-							<b><?=$key?></b>
+						<?php if ($read_only === "true" || $data[$key]["SUSPENDED"] == "yes") { ?>
+							<b><?= $key ?></b>
 						<?php } else { ?>
-							<b><a href="/edit/db/?database=<?=$key?>&token=<?=$_SESSION['token']?>" title="<?= _("Editing Database") ?>: <?=$key?>"><?=$key?></a></b>
+							<b><a href="/edit/db/?database=<?= $key ?>&token=<?= $_SESSION["token"] ?>" title="<?= _("Editing Database") ?>: <?= $key ?>"><?= $key ?></a></b>
 						<?php } ?>
 					</div>
 					<!-- START QUICK ACTION TOOLBAR AREA -->
 					<div class="clearfix l-unit__stat-col--left u-text-right compact-3">
 						<div class="l-unit-toolbar__col l-unit-toolbar__col--right u-noselect">
 							<div class="actions-panel clearfix">
-								<?php if ($read_only === 'true') {?>
+								<?php if ($read_only === "true") { ?>
 									<!-- Restrict the ability to edit, delete, or suspend domain items when impersonating 'admin' user -->
 									&nbsp;
 								<?php } else { ?>
@@ -164,11 +164,11 @@ if (!empty($_SESSION["DB_PGA_ALIAS"])) {
 										</a>
 									</div>
 									<div class="actions-panel__col actions-panel__delete shortcut-delete" key-action="js">
-										<a id="delete_link_<?=$i?>" class="data-controls do_delete" title="<?= _("delete") ?>">
+										<a id="delete_link_<?= $i ?>" class="data-controls do_delete" title="<?= _("delete") ?>">
 											<i class="fas fa-trash icon-red icon-dim do_delete"></i>
-											<input type="hidden" name="delete_url" value="/delete/db/?database=<?=$key?>&token=<?=$_SESSION['token']?>">
-											<div id="delete_dialog_<?=$i?>" class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
-												<p><?=sprintf(_('DELETE_DATABASE_CONFIRMATION'),$key)?></p>
+											<input type="hidden" name="delete_url" value="/delete/db/?database=<?= $key ?>&token=<?= $_SESSION["token"] ?>">
+											<div id="delete_dialog_<?= $i ?>" class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
+												<p><?= sprintf(_("DELETE_DATABASE_CONFIRMATION"), $key) ?></p>
 											</div>
 										</a>
 									</div>

+ 19 - 19
web/templates/pages/list_dns.php

@@ -2,7 +2,7 @@
 <div class="toolbar">
 	<div class="toolbar-inner">
 		<div class="toolbar-buttons">
-			<?php if ($read_only !== 'true') {?>
+			<?php if ($read_only !== "true") { ?>
 				<a href="/add/dns/" class="button button-secondary" id="btn-create"><i class="fas fa-circle-plus icon-green"></i><?= _("Add DNS Domain") ?></a>
 			<?php } ?>
 		</div>
@@ -22,12 +22,12 @@
 					<li entity="sort-name"><span class="name <?php if ($_SESSION['userSortOrder'] === 'name') { echo 'active'; } ?>"><?= _("Name") ?> <i class="fas fa-arrow-down-a-z"></i></span><span class="up"><i class="fas fa-arrow-up-a-z"></i></span></li>
 					<li entity="sort-records"><span class="name"><?= _("Records") ?> <i class="fas fa-arrow-down-a-z"></i></span><span class="up"><i class="fas fa-arrow-up-a-z"></i></span></li>
 				</ul>
-				<?php if ($read_only !== 'true') {?>
+				<?php if ($read_only !== "true") { ?>
 					<form x-data x-bind="BulkEdit" action="/bulk/dns/" method="post">
-						<input type="hidden" name="token" value="<?=$_SESSION['token']?>">
+						<input type="hidden" name="token" value="<?= $_SESSION["token"] ?>">
 						<select class="form-select" name="action">
 							<option value=""><?= _("apply to selected") ?></option>
-							<?php if ($_SESSION['userContext'] === 'admin') {?>
+							<?php if ($_SESSION["userContext"] === "admin") { ?>
 								<option value="rebuild"><?= _("rebuild") ?></option>
 							<?php } ?>
 							<option value="suspend"><?= _("suspend") ?></option>
@@ -58,7 +58,7 @@
 	<div class="header table-header">
 		<div class="l-unit__col l-unit__col--right">
 			<div class="clearfix l-unit__stat-col--left super-compact">
-				<input type="checkbox" class="js-toggle-all" title="<?= _("Select all") ?>" <?=$display_mode;?>>
+				<input type="checkbox" class="js-toggle-all" title="<?= _("Select all") ?>" <?= $display_mode ?>>
 			</div>
 			<div class="clearfix l-unit__stat-col--left wide-3"><b><?= _("Name") ?></b></div>
 			<div class="clearfix l-unit__stat-col--left u-text-right"><b>&nbsp;</b></div>
@@ -97,17 +97,17 @@
 			sort-expire="<?=strtotime($data[$key]['EXP'])?>" sort-records="<?=(int)$data[$key]['RECORDS']?>">
 			<div class="l-unit__col l-unit__col--right">
 				<div class="clearfix l-unit__stat-col--left super-compact">
-					<input id="check<?=$i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="domain[]" value="<?=$key?>" <?=$display_mode;?>>
+					<input id="check<?= $i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="domain[]" value="<?= $key ?>" <?= $display_mode ?>>
 				</div>
 				<div class="clearfix l-unit__stat-col--left wide-3 truncate">
-					<b><a href="/list/dns/?domain=<?=htmlentities($key);?>&token=<?=$_SESSION['token']?>" title="<?= _("DNS records") ?>: <?=htmlentities($key);?>"><?=htmlentities($key);?></a></b>
-					<?=empty($data[$key]['SRC'])? '' : '<br>⇢ <span style="font-size:11px;">' . htmlspecialchars($data[$key]['SRC'], ENT_QUOTES) . '</span>'; ?>
+					<b><a href="/list/dns/?domain=<?= htmlentities($key) ?>&token=<?= $_SESSION["token"] ?>" title="<?= _("DNS records") ?>: <?= htmlentities($key) ?>"><?= htmlentities($key) ?></a></b>
+					<?= empty($data[$key]["SRC"]) ? "" : '<br>⇢ <span style="font-size:11px;">' . htmlspecialchars($data[$key]["SRC"], ENT_QUOTES) . "</span>" ?>
 				</div>
 				<!-- START QUICK ACTION TOOLBAR AREA -->
 				<div class="clearfix l-unit__stat-col--left u-text-right">
 					<div class="l-unit-toolbar__col l-unit-toolbar__col--right u-noselect">
 						<div class="actions-panel clearfix">
-							<?php if ($read_only === 'true') {?>
+							<?php if ($read_only === "true") { ?>
 								<!-- Restrict administrators from editing domain items when impersonating the 'admin' user -->
 								&nbsp;
 							<?php } else { ?>
@@ -128,11 +128,11 @@
 									</a>
 								</div>
 								<div class="actions-panel__col actions-panel__delete shortcut-delete" key-action="js">
-									<a id="delete_link_<?=$i?>" class="data-controls do_delete" title="<?= _("delete") ?>">
+									<a id="delete_link_<?= $i ?>" class="data-controls do_delete" title="<?= _("delete") ?>">
 										<i class="fas fa-trash icon-red icon-dim do_delete"></i>
-										<input type="hidden" name="delete_url" value="/delete/dns/?domain=<?=htmlentities($key);?>&token=<?=$_SESSION['token']?>">
-										<div id="delete_dialog_<?=$i?>" class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
-											<p><?=sprintf(_('DELETE_DOMAIN_CONFIRMATION'),$key)?></p>
+										<input type="hidden" name="delete_url" value="/delete/dns/?domain=<?= htmlentities($key) ?>&token=<?= $_SESSION["token"] ?>">
+										<div id="delete_dialog_<?= $i ?>" class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
+											<p><?= sprintf(_("DELETE_DOMAIN_CONFIRMATION"), $key) ?></p>
 										</div>
 									</a>
 								</div>
@@ -148,13 +148,13 @@
 						echo '<span>0</span>';
 					}?>
 				</div>
-				<div class="clearfix l-unit__stat-col--left u-text-center"><b><?=$data[$key]['TPL']?></b></div>
-				<div class="clearfix l-unit__stat-col--left u-text-center compact"><?=$data[$key]['TTL']?></div>
-				<div class="clearfix l-unit__stat-col--left u-text-center"><?=$data[$key]['SOA']?></div>
+				<div class="clearfix l-unit__stat-col--left u-text-center"><b><?= $data[$key]["TPL"] ?></b></div>
+				<div class="clearfix l-unit__stat-col--left u-text-center compact"><?= $data[$key]["TTL"] ?></div>
+				<div class="clearfix l-unit__stat-col--left u-text-center"><?= $data[$key]["SOA"] ?></div>
 				<div class="clearfix l-unit__stat-col--left u-text-center compact-3">
-					<i class="fas <?=$dnssec_icon;?>"></i>
+					<i class="fas <?= $dnssec_icon ?>"></i>
 				</div>
-				<div class="clearfix l-unit__stat-col--left u-text-center"><b><?=$data[$key]['EXP']?></b></div>
+				<div class="clearfix l-unit__stat-col--left u-text-center"><b><?= $data[$key]["EXP"] ?></b></div>
 			</div>
 		</div>
 	<?php } ?>
@@ -163,7 +163,7 @@
 <footer class="app-footer">
 	<div class="container app-footer-inner">
 		<p>
-			<?php printf(ngettext('%d DNS zone', '%d DNS zones', $i),$i); ?>
+			<?php printf(ngettext("%d DNS zone", "%d DNS zones", $i), $i); ?>
 		</p>
 	</div>
 </footer>

+ 4 - 4
web/templates/pages/list_dns_public.php

@@ -2,7 +2,7 @@
 <div class="toolbar">
 	<div class="toolbar-inner">
 		<div class="toolbar-buttons">
-			<?php if ($read_only !== 'true') {?>
+			<?php if ($read_only !== "true") { ?>
 				<a href="/add/dns/" class="button button-secondary" id="btn-create">
 					<i class="fas fa-circle-plus icon-green"></i><?= _("Add DNS Domain") ?>
 				</a>
@@ -24,12 +24,12 @@
 					<li entity="sort-name"><span class="name <?php if ($_SESSION['userSortOrder'] === 'name') { echo 'active'; } ?>"><?= _("Name") ?> <i class="fas fa-arrow-down-a-z"></i></span><span class="up"><i class="fas fa-arrow-up-a-z"></i></span></li>
 					<li entity="sort-records"><span class="name"><?= _("Records") ?> <i class="fas fa-arrow-down-a-z"></i></span><span class="up"><i class="fas fa-arrow-up-a-z"></i></span></li>
 				</ul>
-				<?php if ($read_only !== 'true') {?>
+				<?php if ($read_only !== "true") { ?>
 					<form x-data x-bind="BulkEdit" action="/bulk/dns/" method="post">
-						<input type="hidden" name="token" value="<?=$_SESSION['token']?>" />
+						<input type="hidden" name="token" value="<?= $_SESSION["token"] ?>" />
 						<select class="form-select" name="action">
 							<option value=""><?= _("apply to selected") ?></option>
-							<?php if ($_SESSION['userContext'] === 'admin') {?>
+							<?php if ($_SESSION["userContext"] === "admin") { ?>
 								<option value="rebuild"><?= _("rebuild") ?></option>
 							<?php } ?>
 							<option value="suspend"><?= _("suspend") ?></option>

+ 14 - 14
web/templates/pages/list_dns_rec.php

@@ -3,9 +3,9 @@
 	<div class="toolbar-inner">
 		<div class="toolbar-buttons">
 			<a class="button button-secondary" id="btn-back" href="/list/dns/"><i class="fas fa-arrow-left icon-blue"></i><?= _("Back") ?></a>
-			<?php if ($read_only !== 'true') {?>
-				<a href="/add/dns/?domain=<?=htmlentities($_GET['domain'])?>" class="button button-secondary" id="btn-create"><i class="fas fa-circle-plus icon-green"></i> <?= _("Add Record") ?></a>
-				<a href="/edit/dns/?domain=<?=htmlentities($_GET['domain'])?>" class="button button-secondary" id="btn-create"><i class="fas fa-pencil icon-blue"></i> <?= _("Editing DNS Domain") ?></a>
+			<?php if ($read_only !== "true") { ?>
+				<a href="/add/dns/?domain=<?= htmlentities($_GET["domain"]) ?>" class="button button-secondary" id="btn-create"><i class="fas fa-circle-plus icon-green"></i> <?= _("Add Record") ?></a>
+				<a href="/edit/dns/?domain=<?= htmlentities($_GET["domain"]) ?>" class="button button-secondary" id="btn-create"><i class="fas fa-pencil icon-blue"></i> <?= _("Editing DNS Domain") ?></a>
 			<?php } ?>
 		</div>
 		<div class="toolbar-right">
@@ -24,10 +24,10 @@
 					<li entity="sort-ttl" sort_as_int="1"><span class="name"><?= _("TTL") ?> <i class="fas fa-arrow-down-a-z"></i></span><span class="up"><i class="fas fa-arrow-up-a-z"></i></span></li>
 					<li entity="sort-type"><span class="name"><?= _("Type") ?> <i class="fas fa-arrow-down-a-z"></i></span><span class="up"><i class="fas fa-arrow-up-a-z"></i></span></li>
 				</ul>
-				<?php if ($read_only !== 'true') {?>
+				<?php if ($read_only !== "true") { ?>
 					<form x-data x-bind="BulkEdit" action="/bulk/dns/" method="post">
-						<input type="hidden" name="domain" value="<?=htmlentities($_GET['domain'])?>">
-						<input type="hidden" name="token" value="<?=$_SESSION['token']?>">
+						<input type="hidden" name="domain" value="<?= htmlentities($_GET["domain"]) ?>">
+						<input type="hidden" name="token" value="<?= $_SESSION["token"] ?>">
 						<select class="form-select" name="action">
 							<option value=""><?= _("apply to selected") ?></option>
 							<option value="suspend"><?= _("suspend") ?></option>
@@ -58,7 +58,7 @@
 	<div class="header table-header">
 		<div class="l-unit__col l-unit__col--right">
 			<div class="clearfix l-unit__stat-col--left super-compact">
-				<input type="checkbox" class="js-toggle-all" title="<?= _("Select all") ?>" <?=$display_mode;?>>
+				<input type="checkbox" class="js-toggle-all" title="<?= _("Select all") ?>" <?= $display_mode ?>>
 			</div>
 			<div class="clearfix l-unit__stat-col--left"><b><?= _("Record") ?></b></div>
 			<div class="clearfix l-unit__stat-col--left super-compact u-text-right"><b>&nbsp;</b></div>
@@ -90,7 +90,7 @@
 			v_unit_id="<?=htmlentities($key);?>" v_section="dns_rec" sort-date="<?=strtotime($data[$key]['DATE'].' '.$data[$key]['TIME'])?>" sort-record="<?=$data[$key]['RECORD']?>" sort-type="<?=$data[$key]['TYPE']?>" sort-ttl="<?=$data[$key]['TTL']?>" sort-value="<?=$data[$key]['VALUE']?>">
 			<div class="l-unit__col l-unit__col--right">
 				<div class="clearfix l-unit__stat-col--left super-compact">
-					<input id="check<?=$data[$key]['ID']?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="record[]" value="<?=$data[$key]['ID']?>" <?=$display_mode;?>>
+					<input id="check<?= $data[$key]["ID"] ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="record[]" value="<?= $data[$key]["ID"] ?>" <?= $display_mode ?>>
 				</div>
 				<div class="clearfix l-unit__stat-col--left u-truncate">
 					<b>
@@ -105,7 +105,7 @@
 			<div class="clearfix l-unit__stat-col--left super-compact u-text-right">
 				<div class="l-unit-toolbar__col l-unit-toolbar__col--right u-noselect">
 					<div class="actions-panel clearfix">
-						<?php if ($read_only === 'true') {?>
+						<?php if ($read_only === "true") { ?>
 							<!-- Restrict editing of DNS records when impersonating 'admin' account -->
 							&nbsp;
 						<?php } else { ?>
@@ -113,11 +113,11 @@
 								<div class="actions-panel__col actions-panel__logs shortcut-enter" key-action="href"><a href="/edit/dns/?domain=<?=htmlspecialchars($_GET['domain'])?>&record_id=<?=$data[$key]['ID']?>&token=<?=$_SESSION['token']?>" title="<?= _("Editing DNS Record") ?>"><i class="fas fa-pencil icon-orange icon-dim"></i></a></div>
 							<?php } ?>
 							<div class="actions-panel__col actions-panel__delete shortcut-delete" key-action="js">
-								<a id="delete_link_<?=$i?>" class="data-controls do_delete" title="<?= _("delete") ?>">
+								<a id="delete_link_<?= $i ?>" class="data-controls do_delete" title="<?= _("delete") ?>">
 									<i class="fas fa-trash icon-red icon-dim do_delete"></i>
-									<input type="hidden" name="delete_url" value="/delete/dns/?domain=<?=htmlspecialchars($_GET['domain'])?>&record_id=<?=$data[$key]['ID']?>&token=<?=$_SESSION['token']?>">
-									<div id="delete_dialog_<?=$i?>" class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
-										<p><?=sprintf(_('DELETE_RECORD_CONFIRMATION'),$key)?></p>
+									<input type="hidden" name="delete_url" value="/delete/dns/?domain=<?= htmlspecialchars($_GET["domain"]) ?>&record_id=<?= $data[$key]["ID"] ?>&token=<?= $_SESSION["token"] ?>">
+									<div id="delete_dialog_<?= $i ?>" class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
+										<p><?= sprintf(_("DELETE_RECORD_CONFIRMATION"), $key) ?></p>
 									</div>
 								</a>
 							</div>
@@ -130,7 +130,7 @@
 			<div class="clearfix l-unit__stat-col--left compact u-text-center"><?=$data[$key]['PRIORITY']?>&nbsp;</div>
 			<div class="clearfix l-unit__stat-col--left compact u-text-center"><?php if($data[$key]['TTL'] == ''){ echo _('Default'); }else{ echo $data[$key]['TTL'];} ?></div>
 			<div class="clearfix l-unit__stat-col--left super-compact"><b>&nbsp;</b></div>
-			<div class="clearfix l-unit__stat-col--left wide-6 truncate" style="word-break: break-word;"><?=htmlspecialchars($data[$key]['VALUE'], ENT_QUOTES, 'UTF-8') ?></div>
+			<div class="clearfix l-unit__stat-col--left wide-6 truncate" style="word-break: break-word;"><?= htmlspecialchars($data[$key]["VALUE"], ENT_QUOTES, "UTF-8") ?></div>
 		</div>
 	</div>
 <?php } ?>

+ 3 - 3
web/templates/pages/list_firewall.php

@@ -74,11 +74,11 @@
 			<div class="l-unit__col l-unit__col--right">
 				<div>
 					<div class="clearfix l-unit__stat-col--left super-compact">
-						<input id="check<?=$i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="rule[]" value="<?=$key?>">
+						<input id="check<?= $i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="rule[]" value="<?= $key ?>">
 					</div>
 					<div class="clearfix l-unit__stat-col--left wide-1">
 						<b>
-							<a href="/edit/firewall/?rule=<?=$key?>&token=<?=$_SESSION['token']?>" title="<?= _("Editing Firewall Rule") ?>">
+							<a href="/edit/firewall/?rule=<?= $key ?>&token=<?= $_SESSION["token"] ?>" title="<?= _("Editing Firewall Rule") ?>">
 								<?php
 									$suspended = $data[$key]["SUSPENDED"] == "no";
 									$action = $data[$key]["ACTION"];
@@ -129,7 +129,7 @@
 <footer class="app-footer">
 	<div class="container app-footer-inner">
 		<p>
-			<?php printf(ngettext('%d firewall rule', '%d firewall rules', $i),$i); ?>
+			<?php printf(ngettext("%d firewall rule", "%d firewall rules", $i), $i); ?>
 		</p>
 	</div>
 </footer>

+ 9 - 9
web/templates/pages/list_firewall_banlist.php

@@ -44,19 +44,19 @@
 		<div class="l-unit animate__animated animate__fadeIn">
 			<div class="l-unit__col l-unit__col--right">
 				<div class="clearfix l-unit__stat-col--left super-compact">
-					<input id="check<?=$i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="ipchain[]" value="<?=$ip . ':' . $value['CHAIN'] ?>">
+					<input id="check<?= $i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="ipchain[]" value="<?= $ip . ":" . $value["CHAIN"] ?>">
 				</div>
-				<div class="clearfix l-unit__stat-col--left wide-3"><b><?=$ip?></b></div>
+				<div class="clearfix l-unit__stat-col--left wide-3"><b><?= $ip ?></b></div>
 				<!-- START QUICK ACTION TOOLBAR AREA -->
 				<div class="clearfix l-unit__stat-col--left compact-4">
 					<div class="l-unit-toolbar__col l-unit-toolbar__col--right u-noselect">
 						<div class="actions-panel clearfix">
 							<div class="actions-panel__col actions-panel__delete shortcut-delete" key-action="js">
-								<a id="delete_link_<?=$i?>" class="data-controls do_delete">
+								<a id="delete_link_<?= $i ?>" class="data-controls do_delete">
 									<i class="fas fa-trash icon-red icon-dim do_delete"></i>
-									<input type="hidden" name="delete_url" value="/delete/firewall/banlist/?ip=<?=$ip?>&chain=<?=$value['CHAIN']?>&token=<?=$_SESSION['token']?>">
-									<div id="delete_dialog_<?=$i?>" class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
-										<p><?=sprintf(_('DELETE_IP_CONFIRMATION'),$key)?></p>
+									<input type="hidden" name="delete_url" value="/delete/firewall/banlist/?ip=<?= $ip ?>&chain=<?= $value["CHAIN"] ?>&token=<?= $_SESSION["token"] ?>">
+									<div id="delete_dialog_<?= $i ?>" class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
+										<p><?= sprintf(_("DELETE_IP_CONFIRMATION"), $key) ?></p>
 									</div>
 								</a>
 							</div>
@@ -64,9 +64,9 @@
 					</div>
 				</div>
 				<!-- END QUICK ACTION TOOLBAR AREA -->
-				<div class="clearfix l-unit__stat-col--left u-text-center compact-5"><?=_($data[$key]['DATE'])?></div>
-				<div class="clearfix l-unit__stat-col--left u-text-center compact-5"><?=$data[$key]['TIME']?></div>
-				<div class="clearfix l-unit__stat-col--left u-text-center wide"><b><?=_($value['CHAIN'])?></b></div>
+				<div class="clearfix l-unit__stat-col--left u-text-center compact-5"><?= _($data[$key]["DATE"]) ?></div>
+				<div class="clearfix l-unit__stat-col--left u-text-center compact-5"><?= $data[$key]["TIME"] ?></div>
+				<div class="clearfix l-unit__stat-col--left u-text-center wide"><b><?= _($value["CHAIN"]) ?></b></div>
 			</div>
 		</div>
 	<?php } ?>

+ 2 - 2
web/templates/pages/list_ip.php

@@ -19,7 +19,7 @@
 					<li entity="sort-owner"><span class="name"><?= _("Owner") ?> <i class="fas fa-arrow-down-a-z"></i></span><span class="up"><i class="fas fa-arrow-up-a-z"></i></span></li>
 				</ul>
 				<form x-data x-bind="BulkEdit" action="/bulk/ip/" method="post">
-					<input type="hidden" name="token" value="<?=$_SESSION['token']?>">
+					<input type="hidden" name="token" value="<?= $_SESSION["token"] ?>">
 					<select class="form-select" name="action">
 						<option value=""><?= _("apply to selected") ?></option>
 						<option value="reread IP"><?= _("reread IP") ?></option>
@@ -65,7 +65,7 @@
 
 			<div class="l-unit__col l-unit__col--right">
 				<div class="clearfix l-unit__stat-col--left super-compact">
-					<input id="check<?=$i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="ip[]" value="<?=$key?>">
+					<input id="check<?= $i ?>" class="ch-toggle" type="checkbox" title="<?= _("Select") ?>" name="ip[]" value="<?= $key ?>">
 				</div>
 				<div class="clearfix l-unit__stat-col--left wide-3"><b><a href="/edit/ip/?ip=<?=$key?>&token=<?=$_SESSION['token']?>" title="<?= _("Editing IP Address") ?>"><?=$key?> <?php if (!empty($data[$key]['NAT'])) echo ' → ' . $data[$key]['NAT'] . ''; ?></a></b>
 				</div>

+ 9 - 9
web/templates/pages/list_key.php

@@ -32,27 +32,27 @@
 		?>
 		<div class="l-unit header animate__animated animate__fadeIn" style="<?php if ($data[$key]['ID'] === 'filemanager.ssh.key'){ echo 'display: none;'; }?>">
 			<div class="l-unit__col l-unit__col--right">
-				<div class="clearfix l-unit__stat-col--left wide-3"><b><?=htmlspecialchars($data[$key]['ID']);?></b></div>
+				<div class="clearfix l-unit__stat-col--left wide-3"><b><?= htmlspecialchars($data[$key]["ID"]) ?></b></div>
 				<div class="clearfix l-unit__stat-col--left text-left compact-2">
 					<div class="l-unit-toolbar__col l-unit-toolbar__col--right u-noselect">
 						<div class="actions-panel clearfix">
 							<div class="actions-panel__col actions-panel__delete shortcut-delete" key-action="js">
-								<a id="delete_link_<?=$i?>" class="data-controls do_delete" title="<?= _("delete") ?>">
+								<a id="delete_link_<?= $i ?>" class="data-controls do_delete" title="<?= _("delete") ?>">
 									<i class="fas fa-trash icon-red icon-dim do_delete"></i>
-									<?php if (($_SESSION['userContext'] === 'admin') && (isset($_GET['user'])) && ($_GET['user'] !== 'admin')) { ?>
-										<input type="hidden" name="delete_url" value="/delete/key/?user=<?=htmlentities($_GET['user']);?>&key=<?=$key?>&token=<?=$_SESSION['token']?>">
+									<?php if ($_SESSION["userContext"] === "admin" && isset($_GET["user"]) && $_GET["user"] !== "admin") { ?>
+										<input type="hidden" name="delete_url" value="/delete/key/?user=<?= htmlentities($_GET["user"]) ?>&key=<?= $key ?>&token=<?= $_SESSION["token"] ?>">
 									<?php } else { ?>
-										<input type="hidden" name="delete_url" value="/delete/key/?key=<?=$key?>&token=<?=$_SESSION['token']?>">
+										<input type="hidden" name="delete_url" value="/delete/key/?key=<?= $key ?>&token=<?= $_SESSION["token"] ?>">
 									<?php } ?>
-									<div id="delete_dialog_<?=$i?>" class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
-										<p><?=sprintf(_('DELETE_KEY_CONFIRM'),$key)?></p>
+									<div id="delete_dialog_<?= $i ?>" class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
+										<p><?= sprintf(_("DELETE_KEY_CONFIRM"), $key) ?></p>
 									</div>
 								</a>
 							</div>
 						</div>
 					</div>
 				</div>
-				<div class="clearfix l-unit__stat-col--left wide-7"><b><?=htmlspecialchars($data[$key]['KEY'], ENT_QUOTES);?></b></div>
+				<div class="clearfix l-unit__stat-col--left wide-7"><b><?= htmlspecialchars($data[$key]["KEY"], ENT_QUOTES) ?></b></div>
 			</div>
 		</div>
 	<?php } ?>
@@ -61,7 +61,7 @@
 <footer class="app-footer">
 	<div class="container app-footer-inner">
 		<p>
-			<?php printf(ngettext('%d SSH Key', '%d SSH Keys', $i),$i); ?>
+			<?php printf(ngettext("%d SSH Key", "%d SSH Keys", $i), $i); ?>
 		</p>
 	</div>
 </footer>

+ 15 - 15
web/templates/pages/list_log.php

@@ -2,15 +2,15 @@
 <div class="toolbar">
 	<div class="toolbar-inner">
 		<div class="toolbar-buttons">
-			<?php if (($_SESSION['userContext'] === 'admin') && ($_SESSION['look'] === 'admin')) {?>
+			<?php if ($_SESSION["userContext"] === "admin" && $_SESSION["look"] === "admin") { ?>
 				<a href="/list/user/" class="button button-secondary" id="btn-back"><i class="fas fa-arrow-left icon-blue"></i><?= _("Back") ?></a>
-			<?php } else if (($_SESSION['userContext'] === 'admin') && (htmlentities($_GET['user']) === 'system')) { ?>
+			<?php } elseif ($_SESSION["userContext"] === "admin" && htmlentities($_GET["user"]) === "system") { ?>
 				<a href="/list/server/" class="button button-secondary" id="btn-back"><i class="fas fa-arrow-left icon-blue"></i><?= _("Back") ?></a>
 			<?php } else { ?>
 				<?php if (($_SESSION['userContext'] === 'admin') && (isset($_GET['user'])) && ($_GET['user'] !== 'admin')) { ?>
 					<a href="/edit/user/?user=<?=htmlentities($_GET['user']); ?>&token=<?=$_SESSION['token']?>" class="button button-secondary" id="btn-back"><i class="fas fa-arrow-left icon-blue"></i><?= _("Back") ?></a>
 				<?php } else { ?>
-					<a href="/edit/user/?token=<?=$_SESSION['token']?>" class="button button-secondary" id="btn-back"><i class="fas fa-arrow-left icon-blue"></i><?= _("Back") ?></a>
+					<a href="/edit/user/?token=<?= $_SESSION["token"] ?>" class="button button-secondary" id="btn-back"><i class="fas fa-arrow-left icon-blue"></i><?= _("Back") ?></a>
 				<?php } ?>
 			<?php } ?>
 			<?php if ($_SESSION['DEMO_MODE'] != "yes"){
@@ -23,24 +23,24 @@
 					<a href="/list/log/auth/" class="button button-secondary" id="btn-back" title="<?= _("Login history") ?>"><i class="fas fa-binoculars icon-green"></i><?= _("Login history") ?></a>
 				<?php } ?>
 			<?php } ?>
-			<?php if ($_SESSION['userContext'] === 'user') {?>
+			<?php if ($_SESSION["userContext"] === "user") { ?>
 				<a href="/list/log/auth/" class="button button-secondary" id="btn-back" title="<?= _("Login history") ?>"><i class="fas fa-binoculars icon-green"></i><?= _("Login history") ?></a>
 			<?php }
 			} ?>
 		</div>
 		<div class="toolbar-buttons">
 			<a href="javascript:location.reload();" class="button button-secondary"><i class="fas fa-arrow-rotate-right icon-green"></i><?= _("Refresh") ?></a>
-			<?php if (($_SESSION['userContext'] === 'admin') && ($_SESSION['look'] === 'admin') && ($_SESSION['POLICY_SYSTEM_PROTECTED_ADMIN'] === 'yes')) {?>
+			<?php if ($_SESSION["userContext"] === "admin" && $_SESSION["look"] === "admin" && $_SESSION["POLICY_SYSTEM_PROTECTED_ADMIN"] === "yes") { ?>
 				<!-- Hide delete buttons-->
 			<?php } else { ?>
-				<?php if (($_SESSION['userContext'] === 'admin') || (($_SESSION['userContext'] === 'user') && ($_SESSION['POLICY_USER_DELETE_LOGS'] !== 'no'))) {?>
+				<?php if ($_SESSION["userContext"] === "admin" || ($_SESSION["userContext"] === "user" && $_SESSION["POLICY_USER_DELETE_LOGS"] !== "no")) { ?>
 					<div class="actions-panel" key-action="js">
 						<a class="data-controls do_delete button button-secondary button-danger">
 							<i class="do_delete fas fa-circle-xmark icon-red"></i><?= _("Delete") ?>
-							<?php if (($_SESSION['userContext'] === 'admin') && (isset($_GET['user']))) {?>
-								<input type="hidden" name="delete_url" value="/delete/log/?user=<?=htmlentities($_GET['user']);?>&token=<?=$_SESSION['token']?>">
+							<?php if ($_SESSION["userContext"] === "admin" && isset($_GET["user"])) { ?>
+								<input type="hidden" name="delete_url" value="/delete/log/?user=<?= htmlentities($_GET["user"]) ?>&token=<?= $_SESSION["token"] ?>">
 							<?php } else { ?>
-								<input type="hidden" name="delete_url" value="/delete/log/?token=<?=$_SESSION['token']?>">
+								<input type="hidden" name="delete_url" value="/delete/log/?token=<?= $_SESSION["token"] ?>">
 							<?php } ?>
 							<div class="dialog js-confirm-dialog-delete" title="<?= _("Confirmation") ?>">
 								<p><?= _("DELETE_LOGS_CONFIRMATION") ?></p>
@@ -84,12 +84,12 @@
 		<div class="l-unit header animate__animated animate__fadeIn">
 			<div class="l-unit__col l-unit__col--right">
 				<div class="clearfix l-unit__stat-col--left super-compact u-text-center">
-					<i class="fas <?=$level_icon;?>"></i>
+					<i class="fas <?= $level_icon ?>"></i>
 				</div>
-				<div class="clearfix l-unit__stat-col--left"><b><?=translate_date($data[$key]['DATE'])?></b></div>
-				<div class="clearfix l-unit__stat-col--left compact-2"><b><?=htmlspecialchars($data[$key]['TIME']);?></b></div>
-				<div class="clearfix l-unit__stat-col--left"><b><?=htmlspecialchars($data[$key]['CATEGORY']);?></b></div>
-				<div class="clearfix l-unit__stat-col--left wide-7"><?=htmlspecialchars($data[$key]['MESSAGE'], ENT_QUOTES);?></div>
+				<div class="clearfix l-unit__stat-col--left"><b><?= translate_date($data[$key]["DATE"]) ?></b></div>
+				<div class="clearfix l-unit__stat-col--left compact-2"><b><?= htmlspecialchars($data[$key]["TIME"]) ?></b></div>
+				<div class="clearfix l-unit__stat-col--left"><b><?= htmlspecialchars($data[$key]["CATEGORY"]) ?></b></div>
+				<div class="clearfix l-unit__stat-col--left wide-7"><?= htmlspecialchars($data[$key]["MESSAGE"], ENT_QUOTES) ?></div>
 			</div>
 		</div>
 	<?php } ?>
@@ -98,7 +98,7 @@
 <footer class="app-footer">
 	<div class="container app-footer-inner">
 		<p>
-			<?php printf(ngettext('%d log record', '%d log records', $i),$i); ?>
+			<?php printf(ngettext("%d log record", "%d log records", $i), $i); ?>
 		</p>
 	</div>
 </footer>

+ 5 - 5
web/templates/pages/list_log_auth.php

@@ -70,12 +70,12 @@
 		<div class="l-unit header animate__animated animate__fadeIn">
 			<div class="l-unit__col l-unit__col--right">
 				<div class="clearfix l-unit__stat-col--left u-text-center">
-					<i class="fas <?=$status_icon;?> u-mr5" title="<?=$status_title;?>"></i>
+					<i class="fas <?= $status_icon ?> u-mr5" title="<?= $status_title ?>"></i>
 				</div>
-				<div class="clearfix l-unit__stat-col--left"><b><?=translate_date($data[$key]['DATE'])?></b></div>
-				<div class="clearfix l-unit__stat-col--left compact-2"><b><?=htmlspecialchars($data[$key]['TIME']);?></b></div>
-				<div class="clearfix l-unit__stat-col--left"><?=htmlspecialchars($data[$key]['IP']);?></div>
-				<div class="clearfix l-unit__stat-col--left wide-7"><?=htmlspecialchars($data[$key]['USER_AGENT']);?></b></div>
+				<div class="clearfix l-unit__stat-col--left"><b><?= translate_date($data[$key]["DATE"]) ?></b></div>
+				<div class="clearfix l-unit__stat-col--left compact-2"><b><?= htmlspecialchars($data[$key]["TIME"]) ?></b></div>
+				<div class="clearfix l-unit__stat-col--left"><?= htmlspecialchars($data[$key]["IP"]) ?></div>
+				<div class="clearfix l-unit__stat-col--left wide-7"><?= htmlspecialchars($data[$key]["USER_AGENT"]) ?></b></div>
 			</div>
 		</div>
 	<?php } ?>

+ 4 - 4
web/templates/pages/list_rrd.php

@@ -6,10 +6,10 @@
 			<a href="/list/server/?cpu" class="button button-secondary"><i class="fas fa-chart-pie icon-green"></i><?= _("show: CPU / MEM / NET / DISK") ?></a>
 		</div>
 		<div class="toolbar-right">
-			<a class="toolbar-link<?php if ((empty($period)) || ($period == 'day')) echo " selected" ?>" href="?period=day"><?= _("Daily") ?></a>
-			<a class="toolbar-link<?php if ((!empty($period)) && ($period == 'week')) echo " selected" ?>" href="?period=week"><?= _("Weekly") ?></a>
-			<a class="toolbar-link<?php if ((!empty($period)) && ($period == 'month')) echo " selected" ?>" href="?period=month"><?= _("Monthly") ?></a>
-			<a class="toolbar-link<?php if ((!empty($period)) && ($period == 'year')) echo " selected" ?>" href="?period=year"><?= _("Yearly") ?></a>
+			<a class="toolbar-link<?php if ((empty($period)) || ($period == 'day')) echo " selected" ?>" href="?period=daily"><?= _("Daily") ?></a>
+			<a class="toolbar-link<?php if ((!empty($period)) && ($period == 'week')) echo " selected" ?>" href="?period=weekly"><?= _("Weekly") ?></a>
+			<a class="toolbar-link<?php if ((!empty($period)) && ($period == 'month')) echo " selected" ?>" href="?period=monthly"><?= _("Monthly") ?></a>
+			<a class="toolbar-link<?php if ((!empty($period)) && ($period == 'year')) echo " selected" ?>" href="?period=yearly"><?= _("Yearly") ?></a>
 		</div>
 	</div>
 </div>

+ 27 - 29
web/templates/pages/list_search.php

@@ -98,12 +98,12 @@
 				</div>
 				<div class="clearfix l-unit__stat-col--left compact-2 u-text-center">
 					<b>
-						<?php if ($status === 'active') {?>
+						<?php if ($status === "active") { ?>
 							<i class="fas fa-circle-check icon-green"></i>
-						<?php	} ?>
-						<?php if ($status === 'suspended') {?>
+						<?php } ?>
+						<?php if ($status === "suspended") { ?>
 							<i class="fas fa-triangle-exclamation icon-orange"></i>
-						<?php	} ?>
+						<?php } ?>
 					</b>
 				</div>
 				<div class="clearfix l-unit__stat-col--left wide-5 truncate">
@@ -125,19 +125,18 @@
 						}
 					?>
 					<b>
-						<?php if (($_SESSION['userContext'] === 'admin') && ($_SESSION['user'] !== 'admin') && ($value['USER'] === 'admin') && ($_SESSION['POLICY_SYSTEM_PROTECTED_ADMIN'] === 'yes')) { ?>
-							<?=$value['RESULT']?>
-						<?} else {
-							if($value['USER'] == $_SESSION['user']){
-							?>
-							<a href="<?=$edit_lnk.'&token='.$_SESSION['token'];?>"><?=$value['RESULT']?></a>
-							<?php
-							}else{
-							?>
-							<a href="/login/?loginas=<?=$value['USER']?>&token=<?=$_SESSION['token']?>&edit_link=<?=urlencode($edit_lnk);?>""><?=$value['RESULT']?></a>
-							<?php
+						<?php
+							if (($_SESSION['userContext'] === 'admin') && ($_SESSION['user'] !== 'admin') && ($value['USER'] === 'admin') && ($_SESSION['POLICY_SYSTEM_PROTECTED_ADMIN'] === 'yes')) {
+								echo $value['RESULT'];
+							} else {
+								if ($value['USER'] == $_SESSION['user']) {
+									$href = $edit_lnk.'&token='.$_SESSION['token'];
+								} else {
+									$href = '/login/?loginas='.$value['USER'].'&token='.$_SESSION['token'].'&edit_link='.urlencode($edit_lnk);
+								}
+								echo '<a href="' . $href . '">' . $value['RESULT'] . '</a>';
 							}
-						} ?>
+						?>
 					</b>
 				</div>
 				<div class="clearfix l-unit__stat-col--left u-text-right compact-3">
@@ -147,19 +146,18 @@
 						</div>
 					</div>
 				</div>
-				<div class="clearfix l-unit__stat-col--left u-text-center"><?=translate_date($value['DATE'])?></div>
-				<div class="clearfix l-unit__stat-col--left u-text-center"><b>
+				<div class="clearfix l-unit__stat-col--left u-text-center"><?= translate_date($value["DATE"]) ?></div>
+				<div class="clearfix l-unit__stat-col--left u-text-center">
+					<b>
 						<a href="/search/?q=<?=htmlentities($_GET['q']); ?>&u=<?=$value['USER']; ?>&token=<?=$_SESSION['token']?>"><?=$value['USER']; ?></a>
-						<?php if (!($_SESSION['POLICY_SYSTEM_HIDE_ADMIN'] === 'yes' && $value['USER'] !== 'admin')){
-						if ($_SESSION['userContext'] === 'admin'){
-						?>
-							<a href="/login/?loginas=<?=$value['USER']?>&token=<?=$_SESSION['token']?>" title="<?= _("login as") ?> <?=$value['USER']?>"><i class="fas fa-right-to-bracket icon-green icon-dim"></i></a>
-						<?php
-						}
-						}
-						?>
-						</b></div>
-				<div class="clearfix l-unit__stat-col--left u-text-center"><?=_($object)?></b></div>
+						<?php if (!($_SESSION['POLICY_SYSTEM_HIDE_ADMIN'] === 'yes' && $value['USER'] !== 'admin') && ($_SESSION['userContext'] === 'admin')) { ?>
+							<a href="/login/?loginas=<?=$value['USER']?>&token=<?=$_SESSION['token']?>" title="<?= _("login as") ?> <?=$value['USER']?>">
+								<i class="fas fa-right-to-bracket icon-green icon-dim"></i>
+							</a>
+						<?php } ?>
+					</b>
+				</div>
+				<div class="clearfix l-unit__stat-col--left u-text-center"><?= _($object) ?></b></div>
 			</div>
 		</div>
 	<?php } ?>
@@ -168,7 +166,7 @@
 <footer class="app-footer">
 	<div class="container app-footer-inner">
 		<p>
-			<?php printf(ngettext('%d object', '%d objects', $i),$i); ?>
+			<?php printf(ngettext("%d object", "%d objects", $i), $i); ?>
 		</p>
 	</div>
 </footer>

+ 4 - 4
web/templates/pages/list_ssl.php

@@ -14,7 +14,7 @@
 
 		<div class="form-container">
 			<h1 class="form-title"><?= _("Generating CSR") ?></h1>
-			<?php show_alert_message($_SESSION);?>
+			<?php show_alert_message($_SESSION); ?>
 			<div
 				x-data="{
 					text: '<?= base64_encode($v_crt) ?>',
@@ -48,7 +48,7 @@
 				class="u-mb20"
 			>
 				<label for="v_key" class="form-label">
-					<?=_("SSL Key");?>
+					<?= _("SSL Key") ?>
 					<a
 						x-bind:href="blob()"
 						download="<?= htmlentities($v_domain) ?>.key"
@@ -71,7 +71,7 @@
 				class="u-mb20"
 			>
 				<label for="v_csr" class="form-label">
-					<?=_("SSL CSR");?>
+					<?= _("SSL CSR") ?>
 					<a
 						x-bind:href="blob()"
 						download="<?= htmlentities($v_domain) ?>.csr"
@@ -86,7 +86,7 @@
 			</div>
 			<div>
 				<button type="button" class="button button-secondary" onclick="<?= $back ?>">
-					<?=_("Back");?>
+					<?= _("Back") ?>
 				</button>
 			</div>
 		</div>

+ 1 - 1
web/templates/pages/login/login.php

@@ -11,7 +11,7 @@
 		<?php show_error_message($error); ?>
 		<div class="u-mb20">
 			<label for="user" class="form-label"><?= _("Username") ?></label>
-			<input type="text" class="form-control" name="user" id="user" autofocus>
+			<input type="text" class="form-control" name="user" id="user" required autofocus>
 		</div>
 		<button type="submit" class="button">
 			<i class="fas fa-right-to-bracket"></i><?= _("Next") ?>

+ 1 - 1
web/templates/pages/login/login_1.php

@@ -18,7 +18,7 @@
 					</a>
 				<?php } ?>
 			</label>
-			<input type="password" class="form-control" name="password" id="password" autofocus>
+			<input type="password" class="form-control" name="password" id="password" required autofocus>
 		</div>
 		<div class="u-side-by-side">
 			<button type="submit" class="button">

+ 1 - 1
web/templates/pages/login/login_2.php

@@ -16,7 +16,7 @@
 					<?= _("Forgot token") ?>
 				</a>
 			</label>
-			<input type="text" class="form-control" name="twofa" id="twofa" autofocus>
+			<input type="text" class="form-control" name="twofa" id="twofa" required autofocus>
 		</div>
 		<div class="u-side-by-side">
 			<button type="submit" class="button">

+ 2 - 2
web/templates/pages/login/login_a.php

@@ -11,7 +11,7 @@
 		<?php show_error_message($error); ?>
 		<div class="u-mb10">
 			<label for="user" class="form-label"><?= _("Username") ?></label>
-			<input type="text" class="form-control" name="user" id="user" autofocus>
+			<input type="text" class="form-control" name="user" id="user" required autofocus>
 		</div>
 		<div class="u-mb20">
 			<label for="password" class="form-label u-side-by-side">
@@ -22,7 +22,7 @@
 					</a>
 				<?php } ?>
 			</label>
-			<input type="password" class="form-control" name="password" id="password" autofocus>
+			<input type="password" class="form-control" name="password" id="password" required autofocus>
 		</div>
 		<button type="submit" class="button">
 			<i class="fas fa-right-to-bracket"></i><?= _("Next") ?>

+ 2 - 2
web/templates/pages/login/reset2fa.php

@@ -23,11 +23,11 @@
 			<?php show_error_message($ERROR); ?>
 			<div class="u-mb10">
 				<label for="user" class="form-label"><?= _("Username") ?></label>
-				<input type="text" class="form-control" name="user" id="user">
+				<input type="text" class="form-control" name="user" id="user" required>
 			</div>
 			<div class="u-mb20">
 				<label for="twofa" class="form-label"><?= _("2FA Reset Code") ?></label>
-				<input type="text" class="form-control" name="twofa" id="twofa">
+				<input type="text" class="form-control" name="twofa" id="twofa" required>
 			</div>
 			<div class="u-side-by-side">
 				<button type="submit" class="button">

+ 2 - 2
web/templates/pages/login/reset_1.php

@@ -10,11 +10,11 @@
 		<?php show_error_message($ERROR); ?>
 		<div class="u-mb10">
 			<label for="user" class="form-label"><?= _("Username") ?></label>
-			<input type="text" class="form-control" name="user" id="user">
+			<input type="text" class="form-control" name="user" id="user" required>
 		</div>
 		<div class="u-mb20">
 			<label for="email" class="form-label"><?= _("Email") ?></label>
-			<input type="email" class="form-control" name="email" id="email">
+			<input type="email" class="form-control" name="email" id="email" required>
 		</div>
 		<div class="u-side-by-side">
 			<button type="submit" class="button">

+ 1 - 1
web/templates/pages/login/reset_2.php

@@ -15,7 +15,7 @@
 			<input type="hidden" name="token" value="<?= htmlentities($_SESSION["token"]) ?>">
 			<input type="hidden" name="user" value="<?= htmlentities($_GET["user"]) ?>">
 			<label for="code" class="form-label"><?= _("Reset Code") ?></label>
-			<input type="text" class="form-control" name="code" id="code">
+			<input type="text" class="form-control" name="code" id="code" required>
 		</div>
 		<div class="u-side-by-side">
 			<button type="submit" class="button">

+ 2 - 2
web/templates/pages/login/reset_3.php

@@ -13,11 +13,11 @@
 			<input type="hidden" name="user" value="<?= htmlentities($_GET["user"]) ?>">
 			<input type="hidden" name="code" value="<?= htmlentities($_GET["code"]) ?>">
 			<label for="password" class="form-label"><?= _("New Password") ?></label>
-			<input type="password" class="form-control" name="password" id="password">
+			<input type="password" class="form-control" name="password" id="password" required>
 		</div>
 		<div class="u-mb20">
 			<label for="password_confirm" class="form-label"><?= _("Confirm Password") ?></label>
-			<input type="password" class="form-control" name="password_confirm" id="password_confirm">
+			<input type="password" class="form-control" name="password_confirm" id="password_confirm" required>
 		</div>
 		<div class="u-side-by-side">
 			<button type="submit" class="button">

+ 1 - 1
web/templates/pages/setup_webapp.php

@@ -12,7 +12,7 @@
 			</a>
 		</div>
 		<div class="toolbar-buttons">
-			<button class="button" type="submit" form="vstobjects">
+			<button type="submit" class="button" form="vstobjects">
 				<i class="fas fa-floppy-disk icon-purple"></i>
 				<?= _("Save") ?>
 			</button>

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 315 - 314
yarn.lock


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio