Просмотр исходного кода

Merge branch 'main' into feature/debian_11_support

Jaap Marcus 4 лет назад
Родитель
Сommit
638be8c1d0
100 измененных файлов с 2606 добавлено и 2025 удалено
  1. 91 0
      .drone.yml
  2. 71 18
      CHANGELOG.md
  3. 2 2
      README.md
  4. 11 0
      bin/v-add-database
  5. 2 2
      bin/v-add-mail-domain-ssl
  6. 4 0
      bin/v-add-mail-domain-webmail
  7. 91 0
      bin/v-add-sys-phpmailer
  8. 23 23
      bin/v-add-sys-roundcube
  9. 59 0
      bin/v-add-sys-smtp
  10. 1 1
      bin/v-add-user
  11. 5 1
      bin/v-change-database-user
  12. 4 0
      bin/v-change-sys-ip-helo
  13. 26 10
      bin/v-delete-firewall-ban
  14. 7 0
      bin/v-delete-sys-ip
  15. 48 0
      bin/v-delete-sys-smtp
  16. 4 4
      bin/v-list-mail-domain-dkim-dns
  17. 19 1
      bin/v-list-sys-config
  18. 6 6
      func/db.sh
  19. 39 34
      func/domain.sh
  20. 7 2
      func/ip.sh
  21. 35 0
      func/syshealth.sh
  22. 0 5
      func/upgrade.sh
  23. 4 3
      install/deb/dovecot/conf.d/10-ssl.conf
  24. 1 1
      install/deb/php-fpm/multiphp.tpl
  25. 1 1
      install/deb/proftpd/tls.conf
  26. 2 11
      install/deb/templates/mail/apache2/disabled.stpl
  27. 2 13
      install/deb/templates/mail/apache2/disabled.tpl
  28. 7 19
      install/deb/templates/mail/nginx/default_disabled.stpl
  29. 11 26
      install/deb/templates/mail/nginx/default_disabled.tpl
  30. 5 7
      install/deb/templates/web/nginx/caching.sh
  31. 15 4
      install/deb/templates/web/nginx/caching.stpl
  32. 15 4
      install/deb/templates/web/nginx/caching.tpl
  33. 0 16
      install/deb/templates/web/nginx/php-fpm/craftcms.stpl
  34. 0 16
      install/deb/templates/web/nginx/php-fpm/craftcms.tpl
  35. 4 4
      install/deb/templates/web/nginx/php-fpm/no-php.stpl
  36. 4 4
      install/deb/templates/web/nginx/php-fpm/no-php.tpl
  37. 41 7
      install/hst-install-debian.sh
  38. 37 6
      install/hst-install-ubuntu.sh
  39. 0 15
      install/rhel/templates/web/nginx/php-fpm/craftcms.stpl
  40. 0 15
      install/rhel/templates/web/nginx/php-fpm/craftcms.tpl
  41. 81 0
      install/upgrade/manual/configure-server-smtp.sh
  42. 3 0
      install/upgrade/upgrade.conf
  43. 21 0
      install/upgrade/versions/1.4.8.sh
  44. 7 0
      install/upgrade/versions/1.4.9.sh
  45. 1 1
      src/deb/hestia/control
  46. 10 5
      src/deb/hestia/postinst
  47. 1 1
      src/deb/php/control
  48. 3 8
      src/hst_autocompile.sh
  49. 3 3
      test/check_php.sh
  50. 81 0
      test/config-tests.bats
  51. 536 0
      test/restore.bats
  52. 396 501
      test/test.bats
  53. 3 2
      web/add/db/index.php
  54. 3 2
      web/add/mail/index.php
  55. 3 2
      web/add/user/index.php
  56. 3 2
      web/add/web/index.php
  57. 1 1
      web/add/webapp/index.php
  58. 0 550
      web/css/dependencies/jquery-custom-dialogs.css
  59. 2 0
      web/css/dependencies/jquery-ui.custom.min.css
  60. 150 0
      web/css/src/dependencies/jquery-ui.custom.css
  61. 1 1
      web/css/src/themes/dark.css
  62. 26 26
      web/css/src/themes/default.css
  63. 1 1
      web/css/src/themes/vestia.css
  64. 0 0
      web/css/themes/dark.min.css
  65. 0 0
      web/css/themes/default.min.css
  66. 0 0
      web/css/themes/vestia.min.css
  67. 3 2
      web/edit/mail/index.php
  68. 9 5
      web/edit/server/index.php
  69. 6 4
      web/edit/web/index.php
  70. 5 0
      web/inc/composer.json
  71. 95 0
      web/inc/composer.lock
  72. 0 1
      web/inc/jquery/jquery-3.5.1.min.js
  73. 3 2
      web/inc/mail-wrapper.php
  74. 38 15
      web/inc/main.php
  75. 5 5
      web/js/events.js
  76. 2 2
      web/js/init.js
  77. 0 1
      web/js/jquery/jquery-1.7.2.min.js
  78. 0 4
      web/js/jquery/jquery-ui-1.8.20.custom.min.js
  79. 5 0
      web/js/jquery/jquery-ui.min.js
  80. 2 2
      web/js/jquery/jquery.finder.js
  81. 2 2
      web/js/pages/add_user.js
  82. 2 2
      web/js/pages/add_web.js
  83. 1 1
      web/js/pages/edit_mail.js
  84. 10 6
      web/js/pages/edit_web.js
  85. BIN
      web/locale/ar/LC_MESSAGES/hestiacp.mo
  86. BIN
      web/locale/az/LC_MESSAGES/hestiacp.mo
  87. BIN
      web/locale/bg/LC_MESSAGES/hestiacp.mo
  88. BIN
      web/locale/bs/LC_MESSAGES/hestiacp.mo
  89. BIN
      web/locale/cs/LC_MESSAGES/hestiacp.mo
  90. BIN
      web/locale/da/LC_MESSAGES/hestiacp.mo
  91. BIN
      web/locale/de/LC_MESSAGES/hestiacp.mo
  92. BIN
      web/locale/el/LC_MESSAGES/hestiacp.mo
  93. BIN
      web/locale/en/LC_MESSAGES/hestiacp.mo
  94. BIN
      web/locale/es/LC_MESSAGES/hestiacp.mo
  95. BIN
      web/locale/fa/LC_MESSAGES/hestiacp.mo
  96. BIN
      web/locale/fi/LC_MESSAGES/hestiacp.mo
  97. BIN
      web/locale/fr/LC_MESSAGES/hestiacp.mo
  98. 378 584
      web/locale/hestiacp.pot
  99. BIN
      web/locale/hr/LC_MESSAGES/hestiacp.mo
  100. BIN
      web/locale/hu/LC_MESSAGES/hestiacp.mo

+ 91 - 0
.drone.yml

@@ -0,0 +1,91 @@
+---
+kind: pipeline
+type: ssh
+name: HestiaCP + Nginx + Apache2  
+
+concurrency:
+  limit: 1
+
+server:
+  host:
+    from_secret: server_address
+  user: 
+    from_secret: username
+  ssh_key: 
+    from_secret: ssh_key
+
+platform:
+  os: linux
+  arch: amd64
+   
+steps:
+- name: Download submodules
+  image: alpine/git
+  commands:
+  - git submodule update --init --recursive
+- name: Build Hestia package and install
+  commands:
+  - ./src/hst_autocompile.sh --hestia --install '~localsrc'
+- name: Run system / user tests
+  commands:
+  - bats ./test/test.bats
+- name: Run restore tests
+  commands:
+  - bats ./test/restore.bats
+- name: Run config tests 
+  commands:
+  - bats ./test/config-tests.bats
+- name: Run Check PHP
+  commands: 
+  - ./test/check_php.sh
+
+trigger:
+  event: [ push, pull_request ]
+
+---
+kind: pipeline
+type: ssh
+name: HestiaCP + Nginx  
+
+concurrency:
+  limit: 1
+
+server:
+  host:
+    from_secret: server_address2
+  user: 
+    from_secret: username
+  ssh_key: 
+    from_secret: ssh_key
+
+platform:
+  os: linux
+  arch: amd64
+   
+steps:
+- name: Download submodules
+  image: alpine/git
+  commands:
+  - git submodule update --init --recursive
+- name: Build Hestia package install
+  commands:
+  - ./src/hst_autocompile.sh --hestia --install '~localsrc'
+- name: Run system / user tests
+  commands:
+  - bats ./test/test.bats
+- name: Run restore tests
+  commands:
+  - bats ./test/restore.bats
+- name: Run config tests 
+  commands:
+  - bats ./test/config-tests.bats
+- name: Run Check PHP
+  commands: 
+  - ./test/check_php.sh
+
+trigger:
+  event: [ push, pull_request ]
+
+---
+kind: signature
+hmac: bca7f80ac6198662bc658235d7345485213847f1c00f027e1439775e02776bc7

+ 71 - 18
CHANGELOG.md

@@ -1,12 +1,65 @@
 # Changelog
 All notable changes to this project will be documented in this file.
 
