diff --git a/advanced/Scripts/chronometer.sh b/advanced/Scripts/chronometer.sh index d9b01fc0..a9ccf900 100755 --- a/advanced/Scripts/chronometer.sh +++ b/advanced/Scripts/chronometer.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +# shellcheck disable=SC1090,SC1091 # Pi-hole: A black hole for Internet advertisements # (c) 2017 Pi-hole, LLC (https://pi-hole.net) # Network-wide ad blocking via your own hardware. @@ -91,10 +92,10 @@ printFunc() { printf "%s%s$spc" "$title" "$text_main" if [[ -n "$text_addn" ]]; then - printf "%s(%s)%s\n" "$COL_NC$COL_DARK_GRAY" "$text_addn" "$COL_NC" + printf "%s(%s)%s\\n" "$COL_NC$COL_DARK_GRAY" "$text_addn" "$COL_NC" else # Do not print trailing newline on final line - [[ -z "$text_last" ]] && printf "%s\n" "$COL_NC" + [[ -z "$text_last" ]] && printf "%s\\n" "$COL_NC" fi } @@ -126,7 +127,7 @@ get_init_stats() { mins=$(( ($1%3600)/60 )); secs=$(( $1%60 )) [[ "$day" -ge "2" ]] && plu="s" [[ "$day" -ge "1" ]] && days="$day day${plu}, " || days="" - printf "%s%02d:%02d:%02d\n" "$days" "$hrs" "$mins" "$secs" + printf "%s%02d:%02d:%02d\\n" "$days" "$hrs" "$mins" "$secs" } # Set Colour Codes @@ -285,6 +286,7 @@ get_sys_stats() { sys_loadavg=$(cut -d " " -f1,2,3 /proc/loadavg) # Get CPU usage, only counting processes over 1% as active + # shellcheck disable=SC2009 cpu_raw=$(ps -eo pcpu,rss --no-headers | grep -E -v " 0") cpu_tasks=$(wc -l <<< "$cpu_raw") cpu_taskact=$(sed -r "/(^ 0.)/d" <<< "$cpu_raw" | wc -l) @@ -306,7 +308,7 @@ get_sys_stats() { # Determine colour for temperature if [[ -n "$temp_file" ]]; then if [[ "$temp_unit" == "C" ]]; then - cpu_temp=$(printf "%.0fc\n" "$(calcFunc "$(< $temp_file) / 1000")") + cpu_temp=$(printf "%.0fc\\n" "$(calcFunc "$(< $temp_file) / 1000")") case "${cpu_temp::-1}" in -*|[0-9]|[1-3][0-9]) cpu_col="$COL_LIGHT_BLUE";; @@ -320,7 +322,7 @@ get_sys_stats() { cpu_temp_str=" @ $cpu_col$cpu_temp$COL_NC$COL_DARK_GRAY" elif [[ "$temp_unit" == "F" ]]; then - cpu_temp=$(printf "%.0ff\n" "$(calcFunc "($(< $temp_file) / 1000) * 9 / 5 + 32")") + cpu_temp=$(printf "%.0ff\\n" "$(calcFunc "($(< $temp_file) / 1000) * 9 / 5 + 32")") case "${cpu_temp::-1}" in -*|[0-9]|[0-9][0-9]) cpu_col="$COL_LIGHT_BLUE";; @@ -333,7 +335,7 @@ get_sys_stats() { cpu_temp_str=" @ $cpu_col$cpu_temp$COL_NC$COL_DARK_GRAY" else - cpu_temp_str=$(printf " @ %.0fk\n" "$(calcFunc "($(< $temp_file) / 1000) + 273.15")") + cpu_temp_str=$(printf " @ %.0fk\\n" "$(calcFunc "($(< $temp_file) / 1000) + 273.15")") fi else cpu_temp_str="" @@ -365,12 +367,12 @@ get_ftl_stats() { local stats_raw mapfile -t stats_raw < <(pihole-FTL "stats") - domains_being_blocked_raw="${stats_raw[1]#* }" - dns_queries_today_raw="${stats_raw[3]#* }" - ads_blocked_today_raw="${stats_raw[5]#* }" - ads_percentage_today_raw="${stats_raw[7]#* }" - queries_forwarded_raw="${stats_raw[11]#* }" - queries_cached_raw="${stats_raw[13]#* }" + domains_being_blocked_raw="${stats_raw[0]#* }" + dns_queries_today_raw="${stats_raw[1]#* }" + ads_blocked_today_raw="${stats_raw[2]#* }" + ads_percentage_today_raw="${stats_raw[3]#* }" + queries_forwarded_raw="${stats_raw[5]#* }" + queries_cached_raw="${stats_raw[6]#* }" # Only retrieve these stats when not called from jsonFunc if [[ -z "$1" ]]; then @@ -378,11 +380,11 @@ get_ftl_stats() { local top_domain_raw local top_client_raw - domains_being_blocked=$(printf "%.0f\n" "${domains_being_blocked_raw}") - dns_queries_today=$(printf "%.0f\n" "${dns_queries_today_raw}") - ads_blocked_today=$(printf "%.0f\n" "${ads_blocked_today_raw}") - ads_percentage_today=$(printf "%'.0f\n" "${ads_percentage_today_raw}") - queries_cached_percentage=$(printf "%.0f\n" "$(calcFunc "$queries_cached_raw * 100 / ( $queries_forwarded_raw + $queries_cached_raw )")") + domains_being_blocked=$(printf "%.0f\\n" "${domains_being_blocked_raw}") + dns_queries_today=$(printf "%.0f\\n" "${dns_queries_today_raw}") + ads_blocked_today=$(printf "%.0f\\n" "${ads_blocked_today_raw}") + ads_percentage_today=$(printf "%'.0f\\n" "${ads_percentage_today_raw}") + queries_cached_percentage=$(printf "%.0f\\n" "$(calcFunc "$queries_cached_raw * 100 / ( $queries_forwarded_raw + $queries_cached_raw )")") recent_blocked=$(pihole-FTL recentBlocked) read -r -a top_ad_raw <<< "$(pihole-FTL "top-ads (1)")" read -r -a top_domain_raw <<< "$(pihole-FTL "top-domains (1)")" @@ -412,6 +414,8 @@ get_strings() { used_str="Used: " leased_str="Leased: " domains_being_blocked=$(printf "%'.0f" "$domains_being_blocked") + ads_blocked_today=$(printf "%'.0f" "$ads_blocked_today") + dns_queries_today=$(printf "%'.0f" "$dns_queries_today") ph_info="Blocking: $domains_being_blocked sites" total_str="Total: " else @@ -473,8 +477,8 @@ chronoFunc() { ${COL_DARK_GRAY}$scr_line_str${COL_NC}" else echo -e "|¯¯¯(¯)_|¯|_ ___|¯|___$phc_ver_str -| ¯_/¯|_| ' \/ _ \ / -_)$lte_ver_str -|_| |_| |_||_\___/_\___|$ftl_ver_str +| ¯_/¯|_| ' \\/ _ \\ / -_)$lte_ver_str +|_| |_| |_||_\\___/_\\___|$ftl_ver_str ${COL_DARK_GRAY}$scr_line_str${COL_NC}" fi diff --git a/advanced/Scripts/piholeCheckout.sh b/advanced/Scripts/piholeCheckout.sh index 093c958e..f214d2ce 100644 --- a/advanced/Scripts/piholeCheckout.sh +++ b/advanced/Scripts/piholeCheckout.sh @@ -24,6 +24,98 @@ update="false" coltable="/opt/pihole/COL_TABLE" source ${coltable} +check_download_exists() { + status=$(curl --head --silent "https://ftl.pi-hole.net/${1}" | head -n 1) + if grep -q "404" <<< "$status"; then + return 1 + else + return 0 + fi +} + +FTLinstall() { + # Download and install FTL binary + local binary + binary="${1}" + local path + path="${2}" + local str + str="Installing FTL" + echo -ne " ${INFO} ${str}..." + + if curl -sSL --fail "https://ftl.pi-hole.net/${path}" -o "/tmp/${binary}"; then + # Get sha1 of the binary we just downloaded for verification. + curl -sSL --fail "https://ftl.pi-hole.net/${path}.sha1" -o "/tmp/${binary}.sha1" + # Check if we just downloaded text, or a binary file. + cd /tmp || return 1 + if sha1sum --status --quiet -c "${binary}".sha1; then + echo -n "transferred... " + stop_service pihole-FTL &> /dev/null + install -T -m 0755 "/tmp/${binary}" "/usr/bin/pihole-FTL" + rm "/tmp/${binary}" "/tmp/${binary}.sha1" + start_service pihole-FTL &> /dev/null + echo -e "${OVER} ${TICK} ${str}" + return 0 + else + echo -e "${OVER} ${CROSS} ${str}" + echo -e " ${COL_LIGHT_RED}Error: Download of binary from ftl.pi-hole.net failed${COL_NC}" + return 1 + fi + else + echo -e "${OVER} ${CROSS} ${str}" + echo -e " ${COL_LIGHT_RED}Error: URL not found${COL_NC}" + fi +} + +get_binary_name() { + local machine + machine=$(uname -m) + + local str + str="Detecting architecture" + echo -ne " ${INFO} ${str}..." + if [[ "${machine}" == "arm"* || "${machine}" == *"aarch"* ]]; then + # ARM + local rev + rev=$(uname -m | sed "s/[^0-9]//g;") + local lib + lib=$(ldd /bin/ls | grep -E '^\s*/lib' | awk '{ print $1 }') + if [[ "${lib}" == "/lib/ld-linux-aarch64.so.1" ]]; then + echo -e "${OVER} ${TICK} Detected ARM-aarch64 architecture" + binary="pihole-FTL-aarch64-linux-gnu" + elif [[ "${lib}" == "/lib/ld-linux-armhf.so.3" ]]; then + if [[ "$rev" -gt "6" ]]; then + echo -e "${OVER} ${TICK} Detected ARM-hf architecture (armv7+)" + binary="pihole-FTL-arm-linux-gnueabihf" + else + echo -e "${OVER} ${TICK} Detected ARM-hf architecture (armv6 or lower) Using ARM binary" + binary="pihole-FTL-arm-linux-gnueabi" + fi + else + echo -e "${OVER} ${TICK} Detected ARM architecture" + binary="pihole-FTL-arm-linux-gnueabi" + fi + elif [[ "${machine}" == "ppc" ]]; then + # PowerPC + echo -e "${OVER} ${TICK} Detected PowerPC architecture" + binary="pihole-FTL-powerpc-linux-gnu" + elif [[ "${machine}" == "x86_64" ]]; then + # 64bit + echo -e "${OVER} ${TICK} Detected x86_64 architecture" + binary="pihole-FTL-linux-x86_64" + else + # Something else - we try to use 32bit executable and warn the user + if [[ ! "${machine}" == "i686" ]]; then + echo -e "${OVER} ${CROSS} ${str}... + ${COL_LIGHT_RED}Not able to detect architecture (unknown: ${machine}), trying 32bit executable + Contact support if you experience issues (e.g: FTL not running)${COL_NC}" + else + echo -e "${OVER} ${TICK} Detected 32bit (i686) architecture" + fi + binary="pihole-FTL-linux-x86_32" + fi +} + fully_fetch_repo() { # Add upstream branches to shallow clone local directory="${1}" @@ -40,7 +132,8 @@ fully_fetch_repo() { get_available_branches() { # Return available branches - local directory="${1}" + local directory + directory="${1}" local output cd "${directory}" || return 1 @@ -50,14 +143,15 @@ get_available_branches() { return } - fetch_checkout_pull_branch() { # Check out specified branch - local directory="${1}" - local branch="${2}" + local directory + directory="${1}" + local branch + branch="${2}" # Set the reference for the requested branch, fetch, check it put and pull it - cd "${directory}" + cd "${directory}" || return 1 git remote set-branches origin "${branch}" || return 1 git stash --all --quiet &> /dev/null || true git clean --quiet --force -d || true @@ -67,8 +161,10 @@ fetch_checkout_pull_branch() { checkout_pull_branch() { # Check out specified branch - local directory="${1}" - local branch="${2}" + local directory + directory="${1}" + local branch + branch="${2}" local oldbranch cd "${directory}" || return 1 @@ -86,7 +182,7 @@ checkout_pull_branch() { if [[ "$git_pull" == *"up-to-date"* ]]; then echo -e " ${INFO} $(git pull)" else - echo -e "$git_pull\n" + echo -e "$git_pull\\n" fi return 0 @@ -97,13 +193,13 @@ warning1() { echo " Features that work on the master branch, may not on a development branch" echo -e " ${COL_LIGHT_RED}This feature is NOT supported unless a Pi-hole developer explicitly asks!${COL_NC}" read -r -p " Have you read and understood this? [y/N] " response - case ${response} in + case "${response}" in [yY][eE][sS]|[yY]) echo "" return 0 ;; *) - echo -e "\n ${INFO} Branch change has been cancelled" + echo -e "\\n ${INFO} Branch change has been cancelled" return 1 ;; esac @@ -122,7 +218,7 @@ checkout() { Please re-run install script from https://github.com/pi-hole/pi-hole${COL_NC}" exit 1; fi - if [[ ${INSTALL_WEB} == "true" ]]; then + if [[ "${INSTALL_WEB}" == "true" ]]; then if ! is_repo "${webInterfaceDir}" ; then echo -e " ${COL_LIGHT_RED}Error: Web Admin repo is missing from system! Please re-run install script from https://github.com/pi-hole/pi-hole${COL_NC}" @@ -146,12 +242,17 @@ checkout() { echo "" echo -e " ${INFO} Pi-hole Core" fetch_checkout_pull_branch "${PI_HOLE_FILES_DIR}" "development" || { echo " ${CROSS} Unable to pull Core developement branch"; exit 1; } - if [[ ${INSTALL_WEB} == "true" ]]; then + if [[ "${INSTALL_WEB}" == "true" ]]; then echo "" echo -e " ${INFO} Web interface" fetch_checkout_pull_branch "${webInterfaceDir}" "devel" || { echo " ${CROSS} Unable to pull Web development branch"; exit 1; } fi #echo -e " ${TICK} Pi-hole Core" + + get_binary_name + local path + path="development/${binary}" + FTLinstall "${binary}" "${path}" elif [[ "${1}" == "master" ]] ; then # Shortcut to check out master branches echo -e " ${INFO} Shortcut \"master\" detected - checking out master branches..." @@ -162,7 +263,10 @@ checkout() { fetch_checkout_pull_branch "${webInterfaceDir}" "master" || { echo " ${CROSS} Unable to pull Web master branch"; exit 1; } fi #echo -e " ${TICK} Web Interface" - + get_binary_name + local path + path="master/${binary}" + FTLinstall "${binary}" "${path}" elif [[ "${1}" == "core" ]] ; then str="Fetching branches from ${piholeGitUrl}" echo -ne " ${INFO} $str" @@ -172,12 +276,12 @@ checkout() { fi corebranches=($(get_available_branches "${PI_HOLE_FILES_DIR}")) - if [[ "${corebranches[@]}" == *"master"* ]]; then + if [[ "${corebranches[*]}" == *"master"* ]]; then echo -e "${OVER} ${TICK} $str ${INFO} ${#corebranches[@]} branches available for Pi-hole Core" else # Print STDERR output from get_available_branches - echo -e "${OVER} ${CROSS} $str\n\n${corebranches[*]}" + echo -e "${OVER} ${CROSS} $str\\n\\n${corebranches[*]}" exit 1 fi @@ -199,12 +303,12 @@ checkout() { fi webbranches=($(get_available_branches "${webInterfaceDir}")) - if [[ "${corebranches[@]}" == *"master"* ]]; then + if [[ "${webbranches[*]}" == *"master"* ]]; then echo -e "${OVER} ${TICK} $str ${INFO} ${#webbranches[@]} branches available for Web Admin" else # Print STDERR output from get_available_branches - echo -e "${OVER} ${CROSS} $str\n\n${corebranches[*]}" + echo -e "${OVER} ${CROSS} $str\\n\\n${webbranches[*]}" exit 1 fi @@ -217,13 +321,29 @@ checkout() { exit 1 fi checkout_pull_branch "${webInterfaceDir}" "${2}" + elif [[ "${1}" == "ftl" ]] ; then + get_binary_name + local path + path="${2}/${binary}" + + if check_download_exists "$path"; then + echo " ${TICK} Branch ${2} exists" + FTLinstall "${binary}" "${path}" + else + echo " ${CROSS} Requested branch \"${2}\" is not available" + ftlbranches=( $(git ls-remote https://github.com/pi-hole/ftl | grep 'heads' | sed 's/refs\/heads\///;s/ //g' | awk '{print $2}') ) + echo -e " ${INFO} Available branches for FTL are:" + for e in "${ftlbranches[@]}"; do echo " - $e"; done + exit 1 + fi + else echo -e " ${INFO} Requested option \"${1}\" is not available" exit 1 fi # Force updating everything - if [[ ! "${1}" == "web" && "${update}" == "true" ]]; then + if [[ ( ! "${1}" == "web" && ! "${1}" == "ftl" ) && "${update}" == "true" ]]; then echo -e " ${INFO} Running installer to upgrade your installation" if "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" --unattended; then exit 0 diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index f98d986a..ea387b5a 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -39,6 +39,8 @@ else OVER="\r\033[K" fi +OBFUSCATED_PLACEHOLDER="" + # FAQ URLs for use in showing the debug log FAQ_UPDATE_PI_HOLE="${COL_CYAN}https://discourse.pi-hole.net/t/how-do-i-update-pi-hole/249${COL_NC}" FAQ_CHECKOUT_COMMAND="${COL_CYAN}https://discourse.pi-hole.net/t/the-pihole-command-with-examples/738#checkout${COL_NC}" @@ -47,6 +49,7 @@ FAQ_HARDWARE_REQUIREMENTS_PORTS="${COL_CYAN}https://discourse.pi-hole.net/t/hard FAQ_GATEWAY="${COL_CYAN}https://discourse.pi-hole.net/t/why-is-a-default-gateway-important-for-pi-hole/3546${COL_NC}" FAQ_ULA="${COL_CYAN}https://discourse.pi-hole.net/t/use-ipv6-ula-addresses-for-pi-hole/2127${COL_NC}" FAQ_FTL_COMPATIBILITY="${COL_CYAN}https://github.com/pi-hole/FTL#compatibility-list${COL_NC}" +FAQ_BAD_ADDRESS="${COL_CYAN}https://discourse.pi-hole.net/t/why-do-i-see-bad-address-at-in-pihole-log/3972${COL_NC}" # Other URLs we may use FORUMS_URL="${COL_CYAN}https://discourse.pi-hole.net${COL_NC}" @@ -159,6 +162,17 @@ ${PIHOLE_FTL_LOG} ${PIHOLE_WEB_SERVER_ACCESS_LOG_FILE} ${PIHOLE_WEB_SERVER_ERROR_LOG_FILE}) +DISCLAIMER="This process collects information from your Pi-hole, and optionally uploads it to a unique and random directory on tricorder.pi-hole.net. + +The intent of this script is to allow users to self-diagnose their installations. This is accomplished by running tests against our software and providing the user with links to FAQ articles when a problem is detected. Since we are a small team and Pi-hole has been growing steadily, it is our hope that this will help us spend more time on development. + +NOTE: All log files auto-delete after 48 hours and ONLY the Pi-hole developers can access your data via the given token. We have taken these extra steps to secure your data and will work to further reduce any personal information gathered. +" + +show_disclaimer(){ + log_write "${DISCLAIMER}" +} + source_setup_variables() { # Display the current test that is running log_write "\n${COL_LIGHT_PURPLE}*** [ INITIALIZING ]${COL_NC} Sourcing setup variables" @@ -203,6 +217,7 @@ copy_to_debug_log() { initiate_debug() { # Clear the screen so the debug log is readable clear + show_disclaimer # Display that the debug process is beginning log_write "${COL_LIGHT_PURPLE}*** [ INITIALIZING ]${COL_NC}" # Timestamp the start of the log @@ -457,7 +472,7 @@ does_ip_match_setup_vars() { # If it's an IPv6 address if [[ "${protocol}" == "6" ]]; then # Strip off the / (CIDR notation) - if [[ "${ip_address%/*}" == "${setup_vars_ip}" ]]; then + if [[ "${ip_address%/*}" == "${setup_vars_ip%/*}" ]]; then # if it matches, show it in green log_write " ${COL_LIGHT_GREEN}${ip_address%/*}${COL_NC} matches the IP found in ${PIHOLE_SETUP_VARS_FILE}" else @@ -583,7 +598,7 @@ compare_port_to_service_assigned() { # The programs we use may change at some point, so they are in a varible here local resolver="dnsmasq" local web_server="lighttpd" - local ftl="pihole-FT" + local ftl="pihole-FTL" if [[ "${service_name}" == "${resolver}" ]] || [[ "${service_name}" == "${web_server}" ]] || [[ "${service_name}" == "${ftl}" ]]; then # if port 53 is dnsmasq, show it in green as it's standard log_write "[${COL_LIGHT_GREEN}${port_number}${COL_NC}] is in use by ${COL_LIGHT_GREEN}${service_name}${COL_NC}" @@ -600,7 +615,7 @@ check_required_ports() { # so we can detect any issues local resolver="dnsmasq" local web_server="lighttpd" - local ftl="pihole-FT" + local ftl="pihole-FTL" # Create an array for these ports in use ports_in_use=() # Sort the addresses and remove duplicates @@ -659,6 +674,10 @@ check_x_headers() { block_page_working="X-Pi-hole: A black hole for Internet advertisements." local dashboard_working dashboard_working="X-Pi-hole: The Pi-hole Web interface is working!" + local full_curl_output_block_page + full_curl_output_block_page="$(curl -Is localhost)" + local full_curl_output_dashboard + full_curl_output_dashboard="$(curl -Is localhost/admin/)" # If the X-header found by curl matches what is should be, if [[ $block_page == "$block_page_working" ]]; then # display a success message @@ -666,6 +685,7 @@ check_x_headers() { else # Otherwise, show an error log_write "$CROSS ${COL_LIGHT_RED}X-Header does not match or could not be retrieved.${COL_NC}" + log_write "${COL_LIGHT_RED}${full_curl_output_block_page}${COL_NC}" fi # Same logic applies to the dashbord as above, if the X-Header matches what a working system shoud have, @@ -675,6 +695,7 @@ check_x_headers() { else # Othewise, it's a failure since the X-Headers either don't exist or have been modified in some way log_write "$CROSS ${COL_LIGHT_RED}X-Header does not match or could not be retrieved.${COL_NC}" + log_write "${COL_LIGHT_RED}${full_curl_output_dashboard}${COL_NC}" fi } @@ -972,8 +993,39 @@ analyze_pihole_log() { local pihole_log_head=() pihole_log_head=( $(head -n 20 ${PIHOLE_LOG}) ) log_write " ${COL_CYAN}-----head of $(basename ${PIHOLE_LOG})------${COL_NC}" + local error_to_check_for + local line_to_obfuscate + local obfuscated_line for head_line in "${pihole_log_head[@]}"; do - log_write " ${head_line}" + # A common error in the pihole.log is when there is a non-hosts formatted file + # that the DNS server is attempting to read. Since it's not formatted + # correctly, there will be an entry for "bad address at line n" + # So we can check for that here and highlight it in red so the user can see it easily + error_to_check_for=$(echo ${head_line} | grep 'bad address at') + # Some users may not want to have the domains they visit sent to us + # To that end, we check for lines in the log that would contain a domain name + line_to_obfuscate=$(echo ${head_line} | grep ': query\|: forwarded\|: reply') + # If the variable contains a value, it found an error in the log + if [[ -n ${error_to_check_for} ]]; then + # So we can print it in red to make it visible to the user + log_write " ${CROSS} ${COL_LIGHT_RED}${head_line}${COL_NC} (${FAQ_BAD_ADDRESS})" + else + # If the variable does not a value (the current default behavior), so do not obfuscate anything + if [[ -z ${OBFUSCATE} ]]; then + log_write " ${head_line}" + # Othwerise, a flag was passed to this command to obfuscate domains in the log + else + # So first check if there are domains in the log that should be obfuscated + if [[ -n ${line_to_obfuscate} ]]; then + # If there are, we need to use awk to replace only the domain name (the 6th field in the log) + # so we substitue the domain for the placeholder value + obfuscated_line=$(echo ${line_to_obfuscate} | awk -v placeholder="${OBFUSCATED_PLACEHOLDER}" '{sub($6,placeholder); print $0}') + log_write " ${obfuscated_line}" + else + log_write " ${head_line}" + fi + fi + fi done log_write "" # Set the IFS back to what it was @@ -1019,17 +1071,7 @@ upload_to_tricorder() { # let the user know log_write "${INFO} Debug script running in automated mode" # and then decide again which tool to use to submit it - if command -v openssl &> /dev/null; then - # If openssl is available, use it - log_write "${INFO} Using ${COL_LIGHT_GREEN}openssl${COL_NC} for transmission." - # Save the token returned by our server in a variable - tricorder_token=$(openssl s_client -quiet -connect tricorder.pi-hole.net:${TRICORDER_SSL_PORT_NUMBER} 2> /dev/null < /dev/stdin) - else - # Otherwise, fallback to netcat - log_write "${INFO} Using ${COL_YELLOW}netcat${COL_NC} for transmission." - # Save the token returned by our server in a variable - tricorder_token=$(nc tricorder.pi-hole.net ${TRICORDER_NC_PORT_NUMBER} < /dev/stdin) - fi + tricorder_use_nc_or_ssl # If we're not running in automated mode, else echo "" diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index 71b7cecd..a4ada4c8 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -19,10 +19,9 @@ readonly PI_HOLE_FILES_DIR="/etc/.pihole" # shellcheck disable=SC2034 PH_TEST=true -# Have to ignore the following rule as spaces in paths are not supported by ShellCheck -#shellcheck disable=SC1090 +# shellcheck disable=SC1090 source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" - +# shellcheck disable=SC1091 source "/opt/pihole/COL_TABLE" # is_repo() sourced from basic-install.sh @@ -51,15 +50,15 @@ GitCheckUpdateAvail() { # defaults to the current one. REMOTE="$(git rev-parse "@{upstream}")" - if [[ ${#LOCAL} == 0 ]]; then - echo -e " ${COL_LIGHT_RED}Error: Local revision could not be obtained, ask Pi-hole support." - echo -e " Additional debugging output:${COL_NC}" + if [[ "${#LOCAL}" == 0 ]]; then + echo -e "\\n ${COL_LIGHT_RED}Error: Local revision could not be obtained, please contact Pi-hole Support + Additional debugging output:${COL_NC}" git status exit fi - if [[ ${#REMOTE} == 0 ]]; then - echo -e " ${COL_LIGHT_RED}Error: Remote revision could not be obtained, ask Pi-hole support." - echo -e " Additional debugging output:${COL_NC}" + if [[ "${#REMOTE}" == 0 ]]; then + echo -e "\\n ${COL_LIGHT_RED}Error: Remote revision could not be obtained, please contact Pi-hole Support + Additional debugging output:${COL_NC}" git status exit fi @@ -94,13 +93,15 @@ FTLcheckUpdate() { main() { local pihole_version_current local web_version_current - #shellcheck disable=1090,2154 + local basicError="\\n ${COL_LIGHT_RED}Unable to complete update, please contact Pi-hole Support${COL_NC}" + + # shellcheck disable=1090,2154 source "${setupVars}" - #This is unlikely + # This is unlikely if ! is_repo "${PI_HOLE_FILES_DIR}" ; then - echo -e " ${COL_LIGHT_RED}Critical Error: Core Pi-hole repo is missing from system!" - echo -e " Please re-run install script from https://github.com/pi-hole/pi-hole${COL_NC}" + echo -e "\\n ${COL_LIGHT_RED}Error: Core Pi-hole repo is missing from system! + Please re-run install script from https://pi-hole.net${COL_NC}" exit 1; fi @@ -108,18 +109,18 @@ main() { if GitCheckUpdateAvail "${PI_HOLE_FILES_DIR}" ; then core_update=true - echo -e " ${INFO} Pi-hole Core:\t${COL_YELLOW}update available${COL_NC}" + echo -e " ${INFO} Pi-hole Core:\\t${COL_YELLOW}update available${COL_NC}" else core_update=false - echo -e " ${INFO} Pi-hole Core:\t${COL_LIGHT_GREEN}up to date${COL_NC}" + echo -e " ${INFO} Pi-hole Core:\\t${COL_LIGHT_GREEN}up to date${COL_NC}" fi if FTLcheckUpdate ; then FTL_update=true - echo -e " ${INFO} FTL:\t\t${COL_YELLOW}update available${COL_NC}" + echo -e " ${INFO} FTL:\\t\\t${COL_YELLOW}update available${COL_NC}" else FTL_update=false - echo -e " ${INFO} FTL:\t\t${COL_LIGHT_GREEN}up to date${COL_NC}" + echo -e " ${INFO} FTL:\\t\\t${COL_LIGHT_GREEN}up to date${COL_NC}" fi # Logic: Don't update FTL when there is a core update available @@ -132,19 +133,19 @@ main() { echo "" fi - if [[ ${INSTALL_WEB} == true ]]; then + if [[ "${INSTALL_WEB}" == true ]]; then if ! is_repo "${ADMIN_INTERFACE_DIR}" ; then - echo -e " ${COL_LIGHT_RED}Critical Error: Web Admin repo is missing from system!" - echo -e " Please re-run install script from https://github.com/pi-hole/pi-hole${COL_NC}" + echo -e "\\n ${COL_LIGHT_RED}Error: Web Admin repo is missing from system! + Please re-run install script from https://pi-hole.net${COL_NC}" exit 1; fi if GitCheckUpdateAvail "${ADMIN_INTERFACE_DIR}" ; then web_update=true - echo -e " ${INFO} Web Interface:\t${COL_YELLOW}update available${COL_NC}" + echo -e " ${INFO} Web Interface:\\t${COL_YELLOW}update available${COL_NC}" else web_update=false - echo -e " ${INFO} Web Interface:\t${COL_LIGHT_GREEN}up to date${COL_NC}" + echo -e " ${INFO} Web Interface:\\t${COL_LIGHT_GREEN}up to date${COL_NC}" fi # Logic @@ -163,25 +164,24 @@ main() { echo -e " ${TICK} Everything is up to date!" exit 0 fi - elif ! ${core_update} && ${web_update} ; then echo "" echo -e " ${INFO} Pi-hole Web Admin files out of date" getGitFiles "${ADMIN_INTERFACE_DIR}" "${ADMIN_INTERFACE_GIT_URL}" - elif ${core_update} && ! ${web_update} ; then echo "" echo -e " ${INFO} Pi-hole core files out of date" getGitFiles "${PI_HOLE_FILES_DIR}" "${PI_HOLE_GIT_URL}" - ${PI_HOLE_FILES_DIR}/automated\ install/basic-install.sh --reconfigure --unattended || echo -e " ${COL_LIGHT_RED}Unable to complete update, contact Pi-hole${COL_NC}" && exit 1 - + ${PI_HOLE_FILES_DIR}/automated\ install/basic-install.sh --reconfigure --unattended || \ + echo -e "${basicError}" && exit 1 elif ${core_update} && ${web_update} ; then echo "" echo -e " ${INFO} Updating Pi-hole core and web admin files" getGitFiles "${PI_HOLE_FILES_DIR}" "${PI_HOLE_GIT_URL}" - ${PI_HOLE_FILES_DIR}/automated\ install/basic-install.sh --unattended || echo -e " ${COL_LIGHT_RED}Unable to complete update, contact Pi-hole${COL_NC}" && exit 1 + ${PI_HOLE_FILES_DIR}/automated\ install/basic-install.sh --unattended || \ + echo -e "${basicError}" && exit 1 else - echo -e " ${COL_LIGHT_RED}Update script has malfunctioned, fallthrough reached. Please contact support${COL_NC}" + echo -e " ${COL_LIGHT_RED}Update script has malfunctioned, please contact Pi-hole Support${COL_NC}" exit 1 fi else # Web Admin not installed, so only verify if core is up to date @@ -193,38 +193,36 @@ main() { fi else echo "" - echo -e " ${INFO} Pi-hole core files out of date" + echo -e " ${INFO} Pi-hole Core files out of date" getGitFiles "${PI_HOLE_FILES_DIR}" "${PI_HOLE_GIT_URL}" - ${PI_HOLE_FILES_DIR}/automated\ install/basic-install.sh --reconfigure --unattended || echo -e " ${COL_LIGHT_RED}Unable to complete update, contact Pi-hole${COL_NC}" && exit 1 + ${PI_HOLE_FILES_DIR}/automated\ install/basic-install.sh --reconfigure --unattended || \ + echo -e "${basicError}" && exit 1 fi fi if [[ "${web_update}" == true ]]; then web_version_current="$(/usr/local/bin/pihole version --admin --current)" echo "" - echo -e " ${INFO} Web Admin version is now at ${web_version_current/* v/v}" - echo -e " ${INFO} If you had made any changes in '/var/www/html/admin/', they have been stashed using 'git stash'" + echo -e " ${INFO} Web Admin version is now at ${web_version_current/* v/v} + ${INFO} If you had made any changes in '/var/www/html/admin/', they have been stashed using 'git stash'" fi if [[ "${core_update}" == true ]]; then pihole_version_current="$(/usr/local/bin/pihole version --pihole --current)" echo "" - echo -e " ${INFO} Pi-hole version is now at ${pihole_version_current/* v/v}" - echo -e " ${INFO} If you had made any changes in '/etc/.pihole/', they have been stashed using 'git stash'" + echo -e " ${INFO} Pi-hole version is now at ${pihole_version_current/* v/v} + ${INFO} If you had made any changes in '/etc/.pihole/', they have been stashed using 'git stash'" fi - if [[ ${FTL_update} == true ]]; then + if [[ "${FTL_update}" == true ]]; then FTL_version_current="$(/usr/bin/pihole-FTL tag)" - echo "" - echo -e " ${INFO} FTL version is now at ${FTL_version_current/* v/v}" + echo -e "\\n ${INFO} FTL version is now at ${FTL_version_current/* v/v}" start_service pihole-FTL enable_service pihole-FTL fi - echo "" exit 0 - } main diff --git a/advanced/Scripts/webpage.sh b/advanced/Scripts/webpage.sh index 5aae18f7..9d101482 100755 --- a/advanced/Scripts/webpage.sh +++ b/advanced/Scripts/webpage.sh @@ -29,6 +29,7 @@ Options: -c, celsius Set Celsius as preferred temperature unit -f, fahrenheit Set Fahrenheit as preferred temperature unit -k, kelvin Set Kelvin as preferred temperature unit + -r, hostrecord Add a name to the DNS associated to an IPv4/IPv6 address -h, --help Show this help dialog -i, interface Specify dnsmasq's interface listening behavior Add '-h' for more info on interface usage" @@ -221,18 +222,19 @@ Reboot() { } RestartDNS() { - local str="Restarting dnsmasq" - echo -ne " ${INFO} ${str}..." - if [[ -x "$(command -v systemctl)" ]]; then - systemctl restart dnsmasq + local str="Restarting DNS service" + [[ -t 1 ]] && echo -ne " ${INFO} ${str}" + if command -v systemctl &> /dev/null; then + output=$( { systemctl restart dnsmasq; } 2>&1 ) else - service dnsmasq restart + output=$( { service dnsmasq restart; } 2>&1 ) fi - if [[ "$?" == 0 ]]; then - echo -e "${OVER} ${TICK} ${str}" + if [[ -z "${output}" ]]; then + [[ -t 1 ]] && echo -e "${OVER} ${TICK} ${str}" else - echo -e "${OVER} ${CROSS} ${str}" + [[ ! -t 1 ]] && OVER="" + echo -e "${OVER} ${CROSS} ${output}" fi } @@ -291,7 +293,9 @@ ra-param=*,0,0 fi else - rm "${dhcpconfig}" &> /dev/null + if [[ -f "${dhcpconfig}" ]]; then + rm "${dhcpconfig}" &> /dev/null + fi fi } @@ -389,12 +393,23 @@ RemoveDHCPStaticAddress() { } SetHostRecord() { - if [ -n "${args[3]}" ]; then + if [[ "${1}" == "-h" ]] || [[ "${1}" == "--help" ]]; then + echo "Usage: pihole -a hostrecord [IPv4-address],[IPv6-address] +Example: 'pihole -a hostrecord home.domain.com 192.168.1.1,2001:db8:a0b:12f0::1' +Add a name to the DNS associated to an IPv4/IPv6 address + +Options: + \"\" Empty: Remove host record + -h, --help Show this help dialog" + exit 0 + fi + + if [[ -n "${args[3]}" ]]; then change_setting "HOSTRECORD" "${args[2]},${args[3]}" - echo "Setting host record for ${args[2]} -> ${args[3]}" + echo -e " ${TICK} Setting host record for ${args[2]} to ${args[3]}" else change_setting "HOSTRECORD" "" - echo "Removing host record" + echo -e " ${TICK} Removing host record" fi ProcessDNSSettings @@ -471,7 +486,7 @@ main() { "resolve" ) ResolutionSettings;; "addstaticdhcp" ) AddDHCPStaticAddress;; "removestaticdhcp" ) RemoveDHCPStaticAddress;; - "hostrecord" ) SetHostRecord;; + "-r" | "hostrecord" ) SetHostRecord "$3";; "-i" | "interface" ) SetListeningMode "$@";; "-t" | "teleporter" ) Teleporter;; "adlist" ) CustomizeAdLists;; diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 74e2a61d..4047502b 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1,22 +1,21 @@ #!/usr/bin/env bash +# shellcheck disable=SC1090 + # Pi-hole: A black hole for Internet advertisements # (c) 2017 Pi-hole, LLC (https://pi-hole.net) # Network-wide ad blocking via your own hardware. # -# Installs Pi-hole +# Installs and Updates Pi-hole # # This file is copyright under the latest version of the EUPL. # Please see LICENSE file for your rights under this license. - - # pi-hole.net/donate # # Install with this command (from your Linux machine): # # curl -L install.pi-hole.net | bash - # -e option instructs bash to immediately exit if any command [1] has a non-zero exit status # We do not want users to end up with a partially working install, so we exit the script # instead of continuing the installation with something broken @@ -35,6 +34,7 @@ instalLogLoc=/etc/pihole/install.log # This is an important file as it contains information specific to the machine it's being installed on setupVars=/etc/pihole/setupVars.conf # Pi-hole uses lighttpd as a Web server, and this is the config file for it +# shellcheck disable=SC2034 lighttpdConfig=/etc/lighttpd/lighttpd.conf # This is a file used for the colorized output coltable=/opt/pihole/COL_TABLE @@ -79,7 +79,7 @@ reconfigure=false runUnattended=false # If the color table file exists, -if [[ -f ${coltable} ]]; then +if [[ -f "${coltable}" ]]; then # source it source ${coltable} # Othwerise, @@ -91,8 +91,9 @@ else TICK="[${COL_LIGHT_GREEN}✓${COL_NC}]" CROSS="[${COL_LIGHT_RED}✗${COL_NC}]" INFO="[i]" + # shellcheck disable=SC2034 DONE="${COL_LIGHT_GREEN} done!${COL_NC}" - OVER="\r\033[K" + OVER="\\r\\033[K" fi # A simple function that just echoes out our logo in ASCII format @@ -122,7 +123,6 @@ show_ascii_berry() { " } - # Compatibility distro_check() { # If apt-get is installed, then we know it's part of the Debian family @@ -321,13 +321,13 @@ getGitFiles() { # Show that we're checking it echo -e "${OVER} ${TICK} ${str}" # Update the repo, returning an error message on failure - update_repo "${directory}" || { echo -e "\n ${COL_LIGHT_RED}Error: Could not update local repository. Contact support.${COL_NC}"; exit 1; } + update_repo "${directory}" || { echo -e "\\n ${COL_LIGHT_RED}Error: Could not update local repository. Contact support.${COL_NC}"; exit 1; } # If it's not a .git repo, else # Show an error echo -e "${OVER} ${CROSS} ${str}" # Attempt to make the repository, showing an error on falure - make_repo "${directory}" "${remoteRepo}" || { echo -e "\n ${COL_LIGHT_RED}Error: Could not update local repository. Contact support.${COL_NC}"; exit 1; } + make_repo "${directory}" "${remoteRepo}" || { echo -e "\\n ${COL_LIGHT_RED}Error: Could not update local repository. Contact support.${COL_NC}"; exit 1; } fi # echo a blank line echo "" @@ -380,13 +380,13 @@ get_available_interfaces() { # A function for displaying the dialogs the user sees when first running the installer welcomeDialogs() { # Display the welcome dialog using an approriately sized window via the calculation conducted earlier in the script - whiptail --msgbox --backtitle "Welcome" --title "Pi-hole automated installer" "\n\nThis installer will transform your device into a network-wide ad blocker!" ${r} ${c} + whiptail --msgbox --backtitle "Welcome" --title "Pi-hole automated installer" "\\n\\nThis installer will transform your device into a network-wide ad blocker!" ${r} ${c} # Request that users donate if they enjoy the software since we all work on it in our free time - whiptail --msgbox --backtitle "Plea" --title "Free and open source" "\n\nThe Pi-hole is free, but powered by your donations: http://pi-hole.net/donate" ${r} ${c} + whiptail --msgbox --backtitle "Plea" --title "Free and open source" "\\n\\nThe Pi-hole is free, but powered by your donations: http://pi-hole.net/donate" ${r} ${c} # Explain the need for a static address - whiptail --msgbox --backtitle "Initiating network interface" --title "Static IP Needed" "\n\nThe Pi-hole is a SERVER so it needs a STATIC IP ADDRESS to function properly. + whiptail --msgbox --backtitle "Initiating network interface" --title "Static IP Needed" "\\n\\nThe Pi-hole is a SERVER so it needs a STATIC IP ADDRESS to function properly. In the next section, you can choose to use your current network settings (DHCP) or to manually edit them." ${r} ${c} } @@ -400,7 +400,8 @@ verifyFreeDiskSpace() { # Reqired space in KB local required_free_kilobytes=51200 # Calculate existing free space on this machine - local existing_free_kilobytes=$(df -Pk | grep -m1 '\/$' | awk '{print $4}') + local existing_free_kilobytes + existing_free_kilobytes=$(df -Pk | grep -m1 '\/$' | awk '{print $4}') # If the existing space is not an integer, if ! [[ "${existing_free_kilobytes}" =~ ^([0-9])+$ ]]; then @@ -414,7 +415,7 @@ verifyFreeDiskSpace() { # exit with an error code exit 1 # If there is insufficient free disk space, - elif [[ ${existing_free_kilobytes} -lt ${required_free_kilobytes} ]]; then + elif [[ "${existing_free_kilobytes}" -lt "${required_free_kilobytes}" ]]; then # show an error message echo -e " ${CROSS} ${str} Your system disk appears to only have ${existing_free_kilobytes} KB free @@ -428,7 +429,7 @@ verifyFreeDiskSpace() { e.g: curl -L https://install.pi-hole.net | bash" fi # Show there is not enough free space - echo -e "\n ${COL_LIGHT_RED}Insufficient free space, exiting...${COL_NC}" + echo -e "\\n ${COL_LIGHT_RED}Insufficient free space, exiting...${COL_NC}" # and exit with an error exit 1 # Otherwise, @@ -455,7 +456,7 @@ chooseInterface() { interfaceCount=$(echo "${availableInterfaces}" | wc -l) # If there is one interface, - if [[ ${interfaceCount} -eq 1 ]]; then + if [[ "${interfaceCount}" -eq 1 ]]; then # Set it as the interface to use since there is no other option PIHOLE_INTERFACE="${availableInterfaces}" # Otherwise, @@ -465,7 +466,7 @@ chooseInterface() { # use a variable to set the option as OFF to begin with mode="OFF" # If it's the first loop, - if [[ ${firstLoop} -eq 1 ]]; then + if [[ "${firstLoop}" -eq 1 ]]; then # set this as the interface to use (ON) firstLoop=0 mode="ON" @@ -501,11 +502,11 @@ testIPv6() { # will contain 162 which is the decimal value corresponding to 0xa2 value2=$(((0x$first)%256)) # the ULA test is testing for fc00::/7 according to RFC 4193 - ((($value1&254)==252)) && echo "ULA" || true + (((value1&254)==252)) && echo "ULA" || true # the GUA test is testing for 2000::/3 according to RFC 4291 - ((($value1&112)==32)) && echo "GUA" || true + (((value1&112)==32)) && echo "GUA" || true # the LL test is testing for fe80::/10 according to RFC 4193 - ((($value1==254) && (($value2&192)==128))) && echo "Link-local" || true + (((value1==254) && ((value2&192)==128))) && echo "Link-local" || true } # A dialog for showing the user about IPv6 blocking @@ -529,17 +530,17 @@ useIPv6dialog() { # set the IPv6 address to the ULA address IPV6_ADDRESS="${ULA_ADDRESS}" # Show this info to the user - echo "::: Found IPv6 ULA address, using it for blocking IPv6 ads" + echo -e " ${INFO} Found IPv6 ULA address, using it for blocking IPv6 ads" # Otherwise, if the GUA_ADDRESS has a value, elif [[ ! -z "${GUA_ADDRESS}" ]]; then # Let the user know - echo "::: Found IPv6 GUA address, using it for blocking IPv6 ads" + echo -e " ${INFO} Found IPv6 GUA address, using it for blocking IPv6 ads" # And assign it to the global variable IPV6_ADDRESS="${GUA_ADDRESS}" # If none of those work, else # explain that IPv6 blocking will not be used - echo "::: Found neither IPv6 ULA nor GUA address, blocking IPv6 ads will not be enabled" + echo -e " ${INFO} Unable to find IPv6 ULA/GUA address, IPv6 adblocking will not be enabled" # So set the variable to be empty IPV6_ADDRESS="" fi @@ -575,14 +576,14 @@ use4andor6() { esac done # If IPv4 is to be used, - if [[ ${useIPv4} ]]; then + if [[ "${useIPv4}" ]]; then # Run our function to get the information we need find_IPv4_information getStaticIPv4Settings setStaticIPv4 fi # If IPv6 is to be used, - if [[ ${useIPv6} ]]; then + if [[ "${useIPv6}" ]]; then # Run our function to get this information useIPv6dialog fi @@ -590,7 +591,7 @@ use4andor6() { echo -e " ${INFO} IPv4 address: ${IPV4_ADDRESS}" echo -e " ${INFO} IPv6 address: ${IPV6_ADDRESS}" # If neither protocol is selected, - if [ ! ${useIPv4} ] && [ ! ${useIPv6} ]; then + if [[ ! "${useIPv4}" ]] && [[ ! "${useIPv6}" ]]; then # Show an error in red echo -e " ${COL_LIGHT_RED}Error: Neither IPv4 or IPv6 selected${COL_NC}" # and exit with an error @@ -616,7 +617,7 @@ It is also possible to use a DHCP reservation, but if you are going to do that, # Otherwise, we need to ask the user to input their desired settings. # Start by getting the IPv4 address (pre-filling it with info gathered from DHCP) # Start a loop to let the user enter their information with the chance to go back and edit it if necessary - until [[ ${ipSettingsCorrect} = True ]]; do + until [[ "${ipSettingsCorrect}" = True ]]; do # Ask for the IPv4 address IPV4_ADDRESS=$(whiptail --backtitle "Calibrating network interface" --title "IPv4 address" --inputbox "Enter your desired IPv4 address" ${r} ${c} "${IPV4_ADDRESS}" 3>&1 1>&2 2>&3) || \ @@ -660,7 +661,7 @@ setStaticIPv4() { local IPADDR local CIDR # For the Debian family, if dhcpcd.conf exists, - if [[ -f /etc/dhcpcd.conf ]]; then + if [[ -f "/etc/dhcpcd.conf" ]]; then # check if the IP is already in the file if grep -q "${IPV4_ADDRESS}" /etc/dhcpcd.conf; then echo -e " ${INFO} Static IP already configured" @@ -672,10 +673,10 @@ setStaticIPv4() { ip addr replace dev "${PIHOLE_INTERFACE}" "${IPV4_ADDRESS}" # Also give a warning that the user may need to reboot their system echo -e " ${TICK} Set IP address to ${IPV4_ADDRESS%/*} - You may need to restart after the install is complete" + You may need to restart after the install is complete" fi # If it's not Debian, check if it's the Fedora family by checking for the file below - elif [[ -f /etc/sysconfig/network-scripts/ifcfg-${PIHOLE_INTERFACE} ]];then + elif [[ -f "/etc/sysconfig/network-scripts/ifcfg-${PIHOLE_INTERFACE}" ]];then # If it exists, IFCFG_FILE=/etc/sysconfig/network-scripts/ifcfg-${PIHOLE_INTERFACE} # check if the desired IP is already set @@ -710,7 +711,7 @@ setStaticIPv4() { fi # Show a warning that the user may need to restart echo -e " ${TICK} Set IP address to ${IPV4_ADDRESS%/*} - You may need to restart after the install is complete" + You may need to restart after the install is complete" fi # If all that fails, else @@ -727,7 +728,7 @@ valid_ip() { local stat=1 # If the IP matches the format xxx.xxx.xxx.xxx, - if [[ ${ip} =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then + if [[ "${ip}" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then # Save the old Interfal Field Separator in a variable OIFS=$IFS # and set the new one to a dot (period) @@ -737,8 +738,8 @@ valid_ip() { # Restore the IFS to what it was IFS=${OIFS} ## Evaluate each octet by checking if it's less than or equal to 255 (the max for each octet) - [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \ - && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]] + [[ "${ip[0]}" -le 255 && "${ip[1]}" -le 255 \ + && "${ip[2]}" -le 255 && "${ip[3]}" -le 255 ]] # Save the exit code stat=$? fi @@ -801,13 +802,13 @@ setDNS() { ;; Custom) # Until the DNS settings are selected, - until [[ ${DNSSettingsCorrect} = True ]]; do + until [[ "${DNSSettingsCorrect}" = True ]]; do # strInvalid="Invalid" # If the first - if [ ! ${PIHOLE_DNS_1} ]; then + if [[ ! "${PIHOLE_DNS_1}" ]]; then # and second upstream servers do not exist - if [ ! ${PIHOLE_DNS_2} ]; then + if [[ ! "${PIHOLE_DNS_2}" ]]; then # prePopulate="" # Otherwise, @@ -816,39 +817,39 @@ setDNS() { prePopulate=", ${PIHOLE_DNS_2}" fi # - elif [ ${PIHOLE_DNS_1} ] && [ ! ${PIHOLE_DNS_2} ]; then + elif [[ "${PIHOLE_DNS_1}" ]] && [[ ! "${PIHOLE_DNS_2}" ]]; then # prePopulate="${PIHOLE_DNS_1}" # - elif [ ${PIHOLE_DNS_1} ] && [ ${PIHOLE_DNS_2} ]; then + elif [[ "${PIHOLE_DNS_1}" ]] && [[ "${PIHOLE_DNS_2}" ]]; then # prePopulate="${PIHOLE_DNS_1}, ${PIHOLE_DNS_2}" fi # Dialog for the user to enter custom upstream servers - piholeDNS=$(whiptail --backtitle "Specify Upstream DNS Provider(s)" --inputbox "Enter your desired upstream DNS provider(s), seperated by a comma.\n\nFor example '8.8.8.8, 8.8.4.4'" ${r} ${c} "${prePopulate}" 3>&1 1>&2 2>&3) || \ + piholeDNS=$(whiptail --backtitle "Specify Upstream DNS Provider(s)" --inputbox "Enter your desired upstream DNS provider(s), seperated by a comma.\\n\\nFor example '8.8.8.8, 8.8.4.4'" ${r} ${c} "${prePopulate}" 3>&1 1>&2 2>&3) || \ { echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; } # PIHOLE_DNS_1=$(echo "${piholeDNS}" | sed 's/[, \t]\+/,/g' | awk -F, '{print$1}') PIHOLE_DNS_2=$(echo "${piholeDNS}" | sed 's/[, \t]\+/,/g' | awk -F, '{print$2}') # If the IP is valid, - if ! valid_ip "${PIHOLE_DNS_1}" || [ ! "${PIHOLE_DNS_1}" ]; then + if ! valid_ip "${PIHOLE_DNS_1}" || [[ ! "${PIHOLE_DNS_1}" ]]; then # store it in the variable so we can use it PIHOLE_DNS_1=${strInvalid} fi # Do the same for the secondary server - if ! valid_ip "${PIHOLE_DNS_2}" && [ "${PIHOLE_DNS_2}" ]; then + if ! valid_ip "${PIHOLE_DNS_2}" && [[ "${PIHOLE_DNS_2}" ]]; then PIHOLE_DNS_2=${strInvalid} fi # If either of the DNS servers are invalid, - if [[ ${PIHOLE_DNS_1} == "${strInvalid}" ]] || [[ ${PIHOLE_DNS_2} == "${strInvalid}" ]]; then + if [[ "${PIHOLE_DNS_1}" == "${strInvalid}" ]] || [[ "${PIHOLE_DNS_2}" == "${strInvalid}" ]]; then # explain this to the user - whiptail --msgbox --backtitle "Invalid IP" --title "Invalid IP" "One or both entered IP addresses were invalid. Please try again.\n\n DNS Server 1: $PIHOLE_DNS_1\n DNS Server 2: ${PIHOLE_DNS_2}" ${r} ${c} + whiptail --msgbox --backtitle "Invalid IP" --title "Invalid IP" "One or both entered IP addresses were invalid. Please try again.\\n\\n DNS Server 1: $PIHOLE_DNS_1\\n DNS Server 2: ${PIHOLE_DNS_2}" ${r} ${c} # and set the variables back to nothing - if [[ ${PIHOLE_DNS_1} == "${strInvalid}" ]]; then + if [[ "${PIHOLE_DNS_1}" == "${strInvalid}" ]]; then PIHOLE_DNS_1="" fi - if [[ ${PIHOLE_DNS_2} == "${strInvalid}" ]]; then + if [[ "${PIHOLE_DNS_2}" == "${strInvalid}" ]]; then PIHOLE_DNS_2="" fi # Since the settings will not work, stay in the loop @@ -856,7 +857,7 @@ setDNS() { # Othwerise, else # Show the settings - if (whiptail --backtitle "Specify Upstream DNS Provider(s)" --title "Upstream DNS Provider(s)" --yesno "Are these settings correct?\n DNS Server 1: $PIHOLE_DNS_1\n DNS Server 2: ${PIHOLE_DNS_2}" ${r} ${c}); then + if (whiptail --backtitle "Specify Upstream DNS Provider(s)" --title "Upstream DNS Provider(s)" --yesno "Are these settings correct?\\n DNS Server 1: $PIHOLE_DNS_1\\n DNS Server 2: ${PIHOLE_DNS_2}" ${r} ${c}); then # and break from the loop since the servers are vaid DNSSettingsCorrect=True # Otherwise, @@ -878,7 +879,7 @@ setLogging() { local LogChoices # Ask if the user wants to log queries - LogToggleCommand=(whiptail --separate-output --radiolist "Do you want to log queries?\n (Disabling will render graphs on the Admin page useless):" ${r} ${c} 6) + LogToggleCommand=(whiptail --separate-output --radiolist "Do you want to log queries?\\n (Disabling will render graphs on the Admin page useless):" ${r} ${c} 6) # The default selection is on LogChooseOptions=("On (Recommended)" "" on Off "" off) @@ -916,12 +917,12 @@ setAdminFlag() { # Depending on their choice case ${WebChoices} in "On (Recommended)") - echo -e " ${INFO} Web Interface On." + echo -e " ${INFO} Web Interface On" # Set it to true INSTALL_WEB=true ;; Off) - echo -e " ${INFO} Web Interface off." + echo -e " ${INFO} Web Interface Off" # or false INSTALL_WEB=false ;; @@ -939,7 +940,7 @@ version_check_dnsmasq() { local dnsmasq_pihole_01_location="/etc/dnsmasq.d/01-pihole.conf" # If the dnsmasq config file exists - if [ -f ${dnsmasq_conf} ]; then + if [[ -f "${dnsmasq_conf}" ]]; then echo -ne " ${INFO} Existing dnsmasq.conf found..." # If gravity.list is found within this file, we presume it's from older versions on Pi-hole, if grep -q ${dnsmasq_pihole_id_string} ${dnsmasq_conf}; then @@ -1048,8 +1049,8 @@ installScripts() { # Otherwise, else # Show an error and exit - echo -e "${OVER} ${CROSS} ${str}" - echo -e " ${COL_LIGHT_RED}Error: Local repo ${PI_HOLE_LOCAL_REPO} not found, exiting installer${COL_NC}" + echo -e "${OVER} ${CROSS} ${str} + ${COL_LIGHT_RED}Error: Local repo ${PI_HOLE_LOCAL_REPO} not found, exiting installer${COL_NC}" exit 1 fi } @@ -1062,15 +1063,15 @@ installConfigs() { version_check_dnsmasq # If the user chose to install the dashboard, - if [[ ${INSTALL_WEB} == true ]]; then + if [[ "${INSTALL_WEB}" == true ]]; then # and if the Web server conf directory does not exist, - if [ ! -d "/etc/lighttpd" ]; then + if [[ ! -d "/etc/lighttpd" ]]; then # make it mkdir /etc/lighttpd # and set the owners chown "${USER}":root /etc/lighttpd # Otherwise, if the config file already exists - elif [ -f "/etc/lighttpd/lighttpd.conf" ]; then + elif [[ -f "/etc/lighttpd/lighttpd.conf" ]]; then # back up the original mv /etc/lighttpd/lighttpd.conf /etc/lighttpd/lighttpd.conf.orig fi @@ -1164,16 +1165,13 @@ update_package_cache() { notify_package_updates_available() { # Local, named variables local str="Checking ${PKG_MANAGER} for upgraded packages" - echo "" - echo -ne " ${INFO} ${str}..." + echo -ne "\\n ${INFO} ${str}..." # Store the list of packages in a variable updatesToInstall=$(eval "${PKG_COUNT}") - #echo -e "\r\033[K ${TICK} ${str}" - #echo "" - # + if [[ -d "/lib/modules/$(uname -r)" ]]; then # - if [[ ${updatesToInstall} -eq "0" ]]; then + if [[ "${updatesToInstall}" -eq 0 ]]; then # echo -e "${OVER} ${TICK} ${str}... up to date!" echo "" @@ -1184,10 +1182,8 @@ notify_package_updates_available() { echo "" fi else - # echo -e "${OVER} ${CROSS} ${str} - Kernel update detected. If the install fails, please reboot and try again" - echo "" + Kernel update detected. If the install fails, please reboot and try again\\n" fi } @@ -1199,7 +1195,7 @@ install_dependent_packages() { # Add one to the counter counter=$((counter+1)) # If it equals 1, - if [ ${counter} == 1 ]; then + if [[ "${counter}" == 1 ]]; then # echo -e " ${INFO} Installer Dependency checks..." else @@ -1233,7 +1229,7 @@ install_dependent_packages() { fi done # - if [[ ${#installArray[@]} -gt 0 ]]; then + if [[ "${#installArray[@]}" -gt 0 ]]; then # test_dpkg_lock # @@ -1258,7 +1254,7 @@ install_dependent_packages() { fi done # - if [[ ${#installArray[@]} -gt 0 ]]; then + if [[ "${#installArray[@]}" -gt 0 ]]; then # "${PKG_INSTALL[@]}" "${installArray[@]}" &> /dev/null return @@ -1273,7 +1269,7 @@ CreateLogFile() { echo "" echo -ne " ${INFO} ${str}..." # If the pihole log does not exist, - if [ ! -f /var/log/pihole.log ]; then + if [[ ! -f "/var/log/pihole.log" ]]; then # Make it, touch /var/log/pihole.log # set the permissions, @@ -1293,11 +1289,11 @@ installPiholeWeb() { echo "" echo " ${INFO} Installing blocking page..." # If the pihole Web directory exists, - if [ -d "/var/www/html/pihole" ]; then + if [[ -d "/var/www/html/pihole" ]]; then local str="Installing index.php" echo -ne " ${INFO} ${str}..." # and if the index file exists, - if [ -f "/var/www/html/pihole/index.php" ]; then + if [[ -f "/var/www/html/pihole/index.php" ]]; then # do not overwrite it, echo -e " ${COL_LIGHT_GREEN}detected index.php, not overwriting${COL_NC}" # if it doesn't exist @@ -1310,7 +1306,7 @@ installPiholeWeb() { local str="Installing index.js" echo -ne " ${INFO} ${str}..." # and if the index file exists, - if [ -f "/var/www/html/pihole/index.js" ]; then + if [[ -f "/var/www/html/pihole/index.js" ]]; then # do not overwrite it, echo -e " ${COL_LIGHT_GREEN}detected index.js, not overwriting${COL_NC}" else @@ -1322,7 +1318,7 @@ installPiholeWeb() { local str="Installing blockingpage.css" echo -ne " ${INFO} ${str}..." # and if the index file exists, - if [ -f "/var/www/html/pihole/blockingpage.css" ]; then + if [[ -f "/var/www/html/pihole/blockingpage.css" ]]; then # do not overwrite it, echo -e " ${COL_LIGHT_GREEN}detected blockingpage.css, not overwriting${COL_NC}" else @@ -1343,15 +1339,15 @@ installPiholeWeb() { local str="Backing up index.lighttpd.html" echo -ne " ${INFO} ${str}..." # If the default index file exists, - if [ -f /var/www/html/index.lighttpd.html ]; then + if [[ -f "/var/www/html/index.lighttpd.html" ]]; then # back it up mv /var/www/html/index.lighttpd.html /var/www/html/index.lighttpd.orig echo -e "${OVER} ${TICK} ${str}" # Othwerwise, else # don't do anything - echo -e "${OVER} ${CROSS} ${str}" - echo -e " No default index.lighttpd.html file found... not backing up" + echo -e "${OVER} ${CROSS} ${str} + No default index.lighttpd.html file found... not backing up" fi fi @@ -1435,9 +1431,9 @@ configureFirewall() { # If a firewall is running, if firewall-cmd --state &> /dev/null; then # ask if the user wants to install Pi-hole's default firwall rules - whiptail --title "Firewall in use" --yesno "We have detected a running firewall\n\nPi-hole currently requires HTTP and DNS port access.\n\n\n\nInstall Pi-hole default firewall rules?" ${r} ${c} || \ + whiptail --title "Firewall in use" --yesno "We have detected a running firewall\\n\\nPi-hole currently requires HTTP and DNS port access.\\n\\n\\n\\nInstall Pi-hole default firewall rules?" ${r} ${c} || \ { echo -e " ${INFO} Not installing firewall rulesets."; return 0; } - echo -e " ${TICK} Configuring FirewallD for httpd and dnsmasq." + echo -e " ${TICK} Configuring FirewallD for httpd and dnsmasq" # Allow HTTP and DNS traffice firewall-cmd --permanent --add-service=http --add-service=dns # Reload the firewall to apply these changes @@ -1448,9 +1444,9 @@ configureFirewall() { # If chain Policy is not ACCEPT or last Rule is not ACCEPT # then check and insert our Rules above the DROP/REJECT Rule. if iptables -S INPUT | head -n1 | grep -qv '^-P.*ACCEPT$' || iptables -S INPUT | tail -n1 | grep -qv '^-\(A\|P\).*ACCEPT$'; then - whiptail --title "Firewall in use" --yesno "We have detected a running firewall\n\nPi-hole currently requires HTTP and DNS port access.\n\n\n\nInstall Pi-hole default firewall rules?" ${r} ${c} || \ + whiptail --title "Firewall in use" --yesno "We have detected a running firewall\\n\\nPi-hole currently requires HTTP and DNS port access.\\n\\n\\n\\nInstall Pi-hole default firewall rules?" ${r} ${c} || \ { echo -e " ${INFO} Not installing firewall rulesets."; return 0; } - echo -e " ${TICK} Installing new IPTables firewall rulesets." + echo -e " ${TICK} Installing new IPTables firewall rulesets" # Check chain first, otherwise a new rule will duplicate old ones iptables -C INPUT -p tcp -m tcp --dport 80 -j ACCEPT &> /dev/null || iptables -I INPUT 1 -p tcp -m tcp --dport 80 -j ACCEPT iptables -C INPUT -p tcp -m tcp --dport 53 -j ACCEPT &> /dev/null || iptables -I INPUT 1 -p tcp -m tcp --dport 53 -j ACCEPT @@ -1461,30 +1457,30 @@ configureFirewall() { # Othwerwise, else # no firewall is running - echo -e " ${INFO} No active firewall detected.. skipping firewall configuration." + echo -e " ${INFO} No active firewall detected.. skipping firewall configuration" # so just exit return 0 fi - echo -e " ${INFO} Skipping firewall configuration." + echo -e " ${INFO} Skipping firewall configuration" } # finalExports() { # If the Web interface is not set to be installed, - if [[ ${INSTALL_WEB} == false ]]; then + if [[ "${INSTALL_WEB}" == false ]]; then # and if there is not an IPv4 address, - if [ ${IPV4_ADDRESS} ]; then + if [[ "${IPV4_ADDRESS}" ]]; then # there is no block page, so set IPv4 to 0.0.0.0 (all IP addresses) IPV4_ADDRESS="0.0.0.0" fi - if [ ${IPV6_ADDRESS} ]; then + if [[ "${IPV6_ADDRESS}" ]]; then # and IPv6 to ::/0 IPV6_ADDRESS="::/0" fi fi # If the setup variable file exists, - if [ -e "${setupVars}" ]; then + if [[ -e "${setupVars}" ]]; then # update the variables in the file sed -i.update.bak '/PIHOLE_INTERFACE/d;/IPV4_ADDRESS/d;/IPV6_ADDRESS/d;/PIHOLE_DNS_1/d;/PIHOLE_DNS_2/d;/QUERY_LOGGING/d;/INSTALL_WEB/d;' "${setupVars}" fi @@ -1497,24 +1493,18 @@ finalExports() { echo "PIHOLE_DNS_2=${PIHOLE_DNS_2}" echo "QUERY_LOGGING=${QUERY_LOGGING}" echo "INSTALL_WEB=${INSTALL_WEB}" + echo "LIGHTTPD_ENABLED=${LIGHTTPD_ENABLED}" }>> "${setupVars}" - # Look for DNS server settings which would have to be reapplied + # Bring in the current settings and the functions to manipulate them source "${setupVars}" - # source "${PI_HOLE_LOCAL_REPO}/advanced/Scripts/webpage.sh" - # - if [[ "${DNS_FQDN_REQUIRED}" != "" ]] ; then - # - ProcessDNSSettings - fi + # Look for DNS server settings which would have to be reapplied + ProcessDNSSettings - # - if [[ "${DHCP_ACTIVE}" != "" ]] ; then - # - ProcessDHCPSettings - fi + # Look for DHCP server settings which would have to be reapplied + ProcessDHCPSettings } # Install the logrotate script @@ -1533,7 +1523,7 @@ installLogrotate() { # the local properties of the /var/log directory logusergroup="$(stat -c '%U %G' /var/log)" # If the variable has a value, - if [[ ! -z $logusergroup ]]; then + if [[ ! -z "${logusergroup}" ]]; then # sed -i "s/# su #/su ${logusergroup}/g;" /etc/pihole/logrotate fi @@ -1546,8 +1536,8 @@ installPihole() { create_pihole_user # If the user wants to install the Web interface, - if [[ ${INSTALL_WEB} == true ]]; then - if [ ! -d "/var/www/html" ]; then + if [[ "${INSTALL_WEB}" == true ]]; then + if [[ ! -d "/var/www/html" ]]; then # make the Web directory if necessary mkdir -p /var/www/html fi @@ -1557,13 +1547,13 @@ installPihole() { # Give pihole access to the Web server group usermod -a -G ${LIGHTTPD_GROUP} pihole # If the lighttpd command is executable, - if [ -x "$(command -v lighty-enable-mod)" ]; then + if [[ -x "$(command -v lighty-enable-mod)" ]]; then # enable fastcgi and fastcgi-php lighty-enable-mod fastcgi fastcgi-php > /dev/null || true else # Othweise, show info about installing them echo -e " ${INFO} Warning: 'lighty-enable-mod' utility not found - Please ensure fastcgi is enabled if you experience issues\n" + Please ensure fastcgi is enabled if you experience issues\\n" fi fi # Install scripts, @@ -1573,7 +1563,7 @@ installPihole() { # and create the log file CreateLogFile # If the user wants to install the dashboard, - if [[ ${INSTALL_WEB} == true ]]; then + if [[ "${INSTALL_WEB}" == true ]]; then # do so installPiholeWeb fi @@ -1582,12 +1572,12 @@ installPihole() { # Install the logrotate file installLogrotate # Check if FTL is installed - FTLdetect || echo -e " ${CROSS} FTL Engine not installed." + FTLdetect || echo -e " ${CROSS} FTL Engine not installed" # Configure the firewall configureFirewall - # Run the final exports + + #update setupvars.conf with any variables that may or may not have been changed during the install finalExports - #runGravity } # At some point in the future this list can be pruned, for now we'll need it to ensure updates don't break. @@ -1611,7 +1601,7 @@ updatePihole() { # Create the log file CreateLogFile # If the user wants to install the dasboard, - if [[ ${INSTALL_WEB} == true ]]; then + if [[ "${INSTALL_WEB}" == true ]]; then # do so installPiholeWeb fi @@ -1621,8 +1611,10 @@ updatePihole() { installLogrotate # Detect if FTL is installed FTLdetect || echo -e " ${CROSS} FTL Engine not installed." - finalExports #re-export setupVars.conf to account for any new vars added in new versions - #runGravity + + #update setupvars.conf with any variables that may or may not have been changed during the install + finalExports + } @@ -1630,19 +1622,17 @@ updatePihole() { checkSelinux() { # If the getenforce command exists, if command -v getenforce &> /dev/null; then - echo "" - echo -ne " ${INFO} SELinux Support Detected... Mode: " # Store the current mode in a variable enforceMode=$(getenforce) - echo "${enforceMode}" + echo -e "\\n ${INFO} SELinux mode detected: ${enforceMode}" + # If it's enforcing, if [[ "${enforceMode}" == "Enforcing" ]]; then # Explain Pi-hole does not support it yet - whiptail --title "SELinux Enforcing Detected" --yesno "SELinux is being Enforced on your system!\n\nPi-hole currently does not support SELinux, but you may still continue with the installation.\n\nNote: Admin UI Will not function fully without setting your policies correctly\n\nContinue installing Pi-hole?" ${r} ${c} || \ - { echo ""; echo -e " ${COL_LIGHT_RED}SELinux Enforcing detected, exiting installer${COL_NC}"; exit 1; } - echo "" - echo -e " ${INFO} Continuing installation with SELinux Enforcing" - echo -e " ${INFO} Please refer to official SELinux documentation to create a custom policy" + whiptail --defaultno --title "SELinux Enforcing Detected" --yesno "SELinux is being ENFORCED on your system! \\n\\nPi-hole currently does not support SELinux, but you may still continue with the installation.\\n\\nNote: Web Admin will not be fully functional unless you set your policies correctly\\n\\nContinue installing Pi-hole?" ${r} ${c} || \ + { echo -e "\\n ${COL_LIGHT_RED}SELinux Enforcing detected, exiting installer${COL_NC}"; exit 1; } + echo -e " ${INFO} Continuing installation with SELinux Enforcing + ${INFO} Please refer to official SELinux documentation to create a custom policy" fi fi } @@ -1650,7 +1640,7 @@ checkSelinux() { # Installation complete message with instructions for the user displayFinalMessage() { # If - if [[ ${#1} -gt 0 ]] ; then + if [[ "${#1}" -gt 0 ]] ; then pwstring="$1" # else, if the dashboard password in the setup variables exists, elif [[ $(grep 'WEBPASSWORD' -c /etc/pihole/setupVars.conf) -gt 0 ]]; then @@ -1661,7 +1651,7 @@ displayFinalMessage() { pwstring="NOT SET" fi # If the user wants to install the dashboard, - if [[ ${INSTALL_WEB} == true ]]; then + if [[ "${INSTALL_WEB}" == true ]]; then # Store a message in a variable and display it additional="View the web interface at http://pi.hole/admin or http://${IPV4_ADDRESS%/*}/admin @@ -1683,7 +1673,7 @@ ${additional}" ${r} ${c} update_dialogs() { # If pihole -r "reconfigure" option was selected, - if [ "${reconfigure}" = true ]; then + if [[ "${reconfigure}" = true ]]; then # set some variables that will be used opt1a="Repair" opt1b="This will retain existing settings" @@ -1699,7 +1689,7 @@ update_dialogs() { opt2b="This will allow you to enter new settings" # Display the information to the user - UpdateCmd=$(whiptail --title "Existing Install Detected!" --menu "\n\nWe have detected an existing install.\n\nPlease choose from the following options: \n($strAdd)" ${r} ${c} 2 \ + UpdateCmd=$(whiptail --title "Existing Install Detected!" --menu "\\n\\nWe have detected an existing install.\\n\\nPlease choose from the following options: \\n($strAdd)" ${r} ${c} 2 \ "${opt1a}" "${opt1b}" \ "${opt2a}" "${opt2b}" 3>&2 2>&1 1>&3) || \ { echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; } @@ -1708,7 +1698,7 @@ update_dialogs() { case ${UpdateCmd} in # repair, or ${opt1a}) - echo -e " ${INFO} ${opt1a} option selected." + echo -e " ${INFO} ${opt1a} option selected" useUpdateVars=true ;; # recongigure, @@ -1719,7 +1709,6 @@ update_dialogs() { esac } - clone_or_update_repos() { # If the user wants to reconfigure, if [[ "${reconfigure}" == true ]]; then @@ -1730,7 +1719,7 @@ clone_or_update_repos() { exit 1; \ } # If the Web interface was installed, - if [[ ${INSTALL_WEB} == true ]]; then + if [[ "${INSTALL_WEB}" == true ]]; then # reset it's repo resetRepo ${webInterfaceDir} || \ { echo -e " ${COL_LIGHT_RED}Unable to reset ${webInterfaceDir}, exiting installer${COL_NC}"; \ @@ -1741,11 +1730,11 @@ clone_or_update_repos() { else # so get git files for Core getGitFiles ${PI_HOLE_LOCAL_REPO} ${piholeGitUrl} || \ - { echo "!!! Unable to clone ${piholeGitUrl} into ${PI_HOLE_LOCAL_REPO}, unable to continue."; \ + { echo -e " ${COL_LIGHT_RED}Unable to clone ${piholeGitUrl} into ${PI_HOLE_LOCAL_REPO}, unable to continue${COL_NC}"; \ exit 1; \ } # If the Web interface was installed, - if [[ ${INSTALL_WEB} == true ]]; then + if [[ "${INSTALL_WEB}" == true ]]; then # get the Web git files getGitFiles ${webInterfaceDir} ${webInterfaceGitUrl} || \ { echo -e " ${COL_LIGHT_RED}Unable to clone ${webInterfaceGitUrl} into ${webInterfaceDir}, exiting installer${COL_NC}"; \ @@ -1761,7 +1750,7 @@ FTLinstall() { local binary="${1}" local latesttag local orig_dir - local str="Installing FTL" + local str="Downloading and Installing FTL" echo -ne " ${INFO} ${str}..." # Get the current working directory @@ -1774,6 +1763,7 @@ FTLinstall() { echo -e " ${COL_LIGHT_RED}Error: Unable to get latest release location from GitHub${COL_NC}" return 1 fi + # If the download worked, if curl -sSL --fail "https://github.com/pi-hole/FTL/releases/download/${latesttag%$'\r'}/${binary}" -o "/tmp/${binary}"; then # get sha1 of the binary we just downloaded for verification. @@ -1816,7 +1806,7 @@ FTLinstall() { # Detect suitable FTL binary platform FTLdetect() { echo "" - echo -e " ${INFO} Downloading latest version of FTL..." + echo -e " ${INFO} FTL Checks..." # Local, named variables local machine @@ -1828,21 +1818,23 @@ FTLdetect() { local str="Detecting architecture" echo -ne " ${INFO} ${str}..." # If the machine is arm or aarch - if [[ ${machine} == arm* || ${machine} == *aarch* ]]; then + if [[ "${machine}" == "arm"* || "${machine}" == *"aarch"* ]]; then # ARM # - local rev=$(uname -m | sed "s/[^0-9]//g;") + local rev + rev=$(uname -m | sed "s/[^0-9]//g;") # - local lib=$(ldd /bin/ls | grep -E '^\s*/lib' | awk '{ print $1 }') + local lib + lib=$(ldd /bin/ls | grep -E '^\s*/lib' | awk '{ print $1 }') # - if [[ "$lib" == "/lib/ld-linux-aarch64.so.1" ]]; then + if [[ "${lib}" == "/lib/ld-linux-aarch64.so.1" ]]; then echo -e "${OVER} ${TICK} Detected ARM-aarch64 architecture" # set the binary to be used binary="pihole-FTL-aarch64-linux-gnu" # - elif [[ "$lib" == "/lib/ld-linux-armhf.so.3" ]]; then + elif [[ "${lib}" == "/lib/ld-linux-armhf.so.3" ]]; then # - if [ "$rev" -gt "6" ]; then + if [[ "${rev}" -gt 6 ]]; then echo -e "${OVER} ${TICK} Detected ARM-hf architecture (armv7+)" # set the binary to be used binary="pihole-FTL-arm-linux-gnueabihf" @@ -1857,35 +1849,63 @@ FTLdetect() { # set the binary to be used binary="pihole-FTL-arm-linux-gnueabi" fi - elif [[ $machine == ppc ]]; then + elif [[ "${machine}" == "ppc" ]]; then # PowerPC - echo "::: Detected PowerPC architecture" + echo -e "${OVER} ${TICK} Detected PowerPC architecture" # set the binary to be used binary="pihole-FTL-powerpc-linux-gnu" - elif [[ ${machine} == x86_64 ]]; then + elif [[ "${machine}" == "x86_64" ]]; then # 64bit echo -e "${OVER} ${TICK} Detected x86_64 architecture" # set the binary to be used binary="pihole-FTL-linux-x86_64" else # Something else - we try to use 32bit executable and warn the user - if [[ ! ${machine} == i686 ]]; then + if [[ ! "${machine}" == "i686" ]]; then echo -e "${OVER} ${CROSS} ${str}... - ${COL_LIGHT_RED}Not able to detect architecture (unknown: ${machine}), trying 32bit executable - Contact support if you experience issues (e.g: FTL not running)${COL_NC}" + ${COL_LIGHT_RED}Not able to detect architecture (unknown: ${machine}), trying 32bit executable${COL_NC} + Contact Pi-hole Support if you experience issues (e.g: FTL not running)" else echo -e "${OVER} ${TICK} Detected 32bit (i686) architecture" fi binary="pihole-FTL-linux-x86_32" fi - # Install FTL - FTLinstall "${binary}" || return 1 + #In the next section we check to see if FTL is already installed (in case of pihole -r). + #If the installed version matches the latest version, then check the installed sha1sum of the binary vs the remote sha1sum. If they do not match, then download + echo -e " ${INFO} Checking for existing FTL binary..." + + local ftlLoc=$(which pihole-FTL) + + if [[ ${ftlLoc} ]]; then + local FTLversion=$(/usr/bin/pihole-FTL tag) + local FTLlatesttag=$(curl -sI https://github.com/pi-hole/FTL/releases/latest | grep 'Location' | awk -F '/' '{print $NF}' | tr -d '\r\n') + + if [[ "${FTLversion}" != "${FTLlatesttag}" ]]; then + # Install FTL + FTLinstall "${binary}" || return 1 + else + echo -e " ${INFO} Latest FTL Binary already installed (${FTLlatesttag}). Confirming Checksum..." + + local remoteSha1=$(curl -sSL --fail "https://github.com/pi-hole/FTL/releases/download/${FTLversion%$'\r'}/${binary}.sha1" | cut -d ' ' -f 1) + local localSha1=$(sha1sum "$(which pihole-FTL)" | cut -d ' ' -f 1) + + if [[ "${remoteSha1}" != "${localSha1}" ]]; then + echo -e " ${INFO} Corruption detected..." + FTLinstall "${binary}" || return 1 + else + echo -e " ${INFO} Checksum correct. No need to download!" + fi + fi + else + # Install FTL + FTLinstall "${binary}" || return 1 + fi + } main() { - ######## FIRST CHECK ######## # Show the Pi-hole logo so people know it's genuine since the logo and name are trademarked show_ascii_berry @@ -1894,18 +1914,17 @@ main() { echo "" # If the user's id is zero, - if [[ ${EUID} -eq 0 ]]; then + if [[ "${EUID}" -eq 0 ]]; then # they are root and all is good echo -e " ${TICK} ${str}" # Otherwise, else # They do not have enough privileges, so let the user know echo -e " ${CROSS} ${str} - Script called with non-root privileges - The Pi-hole requires elevated privleges to install and run - Please check the installer for any concerns regarding this requirement - Make sure to download this script from a trusted source" - echo "" + ${COL_LIGHT_RED}Script called with non-root privileges${COL_NC} + The Pi-hole requires elevated privleges to install and run + Please check the installer for any concerns regarding this requirement + Make sure to download this script from a trusted source\\n" echo -ne " ${INFO} Sudo utility check" # If the sudo command exists, @@ -1918,7 +1937,7 @@ main() { else # Let them know they need to run it as root echo -e "${OVER} ${CROSS} Sudo utility check - Sudo is needed for the Web Interface to run pihole commands\n + Sudo is needed for the Web Interface to run pihole commands\\n ${COL_LIGHT_RED}Please re-run this installer as root${COL_NC}" exit 1 fi @@ -1937,7 +1956,7 @@ main() { done # If the setup variable file exists, - if [[ -f ${setupVars} ]]; then + if [[ -f "${setupVars}" ]]; then # if it's running unattended, if [[ "${runUnattended}" == true ]]; then echo -e " ${INFO} Performing unattended setup, no whiptail dialogs will be displayed" @@ -1970,15 +1989,14 @@ main() { # Check if SELinux is Enforcing checkSelinux - - if [[ ${useUpdateVars} == false ]]; then + if [[ "${useUpdateVars}" == false ]]; then # Display welcome dialogs welcomeDialogs # Create directory for Pi-hole storage mkdir -p /etc/pihole/ stop_service dnsmasq - if [[ ${INSTALL_WEB} == true ]]; then + if [[ "${INSTALL_WEB}" == true ]]; then stop_service lighttpd fi # Determine available interfaces @@ -1997,7 +2015,7 @@ main() { clone_or_update_repos # Install packages used by the Pi-hole - if [[ ${INSTALL_WEB} == true ]]; then + if [[ "${INSTALL_WEB}" == true ]]; then # Install the Web dependencies DEPS=("${PIHOLE_DEPS[@]}" "${PIHOLE_WEB_DEPS[@]}") # Otherwise, @@ -2007,6 +2025,13 @@ main() { fi install_dependent_packages DEPS[@] + if [[ -x "$(command -v systemctl)" ]]; then + # Value will either be 1, if true, or 0 + LIGHTTPD_ENABLED=$(systemctl is-enabled lighttpd | grep -c 'enabled' || true) + else + # Value will either be 1, if true, or 0 + LIGHTTPD_ENABLED=$(service lighttpd status | awk '/Loaded:/ {print $0}' | grep -c 'enabled' || true) + fi # Install and log everything to a file installPihole | tee ${tmpLog} @@ -2014,11 +2039,11 @@ main() { # Clone/Update the repos clone_or_update_repos - # Source ${setupVars} for use in the rest of the functions. + # Source ${setupVars} for use in the rest of the functions source ${setupVars} # Install packages used by the Pi-hole - if [[ ${INSTALL_WEB} == true ]]; then + if [[ "${INSTALL_WEB}" == true ]]; then # Install the Web dependencies DEPS=("${PIHOLE_DEPS[@]}" "${PIHOLE_WEB_DEPS[@]}") # Otherwise, @@ -2028,19 +2053,28 @@ main() { fi install_dependent_packages DEPS[@] + if [[ -x "$(command -v systemctl)" ]]; then + # Value will either be 1, if true, or 0 + LIGHTTPD_ENABLED=$(systemctl is-enabled lighttpd | grep -c 'enabled' || true) + else + # Value will either be 1, if true, or 0 + LIGHTTPD_ENABLED=$(service lighttpd status | awk '/Loaded:/ {print $0}' | grep -c 'enabled' || true) + fi + updatePihole | tee ${tmpLog} fi # Move the log file into /etc/pihole for storage mv ${tmpLog} ${instalLogLoc} - if [[ ${INSTALL_WEB} == true ]]; then + if [[ "${INSTALL_WEB}" == true ]]; then # Add password to web UI if there is none pw="" # If no password is set, if [[ $(grep 'WEBPASSWORD' -c /etc/pihole/setupVars.conf) == 0 ]] ; then # generate a random password pw=$(tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c 8) + # shellcheck disable=SC1091 . /opt/pihole/webpage.sh echo "WEBPASSWORD=$(HashPassword ${pw})" >> ${setupVars} fi @@ -2052,10 +2086,14 @@ main() { enable_service dnsmasq # If the Web server was installed, - if [[ ${INSTALL_WEB} == true ]]; then - # enable it - start_service lighttpd - enable_service lighttpd + if [[ "${INSTALL_WEB}" == true ]]; then + + if [[ "${LIGHTTPD_ENABLED}" == "1" ]]; then + start_service lighttpd + enable_service lighttpd + else + echo -e " ${INFO} Lighttpd is disabled, skipping service restart" + fi fi # Download and compile the aggregated block list @@ -2071,20 +2109,19 @@ main() { fi # If the Web interface was installed, - if [[ ${INSTALL_WEB} == true ]]; then + if [[ "${INSTALL_WEB}" == true ]]; then # If there is a password, if (( ${#pw} > 0 )) ; then # display the password echo -e " ${INFO} Web Interface password: ${COL_LIGHT_GREEN}${pw}${COL_NC} - This can be changed using 'pihole -a -p'" - echo "" + This can be changed using 'pihole -a -p'\\n" fi fi # if [[ "${useUpdateVars}" == false ]]; then # If the Web interface was installed, - if [[ ${INSTALL_WEB} == true ]]; then + if [[ "${INSTALL_WEB}" == true ]]; then echo -e " View the web interface at http://pi.hole/admin or http://${IPV4_ADDRESS%/*}/admin" echo "" fi @@ -2101,8 +2138,9 @@ main() { fi # Display where the log file is - echo -e "\n ${INFO} The install log is located at: /etc/pihole/install.log + echo -e "\\n ${INFO} The install log is located at: /etc/pihole/install.log ${COL_LIGHT_GREEN}${INSTALL_TYPE} Complete! ${COL_NC}" + } # diff --git a/pihole b/pihole index 3c321b93..61ed6cd6 100755 --- a/pihole +++ b/pihole @@ -87,10 +87,14 @@ scanList(){ domain="${1}" list="${2}" method="${3}" - if [[ ${method} == "-exact" ]] ; then - grep -i -E "(^|\s)${domain}($|\s)" "${list}" + + # Switch folder, preventing grep from printing file path + cd "/etc/pihole" || return 1 + + if [[ -n "${method}" ]]; then + grep -i -E -l "(^|\s|\/)${domain}($|\s|\/)" ${list} /dev/null 2> /dev/null else - grep -i "${domain}" "${list}" + grep -i "${domain}" ${list} /dev/null 2> /dev/null fi } @@ -110,46 +114,217 @@ processWildcards() { } queryFunc() { - domain="${2}" - - if [[ -z "${domain}" ]]; then - echo -e " ${COL_LIGHT_RED}Invalid option${COL_NC} - Try 'pihole query --help' for more information." + options="$*" + options="${options/-q /}" + + if [[ "${options}" == "-h" ]] || [[ "${options}" == "--help" ]]; then + echo "Usage: pihole -q [option] +Example: 'pihole -q -exact domain.com' +Query the adlists for a specified domain + +Options: + -adlist Print the name of the block list URL + -exact Search the block lists for exact domain matches + -all Return all query matches within a block list + -h, --help Show this help dialog" + exit 0 + fi + + if [[ "${options}" == *"-exact"* ]]; then + method="exact" + exact=true + fi + + if [[ "${options}" == *"-adlist"* ]]; then + adlist=true + fi + + if [[ "${options}" == *"-bp"* ]]; then + method="exact" + blockpage=true + fi + + if [[ "${options}" == *"-all"* ]]; then + all=true + fi + + # Strip valid options, leaving only the domain and invalid options + options=$(sed 's/ \?-\(exact\|adlist\(s\)\?\|bp\|all\) \?//g' <<< "$options") + + # Handle errors + if [[ "${options}" == *" "* ]]; then + error=true + str="Unknown option specified" + elif [[ "${options}" == "-q" ]]; then + error=true + str="No domain specified" + fi + + if [[ -n "${error}" ]]; then + echo -e " ${COL_LIGHT_RED}${str}${COL_NC} + Try 'pihole -q --help' for more information." exit 1 fi - - method="${3}" - lists=( /etc/pihole/list.* /etc/pihole/blacklist.txt) - for list in ${lists[@]}; do - if [ -e "${list}" ]; then - result=$(scanList ${domain} ${list} ${method}) - # Remove empty lines before couting number of results - count=$(sed '/^\s*$/d' <<< "$result" | wc -l) - echo "${list} (${count} results)" - if [[ ${count} > 0 ]]; then - echo "${result}" - fi - echo "" - else - echo -e " ${CROSS} List does not exist" - echo "" - fi - done - # Scan for possible wildcard matches - if [ -e "${wildcardlist}" ]; then - local wildcards=($(processWildcards "${domain}")) - for domain in ${wildcards[@]}; do - result=$(scanList "\/${domain}\/" ${wildcardlist}) - # Remove empty lines before couting number of results - count=$(sed '/^\s*$/d' <<< "$result" | wc -l) - if [[ ${count} > 0 ]]; then - echo -e " ${TICK} Wildcard blocking ${domain} (${count} results)" - echo "${result}" - echo "" + # If domain contains non ASCII characters, convert domain to punycode if python is available + # Cr: https://serverfault.com/a/335079 + if [[ "$options" = *[![:ascii:]]* ]]; then + if command -v python &> /dev/null; then + query=$(python -c 'import sys;print sys.argv[1].decode("utf-8").encode("idna")' "${options}") + fi + else + query="${options}" + fi + + # Scan Whitelist and Blacklist + lists="whitelist.txt blacklist.txt" + results=($(scanList "${query}" "${lists}" "${method}")) + + if [[ -n "${results[*]}" ]]; then + blResult=true + # Loop through each scanList line to print appropriate title + for result in "${results[@]}"; do + filename="${result/:*/}" + if [[ -n "$exact" ]]; then + printf " Exact result in %s\n" "${filename}" + elif [[ -n "$blockpage" ]]; then + printf "π %s\n" "${filename}" + else + domain="${result/*:/}" + if [[ ! "${filename}" == "${filename_prev:-}" ]]; then + printf " Result from %s\n" "${filename}" + fi + printf " %s\n" "${domain}" + filename_prev="${filename}" fi done fi + + # Scan Wildcards + if [[ -e "${wildcardlist}" ]]; then + wildcards=($(processWildcards "${query}")) + + for match in "${wildcards[@]}"; do + results=($(scanList "\/${match}\/" ${wildcardlist})) + + if [[ -n "${results[*]}" ]]; then + # Remove empty lines before couting number of results + count=$(sed '/^\s*$/d' <<< "${results[@]}" | wc -l) + if [[ "${count}" -ge 0 ]]; then + blResult=true + if [[ -z "${blockpage}" ]]; then + printf " Wildcard result in %s\n" "${wildcardlist/*dnsmasq.d\/}" + fi + + if [[ -n "${blockpage}" ]]; then + echo "π ${wildcardlist/*\/}" + else + echo " *.${match}" + fi + fi + fi + done + + [[ -n "${blResult}" ]] && [[ -n "${blockpage}" ]] && exit 0 + fi + + # Glob *.domains file names, remove file paths and sort by list number + lists_raw=(/etc/pihole/*.domains) + IFS_OLD=$IFS + IFS=$'\n' + lists=$(sort -t . -k 2 -g <<< "${lists_raw[*]//\/etc\/pihole\//}") + + # Scan Domains files + results=($(scanList "${query}" "${lists}" "${method}")) + + # Handle notices + if [[ -z "${blResult}" ]] && [[ -z "${results[*]}" ]]; then + notice=true + str="No ${method/t/t }results found for ${query} found within block lists" + elif [[ -z "${all}" ]] && [[ "${#results[*]}" -ge 16000 ]]; then + # 16000 chars is 15 chars X 1000 lines worth of results + notice=true + str="Hundreds of ${method/t/t }results found for ${query} + This can be overriden using the -all option" + fi + + if [[ -n "${notice}" ]]; then + echo -e " ${INFO} ${str}" + exit + fi + + # Remove unwanted content from results + if [[ -z "${method}" ]]; then + results=($(sed "/:#/d" <<< "${results[*]}")) # Lines starting with comments + results=($(sed "s/[ \t]#.*//g" <<< "${results[*]}")) # Comments after domain + results=($(sed "s/:.*[ \t]/:/g" <<< "${results[*]}")) # IP address + fi + IFS=$IFS_OLD + + # Get adlist content as array + if [[ -n "${adlist}" ]] || [[ -n "${blockpage}" ]]; then + if [[ -f "/etc/pihole/adlists.list" ]]; then + for url in $(< /etc/pihole/adlists.list); do + if [[ "${url:0:4}" == "http" ]] || [[ "${url:0:3}" == "www" ]]; then + adlists+=("$url") + fi + done + else + echo -e " ${COL_LIGHT_RED}The file '/etc/pihole/adlists.list' was not found${COL_NC}" + exit 1 + fi + fi + + if [[ -n "${results[*]}" ]]; then + if [[ -n "${exact}" ]]; then + echo " Exact result(s) for ${query} found in:" + fi + + for result in "${results[@]}"; do + filename="${result/:*/}" + + # Convert file name to URL name for -adlist or -bp options + if [[ -n "${adlist}" ]] || [[ -n "${blockpage}" ]]; then + filenum=("${filename/list./}") + filenum=("${filenum/.*/}") + filename="${adlists[$filenum]}" + + # If gravity has generated associated .domains files + # but adlists.list has been modified since + if [[ -z "${filename}" ]]; then + filename="${COL_LIGHT_RED}Error: no associated adlists URL found${COL_NC}" + fi + fi + + if [[ -n "${exact}" ]]; then + printf " %s\n" "${filename}" + elif [[ -n "${blockpage}" ]]; then + printf "%s %s\n" "${filenum}" "${filename}" + else # Standard query output + + # Print filename heading once per file, not for every match + if [[ ! "${filename}" == "${filename_prev:-}" ]]; then + unset count + printf " Result from %s\n" "${filename}" + else + let count++ + fi + + # Print matching domain if $max_count has not been reached + [[ -z "${all}" ]] && max_count="20" + if [[ -z "${all}" ]] && [[ "${count}" -eq "${max_count}" ]]; then + echo " Over $count results found, skipping rest of file" + elif [[ -z "${all}" ]] && [[ "${count}" -gt "${max_count}" ]]; then + continue + else + domain="${result/*:/}" + printf " %s\n" "${domain}" + fi + filename_prev="${filename}" + fi + done + fi + exit 0 } @@ -173,24 +348,32 @@ versionFunc() { restartDNS() { dnsmasqPid=$(pidof dnsmasq) + local str="Restarting DNS service" + echo -ne " ${INFO} ${str}" if [[ "${dnsmasqPid}" ]]; then # Service already running - reload config - echo -ne " ${INFO} Restarting dnsmasq" if [[ -x "$(command -v systemctl)" ]]; then - systemctl restart dnsmasq + output=$( { systemctl restart dnsmasq; } 2>&1 ) else - service dnsmasq restart + output=$( { service dnsmasq restart; } 2>&1 ) + fi + if [[ -z "${output}" ]]; then + echo -e "${OVER} ${TICK} ${str}" + else + echo -e "${OVER} ${CROSS} ${output}" fi - [[ "$?" == 0 ]] && echo -e "${OVER} ${TICK} Restarted dnsmasq" || echo -e "${OVER} ${CROSS} Failed to restart dnsmasq" else # Service not running, start it up - echo -ne " ${INFO} Starting dnsmasq" if [[ -x "$(command -v systemctl)" ]]; then - systemctl start dnsmasq + output=$( { systemctl start dnsmasq; } 2>&1 ) else - service dnsmasq start + output=$( { service dnsmasq start; } 2>&1 ) + fi + if [[ -z "${output}" ]]; then + echo -e "${OVER} ${TICK} ${str}" + else + echo -e "${OVER} ${CROSS} ${output}" fi - [[ "$?" == 0 ]] && echo -e "${OVER} ${TICK} Restarted dnsmasq" || echo -e "${OVER} ${CROSS} Failed to restart dnsmasq" fi } @@ -253,15 +436,15 @@ Time: # Enable Pi-hole echo -e " ${INFO} Enabling blocking" local str="Pi-hole Enabled" - + sed -i 's/^#addn-hosts/addn-hosts/' /etc/dnsmasq.d/01-pihole.conf if [[ -e "/etc/pihole/wildcard.list" ]]; then mv "/etc/pihole/wildcard.list" "$wildcardlist" fi fi - + restartDNS - + echo -e "${OVER} ${TICK} ${str}" } @@ -359,6 +542,7 @@ Switch Pi-hole subsystems to a different Github branch Repositories: core [branch] Change the branch of Pi-hole's core subsystem web [branch] Change the branch of Admin Console subsystem + ftl [branch] Change the branch of Pi-hole's FTL subsystem Branches: master Update subsystems to the latest stable release @@ -430,7 +614,7 @@ Options: -l, logging Specify whether the Pi-hole log should be used Add '-h' for more info on logging usage -q, query Query the adlists for a specified domain - Add '-exact' AFTER a specified domain for exact match + Add '-h' for more info on query usage -up, updatePihole Update Pi-hole subsystems -v, version Show installed versions of Pi-hole, Admin Console & FTL Add '-h' for more info on version usage diff --git a/test/test_automated_install.py b/test/test_automated_install.py index 60b9dbb8..7f1a86a1 100644 --- a/test/test_automated_install.py +++ b/test/test_automated_install.py @@ -59,6 +59,8 @@ def test_setupVars_saved_to_file(Pihole): TERM=xterm source /opt/pihole/basic-install.sh {} + mkdir -p /etc/dnsmasq.d + version_check_dnsmasq finalExports cat /etc/pihole/setupVars.conf '''.format(set_setup_vars)) @@ -78,7 +80,7 @@ def test_configureFirewall_firewalld_running_no_errors(Pihole): source /opt/pihole/basic-install.sh configureFirewall ''') - expected_stdout = 'Configuring FirewallD for httpd and dnsmasq.' + expected_stdout = 'Configuring FirewallD for httpd and dnsmasq' assert expected_stdout in configureFirewall.stdout firewall_calls = Pihole.run('cat /var/log/firewall-cmd').stdout assert 'firewall-cmd --state' in firewall_calls @@ -93,7 +95,7 @@ def test_configureFirewall_firewalld_disabled_no_errors(Pihole): source /opt/pihole/basic-install.sh configureFirewall ''') - expected_stdout = 'No active firewall detected.. skipping firewall configuration.' + expected_stdout = 'No active firewall detected.. skipping firewall configuration' assert expected_stdout in configureFirewall.stdout def test_configureFirewall_firewalld_enabled_declined_no_errors(Pihole): @@ -319,11 +321,11 @@ def test_FTL_detect_aarch64_no_errors(Pihole): source /opt/pihole/basic-install.sh FTLdetect ''') - expected_stdout = info_box + ' Downloading latest version of FTL...' + expected_stdout = info_box + ' FTL Checks...' assert expected_stdout in detectPlatform.stdout expected_stdout = tick_box + ' Detected ARM-aarch64 architecture' assert expected_stdout in detectPlatform.stdout - expected_stdout = tick_box + ' Installing FTL' + expected_stdout = tick_box + ' Downloading and Installing FTL' assert expected_stdout in detectPlatform.stdout def test_FTL_detect_armv6l_no_errors(Pihole): @@ -336,11 +338,11 @@ def test_FTL_detect_armv6l_no_errors(Pihole): source /opt/pihole/basic-install.sh FTLdetect ''') - expected_stdout = info_box + ' Downloading latest version of FTL...' + expected_stdout = info_box + ' FTL Checks...' assert expected_stdout in detectPlatform.stdout expected_stdout = tick_box + ' Detected ARM-hf architecture (armv6 or lower)' assert expected_stdout in detectPlatform.stdout - expected_stdout = tick_box + ' Installing FTL' + expected_stdout = tick_box + ' Downloading and Installing FTL' assert expected_stdout in detectPlatform.stdout def test_FTL_detect_armv7l_no_errors(Pihole): @@ -353,11 +355,11 @@ def test_FTL_detect_armv7l_no_errors(Pihole): source /opt/pihole/basic-install.sh FTLdetect ''') - expected_stdout = info_box + ' Downloading latest version of FTL...' + expected_stdout = info_box + ' FTL Checks...' assert expected_stdout in detectPlatform.stdout expected_stdout = tick_box + ' Detected ARM-hf architecture (armv7+)' assert expected_stdout in detectPlatform.stdout - expected_stdout = tick_box + ' Installing FTL' + expected_stdout = tick_box + ' Downloading and Installing FTL' assert expected_stdout in detectPlatform.stdout def test_FTL_detect_x86_64_no_errors(Pihole): @@ -366,11 +368,11 @@ def test_FTL_detect_x86_64_no_errors(Pihole): source /opt/pihole/basic-install.sh FTLdetect ''') - expected_stdout = info_box + ' Downloading latest version of FTL...' + expected_stdout = info_box + ' FTL Checks...' assert expected_stdout in detectPlatform.stdout expected_stdout = tick_box + ' Detected x86_64 architecture' assert expected_stdout in detectPlatform.stdout - expected_stdout = tick_box + ' Installing FTL' + expected_stdout = tick_box + ' Downloading and Installing FTL' assert expected_stdout in detectPlatform.stdout def test_FTL_detect_unknown_no_errors(Pihole): @@ -391,7 +393,7 @@ def test_FTL_download_aarch64_no_errors(Pihole): source /opt/pihole/basic-install.sh FTLinstall pihole-FTL-aarch64-linux-gnu ''') - expected_stdout = tick_box + ' Installing FTL' + expected_stdout = tick_box + ' Downloading and Installing FTL' assert expected_stdout in download_binary.stdout error = 'Error: Download of binary from Github failed' assert error not in download_binary.stdout @@ -405,7 +407,7 @@ def test_FTL_download_unknown_fails_no_errors(Pihole): source /opt/pihole/basic-install.sh FTLinstall pihole-FTL-mips ''') - expected_stdout = cross_box + ' Installing FTL' + expected_stdout = cross_box + ' Downloading and Installing FTL' assert expected_stdout in download_binary.stdout error = 'Error: URL not found' assert error in download_binary.stdout @@ -442,7 +444,7 @@ def test_IPv6_only_link_local(Pihole): source /opt/pihole/basic-install.sh useIPv6dialog ''') - expected_stdout = 'Found neither IPv6 ULA nor GUA address, blocking IPv6 ads will not be enabled' + expected_stdout = 'Unable to find IPv6 ULA/GUA address, IPv6 adblocking will not be enabled' assert expected_stdout in detectPlatform.stdout def test_IPv6_only_ULA(Pihole):