diff --git a/action.sh b/action.sh index 3e7aa81..ada5eae 100644 --- a/action.sh +++ b/action.sh @@ -14,32 +14,9 @@ echo " " sleep 0.5 echo "- Upgrading Defenses 🛡️" -if ! ping -w 1 google.com &>/dev/null ; then - echo "- Failed to upgrade. Please check your internet connection." - sleep 2 - exit 1 -fi - -# Download the hosts file and save it as "hosts" -wget --no-check-certificate -O /sdcard/hosts1 https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts &>/dev/null || abort "Failed to download hosts file." -wget --no-check-certificate -O /sdcard/hosts2 https://raw.githubusercontent.com/hagezi/dns-blocklists/main/hosts/pro.plus-compressed.txt &>/dev/null || abort "Failed to download hosts file." -wget --no-check-certificate -O /sdcard/hosts3 https://o0.pages.dev/Pro/hosts.txt &>/dev/null || abort "Failed to download hosts file." -wget --no-check-certificate -O /sdcard/hosts4 https://raw.githubusercontent.com/r-a-y/mobile-hosts/master/AdguardDNS.txt &>/dev/null || abort "Failed to download hosts file." -wget --no-check-certificate -O /sdcard/hosts5 https://raw.githubusercontent.com/r-a-y/mobile-hosts/refs/heads/master/AdguardMobileAds.txt &>/dev/null || abort "Failed to download hosts file." -wget --no-check-certificate -O /sdcard/hosts6 https://raw.githubusercontent.com/r-a-y/mobile-hosts/refs/heads/master/AdguardMobileSpyware.txt &>/dev/null || abort "Failed to download hosts file." +sleep 0.2 echo "- Preparing New weapons 🔫" -for j_cole in /system/etc/hosts /sdcard/hosts1 /sdcard/hosts2 /sdcard/hosts3 /sdcard/hosts4 /sdcard/hosts5 /sdcard/hosts6; do - cat "$j_cole" - echo "" -done | grep -vE '^[[:space:]]*#' | grep -vE '^[[:space:]]*$' | sort | uniq > "$MODDIR/system/etc/hosts" +sh "$MODDIR/system/bin/rmlwk" --update-hosts || abort "- Failed to update hosts." -# let's see if the file was downloaded or not. -if [ ! -f "/sdcard/hosts6" ]; then - echo "- Looks like there is a problem with some weapons, check your internet connection and try again" -else - string="description=Status: Protection is enabled ✅ | protection update date: $(date)" - sed -i "s/^description=.*/$string/g" $MODDIR/module.prop - echo "- Everthing is fine now, Enjoy 😉" - rm /sdcard/hosts* -fi +echo "- Everthing is fine now, Enjoy 😉" diff --git a/common/install.sh b/common/install.sh index e61f39a..ba543ef 100644 --- a/common/install.sh +++ b/common/install.sh @@ -32,33 +32,32 @@ ui_print " │░▀░▀░▀▀▀░░░░░▀░▀░▀░▀░▀▀▀░▀░▀░▀░▀░▀▀▀░▀░▀│ ╚────────────────────────────────────────╝" ui_print " Welcome to Re-Malwack installation wizard!" -sleep 0.5 +sleep 0.2 ui_print "" ui_print " ----------------------------------" ui_print " \ " ui_print "" -sleep 0.5 +sleep 0.2 ui_print "- ⚙ Module Version: $(grep_prop version $TMPDIR/module.prop)" -sleep 0.5 +sleep 0.2 ui_print "- 📱 Device Brand: $(getprop ro.product.brand)" -sleep 0.5 +sleep 0.2 ui_print "- 📱 Device Model: $(getprop ro.product.model)" -sleep 0.5 +sleep 0.2 ui_print "- 🤖 Android Version: $(getprop ro.build.version.release)" -sleep 0.5 +sleep 0.2 ui_print "- ⚙ Device Arch: $(getprop ro.product.cpu.abi)" -sleep 0.5 +sleep 0.2 ui_print "- 🛠 Kernel version: $(uname -r)" -sleep 0.5 +sleep 0.2 ui_print "- ⌛ Current Time: $(date "+%d, %b - %H:%M %Z")" ui_print "" -sleep 0.5 +sleep 0.2 ui_print " /" ui_print " ----------------------------------" ui_print " " -sleep 1 ui_print "[INSTALLATION BEGINS]" -sleep 1 +sleep 0.2 # rcm lore. if ! $BOOTMODE; then @@ -84,39 +83,21 @@ fi # check for conflicts ui_print "- Checking for conflicts" -tempFileToStoreConflicts=$( - if touch /data/local/tmp/tempFile; then - echo "/data/local/tmp/tempFile" - else - echo "/sdcard/tempFile" - fi -) +pm list packages | grep -q org.adaway && abort "- Adaway is detected, Please disable to prevent conflicts." -pm list packages | sed 's/package://' | grep -q org.adaway && abort "- Adaway is detected, Please disable to prevent conflicts." +for module in /data/adb/modules/*; do + module_id="$(grep_prop id ${module}/module.prop)" + # Skip our own module + [ "$module_id" == "Re-Malwack" ] && continue -for i in /data/adb/modules/*; do - # Skip this instance if we are in our own module directory - if [ "$(grep_prop id ${i}/module.prop)" == "Re-Malwack" ]; then - continue - fi # Check for conflict by looking for a hosts file in the module - if [ -f "${i}/system/etc/hosts" ]; then - modules_count=$(($modules_count + 1)) - # Save both the name and ID to the temp file (name|id format) - echo "$(grep_prop name ${i}/module.prop)|$(grep_prop id ${i}/module.prop)" >> $tempFileToStoreConflicts + if [ -f "${module}/system/etc/hosts" ]; then + module_name="$(grep_prop name ${module}/module.prop)" + ui_print "- Disabling conflicting module: $module_name" + touch "/data/adb/modules/$module_id/disable" fi done -if [ "$modules_count" -ge "1" ]; then - echo "- Notice: The following modules will be disabled to prevent conflicts:" - while IFS='|' read -r moduleName moduleID; do - echo "- $moduleName" - # Create the disable file in the corresponding module directory - touch "/data/adb/modules/$moduleID/disable" - done < $tempFileToStoreConflicts -fi - - # make an bool to prevent extracting things if we dont have anything to extract... if [ "$DO_WE_HAVE_ANYTHING_TO_EXTRACT" == "true" ]; then unzip -o "$ZIPFILE" -x 'META-INF/*' -d $MODPATH >&2 @@ -124,43 +105,45 @@ fi # let's check do we have internet or not. ui_print "- Checking internet connection" -ping -w 2 google.com &>/dev/null || abort "- This module requires internet connection to download protections." +ping -c 1 -w 5 google.com &>/dev/null || abort "- This module requires internet connection to download protections." # Download hosts files ui_print "- Preparing Shields 🛡️" +mkdir -p $MODPATH/system/etc counter=1 -echo "$hostsFileURL" | while read -r url; do - # Skip empty lines - [ -n "$url" ] || continue - - # Download using wget - wget --no-check-certificate -O "hosts${counter}" "$url" &>/dev/null || { - abort "- Failed to download hosts file from $url" - } - counter=$((counter + 1)) +pids="" +while read -r url; do + if [ -n "$url" ]; then + wget --no-check-certificate -O "hosts${counter}" "$url" &>/dev/null & + pids="$pids $!" + counter=$((counter + 1)) + fi +done < <(echo "$hostsFileURL") + +# Wait for all downloads to complete +for pid in $pids; do + wait $pid || abort "- Download failed. Please check your internet connection and try again." +done + +# Check if all files were downloaded successfully +for i in $(seq 1 $((counter-1))); do + if [ ! -f "hosts${i}" ]; then + abort "- Download failed. Please check your internet connection and try again." + fi done -# Merge files into a single hosts file -mkdir -p $MODPATH/system/etc ui_print "- Preparing weapons to kill malware 🔫" -{ - for file in /system/etc/hosts hosts1 hosts2 hosts3 hosts4 hosts5 hosts6 ; do - [ -f "$file" ] && cat "$file" - echo "" - done -} | grep -vE '^[[:space:]]*#' | grep -vE '^[[:space:]]*$' | sort | uniq > $MODPATH/system/etc/hosts - -# let's see if the file was downloaded or not. -if [ ! -f "hosts6" ]; then - abort "- Looks like there is a problem with some weapons, maybe check your internet connection?" -else - ui_print "- Your device is now armed against ads, malware and more 🛡" - sleep 0.5 +cat /system/etc/hosts hosts* 2>/dev/null | sed -e '/^[[:space:]]*#/d' -e '/^[[:space:]]*$/d' -e 's/^[[:space:]]*//g' | sort -u > $MODPATH/system/etc/hosts +ui_print "- Your device is now armed against ads, malware and more 🛡" + +# Add a persistent directory to save configuration +if [ ! -f "/data/adb/Re-Malwack/config.sh" ]; then + mkdir /data/adb/Re-Malwack + echo -e "block_porn=0\nblock_gambling=0\nblock_fakenews=0" > "/data/adb/Re-Malwack/config.sh" fi -# set perms +# set permissions chmod 644 $MODPATH/system/etc/hosts chmod 755 $MODPATH/system/bin/rmlwk chmod 755 $MODPATH/action.sh -# cleanup -rm -rf $tempFileToStoreConflicts +chmod 755 "/data/adb/Re-Malwack/config.sh" diff --git a/service.sh b/service.sh index 2930da5..e493013 100644 --- a/service.sh +++ b/service.sh @@ -3,20 +3,13 @@ # Variables MODDIR="/data/adb/modules/Re-Malwack" HOSTS_FILE="/system/etc/hosts" - -while true; do - # Current timestamp - string="description=Status: Protection is enabled ✅ | Protection update date: $(date)" - - # Check if hosts file contains blocked entries - if grep -q '0.0.0.0' "$HOSTS_FILE"; then - # Update the module description - sed -i "s/^description=.*/$string/g" "$MODDIR/module.prop" - else - # Update the module description if no entries are blocked - sed -i "s/^description=.*/description=Status: disabled due to no blocked entries ❌/g" "$MODDIR/module.prop" - fi - - # Wait for 5 minutes before the next refresh - sleep 300 -done +string="description=Status: Protection is enabled ✅ | Protection update date: $(date)" + +# Check if hosts file contains blocked entries +if grep -q '0.0.0.0' "$HOSTS_FILE"; then + # Update the module description + sed -i "s/^description=.*/$string/g" "$MODDIR/module.prop" +else + # Update the module description if no entries are blocked + sed -i "s/^description=.*/description=Status: disabled due to no blocked entries ❌/g" "$MODDIR/module.prop" +fi \ No newline at end of file diff --git a/system/bin/rmlwk b/system/bin/rmlwk index 3a2d07d..e765091 100644 --- a/system/bin/rmlwk +++ b/system/bin/rmlwk @@ -30,13 +30,101 @@ function malvack_banner() { echo -e "\033[0;37m ╚────────────────────────────────────────╝\033[0m" } +# Variables +persist_dir="/data/adb/Re-Malwack" +temp=$(mktemp) +MODDIR="/data/adb/modules/Re-Malwack" +hosts_file="$MODDIR/system/etc/hosts" +tmp_hosts="/data/local/tmp/hosts" +# tmp_hosts 0 = original hosts file, to prevent overwrite before cat process complete, ensure coexisting of different block type. +# tmp_hosts 1-9 = downloaded hosts, to simplify process of install and remove function. + +# Read config +. "$persist_dir/config.sh" + +# Skip banner if running from Magisk Manager +[ -z "$MAGISKTMP" ] && malvack_banner + function install_hosts() { - # Merging hosts with removing commented lines and whitespaces, along with removing duplicated entries - cat "${downloaded_hosts[@]}" "$hosts_file" | grep -vE '^[[:space:]]*#' | grep -vE '^[[:space:]]*$' | sort | uniq > "$hosts_file" - # Delete downloaded hosts files after merging - for file in "${downloaded_hosts[@]}"; do - [ -f "$file" ] && rm -f "$file" - done + # Prepare original hosts + cp -f "$hosts_file" "${tmp_hosts}0" + + # Prepare blacklist + [ -s "$persist_dir/blacklist.txt" ] && sed '/^[[:space:]]*#/d; /^[[:space:]]*$/d' "$persist_dir/blacklist.txt" | awk '{print "0.0.0.0 " $0}' > "${tmp_hosts}b" + + # Update hosts + sed '/^[[:space:]]*#/d; /^[[:space:]]*$/d; s/^[[:space:]]*//; s/\t/ /g; s/ */ /g' "${tmp_hosts}"[!0] > "$tmp_hosts" + sort -u "${tmp_hosts}0" "$tmp_hosts" > "$hosts_file" + + # Process whitelist + if [ -s "$persist_dir/whitelist.txt" ]; then + whitelist=$(cat "$persist_dir/cache/whitelist/whitelist.txt" "$persist_dir/whitelist.txt") + elif [ -s "$persist_dir/cache/whitelist/whitelist.txt" ]; then + whitelist=$(cat "$persist_dir/cache/whitelist/whitelist.txt") + fi + + # Filter whitelist + if [ -n "$whitelist" ]; then + echo "$whitelist" | sed '/^[[:space:]]*#/d; /^[[:space:]]*$/d' | awk '{print "0.0.0.0 " $0}' > "${tmp_hosts}w" + awk 'NR==FNR {seen[$0]=1; next} !seen[$0]' "${tmp_hosts}w" "$hosts_file" > "$tmp_hosts" + cat "$tmp_hosts" > "$hosts_file" + fi + + # Update config + [ -n "$block_type" ] && sed -i "s/^block_${block_type}=.*/block_${block_type}=1/" /data/adb/Re-Malwack/config.sh + + # Clean up + rm -f "${tmp_hosts}"* 2>/dev/null +} + +function remove_hosts() { + # Prepare original hosts + cp -f "$hosts_file" "${tmp_hosts}0" + + # Arrange cached hosts + sed '/^[[:space:]]*#/d; /^[[:space:]]*$/d; s/^[[:space:]]*//; s/\t/ /g; s/ */ /g' "${cache_hosts}"* | sort -u > "${tmp_hosts}1" + + # Remove from hosts file + awk 'NR==FNR {seen[$0]=1; next} !seen[$0]' "${tmp_hosts}1" "${tmp_hosts}0" > "$hosts_file" + + # Restore to default entires if hosts file is empty + if [ ! -s "$hosts_file" ]; then + echo "- Warning: Hosts file is empty. Restoring default entries." + echo -e "127.0.0.1 localhost\n::1 localhost" > "$hosts_file" + fi + + # Update config + sed -i "s/^block_${block_type}=.*/block_${block_type}=0/" /data/adb/Re-Malwack/config.sh + + # Clean up + rm -f "${tmp_hosts}"* 2>/dev/null +} + +function block_content() { + local block_type=$1 + local status=$2 + cache_hosts="$persist_dir/cache/$block_type/hosts" + + if [ "$status" = 0 ] && [ -f "${cache_hosts}1" ]; then + remove_hosts + else + # Download hosts only if no cached host found or during update + nuke_if_we_dont_have_internet + if [ ! -f "${cache_hosts}1" ] || [ "$status" = "update" ]; then + mkdir -p "$persist_dir/cache/$block_type" + fetch "${cache_hosts}1" https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/${block_type}-only/hosts &>/dev/null + if [ "$block_type" = "porn" ]; then + fetch "${cache_hosts}2" https://raw.githubusercontent.com/johnlouie09/Anti-Porn-HOSTS-File/refs/heads/master/HOSTS.txt &>/dev/null & + fetch "${cache_hosts}3" https://www.someonewhocares.org/hosts/hosts &>/dev/null & + wait + fi + fi + + # Skip install for if called from hosts update + [ "$status" = "update" ] && return 0 + cp -f "${cache_hosts}"* "/data/local/tmp" + [ "$status" = 0 ] && remove_hosts || install_hosts + fi } function tolower() { @@ -50,8 +138,7 @@ function abort() { } function nuke_if_we_dont_have_internet() { - ping -w 1 google.com >/dev/null 2>&1 - return $? + ping -c 1 -w 5 raw.githubusercontent.com &>/dev/null || abort "- Please check your internet connection and try again." } function ask() { @@ -59,7 +146,7 @@ function ask() { local answer printf "- $question (y/n): " read -r answer - if [[ "$(tolower "$answer")" == "y" ]]; then + if [ "$(tolower "$answer")" = "y" ]; then return 0 else return 1 @@ -67,136 +154,160 @@ function ask() { } # Fallback to busybox wget if curl binary is not available -fetch() { +function fetch() { PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:/data/data/com.termux/files/usr/bin:$PATH if command -v curl >/dev/null 2>&1; then - curl -o "$@" || abort "Failed to download hosts file." + curl -o "$@" || abort "Failed to download $2." else - busybox wget --no-check-certificate -O - "$@" || abort "Failed to download hosts file." + busybox wget --no-check-certificate -O - "$@" || abort "Failed to download $2." fi } -# Variables -domain="$2" -temp=$(mktemp) -hosts_file="/data/adb/modules/Re-Malwack/system/etc/hosts" -MODDIR="/data/adb/modules/Re-Malwack" - -# Banner -malvack_banner +function update_status() { + if grep -q '0.0.0.0' "$hosts_file"; then + string="description=Status: Protection is enabled ✅ | Last updated: $(date)" + else + string="description=Status: Protection is disabled due to reset ❌" + fi + sed -i "s/^description=.*/$string/g" $MODDIR/module.prop +} # Check Root if [ "$(id -u)" -ne 0 ]; then abort "Root is required to run this script." fi - # Main Logic case "$(tolower "$1")" in --reset) echo "- Reverting the changes..." echo "127.0.0.1 localhost\n::1 localhost" > "$hosts_file" chmod 644 "$hosts_file" - string="description=Status: Protection is disabled due to reset ❌" - sed -i "s/^description=.*/$string/g" $MODDIR/module.prop + update_status echo "- Successfully reverted changes." ;; - --block-gambling|--block-fakenews) - block_type=${1#--block-} - if ! nuke_if_we_dont_have_internet; then - abort "Internet connection is required to proceed. Please check your connection." + --block-porn|--block-gambling|--block-fakenews) + local block_type=${1#--block-} + local status=$2 + eval "block_toggle=\"\$block_${block_type}\"" + + if [ "$status" = "disable" ] || [ "$status" = 0 ]; then + if [ "$block_toggle" = 0 ]; then + echo "- $block_type block is already disabled" + else + echo "- Removing block entries for ${block_type} sites." + block_content "$block_type" 0 + echo "- Unblocked ${block_type} sites successfully." + fi + else + if [ "$block_toggle" = 1 ]; then + echo "- $block_type block is already enabled" + else + echo "- Adding block entries for ${block_type} sites." + block_content "$block_type" 1 + echo "- Blocked ${block_type} sites successfully." + fi fi - echo "- Downloading entries for ${block_type}." - fetch /data/local/tmp/hosts https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/${block_type}-only/hosts &>/dev/null - echo "- Applying entries..." - cat /data/local/tmp/hosts "$hosts_file" | grep -vE '^[[:space:]]*#' | grep -vE '^[[:space:]]*$' | sort | uniq > "$hosts_file" - rm /data/local/tmp/hosts - echo "- Entries for blocking ${block_type} sites are added successfully." - ;; - --block-porn) - block_type=${1#--block-} - if ! nuke_if_we_dont_have_internet; then - abort "Internet connection is required to proceed. Please check your connection." - fi - echo "- Downloading entries for porn block" - fetch /data/local/tmp/hosts1 https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/${block_type}-only/hosts &>/dev/null - fetch /data/local/tmp/hosts2 https://raw.githubusercontent.com/johnlouie09/Anti-Porn-HOSTS-File/refs/heads/master/HOSTS.txt &>/dev/null - fetch /data/local/tmp/hosts3 https://www.someonewhocares.org/hosts/hosts &>/dev/null - echo "- Applying entries..." - # Variables for downloaded files - downloaded_hosts=( - /data/local/tmp/hosts1 - /data/local/tmp/hosts2 - /data/local/tmp/hosts3 - ) - # Merge downloaded hosts files into the main hosts file - install_hosts - echo "- Entries for blocking porn sites are added successfully." + update_status ;; --whitelist) - [[ -z "$domain" ]] && abort "Please provide a domain to whitelist." - # Check if the domain exists in the hosts file - if grep -q "0\.0\.0\.0 $domain" "$hosts_file"; then - # Remove the line containing the domain - if sed -i "/0\.0\.0\.0 $domain/d" "$hosts_file"; then - echo "- Whitelisted $domain." + local option="$2" + local domain="$3" + + if [ "$option" != "add" ] && [ "$option" != "remove" ] || [ -z "$domain" ]; then + echo "usage: rmlwk --whitelist " + display_whitelist=$(cat "$persist_dir/whitelist.txt" 2>/dev/null) + [ ! -z "$display_whitelist" ] && echo "Current whitelist: $display_whitelist" || echo "Current whitelist: no saved whitelist" else - abort "Error: Failed to whitelist $domain. Please check the hosts file and permissions." + touch "$persist_dir/whitelist.txt" + if [ "$option" = "add" ]; then + # Add domain to whitelist.txt and remove from hosts + grep -qx "$domain" "$persist_dir/whitelist.txt" && echo "$domain is already whitelisted" || echo "$domain" >> "$persist_dir/whitelist.txt" + sed -i "/0\.0\.0\.0 $domain/d" "$hosts_file" 2>/dev/null + else + # Remove domain from whitelist.txt if found + if grep -qxF "$domain" "$persist_dir/whitelist.txt"; then + sed -i "/^$(printf '%s' "$domain" | sed 's/[]\/$*.^|[]/\\&/g')$/d" "$persist_dir/whitelist.txt"; + echo "- $domain removed from whitelist." + else + echo "- $domain isn't in whitelist." + fi + fi fi - else - echo "- Domain $domain is not in the hosts file, nothing to whitelist." - exit 1 - fi - ;; + ;; --blacklist) - [[ -z "$domain" ]] && abort "Please provide a domain to blacklist." - # Check if the domain is already blocked - if grep -q "0\.0\.0\.0 $domain" "$hosts_file"; then - echo "- Domain $domain is already blocked." - exit 1 - else - echo "0.0.0.0 $domain" >> "$hosts_file" && echo "- Blacklisted $domain." - # [[ $? -ne 0 ]] && abort "Error: Failed to blacklist $domain. Please check the hosts file and permissions." - fi - ;; + local option="$2" + local domain="$3" + + if [ "$option" != "add" ] && [ "$option" != "remove" ] || [ -z "$domain" ]; then + echo "usage: rmlwk --blacklist " + display_blacklist=$(cat "$persist_dir/blacklist.txt" 2>/dev/null) + [ ! -z "$display_blacklist" ] && echo "Current blacklist: $display_blacklist" || echo "Current blacklist: no saved blacklist" + else + touch "$persist_dir/blacklist.txt" + if [ "$option" = "add" ]; then + # Add domain to blacklist.txt and add to hosts if it isn't there + grep -qx "$domain" "$persist_dir/blacklist.txt" || echo "$domain" >> "$persist_dir/blacklist.txt" + if grep -q "0\.0\.0\.0 $domain" "$hosts_file"; then + echo "- $domain is already blacklisted." + else + echo "0.0.0.0 $domain" >> "$hosts_file" && echo "- Blacklisted $domain." + update_status + fi + else + # Remove domain from blacklist.txt if found + if grep -qxF "$domain" "$persist_dir/blacklist.txt"; then + sed -i "/^$(printf '%s' "$domain" | sed 's/[]\/$*.^|[]/\\&/g')$/d" "$persist_dir/blacklist.txt"; + echo "- $domain removed from blacklist." + else + echo "- $domain isn't in blacklist." + fi + fi + fi + ;; --update-hosts) - if ! nuke_if_we_dont_have_internet; then - abort "Internet connection is required to proceed. Please check your connection." - fi echo "- Downloading updates, Please wait." - fetch /data/local/tmp/hosts1 https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts &>/dev/null - fetch /data/local/tmp/hosts2 https://raw.githubusercontent.com/hagezi/dns-blocklists/main/hosts/pro.plus-compressed.txt &>/dev/null - fetch /data/local/tmp/hosts3 https://o0.pages.dev/Pro/hosts.txt &>/dev/null - fetch /data/local/tmp/hosts4 https://raw.githubusercontent.com/r-a-y/mobile-hosts/master/AdguardDNS.txt &>/dev/null - fetch /data/local/tmp/hosts5 https://raw.githubusercontent.com/r-a-y/mobile-hosts/refs/heads/master/AdguardMobileAds.txt &>/dev/null - fetch /data/local/tmp/hosts6 https://raw.githubusercontent.com/r-a-y/mobile-hosts/refs/heads/master/AdguardMobileSpyware.txt &>/dev/null + nuke_if_we_dont_have_internet + + # Update Re-Malwack general hosts + fetch "${tmp_hosts}1" https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts &>/dev/null & + fetch "${tmp_hosts}2" https://raw.githubusercontent.com/hagezi/dns-blocklists/main/hosts/pro.plus-compressed.txt &>/dev/null & + fetch "${tmp_hosts}3" https://o0.pages.dev/Pro/hosts.txt &>/dev/null & + fetch "${tmp_hosts}4" https://raw.githubusercontent.com/r-a-y/mobile-hosts/master/AdguardDNS.txt &>/dev/null & + fetch "${tmp_hosts}5" https://raw.githubusercontent.com/r-a-y/mobile-hosts/refs/heads/master/AdguardMobileAds.txt &>/dev/null & + fetch "${tmp_hosts}6" https://raw.githubusercontent.com/r-a-y/mobile-hosts/refs/heads/master/AdguardMobileSpyware.txt &>/dev/null & + + # Update hosts for global whitelist + mkdir -p "$persist_dir/cache/whitelist" + fetch "$persist_dir/cache/whitelist/whitelist.txt" https://raw.githubusercontent.com/ZG089/Re-Malwack/main/whitelist.txt &>/dev/null & + + # Update hosts for custom block + [ -d "$persist_dir/cache/porn" ] && block_content "porn" "update" & + [ -d "$persist_dir/cache/gambling" ] && block_content "gambling" "update" & + [ -d "$persist_dir/cache/fakenews" ] && block_content "fakenews" "update" & + wait + echo "- Applying update." - # Variables for downloaded files - downloaded_hosts=( - /data/local/tmp/hosts1 - /data/local/tmp/hosts2 - /data/local/tmp/hosts3 - /data/local/tmp/hosts4 - /data/local/tmp/hosts5 - /data/local/tmp/hosts6 - ) - # Merge downloaded hosts files into the main hosts file install_hosts - string="description=Status: Protection is enabled ✅ | protection update date: $(date)" - sed -i "s/^description=.*/$string/g" $MODDIR/module.prop + + # Check config and apply update + [ "$block_porn" = 1 ] && block_content "porn" + [ "$block_gambling" = 1 ] && block_content "gambling" + [ "$block_fakenews" = 1 ] && block_content "fakenews" + update_status echo "- Done." ;; --help|-h|*) echo "" echo "Usage: su -c rmlwk [--argument]" echo "--reset: Restore original hosts file." - echo "--block-porn: Block pornographic sites." - echo "--block-gambling: Block gambling sites." - echo "--block-fakenews: Block fake news sites." - echo "--whitelist : Whitelist a domain." - echo "--blacklist : Blacklist a domain." + echo "--block-porn : Block pornographic sites, use disable to unblock." + echo "--block-gambling : Block gambling sites, use disable to unblock." + echo "--block-fakenews : Block fake news sites, use disable to unblock." + echo "--whitelist : Whitelist a domain." + echo "--blacklist : Blacklist a domain." echo "--update-hosts: Update the hosts file." echo "--help, -h: Display help." - echo -e "\033[0;31m Example command: su -c rmlwk --update-hosts" + echo -e "\033[0;31m Example command: su -c rmlwk --update-hosts\033[0m" ;; -esac \ No newline at end of file +esac diff --git a/webroot/assets/logo-red.svg b/webroot/assets/logo-red.svg new file mode 100644 index 0000000..140c9f0 --- /dev/null +++ b/webroot/assets/logo-red.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/webroot/index.html b/webroot/index.html index 47b5385..4552515 100644 --- a/webroot/index.html +++ b/webroot/index.html @@ -1,144 +1,176 @@ - - - Re-Malwack - - - + + + Re-Malwack + + + -
-
- - Re-Malwack - - - -