+## [Development]
+
+### Features
+
+### Bugfixes
+
+- Improve handling upgrade of Roundcube #1917
+
+## [1.4.10] - Service release 
+
+### Features
+
+- Added v-delete-firewall-ban ip all #2031
+- Include config tests for nginx/apache2 templates
+
+### Bugfixes
+
+- Fixed UI issues after upgrade jQuery + jQuery UI to last version (#2021 and #2032) + [forum](https://forum.hestiacp.com/t/confusion-about-send-welcome-email-checkbox/4259/11)
+- Fixed security issues in caching templates of Nginx when used as Reverse Proxy
+- Fixed an issue with deleting multiple mail accounts (#2047)
+- Fixed an issue with phpmailer + non latin characters (#2050) thanks @Faymir 
+
+## [1.4.9] - Service release 
+
+### Bugfixes
+
+- Updated jQuery and jQuery UI to the latest version due to a vulnerability in jQuery. @dependabot
+- Fixed bug in /etc/dovecot/conf.d/10-ssl.conf for new installs
+- Fixed bug with notifications
+- Fixed translation string @myrevery 
+
+## [1.4.8] - Service release 
+
+### Features
+
+- Add support for automated testing for HestiaCP code with @drone
+- Add support for SMTP server for internal email #1988 @Myself5 / #1165
+
+### Bugfixes
+
+- Updated jQuery and jQuery UI to the latest version due to a vulnerability in jQuery. @dependabot
+- Resolve issue with double ENFORCE_SUBDOMAIN_OWNERSHIP keys in hestia.conf
+- Resolve issue with create new user during install in some cases #2000
+- Fixed an issue with Quick Install apps named Test123 (@PsychotherapistSam)
+- Fix an issue with dovecot 2.3 ssl config (#1432)
+- Load $HESTIA path during upgrade script (#1698)
+- Remove TLS 1.1 from Proftpd config (#950)
+- Don't remove postfix when Exim is not installed (#1995)
+- Fix a bug in no-php Nginx FPM template (##2007)
+- Update German translations
+- Fixed a few minor error in Mail DMS records (#2005)
+
+
 ## [1.4.7] - Service release 
 
 ### Bugfixes
 
-- Fix #1984 phppgadmin not working on apache2 systems
-- Fix #1985 Restart service not working
+- Fixed #1984 phppgadmin not working on apache2 systems
+- Fixed #1985 Restart service not working
 
 
 ## [1.4.6] - Service release 
@@ -19,18 +72,18 @@ All notable changes to this project will be documented in this file.
 
 ### Bugfixes
 
-- Fix #1961 Renewal Apache2 only SSL certificate fails
+- Fixed #1961 Renewal Apache2 only SSL certificate fails
 - Fixed #1956 to prevent reset of defined webmail client.
 - Explicitly disable cron reports #1978 
 - Fixed an issue where in rare cases certificate failed to install @dpeca and @myvesta
 - Fixed an issue where composer failed to install when .composer folder is missing
-- Fix #1980 Lets Encrypt Auto Renewal Reverts Webmail Client back to Roundcube
+- Fixed #1980 Lets Encrypt Auto Renewal Reverts Webmail Client back to Roundcube
 
 ## [1.4.5] - Service release
 
 ### Bugfixes
 
-- Revert #1943 and rework it to fix possible errors occuring on v-rebuild-cron-jobs.
+- Revert #1943 and rework it to fix possible errors occurring on v-rebuild-cron-jobs.
 - Fixed #1956 to prevent reset of defined webmail client.
 - Explicitly disable cron reports #1978
 
@@ -45,15 +98,15 @@ All notable changes to this project will be documented in this file.
 ### Bugfixes
 
 - Add template for when webmail is disabled allowing to generate SSL. 
-- Fix PHP bug in /list/log/ 
-- Fix issue with time in /list/services as it was showing as 50 minute1 instead of minutes
-- Add missing back buttons + fix behavoir of back buttons on login page. 
+- Fixed PHP bug in /list/log/ 
+- Fixed issue with time in /list/services as it was showing as 50 minute1 instead of minutes
+- Add missing back buttons + fix behaviour of back buttons on login page. 
 - Set "default" when WEB_TEMPLATE and PROXY_TEMPLATE is missing in user.conf 
 - Add BACKEND_TEMPLATE to default package
-- Fix possible error occur for v-rebuild-cron-jobs #1943 (thanks @clarkchentw)
-- Restrict access Filemanager when SSH is enabled for the user (@bet0x)
+- Fixed possible error occur for v-rebuild-cron-jobs #1943 (thanks @clarkchentw)
+- Restrict access file manager when SSH is enabled for the user (@bet0x)
 - Check for DNS domains when running v-change-sys-ip-nat (@clarkchentw)
-- Fix logical error in installer (@clarkchentw)
+- Fixed logical error in installer (@clarkchentw)
 
 ## [1.4.3] - Service release
 
@@ -99,10 +152,10 @@ Then run the update via
 
 ### Bugfixes
 
-- Fix issue wit startup script for iptables / network (#1849) (@myrevery)
-- Fix problem with accidentally replacing nginx.conf during upgrade nginx (#1878 / @myrevery)
-- Fix issue with installing Ubuntu 18.04
-- Fix issue with login into file manger as admin user
+- Fixed issue wit startup script for iptables / network (#1849) (@myrevery)
+- Fixed problem with accidentally replacing nginx.conf during upgrade nginx (#1878 / @myrevery)
+- Fixed issue with installing Ubuntu 18.04
+- Fixed issue with login into file manger as admin user
 - Added proxy_extentions back to support older custom templates
 - Added the possibility to skip the forced reboot when interactive is set to no
 - Fixed an issue with modx template
@@ -539,7 +592,7 @@ Then run the update via
 - Remove broken /webmail alias from previous versions.
 - Webmail IP address is now inherited from web domain when using multiple IPs.
 - Exim now uses the web domain IP if it exists.
-- Fix incorrect MX record for DNS domains using the Office 365 template.
+- Fixed incorrect MX record for DNS domains using the Office 365 template.
 
 ## [1.0.6] - 2019-09-24 - Hotfix
 ### Bugfixes
@@ -547,9 +600,9 @@ Then run the update via
 
 ## [1.0.5] - 2019-08-06 - Hotfix
 ### Bugfixes
-- Fix several security issues, thanks to Andrea Cardaci (https://cardaci.xyz/)
+- Fixed several security issues, thanks to Andrea Cardaci (https://cardaci.xyz/)
 - Rework Let's Encrypt ACME staging to use hestia conform standard.
-- Fix if condition, use nginx for Let's Encrypt ACME request if present.
+- Fixed if condition, use nginx for Let's Encrypt ACME request if present.
 
 ## [1.0.4] - 2019-07-09 - Hotfix
 ### Bugfixes

+ 2 - 2
README.md

@@ -2,13 +2,13 @@
 
 [Hestia Control Panel](https://www.hestiacp.com/)
 ==================================================
-**Latest stable release:** Version 1.4.7 | [View Changelog](https://github.com/hestiacp/hestiacp/blob/release/CHANGELOG.md)<br>
+**Latest stable release:** Version 1.4.10 | [View Changelog](https://github.com/hestiacp/hestiacp/blob/release/CHANGELOG.md) | [![Build Status](https://drone.hestiacp.com/api/badges/hestiacp/hestiacp/status.svg?ref=refs/heads/main)](https://drone.hestiacp.com/hestiacp/hestiacp) <br>
 
 **Web:** [www.hestiacp.com](https://www.hestiacp.com/)<br>
 **Documentation:** [docs.hestiacp.com](https://docs.hestiacp.com/)<br>
 **Forums:** [forum.hestiacp.com](https://forum.hestiacp.com/)<br>
 **Discord:** [Join the discussion](https://discord.gg/nXRUZch)<br />
-<br>
+<br><br>
 [![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ST87LQH2CHGLA)
 <br>
 

+ 11 - 0
bin/v-add-database

@@ -58,6 +58,17 @@ is_object_unsuspended "../../../conf/$type" 'DBHOST' "$host"
 #is_charset_valid
 is_package_full 'DATABASES'
 is_password_valid
+
+if [ "$type" = "pgsql" ]; then 
+   exclude="-"
+    if [[ "$dbuser" =~ $exclude ]]; then
+        check_result $E_INVALID "invalid database user format"
+    fi
+    if [[ "$database" =~ $exclude ]]; then
+      check_result $E_INVALID "invalid database format"
+    fi
+fi
+
 dbpass="$password"
 
 # Perform verification if read-only mode is enabled

+ 2 - 2
bin/v-add-mail-domain-ssl

@@ -78,7 +78,7 @@ fi
 # Call routine to add SSL configuration to mail domain
 add_mail_ssl_config
 
-if [ "$webmail" == "roundcube" ]; then
+if [ "$WEBMAIL" == "roundcube" ]; then
     WEBMAIL_TEMPLATE="default"
     if [ ! -z "$PROXY_SYSTEM" ]; then
         PROXY_TEMPLATE="default"
@@ -88,7 +88,7 @@ if [ "$webmail" == "roundcube" ]; then
     if [ "$WEB_SYSTEM" = "nginx" ]; then
         WEBMAIL_TEMPLATE="web_system"
     fi
-elif [ "$webmail" == "rainloop" ]; then
+elif [ "$WEBMAIL" == "rainloop" ]; then
     WEBMAIL_TEMPLATE="rainloop"
     if [ ! -z "$PROXY_SYSTEM" ]; then
         PROXY_TEMPLATE="default_rainloop"

+ 4 - 0
bin/v-add-mail-domain-webmail

@@ -20,6 +20,10 @@ webmail=$3
 restart="$4"
 quiet=$5
 
+if [ -z "$restart" ]; then 
+    restart="yes"
+fi
+
 # Additional argument formatting
 if [[ "$domain" =~ [[:upper:]] ]]; then
     domain=$(echo "$domain" |tr '[:upper:]' '[:lower:]')

+ 91 - 0
bin/v-add-sys-phpmailer

@@ -0,0 +1,91 @@
+#!/bin/bash
+# info: add PHPMailer functionality to Hestia Control Panel
+# options: [MODE]
+# labels: hestia
+#
+# The function installs PHPMailer for Server sided email communication
+
+#----------------------------------------------------------#
+#                    Variable&Function                     #
+#----------------------------------------------------------#
+
+# Includes
+# shellcheck source=/usr/local/hestia/func/main.sh
+source $HESTIA/func/main.sh
+# shellcheck source=/usr/local/hestia/conf/hestia.conf
+source $HESTIA/conf/hestia.conf
+# shellcheck source=/usr/local/hestia/install/upgrade/upgrade.conf
+source $HESTIA/install/upgrade/upgrade.conf
+
+MODE=$1
+user="admin"
+
+PM_INSTALL_DIR="$HESTIA/web/inc"
+COMPOSER_BIN="$HOMEDIR/$user/.composer/composer"
+
+
+#----------------------------------------------------------#
+#                    Verifications                         #
+#----------------------------------------------------------#
+
+# Checking root permissions
+if [ "x$(id -u)" != 'x0' ]; then
+    echo "ERROR: v-add-sys-phpmailer can be run executed only by root user"
+    exit 10
+fi
+
+# Ensure that $HESTIA (/usr/local/hestia/) and other variables are valid.
+if [ -z "$HESTIA" ]; then
+    HESTIA="/usr/local/hestia"
+fi
+
+if [ -z "$HOMEDIR" ] || [ -z "$HESTIA_INSTALL_DIR" ]; then
+    echo "ERROR: Environment variables not present, installation aborted."
+    exit 2
+fi
+
+# Ensure that Composer is installed for the user before continuing as it is a dependency of the PHPMailer.
+if [ ! -f "$COMPOSER_BIN" ]; then
+    $BIN/v-add-user-composer "$user"
+    if [ $? -ne 0 ]; then
+        $BIN/v-add-user-notification admin 'Composer installation failed!' '<b>PHPMailer will not work without Composer.</b><br><br>Please try running the installer manually from a shell session:<br>v-add-sys-phpmailer<br><br>If this continues, open an issue report on <a href="https://github.com/hestiacp/hestiacp/issues" target="_new"><i class="fab fa-github"></i> GitHub</a>.'
+        exit 1
+    fi
+fi
+
+# Perform verification if read-only mode is enabled
+check_hestia_demo_mode
+
+#----------------------------------------------------------#
+#                       Action                             #
+#----------------------------------------------------------#
+
+cd "$PM_INSTALL_DIR"
+rm --recursive --force ${PM_INSTALL_DIR}/vendor
+mkdir -p ${PM_INSTALL_DIR}/vendor
+chown $user: -R ${PM_INSTALL_DIR}/vendor
+
+COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/bin/php $COMPOSER_BIN --quiet --no-dev install
+
+# Check if installation was successful, if not abort script and throw error message notification and clean-up
+if [ $? -ne 0 ]; then
+    echo "ERROR: PHPMailer installation failed!"
+    echo "Please report this to our development team:"
+    echo "https://github.com/hestiacp/hestiacp/issues"
+    $BIN/v-add-user-notification admin 'PHPMailer installation failed!' 'Please report this to our development team on <a href="https://github.com/hestiacp/hestiacp/issues" target="_new"><i class="fab fa-github"></i> GitHub</a>.'
+    # Installation failed, clean up files
+    rm --recursive --force ${PM_INSTALL_DIR}/vendor
+    $BIN/v-change-sys-config-value 'USE_SERVER_SMTP' 'n'
+    $BIN/v-log-action "system" "Error" "Plugins" "PHPMailer installation failed (Version: $pm_v)."
+    exit 1
+fi
+
+# Set permissions
+chown root: -R "${PM_INSTALL_DIR}/vendor"
+
+#----------------------------------------------------------#
+#                       Logging                            #
+#----------------------------------------------------------#
+
+$BIN/v-log-action "system" "Info" "Plugins" "PHPMailer enabled (Version: $pm_v)."
+log_event "$OK" "$ARGUMENTS"

+ 23 - 23
bin/v-add-sys-roundcube

@@ -89,7 +89,7 @@ if [ "$UPDATE" == "no" ]; then
     [ ! -f "${RC_INSTALL_DIR}/${RC_FILE}" ] && wget "$RC_URL" --retry-connrefused --quiet -O "${RC_INSTALL_DIR}/${RC_FILE}"
     
     tar xzf $RC_FILE
-    cp -rf $RC_EXTRACT/* $RC_INSTALL_DIR
+    cp -rT $RC_EXTRACT $RC_INSTALL_DIR
     
     # Delete old config folder
     cp $RC_INSTALL_DIR/config/defaults.inc.php $RC_CONFIG_DIR/defaults.inc.php
@@ -111,11 +111,20 @@ if [ "$UPDATE" == "no" ]; then
     ln -s $RC_CONFIG_DIR/plugins/newmail_notifier/config.inc.php ./plugins/newmail_notifier/config.inc.php
     cp -f $HESTIA_INSTALL_DIR/roundcube/plugins/config_zipdownload.inc.php $RC_CONFIG_DIR/plugins/zipdownload/config.inc.php
     ln -s $RC_CONFIG_DIR/plugins/zipdownload/config.inc.php ./plugins/zipdownload/config.inc.php
+    # Set up correct permissions roundcube    
+    chown -R root:www-data $RC_CONFIG_DIR/
+    chmod 751 -R $RC_CONFIG_DIR    
+    chmod 644 $RC_CONFIG_DIR/config.inc.php
+    chmod 644 $RC_CONFIG_DIR/plugins/password/config.inc.php
+    chmod 644 $RC_CONFIG_DIR/plugins/newmail_notifier/config.inc.php
+    chmod 644 $RC_CONFIG_DIR/plugins/zipdownload/config.inc.php
     
+    # Add robots.txt
+    echo "User-agent: *" > /var/lib/roundcube/robots.txt
+    echo "Disallow: /" >> /var/lib/roundcube/robots.txt
     
-    chmod 640 $RC_CONFIG_DIR/config.inc.php
-    chown root:www-data $RC_CONFIG_DIR/config.inc.php
-    
+    chown -R root:www-data $RC_INSTALL_DIR
+  
     # Log file 
     if [ ! -d  $RC_LOG ];then
         mkdir $RC_LOG
@@ -146,10 +155,6 @@ if [ "$UPDATE" == "no" ]; then
     rm -f -r $RC_INSTALL_DIR/$RC_FILE;
     rm -f -r $RC_INSTALL_DIR/$RC_EXTRACT;
     
-    # Add robots.txt
-    echo "User-agent: *" > /var/lib/roundcube/robots.txt
-    echo "Disallow: /" >> /var/lib/roundcube/robots.txt
-    
     # Updating hestia.conf
     if [ -z "$(grep WEBMAIL_SYSTEM $HESTIA/conf/hestia.conf)" ]; then
         $BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' 'roundcube'
@@ -165,27 +170,22 @@ if [ "$UPDATE" == "no" ]; then
     
     phpenmod mcrypt > /dev/null 2>&1
 else
-    rm  -f -r $RC_INSTALL_DIR
-    mkdir $RC_INSTALL_DIR
     cd "$RC_INSTALL_DIR"
     [ ! -f "${RC_INSTALL_DIR}/${RC_FILE}" ] && wget "$RC_URL" --quiet -O "${RC_INSTALL_DIR}/${RC_FILE}"
     
     tar xzf $RC_FILE
-    cp -rf $RC_EXTRACT/* $RC_INSTALL_DIR
     
-    cp -f $RC_INSTALL_DIR/config/defaults.inc.php $RC_CONFIG_DIR/defaults.inc.php
-    rm -f -r $RC_INSTALL_DIR/config/
-    ln -s $RC_CONFIG_DIR/ ./config
-
-    ln -s $RC_CONFIG_DIR/plugins/password/config.inc.php ./plugins/password/config.inc.php
-    ln -s $RC_CONFIG_DIR/plugins/newmail_notifier/config.inc.php ./plugins/newmail_notifier/config.inc.php
-    ln -s $RC_CONFIG_DIR/plugins/zipdownload/config.inc.php ./plugins/zipdownload/config.inc.php  
+    # Run Roundcube upgrade script
+    $RC_INSTALL_DIR/$RC_EXTRACT/bin/installto.sh -y $RC_INSTALL_DIR > /dev/null 2>&1
+    $RC_INSTALL_DIR/bin/update.sh --version "$version" > /dev/null 2>&1
+    chown -R root:www-data $RC_INSTALL_DIR
     
-    $RC_INSTALL_DIR/bin/update.sh --version "$version"
-        
-    rm -f -r $RC_INSTALL_DIR/installer;
-    rm -f -r $RC_INSTALL_DIR/$RC_FILE;
-    rm -f -r $RC_INSTALL_DIR/$RC_EXTRACT;  
+    #clean up the mess
+    if [ -d "$RC_INSTALL_DIR/installer" ]; then
+        rm -f -r $RC_INSTALL_DIR/installer
+    fi
+    rm -f -r $RC_INSTALL_DIR/$RC_FILE
+    rm -f -r $RC_INSTALL_DIR/$RC_EXTRACT
 fi
 #----------------------------------------------------------#
 #                       Logging                            #

+ 59 - 0
bin/v-add-sys-smtp

@@ -0,0 +1,59 @@
+#!/bin/bash
+# info: Add SMTP Account for logging, notification and internal mail
+# options: DOMAIN PORT SMTP_SECURITY USERNAME PASSWORD EMAIL
+# labels:
+#
+# example: v-add-sys-smtp example.com 587 STARTTLS [email protected] securepassword [email protected]
+#
+# This function allows configuring a SMTP account for the server to use
+# for logging, notification and warn emails etc.
+
+#----------------------------------------------------------#
+#                    Variable&Function                     #
+#----------------------------------------------------------#
+
+# Argument definition
+domain=$1
+port=$2
+smtp_security=$3
+username=$4
+password=$5
+email=$6
+
+# Includes
+# shellcheck source=/usr/local/hestia/func/main.sh
+source $HESTIA/func/main.sh
+# shellcheck source=/usr/local/hestia/conf/hestia.conf
+source $HESTIA/conf/hestia.conf
+
+#----------------------------------------------------------#
+#                    Verifications                         #
+#----------------------------------------------------------#
+
+check_args '6' "$#" 'DOMAIN PORT SMTP_SECURITY USERNAME PASSWORD EMAIL'
+is_format_valid 'domain' 'port' 'email'
+
+# Perform verification if read-only mode is enabled
+check_hestia_demo_mode
+
+#----------------------------------------------------------#
+#                       Action                             #
+#----------------------------------------------------------#
+
+$BIN/v-change-sys-config-value "USE_SERVER_SMTP" 'true'
+$BIN/v-change-sys-config-value "SERVER_SMTP_HOST" $domain
+$BIN/v-change-sys-config-value "SERVER_SMTP_PORT" $port
+$BIN/v-change-sys-config-value "SERVER_SMTP_SECURITY" $smtp_security
+$BIN/v-change-sys-config-value "SERVER_SMTP_USER" $username
+$BIN/v-change-sys-config-value "SERVER_SMTP_PASSWD" $password
+$BIN/v-change-sys-config-value "SERVER_SMTP_ADDR" $email
+
+#----------------------------------------------------------#
+#                       Hestia                             #
+#----------------------------------------------------------#
+
+# Logging
+$BIN/v-log-action "system" "Info" "Mail" "Server SMTP enabled."
+log_event "$OK" "$ARGUMENTS"
+
+exit

+ 1 - 1
bin/v-add-user

@@ -64,7 +64,7 @@ shell_conf=$(echo "$pkg_data" | grep 'SHELL' | cut -f 2 -d \')
 shell=$(grep -w "$shell_conf" /etc/shells |head -n1)
 
 # Adding user
-/usr/sbin/useradd "$user" -s "$shell" -c "$email" -m -d "$HOMEDIR/$user"
+/usr/sbin/useradd "$user" -s "$shell" -c "$email" -m -d "$HOMEDIR/$user" -U
 check_result $? "user creation failed" $E_INVALID
 
 # Adding password

+ 5 - 1
bin/v-change-database-user

@@ -65,7 +65,11 @@ get_database_values
 
 #Fix issue #1084 with "Upper case not allowed with PGSQL"
 if [ "$TYPE" = "pgsql" ]; then
-   dbuser=$(echo $dbuser | tr '[:upper:]' '[:lower:]'); 
+   dbuser=$(echo $dbuser | tr '[:upper:]' '[:lower:]');
+   exclude="-"
+    if [[ "$dbuser" =~ $exclude ]]; then
+        check_result $E_INVALID "invalid database user format"
+    fi
 fi
 
 # Rebuild database

+ 4 - 0
bin/v-change-sys-ip-helo

@@ -26,6 +26,10 @@ if [ -z "$MAIL_SYSTEM" ]; then
     check_result "$E_NOTEXIST" "Mail system not installed"
 fi
 
+if [ ! -e "$HESTIA/data/ips/$ip" ]; then 
+    exit;
+fi
+
 #----------------------------------------------------------#
 #                    Verifications                         #
 #----------------------------------------------------------#

+ 26 - 10
bin/v-delete-firewall-ban

@@ -50,19 +50,35 @@ check_hestia_demo_mode
 # Self heal iptables links
 heal_iptables_links
 
-# Checking ip in banlist
 conf="$HESTIA/data/firewall/banlist.conf"
-check_ip=$(grep "IP='$ip' CHAIN='$chain'" $conf 2>/dev/null)
-if [ -z "$check_ip" ]; then
-    exit
+if [ "$chain" == "ALL" ]; then  
+    check_ip=$(grep  "IP='$ip' CHAIN='*'" $conf)
+    if [ -z  "$check_ip" ]; then 
+        exit;
+    fi
+    grep  "IP='$ip' CHAIN='*'" $conf | while read -r line ; do
+        parse_object_kv_list  $line
+        
+        # Deleting ip from banlist
+        sip=$(echo "$IP"| sed "s|/|\\\/|g")
+        sed -i "/IP='$sip' CHAIN='$CHAIN'/d" $conf
+        b=$($iptables -L fail2ban-$CHAIN --line-number -n|grep -w $ip|awk '{print $1}')
+        $iptables -D fail2ban-$CHAIN $b 2>/dev/null   
+    done  
+else
+    # Checking ip in banlist
+    check_ip=$(grep "IP='$ip' CHAIN='$chain'" $conf 2>/dev/null)
+    if [ -z "$check_ip" ]; then
+        exit
+    fi
+    
+    # Deleting ip from banlist
+    sip=$(echo "$ip"| sed "s|/|\\\/|g")
+    sed -i "/IP='$sip' CHAIN='$chain'/d" $conf
+    b=$($iptables -L fail2ban-$chain --line-number -n|grep -w $ip|awk '{print $1}')
+    $iptables -D fail2ban-$chain $b 2>/dev/null
 fi
 
-# Deleting ip from banlist
-sip=$(echo "$ip"| sed "s|/|\\\/|g")
-sed -i "/IP='$sip' CHAIN='$chain'/d" $conf
-b=$($iptables -L fail2ban-$chain --line-number -n|grep -w $ip|awk '{print $1}')
-$iptables -D fail2ban-$chain $b 2>/dev/null
-
 # Changing permissions
 chmod 660 $conf
 

+ 7 - 0
bin/v-delete-sys-ip

@@ -126,6 +126,13 @@ if [ ! -z "$PROXY_SYSTEM" ]; then
     fi
 fi
 
+if [ ! -z "$MAIL_SYSTEM" ]; then
+    if [ -z "$NAT" ]; then 
+        delete_ip_helo_value $ip
+    else
+        delete_ip_helo_value $NAT
+    fi
+fi
 
 #----------------------------------------------------------#
 #                       Hestia                             #

+ 48 - 0
bin/v-delete-sys-smtp

@@ -0,0 +1,48 @@
+#!/bin/bash
+# info: Remove SMTP Account for logging, notification and internal mail
+# options: NONE
+# labels:
+#
+# example: v-delete-sys-smtp
+#
+# This function allows configuring a SMTP account for the server to use
+# for logging, notification and warn emails etc.
+
+#----------------------------------------------------------#
+#                    Variable&Function                     #
+#----------------------------------------------------------#
+
+# Includes
+# shellcheck source=/usr/local/hestia/func/main.sh
+source $HESTIA/func/main.sh
+# shellcheck source=/usr/local/hestia/conf/hestia.conf
+source $HESTIA/conf/hestia.conf
+
+#----------------------------------------------------------#
+#                    Verifications                         #
+#----------------------------------------------------------#
+
+# Perform verification if read-only mode is enabled
+check_hestia_demo_mode
+
+#----------------------------------------------------------#
+#                       Action                             #
+#----------------------------------------------------------#
+
+$BIN/v-change-sys-config-value "USE_SERVER_SMTP" 'false'
+$BIN/v-change-sys-config-value "SERVER_SMTP_HOST" ''
+$BIN/v-change-sys-config-value "SERVER_SMTP_PORT" ''
+$BIN/v-change-sys-config-value "SERVER_SMTP_SECURITY" ''
+$BIN/v-change-sys-config-value "SERVER_SMTP_USER" ''
+$BIN/v-change-sys-config-value "SERVER_SMTP_PASSWD" ''
+$BIN/v-change-sys-config-value "SERVER_SMTP_ADDR" ''
+
+#----------------------------------------------------------#
+#                       Hestia                             #
+#----------------------------------------------------------#
+
+# Logging
+$BIN/v-log-action "system" "Info" "Mail" "Server SMTP disabled."
+log_event "$OK" "$ARGUMENTS"
+
+exit

+ 4 - 4
bin/v-list-mail-domain-dkim-dns

@@ -30,7 +30,7 @@ json_list() {
     echo -e "\t},"
     echo -e "\n\t\"mail._domainkey\": {"
     echo "            \"TTL\": \"3600\","
-    echo "            \"TXT\": \"\\\"$pub\\\"\""
+    echo "            \"TXT\": \"'v=DKIM1; k=rsa; p=$pub'\""
     echo -e "\t}\n}"
 }
 
@@ -39,20 +39,20 @@ shell_list() {
     echo "RECORD            TTL         TYPE      VALUE"
     echo "------            ---         ----      -----"
     echo "_domainkey        3600   IN   TXT      \"t=y; o=~;\""
-    echo "mail._domainkey   3600   IN   TXT      \"k=rsa; p=$pub\""
+    echo "mail._domainkey   3600   IN   TXT      \"v=DKIM1; k=rsa; p=$pub\""
 }
 
 # PLAIN list function
 plain_list() {
     echo -e "_domainkey\t3600\tIN\tTXT\t\"t=y; o=~;\""
-    echo -e "mail._domainkey\t3600\tIN\tTXT\t\"k=rsa; p=$pub\""
+    echo -e "mail._domainkey\t3600\tIN\tTXT\t\"v=DKIM1; k=rsa; p=$pub\""
 }
 
 # CSV list function
 csv_list() {
     echo "RECORD,TTL,IN,TYPE,VALUE"
     echo "_domainkey,3600,IN,TXT,\"\"t=y; o=~;\"\""
-    echo "mail._domainkey,3600,IN,TXT,\"\"k=rsa; p=$pub\"\""
+    echo "mail._domainkey,3600,IN,TXT,\"\"v=DKIM1; k=rsa; p=$pub\"\""
 }
 
 

+ 19 - 1
bin/v-list-sys-config

@@ -89,7 +89,14 @@ json_list() {
         "POLICY_USER_EDIT_DNS_TEMPLATES": "'$POLICY_USER_EDIT_DNS_TEMPLATES'",
         "POLICY_USER_DELETE_LOGS": "'$POLICY_USER_DELETE_LOGS'",
         "POLICY_USER_VIEW_LOGS": "'$POLICY_USER_VIEW_LOGS'",
-        "POLICY_USER_CHANGE_THEME": "'$POLICY_USER_CHANGE_THEME'"
+        "POLICY_USER_CHANGE_THEME": "'$POLICY_USER_CHANGE_THEME'",
+        "USE_SERVER_SMTP": "'$USE_SERVER_SMTP'",
+        "SERVER_SMTP_HOST": "'$SERVER_SMTP_HOST'",
+        "SERVER_SMTP_PORT": "'$SERVER_SMTP_PORT'",
+        "SERVER_SMTP_SECURITY": "'$SERVER_SMTP_SECURITY'",
+        "SERVER_SMTP_USER": "'$SERVER_SMTP_USER'",
+        "SERVER_SMTP_PASSWD": "'$SERVER_SMTP_PASSWD'",
+        "SERVER_SMTP_ADDR": "'$SERVER_SMTP_ADDR'"
     }
     }'
 }
@@ -185,6 +192,17 @@ shell_list() {
 	echo "SMTP Relay User:                   $SMTP_RELAY_USER"
     fi
 
+    echo "SMTP Server Account enabled:       $USE_SERVER_SMTP"
+
+    if [ ! -z "$USE_SERVER_SMTP" ] && [ "$USE_SERVER_SMTP" != 'false' ]; then
+    echo "SMTP Server Account Host:          $SERVER_SMTP_HOST"
+    echo "SMTP Server Account Port:          $SERVER_SMTP_PORT"
+    echo "SMTP Server Account Security:      $SERVER_SMTP_SECURITY"
+    echo "SMTP Server Account Username:      $SERVER_SMTP_USER"
+    echo "SMTP Server Account Password:      $SERVER_SMTP_PASSWD"
+    echo "SMTP Server Account Address:       $SERVER_SMTP_ADDR"
+    fi
+
     echo "Release Branch:                   $RELEASE_BRANCH"
     echo "Debug Mode:                       $DEBUG_MODE"
     echo "Theme:                            $THEME"

+ 6 - 6
func/db.sh

@@ -284,7 +284,7 @@ add_pgsql_database() {
     query="GRANT CONNECT ON DATABASE template1 to $dbuser"
     psql_query "$query" > /dev/null
 
-    query="SELECT rolpassword FROM pg_authid WHERE rolname='$dbuser';"
+    query="SELECT rolpassword FROM pg_authid WHERE rolname='$dbuser'"
     md5=$(psql_query "$query" | grep md5 | cut -f 2 -d \ )
 }
 
@@ -350,7 +350,7 @@ change_pgsql_password() {
     query="ALTER ROLE $DBUSER WITH LOGIN PASSWORD '$dbpass'"
     psql_query "$query" > /dev/null
 
-    query="SELECT rolpassword FROM pg_authid WHERE rolname='$DBUSER';"
+    query="SELECT rolpassword FROM pg_authid WHERE rolname='$DBUSER'"
     md5=$(psql_query "$query" | grep md5 |cut -f 2 -d \ )
 }
 
@@ -387,9 +387,9 @@ delete_pgsql_database() {
     psql_query "$query" > /dev/null
 
     if [ "$(grep "DBUSER='$DBUSER'" $USER_DATA/db.conf |wc -l)" -lt 2 ]; then
-        query="REVOKE CONNECT ON DATABASE template1 FROM $db_user"
+        query="REVOKE CONNECT ON DATABASE template1 FROM $DBUSER"
         psql_query "$query" > /dev/null
-        query="DROP ROLE $db_user"
+        query="DROP ROLE $DBUSER"
         psql_query "$query" > /dev/null
     fi
 }
@@ -413,9 +413,9 @@ dump_pgsql_database() {
 
     psql_dump $dump $database
 
-    query="SELECT rolpassword FROM pg_authid WHERE rolname='$DBUSER';"
+    query="SELECT rolpassword FROM pg_authid WHERE rolname='$DBUSER'"
     md5=$(psql_query "$query" | head -n1 | cut -f 2 -d \ )
-    pw_str="UPDATE pg_authid SET rolpassword='$md5' WHERE rolname='$DBUSER';"
+    pw_str="UPDATE pg_authid SET rolpassword='$md5' WHERE rolname='$DBUSER'"
     gr_str="GRANT ALL PRIVILEGES ON DATABASE $database to '$DBUSER'"
     echo -e "$pw_str\n$gr_str" >> $grants
 }

+ 39 - 34
func/domain.sh

@@ -49,36 +49,43 @@ is_web_domain_new() {
 
 # Web alias existence check
 is_web_alias_new() {
-    web_alias=$(grep -wH "$1" $HESTIA/data/users/*/web.conf)
-    if [ ! -z "$web_alias" ]; then
-        a1=$(echo "$web_alias" |grep -F "'$1'" |cut -f 7 -d /)
-        if [ ! -z "$a1" ] && [ "$2" == "web"  ]; then
-            check_result $E_EXISTS "Web alias $1 exists"
-        fi
-        if [ ! -z "$a1" ] && [ "$a1" != "$user" ]; then
-            check_result $E_EXISTS "Web alias $1 exists"
-        fi
-        a2=$(echo "$web_alias" |grep -F "'$1," |cut -f 7 -d /)
-        if [ ! -z "$a2" ] && [ "$2" == "web"  ]; then
-            check_result $E_EXISTS "Web alias $1 exists"
-        fi
-        if [ ! -z "$a2" ] && [ "$a2" != "$user" ]; then
-            check_result $E_EXISTS "Web alias $1 exists"
-        fi
-        a3=$(echo "$web_alias" |grep -F ",$1," |cut -f 7 -d /)
-        if [ ! -z "$a3" ] && [ "$2" == "web"  ]; then
-            check_result $E_EXISTS "Web alias $1 exists"
-        fi
-        if [ ! -z "$a3" ] && [ "$a3" != "$user" ]; then
-            check_result $E_EXISTS "Web alias $1 exists"
-        fi
-        a4=$(echo "$web_alias" |grep -F ",$1'" |cut -f 7 -d /)
-        if [ ! -z "$a4" ] && [ "$2" == "web"  ]; then
-            check_result $E_EXISTS "Web alias $1 exists"
-        fi
-        if [ ! -z "$a4" ] && [ "$a4" != "$user" ]; then
-            check_result $E_EXISTS "Web alias $1 exists"
+    grep -wH "$1" $HESTIA/data/users/*/web.conf | while read -r line ; do
+        user=$(echo $line |cut -f 7 -d /)
+        string=$(echo $line |cut -f 2- -d ':')
+        parse_object_kv_list  $string
+        if [ ! -z "$ALIAS" ]; then
+            a1=$(echo "'$ALIAS'" |grep -F "'$1'");
+            if [ ! -z "$a1" ] && [ "$2" == "web"  ]; then
+                return $E_EXISTS 
+            fi
+            if [ ! -z "$a1" ] && [ "$user" != "$user" ]; then
+                return $E_EXISTS 
+            fi
+            a2=$(echo "'$ALIAS'" |grep -F "'$1,")
+            if [ ! -z "$a2" ] && [ "$2" == "web"  ]; then
+                return $E_EXISTS
+            fi
+            if [ ! -z "$a2" ] && [ "$user" != "$user" ]; then
+                return $E_EXISTS
+            fi
+            a3=$(echo "'$ALIAS'" |grep -F ",$1," )
+            if [ ! -z "$a3" ] && [ "$2" == "web"  ]; then
+               return $E_EXISTS
+            fi
+            if [ ! -z "$a3" ] && [ "$user" != "$user" ]; then
+                return $E_EXISTS
+            fi
+            a4=$(echo "'$ALIAS'" |grep -F ",$1'")
+            if [ ! -z "$a4" ] && [ "$2" == "web"  ]; then
+                return $E_EXISTS
+            fi
+            if [ ! -z "$a4" ] && [ "$user" != "$user" ]; then
+                return $E_EXISTS
+            fi
         fi
+    done
+    if [ $? -ne 0 ]; then
+        check_result $E_EXISTS "Web alias $1 exists"
     fi
 }
 
@@ -802,9 +809,7 @@ add_webmail_config() {
         fi
 
         # Remove old configurations
-        rm -rf $HOMEDIR/$user/conf/mail/$domain.*
-        rm -rf $HOMEDIR/$user/conf/mail/ssl.$domain.*
-        rm -rf $HOMEDIR/$user/conf/mail/*nginx.$domain.*
+        find $HOMEDIR/$user/conf/mail/ -maxdepth 1 -type f \( -name "$domain.*" -o -name "ssl.$domain.*" -o -name "*nginx.$domain.*" \) -exec rm {} \;
     else
         if [ ! -z "$WEB_SYSTEM" ]; then
             rm -f /etc/$1/conf.d/domains/$WEBMAIL_ALIAS.$domain.conf
@@ -815,7 +820,7 @@ add_webmail_config() {
             ln -s $conf /etc/$1/conf.d/domains/$WEBMAIL_ALIAS.$domain.conf
         fi
         # Clear old configurations
-        rm -rf $HOMEDIR/$user/conf/mail/$domain.*
+        find $HOMEDIR/$user/conf/mail/ -maxdepth 1 -type f \( -name "$domain.*" \) -exec rm {} \;
     fi
 }
 
@@ -919,7 +924,7 @@ is_base_domain_owner(){
         if [ "$object" != "none" ]; then
             get_base_domain $object
             web=$(grep -F -H -h "DOMAIN='$basedomain'" $HESTIA/data/users/*/web.conf);
-            if [ $ENFORCE_SUBDOMAIN_OWNERSHIP = "yes" ]; then
+            if [ "$ENFORCE_SUBDOMAIN_OWNERSHIP" = "yes" ]; then
                 if [ ! -z "$web" ]; then
                     parse_object_kv_list "$web"
                     if [ -z "$ALLOW_USERS" ] ||  [ "$ALLOW_USERS" != "yes" ]; then

+ 7 - 2
func/ip.sh

@@ -50,7 +50,7 @@ update_ip_helo_value() {
     natip="$1"
     
     # In case the IP is an NAT use the real ip address 
-    if [ ! -f $HESTIA/data/ips/$ip ]; then
+    if [ ! -e "$HESTIA/data/ips/$ip" ]; then
         ip=$(get_real_ip $ip);
     fi 
     
@@ -74,6 +74,11 @@ update_ip_helo_value() {
     fi
 }
 
+delete_ip_helo_value (){
+    ip=$1
+    sed -i "/^$ip:/d" /etc/${MAIL_SYSTEM}/mailhelo.conf   
+}
+
 # Update ip address value
 update_ip_value() {
     key="$1"
@@ -195,7 +200,7 @@ get_real_ip() {
     if [ -e "$HESTIA/data/ips/$1" ]; then
         echo $1
     else
-        nat=$(grep -H "^NAT='$1'" $HESTIA/data/ips/*)
+        nat=$(grep -H "^NAT='$1'" $HESTIA/data/ips/* | head -n1 )
         if [ ! -z "$nat" ]; then
             echo "$nat" |cut -f 1 -d : |cut -f 7 -d /
         fi

+ 35 - 0
func/syshealth.sh

@@ -380,7 +380,42 @@ function syshealth_repair_system_config() {
         echo "[ ! ] Adding missing variable to hestia.conf: PHPMYADMIN_KEY ('')"
         $BIN/v-change-sys-config-value "PHPMYADMIN_KEY" ""
     fi
+    # Use SMTP server for hestia internal mail 
+    if [ -z "$USE_SERVER_SMTP" ]; then
+        echo "[ ! ] Adding missing variable to hestia.conf: USE_SERVER_SMTP ('')"
+        $BIN/v-change-sys-config-value "USE_SERVER_SMTP" "false"
+    fi
+
+    if [ -z "$SERVER_SMTP_PORT" ]; then
+        echo "[ ! ] Adding missing variable to hestia.conf: SERVER_SMTP_PORT ('')"
+        $BIN/v-change-sys-config-value "SERVER_SMTP_PORT" ""
+    fi
+
+    if [ -z "$SERVER_SMTP_HOST" ]; then
+        echo "[ ! ] Adding missing variable to hestia.conf: SERVER_SMTP_HOST ('')"
+        $BIN/v-change-sys-config-value "SERVER_SMTP_HOST" ""
+    fi
+
+    if [ -z "$SERVER_SMTP_SECURITY" ]; then
+        echo "[ ! ] Adding missing variable to hestia.conf: SERVER_SMTP_SECURITY ('')"
+        $BIN/v-change-sys-config-value "SERVER_SMTP_SECURITY" ""
+    fi
+
+    if [ -z "$SERVER_SMTP_USER" ]; then
+        echo "[ ! ] Adding missing variable to hestia.conf: SERVER_SMTP_USER ('')"
+        $BIN/v-change-sys-config-value "SERVER_SMTP_USER" ""
+    fi
     
+    if [ -z "$SERVER_SMTP_PASSWD" ]; then
+        echo "[ ! ] Adding missing variable to hestia.conf: SERVER_SMTP_PASSWD ('')"
+        $BIN/v-change-sys-config-value "SERVER_SMTP_PASSWD" ""
+    fi
+        
+    if [ -z "$SERVER_SMTP_ADDR" ]; then
+        echo "[ ! ] Adding missing variable to hestia.conf: SERVER_SMTP_ADDR ('')"
+        $BIN/v-change-sys-config-value "SERVER_SMTP_ADDR" ""
+    fi    
+
 }
 
 # Repair System Cron Jobs

+ 0 - 5
func/upgrade.sh

@@ -720,8 +720,3 @@ upgrade_restart_services() {
     fi
     $BIN/v-restart-service hestia
 }
-
-upgrade_perform_cleanup() {
-    # Remove upgrade configuration file as it's not needed
-    rm -f $HESTIA_INSTALL_DIR/upgrade/upgrade.conf
-}

+ 4 - 3
install/deb/dovecot/conf.d/10-ssl.conf

@@ -1,5 +1,6 @@
 ssl = yes
-ssl_protocols = !SSLv3 !TLSv1
+# See #2012 for TLSv1.1 to 1.2 upgrade
+ssl_min_protocol = TLSv1.1
 ssl_prefer_server_ciphers = yes
 ssl_cipher_list = ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
 
@@ -7,7 +8,7 @@ ssl_cert = </usr/local/hestia/ssl/certificate.crt
 ssl_key = </usr/local/hestia/ssl/certificate.key
 
 # From and up to version 2.2
-ssl_dh_parameters_length = 4096
+#ssl_dh_parameters_length = 4096
 
 # From version 2.3
-#ssl_dh = </etc/ssl/dhparam.pem
+ssl_dh = </etc/ssl/dhparam.pem

+ 1 - 1
install/deb/php-fpm/multiphp.tpl

@@ -17,7 +17,7 @@ pm.status_path = /status
 
 php_admin_value[upload_tmp_dir] = /home/%user%/tmp
 php_admin_value[session.save_path] = /home/%user%/tmp
-php_admin_value[open_basedir] = /home/%user%/web/%domain%/public_html:/home/%user%/web/%domain%/private:/home/%user%/web/%domain%/public_shtml:/home/%user%/tmp:/var/www/html:/bin:/usr/bin:/usr/local/bin:/usr/share:/opt
+php_admin_value[open_basedir] = /home/%user%/web/%domain%/public_html:/home/%user%/web/%domain%/private:/home/%user%/web/%domain%/public_shtml:/home/%user%/tmp:/tmp:/var/www/html:/bin:/usr/bin:/usr/local/bin:/usr/share:/opt
 php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f admin@%domain%
 
 env[PATH] = /usr/local/bin:/usr/bin:/bin

+ 1 - 1
install/deb/proftpd/tls.conf

@@ -13,7 +13,7 @@
 TLSEngine                               on
 TLSLog                                  /var/log/proftpd/tls.log
 # this is an example of protocols, proftp works witl all, but use only the most secure ones like TLSv1.1 and TLSv1.2
-TLSProtocol                             TLSv1.1 TLSv1.2
+TLSProtocol                             TLSv1.2
 #
 # Server SSL certificate. You can generate a self-signed certificate using
 # a command like:

+ 2 - 11
install/deb/templates/mail/apache2/disabled.stpl

@@ -1,21 +1,12 @@
 <VirtualHost %ip%:%web_ssl_port%>
 ServerName %domain_idn%
 ServerAlias %alias_idn%
-Alias / /var/www/html/
-Alias /error/ %home%/%user%/web/%root_domain%/document_errors/
-#SuexecUserGroup %user% %group%
+DocumentRoot /var/www/html/
+Alias /error/ /var/www/document_errors/
 
 SSLEngine on
 SSLVerifyClient none
 SSLCertificateFile         %home%/%user%/conf/mail/%root_domain%/ssl/%root_domain%.crt
 SSLCertificateKeyFile      %home%/%user%/conf/mail/%root_domain%/ssl/%root_domain%.key
-    
-<Directory /var/www/html>
-    Options +FollowSymLinks
-    AllowOverride All
-    order allow,deny
-    allow from all
-</Directory>
 
-IncludeOptional %home%/%user%/conf/mail/%root_domain%/%web_system%.conf_*
 </VirtualHost>

+ 2 - 13
install/deb/templates/mail/apache2/disabled.tpl

@@ -1,18 +1,7 @@
 <VirtualHost %ip%:%web_port%>
     ServerName %domain_idn%
     ServerAlias %alias_idn%
-    Alias / /var/www/html
-    Alias /error/ %home%/%user%/web/%root_domain%/document_errors/
+    DocumentRoot /var/www/html/
+    Alias /error/ /var/www/document_errors/
     #SuexecUserGroup %user% %group%
-        
-    IncludeOptional %home%/%user%/conf/mail/%root_domain%/apache2.forcessl.conf*
-
-    <Directory /var/www/html>
-        Options +FollowSymLinks
-        AllowOverride All
-        order allow,deny
-        allow from all
-    </Directory>
-
-    IncludeOptional %home%/%user%/conf/mail/%root_domain%/%web_system%.conf_*
 </VirtualHost>

+ 7 - 19
install/deb/templates/mail/nginx/default_disabled.stpl

@@ -1,33 +1,21 @@
 server {
-    listen      %ip%:%proxy_ssl_port% ssl http2;
-    server_name %domain_idn% %alias_idn%;
-    root        /var/lib/roundcube;
+    listen       %ip%:%proxy_ssl_port% ssl http2;
+    server_name  %domain_idn% %alias_idn%;
     index       index.php index.html index.htm;
     access_log /var/log/nginx/domains/%domain%.log combined;
     error_log  /var/log/nginx/domains/%domain%.error.log error;
-
+    
     ssl_certificate     %ssl_pem%;
     ssl_certificate_key %ssl_key%;
     ssl_stapling on;
     ssl_stapling_verify on;
-
+    
     location ~ /\.(?!well-known\/) {
         deny all;
         return 404;
     }
-
+    
     location / {
-        try_files $uri $uri/ =404;
-        alias /var/www/html;
+        proxy_pass  http://%ip%:%web_port%;
     }
-
-    location /error/ {
-        alias /var/www/document_errors/;
-    }
-	
-    location @fallback {
-        proxy_pass https://%ip%:%web_ssl_port%;
-    }
-
-    include %home%/%user%/conf/mail/%root_domain%/%proxy_system%.conf_*;
-}
+}

+ 11 - 26
install/deb/templates/mail/nginx/default_disabled.tpl

@@ -1,33 +1,18 @@
 server {
-    listen      %ip%:%proxy_ssl_port% ssl http2;
-    server_name %domain_idn% %alias_idn%;
-    root        /var/lib/roundcube;
-    index       index.php index.html index.htm;
-    access_log /var/log/nginx/domains/%domain%.log combined;
-    error_log  /var/log/nginx/domains/%domain%.error.log error;
-    
-    ssl_certificate     %ssl_pem%;
-    ssl_certificate_key %ssl_key%;
-    ssl_stapling on;
-    ssl_stapling_verify on;
-    
+listen       %ip%:%proxy_port%;
+server_name  %domain_idn% %alias_idn%;
+index       index.php index.html index.htm;
+access_log /var/log/nginx/domains/%domain%.log combined;
+error_log  /var/log/nginx/domains/%domain%.error.log error;
+
+include %home%/%user%/conf/mail/%root_domain%/nginx.forcessl.conf*;
+
     location ~ /\.(?!well-known\/) {
         deny all;
         return 404;
     }
-    
+
     location / {
-        try_files $uri $uri/ =404;
-        alias /var/www/html;
+        proxy_pass  http://%ip%:%web_port%;
     }
-    
-    location /error/ {
-        alias /var/www/document_errors/;
-    }
-    
-    location @fallback {
-        proxy_pass https://%ip%:%web_ssl_port%;
-    }
-    
-    include %home%/%user%/conf/mail/%root_domain%/%proxy_system%.conf_*;
-}
+}

+ 5 - 7
install/deb/templates/web/nginx/caching.sh

@@ -6,14 +6,12 @@ ip=$3
 home=$4
 docroot=$5
 
-str="proxy_cache_path /var/cache/nginx/$domain levels=2" 
-str="$str keys_zone=$domain:10m inactive=60m max_size=512m;" 
+str="proxy_cache_path /var/cache/nginx/$domain levels=1:2" 
+str="$str keys_zone=$domain:10m max_size=256m inactive=30m;" 
 conf='/etc/nginx/conf.d/01_caching_pool.conf'
 if [ -e "$conf" ]; then
-    if [ -z "$(grep "=${domain}:" $conf)" ]; then
-        echo "$str" >> $conf
+    if [ -n "$(grep "=${domain}:" $conf)" ]; then
+        sed -i "/=${domain}:/d" $conf
     fi
-else
-    echo "$str" >> $conf
 fi
-
+echo "$str" >> $conf

+ 15 - 4
install/deb/templates/web/nginx/caching.stpl

@@ -18,11 +18,22 @@ server {
         proxy_pass      https://%ip%:%web_ssl_port%;
 
         proxy_cache %domain%;
-        proxy_cache_valid 15m;
-        proxy_cache_valid 404 1m;
+        proxy_cache_valid 200 5m;
+        proxy_cache_valid 301 302 10m;
+        proxy_cache_valid 404 10m;
+        proxy_cache_bypass $no_cache $cookie_session $http_x_update;
         proxy_no_cache $no_cache;
-        proxy_cache_bypass $no_cache;
-        proxy_cache_bypass $cookie_session $http_x_update;
+
+        set $no_cache 0;
+            if ($request_uri ~* "/wp-admin/|wp-.*.php|xmlrpc.php|/store.*|/cart.*|/my-account.*|/checkout.*|/user/|/admin/|/administrator/|/manager/|index.php") {
+                set $no_cache 1;
+            }
+            if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|woocommerce_items_in_cart|woocommerce_cart_hash|PHPSESSID") {
+                set $no_cache 1;
+            }
+            if ($http_cookie ~ SESS) {
+                set $no_cache 1;
+            }
 
         location ~* ^.+\.(%proxy_extensions%)$ {
             proxy_cache    off;

+ 15 - 4
install/deb/templates/web/nginx/caching.tpl

@@ -13,11 +13,22 @@ server {
         proxy_pass      http://%ip%:%web_port%;
 
         proxy_cache %domain%;
-        proxy_cache_valid 15m;
-        proxy_cache_valid 404 1m;
+        proxy_cache_valid 200 5m;
+        proxy_cache_valid 301 302 10m;
+        proxy_cache_valid 404 10m;
+        proxy_cache_bypass $no_cache $cookie_session $http_x_update;
         proxy_no_cache $no_cache;
-        proxy_cache_bypass $no_cache;
-        proxy_cache_bypass $cookie_session $http_x_update;
+
+        set $no_cache 0;
+            if ($request_uri ~* "/wp-admin/|wp-.*.php|xmlrpc.php|/store.*|/cart.*|/my-account.*|/checkout.*|/user/|/admin/|/administrator/|/manager/|index.php") {
+                set $no_cache 1;
+            }
+            if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|woocommerce_items_in_cart|woocommerce_cart_hash|PHPSESSID") {
+                set $no_cache 1;
+            }
+            if ($http_cookie ~ SESS) {
+                set $no_cache 1;
+            }
 
         location ~* ^.+\.(%proxy_extensions%)$ {
             proxy_cache    off;

+ 0 - 16
install/deb/templates/web/nginx/php-fpm/craftcms.stpl

@@ -34,21 +34,6 @@ server {
         deny all;
         return 404;
     }
-
-    # Craft-specific location handlers to ensure AdminCP requests route through index.php
-    # If you change your `cpTrigger`, change it here as well
-    location ^~ /admin {
-        try_files $uri $uri/ @phpfpm_nocache;
-    }
-    location ^~ /index.php/admin {
-        try_files $uri $uri/ @phpfpm_nocache;
-    }
-    location ^~ /cpresources {
-        try_files $uri $uri/ /index.php?$query_string;
-    }
-    location ^~ /actions {
-        try_files $uri $uri/ /index.php?$query_string;
-    }
     
     location / {
         try_files $uri $uri/ /index.php?$args;
@@ -63,7 +48,6 @@ server {
             fastcgi_pass %backend_lsnr%;
             fastcgi_index index.php;
             include /etc/nginx/fastcgi_params;
-            include %home%/%user%/conf/web/%domain%/nginx.fastcgi_cache.conf*;
         }
     }
 

+ 0 - 16
install/deb/templates/web/nginx/php-fpm/craftcms.tpl

@@ -29,21 +29,6 @@ server {
         deny all;
         return 404;
     }
-
-    # Craft-specific location handlers to ensure AdminCP requests route through index.php
-    # If you change your `cpTrigger`, change it here as well
-    location ^~ /admin {
-        try_files $uri $uri/ @phpfpm_nocache;
-    }
-    location ^~ /index.php/admin {
-        try_files $uri $uri/ @phpfpm_nocache;
-    }
-    location ^~ /cpresources {
-        try_files $uri $uri/ /index.php?$query_string;
-    }
-    location ^~ /actions {
-        try_files $uri $uri/ /index.php?$query_string;
-    }
     
     location / {
         try_files $uri $uri/ /index.php?$args;
@@ -58,7 +43,6 @@ server {
             fastcgi_pass %backend_lsnr%;
             fastcgi_index index.php;
             include /etc/nginx/fastcgi_params;
-            include %home%/%user%/conf/web/%domain%/nginx.fastcgi_cache.conf*;
 
         }
     }

+ 4 - 4
install/deb/templates/web/nginx/php-fpm/no-php.stpl

@@ -19,16 +19,16 @@ server {
 
     include %home%/%user%/conf/web/%domain%/nginx.hsts.conf*;
 
-    types {
-            text/html   html htm shtml php php5;
-    }
-
     location / {
         location ~* ^.+\.(jpeg|jpg|png|gif|bmp|ico|svg|css|js)$ {
             expires     max;
             fastcgi_hide_header "Set-Cookie";
         }
     }
+    
+    location ~ [^/]\.php(/|$) {
+        types { } default_type "text/html";
+    }
 
     location /error/ {
         alias   %home%/%user%/web/%domain%/document_errors/;

+ 4 - 4
install/deb/templates/web/nginx/php-fpm/no-php.tpl

@@ -14,16 +14,16 @@ server {
         
     include %home%/%user%/conf/web/%domain%/nginx.forcessl.conf*;
 
-    types {
-            text/html   html htm shtml php php5;
-    }
-
     location / {
         location ~* ^.+\.(jpeg|jpg|png|gif|bmp|ico|svg|css|js)$ {
             expires     max;
             fastcgi_hide_header "Set-Cookie";
         }
     }
+    
+    location ~ [^/]\.php(/|$) {
+        types { } default_type "text/html";
+    }
 
     location /error/ {
         alias   %home%/%user%/web/%domain%/document_errors/;

+ 41 - 7
install/hst-install-debian.sh

@@ -23,7 +23,7 @@ HESTIA_INSTALL_DIR="$HESTIA/install/deb"
 VERBOSE='no'
 
 # Define software versions
-HESTIA_INSTALL_VER='1.4.8~alpha'
+HESTIA_INSTALL_VER='1.4.11~aplpha'
 pma_v='5.1.1'
 rc_v="1.4.11"
 multiphp_v=("5.6" "7.0" "7.1" "7.2" "7.3" "7.4" "8.0")
@@ -284,6 +284,9 @@ fi
 if [ "$iptables" = 'no' ]; then
     fail2ban='no'
 fi
+if [ "$apache" = "no" ]; then
+    phpfpm='yes'
+fi
 
 # Checking root permissions
 if [ "x$(id -u)" != 'x0' ]; then
@@ -342,7 +345,14 @@ check_result $? "Unable to connect to the Hestia APT repository"
 # Check installed packages
 tmpfile=$(mktemp -p /tmp)
 dpkg --get-selections > $tmpfile
-for pkg in exim4 mariadb-server apache2 nginx hestia postfix; do
+conflicts_pkg="exim4 mariadb-server apache2 nginx hestia postfix"
+
+# Drop postfix from the list if exim should not be installed
+if [ "$exim" = 'no' ]; then
+    conflicts_pkg=$(echo $conflicts_pkg | sed 's/postfix//g' | xargs)
+fi
+
+for pkg in $conflicts_pkg; do
     if [ ! -z "$(grep $pkg $tmpfile)" ]; then
         conflicts="$pkg* $conflicts"
     fi
@@ -1152,9 +1162,6 @@ write_config_value "THEME" "dark"
 # Inactive session timeout
 write_config_value "INACTIVE_SESSION_TIMEOUT" "60"
 
-# Do not allow users to create subdomains when they don't own the domain
-write_config_value "ENFORCE_SUBDOMAIN_OWNERSHIP" "yes"
-
 # Version & Release Branch
 write_config_value "VERSION" "${HESTIA_INSTALL_VER}"
 write_config_value "RELEASE_BRANCH" "release"
@@ -1242,6 +1249,7 @@ $HESTIA/bin/v-change-user-role admin admin
 $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                      #
 #----------------------------------------------------------#
@@ -1619,7 +1627,19 @@ if [ "$dovecot" = 'yes' ]; then
     cp -rf $HESTIA_INSTALL_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
+    if [ "$release" -eq 9 ] || [ "$release" -eq 10 ]; then
+        rm -f /etc/dovecot/conf.d/15-mailboxes.conf
+    fi
+    
+    #Alter config for 2.2 
+    version=$(dovecot --version |  cut -f -2 -d .);
+    if [ "$version" = "2.2" ]; then 
+      echo "[ * ] Downgrade dovecot config to sync with 2.2 settings"	
+      sed -i 's|#ssl_dh_parameters_length = 4096|ssl_dh_parameters_length = 4096|g' /etc/dovecot/conf.d/10-ssl.conf
+      sed -i 's|ssl_dh = </etc/ssl/dhparam.pem|#ssl_dh = </etc/ssl/dhparam.pem|g' /etc/dovecot/conf.d/10-ssl.conf
+      sed -i 's|ssl_min_protocol = TLSv1.1|ssl_protocols = !SSLv3 !TLSv1|g' /etc/dovecot/conf.d/10-ssl.conf
+    fi
+    
     update-rc.d dovecot defaults
     systemctl start dovecot
     check_result $? "dovecot start failed"
@@ -1891,11 +1911,25 @@ 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" "no"
-write_config_value "POLICY_SYSTEM_HIDE_SERVICES" "no"
+write_config_value "POLICY_SYSTEM_HIDE_SERVICES" "yes"
 write_config_value "POLICY_SYSTEM_ENABLE_BACON" "no"
 write_config_value "PLUGIN_APP_INSTALLER" "true"
 write_config_value "DEBUG_MODE" "no"
 write_config_value "ENFORCE_SUBDOMAIN_OWNERSHIP" "yes"
+write_config_value "USE_SERVER_SMTP" "false"
+write_config_value "SERVER_SMTP_PORT" ""
+write_config_value "SERVER_SMTP_HOST" ""
+write_config_value "SERVER_SMTP_SECURITY" ""
+write_config_value "SERVER_SMTP_USER" ""
+write_config_value "SERVER_SMTP_PASSWD" ""
+write_config_value "SERVER_SMTP_ADDR" ""
+
+#----------------------------------------------------------#
+#                  Configure PHPMailer                     #
+#----------------------------------------------------------#
+
+echo "[ * ] Configuring PHPMailer..."
+$HESTIA/bin/v-add-sys-phpmailer quiet
 
 #----------------------------------------------------------#
 #                   Hestia Access Info                     #

+ 37 - 6
install/hst-install-ubuntu.sh

@@ -23,7 +23,7 @@ HESTIA_INSTALL_DIR="$HESTIA/install/deb"
 VERBOSE='no'
 
 # Define software versions
-HESTIA_INSTALL_VER='1.4.8~alpha'
+HESTIA_INSTALL_VER='1.4.11~alpha'
 pma_v='5.1.1'
 rc_v="1.4.11"
 multiphp_v=("5.6" "7.0" "7.1" "7.2" "7.3" "7.4" "8.0")
@@ -266,6 +266,9 @@ fi
 if [ "$iptables" = 'no' ]; then
     fail2ban='no'
 fi
+if [ "$apache" = "no" ]; then
+    phpfpm='yes'
+fi
 
 # Checking root permissions
 if [ "x$(id -u)" != 'x0' ]; then
@@ -317,7 +320,14 @@ check_result $? "Unable to connect to the Hestia APT repository"
 # Check installed packages
 tmpfile=$(mktemp -p /tmp)
 dpkg --get-selections > $tmpfile
-for pkg in exim4 mariadb-server apache2 nginx hestia postfix ufw; do
+conflicts_pkg="exim4 mariadb-server apache2 nginx hestia postfix ufw"
+
+# Drop postfix from the list if exim should not be installed
+if [ "$exim" = 'no' ]; then
+    conflicts_pkg=$(echo $conflicts_pkg | sed 's/postfix//g' | xargs)
+fi
+
+for pkg in $conflicts_pkg; do
     if [ ! -z "$(grep $pkg $tmpfile)" ]; then
         conflicts="$pkg* $conflicts"
     fi
@@ -1173,9 +1183,6 @@ write_config_value "THEME" "dark"
 # Inactive session timeout
 write_config_value "INACTIVE_SESSION_TIMEOUT" "60"
 
-# Do not allow users to create subdomains when they don't own the domain
-write_config_value "ENFORCE_SUBDOMAIN_OWNERSHIP" "yes"
-
 # Version & Release Branch
 write_config_value "VERSION" "${HESTIA_INSTALL_VER}"
 write_config_value "RELEASE_BRANCH" "release"
@@ -1267,6 +1274,7 @@ $HESTIA/bin/v-change-user-role admin admin
 $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                      #
@@ -1647,6 +1655,16 @@ if [ "$dovecot" = 'yes' ]; then
         rm -f /etc/dovecot/conf.d/15-mailboxes.conf
     fi
     chown -R root:root /etc/dovecot*
+        
+    #Alter config for 2.2 
+    version=$(dovecot --version |  cut -f -2 -d .);
+    if [ "$version" = "2.2" ]; then 
+      echo "[ * ] Downgrade dovecot config to sync with 2.2 settings"	
+      sed -i 's|#ssl_dh_parameters_length = 4096|ssl_dh_parameters_length = 4096|g' /etc/dovecot/conf.d/10-ssl.conf
+      sed -i 's|ssl_dh = </etc/ssl/dhparam.pem|#ssl_dh = </etc/ssl/dhparam.pem|g' /etc/dovecot/conf.d/10-ssl.conf
+      sed -i 's|ssl_min_protocol = TLSv1.1|ssl_protocols = !SSLv3 !TLSv1|g' /etc/dovecot/conf.d/10-ssl.conf
+    fi
+    
     update-rc.d dovecot defaults
     systemctl start dovecot >> $LOG
     check_result $? "dovecot start failed"
@@ -1909,12 +1927,25 @@ write_config_value "POLICY_USER_EDIT_DETAILS" "yes"
 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" "no"
+write_config_value "POLICY_SYSTEM_PASSWORD_RESET" "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"
 write_config_value "ENFORCE_SUBDOMAIN_OWNERSHIP" "yes"
+write_config_value "USE_SERVER_SMTP" "false"
+write_config_value "SERVER_SMTP_PORT" ""
+write_config_value "SERVER_SMTP_HOST" ""
+write_config_value "SERVER_SMTP_SECURITY" ""
+write_config_value "SERVER_SMTP_USER" ""
+write_config_value "SERVER_SMTP_PASSWD" ""
+write_config_value "SERVER_SMTP_ADDR" ""
+#----------------------------------------------------------#
+#                  Configure PHPMailer                     #
+#----------------------------------------------------------#
+
+echo "[ * ] Configuring PHPMailer..."
+$HESTIA/bin/v-add-sys-phpmailer quiet
 
 #----------------------------------------------------------#
 #                   Hestia Access Info                     #

+ 0 - 15
install/rhel/templates/web/nginx/php-fpm/craftcms.stpl

@@ -14,21 +14,6 @@ server {
     
     include %home%/%user%/conf/web/%domain%/nginx.hsts.conf*;
 
-    # Craft-specific location handlers to ensure AdminCP requests route through index.php
-    # If you change your `cpTrigger`, change it here as well
-    location ^~ /admin {
-        try_files $uri $uri/ @phpfpm_nocache;
-    }
-    location ^~ /index.php/admin {
-        try_files $uri $uri/ @phpfpm_nocache;
-    }
-    location ^~ /cpresources {
-        try_files $uri $uri/ /index.php?$query_string;
-    }
-    location ^~ /actions {
-        try_files $uri $uri/ /index.php?$query_string;
-    }
-
     location / {
         try_files $uri $uri/ /index.php?$query_string;
         location ~* ^.+\.(jpeg|jpg|png|gif|bmp|ico|svg|css|js|webp)$ {

+ 0 - 15
install/rhel/templates/web/nginx/php-fpm/craftcms.tpl

@@ -9,21 +9,6 @@ server {
         
     include %home%/%user%/conf/web/%domain%/nginx.forcessl.conf*;
 
-    # Craft-specific location handlers to ensure AdminCP requests route through index.php
-    # If you change your `cpTrigger`, change it here as well
-    location ^~ /admin {
-        try_files $uri $uri/ @phpfpm_nocache;
-    }
-    location ^~ /index.php/admin {
-        try_files $uri $uri/ @phpfpm_nocache;
-    }
-    location ^~ /cpresources {
-        try_files $uri $uri/ /index.php?$query_string;
-    }
-    location ^~ /actions {
-        try_files $uri $uri/ /index.php?$query_string;
-    }
-
     location / {
         try_files $uri $uri/ /index.php?$query_string;
         location ~* ^.+\.(jpeg|jpg|png|gif|bmp|ico|svg|css|js|webp)$ {

+ 81 - 0
install/upgrade/manual/configure-server-smtp.sh

@@ -0,0 +1,81 @@
+#!/bin/bash
+# info: setup SMTP Account for server logging
+# options: NONE
+# labels:
+#
+# example: configure-server-smtp.sh
+#
+# This function provides an user-interactive configuration of a SMTP account
+# for the server to use for logging, notification and warn emails etc.
+
+#----------------------------------------------------------#
+#                    Variable&Function                     #
+#----------------------------------------------------------#
+
+# Includes
+# shellcheck source=/usr/local/hestia/func/main.sh
+source $HESTIA/func/main.sh
+# shellcheck source=/usr/local/hestia/conf/hestia.conf
+source $HESTIA/conf/hestia.conf
+
+function setupFiles
+{
+	echo "Use SMTP account for server communication (Y/n): "
+	read use_smtp_prompt
+
+	use_smtp="${use_smtp_prompt:-y}"
+	use_smtp="${use_smtp,,}"
+	if [ "${use_smtp}" == "y" ] ; then
+		use_smtp=true
+
+		echo "Enter SMTP Host:"
+		read -i $SERVER_SMTP_HOST -e smtp_server_host
+		echo "Enter SMTP Port:"
+		read -i $SERVER_SMTP_PORT -e smtp_server_port
+		echo "Enter SMTP Security:"
+		read -i $SERVER_SMTP_SECURITY -e smtp_server_security
+		echo "Enter SMTP Username:"
+		read -i $SERVER_SMTP_USER -e smtp_server_user_name
+		echo "Enter SMTP Password (stored as plaintext):"
+		read -i $SERVER_SMTP_PASSWD -e smtp_server_password
+		echo "Enter SMTP Address:"
+		read -i $SERVER_SMTP_ADDR -e smtp_server_addr
+	else
+		use_smtp=false
+	fi
+
+	echo "Summary:
+	Use SMTP: $use_smtp
+	SMTP Host: $smtp_server_host
+	SMTP Port: $smtp_server_port
+	SMTP Security: $smtp_server_security
+	SMTP Username: $smtp_server_user_name
+	SMTP Password: $smtp_server_password
+	SMTP Address: $smtp_server_addr
+	Are these values correct? (y/N)"
+	read correct_validation
+	correct="${correct_validation:-n}"
+	correct="${correct,,}"
+	if [ "${correct}" != "y" ] ; then
+		echo "Not Proceeding. Restart or Quit (r/Q)?"
+		read restart_quit_prompt
+		restart_quit="${restart_quit_prompt:-q}"
+		restart_quit="${restart_quit,,}"
+		if [ "${restart_quit}" == "r" ] ; then
+			clear
+			setupFiles
+		else
+			exit 3
+		fi
+	else
+		$BIN/v-change-sys-config-value "USE_SERVER_SMTP" "${use_smtp:-}"
+		$BIN/v-change-sys-config-value "SERVER_SMTP_HOST" "${smtp_server_host:-}"
+		$BIN/v-change-sys-config-value "SERVER_SMTP_PORT" "${smtp_server_port:-}"
+		$BIN/v-change-sys-config-value "SERVER_SMTP_SECURITY" "${smtp_server_security:-}"
+		$BIN/v-change-sys-config-value "SERVER_SMTP_USER" "${smtp_server_user_name:-}"
+		$BIN/v-change-sys-config-value "SERVER_SMTP_PASSWD" "${smtp_server_password:-}"
+		$BIN/v-change-sys-config-value "SERVER_SMTP_ADDR" "${smtp_server_addr:-}"
+	fi
+}
+
+setupFiles

+ 3 - 0
install/upgrade/upgrade.conf

@@ -61,3 +61,6 @@ rl_v="1.16.0"
 
 # Set version of File manager to update during upgrade if not already installed
 fm_v="7.6.0"
+
+# Set version of PHPMailer to update during upgrade if not already installed
+pm_v="6.5.0"

+ 21 - 0
install/upgrade/versions/1.4.8.sh

@@ -5,3 +5,24 @@
 #######################################################################################
 #######                      Place additional commands below.                   #######
 #######################################################################################
+
+echo "[ * ] Configuring PHPMailer..."
+$HESTIA/bin/v-add-sys-phpmailer quiet
+
+matches=$(grep -o 'ENFORCE_SUBDOMAIN_OWNERSHIP' $HESTIA/conf/hestia.conf | wc -l);
+if [ "$matches" > 1 ]; then
+	echo "[ * ] Removing double matches ENFORCE_SUBDOMAIN_OWNERSHIP key"
+	source $HESTIA/conf/hestia.conf
+	sed -i "/ENFORCE_SUBDOMAIN_OWNERSHIP='$ENFORCE_SUBDOMAIN_OWNERSHIP'/d" $HESTIA/conf/hestia.conf
+	$HESTIA/bin/v-change-sys-config-value "ENFORCE_SUBDOMAIN_OWNERSHIP" "$ENFORCE_SUBDOMAIN_OWNERSHIP"
+fi
+
+if [ "$IMAP_SYSTEM" = "dovecot" ]; then 
+	version=$(dovecot --version |  cut -f -2 -d .);
+	if [ "$version" = "2.3" ]; then 
+		echo "[ * ] Update dovecot config to sync with 2.3 settings"	
+		sed -i 's|ssl_dh_parameters_length = 4096|#ssl_dh_parameters_length = 4096|g' /etc/dovecot/conf.d/10-ssl.conf
+		sed -i 's|#ssl_dh = </etc/ssl/dhparam.pem|ssl_dh = </etc/ssl/dhparam.pem|g' /etc/dovecot/conf.d/10-ssl.conf
+		sed -i 's|ssl_protocols = !SSLv3 !TLSv1|ssl_min_protocol=TLSv1.1|g' /etc/dovecot/conf.d/10-ssl.conf
+	fi
+fi

+ 7 - 0
install/upgrade/versions/1.4.9.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+# Hestia Control Panel upgrade script for target version 1.4.9
+
+#######################################################################################
+#######                      Place additional commands below.                   #######
+#######################################################################################

+ 1 - 1
src/deb/hestia/control

@@ -1,7 +1,7 @@
 Source: hestia
 Package: hestia
 Priority: optional
-Version: 1.4.8~alpha
+Version: 1.4.11~alpha
 Section: admin
 Maintainer: HestiaCP <[email protected]>
 Homepage: https://www.hestiacp.com

+ 10 - 5
src/deb/hestia/postinst

@@ -8,11 +8,17 @@ fi
 #                Initialize functions/variables               #
 ###############################################################
 
+if [ -z "$HESTIA" ]; then
+    export HESTIA='/usr/local/hestia'
+    PATH=$PATH:/usr/local/hestia/bin
+    export PATH
+fi
+
 # Load upgrade functions and variables
-source /usr/local/hestia/func/main.sh
-source /usr/local/hestia/func/upgrade.sh
-source /usr/local/hestia/conf/hestia.conf
-source /usr/local/hestia/install/upgrade/upgrade.conf
+source $HESTIA/func/main.sh
+source $HESTIA/func/upgrade.sh
+source $HESTIA/conf/hestia.conf
+source $HESTIA/install/upgrade/upgrade.conf
 
 ###############################################################
 #             Set new version numbers for packages            #
@@ -86,7 +92,6 @@ upgrade_set_branch $new_version
 upgrade_cleanup_message | tee -a $LOG
 upgrade_rebuild_users | tee -a $LOG
 upgrade_restart_services | tee -a $LOG
-upgrade_perform_cleanup | tee -a $LOG
 
 # Add upgrade notification to admin user's panel and display completion message
 upgrade_complete_message_log >> $LOG

+ 1 - 1
src/deb/php/control

@@ -1,7 +1,7 @@
 Source: hestia-php
 Package: hestia-php
 Priority: optional
-Version: 7.4.19
+Version: 7.4.21
 Section: admin
 Maintainer: HestaCP <[email protected]>
 Homepage: https://www.hestiacp.com

+ 3 - 8
src/hst_autocompile.sh

@@ -459,7 +459,7 @@ if [ "$PHP_B" = true ] ; then
         # Download and unpack source files
         cd $BUILD_DIR
         download_file $PHP '-' | tar xz
-
+        
         # Change to untarred php directory
         cd $BUILD_DIR_PHP
 
@@ -475,7 +475,6 @@ if [ "$PHP_B" = true ] ; then
                         --with-curl \
                         --with-zip \
                         --with-gmp \
-                        --enable-intl \
                         --enable-mbstring
         else
             ./configure   --prefix=/usr/local/hestia/php \
@@ -488,7 +487,6 @@ if [ "$PHP_B" = true ] ; then
                         --with-curl \
                         --with-zip \
                         --with-gmp \
-                        --enable-intl \
                         --enable-mbstring
         fi
     fi
@@ -503,10 +501,6 @@ if [ "$PHP_B" = true ] ; then
         [ "$HESTIA_DEBUG" ] && echo DEBUG: cp -rf "$SRC_DIR/" $BUILD_DIR/hestiacp-$branch_dash
         cp -rf "$SRC_DIR/" $BUILD_DIR/hestiacp-$branch_dash
     fi
-
-    # Set permission
-    #chmod +x postinst
-
     # Move php directory
     [ "$HESTIA_DEBUG" ] && echo DEBUG: mkdir -p $BUILD_DIR_HESTIAPHP/usr/local/hestia
     mkdir -p $BUILD_DIR_HESTIAPHP/usr/local/hestia
@@ -535,7 +529,8 @@ if [ "$PHP_B" = true ] ; then
             sed -i "s/amd64/${BUILD_ARCH}/g" "$BUILD_DIR_HESTIAPHP/DEBIAN/control"
         fi
         get_branch_file 'src/deb/php/copyright' "$BUILD_DIR_HESTIAPHP/DEBIAN/copyright"
-
+        get_branch_file 'src/deb/php/postinst' "$BUILD_DIR_HESTIAPHP/DEBIAN/postinst"
+        chmod +x $BUILD_DIR_HESTIAPHP/DEBIAN/postinst
         # Get custom config
         get_branch_file 'src/deb/php/php-fpm.conf' "${BUILD_DIR_HESTIAPHP}/usr/local/hestia/php/etc/php-fpm.conf"
         get_branch_file 'src/deb/php/php.ini' "${BUILD_DIR_HESTIAPHP}/usr/local/hestia/php/lib/php.ini"

+ 3 - 3
src/check_php.sh → test/check_php.sh

@@ -16,7 +16,7 @@ if [ ! -d $current ] && [ ! -f $current ] ; then
 fi
 
 echo "Checking PHP files..."
-for file in `find $current -type f -name "*.php"` ; do
+for file in `find $current -type f -name "*.php" -not -path "${current}fm/*"` ; do
     RESULTS=`php -l -n $file`
 
     if [ "$RESULTS" != "No syntax errors detected in $file" ] ; then
@@ -26,7 +26,7 @@ for file in `find $current -type f -name "*.php"` ; do
 done
 
 echo "Checking HTML/PHP combined files..."
-for file in `find $current -type f -name "*.html"` ; do
+for file in `find $current -type f -name "*.html" -not -path "${current}fm/*"` ; do
     RESULTS=`php -l -n $file`
 
     if [ "$RESULTS" != "No syntax errors detected in $file" ] ; then
@@ -39,4 +39,4 @@ if [ "$error" = true ] ; then
     exit 1
 else
     exit 0
-fi
+fi

+ 81 - 0
test/config-tests.bats

@@ -0,0 +1,81 @@
+#!/usr/bin/env bats
+
+if [ "${PATH#*/usr/local/hestia/bin*}" = "$PATH" ]; then
+    . /etc/profile.d/hestia.sh
+fi
+
+load 'test_helper/bats-support/load'
+load 'test_helper/bats-assert/load'
+load 'test_helper/bats-file/load'
+
+function random() {
+head /dev/urandom | tr -dc 0-9 | head -c$1
+}
+
+function setup() {
+    # echo "# Setup_file" > &3
+    if [ $BATS_TEST_NUMBER = 1 ]; then
+        echo 'user=test-5285' > /tmp/hestia-test-env.sh
+        echo 'user2=test-5286' >> /tmp/hestia-test-env.sh
+        echo 'userbk=testbk-5285' >> /tmp/hestia-test-env.sh
+        echo 'userpass1=test-5285' >> /tmp/hestia-test-env.sh
+        echo 'userpass2=t3st-p4ssw0rd' >> /tmp/hestia-test-env.sh
+        echo 'HESTIA=/usr/local/hestia' >> /tmp/hestia-test-env.sh
+        echo 'domain=test-5285.hestiacp.com' >> /tmp/hestia-test-env.sh
+        echo 'domainuk=test-5285.hestiacp.com.uk' >> /tmp/hestia-test-env.sh
+        echo 'rootdomain=testhestiacp.com' >> /tmp/hestia-test-env.sh
+        echo 'subdomain=cdn.testhestiacp.com' >> /tmp/hestia-test-env.sh
+        echo 'database=test-5285_database' >> /tmp/hestia-test-env.sh
+        echo 'dbuser=test-5285_dbuser' >> /tmp/hestia-test-env.sh
+    fi
+    
+    source /tmp/hestia-test-env.sh
+    source $HESTIA/func/main.sh
+    source $HESTIA/conf/hestia.conf
+    source $HESTIA/func/ip.sh
+}
+
+@test "Setup" {
+    run v-add-user $user $user [email protected] default "Super Test"
+    assert_success
+    refute_output
+    
+    run run v-add-web-domain $user 'testhestiacp.com'
+    assert_success
+    refute_output
+    
+    ssl=$(v-generate-ssl-cert "testhestiacp.com" "[email protected]" US CA "Orange County" HestiaCP IT "mail.$domain" | tail -n1 | awk '{print $2}')
+    mv $ssl/testhestiacp.com.crt /tmp/testhestiacp.com.crt
+    mv $ssl/testhestiacp.com.key /tmp/testhestiacp.com.key
+    
+    # Use self signed certificates during last test
+    run v-add-web-domain-ssl $user testhestiacp.com /tmp
+    assert_success
+    refute_output
+}
+
+@test "Web Config test" {
+    for template in $(v-list-web-templates plain); do
+        run v-change-web-domain-tpl $user testhestiacp.com $template
+        assert_success
+        refute_output
+    done
+}
+
+@test "Proxy Config test" {
+    if [ "$PROXY_SYSTEM" = "nginx" ]; then
+        for template in $(v-list-web-templates plain); do
+            run v-change-web-domain-proxy-tpl $user testhestiacp.com $template
+            assert_success
+            refute_output
+        done
+    else
+        skip "Proxy not installed"
+    fi
+}
+
+@test "Clean up" {
+    run v-delete-user $user
+    assert_success
+    refute_output
+}

+ 536 - 0
test/restore.bats

@@ -0,0 +1,536 @@
+#!/usr/bin/env bats
+
+if [ "${PATH#*/usr/local/hestia/bin*}" = "$PATH" ]; then
+    . /etc/profile.d/hestia.sh
+fi
+
+load 'test_helper/bats-support/load'
+load 'test_helper/bats-assert/load'
+load 'test_helper/bats-file/load'
+
+function random() {
+head /dev/urandom | tr -dc 0-9 | head -c$1
+}
+
+function setup() {
+    # echo "# Setup_file" > &3
+    if [ $BATS_TEST_NUMBER = 1 ]; then
+        echo 'user=test-5285' > /tmp/hestia-test-env.sh
+        echo 'user2=test-5286' >> /tmp/hestia-test-env.sh
+        echo 'userbk=testbk-5285' >> /tmp/hestia-test-env.sh
+        echo 'userpass1=test-5285' >> /tmp/hestia-test-env.sh
+        echo 'userpass2=t3st-p4ssw0rd' >> /tmp/hestia-test-env.sh
+        echo 'HESTIA=/usr/local/hestia' >> /tmp/hestia-test-env.sh
+        echo 'domain=test-5285.hestiacp.com' >> /tmp/hestia-test-env.sh
+        echo 'domainuk=test-5285.hestiacp.com.uk' >> /tmp/hestia-test-env.sh
+        echo 'rootdomain=testhestiacp.com' >> /tmp/hestia-test-env.sh
+        echo 'subdomain=cdn.testhestiacp.com' >> /tmp/hestia-test-env.sh
+        echo 'database=test-5285_database' >> /tmp/hestia-test-env.sh
+        echo 'dbuser=test-5285_dbuser' >> /tmp/hestia-test-env.sh
+    fi
+    
+    source /tmp/hestia-test-env.sh
+    source $HESTIA/func/main.sh
+    source $HESTIA/conf/hestia.conf
+    source $HESTIA/func/ip.sh
+}
+
+
+
+function validate_web_domain() {
+    local user=$1
+    local domain=$2
+    local webproof=$3
+    local webpath=${4}
+    
+    refute [ -z "$user" ]
+    refute [ -z "$domain" ]
+    refute [ -z "$webproof" ]
+    
+    source $HESTIA/func/ip.sh
+    
+    run v-list-web-domain $user $domain
+    assert_success
+    
+    USER_DATA=$HESTIA/data/users/$user
+    local domain_ip=$(get_object_value 'web' 'DOMAIN' "$domain" '$IP')
+    SSL=$(get_object_value 'web' 'DOMAIN' "$domain" '$SSL')
+    domain_ip=$(get_real_ip "$domain_ip")
+    
+    if [ ! -z $webpath ]; then
+        domain_docroot=$(get_object_value 'web' 'DOMAIN' "$domain" '$CUSTOM_DOCROOT')
+        if [ -n "$domain_docroot" ] && [ -d "$domain_docroot" ]; then
+            assert_file_exist "${domain_docroot}/${webpath}"
+        else
+            assert_file_exist "${HOMEDIR}/${user}/web/${domain}/public_html/${webpath}"
+        fi
+    fi
+    
+    # Test HTTP
+    run curl --location --silent --show-error --insecure --resolve "${domain}:80:${domain_ip}" "http://${domain}/${webpath}"
+    assert_success
+    assert_output --partial "$webproof"
+    
+    # Test HTTPS
+    if [ "$SSL" = "yes" ]; then
+        run v-list-web-domain-ssl $user $domain
+        assert_success
+    
+        run curl --location --silent --show-error --insecure --resolve "${domain}:443:${domain_ip}" "https://${domain}/${webpath}"
+        assert_success
+        assert_output --partial "$webproof"
+    fi
+}
+
+#----------------------------------------------------------#
+#                     Backup / Restore                     #
+#----------------------------------------------------------#
+
+#Test backup
+#  Hestia v1.1.1 archive contains:
+#    user: hestia111
+#    web:
+#      - test.hestia.com (+SSL self-signed)
+#    dns:
+#      - test.hestia.com
+#    mail:
+#      - test.hestia.com
+#    mail acc:
+#      - [email protected]
+#    db:
+#      - hestia111_db
+#    cron:
+#      - 1: /bin/true
+#  Hestia 1.3.1 archive contains (As zstd format)
+#    user: hestia131
+#    web:
+#      - test.hestia.com (+SSL self-signed)
+#    dns:
+#      - test.hestia.com
+#    mail:
+#      - test.hestia.com
+#    mail acc:
+#      - [email protected]
+#    db:
+#      - hestia131_db
+#    cron:
+#      - 1: /bin/true 
+#  Vesta 0.9.8-23 archive contains:
+#    user: vesta09823
+#    web:
+#      - vesta09823.tld (+SSL self-signed)
+#    dns:
+#      - vesta09823.tld
+#    mail:
+#      - vesta09823.tld
+#    mail acc:
+#      - [email protected]
+#    db:
+#      - vesta09823_db
+#    cron:
+#      - 1: /bin/true
+#
+
+# Testing Hestia backups
+@test "Restore[1]: Hestia archive for a non-existing user" {
+    if [ -d "$HOMEDIR/$userbk" ]; then
+        run v-delete-user $userbk
+        assert_success
+        refute_output
+    fi
+
+    mkdir -p /backup
+
+    local archive_name="hestia111.2020-03-26"
+    run wget --quiet --tries=3 --timeout=15 --read-timeout=15 --waitretry=3 --no-dns-cache "https://hestiacp.com/testing/data/${archive_name}.tar" -O "/backup/${archive_name}.tar"
+    assert_success
+
+    run v-restore-user $userbk "${archive_name}.tar"
+    assert_success
+
+    rm "/backup/${archive_name}.tar"
+}
+
+@test "Restore[1]: From Hestia [WEB]" {
+    local domain="test.hestia.com"
+    validate_web_domain $userbk $domain 'Hello Hestia'
+}
+
+@test "Restore[1]: From Hestia [DNS]" {
+    local domain="test.hestia.com"
+
+    run v-list-dns-domain $userbk $domain
+    assert_success
+
+    run nslookup $domain 127.0.0.1
+    assert_success
+}
+
+@test "Restore[1]: From Hestia [MAIL]" {
+    local domain="test.hestia.com"
+
+    run v-list-mail-domain $userbk $domain
+    assert_success
+}
+
+@test "Restore[1]: From Hestia [MAIL-Account]" {
+    local domain="test.hestia.com"
+
+    run v-list-mail-account $userbk $domain testaccount
+    assert_success
+}
+
+@test "Restore[1]: From Hestia [DB]" {
+    run v-list-database $userbk "${userbk}_db"
+    assert_success
+}
+
+@test "Restore[1]: From Hestia [CRON]" {
+    run v-list-cron-job $userbk 1
+    assert_success
+}
+
+@test "Restore[1]: From Hestia Cleanup" {
+    run v-delete-user $userbk
+    assert_success
+    refute_output
+}
+
+
+@test "Restore[2]: Hestia archive over a existing user" {
+    if [ -d "$HOMEDIR/$userbk" ]; then
+        run v-delete-user $userbk
+        assert_success
+        refute_output
+    fi
+
+    if [ ! -d "$HOMEDIR/$userbk" ]; then
+        run v-add-user $userbk $userbk [email protected]
+        assert_success
+    fi
+
+    mkdir -p /backup
+
+    local archive_name="hestia111.2020-03-26"
+    run wget --quiet --tries=3 --timeout=15 --read-timeout=15 --waitretry=3 --no-dns-cache "https://hestiacp.com/testing/data/${archive_name}.tar" -O "/backup/${archive_name}.tar"
+    assert_success
+
+    run v-restore-user $userbk "${archive_name}.tar"
+    assert_success
+
+    rm "/backup/${archive_name}.tar"
+}
+
+@test "Restore[2]: From Hestia [WEB]" {
+    local domain="test.hestia.com"
+    validate_web_domain $userbk "${domain}" 'Hello Hestia'
+}
+
+@test "Restore[2]: From Hestia [DNS]" {
+    local domain="test.hestia.com"
+
+    run v-list-dns-domain $userbk $domain
+    assert_success
+
+    run nslookup $domain 127.0.0.1
+    assert_success
+}
+
+@test "Restore[2]: From Hestia [MAIL]" {
+    local domain="test.hestia.com"
+
+    run v-list-mail-domain $userbk $domain
+    assert_success
+}
+
+@test "Restore[2]: From Hestia [MAIL-Account]" {
+    local domain="test.hestia.com"
+
+    run v-list-mail-account $userbk $domain testaccount
+    assert_success
+}
+
+@test "Restore[2]: From Hestia [DB]" {
+    run v-list-database $userbk "${userbk}_db"
+    assert_success
+}
+
+@test "Restore[2]: From Hestia [CRON]" {
+    run v-list-cron-job $userbk 1
+    assert_success
+}
+
+@test "Restore[2]: From Hestia Cleanup" {
+    run v-delete-user $userbk
+    assert_success
+    refute_output
+}
+
+@test "Restore[3]: Hestia (zstd) archive for a non-existing user" {
+    if [ -d "$HOMEDIR/$userbk" ]; then
+        run v-delete-user $userbk
+        assert_success
+        refute_output
+    fi
+    
+    mkdir -p /backup
+    
+    local archive_name="hestia131.2020-12-12"
+    run wget --quiet --tries=3 --timeout=15 --read-timeout=15 --waitretry=3 --no-dns-cache "https://hestiacp.com/testing/data/${archive_name}.tar" -O "/backup/${archive_name}.tar"
+    assert_success
+    
+    run v-restore-user $userbk "${archive_name}.tar"
+    assert_success
+    
+    rm "/backup/${archive_name}.tar"
+}
+
+@test "Restore[3]: From Hestia [WEB]" {
+    local domain="test.hestia.com"
+    validate_web_domain $userbk $domain 'Hello Hestia'
+}
+
+@test "Restore[3]: From Hestia [DNS]" {
+    local domain="test.hestia.com"
+    
+    run v-list-dns-domain $userbk $domain
+    assert_success
+    
+    run nslookup $domain 127.0.0.1
+    assert_success
+}
+
+@test "Restore[3]: From Hestia [MAIL]" {
+    local domain="test.hestia.com"
+    
+    run v-list-mail-domain $userbk $domain
+    assert_success
+}
+
+@test "Restore[3]: From Hestia [MAIL-Account]" {
+    local domain="test.hestia.com"
+    
+    run v-list-mail-account $userbk $domain testaccount
+    assert_success
+}
+
+@test "Restore[3]: From Hestia [DB]" {
+    run v-list-database $userbk "${userbk}_db"
+    assert_success
+}
+
+@test "Restore[3]: From Hestia [CRON]" {
+    run v-list-cron-job $userbk 1
+    assert_success
+}
+
+@test "Restore[3]: From Hestia Cleanup" {
+    run v-delete-user $userbk
+    assert_success
+    refute_output
+}
+
+@test "Restore[4]: Hestia (zstd) archive for a existing user" {
+    if [ -d "$HOMEDIR/$userbk" ]; then
+        run v-delete-user $userbk
+        assert_success
+        refute_output
+    fi
+
+    if [ ! -d "$HOMEDIR/$userbk" ]; then
+        run v-add-user $userbk $userbk [email protected]
+        assert_success
+    fi
+
+    mkdir -p /backup
+    
+    local archive_name="hestia131.2020-12-12"
+    run wget --quiet --tries=3 --timeout=15 --read-timeout=15 --waitretry=3 --no-dns-cache "https://hestiacp.com/testing/data/${archive_name}.tar" -O "/backup/${archive_name}.tar"
+    assert_success
+    
+    run v-restore-user $userbk "${archive_name}.tar"
+    assert_success
+    
+    rm "/backup/${archive_name}.tar"
+}
+
+@test "Restore[4]: From Hestia [WEB]" {
+    local domain="test.hestia.com"
+    validate_web_domain $userbk $domain 'Hello Hestia'
+}
+
+@test "Restore[4]: From Hestia [DNS]" {
+    local domain="test.hestia.com"
+    
+    run v-list-dns-domain $userbk $domain
+    assert_success
+    
+    run nslookup $domain 127.0.0.1
+    assert_success
+}
+
+@test "Restore[4]: From Hestia [MAIL]" {
+    local domain="test.hestia.com"
+    
+    run v-list-mail-domain $userbk $domain
+    assert_success
+}
+
+@test "Restore[4]: From Hestia [MAIL-Account]" {
+    local domain="test.hestia.com"
+    
+    run v-list-mail-account $userbk $domain testaccount
+    assert_success
+}
+
+@test "Restore[4]: From Hestia [DB]" {
+    run v-list-database $userbk "${userbk}_db"
+    assert_success
+}
+
+@test "Restore[4]: From Hestia [CRON]" {
+    run v-list-cron-job $userbk 1
+    assert_success
+}
+
+@test "Restore[4]: From Hestia Cleanup" {
+    run v-delete-user $userbk
+    assert_success
+    refute_output
+}
+
+
+# Testing Vesta Backups
+@test "Restore[1]: Vesta archive for a non-existing user" {
+    if [ -d "$HOMEDIR/$userbk" ]; then
+        run v-delete-user $userbk
+        assert_success
+        refute_output
+    fi
+
+    mkdir -p /backup
+
+    local archive_name="vesta09823.2018-10-18"
+    run wget --quiet --tries=3 --timeout=15 --read-timeout=15 --waitretry=3 --no-dns-cache "https://hestiacp.com/testing/data/${archive_name}.tar" -O "/backup/${archive_name}.tar"
+    assert_success
+
+    run v-restore-user $userbk "${archive_name}.tar"
+    assert_success
+
+    rm "/backup/${archive_name}.tar"
+}
+
+@test "Restore[1]: From Vesta [WEB]" {
+    local domain="vesta09823.tld"
+    validate_web_domain $userbk $domain 'Hello Vesta'
+}
+
+@test "Restore[1]: From Vesta [DNS]" {
+    local domain="vesta09823.tld"
+
+    run v-list-dns-domain $userbk $domain
+    assert_success
+
+    run nslookup $domain 127.0.0.1
+    assert_success
+}
+
+@test "Restore[1]: From Vesta [MAIL]" {
+    local domain="vesta09823.tld"
+
+    run v-list-mail-domain $userbk $domain
+    assert_success
+}
+
+@test "Restore[1]: From Vesta [MAIL-Account]" {
+    local domain="vesta09823.tld"
+
+    run v-list-mail-account $userbk $domain testaccount
+    assert_success
+}
+
+@test "Restore[1]: From Vesta [DB]" {
+    run v-list-database $userbk "${userbk}_db"
+    assert_success
+}
+
+@test "Restore[1]: From Vesta [CRON]" {
+    run v-list-cron-job $userbk 1
+    assert_success
+}
+
+@test "Restore[1]: From Vesta Cleanup" {
+    run v-delete-user $userbk
+    assert_success
+    refute_output
+}
+
+
+@test "Restore[2]: Vesta archive over a existing user" {
+    if [ -d "$HOMEDIR/$userbk" ]; then
+        run v-delete-user $userbk
+        assert_success
+        refute_output
+    fi
+
+    if [ ! -d "$HOMEDIR/$userbk" ]; then
+        run v-add-user $userbk $userbk [email protected]
+        assert_success
+    fi
+
+    mkdir -p /backup
+
+    local archive_name="vesta09823.2018-10-18"
+    run wget --quiet --tries=3 --timeout=15 --read-timeout=15 --waitretry=3 --no-dns-cache "https://hestiacp.com/testing/data/${archive_name}.tar" -O "/backup/${archive_name}.tar"
+    assert_success
+
+    run v-restore-user $userbk "${archive_name}.tar"
+    assert_success
+
+    rm "/backup/${archive_name}.tar"
+}
+
+@test "Restore[2]: From Vesta [WEB]" {
+    local domain="vesta09823.tld"
+    validate_web_domain $userbk "${domain}" 'Hello Vesta'
+}
+
+@test "Restore[2]: From Vesta [DNS]" {
+    local domain="vesta09823.tld"
+
+    run v-list-dns-domain $userbk $domain
+    assert_success
+
+    run nslookup $domain 127.0.0.1
+    assert_success
+}
+
+@test "Restore[2]: From Vesta [MAIL]" {
+    local domain="vesta09823.tld"
+
+    run v-list-mail-domain $userbk $domain
+    assert_success
+}
+
+@test "Restore[2]: From Vesta [MAIL-Account]" {
+    local domain="vesta09823.tld"
+
+    run v-list-mail-account $userbk $domain testaccount
+    assert_success
+}
+
+@test "Restore[2]: From Vesta [DB]" {
+    run v-list-database $userbk "${userbk}_db"
+    assert_success
+}
+
+@test "Restore[2]: From Vesta [CRON]" {
+    run v-list-cron-job $userbk 1
+    assert_success
+}
+
+@test "Restore[2]: From Vesta Cleanup" {
+    run v-delete-user $userbk
+    assert_success
+    refute_output
+}

Разница между файлами не показана из-за своего большого размера
+ 396 - 501
test/test.bats


+ 3 - 2
web/add/db/index.php

@@ -89,9 +89,10 @@ if (!empty($_POST['ok'])) {
         $to = $v_db_email;
         $subject = _("Database Credentials");
         $hostname = exec('hostname');
-        $from = sprintf(_('MAIL_FROM'),$hostname);
+        $from = "noreply@".$hostname;
+        $from_name = _('Hestia Control Panel');
         $mailtext = sprintf(_('DATABASE_READY'),$user."_".$_POST['v_database'],$user."_".$_POST['v_dbuser'],$_POST['v_password'],$db_admin_link);
-        send_email($to, $subject, $mailtext, $from);
+        send_email($to, $subject, $mailtext, $from, $from_name);
     }
 
     // Flush field values on success

+ 3 - 2
web/add/mail/index.php

@@ -269,9 +269,10 @@ if (!empty($_POST['ok_acc'])) {
         $to = $v_send_email;
         $subject = _("Email Credentials");
         $hostname = exec('hostname');
-        $from = sprintf(_('MAIL_FROM'), $hostname);
+        $from = "noreply@".$hostname;
+        $from_name = _('Hestia Control Panel');
         $mailtext = $v_credentials;
-        send_email($to, $subject, $mailtext, $from);
+        send_email($to, $subject, $mailtext, $from, $from_name);
     }
 
     // Flush field values on success

+ 3 - 2
web/add/user/index.php

@@ -104,7 +104,8 @@ if (!empty($_POST['ok'])) {
         $subject = _("Welcome to Hestia Control Panel");
         $hostname = exec('hostname');
         unset($output);
-        $from = sprintf(_('MAIL_FROM'),$hostname);
+        $from = "noreply@".$hostname;
+        $from_name = _('Hestia Control Panel');
 
         if (!empty($_POST['v_name'])) {
             $mailtext = sprintf(_('GREETINGS_GORDON'),$_POST['v_name'])."\r\n";
@@ -113,7 +114,7 @@ if (!empty($_POST['ok'])) {
         }
         
         $mailtext .= sprintf(_('ACCOUNT_READY'),$_SERVER['HTTP_HOST'],$_POST['v_username'],$_POST['v_password']);
-        send_email($to, $subject, $mailtext, $from);
+        send_email($to, $subject, $mailtext, $from, $from_name, $_POST['name']);
         putenv("LANGUAGE=".detect_user_language());
     }
 

+ 3 - 2
web/add/web/index.php

@@ -381,9 +381,10 @@ if (!empty($_POST['ok'])) {
                     if ((!empty($v_ftp_user_data['v_ftp_email'])) && (empty($_SESSION['error_msg']))) {
                         $to = $v_ftp_user_data['v_ftp_email'];
                         $subject = _("FTP login credentials");
-                        $from = sprintf(_('MAIL_FROM'), $v_domain );
+                        $from = "noreply@".$v_domain;
+                        $from_name = _('Hestia Control Panel');
                         $mailtext = sprintf(_('FTP_ACCOUNT_READY'),$v_domain,$user,$v_ftp_user_data['v_ftp_user'],$v_ftp_user_data['v_ftp_password']);
-                        send_email($to, $subject, $mailtext, $from);
+                        send_email($to, $subject, $mailtext, $from, $from_name);
                         unset($v_ftp_email);
                     }
                 } else {

+ 1 - 1
web/add/webapp/index.php

@@ -91,7 +91,7 @@ if(!empty($installer)) {
     $v_web_apps = array();
     foreach($appInstallers as $app){
         $hestia = new \Hestia\System\HestiaApp();
-        if( preg_match('/Installers\/([a-zA-Z0-0].*)\/([a-zA-Z0-0].*).php/', $app, $matches)){
+        if( preg_match('/Installers\/([a-zA-Z][a-zA-Z0,9].*)\/([a-zA-Z][a-zA-Z0,9].*).php/', $app, $matches)){
             if ($matches[1] != "Resources"){
                 $app_installer_class = '\Hestia\WebApp\Installers\\'.$matches[1].'\\' . $matches[1] . 'Setup';
                 $app_installer = new $app_installer_class($v_domain, $hestia);

+ 0 - 550
web/css/dependencies/jquery-custom-dialogs.css

@@ -1,550 +0,0 @@
-/*!
- * jQuery UI CSS Framework 1.8.20
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Theming/API
- */
-
-/* Layout helpers
-----------------------------------*/
-.ui-helper-hidden { display: none; }
-.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
-.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
-.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
-.ui-helper-clearfix:after { clear: both; }
-.ui-helper-clearfix { zoom: 1; }
-.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
-
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-disabled { cursor: default !important; }
-
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Overlays */
-.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: #999;}
-
-
-/*!
- * jQuery UI CSS Framework 1.8.20
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Theming/API
- *
- * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Arial, Helvetica, sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
- */
-
-
-/* Component containers
-----------------------------------*/
-.ui-widget { font-family: 'Exo'; font-size: 0.85rem; }
-.ui-widget .ui-widget { font-size: 10pt; }
-.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: 'Exo'; }
-.ui-widget-content { border: 1px solid #aaaaaa; color: #ccc; }
-.ui-widget-content a { color: #222222; }
-.ui-widget-header { color: #444; font-size: 10pt; font-weight: bold;}
-.ui-widget-header a { color: #222222; }
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
-.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
-.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
-.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
-.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
-.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
-.ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
-.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
-
-/* Icons
-----------------------------------*/
-
-/* states and images 
-.ui-icon { width: 16px; height: 16px; }
-.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
-.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
-.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
-.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
-.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
-*/
-
-/* positioning */
-.ui-icon-carat-1-n { background-position: 0 0; }
-.ui-icon-carat-1-ne { background-position: -16px 0; }
-.ui-icon-carat-1-e { background-position: -32px 0; }
-.ui-icon-carat-1-se { background-position: -48px 0; }
-.ui-icon-carat-1-s { background-position: -64px 0; }
-.ui-icon-carat-1-sw { background-position: -80px 0; }
-.ui-icon-carat-1-w { background-position: -96px 0; }
-.ui-icon-carat-1-nw { background-position: -112px 0; }
-.ui-icon-carat-2-n-s { background-position: -128px 0; }
-.ui-icon-carat-2-e-w { background-position: -144px 0; }
-.ui-icon-triangle-1-n { background-position: 0 -16px; }
-.ui-icon-triangle-1-ne { background-position: -16px -16px; }
-.ui-icon-triangle-1-e { background-position: -32px -16px; }
-.ui-icon-triangle-1-se { background-position: -48px -16px; }
-.ui-icon-triangle-1-s { background-position: -64px -16px; }
-.ui-icon-triangle-1-sw { background-position: -80px -16px; }
-.ui-icon-triangle-1-w { background-position: -96px -16px; }
-.ui-icon-triangle-1-nw { background-position: -112px -16px; }
-.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
-.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
-.ui-icon-arrow-1-n { background-position: 0 -32px; }
-.ui-icon-arrow-1-ne { background-position: -16px -32px; }
-.ui-icon-arrow-1-e { background-position: -32px -32px; }
-.ui-icon-arrow-1-se { background-position: -48px -32px; }
-.ui-icon-arrow-1-s { background-position: -64px -32px; }
-.ui-icon-arrow-1-sw { background-position: -80px -32px; }
-.ui-icon-arrow-1-w { background-position: -96px -32px; }
-.ui-icon-arrow-1-nw { background-position: -112px -32px; }
-.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
-.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
-.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
-.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
-.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
-.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
-.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
-.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
-.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
-.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
-.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
-.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
-.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
-.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
-.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
-.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
-.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
-.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
-.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
-.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
-.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
-.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
-.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
-.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
-.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
-.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
-.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
-.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
-.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
-.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
-.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
-.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
-.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
-.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
-.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
-.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
-.ui-icon-arrow-4 { background-position: 0 -80px; }
-.ui-icon-arrow-4-diag { background-position: -16px -80px; }
-.ui-icon-extlink { background-position: -32px -80px; }
-.ui-icon-newwin { background-position: -48px -80px; }
-.ui-icon-refresh { background-position: -64px -80px; }
-.ui-icon-shuffle { background-position: -80px -80px; }
-.ui-icon-transfer-e-w { background-position: -96px -80px; }
-.ui-icon-transferthick-e-w { background-position: -112px -80px; }
-.ui-icon-folder-collapsed { background-position: 0 -96px; }
-.ui-icon-folder-open { background-position: -16px -96px; }
-.ui-icon-document { background-position: -32px -96px; }
-.ui-icon-document-b { background-position: -48px -96px; }
-.ui-icon-note { background-position: -64px -96px; }
-.ui-icon-mail-closed { background-position: -80px -96px; }
-.ui-icon-mail-open { background-position: -96px -96px; }
-.ui-icon-suitcase { background-position: -112px -96px; }
-.ui-icon-comment { background-position: -128px -96px; }
-.ui-icon-person { background-position: -144px -96px; }
-.ui-icon-print { background-position: -160px -96px; }
-.ui-icon-trash { background-position: -176px -96px; }
-.ui-icon-locked { background-position: -192px -96px; }
-.ui-icon-unlocked { background-position: -208px -96px; }
-.ui-icon-bookmark { background-position: -224px -96px; }
-.ui-icon-tag { background-position: -240px -96px; }
-.ui-icon-home { background-position: 0 -112px; }
-.ui-icon-flag { background-position: -16px -112px; }
-.ui-icon-calendar { background-position: -32px -112px; }
-.ui-icon-cart { background-position: -48px -112px; }
-.ui-icon-pencil { background-position: -64px -112px; }
-.ui-icon-clock { background-position: -80px -112px; }
-.ui-icon-disk { background-position: -96px -112px; }
-.ui-icon-calculator { background-position: -112px -112px; }
-.ui-icon-zoomin { background-position: -128px -112px; }
-.ui-icon-zoomout { background-position: -144px -112px; }
-.ui-icon-search { background-position: -160px -112px; }
-.ui-icon-wrench { background-position: -176px -112px; }
-.ui-icon-gear { background-position: -192px -112px; }
-.ui-icon-heart { background-position: -208px -112px; }
-.ui-icon-star { background-position: -224px -112px; }
-.ui-icon-link { background-position: -240px -112px; }
-.ui-icon-cancel { background-position: 0 -128px; }
-.ui-icon-plus { background-position: -16px -128px; }
-.ui-icon-plusthick { background-position: -32px -128px; }
-.ui-icon-minus { background-position: -48px -128px; }
-.ui-icon-minusthick { background-position: -64px -128px; }
-.ui-icon-key { background-position: -112px -128px; }
-.ui-icon-lightbulb { background-position: -128px -128px; }
-.ui-icon-scissors { background-position: -144px -128px; }
-.ui-icon-clipboard { background-position: -160px -128px; }
-.ui-icon-copy { background-position: -176px -128px; }
-.ui-icon-contact { background-position: -192px -128px; }
-.ui-icon-image { background-position: -208px -128px; }
-.ui-icon-video { background-position: -224px -128px; }
-.ui-icon-script { background-position: -240px -128px; }
-.ui-icon-alert { background-position: 0 -144px; }
-.ui-icon-info { background-position: -16px -144px; }
-.ui-icon-notice { background-position: -32px -144px; }
-.ui-icon-help { background-position: -48px -144px; }
-.ui-icon-check { background-position: -64px -144px; }
-.ui-icon-bullet { background-position: -80px -144px; }
-.ui-icon-radio-off { background-position: -96px -144px; }
-.ui-icon-radio-on { background-position: -112px -144px; }
-.ui-icon-pin-w { background-position: -128px -144px; }
-.ui-icon-pin-s { background-position: -144px -144px; }
-.ui-icon-play { background-position: 0 -160px; }
-.ui-icon-pause { background-position: -16px -160px; }
-.ui-icon-seek-next { background-position: -32px -160px; }
-.ui-icon-seek-prev { background-position: -48px -160px; }
-.ui-icon-seek-end { background-position: -64px -160px; }
-.ui-icon-seek-start { background-position: -80px -160px; }
-/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
-.ui-icon-seek-first { background-position: -80px -160px; }
-.ui-icon-stop { background-position: -96px -160px; }
-.ui-icon-eject { background-position: -112px -160px; }
-.ui-icon-volume-off { background-position: -128px -160px; }
-.ui-icon-volume-on { background-position: -144px -160px; }
-.ui-icon-power { background-position: 0 -176px; }
-.ui-icon-signal-diag { background-position: -16px -176px; }
-.ui-icon-signal { background-position: -32px -176px; }
-.ui-icon-battery-0 { background-position: -48px -176px; }
-.ui-icon-battery-1 { background-position: -64px -176px; }
-.ui-icon-battery-2 { background-position: -80px -176px; }
-.ui-icon-battery-3 { background-position: -96px -176px; }
-.ui-icon-circle-plus { background-position: 0 -192px; }
-.ui-icon-circle-minus { background-position: -16px -192px; }
-.ui-icon-circle-close { background-position: -32px -192px; }
-.ui-icon-circle-triangle-e { background-position: -48px -192px; }
-.ui-icon-circle-triangle-s { background-position: -64px -192px; }
-.ui-icon-circle-triangle-w { background-position: -80px -192px; }
-.ui-icon-circle-triangle-n { background-position: -96px -192px; }
-.ui-icon-circle-arrow-e { background-position: -112px -192px; }
-.ui-icon-circle-arrow-s { background-position: -128px -192px; }
-.ui-icon-circle-arrow-w { background-position: -144px -192px; }
-.ui-icon-circle-arrow-n { background-position: -160px -192px; }
-.ui-icon-circle-zoomin { background-position: -176px -192px; }
-.ui-icon-circle-zoomout { background-position: -192px -192px; }
-.ui-icon-circle-check { background-position: -208px -192px; }
-.ui-icon-circlesmall-plus { background-position: 0 -208px; }
-.ui-icon-circlesmall-minus { background-position: -16px -208px; }
-.ui-icon-circlesmall-close { background-position: -32px -208px; }
-.ui-icon-squaresmall-plus { background-position: -48px -208px; }
-.ui-icon-squaresmall-minus { background-position: -64px -208px; }
-.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
-.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
-.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
-.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
-.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
-.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
-
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Overlays */
-.ui-widget-overlay { opacity: .30;filter:Alpha(Opacity=30); }
-.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*!
- * jQuery UI Resizable 1.8.20
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Resizable#theming
- */
-.ui-resizable { position: relative;}
-.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
-.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
-.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
-.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
-.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
-.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
-.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
-.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
-.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
-.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*!
- * jQuery UI Selectable 1.8.20
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Selectable#theming
- */
-.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
-/*!
- * jQuery UI Accordion 1.8.20
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Accordion#theming
- */
-/* IE/Win - Fix animation bug - #4615 */
-.ui-accordion { width: 100%; }
-.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
-.ui-accordion .ui-accordion-li-fix { display: inline; }
-.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
-.ui-accordion .ui-accordion-header a { display: block; font-size: 10pt; padding: .5em .5em .5em .7em; }
-.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
-.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
-.ui-accordion .ui-accordion-content { padding: 10pt 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
-.ui-accordion .ui-accordion-content-active { display: block; }
-/*!
- * jQuery UI Autocomplete 1.8.20
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Autocomplete#theming
- */
-.ui-autocomplete { position: absolute; cursor: default; }	
-
-/* workarounds */
-* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
-
-/*
- * jQuery UI Menu 1.8.20
- *
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Menu#theming
- */
-.ui-menu {
-	list-style:none;
-	padding: 2px;
-	margin: 0;
-	display:block;
-	float: left;
-}
-.ui-menu .ui-menu {
-	margin-top: -3px;
-}
-.ui-menu .ui-menu-item {
-	margin:0;
-	padding: 0;
-	zoom: 1;
-	float: left;
-	clear: left;
-	width: 100%;
-}
-.ui-menu .ui-menu-item a {
-	text-decoration:none;
-	display:block;
-	padding:.2em .4em;
-	line-height:1.5;
-	zoom:1;
-}
-.ui-menu .ui-menu-item a.ui-state-hover,
-.ui-menu .ui-menu-item a.ui-state-active {
-	font-weight: normal;
-	margin: -1px;
-}
-/*!
- * jQuery UI Button 1.8.20
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Button#theming
- */
-/*
-.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .10pt; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; }
-.ui-button { filter:chroma(color=#000000); cursor: pointer; color: #fff; background-color: #f79b44; border: 1px solid #f79b44; border-radius: 3px 3px 3px 3px; font-weight: bold; font-size: 14px; padding: 2px 16px; width: 108px; height: 34px; }
-.ui-button:hover { border: 1px solid #9e9e9e; background-color: #9e9e9e; color: #fff;}
-.ui-button:active { background-color: #ccc; color: #fff; border: 1px solid #ccc; }*/
-.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
-button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
-.ui-button-icons-only { width: 3.4em; } 
-button.ui-button-icons-only { width: 3.7em; } 
-
-/*button text element */
-.ui-button .ui-button-text { display: block; line-height: 1.4;  }
-.ui-button-text-only .ui-button-text { padding: .4em 10pt; }
-.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
-.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 10pt .4em 2.10pt; }
-.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.10pt .4em 10pt; }
-.ui-button-text-icons .ui-button-text { padding-left: 2.10pt; padding-right: 2.10pt; }
-/* no icon support for input elements, provide padding by default */
-input.ui-button { padding: .4em 10pt; }
-
-/*button icon element(s) */
-.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
-.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
-.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
-.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
-.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
-
-/*button sets*/
-.ui-buttonset { margin-right: 7px; }
-.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
-
-/* workarounds */
-button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
-/*!
- * jQuery UI Dialog 1.8.20
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Dialog#theming
- */
-.ui-dialog { background: none repeat scroll 0 0 #333; border: 1px solid #333; border-radius: 3px; box-shadow: 0 2px 11px 0 rgba(0, 0, 0, 0.5); font-family: 'Exo', sans-serif; overflow: hidden; padding: 27px 0 5px; position: absolute; width: 480px; }
-.ui-dialog .ui-dialog-titlebar { padding: 2px 26px 0; position: relative;  }
-.ui-dialog .ui-dialog-title { float: left; margin: .10pt 16px .10pt 0;  font-family: 'Exo', sans-serif; color: #ebe697; font-size: 11px; letter-spacing: 1px; text-transform: uppercase; }
-.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
-.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
-.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
-.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: 10px 14px 30px; background: none; overflow: auto; zoom: 1; }
-.ui-dialog .ui-dialog-buttonpane { border-color: #555; border-style: solid none none; text-align: left; margin: .5em 0 0 0; padding: 6px 0 1px 1px; }
-.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { text-align: center; ;margin: 0 0 0 0px; }
-.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
-.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
-.ui-draggable .ui-dialog-titlebar { cursor: move; }
-/*!
- * jQuery UI Slider 1.8.20
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Slider#theming
- */
-.ui-slider { position: relative; text-align: left; }
-.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
-.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
-
-.ui-slider-horizontal { height: .8em; }
-.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
-.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
-.ui-slider-horizontal .ui-slider-range-min { left: 0; }
-.ui-slider-horizontal .ui-slider-range-max { right: 0; }
-
-.ui-slider-vertical { width: .8em; height: 100px; }
-.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
-.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
-.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
-.ui-slider-vertical .ui-slider-range-max { top: 0; }/*!
- * jQuery UI Tabs 1.8.20
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Tabs#theming
- */
-.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
-.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
-.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
-.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 10pt; text-decoration: none; }
-.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
-.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
-.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
-.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 10pt 1.4em; background: none; }
-.ui-tabs .ui-tabs-hide { display: none !important; }
-/*!
- * jQuery UI Datepicker 1.8.20
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Datepicker#theming
- */
-.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
-.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
-.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
-.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
-.ui-datepicker .ui-datepicker-prev { left:2px; }
-.ui-datepicker .ui-datepicker-next { right:2px; }
-.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
-.ui-datepicker .ui-datepicker-next-hover { right:1px; }
-.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
-.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
-.ui-datepicker .ui-datepicker-title select { font-size:10pt; margin:1px 0; }
-.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
-.ui-datepicker select.ui-datepicker-month, 
-.ui-datepicker select.ui-datepicker-year { width: 49%;}
-.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
-.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
-.ui-datepicker td { border: 0; padding: 1px; }
-.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
-.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
-.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
-.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
-
-/* with multiple calendars */
-.ui-datepicker.ui-datepicker-multi { width:auto; }
-.ui-datepicker-multi .ui-datepicker-group { float:left; }
-.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
-.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
-.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
-.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
-.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
-.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
-.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
-.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
-
-/* RTL support */
-.ui-datepicker-rtl { direction: rtl; }
-.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
-.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
-.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
-.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
-.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
-.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
-.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
-.ui-datepicker-rtl .ui-datepicker-group { float:right; }
-.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
-.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
-
-/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
-.ui-datepicker-cover {
-    display: none; /*sorry for IE5*/
-    display/**/: block; /*sorry for IE5*/
-    position: absolute; /*must have*/
-    z-index: -1; /*must have*/
-    filter: mask(); /*must have*/
-    top: -4px; /*must have*/
-    left: -4px; /*must have*/
-    width: 200px; /*must have*/
-    height: 200px; /*must have*/
-}/*!
- * jQuery UI Progressbar 1.8.20
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Progressbar#theming
- */
-.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
-.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }

Разница между файлами не показана из-за своего большого размера
+ 2 - 0
web/css/dependencies/jquery-ui.custom.min.css


+ 150 - 0
web/css/src/dependencies/jquery-ui.custom.css

@@ -0,0 +1,150 @@
+/*!
+ * JQuery UI Custom + few changes
+ */
+.ui-dialog {
+	position: absolute;
+	top: 0;
+	left: 0;
+	padding: .2em;
+	outline: 0;
+	z-index: 1000 !important;
+}
+.ui-dialog .ui-dialog-titlebar {
+	padding: .4em 1em;
+	position: relative;
+}
+.ui-dialog .ui-dialog-title {
+	float: left;
+	margin: .1em 0;
+	white-space: nowrap;
+	width: 90%;
+	overflow: hidden;
+	text-overflow: ellipsis;
+}
+.ui-dialog .ui-dialog-titlebar-close {
+	position: absolute;
+	right: .3em;
+	top: 50%;
+	width: 20px;
+	margin: -10px 0 0 0;
+	padding: 1px;
+	height: 20px;
+}
+.ui-dialog .ui-dialog-content {
+	position: relative;
+	border: 0;
+	padding: .5em 1em;
+	background: none;
+	overflow: auto;
+}
+.ui-dialog .ui-dialog-buttonpane {
+	text-align: left;
+	border-width: 1px 0 0 0;
+	background-image: none;
+	margin-top: .5em;
+	padding: .3em 1em .5em .4em;
+}
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
+	float: right;
+}
+.ui-dialog .ui-dialog-buttonpane button {
+	margin: .5em .4em .5em 0;
+	cursor: pointer;
+}
+.ui-dialog .ui-resizable-n {
+	height: 2px;
+	top: 0;
+}
+.ui-dialog .ui-resizable-e {
+	width: 2px;
+	right: 0;
+}
+.ui-dialog .ui-resizable-s {
+	height: 2px;
+	bottom: 0;
+}
+.ui-dialog .ui-resizable-w {
+	width: 2px;
+	left: 0;
+}
+.ui-dialog .ui-resizable-se,
+.ui-dialog .ui-resizable-sw,
+.ui-dialog .ui-resizable-ne,
+.ui-dialog .ui-resizable-nw {
+	width: 7px;
+	height: 7px;
+}
+.ui-dialog .ui-resizable-se {
+	right: 0;
+	bottom: 0;
+}
+.ui-dialog .ui-resizable-sw {
+	left: 0;
+	bottom: 0;
+}
+.ui-dialog .ui-resizable-ne {
+	right: 0;
+	top: 0;
+}
+.ui-dialog .ui-resizable-nw {
+	left: 0;
+	top: 0;
+}
+.ui-tabs {
+	position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+	padding: .2em;
+}
+.ui-tabs .ui-tabs-nav {
+	margin: 0;
+	padding: .2em .2em 0;
+}
+.ui-tabs .ui-tabs-nav li {
+	list-style: none;
+	float: left;
+	position: relative;
+	top: 0;
+	margin: 1px .2em 0 0;
+	border-bottom-width: 0;
+	padding: 0;
+	white-space: nowrap;
+}
+.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
+	float: left;
+	padding: .5em 1em;
+	text-decoration: none;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active {
+	margin-bottom: -1px;
+	padding-bottom: 1px;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
+	cursor: text;
+}
+.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
+	cursor: pointer;
+}
+.ui-tabs .ui-tabs-panel {
+	display: block;
+	border-width: 0;
+	padding: 1em 1.4em;
+	background: none;
+}
+.ui-dialog-titlebar-close{
+	display: none !important;
+}
+
+.ui-tabs-panel{
+	clear:both !important;
+}
+
+.ui-widget-overlay {
+	 background-color: rgba(0,0,0,0.9);
+	 height: 100%;
+	 width:100%;
+	 z-index: 999 !important;
+	 position: absolute;
+	 top:0px;
+	 left:0px;
+ }

+ 1 - 1
web/css/src/themes/dark.css

@@ -1472,7 +1472,7 @@ form#vstobjects.suspended {
 .cron-helper-tabs a:active {
   color: #3b9de8 !important;
 }
-.cron-helper-tabs .ui-tabs-selected a {
+.cron-helper-tabs .ui-tabs-selected a, li[aria-expanded="true"] a {
   color: #ff3478 !important;
 }
 

+ 26 - 26
web/css/src/themes/default.css

@@ -8,8 +8,8 @@
   font-style: normal;
   font-weight: 300;
   src: local('Exo Light'), local('Exo-Light'),
-       url('../../webfonts/exo-v8-latin-ext_latin-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
-       url('../../webfonts/exo-v8-latin-ext_latin-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+       url('/webfonts/exo-v8-latin-ext_latin-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+       url('/webfonts/exo-v8-latin-ext_latin-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
   font-display: swap;
 }
 
@@ -19,8 +19,8 @@
   font-style: italic;
   font-weight: 300;
   src: local('Exo Light Italic'), local('Exo-LightItalic'),
-       url('../../webfonts/exo-v8-latin-ext_latin-300italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
-       url('../../webfonts/exo-v8-latin-ext_latin-300italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+       url('/webfonts/exo-v8-latin-ext_latin-300italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+       url('/webfonts/exo-v8-latin-ext_latin-300italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
   font-display: swap;
 }
 
@@ -30,8 +30,8 @@
   font-style: normal;
   font-weight: 400;
   src: local('Exo Regular'), local('Exo-Regular'),
-       url('../../webfonts/exo-v8-latin-ext_latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
-       url('../../webfonts/exo-v8-latin-ext_latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+       url('/webfonts/exo-v8-latin-ext_latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+       url('/webfonts/exo-v8-latin-ext_latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
   font-display: swap;
 }
 
@@ -41,8 +41,8 @@
   font-style: italic;
   font-weight: 400;
   src: local('Exo Italic'), local('Exo-Italic'),
-       url('../../webfonts/exo-v8-latin-ext_latin-italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
-       url('../../webfonts/exo-v8-latin-ext_latin-italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+       url('/webfonts/exo-v8-latin-ext_latin-italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+       url('/webfonts/exo-v8-latin-ext_latin-italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
   font-display: swap;
 }
 
@@ -52,8 +52,8 @@
   font-style: normal;
   font-weight: 500;
   src: local('Exo Medium'), local('Exo-Medium'),
-       url('../../webfonts/exo-v8-latin-ext_latin-500.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
-       url('../../webfonts/exo-v8-latin-ext_latin-500.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+       url('/webfonts/exo-v8-latin-ext_latin-500.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+       url('/webfonts/exo-v8-latin-ext_latin-500.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
   font-display: swap;
 }
 
@@ -63,8 +63,8 @@
   font-style: italic;
   font-weight: 500;
   src: local('Exo Medium Italic'), local('Exo-MediumItalic'),
-       url('../../webfonts/exo-v8-latin-ext_latin-500italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
-       url('../../webfonts/exo-v8-latin-ext_latin-500italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+       url('/webfonts/exo-v8-latin-ext_latin-500italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+       url('/webfonts/exo-v8-latin-ext_latin-500italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
   font-display: swap;
 }
 
@@ -74,8 +74,8 @@
   font-style: normal;
   font-weight: 600;
   src: local('Exo SemiBold'), local('Exo-SemiBold'),
-       url('../../webfonts/exo-v8-latin-ext_latin-600.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
-       url('../../webfonts/exo-v8-latin-ext_latin-600.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+       url('/webfonts/exo-v8-latin-ext_latin-600.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+       url('/webfonts/exo-v8-latin-ext_latin-600.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
   font-display: swap;
 }
 
@@ -85,8 +85,8 @@
   font-style: italic;
   font-weight: 600;
   src: local('Exo SemiBold Italic'), local('Exo-SemiBoldItalic'),
-       url('../../webfonts/exo-v8-latin-ext_latin-600italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
-       url('../../webfonts/exo-v8-latin-ext_latin-600italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+       url('/webfonts/exo-v8-latin-ext_latin-600italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+       url('/webfonts/exo-v8-latin-ext_latin-600italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
   font-display: swap;
 }
 
@@ -96,8 +96,8 @@
   font-style: normal;
   font-weight: 700;
   src: local('Exo Bold'), local('Exo-Bold'),
-       url('../../webfonts/exo-v8-latin-ext_latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
-       url('../../webfonts/exo-v8-latin-ext_latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+       url('/webfonts/exo-v8-latin-ext_latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+       url('/webfonts/exo-v8-latin-ext_latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
   font-display: swap;
 }
 
@@ -107,8 +107,8 @@
   font-style: italic;
   font-weight: 700;
   src: local('Exo Bold Italic'), local('Exo-BoldItalic'),
-       url('../../webfonts/exo-v8-latin-ext_latin-700italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
-       url('../../webfonts/exo-v8-latin-ext_latin-700italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+       url('/webfonts/exo-v8-latin-ext_latin-700italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
+       url('/webfonts/exo-v8-latin-ext_latin-700italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
   font-display: swap;
 }
 
@@ -121,8 +121,8 @@
 @font-face {
   font-family: 'Inconsolata';
   src: local('Inconsolata Bold'), local('Inconsolata-Bold'),
-      url('../../webfonts/Inconsolata-Bold.woff2') format('woff2'),
-      url('../../webfonts/Inconsolata-Bold.woff') format('woff');
+      url('/webfonts/Inconsolata-Bold.woff2') format('woff2'),
+      url('/webfonts/Inconsolata-Bold.woff') format('woff');
   font-weight: bold;
   font-style: normal;
   font-display: swap;
@@ -132,8 +132,8 @@
 @font-face {
   font-family: 'Inconsolata';
   src: local('Inconsolata Regular'), local('Inconsolata-Regular'),
-      url('../../webfonts/Inconsolata-Regular.woff2') format('woff2'),
-      url('../../webfonts/Inconsolata-Regular.woff') format('woff');
+      url('/webfonts/Inconsolata-Regular.woff2') format('woff2'),
+      url('/webfonts/Inconsolata-Regular.woff') format('woff');
   font-weight: normal;
   font-style: normal;
   font-display: swap;
@@ -843,7 +843,7 @@ a {
   padding: 4rem;
 }
 
-.notification-container .empty . {
+.notification-container .empty {
   color: #54a6e5;
 }
 
@@ -4057,7 +4057,7 @@ form#vstobjects.suspended {
   color: #3b9de8;
 }
 
-.cron-helper-tabs .ui-tabs-selected a {
+.cron-helper-tabs .ui-tabs-selected a, li[aria-expanded="true"] a {
   color: #cc3366;
 }
 

+ 1 - 1
web/css/src/themes/vestia.css

@@ -672,7 +672,7 @@ a.vst-advanced:active, a.vst-advanced:focus {
     box-shadow: none !important;
 }
 
-.cron-helper-tabs .ui-tabs-selected a {
+.cron-helper-tabs .ui-tabs-selected a, li[aria-expanded="true"] a {
     color: #ff6701;
 }
 

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
web/css/themes/dark.min.css


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
web/css/themes/default.min.css


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
web/css/themes/vestia.min.css


+ 3 - 2
web/edit/mail/index.php

@@ -611,9 +611,10 @@ if ((!empty($_POST['save'])) && (!empty($_GET['domain'])) && (!empty($_GET['acco
         $to = $v_send_email;
         $subject = _("Email Credentials");
         $hostname = exec('hostname');
-        $from = sprintf(_('MAIL_FROM'), $hostname);
+        $from = "noreply@".$hostname;
+        $from_name = _('Hestia Control Panel');
         $mailtext = $v_credentials;
-        send_email($to, $subject, $mailtext, $from);
+        send_email($to, $subject, $mailtext, $from, $from_name);
     }
 
     // Set success message

+ 9 - 5
web/edit/server/index.php

@@ -697,10 +697,14 @@ if (!empty($_POST['save'])) {
     // Change INACTIVE_SESSION_TIMEOUT
     if (empty($_SESSION['error_msg'])) {
         if ($_POST['v_inactive_session_timeout'] != $_SESSION['INACTIVE_SESSION_TIMEOUT']) {
-            exec (HESTIA_CMD."v-change-sys-config-value INACTIVE_SESSION_TIMEOUT ".escapeshellarg($_POST['v_inactive_session_timeout']), $output, $return_var);
-            check_return_code($return_var,$output);
-            unset($output);
-            if (empty($_SESSION['error_msg'])) $v_login_style = $_POST['v_inactive_session_timeout'];
+            if($_POST['v_inactive_session_timeout'] < 1){
+               $_SESSION['error_msg'] = _('Inactive session timeout can not lower than 1 minute');
+            }else{
+               exec (HESTIA_CMD."v-change-sys-config-value INACTIVE_SESSION_TIMEOUT ".escapeshellarg($_POST['v_inactive_session_timeout']), $output, $return_var);
+               check_return_code($return_var,$output);
+               unset($output);
+               if (empty($_SESSION['error_msg'])) $v_login_style = $_POST['v_inactive_session_timeout'];
+            }
             $v_security_adv = 'yes';
         }
     }
@@ -795,7 +799,7 @@ if (!empty($_POST['save'])) {
 
     // Change POLICY_USER_VIEW_SUSPENDED
     if (empty($_SESSION['error_msg'])) {
-        if ($_POST['v_policy_user_view_suspended'] != $_SESSION['POLICY_USER_VIEW_SUSPENDED']) {
+        if ($_POST['v_policy_user_view_suspended'] != $_SESSION['POLICY_USER_VIEW_SUSPENDED'] && !empty($_SESSION['POLICY_USER_VIEW_SUSPENDED'])) {
             exec (HESTIA_CMD."v-change-sys-config-value POLICY_USER_VIEW_SUSPENDED ".escapeshellarg($_POST['v_policy_user_view_suspended']), $output, $return_var);
             check_return_code($return_var,$output);
             unset($output);

+ 6 - 4
web/edit/web/index.php

@@ -759,9 +759,10 @@ if (!empty($_POST['save'])) {
                         $to = $v_ftp_user_data['v_ftp_email'];
                         $subject = _("FTP login credentials");
                         $hostname = exec('hostname');
-                        $from = sprintf(_('MAIL_FROM'),$hostname);
+                        $from = "noreply@".$hostname;
+                        $from_name = _('Hestia Control Panel');
                         $mailtext = sprintf(_('FTP_ACCOUNT_READY'),escapeshellarg($_GET['domain']),$user,$v_ftp_username,$v_ftp_user_data['v_ftp_password']);
-                        send_email($to, $subject, $mailtext, $from);
+                        send_email($to, $subject, $mailtext, $from, $from_name);
                         unset($v_ftp_email);
                     }
                     unset($output);
@@ -833,9 +834,10 @@ if (!empty($_POST['save'])) {
                     $to = $v_ftp_user_data['v_ftp_email'];
                     $subject = _("FTP login credentials");
                     $hostname = exec('hostname');
-                    $from = _('MAIL_FROM',$hostname);
+                    $from = "noreply@".$hostname;
+                    $from_name = _('Hestia Control Panel');
                     $mailtext = _('FTP_ACCOUNT_READY',escapeshellarg($_GET['domain']),$user,$v_ftp_username_for_emailing,$v_ftp_user_data['v_ftp_password']);
-                    send_email($to, $subject, $mailtext, $from);
+                    send_email($to, $subject, $mailtext, $from, $from_name);
                     unset($v_ftp_email);
                 }
                 check_return_code($return_var, $output);

+ 5 - 0
web/inc/composer.json

@@ -0,0 +1,5 @@
+{
+    "require": {
+        "phpmailer/phpmailer": "^6.5"
+    }
+}

+ 95 - 0
web/inc/composer.lock

@@ -0,0 +1,95 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+        "This file is @generated automatically"
+    ],
+    "content-hash": "90bbf95869b4e88bf0dc5022e708a458",
+    "packages": [
+        {
+            "name": "phpmailer/phpmailer",
+            "version": "v6.5.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/PHPMailer/PHPMailer.git",
+                "reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a5b5c43e50b7fba655f793ad27303cd74c57363c",
+                "reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c",
+                "shasum": ""
+            },
+            "require": {
+                "ext-ctype": "*",
+                "ext-filter": "*",
+                "ext-hash": "*",
+                "php": ">=5.5.0"
+            },
+            "require-dev": {
+                "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
+                "doctrine/annotations": "^1.2",
+                "phpcompatibility/php-compatibility": "^9.3.5",
+                "roave/security-advisories": "dev-latest",
+                "squizlabs/php_codesniffer": "^3.5.6",
+                "yoast/phpunit-polyfills": "^0.2.0"
+            },
+            "suggest": {
+                "ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
+                "hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
+                "league/oauth2-google": "Needed for Google XOAUTH2 authentication",
+                "psr/log": "For optional PSR-3 debug logging",
+                "stevenmaguire/oauth2-microsoft": "Needed for Microsoft XOAUTH2 authentication",
+                "symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "PHPMailer\\PHPMailer\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "LGPL-2.1-only"
+            ],
+            "authors": [
+                {
+                    "name": "Marcus Bointon",
+                    "email": "[email protected]"
+                },
+                {
+                    "name": "Jim Jagielski",
+                    "email": "[email protected]"
+                },
+                {
+                    "name": "Andy Prevost",
+                    "email": "[email protected]"
+                },
+                {
+                    "name": "Brent R. Matzelle"
+                }
+            ],
+            "description": "PHPMailer is a full-featured email creation and transfer class for PHP",
+            "support": {
+                "issues": "https://github.com/PHPMailer/PHPMailer/issues",
+                "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.5.0"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/Synchro",
+                    "type": "github"
+                }
+            ],
+            "time": "2021-06-16T14:33:43+00:00"
+        }
+    ],
+    "packages-dev": [],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": [],
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": [],
+    "platform-dev": [],
+    "plugin-api-version": "2.1.0"
+}

Разница между файлами не показана из-за своего большого размера
+ 0 - 1
web/inc/jquery/jquery-3.5.1.min.js


+ 3 - 2
web/inc/mail-wrapper.php

@@ -27,12 +27,13 @@ if (!empty( $data['config']['LANGUAGE'])) {
 }
 
 // Define vars
-$from = 'Hestia Control Panel <noreply@'.gethostname().'>';
+$from = 'noreply@'.gethostname();
+$from_name = _('Hestia Control Panel');
 $to = $argv[3]."\n";
 $subject = $argv[2]."\n";
 $mailtext = file_get_contents("php://stdin");
 
 // Send email
 if ((!empty($to)) && (!empty($subject))) {
-    send_email($to,$subject,$mailtext,$from);
+    send_email($to,$subject,$mailtext,$from, $from_name);
 }

+ 38 - 15
web/inc/main.php

@@ -1,5 +1,11 @@
 <?php
 
+use PHPMailer\PHPMailer\PHPMailer;
+use PHPMailer\PHPMailer\SMTP;
+use PHPMailer\PHPMailer\Exception;
+
+require 'vendor/autoload.php';
+
 session_start();
 
 define('HESTIA_CMD', '/usr/bin/sudo /usr/local/hestia/bin/');
@@ -288,21 +294,38 @@ function get_percentage($used,$total) {
     return $percent;
 }
 
-function send_email($to, $subject, $mailtext, $from) {
-    $charset = "utf-8";
-    $to = '<' . $to . '>';
-    $boundary = '--' . md5( uniqid('myboundary') );
-    $priorities = array( '1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)' );
-    $priority = $priorities[2];
-    $ctencoding = '8bit';
-    $sep = chr(13) . chr(10);
-    $disposition = 'inline';
-    $subject = "=?$charset?B?" . base64_encode($subject) . '?=';
-    $header = "From: $from \nX-Priority: $priority\nCC:\n";
-    $header .= "Mime-Version: 1.0\nContent-Type: text/plain; charset=$charset \n";
-    $header .= "Content-Transfer-Encoding: $ctencoding\nX-Mailer: Php/libMailv1.3\n";
-    $message = $mailtext;
-    mail($to, $subject, $message, $header);
+function send_email($to, $subject, $mailtext, $from, $from_name, $to_name = '') {
+    $mail = new PHPMailer();
+
+    if (isset($_SESSION['USE_SERVER_SMTP']) && $_SESSION['USE_SERVER_SMTP'] == "true") {
+        $from = $_SESSION['SERVER_SMTP_ADDR'];
+
+        $mail->IsSMTP();
+        $mail->Mailer = "smtp";
+        $mail->SMTPDebug  = 0;
+        $mail->SMTPAuth   = TRUE;
+        $mail->SMTPSecure = $_SESSION['SERVER_SMTP_SECURITY'];
+        $mail->Port       = $_SESSION['SERVER_SMTP_PORT'];
+        $mail->Host       = $_SESSION['SERVER_SMTP_HOST'];
+        $mail->Username   = $_SESSION['SERVER_SMTP_USER'];
+        $mail->Password   = $_SESSION['SERVER_SMTP_PASSWD'];
+    }
+
+    $mail->IsHTML(true);
+    $mail->ClearReplyTos();
+    if (empty($to_name)){
+        $mail->AddAddress($to);
+    }else{
+        $mail->AddAddress($to, $to_name);
+    }
+    $mail->SetFrom($from, $from_name);
+
+    $mail->CharSet = "utf-8";
+    $mail->Subject = $subject;
+    $content = $mailtext;
+    $content = nl2br($content);
+    $mail->MsgHTML($content);
+    $mail->Send();
 }
 
 function list_timezones() {

+ 5 - 5
web/js/events.js

@@ -76,7 +76,7 @@ VE.callbacks.click.do_suspend = function(evt, elm) {
      var ref = elm.hasClass('actions-panel') ? elm : elm.parents('.actions-panel');
      var url = $('input[name="suspend_url"]', ref).val();
      var dialog_elm = ref.find('.confirmation-text-suspention');
-     VE.helpers.createConfirmationDialog(dialog_elm, '', url);
+     VE.helpers.createConfirmationDialog(dialog_elm, $(elm).parent().attr('title'), url);
 }
 
 /*
@@ -86,7 +86,7 @@ VE.callbacks.click.do_unsuspend = function(evt, elm) {
      var ref = elm.hasClass('actions-panel') ? elm : elm.parents('.actions-panel');
      var url = $('input[name="unsuspend_url"]', ref).val();
      var dialog_elm = ref.find('.confirmation-text-suspention');
-     VE.helpers.createConfirmationDialog(dialog_elm, '', url);
+     VE.helpers.createConfirmationDialog(dialog_elm, $(elm).parent().attr('title'), url);
 }
 
 /*
@@ -96,21 +96,21 @@ VE.callbacks.click.do_delete = function(evt, elm) {
      var ref = elm.hasClass('actions-panel') ? elm : elm.parents('.actions-panel');
      var url = $('input[name="delete_url"]', ref).val();
      var dialog_elm = ref.find('.confirmation-text-delete');
-     VE.helpers.createConfirmationDialog(dialog_elm, '', url);
+     VE.helpers.createConfirmationDialog(dialog_elm, $(elm).parent().attr('title'), url);
 }
 
 VE.callbacks.click.do_servicerestart = function(evt, elm) {
     var ref = elm.hasClass('actions-panel') ? elm : elm.parents('.actions-panel');
     var url = $('input[name="servicerestart_url"]', ref).val();
     var dialog_elm = ref.find('.confirmation-text-servicerestart');
-    VE.helpers.createConfirmationDialog(dialog_elm, '', url);
+    VE.helpers.createConfirmationDialog(dialog_elm, $(elm).parent().attr('title'), url);
 }
 
 VE.callbacks.click.do_servicestop = function(evt, elm) {
     var ref = elm.hasClass('actions-panel') ? elm : elm.parents('.actions-panel');
     var url = $('input[name="servicestop_url"]', ref).val();
     var dialog_elm = ref.find('.confirmation-text-servicestop');
-    VE.helpers.createConfirmationDialog(dialog_elm, '', url);
+    VE.helpers.createConfirmationDialog(dialog_elm, $(elm).parent().attr('title'), url);
 }
 
 /*

+ 2 - 2
web/js/init.js

@@ -35,7 +35,7 @@ $(document).ready(function(){
             $(window).scroll(function(){hover_menu()});
 
             $('.l-sort-toolbar .sort-by').click(function(){
-              $('.context-menu.sort-order').toggle().css({left: $(this).position().left - 0});
+              $('.context-menu.sort-order').toggle().css({left: $(this).parent().parent().parent().position().left - 0});
             });
 
 
@@ -198,7 +198,7 @@ $(document).ready(function(){
                           }
                       }
                       else {
-                          if ($('.l-unit .ch-toggle:eq(0)').attr('checked')) {
+                          if ($('.l-unit .ch-toggle:eq(0)').prop('checked')) {
                                 $('.l-unit').removeClass('selected');
                                 $('.l-unit .ch-toggle').prop('checked', false);
                           }

Разница между файлами не показана из-за своего большого размера
+ 0 - 1
web/js/jquery/jquery-1.7.2.min.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 4
web/js/jquery/jquery-ui-1.8.20.custom.min.js


Разница между файлами не показана из-за своего большого размера
+ 5 - 0
web/js/jquery/jquery-ui.min.js


+ 2 - 2
web/js/jquery/jquery.finder.js

@@ -214,7 +214,7 @@
                   shortcut.add("Ctrl+a", function(evt){
                     if(jQuery('.ch-toggle:checked').length > 0) {
                       f.t.unHAll(p, o);
-                      jQuery('.ch-toggle:checked').attr('checked', false);
+                      jQuery('.ch-toggle:checked').prop('checked', false);
                     } else {
                       f.t.hAll(p,o);
                     }
@@ -231,7 +231,7 @@
                         //if(f.detect.alt(e)) {
                         if(jQuery('.ch-toggle:checked').length > 0) {
                             f.t.unHAll(p, o);
-                            jQuery('.ch-toggle:checked').attr('checked', false);
+                            jQuery('.ch-toggle:checked').prop('checked', false);
                         } else {
                             f.t.hAll(p,o);
                         }

+ 2 - 2
web/js/pages/add_user.js

@@ -1,11 +1,11 @@
 $(function() {
     $('#v_email').change(function() {
-        if($('#v_email_notify').attr('checked')){
+        if($('#v_email_notify').prop('checked')){
             document.getElementById('v_notify').value = document.getElementById('v_email').value;
         }
     });
     $('#v_email_notify').change(function() {
-        if($('#v_email_notify').attr('checked')){
+        if($('#v_email_notify').prop('checked')){
             document.getElementById('v_notify').value = document.getElementById('v_email').value;
         }else{
             document.getElementById('v_notify').value = '';

+ 2 - 2
web/js/pages/add_web.js

@@ -158,7 +158,7 @@ App.Actions.WEB.remove_ftp_user = function(elm) {
 
 
 App.Actions.WEB.toggle_additional_ftp_accounts = function(elm) {
-    if ($(elm).attr('checked')) {
+    if ($(elm).prop('checked')) {
         $('.ftptable-nrm, .v-add-new-user, .add-new-ftp-user-button').show();
         $('.ftptable-nrm').each(function(i, elm) {
             var login = $(elm).find('.v-ftp-user');
@@ -193,7 +193,7 @@ App.Actions.WEB.toggle_additional_ftp_accounts = function(elm) {
 }
 
 App.Actions.WEB.toggle_letsencrypt = function(elm) {
-    if ($(elm).attr('checked')) {
+    if ($(elm).prop('checked')) {
         $('#ssltable textarea[name=v_ssl_crt],#ssltable textarea[name=v_ssl_key], #ssltable textarea[name=v_ssl_ca]').attr('disabled', 'disabled');
         $('#generate-csr').hide();
 	$('.lets-encrypt-note').show();

+ 1 - 1
web/js/pages/edit_mail.js

@@ -1,5 +1,5 @@
 App.Actions.MAIL.toggle_letsencrypt = function(elm) {
-    if ($(elm).attr('checked')) {
+    if ($(elm).prop('checked')) {
         $('#ssltable textarea[name=v_ssl_crt],#ssltable textarea[name=v_ssl_key], #ssltable textarea[name=v_ssl_ca]').attr('disabled', 'disabled');
         $('#generate-csr').hide();
 	if(!$('.lets-encrypt-note').hasClass('enabled')){

+ 10 - 6
web/js/pages/edit_web.js

@@ -143,12 +143,12 @@ App.Actions.WEB.remove_ftp_user = function(elm) {
     
     if ($('.ftptable-nrm:visible').length == 0) {
         $('.add-new-ftp-user-button').hide();
-        $('input[name="v_ftp"]').attr('checked', false);
+        $('input[name="v_ftp"]').prop('checked', false);
     }
 }
 
 App.Actions.WEB.toggle_additional_ftp_accounts = function(elm) {
-    if ($(elm).attr('checked')) {
+    if ($(elm).prop('checked')) {
         $('.ftptable-nrm, .v-add-new-user, .add-new-ftp-user-button').show();
         $('.ftptable-nrm').each(function(i, elm) {
             var login = $(elm).find('.v-ftp-user');
@@ -177,7 +177,8 @@ App.Actions.WEB.toggle_ssl = function (elm){
 }
 
 App.Actions.WEB.toggle_letsencrypt = function(elm) {
-    if ($(elm).attr('checked')) {
+    if ($(elm).prop('checked')) {
+        $('#ssl-details').hide();
         $('#ssltable textarea[name=v_ssl_crt],#ssltable textarea[name=v_ssl_key], #ssltable textarea[name=v_ssl_ca]').attr('disabled', 'disabled');
         $('#generate-csr').hide();
 	if(!$('.lets-encrypt-note').hasClass('enabled')){
@@ -187,6 +188,7 @@ App.Actions.WEB.toggle_letsencrypt = function(elm) {
     else {
         $('#ssltable textarea[name=v_ssl_crt],#ssltable textarea[name=v_ssl_key], #ssltable textarea[name=v_ssl_ca]').removeAttr('disabled');
         $('#generate-csr').show();
+        $('#ssl-details').show();
 	$('.lets-encrypt-note').hide();
     }
 }
@@ -292,9 +294,11 @@ function FTPrandom(elm) {
     App.Actions.WEB.randomPasswordGenerated && App.Actions.WEB.randomPasswordGenerated(elm);
 }
 
-function elementHideShow(elementToHideOrShow){
-    var el = document.getElementById(elementToHideOrShow);
-    el.style.display = el.style.display === 'none' ? 'block' : 'none';
+function elementHideShow(element){
+    if ( document.getElementById(element)){
+        var el = document.getElementById(element);
+        el.style.display = el.style.display === 'none' ? 'block' : 'none';
+    }
 }
 
 $('.v-redirect-custom-value').change( function(){

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


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


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


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


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


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


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


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


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


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


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


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


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


Разница между файлами не показана из-за своего большого размера
+ 378 - 584
web/locale/hestiacp.pot


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


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


Некоторые файлы не были показаны из-за большого количества измененных файлов