#!/bin/sh set -eu export LC_ALL='C' # Metadata. if [ -z "${HOSTS_VERSION+x}" ]; then HOSTS_VERSION='3.5.1'; fi if [ -z "${HOSTS_AUTHOR+x}" ]; then HOSTS_AUTHOR='FLOSSbOxIN '; fi if [ -z "${HOSTS_LICENSE+x}" ]; then HOSTS_LICENSE='MIT, https://opensource.org/licenses/MIT'; fi if [ -z "${HOSTS_REPOSITORY+x}" ]; then HOSTS_REPOSITORY='https://git.flossboxin.org.in/vdbhb59/hosts/raw/branch/main/hblock'; fi # Emulate ksh if the shell is zsh. if [ -n "${ZSH_VERSION-}" ]; then emulate -L ksh; fi # Define system and user configuration directories. if [ -z "${ETCDIR+x}" ]; then ETCDIR='/etc'; fi if [ -z "${XDG_CONFIG_HOME+x}" ]; then XDG_CONFIG_HOME="${HOME-}/.config"; fi # Trap various signals to remove temporary files on exit. abort() { : "${EXIT_STATUS:=${?}}"; rm -rf -- "${TMPDIR:-${TMP:-/tmp}}/hblock.${$}."*; trap - EXIT; exit "${EXIT_STATUS:?}"; } { trap abort EXIT ||:; trap abort TERM ||:; trap abort INT ||:; trap abort HUP ||:; } 2>/dev/null # For all other signals the exit status is preserved, but USR1 and USR2 will always use 10 and 12 respectively. { trap 'EXIT_STATUS=10; abort' USR1; trap 'EXIT_STATUS=12; abort' USR2; } 2>/dev/null # Built-in header. # HOSTNAME="${HOSTNAME-"$(uname -n)"}" HOSTNAME="" HBLOCK_HEADER_BUILTIN="$(cat <<-EOF 127.0.0.1 localhost ${HOSTNAME?} 255.255.255.255 broadcasthost ::1 localhost ${HOSTNAME?} ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters ff02::3 ip6-allhosts EOF )" # Built-in footer. HBLOCK_FOOTER_BUILTIN='' # Built-in sources. HBLOCK_SOURCES_BUILTIN="$(cat <<-'EOF' https://a.dove.isdumb.one/list.txt https://cdn.jsdelivr.net/gh/ignaciocastro/a-dove-is-dumb@assets/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/adaway.org/list.txt https://raw.githubusercontent.com/ignaciocastro/a-dove-is-dumb/refs/heads/main/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/adaway.org/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/adblock-nocoin-list/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/adguard-cname-trackers/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/adguard-simplified/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/awavenue-ads/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/d3host/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/dandelionsprout-nordic/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-ara/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-bul/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-ces-slk/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-deu/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-fra/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-heb/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-ind/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-ita/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-kor/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-lav/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-lit/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-nld/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-pol/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-por/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-rus/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-spa/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easylist-zho/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/easyprivacy/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/eth-phishing-detect/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/gfrogeye-firstparty-trackers/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/hostsvn/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/kadhosts/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/matomo.org-spammers/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/mitchellkrogza-badd-boyz-hosts/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/pgl.yoyo.org/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/phishing.army/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/red.flag.domains/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/someonewhocares.org/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/spam404.com/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/stevenblack/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/turkish-ad-hosts/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/ublock/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/ublock-2020/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/ublock-2021/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/ublock-2022/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/ublock-2023/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/ublock-2024/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/ublock-2025/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/ublock-abuse/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/ublock-badware/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/ublock-privacy/list.txt https://raw.githubusercontent.com/hectorm/hmirror/master/data/urlhaus/list.txt https://raw.githubusercontent.com/bogachenko/fuckfuckadblock/master/fuckfuckadblock.txt # https://www.apps2sd.info/idm/filters.txt # https://filters.adtidy.org/windows/filters/1.txt?id=1 # https://filters.adtidy.org/extension/ublock/filters/9.txt # https://filters.adtidy.org/windows/filters/13.txt?d=13 # https://filters.adtidy.org/extension/ublock/filters/14.txt # https://filters.adtidy.org/extension/ublock/filters/11.txt # https://secure.fanboy.co.nz/fanboy-indian.txt # https://secure.fanboy.co.nz/fanboy-cookiemonster.txt # https://malware-filter.gitlab.io/malware-filter/urlhaus-filter-online.txt https://raw.githubusercontent.com/ABPindo/indonesianadblockrules/master/subscriptions/abpindo.txt https://easylist-downloads.adblockplus.org/antiadblockfilters.txt EOF )" # Built-in allowlist. HBLOCK_ALLOWLIST_BUILTIN='' # Built-in denylist. HBLOCK_DENYLIST_BUILTIN="$(cat <<-'EOF' # EOF )" # Parse command line options. optParse() { SEP="$(printf '\037')" while [ "${#}" -gt '0' ]; do case "${1?}" in # Short options that accept a value need a "*" in their pattern because they can be found in the "-A" form. '-O'*|'--output') optArgStr "${@-}"; outputFile="${optArg?}"; shift "${optShift:?}" ;; '-H'*|'--header') optArgStr "${@-}"; headerFile="${optArg?}"; shift "${optShift:?}" ;; '-F'*|'--footer') optArgStr "${@-}"; footerFile="${optArg?}"; shift "${optShift:?}" ;; '-S'*|'--sources') optArgStr "${@-}"; sourcesFile="${optArg?}"; shift "${optShift:?}" ;; '-A'*|'--allowlist') optArgStr "${@-}"; allowlistFile="${optArg?}"; shift "${optShift:?}" ;; '-D'*|'--denylist') optArgStr "${@-}"; denylistFile="${optArg?}"; shift "${optShift:?}" ;; '-R'*|'--redirection') optArgStr "${@-}"; redirection="${optArg?}"; shift "${optShift:?}" ;; '-W'*|'--wrap') optArgStr "${@-}"; wrap="${optArg?}"; shift "${optShift:?}" ;; '-T'*|'--template') optArgStr "${@-}"; template="${optArg?}"; shift "${optShift:?}" ;; '-C'*|'--comment') optArgStr "${@-}"; comment="${optArg?}"; shift "${optShift:?}" ;; '-l' |'--lenient'|'--no-lenient') optArgBool "${@-}"; lenient="${optArg:?}" ;; '-r' |'--regex'|'--no-regex') optArgBool "${@-}"; regex="${optArg:?}" ;; '-f' |'--filter-subdomains'|'--no-filter-subdomains') optArgBool "${@-}"; filterSubdomains="${optArg:?}" ;; '-n'*|'--retry') optArgStr "${@-}"; retry="${optArg?}"; shift "${optShift:?}" ;; '-c' |'--continue'|'--no-continue') optArgBool "${@-}"; continue="${optArg:?}" ;; '-p'*|'--parallel') optArgStr "${@-}"; parallel="${optArg?}"; shift "${optShift:?}" ;; '-q' |'--quiet'|'--no-quiet') optArgBool "${@-}"; quiet="${optArg:?}" ;; '-x'*|'--color') optArgStr "${@-}"; color="${optArg?}"; shift "${optShift:?}" ;; '-v' |'--version') showVersion ;; '-h' |'--help') showHelp ;; # If "--" is found, the remaining positional parameters are saved and the parsing ends. --) shift; _IFS="${IFS?}"; IFS="${SEP:?}"; POS="${POS-}${POS+${SEP:?}}${*-}"; IFS="${_IFS?}"; break ;; # If a long option in the form "--opt=value" is found, it is split into "--opt" and "value". --*=*) optSplitEquals "${@-}"; shift; set -- "${optName:?}" "${optArg?}" "${@-}"; continue ;; # If an option did not match any pattern, an error is thrown. -?|--*) optDie "Illegal option ${1:?}" ;; # If multiple short options in the form "-AB" are found, they are split into "-A" and "-B". -?*) optSplitShort "${@-}"; shift; set -- "${optAName:?}" "${optBName:?}" "${@-}"; continue ;; # If a positional parameter is found, it is saved. *) POS="${POS-}${POS+${SEP:?}}${1?}" ;; esac shift done } optSplitShort() { optAName="${1%"${1#??}"}"; optBName="-${1#??}" } optSplitEquals() { optName="${1%="${1#--*=}"}"; optArg="${1#--*=}" } optArgStr() { if [ -n "${1#??}" ] && [ "${1#--}" = "${1:?}" ]; then optArg="${1#??}"; optShift='0'; elif [ -n "${2+x}" ]; then optArg="${2-}"; optShift='1'; else optDie "No argument for ${1:?} option"; fi } optArgBool() { if [ "${1#--no-}" = "${1:?}" ]; then optArg='true'; else optArg='false'; fi } optDie() { printf '%s\n' "${@-}" "Try 'hblock --help' for more information" >&2 exit 2 } # Show help and quit. showHelp() { printf '%s\n' "$(sed -e 's/%NL/\n/g' <<-EOF Usage: hblock [OPTION]... hBlock is a POSIX-compliant shell script that gets a list of domains that serve ads, tracking scripts and malware from multiple sources and creates a hosts file, among other formats, that prevents your system from connecting to them. Options: -O, --output , \${HBLOCK_OUTPUT_FILE}%NL Output file location.%NL If equals "-", it is printed to stdout.%NL (default: ${outputFile?})%NL -H, --header , \${HBLOCK_HEADER_FILE}%NL File to be included at the beginning of the output file.%NL If equals "builtin", the built-in value is used.%NL If equals "none", an empty value is used.%NL If equals "-", the stdin content is used.%NL If unspecified and any of the following files exists, its content is used.%NL \${XDG_CONFIG_HOME}/hblock/header%NL ${ETCDIR?}/hblock/header%NL (default: ${headerFile?})%NL -F, --footer , \${HBLOCK_FOOTER_FILE}%NL File to be included at the end of the output file.%NL If equals "builtin", the built-in value is used.%NL If equals "none", an empty value is used.%NL If equals "-", the stdin content is used.%NL If unspecified and any of the following files exists, its content is used.%NL \${XDG_CONFIG_HOME}/hblock/footer%NL ${ETCDIR?}/hblock/footer%NL (default: ${footerFile?})%NL -S, --sources , \${HBLOCK_SOURCES_FILE}%NL File with line separated URLs used to generate the blocklist.%NL If equals "builtin", the built-in value is used.%NL If equals "none", an empty value is used.%NL If equals "-", the stdin content is used.%NL If unspecified and any of the following files exists, its content is used.%NL \${XDG_CONFIG_HOME}/hblock/sources.list%NL ${ETCDIR?}/hblock/sources.list%NL (default: ${sourcesFile?})%NL -A, --allowlist , \${HBLOCK_ALLOWLIST_FILE}%NL File with line separated entries to be removed from the blocklist.%NL If equals "builtin", the built-in value is used.%NL If equals "none", an empty value is used.%NL If equals "-", the stdin content is used.%NL If unspecified and any of the following files exists, its content is used.%NL \${XDG_CONFIG_HOME}/hblock/allow.list%NL ${ETCDIR?}/hblock/allow.list%NL (default: ${allowlistFile?})%NL -D, --denylist , \${HBLOCK_DENYLIST_FILE}%NL File with line separated entries to be added to the blocklist.%NL If equals "builtin", the built-in value is used.%NL If equals "none", an empty value is used.%NL If equals "-", the stdin content is used.%NL If unspecified and any of the following files exists, its content is used.%NL \${XDG_CONFIG_HOME}/hblock/deny.list%NL ${ETCDIR?}/hblock/deny.list%NL (default: ${denylistFile?})%NL -R, --redirection , \${HBLOCK_REDIRECTION}%NL Redirection for all entries in the blocklist.%NL (default: ${redirection?})%NL -W, --wrap , \${HBLOCK_WRAP}%NL Break blocklist lines after this number of entries.%NL (default: ${wrap?})%NL -T, --template