- Initializing... - -

+
+ +
+ + Re-Malwack + + + +

+ Initializing... + +

+ +
-
-
- -
- -

Re-Malwack

-

by ZG089
WebUI by KOWX712

-
-

-

-

-

Credits

-
-

@person0z - Malwack Magisk module creator

-

@topjohnwu - Magisk Founder

-

@Zackptg5 - MMTE Template

-

@Hagezi - Hosts file

-

@hBlock - Hosts file

-

@StevenBlack - Fake news & gambling sites blocklist

-

@GalaxyA14user - Fixing bugs + Contribution to the Re-Malwack project

-

@forsaken-heart24 - Contribution to the Re-Malwack Project

-

@KOWX712 - WebUI + Fixing bugs

-

And Finally, YOU! For using my module :)

-
-
-
-
+ + +
+
+ + + +
    Update hosts file
+
+
+ + +
+
+ + + +
    Restore original hosts file
+
+
+ + +
+
+ + + +
    Block pornography sites
+ +
+
+ + +
+
+ + + +
    Block gambling sites
+ +
+
+ + +
+
+ + + +
    Block fake news sites
+ +
+
+ + +
+

Whitelist

+
+ + +
+
    +
    + + +
    +

    Blacklist

    +
    + + +
    +
      +
      +
      + + +
      +
      + +
      + +

      Re-Malwack

      +

      by ZG089
      WebUI by KOWX712

      +
      +

      +

      +

      +

      Credits

      +
      +

      @person0z - Malwack Magisk module creator

      +

      @topjohnwu - Magisk Founder

      +

      @Zackptg5 - MMTE Template

      +

      @Hagezi - Hosts file

      +

      @hBlock - Hosts file

      +

      @StevenBlack - Fake news & gambling sites blocklist

      +

      @GalaxyA14user - Fixing bugs + Contribution to the Re-Malwack project

      +

      @forsaken-heart24 - Contribution to the Re-Malwack Project

      +

      @KOWX712 - WebUI + Fixing bugs

      +

      And Finally, YOU! For using my module :)

      +
      +
      +
      +
      -
      +
      - + diff --git a/webroot/index.js b/webroot/index.js index be2c079..ce18a80 100644 --- a/webroot/index.js +++ b/webroot/index.js @@ -6,6 +6,16 @@ const telegramLink = document.getElementById('telegram'); const githubLink = document.getElementById('github'); const xdaLink = document.getElementById('xda'); const sponsorLink = document.getElementById('sponsor'); +const blockPornToggle = document.getElementById('block-porn-toggle'); +const blockGamblingToggle = document.getElementById('block-gambling-toggle'); +const blockFakenewsToggle = document.getElementById('block-fakenews-toggle'); + +const basePath = "/data/adb/Re-Malwack"; + +const filePaths = { + blacklist: `${basePath}/blacklist.txt`, + whitelist: `${basePath}/whitelist.txt`, +}; // Link redirect const links = [ @@ -15,6 +25,12 @@ const links = [ { element: sponsorLink, url: 'https://buymeacoffee.com/zg089', name: 'Sponsor' } ]; +// Ripple effect configuration +const rippleClasses = ['.ripple-container', '.link-icon']; + +let isScrolling = false; +let modeActive = false; + // Function to handle about menu function aboutMenu() { const aboutOverlay = document.getElementById('about-overlay'); @@ -71,10 +87,43 @@ async function getStatus() { } } +// Function to check block porn sites status +async function blockPornStatus() { + try { + const result = await execCommand("su -c 'grep -q '^block_porn=1' /data/adb/Re-Malwack/config.sh'"); + blockPornToggle.checked = !result; + } catch (error) { + blockPornToggle.checked = false; + console.error('Error checking block porn status:', error); + } +} + +// Function to check block gambling sites status +async function blockGamblingStatus() { + try { + const result = await execCommand("su -c 'grep -q '^block_gambling=1' /data/adb/Re-Malwack/config.sh'"); + blockGamblingToggle.checked = !result; + } catch (error) { + blockGamblingToggle.checked = false; + console.error('Error checking block gambling status:', error); + } +} + +// Function to check block fakenews sites status +async function blockFakenewsStatus() { + try { + const result = await execCommand("su -c 'grep -q '^block_fakenews=1' /data/adb/Re-Malwack/config.sh'"); + blockFakenewsToggle.checked = !result; + } catch (error) { + blockFakenewsToggle.checked = false; + console.error('Error checking block fakenews status:', error); + } +} + // Function to handle peform script and output async function performAction(promptMessage, commandOption, errorPrompt, errorMessage) { try { - showPrompt(promptMessage); + showPrompt(promptMessage, true, 50000); await new Promise(resolve => setTimeout(resolve, 300)); const command = `su -c '/data/adb/modules/Re-Malwack/system/bin/rmlwk ${commandOption}'`; const output = await execCommand(command); @@ -101,21 +150,51 @@ async function resetHostsFile() { // Function to block pornography sites async function blockPorn() { - await performAction("- Downloading entries for porn block...", "--block-porn", "- Failed to download porn block hosts", "Failed to download porn block hosts:"); + let prompt_message; + let action; + if (blockPornToggle.checked) { + prompt_message = "- Removing entries..."; + action = "--block-porn 0"; + } else { + prompt_message = "- Applying block for porn sites..."; + action = "--block-porn"; + } + await performAction(prompt_message, action, "- Failed to apply block for porn sites", "Failed to apply block for porn sites:"); + blockPornStatus(); } // Function to block gambling sites async function blockGambling() { - await performAction("- Downloading entries for gambling block...", "--block-gambling", "- Failed to download gambling block hosts", "Failed to download gambling block hosts:"); + let prompt_message; + let action; + if (blockGamblingToggle.checked) { + prompt_message = "- Removing entries..."; + action = "--block-gambling 0"; + } else { + prompt_message = "- Applying block for gambling sites..."; + action = "--block-gambling"; + } + await performAction(prompt_message, action, "- Failed to apply block for gambling sites", "Failed to apply block for gambling sites:"); + blockGamblingStatus(); } // Function to block fake news sites async function blockFakeNews() { - await performAction("- Downloading entries for fake news block...", "--block-fakenews", "- Failed to download fake news block hosts", "Failed to download fake news block hosts:"); + let prompt_message; + let action; + if (blockFakenewsToggle.checked) { + prompt_message = "- Removing entries..."; + action = "--block-fakenews 0"; + } else { + prompt_message = "- Applying block for fake news sites..."; + action = "--block-fakenews"; + } + await performAction(prompt_message, action, "- Failed to apply block for fake news sites", "Failed to apply block for fake news sites:"); + blockFakenewsStatus(); } // Function to show prompt -function showPrompt(message, isSuccess = true) { +function showPrompt(message, isSuccess = true, duration = 2000) { const prompt = document.getElementById('prompt'); prompt.textContent = message; prompt.classList.toggle('error', !isSuccess); @@ -125,11 +204,10 @@ function showPrompt(message, isSuccess = true) { setTimeout(() => { prompt.classList.add('visible'); prompt.classList.remove('hidden'); - const timeoutDuration = message.includes('Downloading') ? 20000 : 3000; window.promptTimeout = setTimeout(() => { prompt.classList.remove('visible'); prompt.classList.add('hidden'); - }, timeoutDuration); + }, duration); }, 100); } @@ -156,10 +234,11 @@ async function handleAdd(fileType) { return; } try { - await execCommand(`su -c '/data/adb/modules/Re-Malwack/system/bin/rmlwk --${fileType} ${inputValue}'`); + await execCommand(`su -c '/data/adb/modules/Re-Malwack/system/bin/rmlwk --${fileType} add ${inputValue}'`); console.log(`${fileType}ed "${inputValue}" successfully.`); showPrompt(`${fileType}ed ${inputValue} successfully.`, true); inputElement.value = ""; + await loadFile(fileType); await getStatus(); } catch (error) { console.log(`Fail to ${fileType} "${inputValue}": ${error}`); @@ -212,7 +291,7 @@ inputs.forEach(input => { // Link redirect links.forEach(link => { - link.element.addEventListener('click', async () => { + link.element.addEventListener("click", async () => { try { await execCommand(`am start -a android.intent.action.VIEW -d ${link.url}`); } catch (error) { @@ -221,6 +300,108 @@ links.forEach(link => { }); }); +// Function to apply ripple effect +function applyRippleEffect() { + rippleClasses.forEach(selector => { + document.querySelectorAll(selector).forEach(element => { + if (element.dataset.rippleListener !== "true") { + element.addEventListener("pointerdown", function (event) { + if (isScrolling) return; + if (modeActive) return; + + const ripple = document.createElement("span"); + ripple.classList.add("ripple"); + + // Calculate ripple size and position + const rect = element.getBoundingClientRect(); + const width = rect.width; + const size = Math.max(rect.width, rect.height); + const x = event.clientX - rect.left - size / 2; + const y = event.clientY - rect.top - size / 2; + + // Determine animation duration + let duration = 0.3 + (width / 800) * 0.3; + duration = Math.min(0.8, Math.max(0.2, duration)); + + // Set ripple styles + ripple.style.width = ripple.style.height = `${size}px`; + ripple.style.left = `${x}px`; + ripple.style.top = `${y}px`; + ripple.style.animationDuration = `${duration}s`; + ripple.style.transition = `opacity ${duration}s ease`; + + // Adaptive color + const computedStyle = window.getComputedStyle(element); + const bgColor = computedStyle.backgroundColor || "rgba(0, 0, 0, 0)"; + const textColor = computedStyle.color; + const isDarkColor = (color) => { + const rgb = color.match(/\d+/g); + if (!rgb) return false; + const [r, g, b] = rgb.map(Number); + return (r * 0.299 + g * 0.587 + b * 0.114) < 96; // Luma formula + }; + ripple.style.backgroundColor = isDarkColor(bgColor) ? "rgba(255, 255, 255, 0.2)" : ""; + + // Append ripple and handle cleanup + element.appendChild(ripple); + const handlePointerUp = () => { + ripple.classList.add("end"); + setTimeout(() => { + ripple.classList.remove("end"); + ripple.remove(); + }, duration * 1000); + element.removeEventListener("pointerup", handlePointerUp); + element.removeEventListener("pointercancel", handlePointerUp); + }; + element.addEventListener("pointerup", handlePointerUp); + element.addEventListener("pointercancel", handlePointerUp); + }); + element.dataset.rippleListener = "true"; + } + }); + }); +} + +// Function to read a file and display its content in the UI +async function loadFile(fileType) { + try { + const content = await execCommand(`cat ${filePaths[fileType]}`); + const lines = content + .split("\n") + .map(line => line.trim()) + .filter(line => line && !line.startsWith("#")); + const listElement = document.getElementById(`${fileType}-list`); + listElement.innerHTML = ""; + lines.forEach(line => { + const listItem = document.createElement("li"); + listItem.innerHTML = ` + ${line} + + `; + listElement.appendChild(listItem); + listItem.querySelector(".delete-btn").addEventListener("click", () => removeLine(fileType, line)); + }); + applyRippleEffect(); + } catch (error) { + console.error(`Failed to load ${fileType} file:`, error); + } +} + +// Function to remove a line from whitelist/blacklist +async function removeLine(fileType, line) { + try { + await execCommand(`su -c '/data/adb/modules/Re-Malwack/system/bin/rmlwk --${fileType} remove ${line}'`); + showPrompt(`Removed ${line} from ${fileType}`, true); + await loadFile(fileType); + await getStatus(); + } catch (error) { + console.error(`Failed to remove line from ${fileType}:`, error); + showPrompt(`Failed to remove ${line} from ${fileType}`, false); + } +} + // Initial load document.addEventListener('DOMContentLoaded', async () => { document.getElementById("about-button").addEventListener("click", aboutMenu); @@ -232,4 +413,10 @@ document.addEventListener('DOMContentLoaded', async () => { attachAddButtonListeners(); getVersion(); getStatus(); + blockPornStatus(); + blockGamblingStatus(); + blockFakenewsStatus(); + applyRippleEffect(); + await loadFile('whitelist'); + await loadFile('blacklist'); }); diff --git a/webroot/styles.css b/webroot/styles.css index a91ead0..d625d59 100644 --- a/webroot/styles.css +++ b/webroot/styles.css @@ -31,6 +31,7 @@ body.input-focused { box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); padding: 15px; overflow: hidden; + user-select: none; } .festival { @@ -93,6 +94,7 @@ body.input-focused { border: none; font-size: 18px; color: #ccc; + user-select: none; } .about-content { @@ -108,13 +110,25 @@ body.input-focused { text-align: left; } +.logo-light { + display: inline-block; + user-select: none; +} + +.logo-dark { + display: none; + user-select: none; +} + #module-name { padding-top: 5px; font-size: 28px; + user-select: none; } #author { font-size: 14px; + user-select: none; } #credits { @@ -122,6 +136,7 @@ body.input-focused { padding-bottom: 5px; font-weight: bold; font-size: 20px; + user-select: none; } .link { @@ -131,11 +146,14 @@ body.input-focused { .link-icon { display:inline-block; font-style: normal; - padding: 5px 10px; + padding: 3px 10px; color: #fff; border-radius: 8px; margin-bottom: 5px; transition: background-color 0.2s ease; + position: relative; + overflow: hidden; + user-select: none; } .link-icon object { @@ -149,43 +167,25 @@ body.input-focused { background-color: #38A7ED; } -#telegram:active { - background-color: #0B76BA; -} - #github { background-color: #606060; } -#github:active { - background-color: #211C1C; -} - #xda { background-color: #FF8002; color: #fff; } -#xda:active { - background-color: #A95400; - color: #fff; -} - #sponsor { background-color: #E7D705; } -#sponsor:active { - background-color: #968B00; -} - #link-text { font-size: 17px; font-weight: bold; } .box { - position: relative; width: 85vw; max-width: 800px; background-color: #fff; @@ -194,6 +194,9 @@ body.input-focused { box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); padding: 15px; transition: background-color 0.2s ease; + position: relative; + overflow: hidden; + user-select: none; } .box h2 { @@ -201,10 +204,12 @@ body.input-focused { font-size: 20px; font-weight: bold; margin-bottom: 10px; + user-select: none; } #version-status { font-size: 14px; + user-select: none; } .toggle-container { @@ -218,6 +223,62 @@ body.input-focused { text-align: left; } +.toggle-switch { + position: relative; + display: inline-block; + margin-left: auto; + width: 40px; + height: 25px; +} + +.toggle-switch input { + opacity: 0; + width: 0; + height: 0; +} + +.slider { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #ccc; + -webkit-transition: .4s; + transition: .4s; +} + +.slider:before { + position: absolute; + content: ""; + height: 19px; + width: 19px; + left: 3px; + bottom: 3px; + background-color: white; + transition: .4s; +} + +input:checked+.slider { + background-color: #D51200; +} + +input:focus+.slider { + box-shadow: 0 0 1px #D51200; +} + +input:checked+.slider:before { + transform: translateX(15px); +} + +.slider.round { + border-radius: 25px; +} + +.slider.round:before { + border-radius: 50%; +} + .control-icon { padding-top: 5px; padding-right: 7px; @@ -256,19 +317,17 @@ body.input-focused { transition: background-color 0.2s ease; } -.current-mode-text:active, -.action-button:active, -.category-container button:active { - background-color: #850B00; -} - -.box:active { - background-color: #ccc; -} - -#whitelist:active, -#blacklist:active { - background-color: #fff; +.delete-btn { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + padding: 0; + border: none; + border-radius: 50%; + background-color: #D51200; + color: #fff; } ul { @@ -281,7 +340,7 @@ li { display: flex; justify-content: space-between; align-items: center; - padding: 8px 3px; + padding: 8px 5px; border-bottom: 1px solid #ccc; } @@ -316,13 +375,14 @@ li:last-child { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); color: white; font-size: 15px; - padding: 5px 15px; + padding: 5px 10px; z-index: 1000; transform: translateY(100%); transition: transform 0.5s ease, background-color 0.2s ease; width: auto; - max-width: 88vw; + max-width: calc(100% - 40px); z-index: 1300; + user-select: none; } .prompt.visible { @@ -371,6 +431,31 @@ li:last-child { text-align: center; } +.ripple-container { + position: relative; + overflow: hidden; +} + +.ripple { + position: absolute; + border-radius: 50%; + transform: scale(0); + opacity: 1; + animation: ripple-animation ease-out forwards; + pointer-events: none; + background: rgba(0, 0, 0, 0.2); +} + +.ripple.end { + opacity: 0; +} + +@keyframes ripple-animation { + to { + transform: scale(3); + } +} + @media (prefers-color-scheme: dark) { body { background-color: #121212; @@ -381,13 +466,19 @@ li:last-child { border-bottom: 1px solid #6E6E6E; } - #whitelist:active, - #blacklist:active, .about-menu, .box { background-color: #343434; } + .logo-light { + display: none; + } + + .logo-dark { + display: inline-block; + } + .category-container input { color: #fff; background-color: #232323; @@ -398,7 +489,6 @@ li:last-child { fill: #fff; } - .box:active, .slider { background-color: #6E6E6E; } diff --git a/whitelist.txt b/whitelist.txt new file mode 100644 index 0000000..270e34f --- /dev/null +++ b/whitelist.txt @@ -0,0 +1,3 @@ +# Re-Malwack hosts whitelist + +s.youtube.com