diff --git a/.gitignore b/.gitignore index 6701a887..fe0574ad 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ *.gz .vscode .DS_Store +data +conf +log \ No newline at end of file diff --git a/bin/v-add-firewall-rule b/bin/v-add-firewall-rule index 6fb867d3..b815778b 100755 --- a/bin/v-add-firewall-rule +++ b/bin/v-add-firewall-rule @@ -83,6 +83,16 @@ sort_fw_rules # Updating system firewall $BIN/v-update-firewall +if [ "$WEB_SYSTEM" == 'nginx' ] || [ "$PROXY_SYSTEM" == 'nginx' ]; then + if [ "$port_ext" == "80,443" ] && [ "$action" == "DROP" ]; then + touch /etc/nginx/conf.d/block-firewall.conf + if ! grep -q "deny $ip;" /etc/nginx/conf.d/block-firewall.conf; then + echo "deny $ip;" >> /etc/nginx/conf.d/block-firewall.conf + systemctl restart nginx + fi + fi +fi + #----------------------------------------------------------# # Vesta # diff --git a/bin/v-add-letsencrypt-domain b/bin/v-add-letsencrypt-domain index 97e555fa..a7c7fbb8 100755 --- a/bin/v-add-letsencrypt-domain +++ b/bin/v-add-letsencrypt-domain @@ -308,6 +308,11 @@ for auth in $authz; do if [[ $(echo "$answer" | grep 'addressesResolved') != "" ]]; then break fi + if [ "$wildcard" = 'yes' ]; then + if [[ $(echo "$answer" | grep '"status": "valid"') != "" ]]; then + break + fi + fi i=$((i + 1)) if ((i > 30)); then break diff --git a/bin/v-add-user-package b/bin/v-add-user-package index 0cab1a3d..e9fe210a 100755 --- a/bin/v-add-user-package +++ b/bin/v-add-user-package @@ -28,7 +28,7 @@ is_package_new() { } is_package_consistent() { - source $pkg_dir/$package.pkg + parse_object_kv_list_non_eval $(cat $pkg_dir/$package.pkg) if [ "$WEB_DOMAINS" != 'unlimited' ]; then is_int_format_valid $WEB_DOMAINS 'WEB_DOMAINS' fi @@ -63,6 +63,9 @@ is_package_consistent() { is_int_format_valid $BACKUPS 'BACKUPS' fi is_format_valid_shell $SHELL + is_web_template_valid $WEB_TEMPLATE + is_dns_template_valid $DNS_TEMPLATE + is_proxy_template_valid $PROXY_TEMPLATE } diff --git a/bin/v-backup-user b/bin/v-backup-user index 0db5d376..f6629c9e 100755 --- a/bin/v-backup-user +++ b/bin/v-backup-user @@ -22,6 +22,9 @@ source $VESTA/func/domain.sh source $VESTA/func/db.sh source $VESTA/conf/vesta.conf +if [ ! -z "$NOW" ]; then + BACKUP_LA_LIMIT=50 +fi #----------------------------------------------------------# # Verifications # diff --git a/bin/v-backup-user-now b/bin/v-backup-user-now index 3a20b4ce..10eecd87 100644 --- a/bin/v-backup-user-now +++ b/bin/v-backup-user-now @@ -1,5 +1,6 @@ #!/bin/bash export ALLOW_BACKUP_ANYTIME='yes' +export NOW='yes' nice -n 19 ionice -c 3 /usr/local/vesta/bin/v-backup-user $1 diff --git a/bin/v-change-database-password-for-all-wordpress b/bin/v-change-database-password-for-all-wordpress new file mode 100644 index 00000000..2741e960 --- /dev/null +++ b/bin/v-change-database-password-for-all-wordpress @@ -0,0 +1,63 @@ +#!/bin/bash +# info: change db password to all wordpress databases +# options: +# +# The command is used for changing db password to all wordpress databases on the server. + + +#----------------------------------------------------------# +# Variable&Function # +#----------------------------------------------------------# + +# Importing system variables +source /etc/profile + +# Includes +source $VESTA/func/main.sh + +only_user=''; +if [ ! -z "$1" ]; then + only_user=$1 +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +touch /root/remember-db-user-pass.txt + +for user in $(grep '@' /etc/passwd |cut -f1 -d:); do + if [ ! -f "/usr/local/vesta/data/users/$user/user.conf" ]; then + continue; + fi + + if [ ! -z "$only_user" ]; then + if [ "$only_user" != "$user" ]; then + continue; + fi + fi + + for domain in $(/usr/local/vesta/bin/v-list-web-domains $user plain |cut -f 1); do + if [ -f "/home/$user/web/$domain/public_html/wp-config.php" ]; then + /usr/local/vesta/bin/v-change-database-password-for-wordpress $domain $user + echo "--------------------------------" + fi + done + + if [ ! -z "$only_user" ]; then + break; + fi + +done + +# cat /root/remember-db-user-pass.txt +rm /root/remember-db-user-pass.txt + +#----------------------------------------------------------# +# Vesta # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-database-password-for-wordpress b/bin/v-change-database-password-for-wordpress new file mode 100644 index 00000000..dd7a3a91 --- /dev/null +++ b/bin/v-change-database-password-for-wordpress @@ -0,0 +1,123 @@ +#!/bin/bash +# info: change database password for wordpress +# options: +# +# The command is used for changing database password for wordpress. + + +#----------------------------------------------------------# +# Variable&Function # +#----------------------------------------------------------# + +whoami=$(whoami) +if [ "$whoami" != "root" ]; then + echo "You must be root to execute this script" + exit 1 +fi + +# Importing system environment +source /etc/profile + +# Argument definition +domain=$1 + +# Check if number of arguments is 2 +if [ $# -eq 2 ]; then + user=$2 +else + user=$(/usr/local/vesta/bin/v-search-domain-owner $domain) +fi +USER=$user + +if [ -z "$user" ]; then + echo "ERROR: Domain $domain not found" + exit 1; +fi + +if [ ! -d "/home/$user" ]; then + echo "ERROR: User $user doesn't exist"; + exit 1; +fi + +# Includes +source /usr/local/vesta/func/main.sh + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +check_args '1' "$#" 'DOMAIN' +is_format_valid 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +if [ ! -d "/home/$user/web/$domain/public_html" ]; then + echo "ERROR: Domain doesn't exist"; + exit 1; +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ -f "/home/$user/web/$domain/public_html/wp-config.php" ]; then + echo "=== Domain: $domain" + wp_config_path="/home/$user/web/$domain/public_html/wp-config.php" + if grep -q $'\r' $wp_config_path; then + echo "=== removing CRLF from wp-config.php" + tr -d '\r' < $wp_config_path > /tmp/wp-config.php && mv /tmp/wp-config.php $wp_config_path + chown $user:$user $wp_config_path + fi + db_name=$(grep "DB_NAME" $wp_config_path | grep -oP "define\s*\(\s*'DB_NAME'\s*,\s*'\K[^']+") + db_user=$(grep "DB_USER" $wp_config_path | grep -oP "define\s*\(\s*'DB_USER'\s*,\s*'\K[^']+") + new_password='' + found_existing_password=0 + if [ -f "/root/remember-db-user-pass.txt" ]; then + db_user_pass=$(grep "$db_user:" /root/remember-db-user-pass.txt) + if [ -n "$db_user_pass" ]; then + new_password=$(echo "$db_user_pass" | cut -d':' -f2) + echo "= Using existing password for $db_user" + found_existing_password=1 + fi + fi + + if [ -z "$new_password" ]; then + new_password=$(generate_password) + fi + + echo "DB name: $db_name" + echo "DB user: $db_user" + echo "New DB password: $new_password" + if [ $found_existing_password -eq 0 ] && [ -f "/root/remember-db-user-pass.txt" ]; then + echo "$db_user:$new_password" >> /root/remember-db-user-pass.txt + fi + /usr/local/vesta/bin/v-change-database-password "$user" "$db_name" "$new_password" + if [ $? -ne 0 ]; then + echo "*************** ERROR: Failed to change database password ***************" + exit 1; + fi + line="define('DB_PASSWORD', '$new_password');" + chattr -i $wp_config_path + sed -i "s/.*define(.*DB_PASSWORD'.*/$line/" $wp_config_path + new_password_line=$(grep "DB_PASSWORD" $wp_config_path) + echo "New DB password line: $new_password_line" + if [ "$new_password_line" != "$line" ]; then + echo "*************** ERROR: line in wp-config.php is not what we expected ***************" + echo "Expected: $line" + echo "Actual : $new_password_line" + echo "*************** ERROR: Please check wp-config.php manually ***************" + exit 1; + fi +else + echo "ERROR: WP-config.php not found" + exit 1; +fi + +#----------------------------------------------------------# +# Vesta # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-domain-owner b/bin/v-change-domain-owner index 09ae9bcc..ed5fa5a4 100755 --- a/bin/v-change-domain-owner +++ b/bin/v-change-domain-owner @@ -82,6 +82,10 @@ if [ ! -z "$web_data" ]; then # Move data mv $HOMEDIR/$owner/web/$domain $HOMEDIR/$user/web/ + if [ -d "/hdd/home/$owner/web/$domain" ]; then + $BIN/v-move-folder-and-make-symlink /hdd/home/$owner/web/$domain /hdd/home/$user/web/$domain + fi + # Change ownership find $HOMEDIR/$user/web/$domain -user $owner \ -exec chown -h $user:$user {} \; @@ -152,6 +156,10 @@ if [ ! -z "$mail_data" ]; then # Move data mv $HOMEDIR/$owner/mail/$domain $HOMEDIR/$user/mail/ + if [ -d "/hdd/home/$owner/mail/$domain" ]; then + $BIN/v-move-folder-and-make-symlink /hdd/home/$owner/mail/$domain /hdd/home/$user/mail/$domain + fi + # Change ownership find $HOMEDIR/$user/mail/$domain -user $owner \ -exec chown -h $user {} \; diff --git a/bin/v-change-firewall-rule b/bin/v-change-firewall-rule index d2502bce..aad2ec38 100755 --- a/bin/v-change-firewall-rule +++ b/bin/v-change-firewall-rule @@ -62,6 +62,8 @@ str="RULE='$rule' ACTION='$action' PROTOCOL='$protocol' PORT='$port_ext'" str="$str IP='$ip' COMMENT='$comment' SUSPENDED='no'" str="$str TIME='$time' DATE='$date'" +oldvalues=$(grep "RULE='$rule'" $VESTA/data/firewall/rules.conf) + # Deleting old rule sed -i "/RULE='$rule' /d" $VESTA/data/firewall/rules.conf @@ -74,6 +76,14 @@ sort_fw_rules # Updating system firewall $BIN/v-update-firewall +if [ "$WEB_SYSTEM" == 'nginx' ] || [ "$PROXY_SYSTEM" == 'nginx' ]; then + if [ "$port_ext" == "80,443" ] && [ "$action" == "DROP" ]; then + NEWIP=$ip + parse_object_kv_list_non_eval "$oldvalues" + sed -i "s|$IP|$NEWIP|g" /etc/nginx/conf.d/block-firewall.conf + systemctl restart nginx + fi +fi #----------------------------------------------------------# # Vesta # diff --git a/bin/v-change-user-package b/bin/v-change-user-package index d0de98db..1e088bcc 100755 --- a/bin/v-change-user-package +++ b/bin/v-change-user-package @@ -16,6 +16,7 @@ force=$3 # Includes source $VESTA/func/main.sh +source $VESTA/func/domain.sh source $VESTA/conf/vesta.conf is_package_avalable() { @@ -23,7 +24,7 @@ is_package_avalable() { usr_data=$(cat $USER_DATA/user.conf) IFS=$'\n' for key in $usr_data; do - eval ${key%%=*}=${key#*=} + parse_object_kv_list_non_eval $key done WEB_DOMAINS='0' @@ -35,7 +36,7 @@ is_package_avalable() { pkg_data=$(cat $VESTA/data/packages/$package.pkg |grep -v TIME |\ grep -v DATE) - eval $pkg_data + parse_object_kv_list_non_eval $pkg_data # Checking usage agains package limits if [ "$WEB_DOMAINS" != 'unlimited' ]; then @@ -73,11 +74,15 @@ is_package_avalable() { check_result $E_LIMIT "Package doesn't cover BANDWIDTH usage" fi fi + + is_web_template_valid $WEB_TEMPLATE + is_dns_template_valid $DNS_TEMPLATE + is_proxy_template_valid $PROXY_TEMPLATE } change_user_package() { - eval $(cat $USER_DATA/user.conf) - eval $(cat $VESTA/data/packages/$package.pkg |egrep -v "TIME|DATE") + parse_object_kv_list_non_eval $(cat $USER_DATA/user.conf) + parse_object_kv_list_non_eval $(cat $VESTA/data/packages/$package.pkg |egrep -v "TIME|DATE") echo "FNAME='$FNAME' LNAME='$LNAME' PACKAGE='$package' diff --git a/bin/v-change-wordpress-admin-passwords b/bin/v-change-wordpress-admin-passwords new file mode 100644 index 00000000..89122a2d --- /dev/null +++ b/bin/v-change-wordpress-admin-passwords @@ -0,0 +1,160 @@ +#!/bin/bash +# info: interactively delete or change WordPress admin passwords for a given domain +# options: DOMAIN +# +# d → delete user (with content reassignment) +# c → change password (random 10-char alnum) +# s → skip +# x → exit + +#----------------------------------------------------------# +# Variable & Function # +#----------------------------------------------------------# + +[ "$(whoami)" != "root" ] && { echo "You must be root to run this command."; exit 1; } +source /etc/profile + +DOMAIN="$1" +[ -z "$DOMAIN" ] && { echo "Usage: v-change-wp-admins-pass DOMAIN"; exit 1; } + +USER="$(/usr/local/vesta/bin/v-search-domain-owner "$DOMAIN")" +[ -z "$USER" ] && { echo "Domain $DOMAIN does not exist."; exit 1; } + +WP_PATH="/home/$USER/web/$DOMAIN/public_html" +[ ! -f "$WP_PATH/wp-config.php" ] && { echo "WordPress is not installed on this domain."; exit 1; } + +# WP-CLI wrapper +WP_RUN=(/usr/local/vesta/bin/v-run-wp-cli $DOMAIN --skip-plugins --skip-themes) +return_code=$? + +if [ $return_code -ne 0 ]; then + echo "WP-CLI error:" + cat /home/$USER/web/$DOMAIN/wp-cli-error.log + exit $return_code +fi + +# random 10-char password +gen_pass() { tr -dc 'A-Za-z0-9' /dev/null | tail -n +2) +[ -z "$ADMIN_LIST_CSV" ] && { echo "No administrator accounts found."; exit 0; } + +printf "%-6s %-20s %s\n" "ID" "Username" "Email" +echo "$ADMIN_LIST_CSV" | while IFS=',' read -r PID PLOGIN PEMAIL; do + printf "%-6s %-20s %s\n" "$PID" "$PLOGIN" "$PEMAIL" +done + +echo +echo "For each admin choose: (d) delete, (c) change password, (s) skip, (x) exit." + +# interactive loop +while IFS=',' read -r ID LOGIN EMAIL; do + [ -n "$EMAIL" ] && TARGET="$LOGIN <$EMAIL>" || TARGET="$LOGIN" + while true; do + echo "-------------------------------------" + read -r -p "Action for \"$TARGET\" [d/c/s/x]? " ACT < /dev/tty + case "$ACT" in + [Dd]* ) + # read -r -p "Really DELETE \"$TARGET\" ? (y/n, default: y) " CONF < /dev/tty + CONF="y" + if [[ ! "$CONF" =~ ^[Nn]$ ]]; then + # build an array of OTHER admin usernames + mapfile -t OTHER_USERS < <(echo "$ADMIN_LIST_CSV" | awk -F',' -v cur="$ID" '$1!=cur {print $2}') + if [ "${#OTHER_USERS[@]}" -eq 0 ]; then + echo "Cannot delete the only administrator account." + break + fi + DEFAULT_USER="${OTHER_USERS[0]}" + echo "Available admin usernames for reassignment: ${OTHER_USERS[*]}" + while true; do + read -r -p "Reassign content to which username? [default: $DEFAULT_USER] " REASSIGN < /dev/tty + REASSIGN=${REASSIGN:-$DEFAULT_USER} + if printf '%s\n' "${OTHER_USERS[@]}" | grep -qx "$REASSIGN"; then + break + else + echo "Invalid username. Please choose one of: ${OTHER_USERS[*]}" + fi + done + # delete by username, reassign by username + "${WP_RUN[@]}" user delete "$LOGIN" --reassign="$REASSIGN" --yes --skip-plugins --skip-themes + if [ $? -eq 0 ]; then + echo "$TARGET deleted (content reassigned to $REASSIGN)." + else + cat /home/$USER/web/$DOMAIN/wp-cli-error.log + echo "Failed to delete $TARGET." + fi + else + echo "Deletion cancelled." + fi + break + ;; + [Cc]* ) + NEW_PASS=$(gen_pass) + "${WP_RUN[@]}" user update "$LOGIN" --user_pass="$NEW_PASS" --skip-plugins --skip-themes + if [ $? -eq 0 ]; then + echo "Password for username '$TARGET' changed to: $NEW_PASS" + echo "Password for username '$TARGET' changed to: $NEW_PASS" >> /home/$USER/web/$DOMAIN/wp-admin-password-change.txt + chown $USER:$USER /home/$USER/web/$DOMAIN/wp-admin-password-change.txt + chmod 600 /home/$USER/web/$DOMAIN/wp-admin-password-change.txt + else + cat /home/$USER/web/$DOMAIN/wp-cli-error.log + echo "Failed to change password for $TARGET." + fi + break + ;; + [Ss]* ) + echo "Skipping $TARGET." + break + ;; + [Xx]* ) + echo "Exiting." + exit 0 + ;; + * ) echo "Please answer d, c, s, or x." ;; + esac + done +done <<< "$ADMIN_LIST_CSV" + +#----------------------------------------------------------# +# flush cache and refresh all security salts # +#----------------------------------------------------------# + +echo "-------------------------------------" +echo +echo "Flushing cache and refreshing salts..." + +"${WP_RUN[@]}" cache flush +"${WP_RUN[@]}" config shuffle-salts WP_CACHE_KEY_SALT --force +"${WP_RUN[@]}" config shuffle-salts + +echo "Cache flushed and salts refreshed." + +echo +echo "Done." + +if [ -f /home/$USER/web/$DOMAIN/wp-admin-password-change.txt ]; then + echo "-------------------------------------" + echo "For website $DOMAIN - new wp-admin passwords have been set." + echo "-------------------------------------" + cat /home/$USER/web/$DOMAIN/wp-admin-password-change.txt + echo "-------------------------------------" + echo "" + read -r -p "== Press Enter to continue..." +fi + +exit 0 diff --git a/bin/v-clean-garbage b/bin/v-clean-garbage index 36b50830..11e29122 100644 --- a/bin/v-clean-garbage +++ b/bin/v-clean-garbage @@ -90,6 +90,13 @@ if [ $fail2ban_running -eq 1 ]; then fi if [ -f "/var/lib/fail2ban/fail2ban.sqlite3" ]; then rm /var/lib/fail2ban/fail2ban.sqlite3 + if [ -f "/etc/nginx/conf.d/block.conf" ]; then + truncate -s 0 /etc/nginx/conf.d/block.conf + nginx_running=$(/usr/local/vesta/bin/v-list-sys-services | grep 'nginx' | grep -c 'running') + if [ $nginx_running -eq 1 ]; then + systemctl restart nginx + fi + fi fi if [ $fail2ban_running -eq 1 ]; then systemctl start fail2ban diff --git a/bin/v-clear-fail2ban b/bin/v-clear-fail2ban new file mode 100644 index 00000000..ab3ab30c --- /dev/null +++ b/bin/v-clear-fail2ban @@ -0,0 +1,59 @@ +#!/bin/bash +# info: Clean fail2ban database +# options: NONE +# +# The function is cleaning fail2ban database + +#----------------------------------------------------------# +# Verifications & Variable & Function # +#----------------------------------------------------------# + +whoami=$(whoami) +if [ "$whoami" != "root" ]; then + echo "You must be root to execute this script" + exit 1 +fi + +# check if fail2ban is installed +fail2ban_installed=$(/usr/local/vesta/bin/v-list-sys-services | grep -c 'fail2ban') +if [ $fail2ban_installed -eq 0 ]; then + echo "Fail2ban is not installed" + exit 1 +fi + +# Includes +source /usr/local/vesta/func/main.sh + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Cleaning fail2ban database +fail2ban_running=$(/usr/local/vesta/bin/v-list-sys-services | grep 'fail2ban' | grep -c 'running') +if [ $fail2ban_running -eq 1 ]; then + echo "== Stopping fail2ban" + systemctl stop fail2ban +fi +if [ -f "/var/lib/fail2ban/fail2ban.sqlite3" ]; then + echo "== Cleaning fail2ban database" + rm /var/lib/fail2ban/fail2ban.sqlite3 + if [ -f "/etc/nginx/conf.d/block.conf" ]; then + echo "== Cleaning nginx block.conf" + truncate -s 0 /etc/nginx/conf.d/block.conf + nginx_running=$(/usr/local/vesta/bin/v-list-sys-services | grep 'nginx' | grep -c 'running') + if [ $nginx_running -eq 1 ]; then + echo "== Restarting nginx" + systemctl restart nginx + fi + fi +fi +if [ $fail2ban_running -eq 1 ]; then + echo "== Starting fail2ban" + systemctl start fail2ban +fi + +echo "== Done, fail2ban database cleaned" + +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-commander b/bin/v-commander index 834fb38b..f04b3a17 100644 --- a/bin/v-commander +++ b/bin/v-commander @@ -101,7 +101,7 @@ myhelp() { echo "m def = install php-memcached if needed" echo "check fc = check if FreshClam is up" echo "-----------------------------" - echo "enable-ssh-root-password-login = Allow root password authentication via SSH and set the root password to match the password for the admin account" + echo "enable-ssh-root-password-login = Allow root password authentication via SSH" echo "id_rsa = generate id_rsa and id_rsa.pub if it does not exist and show id_rsa.pub" echo "-----------------------------" } @@ -535,18 +535,11 @@ do echo "--- New settings ---" grep '^PermitRoot' /etc/ssh/sshd_config echo "--------------------" - root_password=$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 32) - hashed_root_password=$(openssl passwd -6 "$root_password") - sed -i "s#^root:.*#root:$hashed_root_password#" /etc/shadow - echo "Root password is now a new random password." - echo "New root password: $root_password" - echo "--------------------" - grep '^root:' /etc/shadow - grep '^admin:' /etc/shadow - echo "--------------------" echo "Port 22 opened in Firewall for all IP addresses." /usr/local/vesta/bin/v-unsuspend-firewall-rule "11" echo "--------------------" + echo "Type 'passwd' in the terminal to set the root password." + echo "--------------------" fi if [ "$answer" = 'r' ] || [ "$answer" = 'R' ]; then diff --git a/bin/v-delete-database-of-domain b/bin/v-delete-database-of-domain new file mode 100644 index 00000000..30fd18c0 --- /dev/null +++ b/bin/v-delete-database-of-domain @@ -0,0 +1,69 @@ +#!/bin/bash +# info: delete database if domain has database +# options: DOMAIN +# +# The function for deleting database if domain has database + +#----------------------------------------------------------# +# Variable&Function # +#----------------------------------------------------------# + +whoami=$(whoami) +if [ "$whoami" != "root" ]; then + echo "You must be root to execute this script" + exit 1 +fi + +# Importing system environment +source /etc/profile + +# Argument definition +domain=$1 + +user=$(/usr/local/vesta/bin/v-search-domain-owner $domain) +USER=$user + +# Includes +source /usr/local/vesta/func/main.sh + +if [ -z "$user" ]; then + check_result $E_NOTEXIST "domain $domain doesn't exist" +fi + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'DOMAIN' +is_format_valid 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +RET=$OK + +# echo "=================================" +r=$(/usr/local/vesta/bin/v-get-database-credentials-of-domain $domain) +# echo $r +eval $r +# echo "=================================" + +if [ ! -z "$DATABASE_NAME" ]; then + echo "=== v-delete-database $USER $DATABASE_NAME" + /usr/local/vesta/bin/v-delete-database $USER $DATABASE_NAME + if [ $? -ne 0 ]; then + echo "=== v-delete-database failed" + RET=$E_NOTEXIST + fi +fi + +#----------------------------------------------------------# +# Vesta # +#----------------------------------------------------------# + +log_event "$RET" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-domain b/bin/v-delete-domain index b6294679..1ca3373b 100755 --- a/bin/v-delete-domain +++ b/bin/v-delete-domain @@ -37,9 +37,10 @@ is_object_unsuspended 'user' 'USER' "$user" if [ ! -z "$WEB_SYSTEM" ]; then str=$(grep "DOMAIN='$domain'" $USER_DATA/web.conf) if [ ! -z "$str" ]; then + $BIN/v-delete-database-of-domain $domain domain_found='yes' $BIN/v-delete-web-domain $user $domain 'no' - check_result $? "can't suspend web" > /dev/null + check_result $? "can't delete web" > /dev/null fi fi @@ -49,7 +50,7 @@ if [ ! -z "$DNS_SYSTEM" ]; then if [ ! -z "$str" ]; then domain_found='yes' $BIN/v-delete-dns-domain $user $domain 'no' - check_result $? "can't suspend dns" > /dev/null + check_result $? "can't delete dns" > /dev/null fi fi @@ -59,7 +60,7 @@ if [ ! -z "$MAIL_SYSTEM" ]; then if [ ! -z "$str" ]; then domain_found='yes' $BIN/v-delete-mail-domain $user $domain - check_result $? "can't suspend mail" > /dev/null + check_result $? "can't delete mail" > /dev/null fi fi diff --git a/bin/v-delete-firewall-rule b/bin/v-delete-firewall-rule index 8f646644..61f7602d 100755 --- a/bin/v-delete-firewall-rule +++ b/bin/v-delete-firewall-rule @@ -34,12 +34,21 @@ is_object_valid '../../data/firewall/rules' 'RULE' "$rule" # Action # #----------------------------------------------------------# +oldvalues=$(grep "RULE='$rule'" $VESTA/data/firewall/rules.conf) + # Deleting rule sed -i "/RULE='$rule' /d" $VESTA/data/firewall/rules.conf # Updating system firewall $BIN/v-update-firewall +if [ "$WEB_SYSTEM" == 'nginx' ] || [ "$PROXY_SYSTEM" == 'nginx' ]; then + parse_object_kv_list_non_eval "$oldvalues" + if [ "$PORT" == "80,443" ] && [ "$ACTION" == "DROP" ]; then + sed -i "/$IP/d" /etc/nginx/conf.d/block-firewall.conf + systemctl restart nginx + fi +fi #----------------------------------------------------------# # Vesta # diff --git a/bin/v-delete-mail-domain b/bin/v-delete-mail-domain index ee727aa9..9be565bb 100755 --- a/bin/v-delete-mail-domain +++ b/bin/v-delete-mail-domain @@ -51,6 +51,9 @@ if [[ "$MAIL_SYSTEM" =~ exim ]]; then rm -f /etc/$MAIL_SYSTEM/domains/$domain_idn rm -rf $HOMEDIR/$user/conf/mail/$domain rm -rf $HOMEDIR/$user/mail/$domain_idn + if [ -d "/hdd/home/$user/mail/$domain_idn" ]; then + rm -rf /hdd/home/$user/mail/$domain_idn + fi fi # Deleting dkim dns record diff --git a/bin/v-delete-mail-domain-dkim b/bin/v-delete-mail-domain-dkim index f11e48d4..7cfbab58 100755 --- a/bin/v-delete-mail-domain-dkim +++ b/bin/v-delete-mail-domain-dkim @@ -48,7 +48,7 @@ fi # Deleting dns record if [ ! -z "$DNS_SYSTEM" ] && [ -e "$USER_DATA/dns/$domain.conf" ]; then records=$($BIN/v-list-dns-records $user $domain plain) - dkim_records=$(echo "$records" |grep -w '_domainkey' | cut -f 1 -d ' ') + dkim_records=$(echo "$records" |grep -w '_domainkey' | awk '{print $1}') for id in $dkim_records; do $BIN/v-delete-dns-record $user $domain $id done diff --git a/bin/v-delete-mails b/bin/v-delete-mails new file mode 100644 index 00000000..24ac68e5 --- /dev/null +++ b/bin/v-delete-mails @@ -0,0 +1,127 @@ +#!/bin/bash +# info: delete old emails (by mtime) for user/domain/account, with optional scope +# usage: v-delete-mails USER DOMAIN ACCOUNT MTIME_DAYS|all SCOPE +# SCOPE: all – clean every Maildir folder (cur, new, tmp, custom subfolders) +# trash – clean only Trash/Junk/Spam folders + +# load Vesta functions & config +source "$VESTA/func/main.sh" +source "$VESTA/conf/vesta.conf" + +# read arguments +user="$1" +domain="$2" +account="$3" +mtime="$4" +scope="$5" + +# verify argument count +check_args '5' "$#" 'USER DOMAIN ACCOUNT MTIME_DAYS|all SCOPE' + +# validate scope +if [[ "$scope" != "all" && "$scope" != "trash" ]]; then + echo "ERROR: SCOPE must be 'all' or 'trash'." + exit 1 +fi + +# validate logical combinations +if [[ "$user" == "all" ]]; then + if [[ "$domain" != "all" || "$account" != "all" ]]; then + echo "ERROR: When USER is 'all', both DOMAIN and ACCOUNT must be 'all'." + exit 1 + fi +elif [[ "$domain" == "all" && "$account" != "all" ]]; then + echo "ERROR: When DOMAIN is 'all', ACCOUNT must also be 'all'." + exit 1 +fi + +# build a detailed summary for the warning +declare -a summary_parts +if [[ "$user" == "all" ]]; then + summary_parts+=("all users") +else + summary_parts+=("user '$user'") +fi + +if [[ "$domain" == "all" ]]; then + summary_parts+=("all domains") +else + summary_parts+=("domain '$domain'") +fi + +if [[ "$account" == "all" ]]; then + summary_parts+=("all accounts") +else + summary_parts+=("account '$account'") +fi + +# join with commas +summary=$(printf ", %s" "${summary_parts[@]}") +summary=${summary:2} + +# only warn if any of them is 'all' or if mtime is 'all' +if [[ "$mtime" == "all" || "$user" == "all" || "$domain" == "all" || "$account" == "all" ]]; then + echo "WARNING: This will delete emails older than '$mtime' days for ${summary}." + read -p "Are you sure? (yes/no): " confirm + [[ "$confirm" != "yes" ]] && { echo "Aborted."; exit 1; } +fi + +# function to delete emails +delete_emails() { + local u="$1" d="$2" a="$3" + local maildir="/home/$u/mail/$d/$a" + + [[ ! -d "$maildir" ]] && return + + echo "→ Cleaning '$a@$d' (user: $u), scope: $scope, mtime: $mtime" + + # build find predicates + if [[ "$scope" == "all" ]]; then + folder_expr=( -path "*/cur/*" -o -path "*/new/*" -o -path "*/tmp/*" ) + else + folder_expr=( -ipath "*/trash/*" -o -ipath "*/junk/*" -o -ipath "*/spam/*" ) + fi + + # assemble and run find + if [[ "$mtime" == "all" ]]; then + find "$maildir" -type f \( "${folder_expr[@]}" \) -print -delete 2>/dev/null + else + find "$maildir" -type f \( "${folder_expr[@]}" \) -mtime +"$mtime" -print -delete 2>/dev/null + fi +} + +# collect users +if [[ "$user" == "all" ]]; then + users=$(v-list-users plain | awk '{print $1}') +else + users="$user" +fi + +# iterate through users, domains, accounts +for u in $users; do + if [[ "$domain" == "all" ]]; then + domains=$(v-list-mail-domains "$u" plain | awk '{print $1}') + else + domains="$domain" + fi + + for d in $domains; do + if [[ "$account" == "all" ]]; then + accounts=$(v-list-mail-accounts "$u" "$d" plain | awk '{print $1}') + else + accounts="$account" + fi + + for a in $accounts; do + delete_emails "$u" "$d" "$a" + done + done +done + +# restart dovecot to refresh mailbox state +systemctl restart dovecot + +# log the action (status first, then message) +log_event "$OK" "Deleted emails (>$mtime days, scope=$scope) for $user $domain $account" + +exit 0 diff --git a/bin/v-delete-user b/bin/v-delete-user index 120b1f72..cdf809eb 100755 --- a/bin/v-delete-user +++ b/bin/v-delete-user @@ -94,7 +94,7 @@ fi # Deleting user directories chattr -i $HOMEDIR/$user/conf rm -rf $HOMEDIR/$user -if [ -f "/hdd/home/$user" ]; then +if [ -d "/hdd/home/$user" ]; then rm -rf /hdd/home/$user fi rm -f /var/spool/mail/$user diff --git a/bin/v-delete-web-domain b/bin/v-delete-web-domain index 43362e34..e64dd9a7 100755 --- a/bin/v-delete-web-domain +++ b/bin/v-delete-web-domain @@ -130,6 +130,9 @@ rm -f /var/log/$WEB_SYSTEM/domains/$domain.error* # Deleting directory rm -rf $HOMEDIR/$user/web/$domain +if [ -d "/hdd/home/$user/web/$domain" ]; then + rm -rf /hdd/home/$user/web/$domain +fi #----------------------------------------------------------# diff --git a/bin/v-desinfect-wordpress b/bin/v-desinfect-wordpress new file mode 100644 index 00000000..04583c1e --- /dev/null +++ b/bin/v-desinfect-wordpress @@ -0,0 +1,79 @@ +#!/bin/bash +# info: disinfect a WordPress site with several maintenance commands +# options: DOMAIN + +# -------------------------------------------------------- # +# variables and checks # +# -------------------------------------------------------- # + +if [ "$(whoami)" != "root" ]; then + echo "You must be root to run this command." + exit 1 +fi + +# make sure all Vesta helper scripts are reachable +export PATH="/usr/local/vesta/bin:$PATH" +source /etc/profile + +domain="$1" +if [ -z "$domain" ]; then + echo "Usage: v-desinfect-wp DOMAIN" + exit 1 +fi + +user=$(/usr/local/vesta/bin/v-search-domain-owner "$domain") +if [ -z "$user" ]; then + echo "Domain $domain does not exist." + exit 1 +fi + +# absolute paths to maintenance scripts, in desired order +declare -a tasks=( + "/usr/local/vesta/bin/v-change-database-password-for-wordpress" + "/usr/local/vesta/bin/v-change-wordpress-admin-passwords" + "/usr/local/vesta/bin/v-fix-wordpress-core" + "/usr/local/vesta/bin/v-wf-malware-hyperscan-with-remediate" + "INTERACTIVE=1 /usr/local/vesta/bin/v-wf-malware-hyperscan-with-remediate" +) + +# -------------------------------------------------------- # +# execution strategy # +# -------------------------------------------------------- # + +echo +read -r -p "Run all maintenance steps automatically? (y/n) " run_all < /dev/tty + +if [[ "$run_all" =~ ^[Yy]$ ]]; then + echo "Running all maintenance steps for $domain" + automatic=true +else + echo + echo "Selective mode. You will be asked for each step." + automatic=false +fi + +for cmd in "${tasks[@]}"; do + if [ ! -x "$cmd" ]; then + echo "Command $cmd not found or not executable, skipping." + continue + fi + + if [ "$automatic" = false ]; then + while true; do + read -r -p "Run $(basename "$cmd") for $domain? (y/n) " yn < /dev/tty + case "$yn" in + [Yy]* ) break ;; + [Nn]* ) echo "Skipping $(basename "$cmd")."; continue 2 ;; + * ) echo "Please answer y or n." ;; + esac + done + fi + + echo + echo "=== $(basename "$cmd") $domain ===" + "$cmd" "$domain" +done + +echo +echo "Done." +exit 0 diff --git a/bin/v-fix-user-permissions b/bin/v-fix-user-permissions index e55b5e0f..991ada62 100644 --- a/bin/v-fix-user-permissions +++ b/bin/v-fix-user-permissions @@ -52,6 +52,7 @@ find /home/$user/conf/ -type d -exec chown root:root {} \; find /home/$user/web/*/public_html/ -type d -exec chmod 755 {} + find /home/$user/web/*/public_html/ -type f -exec chmod 644 {} + find /home/$user/web/*/public_html/ -exec chown $user:$user {} \; +find /home/$user/web/*/ -name "*.php" -type f -exec chmod 600 {} + echo "Done, permissions fixed for user: $user" diff --git a/bin/v-fix-website-permissions b/bin/v-fix-website-permissions index a63954eb..3a73d13a 100644 --- a/bin/v-fix-website-permissions +++ b/bin/v-fix-website-permissions @@ -18,7 +18,13 @@ source /etc/profile # Argument definition domain=$1 -user=$(/usr/local/vesta/bin/v-search-domain-owner $domain) +# Check if number of arguments is 2 +if [ $# -eq 2 ]; then + user=$2 +else + user=$(/usr/local/vesta/bin/v-search-domain-owner $domain) +fi +USER=$user # Includes source /usr/local/vesta/func/main.sh @@ -27,8 +33,6 @@ if [ -z "$user" ]; then check_result $E_NOTEXIST "domain $domain doesn't exist" fi -USER=$user - #----------------------------------------------------------# # Verifications # #----------------------------------------------------------# @@ -54,14 +58,31 @@ fi # Going to domain directory cd /home/$USER/web/$domain +# Ownership check +if [ -z "$SKIP_OWNERSHIP_CHECK" ] && [ -f "public_html/index.php" ]; then + owner=$(stat -c '%U' "public_html/index.php") + if [ "$owner" = "root" ] || [ "$owner" = "www-data" ]; then + echo "Skipping permission fix for $domain, because v-lock-wordpress is used (index.php is owned by $owner)" + exit 1 + fi +fi + + echo "Updating permissions for /home/$USER/web/$domain/public_html/" find public_html/ -type d -exec chmod 755 {} + find public_html/ -type f -exec chmod 644 {} + chown -R $USER:$USER public_html/ +# Setting chmod 600 for all php files +echo "= Setting chmod 600 for all php files" +find -name "*.php" -type f -exec chmod 600 {} + +find -name ".env" -type f -exec chmod 600 {} + +find -name "*.php" -type f -exec chown $USER:$USER {} + +find -name ".env" -type f -exec chown $USER:$USER {} + + #----------------------------------------------------------# # Vesta # #----------------------------------------------------------# echo "Permissions for $domain have been successfully updated." -exit +exit 0 diff --git a/bin/v-fix-website-permissions-for-all-websites b/bin/v-fix-website-permissions-for-all-websites new file mode 100644 index 00000000..9b1501bd --- /dev/null +++ b/bin/v-fix-website-permissions-for-all-websites @@ -0,0 +1,41 @@ +#!/bin/bash +# info: fix website permissions for all websites +# options: +# +# The command is used for fixing website permissions for all websites on the server. + + +#----------------------------------------------------------# +# Variable&Function # +#----------------------------------------------------------# + +# Importing system variables +source /etc/profile + +# Includes +source $VESTA/func/main.sh + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +for user in $(grep '@' /etc/passwd |cut -f1 -d:); do + if [ ! -f "/usr/local/vesta/data/users/$user/user.conf" ]; then + continue; + fi + + for domain in $(/usr/local/vesta/bin/v-list-web-domains $user plain |cut -f 1); do + /usr/local/vesta/bin/v-fix-website-permissions $domain $user + echo "--------------------------------" + done + +done + +#----------------------------------------------------------# +# Vesta # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-fix-wordpress-core b/bin/v-fix-wordpress-core new file mode 100644 index 00000000..7a511747 --- /dev/null +++ b/bin/v-fix-wordpress-core @@ -0,0 +1,110 @@ +#!/bin/bash +# info: fix compromised wp-admin and wp-includes +# options: DOMAIN [CACHE_DIR] +# +# Replaces wp-admin and wp-includes with clean copies that match +# the WordPress core version detected on the site. +# +# Example: +# v-fix-wp-core example.com +# v-fix-wp-core example.com /srv/wp-cache + +#----------------------------------------------------------# +# Variable & Function # +#----------------------------------------------------------# + +# Arguments +DOMAIN="$1" +CACHE_DIR="${2-/srv/wp-cache}" # default cache location + +QUARANTINE_DIR="/srv/wp-quarantine" + +# Includes +source $VESTA/func/main.sh +source $VESTA/conf/vesta.conf + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# +check_args '1' "$#" 'DOMAIN [CACHE_DIR]' +is_format_valid 'domain' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +TMP_DIR="$(mktemp -d /tmp/wpfix.XXXXXX)" # temp workspace +trap 'rm -rf "$TMP_DIR"' EXIT + +# 1etermine WP version +WP_VERSION="$(/usr/local/vesta/bin/v-run-wp-cli "$DOMAIN" core version | tr -d '[:space:]')" +check_result $? "cannot detect WP version" > /dev/null +if [ -z "$WP_VERSION" ]; then + check_result 1 "empty WP version string" +fi +echo "Detected WordPress version $WP_VERSION" + +# 2ind site owner and path +USER="$(/usr/local/vesta/bin/v-search-domain-owner "$DOMAIN")" +check_result $? "cannot find domain owner" > /dev/null +SITE_PATH="/home/$USER/web/$DOMAIN/public_html" +if [ ! -d "$SITE_PATH" ]; then + check_result 1 "site path $SITE_PATH does not exist" +fi + +# ensure cached core is present +CACHE_PATH="$CACHE_DIR/$WP_VERSION" +if [ ! -d "$CACHE_PATH/wp-admin" ] || [ ! -d "$CACHE_PATH/wp-includes" ]; then + echo "Cache for $WP_VERSION missing, downloading ZIP..." + + mkdir -p "$CACHE_PATH" + ZIP_URL="https://wordpress.org/wordpress-${WP_VERSION}.zip" + ZIP_FILE="$TMP_DIR/wp.zip" + + curl -fSL "$ZIP_URL" -o "$ZIP_FILE" + check_result $? "download failed" > /dev/null + + unzip -q "$ZIP_FILE" -d "$TMP_DIR" + check_result $? "unzip failed" > /dev/null + + mv "$TMP_DIR/wordpress/wp-admin" "$CACHE_PATH/" + mv "$TMP_DIR/wordpress/wp-includes" "$CACHE_PATH/" + cp "$TMP_DIR/wordpress"/*.php "$CACHE_PATH/" +fi + +# backup current core folders +TIMESTAMP="$(date +%Y%m%d%H%M%S)" +BACKUP_DIR="$QUARANTINE_DIR/$DOMAIN/backup-core-$TIMESTAMP" +mkdir -p "$BACKUP_DIR" +mv "$SITE_PATH/wp-admin" "$BACKUP_DIR/" +mv "$SITE_PATH/wp-includes" "$BACKUP_DIR/" + +for f in "$SITE_PATH"/*.php; do + [[ $(basename "$f") == "wp-config.php" ]] && continue + mv "$f" "$BACKUP_DIR/" +done +if [ -f "$SITE_PATH/.user.ini" ]; then + mv "$SITE_PATH/.user.ini" "$BACKUP_DIR/" +fi + +# chown -R www-data:www-data "$BACKUP_DIR" +check_result $? "backup failed" > /dev/null +echo "Old core folders moved to $BACKUP_DIR" + +# deploy clean core +rsync -a --delete "$CACHE_PATH/wp-admin/" "$SITE_PATH/wp-admin/" +rsync -a --delete "$CACHE_PATH/wp-includes/" "$SITE_PATH/wp-includes/" +check_result $? "rsync failed" > /dev/null + +for corephp in "$CACHE_PATH"/*.php; do + base=$(basename "$corephp") + [ "$base" = "wp-config.php" ] && continue + rsync -a "$corephp" "$SITE_PATH/$base" +done + +# fix permissions +SKIP_OWNERSHIP_CHECK=1 /usr/local/vesta/bin/v-fix-website-permissions $DOMAIN +# chown -R www-data:www-data "$BACKUP_DIR" + +echo "Done, core WP files, wp-admin and wp-includes replaced for $DOMAIN" +exit diff --git a/bin/v-get-wp-cli b/bin/v-get-wp-cli new file mode 100644 index 00000000..c097a024 --- /dev/null +++ b/bin/v-get-wp-cli @@ -0,0 +1,44 @@ +#!/bin/bash +# info: Download WP CLI +# options: NONE + +#----------------------------------------------------------# +# Variable&Function # +#----------------------------------------------------------# + +whoami=$(whoami) +if [ "$whoami" != "root" ]; then + echo "You must be root to execute this script" + exit 1 +fi + +# Importing system environment +source /etc/profile + +if [ ! -f "/usr/local/bin/composer" ]; then + echo "= Composer is not installed. Installing..." + php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + php composer-setup.php --install-dir=/usr/local/bin --filename=composer + php -r "unlink('composer-setup.php');" + echo "= Composer installed successfully." +fi + +if [ -d "/usr/local/bin/wp-cli" ]; then + echo "= Removing old WP CLI..." + rm -rf /usr/local/bin/wp-cli +fi + +cd /usr/local/bin +git clone https://github.com/wp-cli/wp-cli.git + +chown -R www-data:www-data wp-cli + +cd wp-cli/ +sudo -H -u www-data composer install + +# Fix terminal columns issue for WP CLI +/usr/local/vesta/bin/v-sed '$columns = 80;' "if (file_exists('/usr/local/bin/wp-cli/COLUMNS')) \$columns=intval(file_get_contents('/usr/local/bin/wp-cli/COLUMNS')); else \$columns = 80;" '/usr/local/bin/wp-cli/vendor/wp-cli/php-cli-tools/lib/cli/Shell.php' + +echo "= WP CLI installed successfully." + +exit 0; \ No newline at end of file diff --git a/bin/v-import-cpanel-backup b/bin/v-import-cpanel-backup index a70213dd..43e8c3bf 100644 --- a/bin/v-import-cpanel-backup +++ b/bin/v-import-cpanel-backup @@ -157,11 +157,15 @@ for sk_dbr in $sk_db_list echo " Create and restore ${sk_dbr} " sed -i "s/utf8mb4_unicode_520_ci/utf8mb4_unicode_ci/g" mysql/${sk_dbr}.create sed -i "s/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g" mysql/${sk_dbr}.create - v-sed '/*!999999\- enable the sandbox mode */' '' mysql/${sk_dbr}.create + if grep -q ' enable the sandbox mode ' mysql/${sk_dbr}.create; then + v-sed '/*!999999\- enable the sandbox mode */' '' mysql/${sk_dbr}.create + fi mysql < mysql/${sk_dbr}.create sed -i "s/utf8mb4_unicode_520_ci/utf8mb4_unicode_ci/g" mysql/${sk_dbr}.sql sed -i "s/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g" mysql/${sk_dbr}.sql - v-sed '/*!999999\- enable the sandbox mode */' '' mysql/${sk_dbr}.sql + if grep -q ' enable the sandbox mode ' mysql/${sk_dbr}.sql; then + v-sed '/*!999999\- enable the sandbox mode */' '' mysql/${sk_dbr}.sql + fi mysql ${sk_dbr} < mysql/${sk_dbr}.sql else echo "Error: Cant restore database $sk_dbr alredy exists in mysql server" diff --git a/bin/v-install-unsigned-ssl b/bin/v-install-unsigned-ssl index 8df023c9..9ac2f188 100644 --- a/bin/v-install-unsigned-ssl +++ b/bin/v-install-unsigned-ssl @@ -52,7 +52,9 @@ fi # Action # #----------------------------------------------------------# -/usr/local/vesta/bin/v-delete-web-domain-ssl "$user" "$domain" +if [ -f "/home/$user/conf/web/ssl.$domain.crt" ]; then + /usr/local/vesta/bin/v-delete-web-domain-ssl "$user" "$domain" +fi release=$(cat /etc/debian_version | tr "." "\n" | head -n1) diff --git a/bin/v-install-wordpress b/bin/v-install-wordpress index 5758e358..202919d0 100644 --- a/bin/v-install-wordpress +++ b/bin/v-install-wordpress @@ -95,19 +95,22 @@ PASSWDDB=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1) # Action # #----------------------------------------------------------# -PROTOCOL='http' -if [ -z "$SKIP_LE" ]; then - if [ ! -f "/home/$user/conf/web/ssl.$domain.ca" ]; then - /usr/local/vesta/bin/v-add-letsencrypt-domain "$user" "$domain" "www.$domain" "yes" - fi -else - PROTOCOL='https' +PROTOCOL='https' + +if [ ! -f "/home/$user/conf/web/ssl.$domain.ca" ]; then + echo "== Trying to install LetsEncrypt for domain $domain" + /usr/local/vesta/bin/v-add-letsencrypt-domain "$user" "$domain" "www.$domain" "yes" +fi + +if [ ! -z "$FORCE_HTTP" ]; then + # Switch to http:// only if --FORCE_HTTP parameter is set + echo "== Force http://" + PROTOCOL='http' fi TPL_CHANGED=0; -if [ -f "/home/$user/conf/web/ssl.$domain.ca" ] || [ ! -z "$SKIP_LE" ]; then - PROTOCOL='https' +if [ "$PROTOCOL" = "https" ]; then if [ -f "/usr/local/vesta/data/templates/web/nginx/force-https-firewall-wordpress.stpl" ] && [ $TPL_CHANGED -eq 0 ]; then TPL_CHANGED=1; /usr/local/vesta/bin/v-change-web-domain-proxy-tpl "$user" "$domain" "force-https-firewall-wordpress" "jpeg,jpg,png,gif,bmp,ico,svg,tif,tiff,css,js,ttf,otf,webp,txt,csv,rtf,doc,docx,xls,xlsx,ppt,pptx,odf,odp,ods,odt,pdf,psd,ai,eot,eps,ps,zip,tar,tgz,gz,rar,bz2,7z,aac,m4a,mp3,mp4,ogg,wav,wma,3gp,avi,flv,m4v,mkv,mov,mpeg,mpg,wmv,exe,iso,dmg,swf,woff,woff2" "yes" @@ -116,7 +119,8 @@ if [ -f "/home/$user/conf/web/ssl.$domain.ca" ] || [ ! -z "$SKIP_LE" ]; then TPL_CHANGED=1; /usr/local/vesta/bin/v-change-web-domain-proxy-tpl "$user" "$domain" "force-https" "jpeg,jpg,png,gif,bmp,ico,svg,tif,tiff,css,js,ttf,otf,webp,txt,csv,rtf,doc,docx,xls,xlsx,ppt,pptx,odf,odp,ods,odt,pdf,psd,ai,eot,eps,ps,zip,tar,tgz,gz,rar,bz2,7z,aac,m4a,mp3,mp4,ogg,wav,wma,3gp,avi,flv,m4v,mkv,mov,mpeg,mpg,wmv,exe,iso,dmg,swf,woff,woff2" "yes" fi -else +fi +if [ "$PROTOCOL" = "http" ]; then if [ -f "/usr/local/vesta/data/templates/web/nginx/hosting-firewall-wordpress.stpl" ] && [ $TPL_CHANGED -eq 0 ]; then TPL_CHANGED=1; /usr/local/vesta/bin/v-change-web-domain-proxy-tpl "$user" "$domain" "hosting-firewall-wordpress" "jpeg,jpg,png,gif,bmp,ico,svg,tif,tiff,css,js,ttf,otf,webp,txt,csv,rtf,doc,docx,xls,xlsx,ppt,pptx,odf,odp,ods,odt,pdf,psd,ai,eot,eps,ps,zip,tar,tgz,gz,rar,bz2,7z,aac,m4a,mp3,mp4,ogg,wav,wma,3gp,avi,flv,m4v,mkv,mov,mpeg,mpg,wmv,exe,iso,dmg,swf,woff,woff2" "yes" @@ -147,11 +151,11 @@ sudo -H -u$user wp core install --url="$domain" --title="$domain" --admin_user=" mysql -u$DBUSER -p$PASSWDDB -e "USE $DBUSER; update wp_options set option_value = '$PROTOCOL://$domain' where option_name = 'siteurl'; update wp_options set option_value = '$PROTOCOL://$domain' where option_name = 'home';" echo "=================================================================" -echo "Installation is complete. Your username/password is listed below." +echo "Your WordPress installation is complete." echo "" -echo "Site: $PROTOCOL://$domain/" +echo "Website URL: $PROTOCOL://$domain/" echo "" -echo "Login: $PROTOCOL://$domain/wp-admin/" +echo "WordPress admin login: $PROTOCOL://$domain/wp-admin/" echo "Username: $wpadmin" echo "Password: $password" echo "" diff --git a/bin/v-list-sys-config b/bin/v-list-sys-config index 127f2176..a0fdbbbc 100755 --- a/bin/v-list-sys-config +++ b/bin/v-list-sys-config @@ -54,7 +54,8 @@ json_list() { "SOFTACULOUS": "'$SOFTACULOUS'", "MAX_DBUSER_LEN": "'$MAX_DBUSER_LEN'", "MAIL_CERTIFICATE": "'$MAIL_CERTIFICATE'", - "VESTA_CERTIFICATE": "'$VESTA_CERTIFICATE'" + "VESTA_CERTIFICATE": "'$VESTA_CERTIFICATE'", + "DISABLE_IP_CHECK": "'$DISABLE_IP_CHECK'" } }' } diff --git a/bin/v-make-main-apache-log b/bin/v-make-main-apache-log index 96e91877..6a6dfadd 100644 --- a/bin/v-make-main-apache-log +++ b/bin/v-make-main-apache-log @@ -11,10 +11,4 @@ if ! /usr/local/vesta/bin/v-grep 'LogFormat "%t %v %a %D %r %>s \"%{User-Agent}i fi systemctl restart apache2 -if [ ! -f "/root/analyze-traffic-per-time.php" ]; then - wget -nv http://dl.myvestacp.com/vesta/apache_requests_analyzer/analyze-traffic-per-time.php -O /root/analyze-traffic-per-time.php - wget -nv http://dl.myvestacp.com/vesta/apache_requests_analyzer/analyze-traffic-per-site-sort-by-time.php -O /root/analyze-traffic-per-site-sort-by-time.php - wget -nv http://dl.myvestacp.com/vesta/apache_requests_analyzer/analyze-traffic-per-site-sort-by-hits.php -O /root/analyze-traffic-per-site-sort-by-hits.php - wget -nv http://dl.myvestacp.com/vesta/apache_requests_analyzer/analyze-traffic-per-ip-sort-by-time.php -O /root/analyze-traffic-per-ip-sort-by-time.php - wget -nv http://dl.myvestacp.com/vesta/apache_requests_analyzer/analyze-traffic-per-ip-sort-by-hits.php -O /root/analyze-traffic-per-ip-sort-by-hits.php -fi +wget -nv http://dl.myvestacp.com/vesta/apache_requests_analyzer/analyze-traffic.php -O /root/analyze-traffic.php diff --git a/bin/v-move-domain-and-database-to-account b/bin/v-move-domain-and-database-to-account index 08180d99..383fd26e 100644 --- a/bin/v-move-domain-and-database-to-account +++ b/bin/v-move-domain-and-database-to-account @@ -92,31 +92,51 @@ fi # Update Wordfence WAF Path # #----------------------------------------------------------# -# Path to .user.ini file -user_ini="$USER_DATA/web/$domain/public_html/.user.ini" +filepath="/home/USER_TO/web/$domain/public_html/.user.ini" +filename=$(basename $filepath) -# Check if .user.ini exists -if [ -f "$user_ini" ]; then - echo "Updating .user.ini with new user path..." +# Check if file exists +if [ -f "$filepath" ]; then + echo "Updating $filename with new user path..." # Temporary file for modification tmp_file=$(mktemp) # Change path from old USER to new USER_TO - sed "s|/home/$owner/public_html|/home/$USER_TO/public_html|g" "$user_ini" > "$tmp_file" + sed "s|/home/$owner/public_html|/home/$USER_TO/public_html|g" "$filepath" > "$tmp_file" - # Check if replacement was successful and update .user.ini + # Check if replacement was successful and update file if [ $? -eq 0 ]; then - mv "$tmp_file" "$user_ini" - echo ".user.ini updated successfully." + mv "$tmp_file" "$filepath" + echo "$filename updated successfully." else - echo "Failed to update .user.ini file." + echo "Failed to update $filename file." rm "$tmp_file" # Deletes temporary file fi -else - echo ".user.ini does not exist, no changes made." fi +filepath="/home/USER_TO/web/$domain/public_html/wordfence-waf.php" +filename=$(basename $filepath) + +# Check if file exists +if [ -f "$filepath" ]; then + echo "Updating $filename with new user path..." + + # Temporary file for modification + tmp_file=$(mktemp) + + # Change path from old USER to new USER_TO + sed "s|/home/$owner/public_html|/home/$USER_TO/public_html|g" "$filepath" > "$tmp_file" + + # Check if replacement was successful and update file + if [ $? -eq 0 ]; then + mv "$tmp_file" "$filepath" + echo "$filename updated successfully." + else + echo "Failed to update $filename file." + rm "$tmp_file" # Deletes temporary file + fi +fi #----------------------------------------------------------# # Vesta # diff --git a/bin/v-move-folder-and-make-symlink b/bin/v-move-folder-and-make-symlink index 81561a97..ccd66b7c 100644 --- a/bin/v-move-folder-and-make-symlink +++ b/bin/v-move-folder-and-make-symlink @@ -19,6 +19,8 @@ fi FROMFOLDER=$1 TOFOLDER=$2 +echo "Executing: v-move-folder-and-make-symlink $1 $2" + # Includes source $VESTA/func/main.sh @@ -26,6 +28,16 @@ source $VESTA/func/main.sh # Verifications # #----------------------------------------------------------# +if [ -z "$FROMFOLDER" ]; then + echo "First parameter is empty, aborting" + exit 1 +fi + +if [ -z "$TOFOLDER" ]; then + echo "Second parameter is empty, aborting" + exit 1 +fi + # Trimming the ending slash, just in case FROMFOLDER=$(echo "$FROMFOLDER" | sed 's:/*$::') TOFOLDER=$(echo "$TOFOLDER" | sed 's:/*$::') @@ -66,19 +78,21 @@ fi # Action # #----------------------------------------------------------# -rsync -a "$FROMFOLDER/" "$TOFOLDER/" -# with slashes on the end of the path of both folders -if [ "$?" -ne 0 ]; then - echo "Error happened, aborting" - exit 1 -fi - if [ "$FROMFOLDER" = "/home/$USER" ] && [ -d "$FROMFOLDER/conf" ]; then # if we are moving myVesta home folder, we must remove immutable attribute from conf/ files chattr -R -i "$FROMFOLDER/conf/" > /dev/null 2>&1 # with slashes on the end of the path of the folder fi +# rsync -a "$FROMFOLDER/" "$TOFOLDER/" +# with slashes on the end of the path of both folders + +mv "$FROMFOLDER" "$TOFOLDER" +if [ "$?" -ne 0 ]; then + echo "Error happened, aborting" + exit 1 +fi + rm -rf "$FROMFOLDER" # without slash on the end of the path of the folder diff --git a/bin/v-run-wp-cli b/bin/v-run-wp-cli index 672832ab..ef4f6e10 100644 --- a/bin/v-run-wp-cli +++ b/bin/v-run-wp-cli @@ -36,10 +36,13 @@ fi # Verifications # #----------------------------------------------------------# +VERBOSE_MODE=1 + check_args '2' "$#" 'DOMAIN WP_CLI_COMMAND' is_format_valid 'domain' is_object_valid 'user' 'USER' "$user" is_object_unsuspended 'user' 'USER' "$user" +is_object_unsuspended 'web' 'DOMAIN' "$domain" if [ ! -d "/home/$user" ]; then # echo "User doesn't exist"; @@ -58,22 +61,42 @@ if ! command -v wp &> /dev/null; then echo "WP CLI installed successfully." fi -if [ ! -d "/home/$user/web/$domain/public_html" ]; then - # echo "Domain doesn't exist"; - exit 1; +wpcli="/usr/local/bin/wp" + +if [ -f "/usr/local/bin/wp-cli/php/boot-fs.php" ]; then + wpcli="/usr/local/bin/wp-cli/php/boot-fs.php" + COLUMNS=$(/usr/bin/env stty size 2>/dev/null | awk '{print $2}') + echo $COLUMNS > /usr/local/bin/wp-cli/COLUMNS fi -phpver=$(/usr/local/vesta/bin/v-get-php-version-of-domain "$domain") +mkdir -p /home/$user/.wp-cli +chown $user:$user /home/$user/.wp-cli + +if [ -z "$PHP" ]; then + phpver=$(/usr/local/vesta/bin/v-get-php-version-of-domain "$domain") +else + phpver=$PHP +fi #----------------------------------------------------------# # Action # #----------------------------------------------------------# cd /home/$USER/web/$domain/public_html -sudo -u $USER /usr/bin/php$phpver /usr/local/bin/wp $wp_command +sudo -u $USER /usr/bin/php$phpver -d disable_functions=pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,exec,system,passthru,shell_exec,proc_open,popen -d open_basedir=/home/$user/web/$domain:/home/$user/.wp-cli:/home/$user/tmp:/usr/local/bin $wpcli --path=/home/$user/web/$domain/public_html/ $wp_command 2>/home/$user/web/$domain/wp-cli-error.log + +return_code=$? + +if [ -f "/usr/local/bin/wp-cli/COLUMNS" ]; then + rm /usr/local/bin/wp-cli/COLUMNS +fi + +# echo "WP CLI: Done." +# echo "To see Warning/Error log: " +# echo "cat /home/$user/web/$domain/wp-cli-error.log" #----------------------------------------------------------# # Vesta # #----------------------------------------------------------# -exit 0; +exit $return_code; diff --git a/bin/v-unlock-wordpress b/bin/v-unlock-wordpress index 1e2cccc6..4a2c42c3 100644 --- a/bin/v-unlock-wordpress +++ b/bin/v-unlock-wordpress @@ -58,6 +58,8 @@ chown -R $user:$user public_html/ rm public_html/wp-content/uploads/.htaccess +/usr/local/vesta/bin/v-fix-website-permissions $domain + #----------------------------------------------------------# # Vesta # #----------------------------------------------------------# diff --git a/bin/v-update-document-errors-files b/bin/v-update-document-errors-files new file mode 100644 index 00000000..c044a80a --- /dev/null +++ b/bin/v-update-document-errors-files @@ -0,0 +1,48 @@ +#!/bin/bash +# info: fix website permissions for all websites +# options: +# +# The command is used for fixing website permissions for all websites on the server. + + +#----------------------------------------------------------# +# Variable&Function # +#----------------------------------------------------------# + +# Importing system variables +source /etc/profile + +# Includes +source $VESTA/func/main.sh + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +for user in $(grep '@' /etc/passwd |cut -f1 -d:); do + if [ ! -f "/usr/local/vesta/data/users/$user/user.conf" ]; then + continue; + fi + + for domain in $(/usr/local/vesta/bin/v-list-web-domains $user plain |cut -f 1); do + cp /usr/local/vesta/data/templates/web/skel/document_errors/403.html /home/$user/web/$domain/document_errors/403.html + cp /usr/local/vesta/data/templates/web/skel/document_errors/404.html /home/$user/web/$domain/document_errors/404.html + cp /usr/local/vesta/data/templates/web/skel/document_errors/50x.html /home/$user/web/$domain/document_errors/50x.html + sed -i "s/%domain%/$domain/g" /home/$user/web/$domain/document_errors/403.html + sed -i "s/%domain%/$domain/g" /home/$user/web/$domain/document_errors/404.html + sed -i "s/%domain%/$domain/g" /home/$user/web/$domain/document_errors/50x.html + chown $user:$user /home/$user/web/$domain/document_errors/* + chmod 644 /home/$user/web/$domain/document_errors/* + done + +done + + +#----------------------------------------------------------# +# Vesta # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-mail-domain-disk b/bin/v-update-mail-domain-disk index 451dbd37..be5502e7 100755 --- a/bin/v-update-mail-domain-disk +++ b/bin/v-update-mail-domain-disk @@ -49,7 +49,8 @@ dom_diks=0 for account in $(search_objects "mail/$domain" 'SUSPENDED' "no" 'ACCOUNT'); do home_dir=$HOMEDIR/$user/mail/$domain/$account if [ -e "$home_dir" ]; then - udisk=$(nice -n 19 du -shm $home_dir | cut -f 1 ) + cd $home_dir + udisk=$(nice -n 19 du -shm ./ | cut -f 1 ) else udisk=0 fi diff --git a/bin/v-update-mail-domains-disk b/bin/v-update-mail-domains-disk index 1dae64cf..807218e3 100755 --- a/bin/v-update-mail-domains-disk +++ b/bin/v-update-mail-domains-disk @@ -35,9 +35,9 @@ fi #----------------------------------------------------------# # Starting loop -for domain in $(search_objects 'mail' 'SUSPENDED' "no" 'DOMAIN'); do +for domain in $(list_objects 'mail' 'DOMAIN'); do dom_diks=0 - accounts=$(search_objects "mail/$domain" 'SUSPENDED' "no" 'ACCOUNT') + accounts=$(list_objects "mail/$domain" 'ACCOUNT') for account in $accounts; do home_dir=$HOMEDIR/$user/mail/$domain/$account if [ -e "$home_dir" ]; then diff --git a/bin/v-update-web-domain-disk b/bin/v-update-web-domain-disk index ac851b92..1bee4685 100755 --- a/bin/v-update-web-domain-disk +++ b/bin/v-update-web-domain-disk @@ -50,6 +50,14 @@ if [ -e "$home_dir" ]; then disk_usage=$(nice -n 19 du -shm $home_dir | cut -f 1 ) fi +# Defining hdd home directory +home_dir="/hdd$HOMEDIR/$user/web/$domain/" + +# Checking home directory exist +if [ -e "$home_dir" ] && [[ ! -L "$home_dir" ]]; then + disk_usage2=$(nice -n 19 du -shm $home_dir | cut -f 1 ) + disk_usage=$(( disk_usage + disk_usage2 )) +fi #----------------------------------------------------------# # Vesta # diff --git a/bin/v-update-web-domains-disk b/bin/v-update-web-domains-disk index 5951f289..5ee58abf 100755 --- a/bin/v-update-web-domains-disk +++ b/bin/v-update-web-domains-disk @@ -32,11 +32,16 @@ is_object_valid 'user' 'USER' "$user" #----------------------------------------------------------# # Domain loop -for domain in $(search_objects 'web' 'SUSPENDED' "no" 'DOMAIN'); do +for domain in $(list_objects 'web' 'DOMAIN'); do home_dir="$HOMEDIR/$user/web/$domain/" if [ -e "$home_dir" ]; then disk_usage=$(nice -n 19 du -shm $home_dir | cut -f 1 ) fi + home_dir="/hdd$HOMEDIR/$user/web/$domain/" + if [ -e "$home_dir" ] && [[ ! -L "$home_dir" ]]; then + disk_usage2=$(nice -n 19 du -shm $home_dir | cut -f 1 ) + disk_usage=$(( disk_usage + disk_usage2 )) + fi update_object_value 'web' 'DOMAIN' "$domain" '$U_DISK' "$disk_usage" done diff --git a/func/db.sh b/func/db.sh index 58a339ee..7e4f4d97 100644 --- a/func/db.sh +++ b/func/db.sh @@ -58,7 +58,7 @@ mysql_query() { mysql_dump() { err="/tmp/e.mysql" - mysqldump --defaults-file=$mycnf --single-transaction --max_allowed_packet=100M -r $1 $2 2> $err + mysqldump --defaults-file=$mycnf --complete-insert --force --quick --single-transaction --max-allowed-packet=1024MB -r $1 $2 2> $err if [ '0' -ne "$?" ]; then rm -rf $tmpdir if [ "$notify" != 'no' ]; then diff --git a/func/main.php b/func/main.php index 22834d42..4628c92a 100644 --- a/func/main.php +++ b/func/main.php @@ -53,6 +53,7 @@ function myvesta_check_args ($requried_arguments, $arguments) { $argument_counter=count($argv); $argument_counter--; $argv[0]=str_replace('/usr/local/vesta/bin/', '', $argv[0]); + $command=$argv[0]; // myvesta_echo ( "-------------------- ".$argv[0]." --------------------\n"); if ($argument_counter<$requried_arguments) { $arguments=str_replace(" ", "' '", $arguments); diff --git a/func/main.sh b/func/main.sh index 10de469a..27c4dcbe 100644 --- a/func/main.sh +++ b/func/main.sh @@ -254,6 +254,9 @@ is_object_unsuspended() { spnd=$(grep "$2='$3'" $USER_DATA/$1.conf |grep "SUSPENDED='yes'") fi if [ ! -z "$spnd" ]; then + if [ ! -z "$VERBOSE_MODE" ]; then + echo "Error: $(basename $1) $3 is suspended" + fi check_result $E_SUSPENDED "$(basename $1) $3 is suspended" fi } @@ -359,6 +362,17 @@ search_objects() { IFS="$OLD_IFS" } +# List objects +list_objects() { + OLD_IFS="$IFS" + IFS=$'\n' + for line in $(cat $USER_DATA/$1.conf); do + eval $line + eval echo \$$2 + done + IFS="$OLD_IFS" +} + # Get user value get_user_value() { grep "^${1//$/}=" $USER_DATA/user.conf |awk -F "'" '{print $2}' @@ -1143,3 +1157,82 @@ check_if_service_exists() { echo "0" fi } + +# Parsing config variables with key='value' and key="value" pairs and setting them as variables, without using Perl. +# Inspired by HestiaCP function and improved +parse_object_kv_list_non_eval() { + # Let's combine all the parameters into one string, replace the new lines with a space + local str="${*//$'\n'/ }" + str=${str//\\\'/---QUOTE---} + str=${str//\\\"/---DQUOTE---} + local backup_str=$str + + local key val match i length length_val prefix position cut + i=0 + # Searching for key='value' blocks + # Loop until we find the next key='value' + while [[ $str =~ ([A-Za-z][[:alnum:]_]*)=\'([^\']*)\' ]]; do + key="${BASH_REMATCH[1]}" + val="${BASH_REMATCH[2]}" + match="${BASH_REMATCH[0]}" + length=${#match} + length_val=${#match} + + # Key validation: alphanumeric, length 2–66 (key must start and end with a letter/number) + if ! [[ "$key" =~ ^[[:alnum:]][_[:alnum:]]{0,64}[[:alnum:]]$ ]]; then + check_result "$E_INVALID" "Invalid key format [$key]" + fi + + # Declaring a global variable + val=${val/---QUOTE---/\\\'} + val=${val/---DQUOTE---/\\\"} + declare -g "$key"="$val" + + # Let's remove the processed part from str to continue + prefix=${str%%"$key="*} + position=${#prefix} + cut=$((position + 1 + length_val)) + str=${str:cut} + ((i++)) + if [ $i -eq 100 ]; then + check_result "$E_INVALID" "Potentially conf-parsing infinite loop detected" + fi + done + + # Terminate function if we don't expect strings with double apostrophes + if [ -z "$PARSE_DOUBLE_QUOTES_VAR" ]; then + return; + fi + + # Searching for key="value" blocks + str=$backup_str + i=0 + # Loop until we find the next key="value" + while [[ $str =~ ([A-Za-z][[:alnum:]_]*)=\"([^\"]*)\" ]]; do + key="${BASH_REMATCH[1]}" + val="${BASH_REMATCH[2]}" + match="${BASH_REMATCH[0]}" + length=${#match} + length_val=${#match} + + # Key validation: alphanumeric, length 2–66 (key must start and end with a letter/number) + if ! [[ "$key" =~ ^[[:alnum:]][_[:alnum:]]{0,64}[[:alnum:]]$ ]]; then + check_result "$E_INVALID" "Invalid key format [$key]" + fi + + # Declaring a global variable + val=${val/---QUOTE---/\\\'} + val=${val/---DQUOTE---/\\\"} + declare -g "$key"="$val" + + # Let's remove the processed part from str to continue + prefix=${str%%"$key="*} + position=${#prefix} + cut=$((position + 1 + length_val)) + str=${str:cut} + ((i++)) + if [ $i -eq 100 ]; then + check_result "$E_INVALID" "Potentially conf-parsing infinite loop detected" + fi + done +} diff --git a/install/debian/10/templates/web/nginx/private-hosting.sh b/install/debian/10/templates/web/nginx/private-hosting.sh index abc9155d..eeed37ef 100755 --- a/install/debian/10/templates/web/nginx/private-hosting.sh +++ b/install/debian/10/templates/web/nginx/private-hosting.sh @@ -1,11 +1,11 @@ -#!/bin/bash -# Changing public_html permission -user="$1" -domain="$2" -ip="$3" -home_dir="$4" -docroot="$5" - -chmod 755 $docroot - -exit 0 +#!/bin/bash +# Changing public_html permission +user="$1" +domain="$2" +ip="$3" +home_dir="$4" +docroot="$5" + +chmod 755 $docroot + +exit 0 diff --git a/install/debian/11/templates/web/nginx/private-hosting.sh b/install/debian/11/templates/web/nginx/private-hosting.sh index abc9155d..eeed37ef 100755 --- a/install/debian/11/templates/web/nginx/private-hosting.sh +++ b/install/debian/11/templates/web/nginx/private-hosting.sh @@ -1,11 +1,11 @@ -#!/bin/bash -# Changing public_html permission -user="$1" -domain="$2" -ip="$3" -home_dir="$4" -docroot="$5" - -chmod 755 $docroot - -exit 0 +#!/bin/bash +# Changing public_html permission +user="$1" +domain="$2" +ip="$3" +home_dir="$4" +docroot="$5" + +chmod 755 $docroot + +exit 0 diff --git a/install/debian/12/templates/web/nginx/private-hosting.sh b/install/debian/12/templates/web/nginx/private-hosting.sh index abc9155d..eeed37ef 100755 --- a/install/debian/12/templates/web/nginx/private-hosting.sh +++ b/install/debian/12/templates/web/nginx/private-hosting.sh @@ -1,11 +1,11 @@ -#!/bin/bash -# Changing public_html permission -user="$1" -domain="$2" -ip="$3" -home_dir="$4" -docroot="$5" - -chmod 755 $docroot - -exit 0 +#!/bin/bash +# Changing public_html permission +user="$1" +domain="$2" +ip="$3" +home_dir="$4" +docroot="$5" + +chmod 755 $docroot + +exit 0 diff --git a/install/vst-install-debian.sh b/install/vst-install-debian.sh index 850b91f7..f6de9e70 100755 --- a/install/vst-install-debian.sh +++ b/install/vst-install-debian.sh @@ -491,10 +491,16 @@ echo -e "\n\n" # Asking for confirmation to proceed if [ "$interactive" = 'yes' ]; then - read -p 'Would you like to continue [y/n]: ' answer - if [ "$answer" != 'y' ] && [ "$answer" != 'Y' ]; then - echo 'Goodbye' - exit 1 + prompt_to_continue=1; + if [ ! -z "$email" ] && [ ! -z "$secret_url" ] && [ ! -z "$port" ] && [ ! -z "$servername" ]; then + prompt_to_continue=0; + fi + if [ $prompt_to_continue -eq 1 ]; then + read -p 'Would you like to continue [y/n]: ' answer + if [ "$answer" != 'y' ] && [ "$answer" != 'Y' ]; then + echo 'Goodbye' + exit 1 + fi fi # Asking for contact email @@ -753,31 +759,37 @@ if [ "$mysql" = 'no' ]; then fi if [ "$mysql8" = 'yes' ]; then echo "=== Preparing MySQL 8 apt repo" - software=$(echo "$software" | sed -e 's/exim4-daemon-heavy//') - software=$(echo "$software" | sed -e 's/exim4//') - #software="$software php-mysql roundcube-mysql" - echo "### THIS FILE IS AUTOMATICALLY CONFIGURED ###" > /etc/apt/sources.list.d/mysql.list - echo "# You may comment out entries below, but any other modifications may be lost." >> /etc/apt/sources.list.d/mysql.list - echo "# Use command 'dpkg-reconfigure mysql-apt-config' as root for modifications." >> /etc/apt/sources.list.d/mysql.list - echo "deb http://repo.mysql.com/apt/debian/ $codename mysql-apt-config" >> /etc/apt/sources.list.d/mysql.list - echo "deb http://repo.mysql.com/apt/debian/ $codename mysql-8.0" >> /etc/apt/sources.list.d/mysql.list - echo "deb http://repo.mysql.com/apt/debian/ $codename mysql-tools" >> /etc/apt/sources.list.d/mysql.list - echo "#deb http://repo.mysql.com/apt/debian/ $codename mysql-tools-preview" >> /etc/apt/sources.list.d/mysql.list - echo "deb-src http://repo.mysql.com/apt/debian/ $codename mysql-8.0" >> /etc/apt/sources.list.d/mysql.list - - # apt-key adv --keyserver pgp.mit.edu --recv-keys 3A79BD29 - key="467B942D3A79BD29" - readonly key - GNUPGHOME="$(mktemp -d)" - export GNUPGHOME - for keyserver in $(shuf -e ha.pool.sks-keyservers.net hkp://p80.pool.sks-keyservers.net:80 keyserver.ubuntu.com hkp://keyserver.ubuntu.com:80) - do - gpg --keyserver "${keyserver}" --recv-keys "${key}" 2>&1 && break - done - gpg --export "${key}" > /etc/apt/trusted.gpg.d/mysql.gpg - gpgconf --kill all - rm -rf "${GNUPGHOME}" - unset GNUPGHOME + if [ "$release" -lt 12 ]; then + software=$(echo "$software" | sed -e 's/exim4-daemon-heavy//') + software=$(echo "$software" | sed -e 's/exim4//') + #software="$software php-mysql roundcube-mysql" + echo "### THIS FILE IS AUTOMATICALLY CONFIGURED ###" > /etc/apt/sources.list.d/mysql.list + echo "# You may comment out entries below, but any other modifications may be lost." >> /etc/apt/sources.list.d/mysql.list + echo "# Use command 'dpkg-reconfigure mysql-apt-config' as root for modifications." >> /etc/apt/sources.list.d/mysql.list + echo "deb http://repo.mysql.com/apt/debian/ $codename mysql-apt-config" >> /etc/apt/sources.list.d/mysql.list + echo "deb http://repo.mysql.com/apt/debian/ $codename mysql-8.0" >> /etc/apt/sources.list.d/mysql.list + echo "deb http://repo.mysql.com/apt/debian/ $codename mysql-tools" >> /etc/apt/sources.list.d/mysql.list + echo "#deb http://repo.mysql.com/apt/debian/ $codename mysql-tools-preview" >> /etc/apt/sources.list.d/mysql.list + echo "deb-src http://repo.mysql.com/apt/debian/ $codename mysql-8.0" >> /etc/apt/sources.list.d/mysql.list + + # apt-key adv --keyserver pgp.mit.edu --recv-keys 3A79BD29 + key="467B942D3A79BD29" + readonly key + GNUPGHOME="$(mktemp -d)" + export GNUPGHOME + for keyserver in $(shuf -e ha.pool.sks-keyservers.net hkp://p80.pool.sks-keyservers.net:80 keyserver.ubuntu.com hkp://keyserver.ubuntu.com:80) + do + gpg --keyserver "${keyserver}" --recv-keys "${key}" 2>&1 && break + done + gpg --export "${key}" > /etc/apt/trusted.gpg.d/mysql.gpg + gpgconf --kill all + rm -rf "${GNUPGHOME}" + unset GNUPGHOME + else + # check latest on: https://dev.mysql.com/downloads/repo/apt/ + wget https://dev.mysql.com/get/mysql-apt-config_0.8.34-1_all.deb + dpkg -i mysql-apt-config_0.8.34-1_all.deb + fi mpass=$(gen_pass) debconf-set-selections <<< "mysql-community-server mysql-community-server/root-pass password $mpass" @@ -1575,6 +1587,15 @@ if [ "$spamd" = 'yes' ]; then echo "=== Patching spamassassin dns_server" sed -i "s/report_safe 1/report_safe 1\n\ndns_server 127.0.0.1/g" /etc/spamassassin/local.cf + echo "== Adding myVesta rules to SpamAssassin" + cat < /etc/spamassassin/myvesta.cf +score RCVD_IN_RP_SAFE 0 +score RCVD_IN_RP_CERTIFIED 0 +score SPF_FAIL 3.0 +score SPF_SOFTFAIL 4.0 +score SPF_NONE 4.0 +EOF + wget -nv -O /etc/spamassassin/barracuda.cf http://c.myvestacp.com/tools/spamassassin/barracuda.cf ensure_startup $currentservice systemctl restart $currentservice @@ -1684,6 +1705,20 @@ if [ "$fail2ban" = 'yes' ]; then chmod 640 /var/log/auth.log chown root:adm /var/log/auth.log fi + if [ "$proftpd" = 'yes' ]; then + cat <> /etc/fail2ban/jail.local + +[proftpd] +enabled = true +filter = proftpd +action = vesta[name=FTP] +port = ftp,ftp-data,ftps,ftps-data +logpath = %(proftpd_log)s +backend = %(proftpd_backend)s +maxretry = 5 +EOF + fi + #update-rc.d fail2ban defaults currentservice='fail2ban' ensure_startup $currentservice @@ -2052,7 +2087,6 @@ if [ "$port" != "8083" ]; then $VESTA/bin/v-change-vesta-port $port fi -echo "=== Set URL for phpmyadmin" echo "DB_PMA_URL='https://$servername/phpmyadmin/'" >> $VESTA/conf/vesta.conf if [ "$release" -gt 9 ]; then echo "=== Set max_length_of_MySQL_username=80" @@ -2060,12 +2094,17 @@ if [ "$release" -gt 9 ]; then fi echo "ALLOW_BACKUP_ANYTIME='yes'" >> $VESTA/conf/vesta.conf echo "NOTIFY_ADMIN_FULL_BACKUP='$email'" >> $VESTA/conf/vesta.conf -echo "================================================================" +echo "=== Adding FileManager license to vesta.conf" +echo "FILEMANAGER_KEY='FREEFM'" >> $VESTA/conf/vesta.conf # Removing old PHP sessions files -crontab -l | { cat; echo "10 2 * * 6 sudo find /home/*/tmp/ -type f -mtime +5 -exec rm {} \;"; } | crontab - +touch /var/spool/cron/crontabs/root +echo "10 2 * * 6 sudo find /home/*/tmp/ -type f -mtime +5 -exec rm {} \;" >> /var/spool/cron/crontabs/root -echo "alias v-cd-www='source /usr/local/vesta/bin/v-change-dir-www'" >> /root/.bash_profile +if [ -f "/root/.bash_profile" ]; then + echo "=== Adding v-cd-www alias to root bash profile" + echo "alias v-cd-www='source /usr/local/vesta/bin/v-change-dir-www'" >> /root/.bash_profile +fi #----------------------------------------------------------# # myVesta Access Info # diff --git a/src/deb/for-download/tools/multi-php-install.sh b/src/deb/for-download/tools/multi-php-install.sh index 70d589cc..aa1b7353 100644 --- a/src/deb/for-download/tools/multi-php-install.sh +++ b/src/deb/for-download/tools/multi-php-install.sh @@ -405,8 +405,8 @@ if [ "$inst_84" -eq 1 ]; then fi -apt update > /dev/null 2>&1 -apt upgrade -y > /dev/null 2>&1 +# apt update > /dev/null 2>&1 +# apt upgrade -y > /dev/null 2>&1 if [ $debian_version -ge 10 ]; then a2dismod ruid2 > /dev/null 2>&1 @@ -454,6 +454,10 @@ if [ -f "/usr/local/bin/tailf_apache_error.php" ]; then echo "=== upgrading tailf_apache_error.php done." sleep 3 echo "" - echo "Everything done." - echo "" fi + +# Fixing php.ini files to have the correct disable_functions line +/usr/local/vesta/bin/v-fix-php-ini-disable-functions + +echo "Everything done." +echo "" diff --git a/src/deb/ioncube/copyright b/src/deb/ioncube/copyright index bd92bd81..c62257d2 100644 --- a/src/deb/ioncube/copyright +++ b/src/deb/ioncube/copyright @@ -1,243 +1,243 @@ -LICENCE AGREEMENT FOR THE IONCUBE PHP LOADER, PROVIDED TO ENABLE THE USE -OF IONCUBE ENCODED FILES AND AS PART OF THE IONCUBE24 SERVICE (ioncube24.com) - -YOU SHOULD CAREFULLY READ THE FOLLOWING TERMS AND CONDITIONS BEFORE USING THE -LOADER SOFTWARE. THE INSTALLATION AND/OR USE OR COPYING OF THE IONCUBE PHP -LOADER SOFTWARE INDICATES YOUR ACCEPTANCE OF THIS LICENCE AGREEMENT. IF YOU -DO NOT ACCEPT THE TERMS OF THIS LICENCE AGREEMENT, DO NOT INSTALL, COPY -AND/OR USE THE LOADER SOFTWARE. - -DEFINITIONS - -The following definitions shall apply in this document: - -LOADER shall mean the ionCube PHP Loader software package or collection -of Loaders, including any modifications or upgrades to the software, used for -executing PHP scripts previously encoded with the ionCube PHP Encoder -software to render them non-humanly readable, and any associated -documentation or electronic or online materials relating to the software. - -ENCODER shall mean any ionCube PHP Encoder software or service used for the -purpose of producing non-humanly readable encoded files from PHP scripts. - -ENCODED FILE shall mean a non-humanly readable file produced by the -Encoder and being derived from humanly readable PHP script source. - -PROVIDER shall mean ionCube Ltd. - -USER/YOU shall mean any entity who has downloaded or obtained through any -other means a version of the Loader software. - - -1 LICENSE ENTITLEMENT - -1.1 The Loader is provided without charge. Title to the Loader does not pass -to the user in any circumstances. The Loader is supplied as object code. - -1.2 The provider grants a personal, non-transferable, non-exclusive licence to -use the Loader in accordance with the terms and conditions of this Licence -Agreement. - -1.3 The installation or downloading and use of the Loader entitles the user -to install and use the Loader for its own internal lawful purposes. - - -2 DISTRIBUTION - -2.1 The Loader may be freely distributed to third parties alone or as -part of a distribution containing other items provided that this license -is also included. - -2.2 The Loader may under no circumstances be branded as another product, -whether distributed or not. - -2.3 Distribution as part of a commercial product is permitted provided such -distribution is in accordance with clauses 2.1 and 2.2 with respect to the -Loader. - - -3 ANALYSIS / REVERSE ENGINEERING / MODIFICATION - -Except insofar as the user is permitted to do so in accordance with applicable -law: - -3.1 Any analysis of the Loader and embedded data by any means and by -any entity whether human or otherwise and including but without limitation to -discover details of internal operation, to reverse engineer, to de-compile -object code, or to modify for the purposes of modifying behaviour is -forbidden. - -3.2 Any analysis of encoded files by any means and by any entity whether human -or otherwise and including but without limitation to discover details of file -format or for the purposes of modifying behaviour or scope of their usage is -forbidden. - - -4 WARRANTY - -THE LOADER SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED -WARRANTIES INCLUDING BUT WITHOUT LIMITATION THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE ARE -DISCLAIMED. THE PROVIDER DOES NOT WARRANT THAT THE LOADER IS UNINTERRUPTED -OR ERROR FREE, NOR THAT THE OPERATION OF THE LOADER WILL FUNCTION IN -CONJUNCTION WITH ANY OTHER PRODUCT. - - -5 LIMITATION OF LIABILITY - -5.1 IN NO EVENT WILL THE PROVIDER OF THE LOADER BE LIABLE TO THE USER OR ANY -PARTY FOR ANY DIRECT, INDIRECT, PUNITIVE, SPECIAL, INCIDENTAL OR OTHER -CONSEQUENTIAL DAMAGES ARISING DIRECTLY OR INDIRECTLY FROM THIS LICENCE -AGREEMENT OR ANY USE OF THE LOADER OR ENCODED FILES, EVEN IF THE PROVIDER IS -EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -5.2 THE LOADER IS PROVIDED ON AN "AS IS" BASIS. THE PROVIDER EXCLUDES ALL -WARRANTIES, CONDITIONS, TERMS, UNDERTAKINGS AND REPRESENTATIONS (EXCLUDING -FRAUDULENT MISREPRESENTATION) OF ANY KIND, EXPRESS OR IMPLIED, STATUTORY OR -OTHERWISE IN CONNECTION WITH THE LOADER TO THE FULLEST EXTENT PERMITTED BY -LAW. - -5.3 DOWNLOADING THE LOADER IS AT YOUR OWN RISK AND THE PROVIDER DOES NOT -ACCEPT LIABILITY FOR ANY DIRECT OR INDIRECT LOSS OR DAMAGE HOWSOEVER CAUSED AS -A RESULT OF ANY COMPUTER VIRUSES, BUGS, TROJAN HORSES, WORMS, SOFTWARE BOMBS -OR OTHER SIMILAR PROGRAMS ARISING FROM YOUR USE OF THE LOADER. WHILST THE -PROVIDER WILL DO ITS BEST TO ENSURE THAT THE LOADER IS FREE FROM SUCH -DESTRUCTIVE PROGRAMS, IT IS YOUR RESPONSIBILITY TO TAKE REASONABLE PRECAUTIONS -TO SCAN FOR SUCH DESTRUCTIVE PROGRAMS DOWNLOADED FROM THE INTERNET. - -5.4 THE PROVIDER'S MAXIMUM LIABILITY FOR ANY LOSS OR DAMAGE ARISING FROM THIS -LICENCE AGREEMENT SHALL IN ANY EVENT BE LIMITED IN THE SOLE DISCRETION OF THE -PROVIDER TO THE REPLACEMENT OF THE LOADER PRODUCT. - -5.5 DUE TO THE NATURE OF THE INTERNET, THE PROVIDER CANNOT GUARANTEE THAT ANY -E-MAILS OR OTHER ELECTRONIC TRANSMISSIONS WILL BE SENT TO YOU OR RECEIVED BY -THE PROVIDER OR THAT THE CONTENT OF SUCH TRANSMISSIONS WILL BE SECURE DURING -TRANSMISSION. - - -6 BUG FIXING AND PRODUCT SUPPORT - -6.1 The provider will use reasonable endeavours to provide support to users. -The provider will at their discretion only provide support for the latest -release. - -6.2 Support comprises of fault reporting via tickets and fault diagnosis, -recommendations on workarounds, and where reasonably possible a timely -resolution. - -6.3 The user accepts that on occasion the ability of the provider to meet -anticipated or published support schedules may be impaired due to, but without -limitation, Internet service provider failures or software failures that -affect the ability to communicate for an indeterminate period. - -6.4 The provider reserves the right to refuse to provide support at any time. - -6.5 The provider wishes to maintain and offer a product of the highest -possible quality, and accordingly may from time to time and at its discretion -make product changes for the purpose of correcting behaviour in variance to -the published specification or the user's reasonable expectations. - -6.6 The provider reserves the right to charge for support where the user does -not have a valid support plan in place, or where the support offered exceeds -the scope of the active support plan. - - -7 PRODUCT UPGRADES - -7.1 The provider may from time to time release product upgrades. These will -be provided free of charge and attempts made to provide a timely notification -to customers of the existence of any new release. - - -8 ERRORS AND OMISSIONS - -Whilst reasonable endeavours are made to ensure the accuracy of documentation -concerning the details of the Loader, the user accepts the possibility of -inaccuracies in information presented in any format, including email -communications and online services. The provider shall under no circumstances -be liable for any events that arise as a result of unintentional inaccuracies -or omissions. - - -9 USER INDEMNITY - -You agree to fully indemnify, defend and hold the provider harmless -immediately upon demand from and against all actions, liability, claims, -losses, damages, costs and expenses (including legal/attorney fees) incurred -by the provider arising directly or indirectly as a result of your breach of -this Licence Agreement. - - -10 INTELLECTUAL PROPERTY RIGHTS - -10.1 The user acknowledges that the Loader and associated documentation and -materials contain proprietary information of the provider and are and shall -remain the exclusive property of the provider and/or its licensors and all -title, copyright, trade marks, trade names, patents and other intellectual -property rights therein of whatever nature shall remain the sole property of -the provider and/or its licensors. - -10.2 No title to or rights of ownership, copyright or other intellectual -property in the Loader is transferred to the user (other than the licence -rights expressly granted in this Licence Agreement). - - -11 TERMINATION - -11.1 The provider reserves the right to terminate this Licence Agreement -immediately by notice in writing against the user if the user is in breach of -any terms and conditions of this Licence Agreement. - -11.2 Termination of this Licence Agreement for any reason shall be without -prejudice to any other rights or remedies of the provider which may have -arisen on or before the date of termination under this Licence Agreement or in -law. - -11.3 The provisions of the following clauses shall survive any termination of -this agreement; clause 3, 5, 10 and 13. - - -12 GENERAL - -12.1 The provider reserves the right to transfer or assign all or any of its -rights and duties and responsibilities set out in this Licence Agreement to -another party. - -12.2 Headings have been included for convenience only and will not be used in -construing any provision of this Licence Agreement. - -12.3 No delay or failure by the provider to exercise any powers, rights or -remedies under this Licence Agreement will operate as a waiver of them nor -will any single or partial exercise of any such powers, rights or remedies -include any other or further exercise of them. - -12.4 If any part of this Licence Agreement is found by a court of competent -jurisdiction or other competent authority to be invalid, unlawful or -unenforceable then such part shall be severed from the remainder of this -Licence Agreement which will continue to be valid and enforceable to the -fullest extent permitted by applicable law. - -12.5 This Licence Agreement including the documents or other sources referred -to herein supersede all prior representations, understandings and agreements -between the user and the provider relating to the Loader and sets forth the -entire agreement and understanding between the user and the provider relating -to the Loader. - -12.6 Nothing in this Licence Agreement shall be deemed to constitute a -partnership between you and the provider nor constitute either party being an -agent of the other party. - -12.7 This Agreement does not create any rights or benefits enforceable by any -person not a party to it (within the meaning of the U.K.Contracts (Rights of -Third Parties) Act 1999) except that a person who under clause 12.1 is a -permitted successor or assignee of the rights or benefits of the provider may -enforce such rights or benefits. - - -13 GOVERNING LAW AND JURISDICTION - -This License Agreement and any issues relating thereto shall be construed and -interpreted in accordance with the laws of England and subject to the -exclusive jurisdiction of the English courts. - -Copyright (c) 2002-2017 ionCube Ltd. Last revised 23-April-2015 +LICENCE AGREEMENT FOR THE IONCUBE PHP LOADER, PROVIDED TO ENABLE THE USE +OF IONCUBE ENCODED FILES AND AS PART OF THE IONCUBE24 SERVICE (ioncube24.com) + +YOU SHOULD CAREFULLY READ THE FOLLOWING TERMS AND CONDITIONS BEFORE USING THE +LOADER SOFTWARE. THE INSTALLATION AND/OR USE OR COPYING OF THE IONCUBE PHP +LOADER SOFTWARE INDICATES YOUR ACCEPTANCE OF THIS LICENCE AGREEMENT. IF YOU +DO NOT ACCEPT THE TERMS OF THIS LICENCE AGREEMENT, DO NOT INSTALL, COPY +AND/OR USE THE LOADER SOFTWARE. + +DEFINITIONS + +The following definitions shall apply in this document: + +LOADER shall mean the ionCube PHP Loader software package or collection +of Loaders, including any modifications or upgrades to the software, used for +executing PHP scripts previously encoded with the ionCube PHP Encoder +software to render them non-humanly readable, and any associated +documentation or electronic or online materials relating to the software. + +ENCODER shall mean any ionCube PHP Encoder software or service used for the +purpose of producing non-humanly readable encoded files from PHP scripts. + +ENCODED FILE shall mean a non-humanly readable file produced by the +Encoder and being derived from humanly readable PHP script source. + +PROVIDER shall mean ionCube Ltd. + +USER/YOU shall mean any entity who has downloaded or obtained through any +other means a version of the Loader software. + + +1 LICENSE ENTITLEMENT + +1.1 The Loader is provided without charge. Title to the Loader does not pass +to the user in any circumstances. The Loader is supplied as object code. + +1.2 The provider grants a personal, non-transferable, non-exclusive licence to +use the Loader in accordance with the terms and conditions of this Licence +Agreement. + +1.3 The installation or downloading and use of the Loader entitles the user +to install and use the Loader for its own internal lawful purposes. + + +2 DISTRIBUTION + +2.1 The Loader may be freely distributed to third parties alone or as +part of a distribution containing other items provided that this license +is also included. + +2.2 The Loader may under no circumstances be branded as another product, +whether distributed or not. + +2.3 Distribution as part of a commercial product is permitted provided such +distribution is in accordance with clauses 2.1 and 2.2 with respect to the +Loader. + + +3 ANALYSIS / REVERSE ENGINEERING / MODIFICATION + +Except insofar as the user is permitted to do so in accordance with applicable +law: + +3.1 Any analysis of the Loader and embedded data by any means and by +any entity whether human or otherwise and including but without limitation to +discover details of internal operation, to reverse engineer, to de-compile +object code, or to modify for the purposes of modifying behaviour is +forbidden. + +3.2 Any analysis of encoded files by any means and by any entity whether human +or otherwise and including but without limitation to discover details of file +format or for the purposes of modifying behaviour or scope of their usage is +forbidden. + + +4 WARRANTY + +THE LOADER SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED +WARRANTIES INCLUDING BUT WITHOUT LIMITATION THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE ARE +DISCLAIMED. THE PROVIDER DOES NOT WARRANT THAT THE LOADER IS UNINTERRUPTED +OR ERROR FREE, NOR THAT THE OPERATION OF THE LOADER WILL FUNCTION IN +CONJUNCTION WITH ANY OTHER PRODUCT. + + +5 LIMITATION OF LIABILITY + +5.1 IN NO EVENT WILL THE PROVIDER OF THE LOADER BE LIABLE TO THE USER OR ANY +PARTY FOR ANY DIRECT, INDIRECT, PUNITIVE, SPECIAL, INCIDENTAL OR OTHER +CONSEQUENTIAL DAMAGES ARISING DIRECTLY OR INDIRECTLY FROM THIS LICENCE +AGREEMENT OR ANY USE OF THE LOADER OR ENCODED FILES, EVEN IF THE PROVIDER IS +EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +5.2 THE LOADER IS PROVIDED ON AN "AS IS" BASIS. THE PROVIDER EXCLUDES ALL +WARRANTIES, CONDITIONS, TERMS, UNDERTAKINGS AND REPRESENTATIONS (EXCLUDING +FRAUDULENT MISREPRESENTATION) OF ANY KIND, EXPRESS OR IMPLIED, STATUTORY OR +OTHERWISE IN CONNECTION WITH THE LOADER TO THE FULLEST EXTENT PERMITTED BY +LAW. + +5.3 DOWNLOADING THE LOADER IS AT YOUR OWN RISK AND THE PROVIDER DOES NOT +ACCEPT LIABILITY FOR ANY DIRECT OR INDIRECT LOSS OR DAMAGE HOWSOEVER CAUSED AS +A RESULT OF ANY COMPUTER VIRUSES, BUGS, TROJAN HORSES, WORMS, SOFTWARE BOMBS +OR OTHER SIMILAR PROGRAMS ARISING FROM YOUR USE OF THE LOADER. WHILST THE +PROVIDER WILL DO ITS BEST TO ENSURE THAT THE LOADER IS FREE FROM SUCH +DESTRUCTIVE PROGRAMS, IT IS YOUR RESPONSIBILITY TO TAKE REASONABLE PRECAUTIONS +TO SCAN FOR SUCH DESTRUCTIVE PROGRAMS DOWNLOADED FROM THE INTERNET. + +5.4 THE PROVIDER'S MAXIMUM LIABILITY FOR ANY LOSS OR DAMAGE ARISING FROM THIS +LICENCE AGREEMENT SHALL IN ANY EVENT BE LIMITED IN THE SOLE DISCRETION OF THE +PROVIDER TO THE REPLACEMENT OF THE LOADER PRODUCT. + +5.5 DUE TO THE NATURE OF THE INTERNET, THE PROVIDER CANNOT GUARANTEE THAT ANY +E-MAILS OR OTHER ELECTRONIC TRANSMISSIONS WILL BE SENT TO YOU OR RECEIVED BY +THE PROVIDER OR THAT THE CONTENT OF SUCH TRANSMISSIONS WILL BE SECURE DURING +TRANSMISSION. + + +6 BUG FIXING AND PRODUCT SUPPORT + +6.1 The provider will use reasonable endeavours to provide support to users. +The provider will at their discretion only provide support for the latest +release. + +6.2 Support comprises of fault reporting via tickets and fault diagnosis, +recommendations on workarounds, and where reasonably possible a timely +resolution. + +6.3 The user accepts that on occasion the ability of the provider to meet +anticipated or published support schedules may be impaired due to, but without +limitation, Internet service provider failures or software failures that +affect the ability to communicate for an indeterminate period. + +6.4 The provider reserves the right to refuse to provide support at any time. + +6.5 The provider wishes to maintain and offer a product of the highest +possible quality, and accordingly may from time to time and at its discretion +make product changes for the purpose of correcting behaviour in variance to +the published specification or the user's reasonable expectations. + +6.6 The provider reserves the right to charge for support where the user does +not have a valid support plan in place, or where the support offered exceeds +the scope of the active support plan. + + +7 PRODUCT UPGRADES + +7.1 The provider may from time to time release product upgrades. These will +be provided free of charge and attempts made to provide a timely notification +to customers of the existence of any new release. + + +8 ERRORS AND OMISSIONS + +Whilst reasonable endeavours are made to ensure the accuracy of documentation +concerning the details of the Loader, the user accepts the possibility of +inaccuracies in information presented in any format, including email +communications and online services. The provider shall under no circumstances +be liable for any events that arise as a result of unintentional inaccuracies +or omissions. + + +9 USER INDEMNITY + +You agree to fully indemnify, defend and hold the provider harmless +immediately upon demand from and against all actions, liability, claims, +losses, damages, costs and expenses (including legal/attorney fees) incurred +by the provider arising directly or indirectly as a result of your breach of +this Licence Agreement. + + +10 INTELLECTUAL PROPERTY RIGHTS + +10.1 The user acknowledges that the Loader and associated documentation and +materials contain proprietary information of the provider and are and shall +remain the exclusive property of the provider and/or its licensors and all +title, copyright, trade marks, trade names, patents and other intellectual +property rights therein of whatever nature shall remain the sole property of +the provider and/or its licensors. + +10.2 No title to or rights of ownership, copyright or other intellectual +property in the Loader is transferred to the user (other than the licence +rights expressly granted in this Licence Agreement). + + +11 TERMINATION + +11.1 The provider reserves the right to terminate this Licence Agreement +immediately by notice in writing against the user if the user is in breach of +any terms and conditions of this Licence Agreement. + +11.2 Termination of this Licence Agreement for any reason shall be without +prejudice to any other rights or remedies of the provider which may have +arisen on or before the date of termination under this Licence Agreement or in +law. + +11.3 The provisions of the following clauses shall survive any termination of +this agreement; clause 3, 5, 10 and 13. + + +12 GENERAL + +12.1 The provider reserves the right to transfer or assign all or any of its +rights and duties and responsibilities set out in this Licence Agreement to +another party. + +12.2 Headings have been included for convenience only and will not be used in +construing any provision of this Licence Agreement. + +12.3 No delay or failure by the provider to exercise any powers, rights or +remedies under this Licence Agreement will operate as a waiver of them nor +will any single or partial exercise of any such powers, rights or remedies +include any other or further exercise of them. + +12.4 If any part of this Licence Agreement is found by a court of competent +jurisdiction or other competent authority to be invalid, unlawful or +unenforceable then such part shall be severed from the remainder of this +Licence Agreement which will continue to be valid and enforceable to the +fullest extent permitted by applicable law. + +12.5 This Licence Agreement including the documents or other sources referred +to herein supersede all prior representations, understandings and agreements +between the user and the provider relating to the Loader and sets forth the +entire agreement and understanding between the user and the provider relating +to the Loader. + +12.6 Nothing in this Licence Agreement shall be deemed to constitute a +partnership between you and the provider nor constitute either party being an +agent of the other party. + +12.7 This Agreement does not create any rights or benefits enforceable by any +person not a party to it (within the meaning of the U.K.Contracts (Rights of +Third Parties) Act 1999) except that a person who under clause 12.1 is a +permitted successor or assignee of the rights or benefits of the provider may +enforce such rights or benefits. + + +13 GOVERNING LAW AND JURISDICTION + +This License Agreement and any issues relating thereto shall be construed and +interpreted in accordance with the laws of England and subject to the +exclusive jurisdiction of the English courts. + +Copyright (c) 2002-2017 ionCube Ltd. Last revised 23-April-2015 diff --git a/src/deb/vesta/postinst b/src/deb/vesta/postinst index 9f8ee3e8..68252789 100755 --- a/src/deb/vesta/postinst +++ b/src/deb/vesta/postinst @@ -25,6 +25,76 @@ fi echo "1" > /usr/local/vesta/data/upgrades/show_changelog chmod a=rw /usr/local/vesta/data/upgrades/show_changelog +if ! grep -q "FILEMANAGER_KEY='FREEFM'" /usr/local/vesta/conf/vesta.conf; then + echo "== Adding FileManager license to vesta.conf" + echo "FILEMANAGER_KEY='FREEFM'" >> /usr/local/vesta/conf/vesta.conf +fi + +if [ -f "/root/.bash_profile" ]; then + if ! grep -q "v-cd-www" /root/.bash_profile; then + echo "== Adding v-cd-www alias to root bash profile" + echo "alias v-cd-www='source /usr/local/vesta/bin/v-change-dir-www'" >> /root/.bash_profile + fi +fi + +# Adding myVesta rules to SpamAssassin +if [ -d "/etc/spamassassin" ]; then + spamassassin_modified=0 + if [ ! -f "/etc/spamassassin/myvesta.cf" ]; then + touch /etc/spamassassin/myvesta.cf + fi + if ! grep -q 'RCVD_IN_RP_SAFE' /etc/spamassassin/myvesta.cf; then + echo "== Adding RCVD_IN_RP_ myVesta rules to SpamAssassin" + echo 'score RCVD_IN_RP_SAFE 0' >> /etc/spamassassin/myvesta.cf + echo 'score RCVD_IN_RP_CERTIFIED 0' >> /etc/spamassassin/myvesta.cf + spamassassin_modified=1 + fi + if ! grep -q 'SPF_FAIL' /etc/spamassassin/myvesta.cf; then + echo "== Adding SPF_FAIL myVesta rules to SpamAssassin" + cat <> /etc/spamassassin/myvesta.cf +score SPF_FAIL 3.0 +score SPF_SOFTFAIL 4.0 +score SPF_NONE 4.0 +EOF + spamassassin_modified=1 + fi + + if [ $spamassassin_modified -eq 1 ]; then + spamassassin_running=$(/usr/local/vesta/bin/v-list-sys-services | grep 'spamassassin\|spamd' | grep -c 'running') + if [ $spamassassin_running -eq 1 ]; then + echo "== Restarting SpamAssassin" + if [ "$release" -lt 12 ]; then + systemctl restart spamassassin.service + else + systemctl restart spamd.service + fi + fi + fi +fi + +# Adding ProFTPD to Fail2Ban +if [ -f "/etc/fail2ban/jail.local" ] && [ -f "/etc/proftpd/proftpd.conf" ]; then + if ! grep -q 'proftpd' /etc/fail2ban/jail.local; then + echo "== Adding ProFTPD to Fail2Ban" + cat <> /etc/fail2ban/jail.local + +[proftpd] +enabled = true +filter = proftpd +action = vesta[name=FTP] +port = ftp,ftp-data,ftps,ftps-data +logpath = %(proftpd_log)s +backend = %(proftpd_backend)s +maxretry = 5 +EOF + fail2ban_running=$(/usr/local/vesta/bin/v-list-sys-services | grep 'fail2ban' | grep -c 'running') + if [ $fail2ban_running -eq 1 ]; then + echo "== Restarting Fail2Ban" + systemctl restart fail2ban + fi + fi +fi + # Removing SpamHaus DNSBL if [ ! -f "/usr/local/vesta/data/upgrades/spamhaus_dnsbl_removed" ]; then sed -i '/zen.spamhaus.org/d' /etc/exim4/dnsbl.conf @@ -99,14 +169,18 @@ fi # Adding Barracuda RBL to SpamAssassin if [ ! -f "/usr/local/vesta/data/upgrades/barracuda_rbl" ]; then spamassassin_installed=$(/usr/local/vesta/bin/v-list-sys-services | grep -c 'spamassassin') - spamassassin_running=$(/usr/local/vesta/bin/v-list-sys-services | grep 'spamassassin' | grep -c 'running') + spamassassin_running=$(/usr/local/vesta/bin/v-list-sys-services | grep 'spamassassin\|spamd' | grep -c 'running') if [ $spamassassin_installed -eq 1 ]; then echo "== Adding Barracuda RBL to SpamAssassin" wget -nv -O /etc/spamassassin/barracuda.cf http://c.myvestacp.com/tools/spamassassin/barracuda.cf fi if [ $spamassassin_running -eq 1 ]; then echo "== Restarting SpamAssassin" - systemctl restart spamassassin + if [ "$release" -lt 12 ]; then + systemctl restart spamassassin.service + else + systemctl restart spamd.service + fi fi touch /usr/local/vesta/data/upgrades/barracuda_rbl fi @@ -163,7 +237,11 @@ if [ ! -f "/usr/local/vesta/data/upgrades/enable-tls-in-proftpd" ]; then echo "== Enabling TLS for ProFTPD FTPS" wget -nv https://c.myvestacp.com/debian/10/proftpd/tls.conf -O /etc/proftpd/tls.conf sed -i "s|AuthPAMConfig|Include /etc/proftpd/tls.conf\n\nAuthPAMConfig|g" /etc/proftpd/proftpd.conf - systemctl restart proftpd + proftpd_running=$(/usr/local/vesta/bin/v-list-sys-services | grep 'proftpd' | grep -c 'running') + if [ $proftpd_running -eq 1 ]; then + echo "== Restarting ProFTPD" + systemctl restart proftpd + fi fi fi fi diff --git a/web/edit/server/index.php b/web/edit/server/index.php index 49c577d8..eed4baab 100644 --- a/web/edit/server/index.php +++ b/web/edit/server/index.php @@ -339,7 +339,8 @@ if (!empty($_POST['save'])) { $v_backup_username = escapeshellarg($_POST['v_backup_username']); $v_backup_password = escapeshellarg($_POST['v_backup_password']); $v_backup_bpath = escapeshellarg($_POST['v_backup_bpath']); - exec (VESTA_CMD."v-add-backup-host ".$v_backup_type." ".$v_backup_host ." ".$v_backup_username." ".$v_backup_password." ".$v_backup_bpath, $output, $return_var); + $v_backup_port = escapeshellarg($_POST['v_backup_port']); + exec (VESTA_CMD."v-add-backup-host ".$v_backup_type." ".$v_backup_host ." ".$v_backup_username." ".$v_backup_password." ".$v_backup_bpath." ".$v_backup_port, $output, $return_var); check_return_code($return_var,$output); unset($output); if (empty($_SESSION['error_msg'])) $v_backup_host = $_POST['v_backup_host']; @@ -347,12 +348,12 @@ if (!empty($_POST['save'])) { if (empty($_SESSION['error_msg'])) $v_backup_username = $_POST['v_backup_username']; if (empty($_SESSION['error_msg'])) $v_backup_password = $_POST['v_backup_password']; if (empty($_SESSION['error_msg'])) $v_backup_bpath = $_POST['v_backup_bpath']; + if (empty($_SESSION['error_msg'])) $v_backup_port = $_POST['v_backup_port']; $v_backup_new = 'yes'; $v_backup_adv = 'yes'; $v_backup_remote_adv = 'yes'; } } - // Change remote backup host type if (empty($_SESSION['error_msg'])) { if ((!empty($_POST['v_backup_host'])) && ($_POST['v_backup_type'] != $v_backup_type)) { diff --git a/web/inc/main.php b/web/inc/main.php index 26df863e..f13e4142 100644 --- a/web/inc/main.php +++ b/web/inc/main.php @@ -38,8 +38,13 @@ if(!isset($_SESSION['user_combined_ip'])){ $_SESSION['user_combined_ip'] = $user_combined_ip; } +$SKIP_IP_CHECK = false; +if (isset($_SESSION['DISABLE_IP_CHECK']) && $_SESSION['DISABLE_IP_CHECK'] == 'yes') { + $SKIP_IP_CHECK = true; +} + // Checking user to use session from the same IP he has been logged in -if($_SESSION['user_combined_ip'] != $user_combined_ip && $_SERVER['REMOTE_ADDR'] != '127.0.0.1'){ +if ($_SESSION['user_combined_ip'] != $user_combined_ip && $_SERVER['REMOTE_ADDR'] != '127.0.0.1' && $SKIP_IP_CHECK==false) { session_destroy(); session_start(); $_SESSION['request_uri'] = $_SERVER['REQUEST_URI']; diff --git a/web/list/firewall/banlist/ip_info.php b/web/list/firewall/banlist/ip_info.php index cf7607bf..e7888a75 100644 --- a/web/list/firewall/banlist/ip_info.php +++ b/web/list/firewall/banlist/ip_info.php @@ -1,164 +1,164 @@ - 'http://lists.blocklist.de/lists/all.txt', - 'BFB' => 'http://danger.rulez.sk/projects/bruteforceblocker/blist.php', - 'CIARMY' => 'http://www.ciarmy.com/list/ci-badguys.txt', - 'GREENSNOW' => 'https://blocklist.greensnow.co/greensnow.txt', - 'SPAMDROP' => 'https://www.spamhaus.org/drop/drop.txt', - 'SPAMEDROP' => 'https://www.spamhaus.org/drop/edrop.txt', - 'TOR' => 'https://check.torproject.org/cgi-bin/TorBulkExitList.py', - ]; - $today = date('Y-m-d'); - - foreach ($lists as $code => $url) { - $cache_tag = 'ip-blacklist-' . $code . '-cache'; - - // init cache - if (!isset($_SESSION[$cache_tag])) $_SESSION[$cache_tag] = ['updated' => '', 'items' => [], 'http_code' => '']; - - // invalidate cache if clear_cache parameter is 1 - if (!empty($_REQUEST['clear_cache']) && $_REQUEST['clear_cache'] == 1) $_SESSION[$cache_tag]['updated'] = '2000-01-01'; - - // if cache is not updated, fetch new data and save to cache - if (strtotime($today) > strtotime($_SESSION[$cache_tag]['updated'])) { - $new_cache_data = fetchURL($url, $url_result); - if ($url_result['http_code'] == '200') $new_cache_items = parseCacheEntries($new_cache_data); - $_SESSION[$cache_tag] = ['updated' => $today, 'items' => $new_cache_items, 'http_code' => $url_result['http_code']]; - } - - // check ip - $matched_ips = array_filter($_SESSION[$cache_tag]['items'], function ($item) use ($ip) { - if (str_contains($item, '/')) return cidrMatch($ip, $item); - if ($ip == $item) return true; - return false; - }); - - $check_results[$code]['found'] = count($matched_ips) > 0 ? true : false; - $check_results[$code]['updated'] = $_SESSION[$cache_tag]['updated']; - $check_results[$code]['http_code'] = $_SESSION[$cache_tag]['http_code']; - } - - return $check_results; -} - -// Check token -if ((!isset($_REQUEST['token'])) || ($_SESSION['token'] != $_REQUEST['token'])) { - die("Wrong token"); -} - -$ip = $_REQUEST['ip']; - -// Validate IP format -if (filter_var($ip, FILTER_VALIDATE_IP) === false) { - die('GENERAL ERROR
BAD_IP_FORMAT'); -} - -// Query host -$host = gethostbyaddr($ip); - -// Query blocklists -$result_blocklists = ''; -$ip_check = checkIP($ip); -if ($ip_check) { - foreach ($ip_check as $list_code => $list_results) { - $result_blocklists .= '
'; - $result_blocklists .= $list_results['found'] ? '' : ''; - $result_blocklists .= ' '.$list_code.' '; - $result_blocklists .= $list_results['http_code'] == '200' ? '' : ''; - $result_blocklists .= '
'; - } -} - -// Query location -$url = 'https://api.db-ip.com/v2/free/'.$ip; -$result = fetchURL($url); -$result_array = json_decode($result, true); -if (!is_array($result_array)) { - die('GENERAL ERROR
BAD_JSON'); -} -if (!empty($result_array['errorCode'])) { - die('GENERAL ERROR
'.$result_array['errorCode']); -} - -// Output -echo " -
-
".__('Host')."
-
".$host."
-
".__('Banlist')."
-
".$result_blocklists."
-
".__('Continent')."
-
".$result_array['continentName']." [".$result_array['continentCode']."]
-
".__('Country')."
-
".$result_array['countryName']." [".$result_array['countryCode']."]
-
".__('State / Province')."
-
".$result_array['stateProv']." [".$result_array['stateProvCode']."]
-
".__('City / Locality')."
-
".$result_array['city']."
-
-"; + 'http://lists.blocklist.de/lists/all.txt', + 'BFB' => 'http://danger.rulez.sk/projects/bruteforceblocker/blist.php', + 'CIARMY' => 'http://www.ciarmy.com/list/ci-badguys.txt', + 'GREENSNOW' => 'https://blocklist.greensnow.co/greensnow.txt', + 'SPAMDROP' => 'https://www.spamhaus.org/drop/drop.txt', + 'SPAMEDROP' => 'https://www.spamhaus.org/drop/edrop.txt', + 'TOR' => 'https://check.torproject.org/cgi-bin/TorBulkExitList.py', + ]; + $today = date('Y-m-d'); + + foreach ($lists as $code => $url) { + $cache_tag = 'ip-blacklist-' . $code . '-cache'; + + // init cache + if (!isset($_SESSION[$cache_tag])) $_SESSION[$cache_tag] = ['updated' => '', 'items' => [], 'http_code' => '']; + + // invalidate cache if clear_cache parameter is 1 + if (!empty($_REQUEST['clear_cache']) && $_REQUEST['clear_cache'] == 1) $_SESSION[$cache_tag]['updated'] = '2000-01-01'; + + // if cache is not updated, fetch new data and save to cache + if (strtotime($today) > strtotime($_SESSION[$cache_tag]['updated'])) { + $new_cache_data = fetchURL($url, $url_result); + if ($url_result['http_code'] == '200') $new_cache_items = parseCacheEntries($new_cache_data); + $_SESSION[$cache_tag] = ['updated' => $today, 'items' => $new_cache_items, 'http_code' => $url_result['http_code']]; + } + + // check ip + $matched_ips = array_filter($_SESSION[$cache_tag]['items'], function ($item) use ($ip) { + if (str_contains($item, '/')) return cidrMatch($ip, $item); + if ($ip == $item) return true; + return false; + }); + + $check_results[$code]['found'] = count($matched_ips) > 0 ? true : false; + $check_results[$code]['updated'] = $_SESSION[$cache_tag]['updated']; + $check_results[$code]['http_code'] = $_SESSION[$cache_tag]['http_code']; + } + + return $check_results; +} + +// Check token +if ((!isset($_REQUEST['token'])) || ($_SESSION['token'] != $_REQUEST['token'])) { + die("Wrong token"); +} + +$ip = $_REQUEST['ip']; + +// Validate IP format +if (filter_var($ip, FILTER_VALIDATE_IP) === false) { + die('GENERAL ERROR
BAD_IP_FORMAT'); +} + +// Query host +$host = gethostbyaddr($ip); + +// Query blocklists +$result_blocklists = ''; +$ip_check = checkIP($ip); +if ($ip_check) { + foreach ($ip_check as $list_code => $list_results) { + $result_blocklists .= '
'; + $result_blocklists .= $list_results['found'] ? '' : ''; + $result_blocklists .= ' '.$list_code.' '; + $result_blocklists .= $list_results['http_code'] == '200' ? '' : ''; + $result_blocklists .= '
'; + } +} + +// Query location +$url = 'https://api.db-ip.com/v2/free/'.$ip; +$result = fetchURL($url); +$result_array = json_decode($result, true); +if (!is_array($result_array)) { + die('GENERAL ERROR
BAD_JSON'); +} +if (!empty($result_array['errorCode'])) { + die('GENERAL ERROR
'.$result_array['errorCode']); +} + +// Output +echo " +
+
".__('Host')."
+
".$host."
+
".__('Banlist')."
+
".$result_blocklists."
+
".__('Continent')."
+
".$result_array['continentName']." [".$result_array['continentCode']."]
+
".__('Country')."
+
".$result_array['countryName']." [".$result_array['countryCode']."]
+
".__('State / Province')."
+
".$result_array['stateProv']." [".$result_array['stateProvCode']."]
+
".__('City / Locality')."
+
".$result_array['city']."
+
+"; diff --git a/web/templates/admin/edit_server.html b/web/templates/admin/edit_server.html index b5da08de..888b081f 100644 --- a/web/templates/admin/edit_server.html +++ b/web/templates/admin/edit_server.html @@ -641,6 +641,17 @@

+ + + + + + + + "> +

+ + diff --git a/web/templates/file_manager/main.php b/web/templates/file_manager/main.php index 2e82f811..dd9095f7 100644 --- a/web/templates/file_manager/main.php +++ b/web/templates/file_manager/main.php @@ -19,6 +19,7 @@ +
©