From dbe726d9fb5dc88a29c8d2f515b351f88446eba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sat, 2 Jul 2022 21:51:03 +0200 Subject: [PATCH 01/81] Add FTL communication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 178 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 151 insertions(+), 27 deletions(-) diff --git a/padd.sh b/padd.sh index 5cb68c4e..5552f073 100755 --- a/padd.sh +++ b/padd.sh @@ -14,7 +14,7 @@ LC_NUMERIC=C ############################################ VARIABLES ############################################# # VERSION -padd_version="v3.8.0" +padd_version="v4.0.0" # LastChecks LastCheckVersionInformation=$(date +%s) @@ -103,6 +103,98 @@ padd_logo_retro_1="${bold_text} ${yellow_text}_${green_text}_ ${blue_text}_ padd_logo_retro_2="${bold_text}${yellow_text}|${green_text}_${blue_text}_${cyan_text}) ${red_text}/${yellow_text}\\ ${blue_text}| ${red_text}\\${yellow_text}| ${cyan_text}\\ ${reset_text}" padd_logo_retro_3="${bold_text}${green_text}| ${red_text}/${yellow_text}-${green_text}-${blue_text}\\${cyan_text}|${magenta_text}_${red_text}_${yellow_text}/${green_text}|${blue_text}_${cyan_text}_${magenta_text}/ ${reset_text}" +############################################# FTL ################################################## + +ConstructAPI() { + # If no arguments were supplied set them to default + if [ -z "${URL}" ]; then + URL=pi.hole + fi + if [ -z "${PORT}" ]; then + PORT=8080 + fi + if [ -z "${APIPATH}" ]; then + APIPATH=api + fi +} + +Authenthication() { + # Try to authenticate + ChallengeResponse + + while [ "${validSession}" = false ]; do + echo "Authentication with FTL server failed." + + # no password was supplied as argument + if [ -z "${password}" ]; then + echo "Please enter your Pi-hole password:" + else + echo "Wrong Pi-hole password supplied, please enter the correct password:" + fi + + # POSIX's `read` does not support `-s` option (suppressing the input) + # this workaround changes the terminal characteristics to not echo input and later rests this option + # credits https://stackoverflow.com/a/4316765 + + stty_orig=$(stty -g) + stty -echo + read -r password + stty "${stty_orig}" + echo "" + + # Try to authenticate again + ChallengeResponse + done + + # Loop exited, authentication was successful + echo "Authentication with FTL server successful." + +} + +DeleteSession() { + + # Try to delte the session. Omitt the output, but get the http status code + deleteResponse=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE http://${URL}:${PORT}/${APIPATH}/auth -H "Accept: application/json" -H "sid: ${SID}") + + case "${deleteResponse}" in + "200") echo "A session that was not created cannot be deleted (e.g., empty API password).";; + "401") echo "Logout attempt without a valid session. Unauthorized!";; + "410") echo "Session deleted successfully";; + esac; + +} + +ChallengeResponse() { + # Challenge-response authentication + + # Compute password hash from user password + # Compute password hash twice to avoid rainbow table vulnerability + hash1=$(printf "%b" "$password" | sha256sum | sed 's/\s.*$//') + pwhash=$(printf "%b" "$hash1" | sha256sum | sed 's/\s.*$//') + + + # Get challenge from FTL + # Calculate response based on challenge and password hash + # Send response & get session response + challenge="$(curl --silent -X GET http://${URL}:${PORT}/${APIPATH}/auth | jq --raw-output .challenge)" + response="$(printf "%b" "${challenge}:${pwhash}" | sha256sum | sed 's/\s.*$//')" + sessionResponse="$(curl --silent -X POST http://${URL}:${PORT}/${APIPATH}/auth --data "{\"response\":\"${response}\"}" )" + + if [ -z "${sessionResponse}" ]; then + echo "No response from FTL server. Please check connectivity and use the options to set the API URL" + echo "Usage: $0 [-u ] [-p ] [-a ] " + exit 1 + fi + # obtain validity and session ID from session response + validSession=$(echo "${sessionResponse}"| jq .session.valid) + SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid) +} + +GetFTLData() { + data=$(curl -sS -X GET "http://${URL}:${PORT}/${APIPATH}$1" -H "Accept: application/json" -H "sid: ${SID}" ) + echo "${data}" +} + ############################################# GETTERS ############################################## @@ -1008,17 +1100,27 @@ VersionConverter() { OutputJSON() { GetSummaryInformation echo "{\"domains_being_blocked\":${domains_being_blocked_raw},\"dns_queries_today\":${dns_queries_today_raw},\"ads_blocked_today\":${ads_blocked_today_raw},\"ads_percentage_today\":${ads_percentage_today_raw},\"clients\": ${clients}}" + exit 0 } StartupRoutine(){ - # Get config variables + + # Construct FTL's API address depending on the arguments supplied + ConstructAPI + + # Get config variables . /etc/pihole/setupVars.conf if [ "$1" = "pico" ] || [ "$1" = "nano" ] || [ "$1" = "micro" ]; then PrintLogo "$1" printf "%b" "START-UP ===========\n" - printf "%b" "Checking connection.\n" + printf "%b" "Checking Internet connection.\n" CheckConnectivity "$1" + + # Authenticate with the FTL server + printf "%b" "Establishing connection with FTL...\n" + Authenthication + printf "%b" "Starting PADD...\n" printf "%b" " [■·········] 10%\\r" @@ -1047,6 +1149,11 @@ StartupRoutine(){ echo "Checking connectivity." CheckConnectivity "$1" + # Authenticate with the FTL server + printf "%b" "Establishing connection with FTL...\n" + Authenthication + + echo "Starting PADD." # Get our information for the first time @@ -1076,6 +1183,11 @@ StartupRoutine(){ printf "%b" "- Checking internet connection...\n" CheckConnectivity "$1" + # Authenticate with the FTL server + printf "%b" "Establishing connection with FTL...\n" + Authenthication + + # Get our information for the first time echo "- Gathering system information..." GetSystemInformation "$1" @@ -1174,39 +1286,51 @@ DisplayHelp() { cat << EOM ::: PADD displays stats about your piHole! ::: -::: Note: If no option is passed, then stats are displayed on screen, updated every 5 seconds ::: ::: Options: -::: -j, --json output stats as JSON formatted string -::: -h, --help display this help text +::: +::: -u URL or address of your Pi-hole (default: pi.hole) +::: -p Port of your Pi-hole's API (default: 8080) +::: -a Path where your Pi-hole's API is hosted (default: api) +::: -s Your Pi-hole's password, required to access the API +::: -j output stats as JSON formatted string and exit +::: -h display this help text EOM exit 0 } -if [ $# = 0 ]; then - # Turns off the cursor - # (From Pull request #8 https://github.com/jpmck/PADD/pull/8) - setterm -cursor off - trap "{ setterm -cursor on ; echo "" ; exit 0 ; }" INT TERM EXIT +# Get supplied options + +while getopts ":u:p:a:s:jh" args; do + case "${args}" in + u) URL="${OPTARG}" ;; + p) PORT="${OPTARG}" ;; + a) APIPATH="${OPTARG}" ;; + s) password="${OPTARG}" ;; + j) OutputJSON;; + h) DisplayHelp;; + \?) echo "Invalid option: -${OPTARG}" + exit 1 ;; + :) echo "Option -$OPTARG requires an argument." + exit 1 ;; + *) DisplayHelp;; + esac +done - clear + # Turns off the cursor +# (From Pull request #8 https://github.com/jpmck/PADD/pull/8) +setterm -cursor off +trap "{ setterm -cursor on ; echo "" ; exit 0 ; }" INT TERM EXIT - console_width=$(tput cols) - console_height=$(tput lines) +clear - SizeChecker +console_width=$(tput cols) +console_height=$(tput lines) - StartupRoutine ${padd_size} +SizeChecker - # Run PADD - clear - NormalPADD -fi +StartupRoutine ${padd_size} -for var in "$@"; do - case "$var" in - "-j" | "--json" ) OutputJSON;; - "-h" | "--help" ) DisplayHelp;; - * ) exit 1;; - esac -done +# Run PADD +clear +NormalPADD From 8916cb2cb4dae606ed6654f851582adf639f0afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sat, 2 Jul 2022 22:57:37 +0200 Subject: [PATCH 02/81] Improve exit routines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/padd.sh b/padd.sh index 5552f073..a74094bb 100755 --- a/padd.sh +++ b/padd.sh @@ -157,9 +157,9 @@ DeleteSession() { deleteResponse=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE http://${URL}:${PORT}/${APIPATH}/auth -H "Accept: application/json" -H "sid: ${SID}") case "${deleteResponse}" in - "200") echo "A session that was not created cannot be deleted (e.g., empty API password).";; - "401") echo "Logout attempt without a valid session. Unauthorized!";; - "410") echo "Session deleted successfully";; + "200") printf "%b" "\nA session that was not created cannot be deleted (e.g., empty API password).\n";; + "401") printf "%b" "\nLogout attempt without a valid session. Unauthorized!\n";; + "410") printf "%b" "\nSession deleted successfully\n";; esac; } @@ -1280,6 +1280,8 @@ NormalPADD() { fi done + + DeleteSession } DisplayHelp() { @@ -1299,6 +1301,36 @@ EOM exit 0 } +# Called on signals INT QUIT TERM +sig_cleanup() { + # save error code (130 for SIGINT, 143 for SIGTERM, 131 for SIGQUIT) + err=$? + + # some shells will call EXIT after the INT signal + # causing EXIT trap to be executed, so we trap EXIT after INT + trap '' EXIT + + (exit $err) # execute in a subshell just to pass $? to clean_exit() + clean_exit +} + +# Called on signal EXIT, or indirectly on INT QUIT TERM +clean_exit() { + # save the return code of the script + err=$? + + # reset trap for all signals to not interrupt clean_tempfiles() on any next signal + trap '' EXIT INT QUIT TERM + + # restore terminal settings + setterm -cursor on + stty "${stty_orig}" + + # Delete session from FTL server + DeleteSession + exit $err # exit the script with saved $? +} + # Get supplied options while getopts ":u:p:a:s:jh" args; do @@ -1320,7 +1352,11 @@ done # Turns off the cursor # (From Pull request #8 https://github.com/jpmck/PADD/pull/8) setterm -cursor off -trap "{ setterm -cursor on ; echo "" ; exit 0 ; }" INT TERM EXIT + +# Traps for graceful shutdown +# https://unix.stackexchange.com/a/681201 +trap clean_exit EXIT +trap sig_cleanup INT QUIT TERM clear From 55ade42fa9639204bceafd1070c6fe1cdd4a7488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 17 Jul 2022 13:54:50 +0200 Subject: [PATCH 03/81] Add TestAPIAvailability() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 105 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 41 deletions(-) diff --git a/padd.sh b/padd.sh index a74094bb..4defda69 100755 --- a/padd.sh +++ b/padd.sh @@ -118,49 +118,65 @@ ConstructAPI() { fi } +TestAPIAvailability() { + + availabilityResonse=$(curl -s -o /dev/null -w "%{http_code}" http://${URL}:${PORT}/${APIPATH}/auth) + + # test if http status code was 200 (OK) + if [ "${availabilityResonse}" = 200 ]; then + printf "%b" "API available at: http://${URL}:${PORT}/${APIPATH}\n\n" + else + echo "API not available at: http://${URL}:${PORT}/${APIPATH}" + echo "Exiting." + exit 1 + fi +} + Authenthication() { - # Try to authenticate - ChallengeResponse + # Try to authenticate + ChallengeResponse - while [ "${validSession}" = false ]; do - echo "Authentication with FTL server failed." + while [ "${validSession}" = false ]; do + echo "Authentication failed." - # no password was supplied as argument - if [ -z "${password}" ]; then - echo "Please enter your Pi-hole password:" - else - echo "Wrong Pi-hole password supplied, please enter the correct password:" - fi + # no password was supplied as argument + if [ -z "${password}" ]; then + echo "No password supplied. Please enter your password:" + else + echo "Wrong password supplied, please enter the correct password:" + fi - # POSIX's `read` does not support `-s` option (suppressing the input) - # this workaround changes the terminal characteristics to not echo input and later rests this option - # credits https://stackoverflow.com/a/4316765 + # POSIX's `read` does not support `-s` option (suppressing the input) + # this workaround changes the terminal characteristics to not echo input and later rests this option + # credits https://stackoverflow.com/a/4316765 - stty_orig=$(stty -g) - stty -echo - read -r password - stty "${stty_orig}" - echo "" + stty -echo + read -r password + stty "${stty_orig}" + echo "" - # Try to authenticate again - ChallengeResponse - done + # Try to authenticate again + ChallengeResponse + done - # Loop exited, authentication was successful - echo "Authentication with FTL server successful." + # Loop exited, authentication was successful + echo "Authentication successful." } DeleteSession() { - - # Try to delte the session. Omitt the output, but get the http status code - deleteResponse=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE http://${URL}:${PORT}/${APIPATH}/auth -H "Accept: application/json" -H "sid: ${SID}") - - case "${deleteResponse}" in - "200") printf "%b" "\nA session that was not created cannot be deleted (e.g., empty API password).\n";; - "401") printf "%b" "\nLogout attempt without a valid session. Unauthorized!\n";; - "410") printf "%b" "\nSession deleted successfully\n";; - esac; + # if a valid Session exists (no password required or successful authenthication) and + # SID is not null (successful authenthication only), delete the session + if [ "${validSession}" = true ] && [ ! "${SID}" = null ]; then + # Try to delte the session. Omitt the output, but get the http status code + deleteResponse=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE http://${URL}:${PORT}/${APIPATH}/auth -H "Accept: application/json" -H "sid: ${SID}") + + case "${deleteResponse}" in + "200") printf "%b" "\nA session that was not created cannot be deleted (e.g., empty API password).\n";; + "401") printf "%b" "\nLogout attempt without a valid session. Unauthorized!\n";; + "410") printf "%b" "\nSession successfully deleted.\n";; + esac; + fi } @@ -1105,9 +1121,6 @@ OutputJSON() { StartupRoutine(){ - # Construct FTL's API address depending on the arguments supplied - ConstructAPI - # Get config variables . /etc/pihole/setupVars.conf @@ -1322,9 +1335,10 @@ clean_exit() { # reset trap for all signals to not interrupt clean_tempfiles() on any next signal trap '' EXIT INT QUIT TERM - # restore terminal settings - setterm -cursor on - stty "${stty_orig}" + # restore terminal settings if they have been changed (e.g. user cancled script while at password input prompt) + if [ "$(stty -g)" != "${stty_orig}" ]; then + stty "${stty_orig}" + fi # Delete session from FTL server DeleteSession @@ -1336,10 +1350,10 @@ clean_exit() { while getopts ":u:p:a:s:jh" args; do case "${args}" in u) URL="${OPTARG}" ;; - p) PORT="${OPTARG}" ;; + p) PORT="${OPTARG}" ;; a) APIPATH="${OPTARG}" ;; s) password="${OPTARG}" ;; - j) OutputJSON;; + j) OutputJSON;; h) DisplayHelp;; \?) echo "Invalid option: -${OPTARG}" exit 1 ;; @@ -1349,10 +1363,19 @@ while getopts ":u:p:a:s:jh" args; do esac done - # Turns off the cursor +# Save current terminal settings (needed for later restore after password prompt) +stty_orig=$(stty -g) + +# Turns off the cursor # (From Pull request #8 https://github.com/jpmck/PADD/pull/8) setterm -cursor off +# Construct FTL's API address depending on the arguments supplied +ConstructAPI + +# Test if the authentication endpoint is availabe +TestAPIAvailability + # Traps for graceful shutdown # https://unix.stackexchange.com/a/681201 trap clean_exit EXIT From cea974e74a486a828842103bfb1efc40580c2919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 17 Jul 2022 14:25:02 +0200 Subject: [PATCH 04/81] Use API for GetSummaryInformation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 72 +++++++++++++++------------------------------------------ 1 file changed, 19 insertions(+), 53 deletions(-) diff --git a/padd.sh b/padd.sh index 4defda69..f67b2859 100755 --- a/padd.sh +++ b/padd.sh @@ -54,7 +54,6 @@ pico_status_hot="${check_box_bad} Sys. Hot!" pico_status_off="${check_box_bad} Offline" pico_status_ftl_down="${check_box_info} FTL Down" pico_status_dns_down="${check_box_bad} DNS Down" -pico_status_unknown="${check_box_question} Stat. Unk." # MINI STATUS mini_status_ok="${check_box_good} System OK" @@ -63,7 +62,6 @@ mini_status_hot="${check_box_bad} System is hot!" mini_status_off="${check_box_bad} Pi-hole off!" mini_status_ftl_down="${check_box_info} FTL down!" mini_status_dns_down="${check_box_bad} DNS off!" -mini_status_unknown="${check_box_question} Status unknown" # REGULAR STATUS full_status_ok="${check_box_good} System is healthy." @@ -72,7 +70,6 @@ full_status_hot="${check_box_bad} System is hot!" full_status_off="${check_box_bad} Pi-hole is offline" full_status_ftl_down="${check_box_info} FTL is down!" full_status_dns_down="${check_box_bad} DNS is off!" -full_status_unknown="${check_box_question} Status unknown!" # MEGA STATUS mega_status_ok="${check_box_good} Your system is healthy." @@ -81,7 +78,6 @@ mega_status_hot="${check_box_bad} Your system is hot!" mega_status_off="${check_box_bad} Pi-hole is offline." mega_status_ftl_down="${check_box_info} FTLDNS service is not running." mega_status_dns_down="${check_box_bad} Pi-hole's DNS server is off!" -mega_status_unknown="${check_box_question} Unable to determine Pi-hole status." # TINY STATUS tiny_status_ok="${check_box_good} System is healthy." @@ -90,7 +86,6 @@ tiny_status_hot="${check_box_bad} System is hot!" tiny_status_off="${check_box_bad} Pi-hole is offline" tiny_status_ftl_down="${check_box_info} FTL is down!" tiny_status_dns_down="${check_box_bad} DNS is off!" -tiny_status_unknown="${check_box_question} Status unknown!" # Text only "logos" padd_text="${green_text}${bold_text}PADD${reset_text}" @@ -214,52 +209,37 @@ GetFTLData() { ############################################# GETTERS ############################################## -GetFTLData() { - ftl_port=$(cat /run/pihole-FTL.port 2> /dev/null) - if [ -n "$ftl_port" ]; then - # Send command to FTL and ask to quit when finished - echo ">$1 >quit" | nc 127.0.0.1 "${ftl_port}" - else - echo "0" - fi -} - GetSummaryInformation() { - summary=$(GetFTLData "stats") - cache_info=$(GetFTLData "cacheinfo") + summary=$(GetFTLData "/stats/summary") + cache_info=$(GetFTLData "/dns/cache") - clients=$(echo "${summary}" | grep "unique_clients" | grep -Eo "[0-9]+$") + clients=$(echo "${summary}" | jq .ftl.clients.active ) - blocking_status=$(echo "${summary}" | grep "status" | grep -Eo "enabled|disabled|unknown" ) + blocking_status=$(echo "${summary}" | jq .system.dns.blocking ) - domains_being_blocked_raw=$(echo "${summary}" | grep "domains_being_blocked" | grep -Eo "[0-9]+$") + domains_being_blocked_raw=$(echo "${summary}" | jq .ftl.database.gravity ) domains_being_blocked=$(printf "%.f" "${domains_being_blocked_raw}") - dns_queries_today_raw=$(echo "$summary" | grep "dns_queries_today" | grep -Eo "[0-9]+$") + dns_queries_today_raw=$(echo "$summary" | jq .queries.total ) dns_queries_today=$(printf "%.f" "${dns_queries_today_raw}") - ads_blocked_today_raw=$(echo "$summary" | grep "ads_blocked_today" | grep -Eo "[0-9]+$") + ads_blocked_today_raw=$(echo "$summary" | jq .queries.blocked ) ads_blocked_today=$(printf "%.f" "${ads_blocked_today_raw}") - ads_percentage_today_raw=$(echo "$summary" | grep "ads_percentage_today" | grep -Eo "[0-9.]+$") + ads_percentage_today_raw=$(echo "$summary" | jq .queries.percent_blocked) ads_percentage_today=$(printf "%.1f" "${ads_percentage_today_raw}") - cache_size=$(echo "$cache_info" | grep "cache-size" | grep -Eo "[0-9.]+$") - cache_deletes=$(echo "$cache_info" | grep "cache-live-freed" | grep -Eo "[0-9.]+$") - cache_inserts=$(echo "$cache_info"| grep "cache-inserted" | grep -Eo "[0-9.]+$") + cache_size=$(echo "$cache_info" | jq .size) + cache_evictions=$(echo "$cache_info" | jq .evicted) + cache_inserts=$(echo "$cache_info"| jq .inserted) - latest_blocked=$(GetFTLData recentBlocked) + latest_blocked=$(GetFTLData "/stats/recent_blocked" | jq --raw-output .blocked[0]) - top_blocked=$(GetFTLData "top-ads (1)" | awk '{print $3}') + top_blocked=$(GetFTLData "/stats/top_blocked" | jq --raw-output .top_domains[0].domain) - top_domain=$(GetFTLData "top-domains (1)" | awk '{print $3}') + top_domain=$(GetFTLData "/stats/top_domains" | jq --raw-output .top_domains[0].domain) - top_client_raw=$(GetFTLData "top-clients (1)" | awk '{print $4}') - if [ -z "${top_client_raw}" ]; then - top_client=$(GetFTLData "top-clients (1)" | awk '{print $3}') - else - top_client="${top_client_raw}" - fi + top_client=$(GetFTLData "/stats/top_clients " | jq --raw-output .top_clients[0].name) if [ "$1" = "pico" ] || [ "$1" = "nano" ] || [ "$1" = "micro" ]; then ads_blocked_bar=$(BarGenerator "$ads_percentage_today" 10 "color") @@ -533,7 +513,7 @@ GetPiholeInformation() { fi # Get Pi-hole (blocking) status - ftl_dns_port=$(GetFTLData "dns-port") + ftl_dns_port=$(GetFTLData "/dns/port" | jq .dns-port) # ${ftl_dns_port} == 0 DNS server part of dnsmasq disabled, ${ftl_status} == "Not running" no ftlPID found if [ "${ftl_dns_port}" = 0 ] || [ "${ftl_status}" = "Not running" ]; then @@ -546,12 +526,12 @@ GetPiholeInformation() { full_status=${full_status_dns_down} mega_status=${mega_status_dns_down} else - if [ "${blocking_status}" = "enabled" ]; then + if [ "${blocking_status}" = "true" ]; then pihole_status="Active" pihole_heatmap=${green_text} pihole_check_box=${check_box_good} fi - if [ "${blocking_status}" = "disabled" ]; then + if [ "${blocking_status}" = "false" ]; then pihole_status="Blocking disabled" pihole_heatmap=${red_text} pihole_check_box=${check_box_bad} @@ -561,16 +541,6 @@ GetPiholeInformation() { full_status=${full_status_off} mega_status=${mega_status_off} fi - if [ "${blocking_status}" = "unknown" ]; then - pihole_status="Unknown" - pihole_heatmap=${yellow_text} - pihole_check_box=${check_box_question} - pico_status=${pico_status_unknown} - mini_status=${mini_status_unknown} - tiny_status=${tiny_status_unknown} - full_status=${full_status_unknown} - mega_status=${mega_status_unknown} - fi fi } @@ -891,7 +861,7 @@ PrintPiholeStats() { CleanPrintf " %-10s%-39s\e[0K\\n" "Top Clnt:" "${top_client}" CleanEcho "FTL ===========================================================================" CleanPrintf " %-10s%-9s %-10s%-9s %-10s%-9s\e[0K\\n" "PID:" "${ftlPID}" "CPU Use:" "${ftl_cpu}%" "Mem. Use:" "${ftl_mem_percentage}%" - CleanPrintf " %-10s%-69s\e[0K\\n" "DNSCache:" "${cache_inserts} insertions, ${cache_deletes} deletions, ${cache_size} total entries" + CleanPrintf " %-10s%-69s\e[0K\\n" "DNSCache:" "${cache_inserts} insertions, ${cache_evictions} evictions, ${cache_size} total entries" fi } @@ -1121,9 +1091,6 @@ OutputJSON() { StartupRoutine(){ - # Get config variables - . /etc/pihole/setupVars.conf - if [ "$1" = "pico" ] || [ "$1" = "nano" ] || [ "$1" = "micro" ]; then PrintLogo "$1" printf "%b" "START-UP ===========\n" @@ -1263,7 +1230,6 @@ NormalPADD() { # Get uptime, CPU load, temp, etc. every 5 seconds if [ $((now - LastCheckSystemInformation)) -ge 5 ]; then - . /etc/pihole/setupVars.conf GetSystemInformation ${padd_size} LastCheckSystemInformation="${now}" fi From 0df566a2e3d11091c7cf5135f5f0c21b5f2f2413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 17 Jul 2022 20:23:33 +0200 Subject: [PATCH 05/81] Use API for GetSystemInformation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 127 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 63 insertions(+), 64 deletions(-) diff --git a/padd.sh b/padd.sh index f67b2859..7ec86a07 100755 --- a/padd.sh +++ b/padd.sh @@ -23,9 +23,6 @@ LastCheckSummaryInformation=$(date +%s) LastCheckPiholeInformation=$(date +%s) LastCheckSystemInformation=$(date +%s) -# CORES -core_count=$(nproc --all 2> /dev/null) - # COLORS CSI="$(printf '\033')[" red_text="${CSI}91m" # Red @@ -233,7 +230,7 @@ GetSummaryInformation() { cache_evictions=$(echo "$cache_info" | jq .evicted) cache_inserts=$(echo "$cache_info"| jq .inserted) - latest_blocked=$(GetFTLData "/stats/recent_blocked" | jq --raw-output .blocked[0]) + latest_blocked=$(GetFTLData "/stats/recent_blocked&show=1" | jq --raw-output .blocked[0]) top_blocked=$(GetFTLData "/stats/top_blocked" | jq --raw-output .top_domains[0].domain) @@ -279,60 +276,60 @@ GetSummaryInformation() { } GetSystemInformation() { - # System uptime - if [ "$1" = "pico" ] || [ "$1" = "nano" ] || [ "$1" = "micro" ]; then - system_uptime=$(uptime | awk -F'( |,|:)+' '{if ($7=="min") m=$6; else {if ($7~/^day/){if ($9=="min") {d=$6;m=$8} else {d=$6;h=$8;m=$9}} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours"}') - else - system_uptime=$(uptime | awk -F'( |,|:)+' '{if ($7=="min") m=$6; else {if ($7~/^day/){if ($9=="min") {d=$6;m=$8} else {d=$6;h=$8;m=$9}} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes"}') - fi + # System uptime + system_uptime_raw=$(echo "${summary}" | jq .system.uptime ) + if [ "$1" = "pico" ] || [ "$1" = "nano" ] || [ "$1" = "micro" ]; then + system_uptime="$(printf '%d days, %d hours' $((system_uptime_raw/86400)) $((system_uptime_raw%86400/3600)))" + else + system_uptime="$(printf '%d days, %d hours, %d minutes' $((system_uptime_raw/86400)) $((system_uptime_raw%86400/3600)) $((system_uptime_raw%3600/60)))" + fi - # CPU temperature - if [ -f /sys/class/thermal/thermal_zone0/temp ]; then - cpu=$(cat /sys/class/thermal/thermal_zone0/temp) - elif [ -f /sys/class/hwmon/hwmon0/temp1_input ]; then - cpu=$(cat /sys/class/hwmon/hwmon0/temp1_input) - else - cpu=0 - fi + # CPU temperature is returned in °C + cpu_temp=$(echo "${summary}" | jq .system.sensors[0].value ) - # Convert CPU temperature to correct unit - if [ "${TEMPERATUREUNIT}" = "F" ]; then - temperature="$(printf %.1f "$(echo "${cpu}" | awk '{print $1 * 9 / 5000 + 32}')")°F" - elif [ "${TEMPERATUREUNIT}" = "K" ]; then - temperature="$(printf %.1f "$(echo "${cpu}" | awk '{print $1 / 1000 + 273.15}')")°K" - # Addresses Issue 1: https://github.com/jpmck/PAD/issues/1 - else - temperature="$(printf %.1f "$(echo "${cpu}" | awk '{print $1 / 1000}')")°C" - fi + # Convert CPU temperature to correct unit + if [ "${TEMPERATUREUNIT}" = "F" ]; then + temperature="$(printf %.1f "$(echo "${cpu_temp}" | awk '{print $1 * 9 / 5 + 32}')")°F" + elif [ "${TEMPERATUREUNIT}" = "K" ]; then + temperature="$(printf %.1f "$(echo "${cpu_temp}" | awk '{print $1 + 273.15}')")°K" + else + temperature="$(printf %.1f "${cpu_temp}" )°C" + fi - # CPU load, heatmap - cpu_load_1=$(awk '{print $1}' < /proc/loadavg) - cpu_load_5=$(awk '{print $2}' < /proc/loadavg) - cpu_load_15=$(awk '{print $3}' < /proc/loadavg) - cpu_load_1_heatmap=$(HeatmapGenerator "${cpu_load_1}" "${core_count}") - cpu_load_5_heatmap=$(HeatmapGenerator "${cpu_load_5}" "${core_count}") - cpu_load_15_heatmap=$(HeatmapGenerator "${cpu_load_15}" "${core_count}") - cpu_percent=$(printf %.1f "$(echo "${cpu_load_1} ${core_count}" | awk '{print ($1 / $2) * 100}')") - - # CPU temperature heatmap - # If we're getting close to 85°C... (https://www.raspberrypi.org/blog/introducing-turbo-mode-up-to-50-more-performance-for-free/) - if [ ${cpu} -gt 80000 ]; then - temp_heatmap=${blinking_text}${red_text} - pico_status="${pico_status_hot}" - mini_status="${mini_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" - tiny_status="${tiny_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" - full_status="${full_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" - mega_status="${mega_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" - elif [ ${cpu} -gt 70000 ]; then - temp_heatmap=${magenta_text} - elif [ ${cpu} -gt 60000 ]; then - temp_heatmap=${blue_text} - else - temp_heatmap=${cyan_text} - fi + # CPU, load, heatmap + core_count=$(echo "${summary}" | jq .system.cpu.nprocs) + cpu_load_1=$(printf %.2f "$(echo "${summary}" | jq .system.cpu.load.raw[0])") + cpu_load_5=$(printf %.2f "$(echo "${summary}" | jq .system.cpu.load.raw[1])") + cpu_load_15=$(printf %.2f "$(echo "${summary}" | jq .system.cpu.load.raw[2])") + cpu_load_1_heatmap=$(HeatmapGenerator "${cpu_load_1}" "${core_count}") + cpu_load_5_heatmap=$(HeatmapGenerator "${cpu_load_5}" "${core_count}") + cpu_load_15_heatmap=$(HeatmapGenerator "${cpu_load_15}" "${core_count}") + cpu_percent=$(printf %.1f "$(echo "${summary}" | jq .system.cpu.load.percent[0])") + + # CPU temperature heatmap + # If we're getting close to 85°C... (https://www.raspberrypi.org/blog/introducing-turbo-mode-up-to-50-more-performance-for-free/) + + # Remove decimal accuracy + cpu_temp=$(echo "${cpu_temp}" | cut -d '.' -f1) + if [ "${cpu_temp}" -gt 80 ]; then + temp_heatmap=${blinking_text}${red_text} + pico_status="${pico_status_hot}" + mini_status="${mini_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" + tiny_status="${tiny_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" + full_status="${full_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" + mega_status="${mega_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" + elif [ "${cpu_temp}" -gt 70 ]; then + temp_heatmap=${magenta_text} + elif [ "${cpu_temp}" -gt 60 ]; then + temp_heatmap=${blue_text} + else + temp_heatmap=${cyan_text} + fi # Memory use, heatmap and bar - memory_percent=$(awk '/MemTotal:/{total=$2} /MemFree:/{free=$2} /Buffers:/{buffers=$2} /^Cached:/{cached=$2} END {printf "%.1f", (total-free-buffers-cached)*100/total}' '/proc/meminfo') + memory_total=$(echo "${summary}" | jq .system.memory.ram.total) + memory_available=$(echo "${summary}" | jq .system.memory.ram.available) + memory_percent=$(printf %.1f $(((memory_total-memory_available)*100/memory_total)) ) memory_heatmap=$(HeatmapGenerator "${memory_percent}") # Bar generations @@ -513,7 +510,7 @@ GetPiholeInformation() { fi # Get Pi-hole (blocking) status - ftl_dns_port=$(GetFTLData "/dns/port" | jq .dns-port) + ftl_dns_port=$(GetFTLData "/dns/port" | jq .dns_port) # ${ftl_dns_port} == 0 DNS server part of dnsmasq disabled, ${ftl_status} == "Not running" no ftlPID found if [ "${ftl_dns_port}" = 0 ] || [ "${ftl_status}" = "Not running" ]; then @@ -1111,9 +1108,9 @@ StartupRoutine(){ # Get our information for the first time printf "%b" " [■■■■······] 40%\\r" - GetSystemInformation "$1" - printf "%b" " [■■■■■·····] 50%\\r" GetSummaryInformation "$1" + printf "%b" " [■■■■■·····] 50%\\r" + GetSystemInformation "$1" printf "%b" " [■■■■■■····] 60%\\r" GetPiholeInformation "$1" printf "%b" " [■■■■■■■···] 70%\\r" @@ -1137,11 +1134,12 @@ StartupRoutine(){ echo "Starting PADD." # Get our information for the first time + echo "- Gathering Summary info." + GetSummaryInformation "mini" echo "- Gathering system info." GetSystemInformation "mini" echo "- Gathering Pi-hole info." GetPiholeInformation "mini" - GetSummaryInformation "mini" echo "- Gathering network info." GetNetworkInformation "mini" echo "- Gathering version info." @@ -1169,10 +1167,11 @@ StartupRoutine(){ # Get our information for the first time + echo "- Gathering Summary information..." + GetSummaryInformation "$1" echo "- Gathering system information..." GetSystemInformation "$1" echo "- Gathering Pi-hole information..." - GetSummaryInformation "$1" GetPiholeInformation "$1" echo "- Gathering network information..." GetNetworkInformation "$1" @@ -1228,18 +1227,18 @@ NormalPADD() { # Start getting our information for next round now=$(date +%s) - # Get uptime, CPU load, temp, etc. every 5 seconds - if [ $((now - LastCheckSystemInformation)) -ge 5 ]; then - GetSystemInformation ${padd_size} - LastCheckSystemInformation="${now}" - fi - # Get cache info, last ad domain, blocking percentage, etc. every 5 seconds if [ $((now - LastCheckSummaryInformation)) -ge 5 ]; then GetSummaryInformation ${padd_size} LastCheckSummaryInformation="${now}" fi + # Get uptime, CPU load, temp, etc. every 5 seconds + if [ $((now - LastCheckSystemInformation)) -ge 5 ]; then + GetSystemInformation ${padd_size} + LastCheckSystemInformation="${now}" + fi + # Get FTL status every 5 seconds if [ $((now - LastCheckPiholeInformation)) -ge 5 ]; then GetPiholeInformation ${padd_size} From 67184b79d40f7eb051ce3d248854b2c9593e25ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 18 Jul 2022 11:26:51 +0200 Subject: [PATCH 06/81] Use API for GetNetworkInformation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 62 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/padd.sh b/padd.sh index 7ec86a07..faa8f483 100755 --- a/padd.sh +++ b/padd.sh @@ -166,7 +166,7 @@ DeleteSession() { case "${deleteResponse}" in "200") printf "%b" "\nA session that was not created cannot be deleted (e.g., empty API password).\n";; "401") printf "%b" "\nLogout attempt without a valid session. Unauthorized!\n";; - "410") printf "%b" "\nSession successfully deleted.\n";; + "410") printf "%b" "\n\nSession successfully deleted.\n";; esac; fi @@ -230,7 +230,7 @@ GetSummaryInformation() { cache_evictions=$(echo "$cache_info" | jq .evicted) cache_inserts=$(echo "$cache_info"| jq .inserted) - latest_blocked=$(GetFTLData "/stats/recent_blocked&show=1" | jq --raw-output .blocked[0]) + latest_blocked=$(GetFTLData "/stats/recent_blocked?show=1" | jq --raw-output .blocked[0]) top_blocked=$(GetFTLData "/stats/top_blocked" | jq --raw-output .top_domains[0].domain) @@ -344,45 +344,41 @@ GetSystemInformation() { memory_bar=$(BarGenerator "${memory_percent}" 10) fi - # Device model - if [ -f /sys/firmware/devicetree/base/model ]; then - # Get model, remove possible null byte - sys_model=$(tr -d '\0' < /sys/firmware/devicetree/base/model) - else - sys_model="" - fi + # Device model + sys_model=$(echo "${summary}" | jq --raw-output .system.model) } GetNetworkInformation() { - # Get pi IPv4 address - pi_ip4_addrs="$(ip addr | grep 'inet ' | grep -v '127.0.0.1/8' | awk '{print $2}' | cut -f1 -d'/' |wc -l)" - if [ "${pi_ip4_addrs}" -eq 0 ]; then - # No IPv4 address available - pi_ip4_addr="N/A" - elif [ "${pi_ip4_addrs}" -eq 1 ]; then - # One IPv4 address available - pi_ip4_addr="$(ip addr | grep 'inet ' | grep -v '127.0.0.1/8' | awk '{print $2}' | cut -f1 -d'/' | head -n 1)" - else - # More than one IPv4 address available - pi_ip4_addr="$(ip addr | grep 'inet ' | grep -v '127.0.0.1/8' | awk '{print $2}' | cut -f1 -d'/' | head -n 1)+" - fi + interfaces_raw=$(GetFTLData "/ftl/interfaces") + # Get pi IPv4 address of the default interface + pi_ip4_addrs="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].ipv4 | sed "s/127.0.0.1,//g" | tr "," " " | wc -w)" + if [ "${pi_ip4_addrs}" -eq 0 ]; then + # No IPv4 address available + pi_ip4_addr="N/A" + elif [ "${pi_ip4_addrs}" -eq 1 ]; then + # One IPv4 address available + pi_ip4_addr="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].ipv4 | sed "s/127.0.0.1,//g" | awk -F ',' '{printf $1}')" + else + # More than one IPv4 address available + pi_ip4_addr="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].ipv4 | sed "s/127.0.0.1,//g"| awk -F ',' '{printf $1}')+" + fi - # Get pi IPv6 address - pi_ip6_addrs="$(ip addr | grep 'inet6 ' | grep -v '::1/128' | awk '{print $2}' | cut -f1 -d'/' | wc -l)" + # Get pi IPv6 address of the default interface + pi_ip6_addrs="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].ipv6 | sed "s/::1,//g" | tr "," " " | wc -w)" if [ "${pi_ip6_addrs}" -eq 0 ]; then # No IPv6 address available pi_ip6_addr="N/A" elif [ "${pi_ip6_addrs}" -eq 1 ]; then # One IPv6 address available - pi_ip6_addr="$(ip addr | grep 'inet6 ' | grep -v '::1/128' | awk '{print $2}' | cut -f1 -d'/' | head -n 1)" + pi_ip6_addr="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].ipv6 | sed "s/::1,//g" | awk -F ',' '{printf $1}')" else # More than one IPv6 address available - pi_ip6_addr="$(ip addr | grep 'inet6 ' | grep -v '::1/128' | awk '{print $2}' | cut -f1 -d'/' | head -n 1)+" + pi_ip6_addr="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].ipv6 | sed "s/::1,//g" | awk -F ',' '{printf $1}')+" fi # Get hostname and gateway pi_hostname=$(hostname) - pi_gateway=$(ip r | grep 'default' | awk '{print $3}') + pi_gateway=$(echo "${interfaces_raw}" | jq --raw-output .gateway.address) full_hostname=${pi_hostname} # does the Pi-hole have a domain set? @@ -481,11 +477,15 @@ GetNetworkInformation() { conditional_forwarding_heatmap=${red_text} fi - #Default interface data - def_iface_data=$(GetFTLData "interfaces" | head -n1) - iface_name="$(echo "$def_iface_data" | awk '{print $1}')" - tx_bytes="$(echo "$def_iface_data" | awk '{print $4}')" - rx_bytes="$(echo "$def_iface_data" | awk '{print $5}')" + #Default interface data + iface_name="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].name)" + tx_bytes="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].tx.num)" + tx_bytes_unit="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].tx.unit)" + tx_bytes=$(printf "%.1f %b" "${tx_bytes}" "${tx_bytes_unit}") + + rx_bytes="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].rx.num)" + rx_bytes_unit="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].rx.unit)" + rx_bytes=$(printf "%.1f %b" "${rx_bytes}" "${rx_bytes_unit}") } GetPiholeInformation() { From f92afc742912061b32fe24277cece21b0198e858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 18 Jul 2022 14:07:12 +0200 Subject: [PATCH 07/81] Use API for GetVersionInformation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 128 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 67 insertions(+), 61 deletions(-) diff --git a/padd.sh b/padd.sh index faa8f483..4ab329c3 100755 --- a/padd.sh +++ b/padd.sh @@ -543,77 +543,83 @@ GetPiholeInformation() { } GetVersionInformation() { - # Check if version status has been saved - core_version=$(pihole -v -p | awk '{print $4}' | tr -d '[:alpha:]') - core_version_latest=$(pihole -v -p | awk '{print $(NF)}' | tr -d ')') - - # if core_version is something else then x.xx or x.xx.xxx set it to N/A - if ! echo "${core_version}" | grep -qE '^[0-9]+([.][0-9]+){1,2}$' || [ "${core_version_latest}" = "ERROR" ]; then - core_version="N/A" - core_version_heatmap=${yellow_text} - else - # remove the leading "v" from core_version_latest - core_version_latest=$(echo "${core_version_latest}" | tr -d '\r\n[:alpha:]') - # is core up-to-date? - if [ "${core_version}" != "${core_version_latest}" ]; then - out_of_date_flag="true" - core_version_heatmap=${red_text} + + versions_raw=$(GetFTLData "/version") + + # Check if core version + core_branch="$(echo "${versions_raw}" | jq --raw-output .core.branch)" + core_version=$(echo "${versions_raw}" | jq --raw-output .core.tag | tr -d '[:alpha:]' | awk -F '-' '{printf $1}') + core_version_latest=$(pihole -v -p | awk '{print $(NF)}' | tr -d ')') + + # if core_version is something else then x.xx or x.xx.xxx or branch not master set it to N/A + if ! echo "${core_version}" | grep -qE '^[0-9]+([.][0-9]+){1,2}$' || [ ! "${core_branch}" = "master" ]; then + core_version="N/A" + core_version_heatmap=${yellow_text} else - core_version_heatmap=${green_text} + # remove the leading "v" from core_version_latest + core_version_latest=$(echo "${core_version_latest}" | tr -d '\r\n[:alpha:]') + # is core up-to-date? + if [ "${core_version}" != "${core_version_latest}" ]; then + out_of_date_flag="true" + core_version_heatmap=${red_text} + else + core_version_heatmap=${green_text} + fi + # add leading "v" to version number + core_version="v${core_version}" fi - # add leading "v" to version number - core_version="v${core_version}" - fi - # Gather web version information... - if [ "$INSTALL_WEB_INTERFACE" = true ]; then - web_version=$(pihole -v -a | awk '{print $4}' | tr -d '[:alpha:]') - web_version_latest=$(pihole -v -a | awk '{print $(NF)}' | tr -d ')') + # Gather web version information... + if [ "$INSTALL_WEB_INTERFACE" = true ]; then + web_branch="$(echo "${versions_raw}" | jq --raw-output .web.branch)" + web_version=$(echo "${versions_raw}" | jq --raw-output .web.tag | tr -d '[:alpha:]' | awk -F '-' '{printf $1}') + web_version_latest=$(pihole -v -a | awk '{print $(NF)}' | tr -d ')') - # if web_version is something else then x.xx or x.xx.xxx set it to N/A - if ! echo "${web_version}" | grep -qE '^[0-9]+([.][0-9]+){1,2}$' || [ "${web_version_latest}" = "ERROR" ]; then - web_version="N/A" - web_version_heatmap=${yellow_text} + # if web_version is something else then x.xx or x.xx.xxx or branch not master set it to N/A + if ! echo "${web_version}" | grep -qE '^[0-9]+([.][0-9]+){1,2}$' || [ ! "${web_branch}" = "master" ]; then + web_version="N/A" + web_version_heatmap=${yellow_text} + else + # remove the leading "v" from web_version_latest + web_version_latest=$(echo "${web_version_latest}" | tr -d '\r\n[:alpha:]') + # is web up-to-date? + if [ "${web_version}" != "${web_version_latest}" ]; then + out_of_date_flag="true" + web_version_heatmap=${red_text} + else + web_version_heatmap=${green_text} + fi + # add leading "v" to version number + web_version="v${web_version}" + fi else - # remove the leading "v" from web_version_latest - web_version_latest=$(echo "${web_version_latest}" | tr -d '\r\n[:alpha:]') - # is web up-to-date? - if [ "${web_version}" != "${web_version_latest}" ]; then - out_of_date_flag="true" - web_version_heatmap=${red_text} - else - web_version_heatmap=${green_text} - fi - # add leading "v" to version number - web_version="v${web_version}" + # Web interface not installed + web_version="N/A" + web_version_heatmap=${yellow_text} fi - else - # Web interface not installed - web_version="N/A" - web_version_heatmap=${yellow_text} - fi - # Gather FTL version information... - ftl_version=$(pihole -v -f | awk '{print $4}' | tr -d '[:alpha:]') - ftl_version_latest=$(pihole -v -f | awk '{print $(NF)}' | tr -d ')') + # Gather FTL version information... + ftl_branch="$(echo "${versions_raw}" | jq --raw-output .ftl.branch)" + ftl_version=$(echo "${versions_raw}" | jq --raw-output .ftl.tag | tr -d '[:alpha:]' | awk -F '-' '{printf $1}') + ftl_version_latest=$(pihole -v -f | awk '{print $(NF)}' | tr -d ')') - # if ftl_version is something else then x.xx or x.xx.xxx set it to N/A - if ! echo "${ftl_version}" | grep -qE '^[0-9]+([.][0-9]+){1,2}$' || [ "${ftl_version_latest}" = "ERROR" ]; then - ftl_version="N/A" - ftl_version_heatmap=${yellow_text} - else - # remove the leading "v" from ftl_version_latest - ftl_version_latest=$(echo "${ftl_version_latest}" | tr -d '\r\n[:alpha:]') - # is ftl up-to-date? - if [ "${ftl_version}" != "${ftl_version_latest}" ]; then - out_of_date_flag="true" - ftl_version_heatmap=${red_text} + # if ftl_version is something else then x.xx or x.xx.xxx or branch not master set it to N/A + if ! echo "${ftl_version}" | grep -qE '^[0-9]+([.][0-9]+){1,2}$' || [ ! "${ftl_branch}" = "master" ]; then + ftl_version="N/A" + ftl_version_heatmap=${yellow_text} else - ftl_version_heatmap=${green_text} + # remove the leading "v" from ftl_version_latest + ftl_version_latest=$(echo "${ftl_version_latest}" | tr -d '\r\n[:alpha:]') + # is ftl up-to-date? + if [ "${ftl_version}" != "${ftl_version_latest}" ]; then + out_of_date_flag="true" + ftl_version_heatmap=${red_text} + else + ftl_version_heatmap=${green_text} + fi + # add leading "v" to version number + ftl_version="v${ftl_version}" fi - # add leading "v" to version number - ftl_version="v${ftl_version}" - fi # PADD version information... padd_version_latest="$(curl --silent https://api.github.com/repos/pi-hole/PADD/releases/latest | grep '"tag_name":' | awk -F \" '{print $4}')" From 7531a1a45928b6a7841bf05d39bb2929f53dc7ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 18 Jul 2022 14:09:54 +0200 Subject: [PATCH 08/81] Remove CheckConnectivity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 69 --------------------------------------------------------- 1 file changed, 69 deletions(-) diff --git a/padd.sh b/padd.sh index 4ab329c3..97ea5ff6 100755 --- a/padd.sh +++ b/padd.sh @@ -639,7 +639,6 @@ GetVersionInformation() { fi fi - # was any portion of Pi-hole out-of-date? # yes, pi-hole is out of date if [ "${out_of_date_flag}" = "true" ]; then @@ -1016,68 +1015,6 @@ SizeChecker(){ fi } -CheckConnectivity() { - connectivity="false" - connection_attempts=1 - wait_timer=1 - - while [ $connection_attempts -lt 9 ]; do - - if nc -zw1 google.com 443 2>/dev/null; then - if [ "$1" = "pico" ] || [ "$1" = "nano" ] || [ "$1" = "micro" ]; then - echo "Attempt #${connection_attempts} passed..." - elif [ "$1" = "mini" ]; then - echo "Attempt ${connection_attempts} passed." - else - echo " - Attempt ${connection_attempts} passed... " - fi - - connectivity="true" - connection_attempts=11 - else - connection_attempts=$((connection_attempts+1)) - - inner_wait_timer=$((wait_timer*1)) - - # echo "$wait_timer = $inner_wait_timer" - while [ $inner_wait_timer -gt 0 ]; do - if [ "$1" = "pico" ] || [ "$1" = "nano" ] || [ "$1" = "micro" ]; then - printf "%b" "Attempt #${connection_attempts} failed...\\r" - elif [ "$1" = "mini" ] || [ "$1" = "tiny" ]; then - printf "%b" "- Attempt ${connection_attempts} failed, wait ${inner_wait_timer} \\r" - else - printf "%b" " - Attempt ${connection_attempts} failed... waiting ${inner_wait_timer} seconds... \\r" - fi - sleep 1 - inner_wait_timer=$((inner_wait_timer-1)) - done - - # echo -ne "Attempt $connection_attempts failed... waiting $wait_timer seconds...\\r" - # sleep $wait_timer - wait_timer=$((wait_timer*2)) - fi - - done - - if [ "$connectivity" = "false" ]; then - if [ "$1" = "pico" ] || [ "$1" = "nano" ] || [ "$1" = "micro" ]; then - echo "Check failed..." - elif [ "$1" = "mini" ] || [ "$1" = "tiny" ]; then - echo "- Connectivity check failed." - else - echo " - Connectivity check failed..." - fi - else - if [ "$1" = "pico" ] || [ "$1" = "nano" ] || [ "$1" = "micro" ]; then - echo "Check passed..." - elif [ "$1" = "mini" ] || [ "$1" = "tiny" ]; then - echo "- Connectivity check passed." - else - echo " - Connectivity check passed..." - fi - fi -} - # converts a given version string e.g. v3.7.1 to 3007001000 to allow for easier comparison of multi digit version numbers # credits https://apple.stackexchange.com/a/123408 VersionConverter() { @@ -1097,8 +1034,6 @@ StartupRoutine(){ if [ "$1" = "pico" ] || [ "$1" = "nano" ] || [ "$1" = "micro" ]; then PrintLogo "$1" printf "%b" "START-UP ===========\n" - printf "%b" "Checking Internet connection.\n" - CheckConnectivity "$1" # Authenticate with the FTL server printf "%b" "Establishing connection with FTL...\n" @@ -1129,8 +1064,6 @@ StartupRoutine(){ elif [ "$1" = "mini" ]; then PrintLogo "$1" echo "START UP =====================" - echo "Checking connectivity." - CheckConnectivity "$1" # Authenticate with the FTL server printf "%b" "Establishing connection with FTL...\n" @@ -1164,8 +1097,6 @@ StartupRoutine(){ echo "START UP ===================================================" fi - printf "%b" "- Checking internet connection...\n" - CheckConnectivity "$1" # Authenticate with the FTL server printf "%b" "Establishing connection with FTL...\n" From cc9a9f83d183665a7856f5a6ea84917f6884a728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 18 Jul 2022 19:23:32 +0200 Subject: [PATCH 09/81] Set DHCP_ROUTER via API, turn cursor back on when exiting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/padd.sh b/padd.sh index 97ea5ff6..b114adca 100755 --- a/padd.sh +++ b/padd.sh @@ -236,7 +236,7 @@ GetSummaryInformation() { top_domain=$(GetFTLData "/stats/top_domains" | jq --raw-output .top_domains[0].domain) - top_client=$(GetFTLData "/stats/top_clients " | jq --raw-output .top_clients[0].name) + top_client=$(GetFTLData "/stats/top_clients" | jq --raw-output .top_clients[0].name) if [ "$1" = "pico" ] || [ "$1" = "nano" ] || [ "$1" = "micro" ]; then ads_blocked_bar=$(BarGenerator "$ads_percentage_today" 10 "color") @@ -445,9 +445,8 @@ GetNetworkInformation() { dhcp_check_box=${check_box_bad} # if the DHCP Router variable isn't set - # Issue 3: https://github.com/jpmck/PADD/issues/3 if [ -z ${DHCP_ROUTER+x} ]; then - DHCP_ROUTER=$(GetFTLData "gateway" | awk '{ printf $1 }') + DHCP_ROUTER=$(printf %b "${interfaces_raw}" | jq --raw-output .gateway.address) fi dhcp_info=" Router: ${DHCP_ROUTER}" @@ -1242,6 +1241,9 @@ clean_exit() { stty "${stty_orig}" fi + # Turn cursor on + setterm -cursor on + # Delete session from FTL server DeleteSession exit $err # exit the script with saved $? From 0e008799b00535d733b7c08f7421644790a040ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 18 Jul 2022 22:21:03 +0200 Subject: [PATCH 10/81] Make OutputJSON compatible with FTLv6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/padd.sh b/padd.sh index b114adca..cd14dc6e 100755 --- a/padd.sh +++ b/padd.sh @@ -116,7 +116,7 @@ TestAPIAvailability() { # test if http status code was 200 (OK) if [ "${availabilityResonse}" = 200 ]; then - printf "%b" "API available at: http://${URL}:${PORT}/${APIPATH}\n\n" + printf "%b" "API available at: http://${URL}:${PORT}/${APIPATH}\n" else echo "API not available at: http://${URL}:${PORT}/${APIPATH}" echo "Exiting." @@ -307,8 +307,6 @@ GetSystemInformation() { cpu_percent=$(printf %.1f "$(echo "${summary}" | jq .system.cpu.load.percent[0])") # CPU temperature heatmap - # If we're getting close to 85°C... (https://www.raspberrypi.org/blog/introducing-turbo-mode-up-to-50-more-performance-for-free/) - # Remove decimal accuracy cpu_temp=$(echo "${cpu_temp}" | cut -d '.' -f1) if [ "${cpu_temp}" -gt 80 ]; then @@ -1023,9 +1021,24 @@ VersionConverter() { ########################################## MAIN FUNCTIONS ########################################## OutputJSON() { - GetSummaryInformation - echo "{\"domains_being_blocked\":${domains_being_blocked_raw},\"dns_queries_today\":${dns_queries_today_raw},\"ads_blocked_today\":${ads_blocked_today_raw},\"ads_percentage_today\":${ads_percentage_today_raw},\"clients\": ${clients}}" - exit 0 + # Traps for graceful shutdown + # https://unix.stackexchange.com/a/681201 + trap clean_exit EXIT + trap sig_cleanup INT QUIT TERM + + # Save current terminal settings (needed for later restore after password prompt) + stty_orig=$(stty -g) + # Construct FTL's API address depending on the arguments supplied + ConstructAPI + # Test if the authentication endpoint is availabe + TestAPIAvailability + # Authenticate with the FTL server + printf "%b" "Establishing connection with FTL...\n" + Authenthication + + GetSummaryInformation + echo "{\"domains_being_blocked\":${domains_being_blocked_raw},\"dns_queries_today\":${dns_queries_today_raw},\"ads_blocked_today\":${ads_blocked_today_raw},\"ads_percentage_today\":${ads_percentage_today},\"clients\": ${clients}}" + exit 0 } StartupRoutine(){ @@ -1209,8 +1222,8 @@ DisplayHelp() { ::: -p Port of your Pi-hole's API (default: 8080) ::: -a Path where your Pi-hole's API is hosted (default: api) ::: -s Your Pi-hole's password, required to access the API -::: -j output stats as JSON formatted string and exit -::: -h display this help text +::: -j output stats as JSON formatted string and exit +::: -h display this help text EOM exit 0 } From bb6f8b356229498a44b6a9e519696974c731114c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 18 Jul 2022 22:27:18 +0200 Subject: [PATCH 11/81] Remove commas between component's version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/padd.sh b/padd.sh index cd14dc6e..f75d3dd5 100755 --- a/padd.sh +++ b/padd.sh @@ -697,7 +697,7 @@ PrintLogo() { CleanEcho "${padd_text}${dim_text}mini${reset_text} ${mini_status}" CleanEcho "" elif [ "$1" = "tiny" ]; then - CleanEcho "${padd_text}${dim_text}tiny${reset_text} Pi-hole® ${core_version_heatmap}${core_version}${reset_text}, Web ${web_version_heatmap}${web_version}${reset_text}, FTL ${ftl_version_heatmap}${ftl_version}${reset_text}" + CleanEcho "${padd_text}${dim_text}tiny${reset_text} Pi-hole® ${core_version_heatmap}${core_version}${reset_text} Web ${web_version_heatmap}${web_version}${reset_text} FTL ${ftl_version_heatmap}${ftl_version}${reset_text}" CleanPrintf " PADD ${padd_version_heatmap}${padd_version}${reset_text} ${tiny_status}${reset_text}\e[0K\\n" elif [ "$1" = "slim" ]; then CleanEcho "${padd_text}${dim_text}slim${reset_text} ${full_status}" @@ -705,13 +705,13 @@ PrintLogo() { # For the next two, use printf to make sure spaces aren't collapsed elif [ "$1" = "regular" ] || [ "$1" = "slim" ]; then CleanPrintf "${padd_logo_1}\e[0K\\n" - CleanPrintf "${padd_logo_2}Pi-hole® ${core_version_heatmap}${core_version}${reset_text}, Web ${web_version_heatmap}${web_version}${reset_text}, FTL ${ftl_version_heatmap}${ftl_version}${reset_text}\e[0K\\n" + CleanPrintf "${padd_logo_2}Pi-hole® ${core_version_heatmap}${core_version}${reset_text} Web ${web_version_heatmap}${web_version}${reset_text} FTL ${ftl_version_heatmap}${ftl_version}${reset_text}\e[0K\\n" CleanPrintf "${padd_logo_3}PADD ${padd_version_heatmap}${padd_version}${reset_text} ${full_status}${reset_text}\e[0K\\n" CleanEcho "" # normal or not defined else CleanPrintf "${padd_logo_retro_1}\e[0K\\n" - CleanPrintf "${padd_logo_retro_2} Pi-hole® ${core_version_heatmap}${core_version}${reset_text}, Web ${web_version_heatmap}${web_version}${reset_text}, FTL ${ftl_version_heatmap}${ftl_version}${reset_text}, PADD ${padd_version_heatmap}${padd_version}${reset_text}\e[0K\\n" + CleanPrintf "${padd_logo_retro_2} Pi-hole® ${core_version_heatmap}${core_version}${reset_text} Web ${web_version_heatmap}${web_version}${reset_text} FTL ${ftl_version_heatmap}${ftl_version}${reset_text} PADD ${padd_version_heatmap}${padd_version}${reset_text}\e[0K\\n" CleanPrintf "${padd_logo_retro_3} ${pihole_check_box} Core ${ftl_check_box} FTL ${mega_status}${reset_text}\e[0K\\n" CleanEcho "" From afd573e9086672d12520e7a52cefe2a9d68d48d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 19 Jul 2022 15:20:06 +0200 Subject: [PATCH 12/81] Rebase on development including new VersionConverter() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/padd.sh b/padd.sh index f75d3dd5..d986e70b 100755 --- a/padd.sh +++ b/padd.sh @@ -618,23 +618,23 @@ GetVersionInformation() { ftl_version="v${ftl_version}" fi - # PADD version information... - padd_version_latest="$(curl --silent https://api.github.com/repos/pi-hole/PADD/releases/latest | grep '"tag_name":' | awk -F \" '{print $4}')" - # is PADD up-to-date? - if [ -z "${padd_version_latest}" ]; then - padd_version_heatmap=${yellow_text} - else - padd_version_latest_converted="$(VersionConverter "${padd_version_latest}")" - padd_version_converted=$(VersionConverter "${padd_version}") - - if [ "${padd_version_converted}" -lt "${padd_version_latest_converted}" ]; then - padd_out_of_date_flag="true" - padd_version_heatmap=${red_text} + # PADD version information... + padd_version_latest="$(curl --silent https://api.github.com/repos/pi-hole/PADD/releases/latest | grep '"tag_name":' | awk -F \" '{print $4}')" + # is PADD up-to-date? + if [ -z "${padd_version_latest}" ]; then + padd_version_heatmap=${yellow_text} else - # local and remote PADD version match or local is newer - padd_version_heatmap=${green_text} + padd_version_latest_converted="$(VersionConverter "${padd_version_latest}")" + padd_version_converted=$(VersionConverter "${padd_version}") + + if [ "${padd_version_converted}" -lt "${padd_version_latest_converted}" ]; then + padd_out_of_date_flag="true" + padd_version_heatmap=${red_text} + else + # local and remote PADD version match or local is newer + padd_version_heatmap=${green_text} + fi fi - fi # was any portion of Pi-hole out-of-date? # yes, pi-hole is out of date From 2096d3b9c526ddd2ce5a13860f9897c5d05214e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 6 Jan 2023 21:36:04 +0100 Subject: [PATCH 13/81] Don't allow $validSession to be empty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/padd.sh b/padd.sh index d986e70b..43fd9795 100755 --- a/padd.sh +++ b/padd.sh @@ -128,7 +128,7 @@ Authenthication() { # Try to authenticate ChallengeResponse - while [ "${validSession}" = false ]; do + while [ "${validSession}" = false ] || [ -z "${validSession}" ] ; do echo "Authentication failed." # no password was supplied as argument From a726df6e60d63430721f3fc3b165ec15aea954ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sat, 14 Jan 2023 14:41:19 +0100 Subject: [PATCH 14/81] Mix merge mess MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 215 +++++++++++++++++++++++--------------------------------- 1 file changed, 86 insertions(+), 129 deletions(-) diff --git a/padd.sh b/padd.sh index c19ecff9..2db64454 100755 --- a/padd.sh +++ b/padd.sh @@ -84,7 +84,6 @@ mega_status_hot="${check_box_bad} Your system is hot!" mega_status_off="${check_box_info} Blocking is disabled!" mega_status_ftl_down="${check_box_bad} FTLDNS service is not running!" mega_status_dns_down="${check_box_bad} Pi-hole's DNS server is off!" -mega_status_unknown="${check_box_question} Unable to determine Pi-hole status!" # TINY STATUS tiny_status_ok="${check_box_good} System is healthy" @@ -122,7 +121,7 @@ ConstructAPI() { TestAPIAvailability() { - availabilityResonse=$(curl -s -o /dev/null -w "%{http_code}" http://${URL}:${PORT}/${APIPATH}/auth) + availabilityResonse=$(curl -s -o /dev/null -w "%{http_code}" "http://${URL}:${PORT}/${APIPATH}/auth") # test if http status code was 200 (OK) if [ "${availabilityResonse}" = 200 ]; then @@ -171,7 +170,7 @@ DeleteSession() { # SID is not null (successful authenthication only), delete the session if [ "${validSession}" = true ] && [ ! "${SID}" = null ]; then # Try to delte the session. Omitt the output, but get the http status code - deleteResponse=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE http://${URL}:${PORT}/${APIPATH}/auth -H "Accept: application/json" -H "sid: ${SID}") + deleteResponse=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE "http://${URL}:${PORT}/${APIPATH}/auth" -H "Accept: application/json" -H "sid: ${SID}") case "${deleteResponse}" in "200") printf "%b" "\nA session that was not created cannot be deleted (e.g., empty API password).\n";; @@ -194,9 +193,9 @@ ChallengeResponse() { # Get challenge from FTL # Calculate response based on challenge and password hash # Send response & get session response - challenge="$(curl --silent -X GET http://${URL}:${PORT}/${APIPATH}/auth | jq --raw-output .challenge)" + challenge="$(curl --silent -X GET "http://${URL}:${PORT}/${APIPATH}/auth" | jq --raw-output .challenge)" response="$(printf "%b" "${challenge}:${pwhash}" | sha256sum | sed 's/\s.*$//')" - sessionResponse="$(curl --silent -X POST http://${URL}:${PORT}/${APIPATH}/auth --data "{\"response\":\"${response}\"}" )" + sessionResponse="$(curl --silent -X POST "http://${URL}:${PORT}/${APIPATH}/auth" --data "{\"response\":\"${response}\"}" )" if [ -z "${sessionResponse}" ]; then echo "No response from FTL server. Please check connectivity and use the options to set the API URL" @@ -222,7 +221,7 @@ GetSummaryInformation() { clients=$(echo "${summary}" | jq .ftl.clients.active ) - blocking_status=$(echo "${summary}" | jq .system.dns.blocking ) + blocking_enabled=$(echo "${summary}" | jq .system.dns.blocking ) domains_being_blocked_raw=$(echo "${summary}" | jq .ftl.database.gravity ) domains_being_blocked=$(printf "%.f" "${domains_being_blocked_raw}") @@ -246,10 +245,10 @@ GetSummaryInformation() { top_domain_raw=$(GetFTLData "/stats/top_domains" | jq --raw-output .top_domains[0].domain) - top_client_raw=$(GetFTLData "/stats/top_clients" | jq --raw-output .clients[0].name)) + top_client_raw=$(GetFTLData "/stats/top_clients" | jq --raw-output .clients[0].name) if [ -z "${top_client_raw}" ]; then # if no hostname was supplied, use IP - top_client_raw=$(GetFTLData "/stats/top_clients" | jq --raw-output .clients[0].ip)) + top_client_raw=$(GetFTLData "/stats/top_clients" | jq --raw-output .clients[0].ip) fi } @@ -260,15 +259,15 @@ GetSystemInformation() { # CPU temperature is returned in °C cpu_temp=$(echo "${summary}" | jq .system.sensors[0].value ) - # Convert CPU temperature to correct unit - if [ "${TEMPERATUREUNIT}" = "F" ]; then - temperature="$(printf %.1f "$(echo "${cpu_temp}" | awk '{print $1 * 9 / 5000 + 32}')")°F" - elif [ "${TEMPERATUREUNIT}" = "K" ]; then - temperature="$(printf %.1f "$(echo "${cpu_temp}" | awk '{print $1 / 1000 + 273.15}')")°K" - # Addresses Issue 1: https://github.com/jpmck/PAD/issues/1 - else - temperature="$(printf %.1f "$(echo "${cpu_temp}" | awk '{print $1 / 1000}')")°C" - fi + # Convert CPU temperature to correct unit + if [ "${TEMPERATUREUNIT}" = "F" ]; then + cpu_temp="$(printf %.1f "$(echo "${cpu_temp}" | awk '{print $1 * 9 / 5000 + 32}')")°F" + elif [ "${TEMPERATUREUNIT}" = "K" ]; then + cpu_temp="$(printf %.1f "$(echo "${cpu_temp}" | awk '{print $1 / 1000 + 273.15}')")°K" + # Addresses Issue 1: https://github.com/jpmck/PAD/issues/1 + else + cpu_temp="$(printf %.1f "$(echo "${cpu_temp}" | awk '{print $1 / 1000}')")°C" + fi # CPU, load, heatmap core_count=$(echo "${summary}" | jq .system.cpu.nprocs) @@ -283,13 +282,13 @@ GetSystemInformation() { # CPU temperature heatmap hot_flag=false # If we're getting close to 85°C... (https://www.raspberrypi.org/blog/introducing-turbo-mode-up-to-50-more-performance-for-free/) - if [ ${cpu_tmp} -gt 80000 ]; then + if [ "${cpu_temp}" -gt 80000 ]; then temp_heatmap=${blinking_text}${red_text} # set flag to change the status message in SetStatusMessage() hot_flag=true - elif [ ${cpu_temp} -gt 70000 ]; then + elif [ "${cpu_temp}" -gt 70000 ]; then temp_heatmap=${magenta_text} - elif [ ${cpu_temp} -gt 60000 ]; then + elif [ "${cpu_temp}" -gt 60000 ]; then temp_heatmap=${blue_text} else temp_heatmap=${cyan_text} @@ -503,12 +502,14 @@ GetPiholeInformation() { ftl_status="Running" ftl_heatmap=${green_text} ftl_check_box=${check_box_good} + # Get FTL CPU and memory usage ftl_cpu="$(ps -p "${ftlPID}" -o %cpu | tail -n1 | tr -d '[:space:]')" ftl_mem_percentage="$(ps -p "${ftlPID}" -o %mem | tail -n1 | tr -d '[:space:]')" + # Get Pi-hole (blocking) status + ftl_dns_port=$(GetFTLData "/dns/port" | jq .dns_port) fi - # Get Pi-hole (blocking) status - ftl_dns_port=$(GetFTLData "/dns/port" | jq .dns_port) + # ${ftl_dns_port} == 0 DNS server part of dnsmasq disabled, ${ftl_status} == "Not running" no ftlPID found dns_down_flag=false @@ -527,16 +528,17 @@ fi GetVersionInformation() { + out_of_date_flag=false versions_raw=$(GetFTLData "/version") # Check if core version - core_branch="$(echo "${versions_raw}" | jq --raw-output .core.branch)" - core_version=$(echo "${versions_raw}" | jq --raw-output .core.tag | tr -d '[:alpha:]' | awk -F '-' '{printf $1}') - core_version_latest=$(pihole -v -p | awk '{print $(NF)}' | tr -d ')') - - out_of_date_flag=false + CORE_BRANCH="$(echo "${versions_raw}" | jq --raw-output .core.branch)" + CORE_VERSION=$(echo "${versions_raw}" | jq --raw-output .core.tag | tr -d '[:alpha:]' | awk -F '-' '{printf $1}') + GITHUB_CORE_VERSION=$(pihole -v -p | awk '{print $(NF)}' | tr -d ')') + CORE_HASH + GITHUB_CORE_HASH - # Gather CORE version information... + # Gather core version information... # Extract vx.xx or vx.xx.xxx version CORE_VERSION="$(echo "${CORE_VERSION}" | grep -oE '^v[0-9]+([.][0-9]+){1,2}')" if [ "${CORE_BRANCH}" = "master" ]; then @@ -576,6 +578,9 @@ GetVersionInformation() { if [ "$INSTALL_WEB_INTERFACE" = true ]; then WEB_BRANCH="$(echo "${versions_raw}" | jq --raw-output .web.branch)" WEB_VERSION=$(echo "${versions_raw}" | jq --raw-output .web.tag | tr -d '[:alpha:]' | awk -F '-' '{printf $1}') + GITHUB_WEB_VERSION + WEB_HASH + GITHUB_WEB_HASH if [ "${WEB_BRANCH}" = "master" ]; then web_version_converted="$(VersionConverter "${WEB_VERSION}")" @@ -618,6 +623,10 @@ GetVersionInformation() { # Extract vx.xx or vx.xx.xxx version FTL_BRANCH="$(echo "${versions_raw}" | jq --raw-output .ftl.branch)" FTL_VERSION=$(echo "${versions_raw}" | jq --raw-output .ftl.tag | tr -d '[:alpha:]' | awk -F '-' '{printf $1}') + GITHUB_FTL_VERSION + FTL_HASH + GITHUB_FTL_HASH + if [ "${FTL_BRANCH}" = "master" ]; then ftl_version_converted="$(VersionConverter "${FTL_VERSION}")" @@ -750,10 +759,10 @@ SetStatusMessage() { if [ "${hot_flag}" = true ]; then # Check if CPU temperature is high pico_status="${pico_status_hot}" - mini_status="${mini_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" - tiny_status="${tiny_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" - full_status="${full_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" - mega_status="${mega_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" + mini_status="${mini_status_hot} ${blinking_text}${red_text}${cpu_temp}${reset_text}" + tiny_status="${tiny_status_hot} ${blinking_text}${red_text}${cpu_temp}${reset_text}" + full_status="${full_status_hot} ${blinking_text}${red_text}${cpu_temp}${reset_text}" + mega_status="${mega_status_hot} ${blinking_text}${red_text}${cpu_temp}${reset_text}" elif [ "${ftl_down_flag}" = true ]; then # Check if FTL is down @@ -771,15 +780,7 @@ SetStatusMessage() { full_status=${full_status_dns_down} mega_status=${mega_status_dns_down} - elif [ "${blocking_status}" = "unknown" ]; then - # Check if blocking status is unknown - pico_status=${pico_status_unknown} - mini_status=${mini_status_unknown} - tiny_status=${tiny_status_unknown} - full_status=${full_status_unknown} - mega_status=${mega_status_unknown} - - elif [ "${blocking_status}" = "disabled" ]; then + elif [ "${blocking_enabled}" = "false" ]; then # Check if blocking status is disabled pico_status=${pico_status_off} mini_status=${mini_status_off} @@ -795,7 +796,7 @@ SetStatusMessage() { full_status=${full_status_update} mega_status=${mega_status_update} - elif [ "${blocking_status}" = "enabled" ]; then + elif [ "${blocking_enabled}" = "true" ]; then # if we reach this point and blocking is enabled, everything is fine pico_status=${pico_status_ok} mini_status=${mini_status_ok} @@ -936,7 +937,7 @@ PrintDashboard() { fi moveXOffset; printf "%s${clear_line}\n" "${bold_text}SYSTEM ==============================================${reset_text}" moveXOffset; printf " %-10s%-29s${clear_line}\n" "Uptime:" "${system_uptime}" - moveXOffset; printf " %-10s${temp_heatmap}%-17s${reset_text} %-8s${cpu_load_1_heatmap}%-4s${reset_text}, ${cpu_load_5_heatmap}%-4s${reset_text}, ${cpu_load_15_heatmap}%-4s${reset_text}${clear_line}\n" "CPU Temp:" "${temperature}" "Load:" "${cpu_load_1}" "${cpu_load_5}" "${cpu_load_15}" + moveXOffset; printf " %-10s${temp_heatmap}%-17s${reset_text} %-8s${cpu_load_1_heatmap}%-4s${reset_text}, ${cpu_load_5_heatmap}%-4s${reset_text}, ${cpu_load_15_heatmap}%-4s${reset_text}${clear_line}\n" "CPU Temp:" "${cpu_temp}" "Load:" "${cpu_load_1}" "${cpu_load_5}" "${cpu_load_15}" moveXOffset; printf " %-10s[${memory_heatmap}%-7s${reset_text}] %-6s %-8s[${cpu_load_1_heatmap}%-7s${reset_text}] %-5s${clear_line}" "Memory:" "${memory_bar}" "${memory_percent}%" "CPU:" "${cpu_bar}" "${cpu_percent}%" elif [ "$1" = "regular" ] || [ "$1" = "slim" ]; then # slim is a screen with at least 60 columns and exactly 21 lines @@ -973,7 +974,7 @@ PrintDashboard() { fi moveXOffset; printf "%s${clear_line}\n" "${bold_text}SYSTEM =====================================================${reset_text}" moveXOffset; printf " %-10s%-39s${clear_line}\n" "Uptime:" "${system_uptime}" - moveXOffset; printf " %-10s${temp_heatmap}%-21s${reset_text}%-10s${cpu_load_1_heatmap}%-4s${reset_text}, ${cpu_load_5_heatmap}%-4s${reset_text}, ${cpu_load_15_heatmap}%-4s${reset_text}${clear_line}\n" "CPU Temp:" "${temperature}" "CPU Load:" "${cpu_load_1}" "${cpu_load_5}" "${cpu_load_15}" + moveXOffset; printf " %-10s${temp_heatmap}%-21s${reset_text}%-10s${cpu_load_1_heatmap}%-4s${reset_text}, ${cpu_load_5_heatmap}%-4s${reset_text}, ${cpu_load_15_heatmap}%-4s${reset_text}${clear_line}\n" "CPU Temp:" "${cpu_temp}" "CPU Load:" "${cpu_load_1}" "${cpu_load_5}" "${cpu_load_15}" moveXOffset; printf " %-10s[${memory_heatmap}%-10s${reset_text}] %-6s %-10s[${cpu_load_1_heatmap}%-10s${reset_text}] %-5s${clear_line}" "Memory:" "${memory_bar}" "${memory_percent}%" "CPU Load:" "${cpu_bar}" "${cpu_percent}%" else # ${padd_size} = mega # mega is a screen with at least 80 columns and 26 lines @@ -990,7 +991,7 @@ PrintDashboard() { moveXOffset; printf " %-10s%-39s${clear_line}\n" "Top Clnt:" "${top_client}" moveXOffset; printf "%s${clear_line}\n" "${bold_text}FTL ============================================================================${reset_text}" moveXOffset; printf " %-10s%-9s %-10s%-9s %-10s%-9s${clear_line}\n" "PID:" "${ftlPID}" "CPU Use:" "${ftl_cpu}" "Mem. Use:" "${ftl_mem_percentage}" - moveXOffset; printf " %-10s%-69s${clear_line}\n" "DNSCache:" "${cache_inserts} insertions, ${cache_deletes} deletions, ${cache_size} total entries" + moveXOffset; printf " %-10s%-69s${clear_line}\n" "DNSCache:" "${cache_inserts} insertions, ${cache_evictions} deletions, ${cache_size} total entries" moveXOffset; printf "%s${clear_line}\n" "${bold_text}NETWORK ========================================================================${reset_text}" moveXOffset; printf " %-10s%-19s${clear_line}\n" "Hostname:" "${full_hostname}" moveXOffset; printf " %-10s%-15s %-4s%-9s %-4s%-9s${clear_line}\n" "Interfce:" "${iface_name}" "TX:" "${tx_bytes}" "RX:" "${rx_bytes}" @@ -1002,7 +1003,7 @@ PrintDashboard() { moveXOffset; printf "%s${clear_line}\n" "${bold_text}SYSTEM =========================================================================${reset_text}" moveXOffset; printf " %-10s%-39s${clear_line}\n" "Device:" "${sys_model}" moveXOffset; printf " %-10s%-39s %-10s[${memory_heatmap}%-10s${reset_text}] %-6s${clear_line}\n" "Uptime:" "${system_uptime}" "Memory:" "${memory_bar}" "${memory_percent}%" - moveXOffset; printf " %-10s${temp_heatmap}%-10s${reset_text} %-10s${cpu_load_1_heatmap}%-4s${reset_text}, ${cpu_load_5_heatmap}%-4s${reset_text}, ${cpu_load_15_heatmap}%-7s${reset_text} %-10s[${memory_heatmap}%-10s${reset_text}] %-6s${clear_line}" "CPU Temp:" "${temperature}" "CPU Load:" "${cpu_load_1}" "${cpu_load_5}" "${cpu_load_15}" "CPU Load:" "${cpu_bar}" "${cpu_percent}%" + moveXOffset; printf " %-10s${temp_heatmap}%-10s${reset_text} %-10s${cpu_load_1_heatmap}%-4s${reset_text}, ${cpu_load_5_heatmap}%-4s${reset_text}, ${cpu_load_15_heatmap}%-7s${reset_text} %-10s[${memory_heatmap}%-10s${reset_text}] %-6s${clear_line}" "CPU Temp:" "${cpu_temp}" "CPU Load:" "${cpu_load_1}" "${cpu_load_5}" "${cpu_load_15}" "CPU Load:" "${cpu_bar}" "${cpu_percent}%" fi # Clear to end of screen (below the drawn dashboard) @@ -1152,6 +1153,7 @@ SizeChecker(){ fi fi } + # converts a given version string e.g. v3.7.1 to 3007001000 to allow for easier comparison of multi digit version numbers # credits https://apple.stackexchange.com/a/123408 VersionConverter() { @@ -1178,6 +1180,7 @@ moveXOffset(){ if [ "${xOffset}" -gt 0 ]; then printf '\e[%sC' "${xOffset}" fi +} # Remove undesired strings from sys_model variable - used in GetSystemInformation() function filterModel() { @@ -1216,7 +1219,7 @@ truncateString() { OutputJSON() { # Traps for graceful shutdown # https://unix.stackexchange.com/a/681201 - trap clean_exit EXIT + trap CleanExit EXIT trap sig_cleanup INT QUIT TERM # Save current terminal settings (needed for later restore after password prompt) @@ -1235,8 +1238,6 @@ OutputJSON() { } StartupRoutine(){ - # Get config variables - . /etc/pihole/setupVars.conf # Clear the screen and move cursor to (0,0). # This mimics the 'clear' command. @@ -1248,9 +1249,6 @@ StartupRoutine(){ # adds the y-offset moveYOffset - # Get versions information - . /etc/pihole/versions - if [ "$1" = "pico" ] || [ "$1" = "nano" ] || [ "$1" = "micro" ]; then moveXOffset; PrintLogo "$1" moveXOffset; printf "%b" "START-UP ===========\n" @@ -1378,7 +1376,6 @@ NormalPADD() { # Get uptime, CPU load, temp, etc. every 5 seconds if [ $((now - LastCheckSystemInformation)) -ge 5 ]; then - . /etc/pihole/setupVars.conf GetSystemInformation LastCheckSystemInformation="${now}" fi @@ -1389,12 +1386,6 @@ NormalPADD() { LastCheckSummaryInformation="${now}" fi - # Get uptime, CPU load, temp, etc. every 5 seconds - if [ $((now - LastCheckSystemInformation)) -ge 5 ]; then - GetSystemInformation ${padd_size} - LastCheckSystemInformation="${now}" - fi - # Get FTL status every 5 seconds if [ $((now - LastCheckPiholeInformation)) -ge 5 ]; then GetPiholeInformation @@ -1409,7 +1400,6 @@ NormalPADD() { # Get Pi-hole components version information every 30 seconds if [ $((now - LastCheckVersionInformation)) -ge 30 ]; then - . /etc/pihole/versions GetVersionInformation LastCheckVersionInformation="${now}" fi @@ -1421,8 +1411,6 @@ NormalPADD() { fi done - - DeleteSession } DisplayHelp() { @@ -1435,15 +1423,16 @@ DisplayHelp() { ::: -xoff [num] set the x-offset, reference is the upper left corner, disables auto-centering ::: -yoff [num] set the y-offset, reference is the upper left corner, disables auto-centering ::: -::: -u URL or address of your Pi-hole (default: pi.hole) -::: -p Port of your Pi-hole's API (default: 8080) -::: -a Path where your Pi-hole's API is hosted (default: api) -::: -s Your Pi-hole's password, required to access the API -::: -j output stats as JSON formatted string and exit and exit -::: -h display this help text +::: -u URL or address of your Pi-hole (default: pi.hole) +::: -p Port of your Pi-hole's API (default: 8080) +::: -a Path where your Pi-hole's API is hosted (default: api) +::: -s Your Pi-hole's password, required to access the API +::: -j output stats as JSON formatted string and exit and exit +::: -h display this help text EOM - exit 0 + # exit with the supplied argument + exit "$1" } # Called on signals INT QUIT TERM @@ -1455,12 +1444,12 @@ sig_cleanup() { # causing EXIT trap to be executed, so we trap EXIT after INT trap '' EXIT - (exit $err) # execute in a subshell just to pass $? to clean_exit() - clean_exit + (exit $err) # execute in a subshell just to pass $? to CleanExit() + CleanExit } # Called on signal EXIT, or indirectly on INT QUIT TERM -clean_exit() { +CleanExit() { # save the return code of the script err=$? @@ -1472,58 +1461,16 @@ clean_exit() { stty "${stty_orig}" fi - # Turn cursor on - setterm -cursor on - - # Delete session from FTL server - DeleteSession - exit $err # exit the script with saved $? -} - -# Get supplied options - -while getopts ":u:p:a:s:jh" args; do - case "${args}" in - u) URL="${OPTARG}" ;; - p) PORT="${OPTARG}" ;; - a) APIPATH="${OPTARG}" ;; - s) password="${OPTARG}" ;; - j) OutputJSON;; - h) DisplayHelp;; - \?) echo "Invalid option: -${OPTARG}" - exit 1 ;; - :) echo "Option -$OPTARG requires an argument." - exit 1 ;; - *) DisplayHelp;; - esac -done - -# Save current terminal settings (needed for later restore after password prompt) -stty_orig=$(stty -g) - -# Turns off the cursor -# (From Pull request #8 https://github.com/jpmck/PADD/pull/8) -setterm -cursor off - -# Construct FTL's API address depending on the arguments supplied -ConstructAPI - -# Test if the authentication endpoint is availabe -TestAPIAvailability - -# Traps for graceful shutdown -# https://unix.stackexchange.com/a/681201 -trap clean_exit EXIT -trap sig_cleanup INT QUIT TERM - # Show the cursor # https://vt100.net/docs/vt510-rm/DECTCEM.html printf '\e[?25h' # if background sleep is running, kill it # http://mywiki.wooledge.org/SignalTrap#When_is_the_signal_handled.3F - kill $sleepPID > /dev/null 2>&1 + kill "{$sleepPID}" > /dev/null 2>&1 + # Delete session from FTL server + DeleteSession exit $err # exit the script with saved $? } @@ -1541,23 +1488,29 @@ TerminalResize(){ printf '\e[H\e[2J\e[3J' - kill $sleepPID > /dev/null 2>&1 + kill "{$sleepPID}" > /dev/null 2>&1 } main(){ + # Hiding the cursor. # https://vt100.net/docs/vt510-rm/DECTCEM.html printf '\e[?25l' - # Trap on exit - trap 'CleanExit' INT TERM EXIT + # Traps for graceful shutdown + # https://unix.stackexchange.com/a/681201 + trap CleanExit EXIT + trap sig_cleanup INT QUIT TERM - # If setupVars.conf is not present, then PADD is not running on a Pi-hole - # and we are not able to start as StartupRoutine() will fail below - if [ ! -f /etc/pihole/setupVars.conf ]; then - printf "%b" "${check_box_bad} Error!\n PADD only works in conjunction with Pi-hole!\n" - exit 1 - fi + # Save current terminal settings (needed for later restore after password prompt) + stty_orig=$(stty -g) + + + # Construct FTL's API address depending on the arguments supplied + ConstructAPI + + # Test if the authentication endpoint is availabe + TestAPIAvailability SizeChecker @@ -1570,11 +1523,15 @@ main(){ # Process all options (if present) while [ "$#" -gt 0 ]; do case "$1" in - "-j" | "--json" ) OutputJSON; exit 0;; - "-h" | "--help" ) DisplayHelp; exit 0;; + "-j" | "--json" ) OutputJSON;; + "-h" | "--help" ) DisplayHelp "0";; "-xoff" ) xOffset="$2"; xOffOrig="$2"; shift;; "-yoff" ) yOffset="$2"; yOffOrig="$2"; shift;; - * ) DisplayHelp; exit 1;; + "-u" ) URL="$2"; shift;; + "-p" ) PORT="$2"; shift;; + "-a" ) APIPATH="$2"; shift;; + "-s" ) password="$2"; shift;; + * ) DisplayHelp "1";; esac shift done From 70e33c1014cda6ca3013303c1b7b853ceaab0263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sat, 14 Jan 2023 20:03:40 +0100 Subject: [PATCH 15/81] Adjust to current FTL endpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 666 +++++++++++++++++++++++++++----------------------------- 1 file changed, 321 insertions(+), 345 deletions(-) diff --git a/padd.sh b/padd.sh index 2db64454..0245cb02 100755 --- a/padd.sh +++ b/padd.sh @@ -28,9 +28,6 @@ LastCheckPiholeInformation=$(date +%s) LastCheckSystemInformation=$(date +%s) LastCheckPADDInformation=$(date +%s) -# CORES -core_count=$(nproc --all 2> /dev/null) - # COLORS CSI="$(printf '\033')[" # Control Sequence Introducer red_text="${CSI}91m" # Red @@ -125,10 +122,10 @@ TestAPIAvailability() { # test if http status code was 200 (OK) if [ "${availabilityResonse}" = 200 ]; then - printf "%b" "API available at: http://${URL}:${PORT}/${APIPATH}\n" + moveXOffset; printf "%b" "API available at: http://${URL}:${PORT}/${APIPATH}\n" else - echo "API not available at: http://${URL}:${PORT}/${APIPATH}" - echo "Exiting." + moveXOffset; echo "API not available at: http://${URL}:${PORT}/${APIPATH}" + moveXOffset; echo "Exiting." exit 1 fi } @@ -138,13 +135,13 @@ Authenthication() { ChallengeResponse while [ "${validSession}" = false ] || [ -z "${validSession}" ] ; do - echo "Authentication failed." + moveXOffset; echo "Authentication failed." # no password was supplied as argument if [ -z "${password}" ]; then - echo "No password supplied. Please enter your password:" + moveXOffset; echo "No password supplied. Please enter your password:" else - echo "Wrong password supplied, please enter the correct password:" + moveXOffset; echo "Wrong password supplied, please enter the correct password:" fi # POSIX's `read` does not support `-s` option (suppressing the input) @@ -161,7 +158,7 @@ Authenthication() { done # Loop exited, authentication was successful - echo "Authentication successful." + moveXOffset; echo "Authentication successful." } @@ -172,10 +169,11 @@ DeleteSession() { # Try to delte the session. Omitt the output, but get the http status code deleteResponse=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE "http://${URL}:${PORT}/${APIPATH}/auth" -H "Accept: application/json" -H "sid: ${SID}") + printf "\n\n" case "${deleteResponse}" in - "200") printf "%b" "\nA session that was not created cannot be deleted (e.g., empty API password).\n";; - "401") printf "%b" "\nLogout attempt without a valid session. Unauthorized!\n";; - "410") printf "%b" "\n\nSession successfully deleted.\n";; + "200") moveXOffset; printf "%b" "A session that was not created cannot be deleted (e.g., empty API password).\n";; + "401") moveXOffset; printf "%b" "Logout attempt without a valid session. Unauthorized!\n";; + "410") moveXOffset; printf "%b" "Session successfully deleted.\n";; esac; fi @@ -198,8 +196,8 @@ ChallengeResponse() { sessionResponse="$(curl --silent -X POST "http://${URL}:${PORT}/${APIPATH}/auth" --data "{\"response\":\"${response}\"}" )" if [ -z "${sessionResponse}" ]; then - echo "No response from FTL server. Please check connectivity and use the options to set the API URL" - echo "Usage: $0 [-u ] [-p ] [-a ] " + moveXOffset; echo "No response from FTL server. Please check connectivity and use the options to set the API URL" + moveXOffset; echo "Usage: $0 [-u ] [-p ] [-a ] " exit 1 fi # obtain validity and session ID from session response @@ -218,12 +216,14 @@ GetFTLData() { GetSummaryInformation() { summary=$(GetFTLData "/stats/summary") cache_info=$(GetFTLData "/dns/cache") + sysinfo=$(GetFTLData "/ftl/sysinfo") + dns_blocking=$(GetFTLData "/dns/blocking") - clients=$(echo "${summary}" | jq .ftl.clients.active ) + clients=$(echo "${sysinfo}" | jq .ftl.clients.active ) - blocking_enabled=$(echo "${summary}" | jq .system.dns.blocking ) + blocking_enabled=$(echo "${dns_blocking}" | jq .blocking ) - domains_being_blocked_raw=$(echo "${summary}" | jq .ftl.database.gravity ) + domains_being_blocked_raw=$(echo "${sysinfo}" | jq .ftl.database.gravity) domains_being_blocked=$(printf "%.f" "${domains_being_blocked_raw}") dns_queries_today_raw=$(echo "$summary" | jq .queries.total ) @@ -235,15 +235,15 @@ GetSummaryInformation() { ads_percentage_today_raw=$(echo "$summary" | jq .queries.percent_blocked) ads_percentage_today=$(printf "%.1f" "${ads_percentage_today_raw}") - cache_size=$(echo "$cache_info" | jq .size) - cache_evictions=$(echo "$cache_info" | jq .evicted) - cache_inserts=$(echo "$cache_info"| jq .inserted) + cache_size=$(echo "$cache_info" | jq .cache.size) + cache_evictions=$(echo "$cache_info" | jq .cache.evicted) + cache_inserts=$(echo "$cache_info"| jq .cache.inserted) latest_blocked_raw=$(GetFTLData "/stats/recent_blocked?show=1" | jq --raw-output .blocked[0]) - top_blocked_raw=$(GetFTLData "/stats/top_blocked" | jq --raw-output .top_domains[0].domain) + top_blocked_raw=$(GetFTLData "/stats/top_domains?blocked=true" | jq --raw-output .domains[0].domain) - top_domain_raw=$(GetFTLData "/stats/top_domains" | jq --raw-output .top_domains[0].domain) + top_domain_raw=$(GetFTLData "/stats/top_domains" | jq --raw-output .domains[0].domain) top_client_raw=$(GetFTLData "/stats/top_clients" | jq --raw-output .clients[0].name) if [ -z "${top_client_raw}" ]; then @@ -253,242 +253,210 @@ GetSummaryInformation() { } GetSystemInformation() { - # System uptime - system_uptime_raw=$(echo "${summary}" | jq .system.uptime ) + sysinfo=$(GetFTLData "/ftl/sysinfo") - # CPU temperature is returned in °C - cpu_temp=$(echo "${summary}" | jq .system.sensors[0].value ) + # System uptime + system_uptime_raw=$(echo "${sysinfo}" | jq .system.uptime ) + + # CPU temperature and unit + cpu_temp_raw=$(echo "${sysinfo}" | jq .system.sensors[0].value) + cpu_temp=$(printf "%.1f" "${cpu_temp_raw}") + temp_unit=$(echo "${sysinfo}" | jq --raw-output .system.sensors[0].unit) + + # Temp + Unit + if [ "${temp_unit}" = "C" ]; then + temperature="${cpu_temp}°${temp_unit}" + # no conversion needed + cpu_temp_celsius="$(echo "${cpu_temp}" | awk -F '.' '{print $1}')" + elif [ "${temp_unit}" = "F" ]; then + temperature="${cpu_temp}°${temp_unit}" + # convert to Celsius for limit checking + cpu_temp_celsius="$(echo "${cpu_temp}" | awk '{print ($1-32) * 5 / 9}' | awk -F '.' '{print $1}')" + elif [ "${temp_unit}" = "K" ]; then + # no ° for Kelvin + temperature="${cpu_temp}${temp_unit}" + # convert to Celsius for limit checking + cpu_temp_celsius="$(echo "${cpu_temp}" | awk '{print $1 - 273.15}' | awk -F '.' '{print $1}')" + fi - # Convert CPU temperature to correct unit - if [ "${TEMPERATUREUNIT}" = "F" ]; then - cpu_temp="$(printf %.1f "$(echo "${cpu_temp}" | awk '{print $1 * 9 / 5000 + 32}')")°F" - elif [ "${TEMPERATUREUNIT}" = "K" ]; then - cpu_temp="$(printf %.1f "$(echo "${cpu_temp}" | awk '{print $1 / 1000 + 273.15}')")°K" - # Addresses Issue 1: https://github.com/jpmck/PAD/issues/1 + # CPU temperature heatmap + hot_flag=false + # If we're getting close to 85°C... (https://www.raspberrypi.org/blog/introducing-turbo-mode-up-to-50-more-performance-for-free/) + if [ "${cpu_temp_celsius}" -gt 80 ]; then + temp_heatmap=${blinking_text}${red_text} + # set flag to change the status message in SetStatusMessage() + hot_flag=true + elif [ "${cpu_temp_celsius}" -gt 70 ]; then + temp_heatmap=${magenta_text} + elif [ "${cpu_temp_celsius}" -gt 60 ]; then + temp_heatmap=${blue_text} else - cpu_temp="$(printf %.1f "$(echo "${cpu_temp}" | awk '{print $1 / 1000}')")°C" + temp_heatmap=${cyan_text} fi # CPU, load, heatmap - core_count=$(echo "${summary}" | jq .system.cpu.nprocs) - cpu_load_1=$(printf %.2f "$(echo "${summary}" | jq .system.cpu.load.raw[0])") - cpu_load_5=$(printf %.2f "$(echo "${summary}" | jq .system.cpu.load.raw[1])") - cpu_load_15=$(printf %.2f "$(echo "${summary}" | jq .system.cpu.load.raw[2])") + core_count=$(echo "${sysinfo}" | jq .system.cpu.nprocs) + cpu_load_1=$(printf %.2f "$(echo "${sysinfo}" | jq .system.cpu.load.raw[0])") + cpu_load_5=$(printf %.2f "$(echo "${sysinfo}" | jq .system.cpu.load.raw[1])") + cpu_load_15=$(printf %.2f "$(echo "${sysinfo}" | jq .system.cpu.load.raw[2])") cpu_load_1_heatmap=$(HeatmapGenerator "${cpu_load_1}" "${core_count}") cpu_load_5_heatmap=$(HeatmapGenerator "${cpu_load_5}" "${core_count}") cpu_load_15_heatmap=$(HeatmapGenerator "${cpu_load_15}" "${core_count}") - cpu_percent=$(printf %.1f "$(echo "${summary}" | jq .system.cpu.load.percent[0])") + cpu_percent=$(printf %.1f "$(echo "${sysinfo}" | jq .system.cpu.load.percent[0])") - # CPU temperature heatmap - hot_flag=false - # If we're getting close to 85°C... (https://www.raspberrypi.org/blog/introducing-turbo-mode-up-to-50-more-performance-for-free/) - if [ "${cpu_temp}" -gt 80000 ]; then - temp_heatmap=${blinking_text}${red_text} - # set flag to change the status message in SetStatusMessage() - hot_flag=true - elif [ "${cpu_temp}" -gt 70000 ]; then - temp_heatmap=${magenta_text} - elif [ "${cpu_temp}" -gt 60000 ]; then - temp_heatmap=${blue_text} - else - temp_heatmap=${cyan_text} - fi + # Memory use, heatmap and bar + memory_percent="$(echo "${sysinfo}" | jq '.system.memory.ram."%used"')" + memory_heatmap="$(HeatmapGenerator "${memory_percent}")" - # Memory use, heatmap and bar - memory_total=$(echo "${summary}" | jq .system.memory.ram.total) - memory_available=$(echo "${summary}" | jq .system.memory.ram.available) - memory_percent=$(printf %.1f $(((memory_total-memory_available)*100/memory_total)) ) - memory_heatmap=$(HeatmapGenerator "${memory_percent}") - - # Get product name and family - product_name= - product_family= - if [ -f /sys/devices/virtual/dmi/id/product_name ]; then - # Get product name, remove possible null byte - product_name=$(tr -d '\0' < /sys/devices/virtual/dmi/id/product_name) - fi - if [ -f /sys/devices/virtual/dmi/id/product_family ]; then - # Get product family, remove possible null byte - product_family=$(tr -d '\0' < /sys/devices/virtual/dmi/id/product_family) - fi + # Get device model + sys_model="$(echo "${sysinfo}" | jq --raw-output .system.model)" - board_vendor= - board_name= - if [ -f /sys/devices/virtual/dmi/id/board_vendor ]; then - board_vendor=$(tr -d '\0' < /sys/devices/virtual/dmi/id/board_vendor) - fi - if [ -f /sys/devices/virtual/dmi/id/board_name ]; then - board_name="$(tr -d '\0' < /sys/devices/virtual/dmi/id/board_name)" - fi - - - if [ -n "$product_name" ] || [ -n "$product_family" ]; then - if echo "$product_family" | grep -q "$product_name"; then - # If product_name is contained in product_family, only show product_family - sys_model="${product_family}" - else - # If product_name is not contained in product_family, both are shown - sys_model="${product_family} ${product_name}" + # DOCKER_VERSION is set during GetVersionInformation, so this needs to run first during startup + if [ -n "${DOCKER_VERSION}" ] && [ ! "${DOCKER_VERSION}" = "null" ]; then + # Docker image + sys_model="Docker tag ${DOCKER_VERSION}" fi - elif [ -f /sys/firmware/devicetree/base/model ]; then - sys_model=$(tr -d '\0' < /sys/firmware/devicetree/base/model) - elif [ -n "$board_vendor" ] || [ -n "$board_name" ]; then - sys_model="${board_vendor} ${board_name}" - elif [ -f /tmp/sysinfo/model ]; then - sys_model=$(tr -d '\0' < /tmp/sysinfo/model) - elif [ -n "${DOCKER_VERSION}" ]; then - # Docker image. DOCKER_VERSION is read from /etc/pihole/versions - sys_model="Docker tag ${DOCKER_VERSION}" - fi - # Cleaning device model from useless OEM information - sys_model=$(filterModel "${sys_model}") + # Cleaning device model from useless OEM information + sys_model=$(filterModel "${sys_model}") - if [ -z "$sys_model" ]; then - sys_model="Unknown" - fi + if [ -z "$sys_model" ]; then + sys_model="Unknown" + fi } GetNetworkInformation() { - interfaces_raw=$(GetFTLData "/ftl/interfaces") + interfaces_raw=$(GetFTLData "/network/interfaces") + sysinfo=$(GetFTLData "/ftl/sysinfo") + config=$(GetFTLData "/config") + # Get pi IPv4 address of the default interface - pi_ip4_addrs="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].ipv4 | sed "s/127.0.0.1,//g" | tr "," " " | wc -w)" + pi_ip4_addrs="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv4[]' | wc -w)" if [ "${pi_ip4_addrs}" -eq 0 ]; then # No IPv4 address available pi_ip4_addr="N/A" elif [ "${pi_ip4_addrs}" -eq 1 ]; then # One IPv4 address available - pi_ip4_addr="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].ipv4 | sed "s/127.0.0.1,//g" | awk -F ',' '{printf $1}')" + pi_ip4_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv4[0]')" else # More than one IPv4 address available - pi_ip4_addr="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].ipv4 | sed "s/127.0.0.1,//g"| awk -F ',' '{printf $1}')+" + pi_ip4_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv4[0]')+" fi - # Get pi IPv6 address of the default interface - pi_ip6_addrs="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].ipv6 | sed "s/::1,//g" | tr "," " " | wc -w)" - if [ "${pi_ip6_addrs}" -eq 0 ]; then - # No IPv6 address available - pi_ip6_addr="N/A" - ipv6_check_box=${check_box_bad} - elif [ "${pi_ip6_addrs}" -eq 1 ]; then - # One IPv6 address available - pi_ip6_addr="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].ipv6 | sed "s/::1,//g" | awk -F ',' '{printf $1}')" - ipv6_check_box=${check_box_good} - else - # More than one IPv6 address available - pi_ip6_addr="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].ipv6 | sed "s/::1,//g" | awk -F ',' '{printf $1}')+" - ipv6_check_box=${check_box_good} - fi - - # Get hostname and gateway - pi_hostname=$(hostname) - - full_hostname=${pi_hostname} - # does the Pi-hole have a domain set? - if [ -n "${PIHOLE_DOMAIN+x}" ]; then - # is Pi-hole acting as DHCP server? - if [ "${DHCP_ACTIVE}" = "true" ]; then - count=${pi_hostname}"."${PIHOLE_DOMAIN} - count=${#count} - if [ "${count}" -lt "18" ]; then - full_hostname=${pi_hostname}"."${PIHOLE_DOMAIN} - fi + # Get pi IPv6 address of the default interface + pi_ip6_addrs="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv6[]' | wc -w)" + if [ "${pi_ip6_addrs}" -eq 0 ]; then + # No IPv6 address available + pi_ip6_addr="N/A" + ipv6_check_box=${check_box_bad} + elif [ "${pi_ip6_addrs}" -eq 1 ]; then + # One IPv6 address available + pi_ip6_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv6[0]' | cut -f1 -d "%" )" + ipv6_check_box=${check_box_good} + else + # More than one IPv6 address available + pi_ip6_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv6[0]' | cut -f1 -d "%" )+" + ipv6_check_box=${check_box_good} fi - fi - # Get the DNS count (from pihole -c) - dns_count="0" - [ -n "${PIHOLE_DNS_1}" ] && dns_count=$((dns_count+1)) - [ -n "${PIHOLE_DNS_2}" ] && dns_count=$((dns_count+1)) - [ -n "${PIHOLE_DNS_3}" ] && dns_count=$((dns_count+1)) - [ -n "${PIHOLE_DNS_4}" ] && dns_count=$((dns_count+1)) - [ -n "${PIHOLE_DNS_5}" ] && dns_count=$((dns_count+1)) - [ -n "${PIHOLE_DNS_6}" ] && dns_count=$((dns_count+1)) - [ -n "${PIHOLE_DNS_7}" ] && dns_count=$((dns_count+1)) - [ -n "${PIHOLE_DNS_8}" ] && dns_count=$((dns_count+1)) - [ -n "${PIHOLE_DNS_9}" ] && dns_count=$((dns_count+1)) - - # if there's only one DNS server - if [ ${dns_count} -eq 1 ]; then - dns_information="1 server" - else - dns_information="${dns_count} servers" - fi + # Is Pi-Hole acting as the DHCP server? + DHCP_ACTIVE="$(echo "${config}" | jq .config.dnsmasq.dhcp.active)" - # Is Pi-Hole acting as the DHCP server? - if [ "${DHCP_ACTIVE}" = "true" ]; then - dhcp_status="Enabled" - dhcp_info=" Range: ${DHCP_START} - ${DHCP_END}" - dhcp_heatmap=${green_text} - dhcp_check_box=${check_box_good} - - # Is DHCP handling IPv6? - # DHCP_IPv6 is set in setupVars.conf - # shellcheck disable=SC2154 - if [ "${DHCP_IPv6}" = "true" ]; then - dhcp_ipv6_status="Enabled" - dhcp_ipv6_heatmap=${green_text} - dhcp_ipv6_check_box=${check_box_good} + if [ "${DHCP_ACTIVE}" = "true" ]; then + DHCP_START="$(echo "${config}" | jq --raw-output .config.dnsmasq.dhcp.start)" + DHCP_END="$(echo "${config}" | jq --raw-output .config.dnsmasq.dhcp.end)" + + dhcp_status="Enabled" + dhcp_info=" Range: ${DHCP_START} - ${DHCP_END}" + dhcp_heatmap=${green_text} + dhcp_check_box=${check_box_good} + + # Is DHCP handling IPv6? + DHCP_IPv6="$(echo "${config}" | jq --raw-output .config.dnsmasq.dhcp.ipv6)" + if [ "${DHCP_IPv6}" = "true" ]; then + dhcp_ipv6_status="Enabled" + dhcp_ipv6_heatmap=${green_text} + dhcp_ipv6_check_box=${check_box_good} + else + dhcp_ipv6_status="Disabled" + dhcp_ipv6_heatmap=${red_text} + dhcp_ipv6_check_box=${check_box_bad} + fi else - dhcp_ipv6_status="Disabled" - dhcp_ipv6_heatmap=${red_text} - dhcp_ipv6_check_box=${check_box_bad} + dhcp_status="Disabled" + dhcp_heatmap=${red_text} + dhcp_check_box=${check_box_bad} + + GATEWAY="$(GetFTLData "/network/gateway" | jq --raw-output .address)" + dhcp_info=" Router: ${GATEWAY}" + dhcp_ipv6_status="N/A" + dhcp_ipv6_heatmap=${yellow_text} + dhcp_ipv6_check_box=${check_box_question} fi - else - dhcp_status="Disabled" - dhcp_heatmap=${red_text} - dhcp_check_box=${check_box_bad} - # if the DHCP Router variable isn't set - if [ -z ${DHCP_ROUTER+x} ]; then - DHCP_ROUTER=$(printf %b "${interfaces_raw}" | jq --raw-output .gateway.address) + # Get hostname + pi_hostname="$(echo "${sysinfo}" | jq --raw-output .system.uname.nodename)" + full_hostname=${pi_hostname} + # when PI-hole is the DHCP server, append the domain to the hostname + if [ "${DHCP_ACTIVE}" = "true" ]; then + PIHOLE_DOMAIN="$(echo "${config}" | jq --raw-output .config.dnsmasq.domain)" + if [ -n "${PIHOLE_DOMAIN}" ]; then + count=${pi_hostname}"."${PIHOLE_DOMAIN} + count=${#count} + if [ "${count}" -lt "18" ]; then + full_hostname=${pi_hostname}"."${PIHOLE_DOMAIN} + fi + fi fi - dhcp_info=" Router: ${DHCP_ROUTER}" - dhcp_heatmap=${red_text} - dhcp_check_box=${check_box_bad} + # Get the number of configured upstream DNS servers + dns_count="$(echo "${config}" | jq --raw-output .config.dnsmasq.upstreams[] | sed '/^\s*$/d' | wc -l)" + # if there's only one DNS server + if [ "${dns_count}" -eq 1 ]; then + dns_information="1 server" + else + dns_information="${dns_count} servers" + fi - dhcp_ipv6_status="N/A" - dhcp_ipv6_heatmap=${yellow_text} - dhcp_ipv6_check_box=${check_box_question} - fi - # DNSSEC - if [ "${DNSSEC}" = "true" ]; then - dnssec_status="Enabled" - dnssec_heatmap=${green_text} - else - dnssec_status="Disabled" - dnssec_heatmap=${red_text} - fi + # DNSSEC + DNSSEC="$(echo "${config}" | jq .config.dnsmasq.dnssec)" + if [ "${DNSSEC}" = "true" ]; then + dnssec_status="Enabled" + dnssec_heatmap=${green_text} + else + dnssec_status="Disabled" + dnssec_heatmap=${red_text} + fi - # Conditional forwarding - if [ "${CONDITIONAL_FORWARDING}" = "true" ] || [ "${REV_SERVER}" = "true" ]; then - conditional_forwarding_status="Enabled" - conditional_forwarding_heatmap=${green_text} - else - conditional_forwarding_status="Disabled" - conditional_forwarding_heatmap=${red_text} - fi + # Conditional forwarding + CONDITIONAL_FORWARDING="$(echo "${config}" | jq .config.dnsmasq.rev_server.active)" + if [ "${CONDITIONAL_FORWARDING}" = "true" ]; then + conditional_forwarding_status="Enabled" + conditional_forwarding_heatmap=${green_text} + else + conditional_forwarding_status="Disabled" + conditional_forwarding_heatmap=${red_text} + fi - #Default interface data - iface_name="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].name)" - tx_bytes="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].tx.num)" - tx_bytes_unit="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].tx.unit)" + # Default interface data + iface_name="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .name')" + tx_bytes="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .tx.num')" + tx_bytes_unit="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .tx.unit')" tx_bytes=$(printf "%.1f %b" "${tx_bytes}" "${tx_bytes_unit}") - rx_bytes="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].rx.num)" - rx_bytes_unit="$(echo "${interfaces_raw}" | jq --raw-output .interfaces[0].rx.unit)" + rx_bytes="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .rx.num')" + rx_bytes_unit="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .rx.unit')" rx_bytes=$(printf "%.1f %b" "${rx_bytes}" "${rx_bytes_unit}") } GetPiholeInformation() { - # Get FTL status + sysinfo=$(GetFTLData "/ftl/sysinfo") - # Get FTL's current PID - ftlPID="$(getFTLPID)" + # Get FTL's current PID + ftlPID="$(echo "${sysinfo}" | jq .ftl.pid)" - # If FTL is not running (getFTLPID returns -1), set all variables to "not running" + # If FTL is not running (ftlPID is -1), set all variables to "not running" ftl_down_flag=false if [ "${ftlPID}" = "-1" ]; then ftl_status="Not running" @@ -503,8 +471,10 @@ GetPiholeInformation() { ftl_heatmap=${green_text} ftl_check_box=${check_box_good} # Get FTL CPU and memory usage - ftl_cpu="$(ps -p "${ftlPID}" -o %cpu | tail -n1 | tr -d '[:space:]')" - ftl_mem_percentage="$(ps -p "${ftlPID}" -o %mem | tail -n1 | tr -d '[:space:]')" + ftl_cpu_raw="$(echo "${sysinfo}" | jq '.ftl."%cpu"')" + ftl_mem_percentage_raw="$(echo "${sysinfo}" | jq '.ftl."%mem"')" + ftl_cpu="$(printf "%.1f" "${ftl_cpu_raw}")%" + ftl_mem_percentage="$(printf "%.1f" "${ftl_mem_percentage_raw}")%" # Get Pi-hole (blocking) status ftl_dns_port=$(GetFTLData "/dns/port" | jq .dns_port) fi @@ -531,133 +501,133 @@ GetVersionInformation() { out_of_date_flag=false versions_raw=$(GetFTLData "/version") - # Check if core version - CORE_BRANCH="$(echo "${versions_raw}" | jq --raw-output .core.branch)" - CORE_VERSION=$(echo "${versions_raw}" | jq --raw-output .core.tag | tr -d '[:alpha:]' | awk -F '-' '{printf $1}') - GITHUB_CORE_VERSION=$(pihole -v -p | awk '{print $(NF)}' | tr -d ')') - CORE_HASH - GITHUB_CORE_HASH - - # Gather core version information... - # Extract vx.xx or vx.xx.xxx version - CORE_VERSION="$(echo "${CORE_VERSION}" | grep -oE '^v[0-9]+([.][0-9]+){1,2}')" - if [ "${CORE_BRANCH}" = "master" ]; then - core_version_converted="$(VersionConverter "${CORE_VERSION}")" - core_version_latest_converted=$(VersionConverter "${GITHUB_CORE_VERSION}") - - if [ "${core_version_converted}" -lt "${core_version_latest_converted}" ]; then - out_of_date_flag="true" - core_version_heatmap=${red_text} - else - core_version_heatmap=${green_text} - fi + # Gather core version information... + CORE_BRANCH="$(echo "${versions_raw}" | jq --raw-output .version.core.local.branch)" + CORE_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.core.local.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_CORE_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.core.remmote.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + CORE_HASH="$(echo "${versions_raw}" | jq --raw-output .version.core.local.hash)" + GITHUB_CORE_HASH="$(echo "${versions_raw}" | jq --raw-output .version.core.remote.hash)" - else - # Custom branch - if [ -z "${CORE_BRANCH}" ]; then - # Branch name is empty, something went wrong - core_version_heatmap=${red_text} - CORE_VERSION="?" + if [ "${CORE_BRANCH}" = "master" ]; then + core_version_converted="$(VersionConverter "${CORE_VERSION}")" + core_version_latest_converted=$(VersionConverter "${GITHUB_CORE_VERSION}") + + if [ "${core_version_converted}" -lt "${core_version_latest_converted}" ]; then + out_of_date_flag="true" + core_version_heatmap=${red_text} + else + core_version_heatmap=${green_text} + fi else - if [ "${CORE_HASH}" = "${GITHUB_CORE_HASH}" ]; then - # up-to-date - core_version_heatmap=${green_text} - else - # out-of-date - out_of_date_flag="true" - core_version_heatmap=${red_text} - fi - # shorten common branch names (fix/, tweak/, new/) - # use the first 7 characters of the branch name as version - CORE_VERSION="$(printf '%s' "$CORE_BRANCH" | sed 's/fix\//f\//;s/new\//n\//;s/tweak\//t\//' | cut -c 1-7)" + # Custom branch + if [ -z "${CORE_BRANCH}" ]; then + # Branch name is empty, something went wrong + core_version_heatmap=${red_text} + CORE_VERSION="?" + else + if [ "${CORE_HASH}" = "${GITHUB_CORE_HASH}" ]; then + # up-to-date + core_version_heatmap=${green_text} + else + # out-of-date + out_of_date_flag="true" + core_version_heatmap=${red_text} + fi + # shorten common branch names (fix/, tweak/, new/) + # use the first 7 characters of the branch name as version + CORE_VERSION="$(printf '%s' "$CORE_BRANCH" | sed 's/fix\//f\//;s/new\//n\//;s/tweak\//t\//' | cut -c 1-7)" + fi fi - fi # Gather web version information... - # Extract vx.xx or vx.xx.xxx version - if [ "$INSTALL_WEB_INTERFACE" = true ]; then - WEB_BRANCH="$(echo "${versions_raw}" | jq --raw-output .web.branch)" - WEB_VERSION=$(echo "${versions_raw}" | jq --raw-output .web.tag | tr -d '[:alpha:]' | awk -F '-' '{printf $1}') - GITHUB_WEB_VERSION - WEB_HASH - GITHUB_WEB_HASH - - if [ "${WEB_BRANCH}" = "master" ]; then - web_version_converted="$(VersionConverter "${WEB_VERSION}")" - web_version_latest_converted=$(VersionConverter "${GITHUB_WEB_VERSION}") - - if [ "${web_version_converted}" -lt "${web_version_latest_converted}" ]; then - out_of_date_flag="true" - web_version_heatmap=${red_text} - else - web_version_heatmap=${green_text} - fi + WEB_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.web.local.version)" + + if [ ! "$WEB_VERSION" = "null" ]; then + WEB_BRANCH="$(echo "${versions_raw}" | jq --raw-output .version.web.local.branch)" + WEB_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.web.local.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_WEB_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.web.remmote.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + WEB_HASH="$(echo "${versions_raw}" | jq --raw-output .version.web.local.hash)" + GITHUB_WEB_HASH="$(echo "${versions_raw}" | jq --raw-output .version.web.remote.hash)" + + if [ "${WEB_BRANCH}" = "master" ]; then + web_version_converted="$(VersionConverter "${WEB_VERSION}")" + web_version_latest_converted=$(VersionConverter "${GITHUB_WEB_VERSION}") + + if [ "${web_version_converted}" -lt "${web_version_latest_converted}" ]; then + out_of_date_flag="true" + web_version_heatmap=${red_text} + else + web_version_heatmap=${green_text} + fi - else - # Custom branch - if [ -z "${WEB_BRANCH}" ]; then - # Branch name is empty, something went wrong - web_version_heatmap=${red_text} - WEB_VERSION="?" - else - if [ "${WEB_HASH}" = "${GITHUB_WEB_HASH}" ]; then - # up-to-date - web_version_heatmap=${green_text} else - # out-of-date - out_of_date_flag="true" - web_version_heatmap=${red_text} + # Custom branch + if [ -z "${WEB_BRANCH}" ]; then + # Branch name is empty, something went wrong + web_version_heatmap=${red_text} + WEB_VERSION="?" + else + if [ "${WEB_HASH}" = "${GITHUB_WEB_HASH}" ]; then + # up-to-date + web_version_heatmap=${green_text} + else + # out-of-date + out_of_date_flag="true" + web_version_heatmap=${red_text} + fi + # shorten common branch names (fix/, tweak/, new/) + # use the first 7 characters of the branch name as version + WEB_VERSION="$(printf '%s' "$WEB_BRANCH" | sed 's/fix\//f\//;s/new\//n\//;s/tweak\//t\//' | cut -c 1-7)" + fi fi - # shorten common branch names (fix/, tweak/, new/) - # use the first 7 characters of the branch name as version - WEB_VERSION="$(printf '%s' "$WEB_BRANCH" | sed 's/fix\//f\//;s/new\//n\//;s/tweak\//t\//' | cut -c 1-7)" - fi + else + # Web interface not installed + WEB_VERSION="N/A" + web_version_heatmap=${yellow_text} fi - else - # Web interface not installed - WEB_VERSION="N/A" - web_version_heatmap=${yellow_text} - fi - # Gather FTL version information... - # Extract vx.xx or vx.xx.xxx version - FTL_BRANCH="$(echo "${versions_raw}" | jq --raw-output .ftl.branch)" - FTL_VERSION=$(echo "${versions_raw}" | jq --raw-output .ftl.tag | tr -d '[:alpha:]' | awk -F '-' '{printf $1}') - GITHUB_FTL_VERSION - FTL_HASH - GITHUB_FTL_HASH + # Gather FTL version information... + FTL_BRANCH="$(echo "${versions_raw}" | jq --raw-output .version.ftl.local.branch)" + FTL_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.ftl.local.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_FTL_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.ftl.remmote.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + FTL_HASH="$(echo "${versions_raw}" | jq --raw-output .version.ftl.local.hash)" + GITHUB_FTL_HASH="$(echo "${versions_raw}" | jq --raw-output .version.ftl.remote.hash)" - if [ "${FTL_BRANCH}" = "master" ]; then - ftl_version_converted="$(VersionConverter "${FTL_VERSION}")" - ftl_version_latest_converted=$(VersionConverter "${GITHUB_FTL_VERSION}") + if [ "${FTL_BRANCH}" = "master" ]; then + ftl_version_converted="$(VersionConverter "${FTL_VERSION}")" + ftl_version_latest_converted=$(VersionConverter "${GITHUB_FTL_VERSION}") - if [ "${ftl_version_converted}" -lt "${ftl_version_latest_converted}" ]; then - out_of_date_flag="true" - ftl_version_heatmap=${red_text} - else - ftl_version_heatmap=${green_text} - fi - else - # Custom branch - if [ -z "${FTL_BRANCH}" ]; then - # Branch name is empty, something went wrong - ftl_version_heatmap=${red_text} - FTL_VERSION="?" + if [ "${ftl_version_converted}" -lt "${ftl_version_latest_converted}" ]; then + out_of_date_flag="true" + ftl_version_heatmap=${red_text} + else + ftl_version_heatmap=${green_text} + fi else - if [ "${FTL_HASH}" = "${GITHUB_FTL_HASH}" ]; then - # up-to-date - ftl_version_heatmap=${green_text} - else - # out-of-date - out_of_date_flag="true" - ftl_version_heatmap=${red_text} - fi - # shorten common branch names (fix/, tweak/, new/) - # use the first 7 characters of the branch name as version - FTL_VERSION="$(printf '%s' "$FTL_BRANCH" | sed 's/fix\//f\//;s/new\//n\//;s/tweak\//t\//' | cut -c 1-7)" + # Custom branch + if [ -z "${FTL_BRANCH}" ]; then + # Branch name is empty, something went wrong + ftl_version_heatmap=${red_text} + FTL_VERSION="?" + else + if [ "${FTL_HASH}" = "${GITHUB_FTL_HASH}" ]; then + # up-to-date + ftl_version_heatmap=${green_text} + else + # out-of-date + out_of_date_flag="true" + ftl_version_heatmap=${red_text} + fi + # shorten common branch names (fix/, tweak/, new/) + # use the first 7 characters of the branch name as version + FTL_VERSION="$(printf '%s' "$FTL_BRANCH" | sed 's/fix\//f\//;s/new\//n\//;s/tweak\//t\//' | cut -c 1-7)" + fi fi - fi + + # Gather DOCKER version information... + # returns "null" if not running Pi-hole in Docker container + DOCKER_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.docker.local)" } @@ -725,9 +695,9 @@ GenerateSizeDependendOutput() { # System uptime if [ "$1" = "pico" ] || [ "$1" = "nano" ] || [ "$1" = "micro" ]; then - system_uptime=$(echo "${system_uptime_raw}" | awk -F'( |,|:)+' '{if ($7=="min") m=$6; else {if ($7~/^day/){if ($9=="min") {d=$6;m=$8} else {d=$6;h=$8;m=$9}} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours"}') + system_uptime="$(convertUptime "${system_uptime_raw}" | awk -F ',' '{print $1 "," $2}')" else - system_uptime=$(echo "${system_uptime_raw}" | awk -F'( |,|:)+' '{if ($7=="min") m=$6; else {if ($7~/^day/){if ($9=="min") {d=$6;m=$8} else {d=$6;h=$8;m=$9}} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes"}') + system_uptime="$(convertUptime "${system_uptime_raw}")" fi # Bar generations @@ -759,10 +729,10 @@ SetStatusMessage() { if [ "${hot_flag}" = true ]; then # Check if CPU temperature is high pico_status="${pico_status_hot}" - mini_status="${mini_status_hot} ${blinking_text}${red_text}${cpu_temp}${reset_text}" - tiny_status="${tiny_status_hot} ${blinking_text}${red_text}${cpu_temp}${reset_text}" - full_status="${full_status_hot} ${blinking_text}${red_text}${cpu_temp}${reset_text}" - mega_status="${mega_status_hot} ${blinking_text}${red_text}${cpu_temp}${reset_text}" + mini_status="${mini_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" + tiny_status="${tiny_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" + full_status="${full_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" + mega_status="${mega_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" elif [ "${ftl_down_flag}" = true ]; then # Check if FTL is down @@ -937,7 +907,7 @@ PrintDashboard() { fi moveXOffset; printf "%s${clear_line}\n" "${bold_text}SYSTEM ==============================================${reset_text}" moveXOffset; printf " %-10s%-29s${clear_line}\n" "Uptime:" "${system_uptime}" - moveXOffset; printf " %-10s${temp_heatmap}%-17s${reset_text} %-8s${cpu_load_1_heatmap}%-4s${reset_text}, ${cpu_load_5_heatmap}%-4s${reset_text}, ${cpu_load_15_heatmap}%-4s${reset_text}${clear_line}\n" "CPU Temp:" "${cpu_temp}" "Load:" "${cpu_load_1}" "${cpu_load_5}" "${cpu_load_15}" + moveXOffset; printf " %-10s${temp_heatmap}%-17s${reset_text} %-8s${cpu_load_1_heatmap}%-4s${reset_text}, ${cpu_load_5_heatmap}%-4s${reset_text}, ${cpu_load_15_heatmap}%-4s${reset_text}${clear_line}\n" "CPU Temp:" "${temperature}" "Load:" "${cpu_load_1}" "${cpu_load_5}" "${cpu_load_15}" moveXOffset; printf " %-10s[${memory_heatmap}%-7s${reset_text}] %-6s %-8s[${cpu_load_1_heatmap}%-7s${reset_text}] %-5s${clear_line}" "Memory:" "${memory_bar}" "${memory_percent}%" "CPU:" "${cpu_bar}" "${cpu_percent}%" elif [ "$1" = "regular" ] || [ "$1" = "slim" ]; then # slim is a screen with at least 60 columns and exactly 21 lines @@ -974,7 +944,7 @@ PrintDashboard() { fi moveXOffset; printf "%s${clear_line}\n" "${bold_text}SYSTEM =====================================================${reset_text}" moveXOffset; printf " %-10s%-39s${clear_line}\n" "Uptime:" "${system_uptime}" - moveXOffset; printf " %-10s${temp_heatmap}%-21s${reset_text}%-10s${cpu_load_1_heatmap}%-4s${reset_text}, ${cpu_load_5_heatmap}%-4s${reset_text}, ${cpu_load_15_heatmap}%-4s${reset_text}${clear_line}\n" "CPU Temp:" "${cpu_temp}" "CPU Load:" "${cpu_load_1}" "${cpu_load_5}" "${cpu_load_15}" + moveXOffset; printf " %-10s${temp_heatmap}%-21s${reset_text}%-10s${cpu_load_1_heatmap}%-4s${reset_text}, ${cpu_load_5_heatmap}%-4s${reset_text}, ${cpu_load_15_heatmap}%-4s${reset_text}${clear_line}\n" "CPU Temp:" "${temperature}" "CPU Load:" "${cpu_load_1}" "${cpu_load_5}" "${cpu_load_15}" moveXOffset; printf " %-10s[${memory_heatmap}%-10s${reset_text}] %-6s %-10s[${cpu_load_1_heatmap}%-10s${reset_text}] %-5s${clear_line}" "Memory:" "${memory_bar}" "${memory_percent}%" "CPU Load:" "${cpu_bar}" "${cpu_percent}%" else # ${padd_size} = mega # mega is a screen with at least 80 columns and 26 lines @@ -1003,7 +973,7 @@ PrintDashboard() { moveXOffset; printf "%s${clear_line}\n" "${bold_text}SYSTEM =========================================================================${reset_text}" moveXOffset; printf " %-10s%-39s${clear_line}\n" "Device:" "${sys_model}" moveXOffset; printf " %-10s%-39s %-10s[${memory_heatmap}%-10s${reset_text}] %-6s${clear_line}\n" "Uptime:" "${system_uptime}" "Memory:" "${memory_bar}" "${memory_percent}%" - moveXOffset; printf " %-10s${temp_heatmap}%-10s${reset_text} %-10s${cpu_load_1_heatmap}%-4s${reset_text}, ${cpu_load_5_heatmap}%-4s${reset_text}, ${cpu_load_15_heatmap}%-7s${reset_text} %-10s[${memory_heatmap}%-10s${reset_text}] %-6s${clear_line}" "CPU Temp:" "${cpu_temp}" "CPU Load:" "${cpu_load_1}" "${cpu_load_5}" "${cpu_load_15}" "CPU Load:" "${cpu_bar}" "${cpu_percent}%" + moveXOffset; printf " %-10s${temp_heatmap}%-10s${reset_text} %-10s${cpu_load_1_heatmap}%-4s${reset_text}, ${cpu_load_5_heatmap}%-4s${reset_text}, ${cpu_load_15_heatmap}%-7s${reset_text} %-10s[${memory_heatmap}%-10s${reset_text}] %-6s${clear_line}" "CPU Temp:" "${temperature}" "CPU Load:" "${cpu_load_1}" "${cpu_load_5}" "${cpu_load_15}" "CPU Load:" "${cpu_bar}" "${cpu_percent}%" fi # Clear to end of screen (below the drawn dashboard) @@ -1212,7 +1182,12 @@ truncateString() { fi } - +# Converts seconds to days, hours, minuts +#https://unix.stackexchange.com/a/338844 +convertUptime() { + # shellcheck disable=SC2016 + eval "echo $(date -ud "@$1" +'$((%s/3600/24)) days, %H hours, %M minutes')" +} ########################################## MAIN FUNCTIONS ########################################## @@ -1229,7 +1204,7 @@ OutputJSON() { # Test if the authentication endpoint is availabe TestAPIAvailability # Authenticate with the FTL server - printf "%b" "Establishing connection with FTL...\n" + moveXOffset; printf "%b" "Establishing connection with FTL...\n" Authenthication GetSummaryInformation @@ -1254,7 +1229,7 @@ StartupRoutine(){ moveXOffset; printf "%b" "START-UP ===========\n" # Authenticate with the FTL server - printf "%b" "Establishing connection with FTL...\n" + moveXOffset; printf "%b" "Establishing connection with FTL...\n" Authenthication printf "%b" "Starting PADD...\n" @@ -1267,7 +1242,7 @@ StartupRoutine(){ # Get our information for the first time moveXOffset; printf "%b" " [■■■■······] 40%\r" - GetSystemInformation + GetVersionInformation moveXOffset; printf "%b" " [■■■■■·····] 50%\r" GetSummaryInformation moveXOffset; printf "%b" " [■■■■■■····] 60%\r" @@ -1275,7 +1250,7 @@ StartupRoutine(){ moveXOffset; printf "%b" " [■■■■■■■···] 70%\r" GetNetworkInformation moveXOffset; printf "%b" " [■■■■■■■■··] 80%\r" - GetVersionInformation + GetSystemInformation moveXOffset; printf "%b" " [■■■■■■■■■·] 90%\r" GetPADDInformation moveXOffset; printf "%b" " [■■■■■■■■■■] 100%\n" @@ -1284,10 +1259,12 @@ StartupRoutine(){ moveXOffset; PrintLogo "$1" moveXOffset; echo "START UP =====================" # Authenticate with the FTL server - printf "%b" "Establishing connection with FTL...\n" + moveXOffset; printf "%b" "Establishing connection with FTL...\n" Authenthication # Get our information for the first time + moveXOffset; echo "- Gathering version info." + GetVersionInformation moveXOffset; echo "- Gathering system info." GetSystemInformation moveXOffset; echo "- Gathering Pi-hole info." @@ -1295,8 +1272,6 @@ StartupRoutine(){ GetSummaryInformation moveXOffset; echo "- Gathering network info." GetNetworkInformation - moveXOffset; echo "- Gathering version info." - GetVersionInformation GetPADDInformation moveXOffset; echo " - Core $CORE_VERSION, Web $WEB_VERSION" moveXOffset; echo " - FTL $FTL_VERSION, PADD $padd_version" @@ -1314,11 +1289,13 @@ StartupRoutine(){ # Authenticate with the FTL server - printf "%b" "Establishing connection with FTL...\n" + moveXOffset; printf "%b" "Establishing connection with FTL...\n" Authenthication # Get our information for the first time + moveXOffset; echo "- Gathering version information..." + GetVersionInformation moveXOffset; echo "- Gathering system information..." GetSystemInformation moveXOffset; echo "- Gathering Pi-hole information..." @@ -1326,8 +1303,7 @@ StartupRoutine(){ GetPiholeInformation moveXOffset; echo "- Gathering network information..." GetNetworkInformation - moveXOffset; echo "- Gathering version information..." - GetVersionInformation + GetPADDInformation moveXOffset; echo " - Pi-hole Core $CORE_VERSION" moveXOffset; echo " - Web Admin $WEB_VERSION" From 1a23a9c3d8eca1eabd24a25c9d2d186975165693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 16 Jan 2023 21:12:04 +0100 Subject: [PATCH 16/81] Mask user password during input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 57 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/padd.sh b/padd.sh index 0245cb02..6b8e7dcc 100755 --- a/padd.sh +++ b/padd.sh @@ -144,14 +144,8 @@ Authenthication() { moveXOffset; echo "Wrong password supplied, please enter the correct password:" fi - # POSIX's `read` does not support `-s` option (suppressing the input) - # this workaround changes the terminal characteristics to not echo input and later rests this option - # credits https://stackoverflow.com/a/4316765 - - stty -echo - read -r password - stty "${stty_orig}" - echo "" + # secretly read the password + moveXOffset; secretRead; printf '\n' # Try to authenticate again ChallengeResponse @@ -1189,6 +1183,53 @@ convertUptime() { eval "echo $(date -ud "@$1" +'$((%s/3600/24)) days, %H hours, %M minutes')" } +secretRead() { + + # POSIX compliant function to read user-input and + # mask every character entered by (*) + # + # This is challenging, because in POSIX, `read` does not support + # `-s` option (suppressing the input) or + # `-n` option (reading n chars) + + + # This workaround changes the terminal characteristics to not echo input and later rests this option + # credits https://stackoverflow.com/a/4316765 + # showing astrix instead of password + # https://stackoverflow.com/a/24600839 + # https://unix.stackexchange.com/a/464963 + + stty -echo # do not echo user input + stty -icanon min 1 time 0 # disable cannonical mode https://man7.org/linux/man-pages/man3/termios.3.html + + unset password + unset key + unset charcount + charcount=0 + while key=$(dd ibs=1 count=1 2>/dev/null); do #read one byte of input + if [ "${key}" = "$(printf '\0' | tr -d '\0')" ] ; then + # Enter - accept password + break + fi + if [ "${key}" = "$(printf '\177')" ] ; then + # Backspace + if [ $charcount -gt 0 ] ; then + charcount=$((charcount-1)) + printf '\b \b' + password="${password%?}" + fi + else + # any other character + charcount=$((charcount+1)) + printf '*' + password="$password$key" + fi + done + + # restore original terminal settings + stty "${stty_orig}" +} + ########################################## MAIN FUNCTIONS ########################################## OutputJSON() { From d3a209e40718c0ea8f518b72bb96607f036a39f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 16 Jan 2023 21:25:39 +0100 Subject: [PATCH 17/81] Format memory_percentage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/padd.sh b/padd.sh index 6b8e7dcc..a1add843 100755 --- a/padd.sh +++ b/padd.sh @@ -299,7 +299,8 @@ GetSystemInformation() { cpu_percent=$(printf %.1f "$(echo "${sysinfo}" | jq .system.cpu.load.percent[0])") # Memory use, heatmap and bar - memory_percent="$(echo "${sysinfo}" | jq '.system.memory.ram."%used"')" + memory_percent_raw="$(echo "${sysinfo}" | jq '.system.memory.ram."%used"')" + memory_percent=$(printf %.1f "${memory_percent_raw}") memory_heatmap="$(HeatmapGenerator "${memory_percent}")" # Get device model From e0f78cfaf0793f5613ed8663900a84e1230aa7ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 19 Jan 2023 21:40:14 +0100 Subject: [PATCH 18/81] Adjust for changed API endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/padd.sh b/padd.sh index a1add843..8bae11cd 100755 --- a/padd.sh +++ b/padd.sh @@ -471,7 +471,7 @@ GetPiholeInformation() { ftl_cpu="$(printf "%.1f" "${ftl_cpu_raw}")%" ftl_mem_percentage="$(printf "%.1f" "${ftl_mem_percentage_raw}")%" # Get Pi-hole (blocking) status - ftl_dns_port=$(GetFTLData "/dns/port" | jq .dns_port) + ftl_dns_port=$(GetFTLData "/config" | jq .config.dnsmasq.port) fi From 7c6efb10bcec045ee5a1b75e2dbc09f12ff67486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 20 Jan 2023 07:29:49 +0100 Subject: [PATCH 19/81] Use 127.0.0.1 instead of pi.hole as default address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/padd.sh b/padd.sh index 991a85e8..f13e184b 100755 --- a/padd.sh +++ b/padd.sh @@ -103,7 +103,7 @@ padd_logo_retro_3="${bold_text}${green_text}| ${red_text}/${yellow_text}-${gre ConstructAPI() { # If no arguments were supplied set them to default if [ -z "${URL}" ]; then - URL=pi.hole + URL=127.0.0.1 fi if [ -z "${PORT}" ]; then PORT=8080 @@ -1475,7 +1475,7 @@ DisplayHelp() { ::: -xoff [num] set the x-offset, reference is the upper left corner, disables auto-centering ::: -yoff [num] set the y-offset, reference is the upper left corner, disables auto-centering ::: -::: -u URL or address of your Pi-hole (default: pi.hole) +::: -u URL or address of your Pi-hole (default: 127.0.0.1) ::: -p Port of your Pi-hole's API (default: 8080) ::: -a Path where your Pi-hole's API is hosted (default: api) ::: -s Your Pi-hole's password, required to access the API From 9acad77431fdf8fb73a596aa7fad391a1f28dfce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 22 Jan 2023 09:51:02 +0100 Subject: [PATCH 20/81] Adjust FTL endpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/padd.sh b/padd.sh index f13e184b..99769367 100755 --- a/padd.sh +++ b/padd.sh @@ -207,14 +207,14 @@ GetFTLData() { GetSummaryInformation() { summary=$(GetFTLData "/stats/summary") cache_info=$(GetFTLData "/dns/cache") - sysinfo=$(GetFTLData "/ftl/sysinfo") + ftl_info=$(GetFTLData "/info/ftl") dns_blocking=$(GetFTLData "/dns/blocking") - clients=$(echo "${sysinfo}" | jq .ftl.clients.active ) + clients=$(echo "${ftl_info}" | jq .ftl.clients.active ) blocking_enabled=$(echo "${dns_blocking}" | jq .blocking ) - domains_being_blocked_raw=$(echo "${sysinfo}" | jq .ftl.database.gravity) + domains_being_blocked_raw=$(echo "${ftl_info}" | jq .ftl.database.gravity) domains_being_blocked=$(printf "%.f" "${domains_being_blocked_raw}") dns_queries_today_raw=$(echo "$summary" | jq .queries.total ) @@ -244,15 +244,15 @@ GetSummaryInformation() { } GetSystemInformation() { - sysinfo=$(GetFTLData "/ftl/sysinfo") + sysinfo=$(GetFTLData "/info/system") # System uptime system_uptime_raw=$(echo "${sysinfo}" | jq .system.uptime ) # CPU temperature and unit - cpu_temp_raw=$(echo "${sysinfo}" | jq .system.sensors[0].value) + cpu_temp_raw=$(GetFTLData "/info/sensors" | jq .sensors[0].value) cpu_temp=$(printf "%.1f" "${cpu_temp_raw}") - temp_unit=$(echo "${sysinfo}" | jq --raw-output .system.sensors[0].unit) + temp_unit=$(GetFTLData "/info/sensors" | jq --raw-output .sensors[0].unit) # Temp + Unit if [ "${temp_unit}" = "C" ]; then @@ -301,7 +301,7 @@ GetSystemInformation() { memory_heatmap="$(HeatmapGenerator "${memory_percent}")" # Get device model - sys_model="$(echo "${sysinfo}" | jq --raw-output .system.model)" + sys_model="$(GetFTLData "/info/host" | jq --raw-output .host.model)" # DOCKER_VERSION is set during GetVersionInformation, so this needs to run first during startup if [ ! "${DOCKER_VERSION}" = "null" ]; then @@ -319,7 +319,6 @@ GetSystemInformation() { GetNetworkInformation() { interfaces_raw=$(GetFTLData "/network/interfaces") - sysinfo=$(GetFTLData "/ftl/sysinfo") config=$(GetFTLData "/config") # Get pi IPv4 address of the default interface @@ -387,7 +386,7 @@ GetNetworkInformation() { fi # Get hostname - pi_hostname="$(echo "${sysinfo}" | jq --raw-output .system.uname.nodename)" + pi_hostname="$(GetFTLData "/info/host" | jq --raw-output .host.uname.nodename)" full_hostname=${pi_hostname} # when PI-hole is the DHCP server, append the domain to the hostname if [ "${DHCP_ACTIVE}" = "true" ]; then @@ -443,7 +442,7 @@ GetNetworkInformation() { } GetPiholeInformation() { - sysinfo=$(GetFTLData "/ftl/sysinfo") + sysinfo=$(GetFTLData "/info/ftl") # Get FTL's current PID ftlPID="$(echo "${sysinfo}" | jq .ftl.pid)" @@ -491,7 +490,7 @@ fi GetVersionInformation() { out_of_date_flag=false - versions_raw=$(GetFTLData "/version") + versions_raw=$(GetFTLData "/info/version") # Gather DOCKER version information... # returns "null" if not running Pi-hole in Docker container @@ -1297,6 +1296,9 @@ StartupRoutine(){ moveXOffset; PrintLogo "$1" moveXOffset; printf "%b" "START-UP ===========\n" + # Test if the authentication endpoint is availabe + TestAPIAvailability + # Authenticate with the FTL server moveXOffset; printf "%b" "Establishing connection with FTL...\n" Authenthication @@ -1327,6 +1329,8 @@ StartupRoutine(){ elif [ "$1" = "mini" ]; then moveXOffset; PrintLogo "$1" moveXOffset; echo "START UP =====================" + # Test if the authentication endpoint is availabe + TestAPIAvailability # Authenticate with the FTL server moveXOffset; printf "%b" "Establishing connection with FTL...\n" Authenthication @@ -1359,6 +1363,8 @@ StartupRoutine(){ moveXOffset; echo "START UP ===================================================" fi + # Test if the authentication endpoint is availabe + TestAPIAvailability # Authenticate with the FTL server moveXOffset; printf "%b" "Establishing connection with FTL...\n" @@ -1557,13 +1563,9 @@ main(){ # Save current terminal settings (needed for later restore after password prompt) stty_orig=$(stty -g) - # Construct FTL's API address depending on the arguments supplied ConstructAPI - # Test if the authentication endpoint is availabe - TestAPIAvailability - SizeChecker StartupRoutine ${padd_size} From 9eb478a35f31f10cf22ffc5409529936c9e08b79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 22 Jan 2023 21:17:01 +0100 Subject: [PATCH 21/81] Handle connection loss and re-authentication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 203 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 116 insertions(+), 87 deletions(-) diff --git a/padd.sh b/padd.sh index 99769367..f974e54b 100755 --- a/padd.sh +++ b/padd.sh @@ -52,7 +52,7 @@ pico_status_ok="${check_box_good} Sys. OK" pico_status_update="${check_box_info} Update" pico_status_hot="${check_box_bad} Sys. Hot!" pico_status_off="${check_box_info} No blck" -pico_status_ftl_down="${check_box_bad} FTL Down" +pico_status_ftl_down="${check_box_bad} No CXN" pico_status_dns_down="${check_box_bad} DNS Down" # MINI STATUS @@ -60,7 +60,7 @@ mini_status_ok="${check_box_good} System OK" mini_status_update="${check_box_info} Update avail." mini_status_hot="${check_box_bad} System is hot!" mini_status_off="${check_box_info} No blocking!" -mini_status_ftl_down="${check_box_bad} FTL down!" +mini_status_ftl_down="${check_box_bad} No connection!" mini_status_dns_down="${check_box_bad} DNS off!" # REGULAR STATUS @@ -68,7 +68,7 @@ full_status_ok="${check_box_good} System is healthy" full_status_update="${check_box_info} Updates are available" full_status_hot="${check_box_bad} System is hot!" full_status_off="${check_box_info} Blocking is disabled" -full_status_ftl_down="${check_box_bad} FTL is down!" +full_status_ftl_down="${check_box_bad} No connection!" full_status_dns_down="${check_box_bad} DNS is off!" # MEGA STATUS @@ -76,7 +76,7 @@ mega_status_ok="${check_box_good} Your system is healthy" mega_status_update="${check_box_info} Updates are available" mega_status_hot="${check_box_bad} Your system is hot!" mega_status_off="${check_box_info} Blocking is disabled!" -mega_status_ftl_down="${check_box_bad} FTLDNS service is not running!" +mega_status_ftl_down="${check_box_bad} No connection to FTL!" mega_status_dns_down="${check_box_bad} Pi-hole's DNS server is off!" # TINY STATUS @@ -84,7 +84,7 @@ tiny_status_ok="${check_box_good} System is healthy" tiny_status_update="${check_box_info} Updates are available" tiny_status_hot="${check_box_bad} System is hot!" tiny_status_off="${check_box_info} Blocking is disabled" -tiny_status_ftl_down="${check_box_bad} FTL is down!" +tiny_status_ftl_down="${check_box_bad} No connection to FTL!" tiny_status_dns_down="${check_box_bad} DNS is off!" # Text only "logos" @@ -172,6 +172,7 @@ DeleteSession() { ChallengeResponse() { # Challenge-response authentication + local response # Compute password hash from user password # Compute password hash twice to avoid rainbow table vulnerability @@ -182,7 +183,7 @@ ChallengeResponse() { # Get challenge from FTL # Calculate response based on challenge and password hash # Send response & get session response - challenge="$(curl --silent -X GET "http://${URL}:${PORT}/${APIPATH}/auth" | jq --raw-output .challenge)" + challenge="$(curl --silent -X GET "http://${URL}:${PORT}/${APIPATH}/auth" | jq --raw-output .challenge 2>/dev/null)" response="$(printf "%b" "${challenge}:${pwhash}" | sha256sum | sed 's/\s.*$//')" sessionResponse="$(curl --silent -X POST "http://${URL}:${PORT}/${APIPATH}/auth" --data "{\"response\":\"${response}\"}" )" @@ -192,13 +193,29 @@ ChallengeResponse() { exit 1 fi # obtain validity and session ID from session response - validSession=$(echo "${sessionResponse}"| jq .session.valid) - SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid) + validSession=$(echo "${sessionResponse}"| jq .session.valid 2>/dev/null) + SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid 2>/dev/null) } GetFTLData() { - data=$(curl -sS -X GET "http://${URL}:${PORT}/${APIPATH}$1" -H "Accept: application/json" -H "sid: ${SID}" ) - echo "${data}" + local response + # get the data from querying the API as well as the http status code + response=$(curl -s -w "%{http_code}" -X GET "http://${URL}:${PORT}/${APIPATH}$1" -H "Accept: application/json" -H "sid: ${SID}" ) + + # status are the last 3 characters + status=$(printf %s "${response#"${response%???}"}") + # data is everything from repsonse without the last 3 characters + data=$(printf %s "${response%???}") + + if [ "${status}" = 200 ]; then + echo "${data}" + elif [ "${status}" = 000 ]; then + # connection lost + echo "000" + elif [ "${status}" = 401 ]; then + # unauthorized + echo "401" + fi } @@ -210,36 +227,36 @@ GetSummaryInformation() { ftl_info=$(GetFTLData "/info/ftl") dns_blocking=$(GetFTLData "/dns/blocking") - clients=$(echo "${ftl_info}" | jq .ftl.clients.active ) + clients=$(echo "${ftl_info}" | jq .ftl.clients.active 2>/dev/null) - blocking_enabled=$(echo "${dns_blocking}" | jq .blocking ) + blocking_enabled=$(echo "${dns_blocking}" | jq .blocking 2>/dev/null) - domains_being_blocked_raw=$(echo "${ftl_info}" | jq .ftl.database.gravity) + domains_being_blocked_raw=$(echo "${ftl_info}" | jq .ftl.database.gravity 2>/dev/null) domains_being_blocked=$(printf "%.f" "${domains_being_blocked_raw}") - dns_queries_today_raw=$(echo "$summary" | jq .queries.total ) + dns_queries_today_raw=$(echo "$summary" | jq .queries.total 2>/dev/null) dns_queries_today=$(printf "%.f" "${dns_queries_today_raw}") - ads_blocked_today_raw=$(echo "$summary" | jq .queries.blocked ) + ads_blocked_today_raw=$(echo "$summary" | jq .queries.blocked 2>/dev/null) ads_blocked_today=$(printf "%.f" "${ads_blocked_today_raw}") - ads_percentage_today_raw=$(echo "$summary" | jq .queries.percent_blocked) + ads_percentage_today_raw=$(echo "$summary" | jq .queries.percent_blocked 2>/dev/null) ads_percentage_today=$(printf "%.1f" "${ads_percentage_today_raw}") - cache_size=$(echo "$cache_info" | jq .cache.size) - cache_evictions=$(echo "$cache_info" | jq .cache.evicted) - cache_inserts=$(echo "$cache_info"| jq .cache.inserted) + cache_size=$(echo "$cache_info" | jq .cache.size 2>/dev/null) + cache_evictions=$(echo "$cache_info" | jq .cache.evicted 2>/dev/null) + cache_inserts=$(echo "$cache_info"| jq .cache.inserted 2>/dev/null) - latest_blocked_raw=$(GetFTLData "/stats/recent_blocked?show=1" | jq --raw-output .blocked[0]) + latest_blocked_raw=$(GetFTLData "/stats/recent_blocked?show=1" | jq --raw-output .blocked[0] 2>/dev/null) - top_blocked_raw=$(GetFTLData "/stats/top_domains?blocked=true" | jq --raw-output .domains[0].domain) + top_blocked_raw=$(GetFTLData "/stats/top_domains?blocked=true" | jq --raw-output .domains[0].domain 2>/dev/null) - top_domain_raw=$(GetFTLData "/stats/top_domains" | jq --raw-output .domains[0].domain) + top_domain_raw=$(GetFTLData "/stats/top_domains" | jq --raw-output .domains[0].domain 2>/dev/null) - top_client_raw=$(GetFTLData "/stats/top_clients" | jq --raw-output .clients[0].name) + top_client_raw=$(GetFTLData "/stats/top_clients" | jq --raw-output .clients[0].name 2>/dev/null) if [ -z "${top_client_raw}" ]; then # if no hostname was supplied, use IP - top_client_raw=$(GetFTLData "/stats/top_clients" | jq --raw-output .clients[0].ip) + top_client_raw=$(GetFTLData "/stats/top_clients" | jq --raw-output .clients[0].ip 2>/dev/null) fi } @@ -247,12 +264,17 @@ GetSystemInformation() { sysinfo=$(GetFTLData "/info/system") # System uptime - system_uptime_raw=$(echo "${sysinfo}" | jq .system.uptime ) + if [ "${sysinfo}" = 000 ]; then + # in case FTL connection is down, system_uptime_raw need to be set to 0 otherwise convertUptime() will complain + system_uptime_raw=0 + else + system_uptime_raw=$(echo "${sysinfo}" | jq .system.uptime 2>/dev/null) + fi # CPU temperature and unit - cpu_temp_raw=$(GetFTLData "/info/sensors" | jq .sensors[0].value) + cpu_temp_raw=$(GetFTLData "/info/sensors" | jq .sensors[0].value 2>/dev/null) cpu_temp=$(printf "%.1f" "${cpu_temp_raw}") - temp_unit=$(GetFTLData "/info/sensors" | jq --raw-output .sensors[0].unit) + temp_unit=$(GetFTLData "/info/sensors" | jq --raw-output .sensors[0].unit 2>/dev/null) # Temp + Unit if [ "${temp_unit}" = "C" ]; then @@ -286,22 +308,22 @@ GetSystemInformation() { fi # CPU, load, heatmap - core_count=$(echo "${sysinfo}" | jq .system.cpu.nprocs) - cpu_load_1=$(printf %.2f "$(echo "${sysinfo}" | jq .system.cpu.load.raw[0])") - cpu_load_5=$(printf %.2f "$(echo "${sysinfo}" | jq .system.cpu.load.raw[1])") - cpu_load_15=$(printf %.2f "$(echo "${sysinfo}" | jq .system.cpu.load.raw[2])") + core_count=$(echo "${sysinfo}" | jq .system.cpu.nprocs 2>/dev/null) + cpu_load_1=$(printf %.2f "$(echo "${sysinfo}" | jq .system.cpu.load.raw[0] 2>/dev/null)") + cpu_load_5=$(printf %.2f "$(echo "${sysinfo}" | jq .system.cpu.load.raw[1] 2>/dev/null)") + cpu_load_15=$(printf %.2f "$(echo "${sysinfo}" | jq .system.cpu.load.raw[2] 2>/dev/null)") cpu_load_1_heatmap=$(HeatmapGenerator "${cpu_load_1}" "${core_count}") cpu_load_5_heatmap=$(HeatmapGenerator "${cpu_load_5}" "${core_count}") cpu_load_15_heatmap=$(HeatmapGenerator "${cpu_load_15}" "${core_count}") - cpu_percent=$(printf %.1f "$(echo "${sysinfo}" | jq .system.cpu.load.percent[0])") + cpu_percent=$(printf %.1f "$(echo "${sysinfo}" | jq .system.cpu.load.percent[0] 2>/dev/null)") # Memory use, heatmap and bar - memory_percent_raw="$(echo "${sysinfo}" | jq '.system.memory.ram."%used"')" + memory_percent_raw="$(echo "${sysinfo}" | jq '.system.memory.ram."%used"' 2>/dev/null)" memory_percent=$(printf %.1f "${memory_percent_raw}") memory_heatmap="$(HeatmapGenerator "${memory_percent}")" # Get device model - sys_model="$(GetFTLData "/info/host" | jq --raw-output .host.model)" + sys_model="$(GetFTLData "/info/host" | jq --raw-output .host.model 2>/dev/null)" # DOCKER_VERSION is set during GetVersionInformation, so this needs to run first during startup if [ ! "${DOCKER_VERSION}" = "null" ]; then @@ -322,40 +344,40 @@ GetNetworkInformation() { config=$(GetFTLData "/config") # Get pi IPv4 address of the default interface - pi_ip4_addrs="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv4[]' | wc -w)" + pi_ip4_addrs="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv4[]' 2>/dev/null | wc -w)" if [ "${pi_ip4_addrs}" -eq 0 ]; then # No IPv4 address available pi_ip4_addr="N/A" elif [ "${pi_ip4_addrs}" -eq 1 ]; then # One IPv4 address available - pi_ip4_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv4[0]')" + pi_ip4_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv4[0]' 2>/dev/null)" else # More than one IPv4 address available - pi_ip4_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv4[0]')+" + pi_ip4_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv4[0]' 2>/dev/null)+" fi # Get pi IPv6 address of the default interface - pi_ip6_addrs="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv6[]' | wc -w)" + pi_ip6_addrs="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv6[]' 2>/dev/null | wc -w)" if [ "${pi_ip6_addrs}" -eq 0 ]; then # No IPv6 address available pi_ip6_addr="N/A" ipv6_check_box=${check_box_bad} elif [ "${pi_ip6_addrs}" -eq 1 ]; then # One IPv6 address available - pi_ip6_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv6[0]' | cut -f1 -d "%" )" + pi_ip6_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv6[0]' 2>/dev/null | cut -f1 -d "%" )" ipv6_check_box=${check_box_good} else # More than one IPv6 address available - pi_ip6_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv6[0]' | cut -f1 -d "%" )+" + pi_ip6_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv6[0]' 2>/dev/null | cut -f1 -d "%" )+" ipv6_check_box=${check_box_good} fi # Is Pi-Hole acting as the DHCP server? - DHCP_ACTIVE="$(echo "${config}" | jq .config.dnsmasq.dhcp.active)" + DHCP_ACTIVE="$(echo "${config}" | jq .config.dnsmasq.dhcp.active 2>/dev/null )" if [ "${DHCP_ACTIVE}" = "true" ]; then - DHCP_START="$(echo "${config}" | jq --raw-output .config.dnsmasq.dhcp.start)" - DHCP_END="$(echo "${config}" | jq --raw-output .config.dnsmasq.dhcp.end)" + DHCP_START="$(echo "${config}" | jq --raw-output .config.dnsmasq.dhcp.start 2>/dev/null)" + DHCP_END="$(echo "${config}" | jq --raw-output .config.dnsmasq.dhcp.end 2>/dev/null)" dhcp_status="Enabled" dhcp_info=" Range: ${DHCP_START} - ${DHCP_END}" @@ -363,7 +385,7 @@ GetNetworkInformation() { dhcp_check_box=${check_box_good} # Is DHCP handling IPv6? - DHCP_IPv6="$(echo "${config}" | jq --raw-output .config.dnsmasq.dhcp.ipv6)" + DHCP_IPv6="$(echo "${config}" | jq --raw-output .config.dnsmasq.dhcp.ipv6 2>/dev/null)" if [ "${DHCP_IPv6}" = "true" ]; then dhcp_ipv6_status="Enabled" dhcp_ipv6_heatmap=${green_text} @@ -378,7 +400,7 @@ GetNetworkInformation() { dhcp_heatmap=${red_text} dhcp_check_box=${check_box_bad} - GATEWAY="$(GetFTLData "/network/gateway" | jq --raw-output .address)" + GATEWAY="$(GetFTLData "/network/gateway" | jq --raw-output .address 2>/dev/null)" dhcp_info=" Router: ${GATEWAY}" dhcp_ipv6_status="N/A" dhcp_ipv6_heatmap=${yellow_text} @@ -386,11 +408,11 @@ GetNetworkInformation() { fi # Get hostname - pi_hostname="$(GetFTLData "/info/host" | jq --raw-output .host.uname.nodename)" + pi_hostname="$(GetFTLData "/info/host" | jq --raw-output .host.uname.nodename 2>/dev/null)" full_hostname=${pi_hostname} # when PI-hole is the DHCP server, append the domain to the hostname if [ "${DHCP_ACTIVE}" = "true" ]; then - PIHOLE_DOMAIN="$(echo "${config}" | jq --raw-output .config.dnsmasq.domain)" + PIHOLE_DOMAIN="$(echo "${config}" | jq --raw-output .config.dnsmasq.domain 2>/dev/null)" if [ -n "${PIHOLE_DOMAIN}" ]; then count=${pi_hostname}"."${PIHOLE_DOMAIN} count=${#count} @@ -401,7 +423,7 @@ GetNetworkInformation() { fi # Get the number of configured upstream DNS servers - dns_count="$(echo "${config}" | jq --raw-output .config.dnsmasq.upstreams[] | sed '/^\s*$/d' | wc -l)" + dns_count="$(echo "${config}" | jq --raw-output .config.dnsmasq.upstreams[] 2>/dev/null | sed '/^\s*$/d' | wc -l)" # if there's only one DNS server if [ "${dns_count}" -eq 1 ]; then dns_information="1 server" @@ -411,7 +433,7 @@ GetNetworkInformation() { # DNSSEC - DNSSEC="$(echo "${config}" | jq .config.dnsmasq.dnssec)" + DNSSEC="$(echo "${config}" | jq .config.dnsmasq.dnssec 2>/dev/null)" if [ "${DNSSEC}" = "true" ]; then dnssec_status="Enabled" dnssec_heatmap=${green_text} @@ -421,7 +443,7 @@ GetNetworkInformation() { fi # Conditional forwarding - CONDITIONAL_FORWARDING="$(echo "${config}" | jq .config.dnsmasq.rev_server.active)" + CONDITIONAL_FORWARDING="$(echo "${config}" | jq .config.dnsmasq.rev_server.active 2>/dev/null)" if [ "${CONDITIONAL_FORWARDING}" = "true" ]; then conditional_forwarding_status="Enabled" conditional_forwarding_heatmap=${green_text} @@ -431,30 +453,27 @@ GetNetworkInformation() { fi # Default interface data - iface_name="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .name')" - tx_bytes="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .tx.num')" - tx_bytes_unit="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .tx.unit')" + iface_name="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .name' 2>/dev/null)" + tx_bytes="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .tx.num' 2>/dev/null)" + tx_bytes_unit="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .tx.unit' 2>/dev/null)" tx_bytes=$(printf "%.1f %b" "${tx_bytes}" "${tx_bytes_unit}") - rx_bytes="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .rx.num')" - rx_bytes_unit="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .rx.unit')" + rx_bytes="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .rx.num' 2>/dev/null)" + rx_bytes_unit="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .rx.unit' 2>/dev/null)" rx_bytes=$(printf "%.1f %b" "${rx_bytes}" "${rx_bytes_unit}") } GetPiholeInformation() { sysinfo=$(GetFTLData "/info/ftl") - # Get FTL's current PID - ftlPID="$(echo "${sysinfo}" | jq .ftl.pid)" - - # If FTL is not running (ftlPID is -1), set all variables to "not running" - ftl_down_flag=false - if [ "${ftlPID}" = "-1" ]; then - ftl_status="Not running" + # If FTL is not running (sysinfo is 000), set all variables to "not running" + connection_down_flag=false + if [ "${sysinfo}" = "000" ]; then + ftl_status="No connection" ftl_heatmap=${red_text} ftl_check_box=${check_box_bad} # set flag to change the status message in SetStatusMessage() - ftl_down_flag=true + connection_down_flag=true ftl_cpu="N/A" ftl_mem_percentage="N/A" else @@ -462,19 +481,21 @@ GetPiholeInformation() { ftl_heatmap=${green_text} ftl_check_box=${check_box_good} # Get FTL CPU and memory usage - ftl_cpu_raw="$(echo "${sysinfo}" | jq '.ftl."%cpu"')" - ftl_mem_percentage_raw="$(echo "${sysinfo}" | jq '.ftl."%mem"')" + ftl_cpu_raw="$(echo "${sysinfo}" | jq '.ftl."%cpu"' 2>/dev/null)" + ftl_mem_percentage_raw="$(echo "${sysinfo}" | jq '.ftl."%mem"' 2>/dev/null)" ftl_cpu="$(printf "%.1f" "${ftl_cpu_raw}")%" ftl_mem_percentage="$(printf "%.1f" "${ftl_mem_percentage_raw}")%" # Get Pi-hole (blocking) status - ftl_dns_port=$(GetFTLData "/config" | jq .config.dnsmasq.port) + ftl_dns_port=$(GetFTLData "/config" | jq .config.dnsmasq.port 2>/dev/null) + # Get FTL's current PID + ftlPID="$(echo "${sysinfo}" | jq .ftl.pid 2>/dev/null)" fi - # ${ftl_dns_port} == 0 DNS server part of dnsmasq disabled, ${ftl_status} == "Not running" no ftlPID found + # ${ftl_dns_port} == 0 DNS server part of dnsmasq disabled dns_down_flag=false - if [ "${ftl_dns_port}" = 0 ] || [ "${ftl_status}" = "Not running" ]; then + if [ "${ftl_dns_port}" = 0 ] || [ "${ftl_status}" = "No connection" ]; then dns_status="DNS offline" dns_heatmap=${red_text} dns_check_box=${check_box_bad} @@ -494,11 +515,11 @@ GetVersionInformation() { # Gather DOCKER version information... # returns "null" if not running Pi-hole in Docker container - DOCKER_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.docker.local)" + DOCKER_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.docker.local 2>/dev/null)" # If PADD is running inside docker, immediately return without checking for updated component versions if [ ! "${DOCKER_VERSION}" = "null" ] ; then - GITHUB_DOCKER_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.docker.remote)" + GITHUB_DOCKER_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.docker.remote 2>/dev/null)" docker_version_converted="$(VersionConverter "${DOCKER_VERSION}")" docker_version_latest_converted="$(VersionConverter "${GITHUB_DOCKER_VERSION}")" @@ -512,11 +533,11 @@ GetVersionInformation() { fi # Gather core version information... - CORE_BRANCH="$(echo "${versions_raw}" | jq --raw-output .version.core.local.branch)" - CORE_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.core.local.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - GITHUB_CORE_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.core.remmote.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - CORE_HASH="$(echo "${versions_raw}" | jq --raw-output .version.core.local.hash)" - GITHUB_CORE_HASH="$(echo "${versions_raw}" | jq --raw-output .version.core.remote.hash)" + CORE_BRANCH="$(echo "${versions_raw}" | jq --raw-output .version.core.local.branch 2>/dev/null)" + CORE_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.core.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_CORE_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.core.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + CORE_HASH="$(echo "${versions_raw}" | jq --raw-output .version.core.local.hash 2>/dev/null)" + GITHUB_CORE_HASH="$(echo "${versions_raw}" | jq --raw-output .version.core.remote.hash 2>/dev/null)" if [ "${CORE_BRANCH}" = "master" ]; then core_version_converted="$(VersionConverter "${CORE_VERSION}")" @@ -550,14 +571,14 @@ GetVersionInformation() { fi # Gather web version information... - WEB_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.web.local.version)" + WEB_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.web.local.version 2>/dev/null)" if [ ! "$WEB_VERSION" = "null" ]; then - WEB_BRANCH="$(echo "${versions_raw}" | jq --raw-output .version.web.local.branch)" - WEB_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.web.local.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - GITHUB_WEB_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.web.remmote.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - WEB_HASH="$(echo "${versions_raw}" | jq --raw-output .version.web.local.hash)" - GITHUB_WEB_HASH="$(echo "${versions_raw}" | jq --raw-output .version.web.remote.hash)" + WEB_BRANCH="$(echo "${versions_raw}" | jq --raw-output .version.web.local.branch 2>/dev/null)" + WEB_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.web.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_WEB_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.web.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + WEB_HASH="$(echo "${versions_raw}" | jq --raw-output .version.web.local.hash 2>/dev/null)" + GITHUB_WEB_HASH="$(echo "${versions_raw}" | jq --raw-output .version.web.remote.hash 2>/dev/null)" if [ "${WEB_BRANCH}" = "master" ]; then web_version_converted="$(VersionConverter "${WEB_VERSION}")" @@ -597,11 +618,11 @@ GetVersionInformation() { fi # Gather FTL version information... - FTL_BRANCH="$(echo "${versions_raw}" | jq --raw-output .version.ftl.local.branch)" - FTL_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.ftl.local.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - GITHUB_FTL_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.ftl.remmote.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - FTL_HASH="$(echo "${versions_raw}" | jq --raw-output .version.ftl.local.hash)" - GITHUB_FTL_HASH="$(echo "${versions_raw}" | jq --raw-output .version.ftl.remote.hash)" + FTL_BRANCH="$(echo "${versions_raw}" | jq --raw-output .version.ftl.local.branch 2>/dev/null)" + FTL_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.ftl.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_FTL_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.ftl.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + FTL_HASH="$(echo "${versions_raw}" | jq --raw-output .version.ftl.local.hash 2>/dev/null)" + GITHUB_FTL_HASH="$(echo "${versions_raw}" | jq --raw-output .version.ftl.remote.hash 2>/dev/null)" if [ "${FTL_BRANCH}" = "master" ]; then @@ -744,7 +765,7 @@ SetStatusMessage() { full_status="${full_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" mega_status="${mega_status_hot} ${blinking_text}${red_text}${temperature}${reset_text}" - elif [ "${ftl_down_flag}" = true ]; then + elif [ "${connection_down_flag}" = true ]; then # Check if FTL is down pico_status=${pico_status_ftl_down} mini_status=${mini_status_ftl_down} @@ -1432,6 +1453,14 @@ NormalPADD() { # Start getting our information for next round now=$(date +%s) + # check if a new authentication is required (e.g. after connection to FTL has re-established) + # GetFTLData() will return a 401 if a 401 http status code is returned + # as $password should be set already, PADD should automatically re-authenticate + authenthication_required=$(GetFTLData "/info/ftl") + if [ "${authenthication_required}" = 401 ]; then + ChallengeResponse + fi + # Get uptime, CPU load, temp, etc. every 5 seconds if [ $((now - LastCheckSystemInformation)) -ge 5 ]; then GetSystemInformation From ed2de7807eaa24fc92b42761c5a4652b554eea34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 12 Mar 2023 22:58:06 +0100 Subject: [PATCH 22/81] Adjust endoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/padd.sh b/padd.sh index ba308ee4..9f738b62 100755 --- a/padd.sh +++ b/padd.sh @@ -223,7 +223,7 @@ GetFTLData() { GetSummaryInformation() { summary=$(GetFTLData "/stats/summary") - cache_info=$(GetFTLData "/dns/cache") + cache_info=$(GetFTLData "/info/metrics") ftl_info=$(GetFTLData "/info/ftl") dns_blocking=$(GetFTLData "/dns/blocking") @@ -243,9 +243,9 @@ GetSummaryInformation() { ads_percentage_today_raw=$(echo "$summary" | jq .queries.percent_blocked 2>/dev/null) ads_percentage_today=$(printf "%.1f" "${ads_percentage_today_raw}") - cache_size=$(echo "$cache_info" | jq .cache.size 2>/dev/null) - cache_evictions=$(echo "$cache_info" | jq .cache.evicted 2>/dev/null) - cache_inserts=$(echo "$cache_info"| jq .cache.inserted 2>/dev/null) + cache_size=$(echo "$cache_info" | jq .metrics.dns.cache.size 2>/dev/null) + cache_evictions=$(echo "$cache_info" | jq .metrics.dns.cache.evicted 2>/dev/null) + cache_inserts=$(echo "$cache_info"| jq .metrics.dns.cache.inserted 2>/dev/null) latest_blocked_raw=$(GetFTLData "/stats/recent_blocked?show=1" | jq --raw-output .blocked[0] 2>/dev/null) @@ -813,7 +813,7 @@ PrintLogo() { if [ ! "${DOCKER_VERSION}" = "null" ]; then version_info="Docker ${docker_version_heatmap}${DOCKER_VERSION}${reset_text}" else - version_info="Pi-hole® ${core_version_heatmap}${CORE_VERSION}${reset_text}, Web ${web_version_heatmap}${WEB_VERSION}${reset_text}, FTL ${ftl_version_heatmap}${FTL_VERSION}" + version_info="Pi-hole® ${core_version_heatmap}${CORE_VERSION}${reset_text}, Web ${web_version_heatmap}${WEB_VERSION}${reset_text}, FTL ${ftl_version_heatmap}${FTL_VERSION}${reset_text}" fi # Screen size checks @@ -846,7 +846,7 @@ PrintDashboard() { if [ ! "${DOCKER_VERSION}" = "null" ]; then version_info="Docker ${docker_version_heatmap}${DOCKER_VERSION}${reset_text}" else - version_info="Pi-hole® ${core_version_heatmap}${CORE_VERSION}${reset_text}, Web ${web_version_heatmap}${WEB_VERSION}${reset_text}, FTL ${ftl_version_heatmap}${FTL_VERSION}" + version_info="Pi-hole® ${core_version_heatmap}${CORE_VERSION}${reset_text}, Web ${web_version_heatmap}${WEB_VERSION}${reset_text}, FTL ${ftl_version_heatmap}${FTL_VERSION}${reset_text}" fi # Move cursor to (0,0). printf '\e[H' From 94032c9574705c01a7719a435ee7f47f9811ad36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 13 Mar 2023 13:51:57 +0100 Subject: [PATCH 23/81] Account for cpu_temp_sensor returning null MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/padd.sh b/padd.sh index 9f738b62..e732cd3d 100755 --- a/padd.sh +++ b/padd.sh @@ -272,9 +272,10 @@ GetSystemInformation() { fi # CPU temperature and unit - cpu_temp_raw=$(GetFTLData "/info/sensors" | jq .sensors[0].value 2>/dev/null) + # in case .sensors.cpu_temp returns 'null' we substitute with 0 + cpu_temp_raw=$(GetFTLData "/info/sensors" | jq '(.sensors.cpu_temp // 0)' 2>/dev/null) cpu_temp=$(printf "%.1f" "${cpu_temp_raw}") - temp_unit=$(GetFTLData "/info/sensors" | jq --raw-output .sensors[0].unit 2>/dev/null) + temp_unit=$(GetFTLData "/info/sensors" | jq --raw-output .sensors.unit 2>/dev/null) # Temp + Unit if [ "${temp_unit}" = "C" ]; then From b1784466968c75567e4df44afb6bdf98214b05aa Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 24 May 2023 20:41:48 +0200 Subject: [PATCH 24/81] Show a running PADD as "PADD v4.0.0" instead of "curl/7.81.0" on the web interface Signed-off-by: DL6ER --- padd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/padd.sh b/padd.sh index e732cd3d..17eed201 100755 --- a/padd.sh +++ b/padd.sh @@ -185,7 +185,7 @@ ChallengeResponse() { # Send response & get session response challenge="$(curl --silent -X GET "http://${URL}:${PORT}/${APIPATH}/auth" | jq --raw-output .challenge 2>/dev/null)" response="$(printf "%b" "${challenge}:${pwhash}" | sha256sum | sed 's/\s.*$//')" - sessionResponse="$(curl --silent -X POST "http://${URL}:${PORT}/${APIPATH}/auth" --data "{\"response\":\"${response}\"}" )" + sessionResponse="$(curl --silent -X POST "http://${URL}:${PORT}/${APIPATH}/auth" --user-agent "PADD ${padd_version}" --data "{\"response\":\"${response}\"}" )" if [ -z "${sessionResponse}" ]; then moveXOffset; echo "No response from FTL server. Please check connectivity and use the options to set the API URL" From 716897b8ed1a0e8768e4ca48fd6e7d9cb7bda0a6 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Tue, 30 May 2023 21:25:37 +0200 Subject: [PATCH 25/81] Switch to the proven memory-hard password-hashing alogorithm BALLOON Signed-off-by: DL6ER --- padd.sh | 44 +++++++++++++++----------------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/padd.sh b/padd.sh index e83b16fb..9b28ea03 100755 --- a/padd.sh +++ b/padd.sh @@ -118,7 +118,7 @@ TestAPIAvailability() { availabilityResonse=$(curl -s -o /dev/null -w "%{http_code}" "http://${URL}:${PORT}/${APIPATH}/auth") # test if http status code was 200 (OK) - if [ "${availabilityResonse}" = 200 ]; then + if [ "${availabilityResonse}" = 200 ] || [ "${availabilityResonse}" = 401 ]; then moveXOffset; printf "%b" "API available at: http://${URL}:${PORT}/${APIPATH}\n" else moveXOffset; echo "API not available at: http://${URL}:${PORT}/${APIPATH}" @@ -129,7 +129,7 @@ TestAPIAvailability() { Authenthication() { # Try to authenticate - ChallengeResponse + LoginAPI while [ "${validSession}" = false ] || [ -z "${validSession}" ] ; do moveXOffset; echo "Authentication failed." @@ -145,7 +145,7 @@ Authenthication() { moveXOffset; secretRead; printf '\n' # Try to authenticate again - ChallengeResponse + LoginAPI done # Loop exited, authentication was successful @@ -170,22 +170,8 @@ DeleteSession() { } -ChallengeResponse() { - # Challenge-response authentication - local response - - # Compute password hash from user password - # Compute password hash twice to avoid rainbow table vulnerability - hash1=$(printf "%b" "$password" | sha256sum | sed 's/\s.*$//') - pwhash=$(printf "%b" "$hash1" | sha256sum | sed 's/\s.*$//') - - - # Get challenge from FTL - # Calculate response based on challenge and password hash - # Send response & get session response - challenge="$(curl --silent -X GET "http://${URL}:${PORT}/${APIPATH}/auth" | jq --raw-output .challenge 2>/dev/null)" - response="$(printf "%b" "${challenge}:${pwhash}" | sha256sum | sed 's/\s.*$//')" - sessionResponse="$(curl --silent -X POST "http://${URL}:${PORT}/${APIPATH}/auth" --user-agent "PADD ${padd_version}" --data "{\"response\":\"${response}\"}" )" +LoginAPI() { + sessionResponse="$(curl --silent -X POST "http://${URL}:${PORT}/${APIPATH}/auth" --user-agent "PADD ${padd_version}" --data "{\"password\":\"${password}\"}" )" if [ -z "${sessionResponse}" ]; then moveXOffset; echo "No response from FTL server. Please check connectivity and use the options to set the API URL" @@ -374,11 +360,11 @@ GetNetworkInformation() { fi # Is Pi-Hole acting as the DHCP server? - DHCP_ACTIVE="$(echo "${config}" | jq .config.dnsmasq.dhcp.active 2>/dev/null )" + DHCP_ACTIVE="$(echo "${config}" | jq .config.dns.dhcp.active 2>/dev/null )" if [ "${DHCP_ACTIVE}" = "true" ]; then - DHCP_START="$(echo "${config}" | jq --raw-output .config.dnsmasq.dhcp.start 2>/dev/null)" - DHCP_END="$(echo "${config}" | jq --raw-output .config.dnsmasq.dhcp.end 2>/dev/null)" + DHCP_START="$(echo "${config}" | jq --raw-output .config.dns.dhcp.start 2>/dev/null)" + DHCP_END="$(echo "${config}" | jq --raw-output .config.dns.dhcp.end 2>/dev/null)" dhcp_status="Enabled" dhcp_info=" Range: ${DHCP_START} - ${DHCP_END}" @@ -386,7 +372,7 @@ GetNetworkInformation() { dhcp_check_box=${check_box_good} # Is DHCP handling IPv6? - DHCP_IPv6="$(echo "${config}" | jq --raw-output .config.dnsmasq.dhcp.ipv6 2>/dev/null)" + DHCP_IPv6="$(echo "${config}" | jq --raw-output .config.dns.dhcp.ipv6 2>/dev/null)" if [ "${DHCP_IPv6}" = "true" ]; then dhcp_ipv6_status="Enabled" dhcp_ipv6_heatmap=${green_text} @@ -413,7 +399,7 @@ GetNetworkInformation() { full_hostname=${pi_hostname} # when PI-hole is the DHCP server, append the domain to the hostname if [ "${DHCP_ACTIVE}" = "true" ]; then - PIHOLE_DOMAIN="$(echo "${config}" | jq --raw-output .config.dnsmasq.domain 2>/dev/null)" + PIHOLE_DOMAIN="$(echo "${config}" | jq --raw-output .config.dns.domain 2>/dev/null)" if [ -n "${PIHOLE_DOMAIN}" ]; then count=${pi_hostname}"."${PIHOLE_DOMAIN} count=${#count} @@ -424,7 +410,7 @@ GetNetworkInformation() { fi # Get the number of configured upstream DNS servers - dns_count="$(echo "${config}" | jq --raw-output .config.dnsmasq.upstreams[] 2>/dev/null | sed '/^\s*$/d' | wc -l)" + dns_count="$(echo "${config}" | jq --raw-output .config.dns.upstreams[] 2>/dev/null | sed '/^\s*$/d' | wc -l)" # if there's only one DNS server if [ "${dns_count}" -eq 1 ]; then dns_information="1 server" @@ -434,7 +420,7 @@ GetNetworkInformation() { # DNSSEC - DNSSEC="$(echo "${config}" | jq .config.dnsmasq.dnssec 2>/dev/null)" + DNSSEC="$(echo "${config}" | jq .config.dns.dnssec 2>/dev/null)" if [ "${DNSSEC}" = "true" ]; then dnssec_status="Enabled" dnssec_heatmap=${green_text} @@ -444,7 +430,7 @@ GetNetworkInformation() { fi # Conditional forwarding - CONDITIONAL_FORWARDING="$(echo "${config}" | jq .config.dnsmasq.rev_server.active 2>/dev/null)" + CONDITIONAL_FORWARDING="$(echo "${config}" | jq .config.dns.rev_server.active 2>/dev/null)" if [ "${CONDITIONAL_FORWARDING}" = "true" ]; then conditional_forwarding_status="Enabled" conditional_forwarding_heatmap=${green_text} @@ -487,7 +473,7 @@ GetPiholeInformation() { ftl_cpu="$(printf "%.1f" "${ftl_cpu_raw}")%" ftl_mem_percentage="$(printf "%.1f" "${ftl_mem_percentage_raw}")%" # Get Pi-hole (blocking) status - ftl_dns_port=$(GetFTLData "/config" | jq .config.dnsmasq.port 2>/dev/null) + ftl_dns_port=$(GetFTLData "/config" | jq .config.dns.port 2>/dev/null) # Get FTL's current PID ftlPID="$(echo "${sysinfo}" | jq .ftl.pid 2>/dev/null)" fi @@ -1495,7 +1481,7 @@ NormalPADD() { # as $password should be set already, PADD should automatically re-authenticate authenthication_required=$(GetFTLData "/info/ftl") if [ "${authenthication_required}" = 401 ]; then - ChallengeResponse + LoginAPI fi # Get uptime, CPU load, temp, etc. every 5 seconds From 57b102c909ef61c43d558ddf10f461a8a8219d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 31 Jul 2023 23:00:12 +0200 Subject: [PATCH 26/81] Change default API port to 80 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/padd.sh b/padd.sh index a9bdc66d..78e81fbf 100755 --- a/padd.sh +++ b/padd.sh @@ -106,7 +106,7 @@ ConstructAPI() { URL=127.0.0.1 fi if [ -z "${PORT}" ]; then - PORT=8080 + PORT=80 fi if [ -z "${APIPATH}" ]; then APIPATH=api @@ -1583,7 +1583,7 @@ DisplayHelp() { ::: -yoff [num] set the y-offset, reference is the upper left corner, disables auto-centering ::: ::: --server url or address of your Pi-hole (default: 127.0.0.1) -::: --port port of your Pi-hole's API (default: 8080) +::: --port port of your Pi-hole's API (default: 80) ::: --api path where your Pi-hole's API is hosted (default: api) ::: --secret your Pi-hole's password, required to access the API ::: -j, --json output stats as JSON formatted string and exit and exit From 36257d1deb9c416472d6c198312300c45f06a602 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Mon, 31 Jul 2023 18:46:56 -0300 Subject: [PATCH 27/81] Add on the help text the missing dash for xoff and yoff options Signed-off-by: RD WebDesign --- padd.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/padd.sh b/padd.sh index 78e81fbf..d1490f9f 100755 --- a/padd.sh +++ b/padd.sh @@ -1579,8 +1579,8 @@ DisplayHelp() { ::: ::: ::: Options: -::: -xoff [num] set the x-offset, reference is the upper left corner, disables auto-centering -::: -yoff [num] set the y-offset, reference is the upper left corner, disables auto-centering +::: --xoff [num] set the x-offset, reference is the upper left corner, disables auto-centering +::: --yoff [num] set the y-offset, reference is the upper left corner, disables auto-centering ::: ::: --server url or address of your Pi-hole (default: 127.0.0.1) ::: --port port of your Pi-hole's API (default: 80) From 794d7b0459360a3e3c4cf308727786e0c225011c Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Mon, 31 Jul 2023 19:09:16 -0300 Subject: [PATCH 28/81] Fix spellcheck and a few spaces Signed-off-by: RD WebDesign --- padd.sh | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/padd.sh b/padd.sh index d1490f9f..ef456602 100755 --- a/padd.sh +++ b/padd.sh @@ -157,7 +157,7 @@ DeleteSession() { # if a valid Session exists (no password required or successful authenthication) and # SID is not null (successful authenthication only), delete the session if [ "${validSession}" = true ] && [ ! "${SID}" = null ]; then - # Try to delte the session. Omitt the output, but get the http status code + # Try to delete the session. Omit the output, but get the http status code deleteResponse=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE "http://${URL}:${PORT}/${APIPATH}/auth" -H "Accept: application/json" -H "sid: ${SID}") printf "\n\n" @@ -190,7 +190,7 @@ GetFTLData() { # status are the last 3 characters status=$(printf %s "${response#"${response%???}"}") - # data is everything from repsonse without the last 3 characters + # data is everything from response without the last 3 characters data=$(printf %s "${response%???}") if [ "${status}" = 200 ]; then @@ -1214,8 +1214,8 @@ truncateString() { fi } -# Converts seconds to days, hours, minuts -#https://unix.stackexchange.com/a/338844 +# Converts seconds to days, hours, minutes +# https://unix.stackexchange.com/a/338844 convertUptime() { # shellcheck disable=SC2016 eval "echo $(date -ud "@$1" +'$((%s/3600/24)) days, %H hours, %M minutes')" @@ -1233,12 +1233,12 @@ secretRead() { # This workaround changes the terminal characteristics to not echo input and later rests this option # credits https://stackoverflow.com/a/4316765 - # showing astrix instead of password + # showing asterisk instead of password # https://stackoverflow.com/a/24600839 # https://unix.stackexchange.com/a/464963 stty -echo # do not echo user input - stty -icanon min 1 time 0 # disable cannonical mode https://man7.org/linux/man-pages/man3/termios.3.html + stty -icanon min 1 time 0 # disable canonical mode https://man7.org/linux/man-pages/man3/termios.3.html unset password unset key @@ -1283,7 +1283,7 @@ OutputJSON() { # Construct FTL's API address depending on the arguments supplied ConstructAPI - # Test if the authentication endpoint is availabe + # Test if the authentication endpoint is available TestAPIAvailability # Authenticate with the FTL server printf "%b" "Establishing connection with FTL...\n" @@ -1307,7 +1307,7 @@ ShowVersion() { # Construct FTL's API address depending on the arguments supplied ConstructAPI - # Test if the authentication endpoint is availabe + # Test if the authentication endpoint is available TestAPIAvailability # Authenticate with the FTL server printf "%b" "Establishing connection with FTL...\n" @@ -1343,7 +1343,7 @@ StartupRoutine(){ moveXOffset; PrintLogo "$1" moveXOffset; printf "%b" "START-UP ===========\n" - # Test if the authentication endpoint is availabe + # Test if the authentication endpoint is available TestAPIAvailability # Authenticate with the FTL server @@ -1376,7 +1376,7 @@ StartupRoutine(){ elif [ "$1" = "mini" ]; then moveXOffset; PrintLogo "$1" moveXOffset; echo "START UP =====================" - # Test if the authentication endpoint is availabe + # Test if the authentication endpoint is available TestAPIAvailability # Authenticate with the FTL server moveXOffset; printf "%b" "Establishing connection with FTL...\n" @@ -1410,7 +1410,7 @@ StartupRoutine(){ moveXOffset; echo "START UP ===================================================" fi - # Test if the authentication endpoint is availabe + # Test if the authentication endpoint is available TestAPIAvailability # Authenticate with the FTL server @@ -1615,7 +1615,7 @@ CleanExit() { # reset trap for all signals to not interrupt clean_tempfiles() on any next signal trap '' EXIT INT QUIT TERM - # restore terminal settings if they have been changed (e.g. user cancled script while at password input prompt) + # restore terminal settings if they have been changed (e.g. user canceled script while at password input prompt) if [ "$(stty -g)" != "${stty_orig}" ]; then stty "${stty_orig}" fi From 4a69af0dd201cb87dff77c23cde38e6c6eebce00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 2 Aug 2023 21:31:02 +0200 Subject: [PATCH 29/81] When running locally derive port from FTL itself MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/padd.sh b/padd.sh index 78e81fbf..58a2d4eb 100755 --- a/padd.sh +++ b/padd.sh @@ -104,6 +104,9 @@ ConstructAPI() { # If no arguments were supplied set them to default if [ -z "${URL}" ]; then URL=127.0.0.1 + # when no $URL is set we assume PADD is running locally and we can get the port value from FTL directly + PORT="$(pihole-FTL --config webserver.port)" + PORT="${PORT%%,*}" fi if [ -z "${PORT}" ]; then PORT=80 @@ -1231,7 +1234,7 @@ secretRead() { # `-n` option (reading n chars) - # This workaround changes the terminal characteristics to not echo input and later rests this option + # This workaround changes the terminal characteristics to not echo input and later resets this option # credits https://stackoverflow.com/a/4316765 # showing astrix instead of password # https://stackoverflow.com/a/24600839 From b67b0fb2e0db69e53db1773b8b2115baa9d4e0d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 2 Aug 2023 21:44:01 +0200 Subject: [PATCH 30/81] Remove space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/padd.sh b/padd.sh index 58a2d4eb..fcdecc9c 100755 --- a/padd.sh +++ b/padd.sh @@ -105,7 +105,7 @@ ConstructAPI() { if [ -z "${URL}" ]; then URL=127.0.0.1 # when no $URL is set we assume PADD is running locally and we can get the port value from FTL directly - PORT="$(pihole-FTL --config webserver.port)" + PORT="$(pihole-FTL --config webserver.port)" PORT="${PORT%%,*}" fi if [ -z "${PORT}" ]; then From 13dbce323fa97144f9ab49ad0beeb1d85dba3c27 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 21 Oct 2023 10:42:23 +0000 Subject: [PATCH 31/81] Bump actions/checkout from 4.1.0 to 4.1.1 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.0...v4.1.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codespell.yml | 2 +- .github/workflows/editorconfig-checker.yml | 2 +- .github/workflows/stale.yml | 2 +- .github/workflows/sync-back-to-dev.yml | 2 +- .github/workflows/version_bump.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 8f5f6aac..cbd7f851 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Spell-Checking uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/editorconfig-checker.yml b/.github/workflows/editorconfig-checker.yml index 9eff6db2..807dc02a 100644 --- a/.github/workflows/editorconfig-checker.yml +++ b/.github/workflows/editorconfig-checker.yml @@ -9,6 +9,6 @@ jobs: name: editorconfig-checker runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 - uses: editorconfig-checker/action-editorconfig-checker@main # current tag v1.0.0 is really out-of-date - run: editorconfig-checker diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 5535c562..f0b40854 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Remove 'stale' label run: gh issue edit ${{ github.event.issue.number }} --remove-label ${{ env.stale_label }} env: diff --git a/.github/workflows/sync-back-to-dev.yml b/.github/workflows/sync-back-to-dev.yml index 6d59401f..3d8b7c50 100644 --- a/.github/workflows/sync-back-to-dev.yml +++ b/.github/workflows/sync-back-to-dev.yml @@ -11,7 +11,7 @@ jobs: name: Syncing branches steps: - name: Checkout - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Opening pull request run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'Internal' env: diff --git a/.github/workflows/version_bump.yml b/.github/workflows/version_bump.yml index 9d1d893f..e0f95ee5 100644 --- a/.github/workflows/version_bump.yml +++ b/.github/workflows/version_bump.yml @@ -19,7 +19,7 @@ jobs: echo "latest_tag=$LATEST_TAG" >> $GITHUB_ENV - name: Checkout code - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 with: ref: 'development' From 9aee13872da35178bf0d110d6ae206d69de85361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sat, 2 Dec 2023 21:53:58 +0100 Subject: [PATCH 32/81] Use CHAOS TXT to connect to FTL's API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 95 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/padd.sh b/padd.sh index 4d697198..3f7e9de3 100755 --- a/padd.sh +++ b/padd.sh @@ -100,32 +100,63 @@ padd_logo_retro_3="${bold_text}${green_text}| ${red_text}/${yellow_text}-${gre ############################################# FTL ################################################## -ConstructAPI() { - # If no arguments were supplied set them to default - if [ -z "${URL}" ]; then - URL=127.0.0.1 - # when no $URL is set we assume PADD is running locally and we can get the port value from FTL directly - PORT="$(pihole-FTL --config webserver.port)" - PORT="${PORT%%,*}" - fi - if [ -z "${PORT}" ]; then - PORT=80 - fi - if [ -z "${APIPATH}" ]; then - APIPATH=api - fi -} - TestAPIAvailability() { - availabilityResonse=$(curl -s -o /dev/null -w "%{http_code}" "http://${URL}:${PORT}/${APIPATH}/auth") + local chaos_api_list availabilityResonse - # test if http status code was 200 (OK) - if [ "${availabilityResonse}" = 200 ] || [ "${availabilityResonse}" = 401 ]; then - moveXOffset; printf "%b" "API available at: http://${URL}:${PORT}/${APIPATH}\n" + # Query the API URLs from FTL using CHAOS TXT + # The result is a space-separated enumeration of full URLs + # e.g., "http://localhost:80/api" or "https://domain.com:443/api" + if [ -z "${SERVER}" ]; then + # --server was not set, assuming we're running locally + chaos_api_list="$(dig +short chaos txt local.api.ftl @localhost)" else - moveXOffset; echo "API not available at: http://${URL}:${PORT}/${APIPATH}" - moveXOffset; echo "Exiting." + # --server was set, try to get response from there + chaos_api_list="$(dig +short chaos txt domain.api.ftl @"${SERVER}")" + fi + + # If the query was not successful, the variable is empty + if [ -z "${chaos_api_list}" ]; then + echo "API not available. Please check connectivity" + exit 1 + fi + + # Iterate over space-separated list of URLs + while [ -n "${chaos_api_list}" ]; do + # Get the first URL + API_URL="${chaos_api_list%% *}" + # Strip leading and trailing quotes + API_URL="${API_URL%\"}" + API_URL="${API_URL#\"}" + + # Test if the API is available at this URL + availabilityResonse=$(curl -skS -o /dev/null -w "%{http_code}" "${API_URL}auth") + + # Test if http status code was 200 (OK) or 401 (authentication required) + if [ ! "${availabilityResonse}" = 200 ] && [ ! "${availabilityResonse}" = 401 ]; then + # API is not available at this port/protocol combination + API_PORT="" + else + # API is available at this URL combination + break + fi + + # Remove the first URL from the list + local last_api_list + last_api_list="${chaos_api_list}" + chaos_api_list="${chaos_api_list#* }" + + # If the list did not change, we are at the last element + if [ "${last_api_list}" = "${chaos_api_list}" ]; then + # Remove the last element + chaos_api_list="" + fi + done + + # if API_PORT is empty, no working API port was found + if [ -n "${API_PORT}" ]; then + echo "API not available at: ${API_URL}" + echo "Exiting." exit 1 fi } @@ -161,7 +192,7 @@ DeleteSession() { # SID is not null (successful authenthication only), delete the session if [ "${validSession}" = true ] && [ ! "${SID}" = null ]; then # Try to delete the session. Omit the output, but get the http status code - deleteResponse=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE "http://${URL}:${PORT}/${APIPATH}/auth" -H "Accept: application/json" -H "sid: ${SID}") + deleteResponse=$(curl -skS -o /dev/null -w "%{http_code}" -X DELETE "${API_URL}/auth" -H "Accept: application/json" -H "sid: ${SID}") printf "\n\n" case "${deleteResponse}" in @@ -174,7 +205,7 @@ DeleteSession() { } LoginAPI() { - sessionResponse="$(curl --silent -X POST "http://${URL}:${PORT}/${APIPATH}/auth" --user-agent "PADD ${padd_version}" --data "{\"password\":\"${password}\"}" )" + sessionResponse="$(curl -skS -X POST "${API_URL}/auth" --user-agent "PADD ${padd_version}" --data "{\"password\":\"${password}\"}" )" if [ -z "${sessionResponse}" ]; then moveXOffset; echo "No response from FTL server. Please check connectivity and use the options to set the API URL" @@ -189,7 +220,7 @@ LoginAPI() { GetFTLData() { local response # get the data from querying the API as well as the http status code - response=$(curl -s -w "%{http_code}" -X GET "http://${URL}:${PORT}/${APIPATH}$1" -H "Accept: application/json" -H "sid: ${SID}" ) + response=$(curl -skS -w "%{http_code}" -X GET "${API_URL}$1" -H "Accept: application/json" -H "sid: ${SID}" ) # status are the last 3 characters status=$(printf %s "${response#"${response%???}"}") @@ -1284,8 +1315,6 @@ OutputJSON() { # Save current terminal settings (needed for later restore after password prompt) stty_orig=$(stty -g) - # Construct FTL's API address depending on the arguments supplied - ConstructAPI # Test if the authentication endpoint is available TestAPIAvailability # Authenticate with the FTL server @@ -1308,8 +1337,6 @@ ShowVersion() { # Save current terminal settings (needed for later restore after password prompt) stty_orig=$(stty -g) - # Construct FTL's API address depending on the arguments supplied - ConstructAPI # Test if the authentication endpoint is available TestAPIAvailability # Authenticate with the FTL server @@ -1585,9 +1612,7 @@ DisplayHelp() { ::: --xoff [num] set the x-offset, reference is the upper left corner, disables auto-centering ::: --yoff [num] set the y-offset, reference is the upper left corner, disables auto-centering ::: -::: --server url or address of your Pi-hole (default: 127.0.0.1) -::: --port port of your Pi-hole's API (default: 80) -::: --api path where your Pi-hole's API is hosted (default: api) +::: --server domain or IP of your Pi-hole (default: localhost) ::: --secret your Pi-hole's password, required to access the API ::: -j, --json output stats as JSON formatted string and exit and exit ::: -u, --update update to the latest version @@ -1666,8 +1691,6 @@ main(){ # Save current terminal settings (needed for later restore after password prompt) stty_orig=$(stty -g) - # Construct FTL's API address depending on the arguments supplied - ConstructAPI SizeChecker @@ -1686,9 +1709,7 @@ while [ "$#" -gt 0 ]; do "-v" | "--version" ) xOffset=0; ShowVersion; exit 0;; "--xoff" ) xOffset="$2"; xOffOrig="$2"; shift;; "--yoff" ) yOffset="$2"; yOffOrig="$2"; shift;; - "--server" ) URL="$2"; shift;; - "--port" ) PORT="$2"; shift;; - "--api" ) APIPATH="$2"; shift;; + "--server" ) SERVER="$2"; shift;; "--secret" ) password="$2"; shift;; * ) DisplayHelp; exit 1;; esac From 1b243f4a2d018150c977fa8800cd3fe28b7dd01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sat, 2 Dec 2023 22:09:00 +0100 Subject: [PATCH 33/81] Adjust endpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/padd.sh b/padd.sh index 3f7e9de3..10346619 100755 --- a/padd.sh +++ b/padd.sh @@ -192,7 +192,7 @@ DeleteSession() { # SID is not null (successful authenthication only), delete the session if [ "${validSession}" = true ] && [ ! "${SID}" = null ]; then # Try to delete the session. Omit the output, but get the http status code - deleteResponse=$(curl -skS -o /dev/null -w "%{http_code}" -X DELETE "${API_URL}/auth" -H "Accept: application/json" -H "sid: ${SID}") + deleteResponse=$(curl -skS -o /dev/null -w "%{http_code}" -X DELETE "${API_URL}auth" -H "Accept: application/json" -H "sid: ${SID}") printf "\n\n" case "${deleteResponse}" in @@ -205,11 +205,11 @@ DeleteSession() { } LoginAPI() { - sessionResponse="$(curl -skS -X POST "${API_URL}/auth" --user-agent "PADD ${padd_version}" --data "{\"password\":\"${password}\"}" )" + sessionResponse="$(curl -skS -X POST "${API_URL}auth" --user-agent "PADD ${padd_version}" --data "{\"password\":\"${password}\"}" )" if [ -z "${sessionResponse}" ]; then moveXOffset; echo "No response from FTL server. Please check connectivity and use the options to set the API URL" - moveXOffset; echo "Usage: $0 [-u ] [-p ] [-a ] " + moveXOffset; echo "Usage: $0 [--server ]" exit 1 fi # obtain validity and session ID from session response @@ -242,10 +242,10 @@ GetFTLData() { ############################################# GETTERS ############################################## GetSummaryInformation() { - summary=$(GetFTLData "/stats/summary") - cache_info=$(GetFTLData "/info/metrics") - ftl_info=$(GetFTLData "/info/ftl") - dns_blocking=$(GetFTLData "/dns/blocking") + summary=$(GetFTLData "stats/summary") + cache_info=$(GetFTLData "info/metrics") + ftl_info=$(GetFTLData "info/ftl") + dns_blocking=$(GetFTLData "dns/blocking") clients=$(echo "${ftl_info}" | jq .ftl.clients.active 2>/dev/null) @@ -267,21 +267,21 @@ GetSummaryInformation() { cache_evictions=$(echo "$cache_info" | jq .metrics.dns.cache.evicted 2>/dev/null) cache_inserts=$(echo "$cache_info"| jq .metrics.dns.cache.inserted 2>/dev/null) - latest_blocked_raw=$(GetFTLData "/stats/recent_blocked?show=1" | jq --raw-output .blocked[0] 2>/dev/null) + latest_blocked_raw=$(GetFTLData "stats/recent_blocked?show=1" | jq --raw-output .blocked[0] 2>/dev/null) - top_blocked_raw=$(GetFTLData "/stats/top_domains?blocked=true" | jq --raw-output .domains[0].domain 2>/dev/null) + top_blocked_raw=$(GetFTLData "stats/top_domains?blocked=true" | jq --raw-output .domains[0].domain 2>/dev/null) - top_domain_raw=$(GetFTLData "/stats/top_domains" | jq --raw-output .domains[0].domain 2>/dev/null) + top_domain_raw=$(GetFTLData "stats/top_domains" | jq --raw-output .domains[0].domain 2>/dev/null) - top_client_raw=$(GetFTLData "/stats/top_clients" | jq --raw-output .clients[0].name 2>/dev/null) + top_client_raw=$(GetFTLData "stats/top_clients" | jq --raw-output .clients[0].name 2>/dev/null) if [ -z "${top_client_raw}" ]; then # if no hostname was supplied, use IP - top_client_raw=$(GetFTLData "/stats/top_clients" | jq --raw-output .clients[0].ip 2>/dev/null) + top_client_raw=$(GetFTLData "stats/top_clients" | jq --raw-output .clients[0].ip 2>/dev/null) fi } GetSystemInformation() { - sysinfo=$(GetFTLData "/info/system") + sysinfo=$(GetFTLData "info/system") # System uptime if [ "${sysinfo}" = 000 ]; then @@ -293,9 +293,9 @@ GetSystemInformation() { # CPU temperature and unit # in case .sensors.cpu_temp returns 'null' we substitute with 0 - cpu_temp_raw=$(GetFTLData "/info/sensors" | jq '(.sensors.cpu_temp // 0)' 2>/dev/null) + cpu_temp_raw=$(GetFTLData "info/sensors" | jq '(.sensors.cpu_temp // 0)' 2>/dev/null) cpu_temp=$(printf "%.1f" "${cpu_temp_raw}") - temp_unit=$(GetFTLData "/info/sensors" | jq --raw-output .sensors.unit 2>/dev/null) + temp_unit=$(GetFTLData "info/sensors" | jq --raw-output .sensors.unit 2>/dev/null) # Temp + Unit if [ "${temp_unit}" = "C" ]; then @@ -344,7 +344,7 @@ GetSystemInformation() { memory_heatmap="$(HeatmapGenerator "${memory_percent}")" # Get device model - sys_model="$(GetFTLData "/info/host" | jq --raw-output .host.model 2>/dev/null)" + sys_model="$(GetFTLData "info/host" | jq --raw-output .host.model 2>/dev/null)" # DOCKER_VERSION is set during GetVersionInformation, so this needs to run first during startup if [ ! "${DOCKER_VERSION}" = "null" ]; then @@ -361,8 +361,8 @@ GetSystemInformation() { } GetNetworkInformation() { - interfaces_raw=$(GetFTLData "/network/interfaces") - config=$(GetFTLData "/config") + interfaces_raw=$(GetFTLData "network/interfaces") + config=$(GetFTLData "config") # Get pi IPv4 address of the default interface pi_ip4_addrs="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv4[]' 2>/dev/null | wc -w)" @@ -421,7 +421,7 @@ GetNetworkInformation() { dhcp_heatmap=${red_text} dhcp_check_box=${check_box_bad} - GATEWAY="$(GetFTLData "/network/gateway" | jq --raw-output .address 2>/dev/null)" + GATEWAY="$(GetFTLData "network/gateway" | jq --raw-output .address 2>/dev/null)" dhcp_info=" Router: ${GATEWAY}" dhcp_ipv6_status="N/A" dhcp_ipv6_heatmap=${yellow_text} @@ -429,7 +429,7 @@ GetNetworkInformation() { fi # Get hostname - pi_hostname="$(GetFTLData "/info/host" | jq --raw-output .host.uname.nodename 2>/dev/null)" + pi_hostname="$(GetFTLData "info/host" | jq --raw-output .host.uname.nodename 2>/dev/null)" full_hostname=${pi_hostname} # when PI-hole is the DHCP server, append the domain to the hostname if [ "${DHCP_ACTIVE}" = "true" ]; then @@ -485,7 +485,7 @@ GetNetworkInformation() { } GetPiholeInformation() { - sysinfo=$(GetFTLData "/info/ftl") + sysinfo=$(GetFTLData "info/ftl") # If FTL is not running (sysinfo is 000), set all variables to "not running" connection_down_flag=false @@ -507,7 +507,7 @@ GetPiholeInformation() { ftl_cpu="$(printf "%.1f" "${ftl_cpu_raw}")%" ftl_mem_percentage="$(printf "%.1f" "${ftl_mem_percentage_raw}")%" # Get Pi-hole (blocking) status - ftl_dns_port=$(GetFTLData "/config" | jq .config.dns.port 2>/dev/null) + ftl_dns_port=$(GetFTLData "config" | jq .config.dns.port 2>/dev/null) # Get FTL's current PID ftlPID="$(echo "${sysinfo}" | jq .ftl.pid 2>/dev/null)" fi @@ -532,7 +532,7 @@ fi GetVersionInformation() { out_of_date_flag=false - versions_raw=$(GetFTLData "/info/version") + versions_raw=$(GetFTLData "info/version") # Gather DOCKER version information... # returns "null" if not running Pi-hole in Docker container @@ -1512,7 +1512,7 @@ NormalPADD() { # check if a new authentication is required (e.g. after connection to FTL has re-established) # GetFTLData() will return a 401 if a 401 http status code is returned # as $password should be set already, PADD should automatically re-authenticate - authenthication_required=$(GetFTLData "/info/ftl") + authenthication_required=$(GetFTLData "info/ftl") if [ "${authenthication_required}" = 401 ]; then LoginAPI fi From a41dcd0bb7365a0f007088246c0d604524cdc6a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 5 Dec 2023 22:19:13 +0100 Subject: [PATCH 34/81] Cover --server localhost case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/padd.sh b/padd.sh index 10346619..50877921 100755 --- a/padd.sh +++ b/padd.sh @@ -107,7 +107,7 @@ TestAPIAvailability() { # Query the API URLs from FTL using CHAOS TXT # The result is a space-separated enumeration of full URLs # e.g., "http://localhost:80/api" or "https://domain.com:443/api" - if [ -z "${SERVER}" ]; then + if [ -z "${SERVER}" ] || [ "${SERVER}" = "localhost" ] || [ "${SERVER}" = "127.0.0.1" ]; then # --server was not set, assuming we're running locally chaos_api_list="$(dig +short chaos txt local.api.ftl @localhost)" else From 266a711e192f6b5eb0b783cf95984590d8096279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 5 Dec 2023 23:21:36 +0100 Subject: [PATCH 35/81] Improve error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/padd.sh b/padd.sh index 50877921..d629b782 100755 --- a/padd.sh +++ b/padd.sh @@ -102,23 +102,30 @@ padd_logo_retro_3="${bold_text}${green_text}| ${red_text}/${yellow_text}-${gre TestAPIAvailability() { - local chaos_api_list availabilityResonse + local chaos_api_list availabilityResonse cmdResult digReturnCode # Query the API URLs from FTL using CHAOS TXT # The result is a space-separated enumeration of full URLs # e.g., "http://localhost:80/api" or "https://domain.com:443/api" if [ -z "${SERVER}" ] || [ "${SERVER}" = "localhost" ] || [ "${SERVER}" = "127.0.0.1" ]; then - # --server was not set, assuming we're running locally - chaos_api_list="$(dig +short chaos txt local.api.ftl @localhost)" + # --server was not set or set to local, assuming we're running locally + cmdResult="$(dig +short chaos txt local.api.ftl @localhost 2>&1; echo $?)" else # --server was set, try to get response from there - chaos_api_list="$(dig +short chaos txt domain.api.ftl @"${SERVER}")" + cmdResult="$(dig +short chaos txt domain.api.ftl @"${SERVER}" 2>&1; echo $?)" fi - # If the query was not successful, the variable is empty - if [ -z "${chaos_api_list}" ]; then - echo "API not available. Please check connectivity" + # Gets the return code of the dig command (last line) + # We can't use${cmdResult##*$'\n'*} here as $'..' is not POSIX + digReturnCode="$(echo "${cmdResult}" | tail -n 1)" + + if [ ! "${digReturnCode}" = "0" ]; then + # If the query was not successful + echo "API not available. Please check server address and connectivity" exit 1 + else + # Dig returned 0 (success), so get the actual response (first line) + chaos_api_list="$(echo "${cmdResult}" | head -n 1)" fi # Iterate over space-separated list of URLs From 552ece2a963b1caf13f62a6732e791dc6dbe7365 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 Dec 2023 10:35:15 +0000 Subject: [PATCH 36/81] Bump actions/stale from 8.0.0 to 9.0.0 Bumps [actions/stale](https://github.com/actions/stale) from 8.0.0 to 9.0.0. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v8.0.0...v9.0.0) --- updated-dependencies: - dependency-name: actions/stale dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/stale.yml | 2 +- .github/workflows/stale_pr.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index f0b40854..a02ca802 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -17,7 +17,7 @@ jobs: issues: write steps: - - uses: actions/stale@v8.0.0 + - uses: actions/stale@v9.0.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 30 diff --git a/.github/workflows/stale_pr.yml b/.github/workflows/stale_pr.yml index 4a151100..171c9030 100644 --- a/.github/workflows/stale_pr.yml +++ b/.github/workflows/stale_pr.yml @@ -17,7 +17,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@v8.0.0 + - uses: actions/stale@v9.0.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} # Do not automatically mark PR/issue as stale From 353c0035d08edb026b21de0b1ec4db9d1dec0827 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 7 Jan 2024 10:06:18 +0100 Subject: [PATCH 37/81] The correct key is config.dns.revServer.active Signed-off-by: DL6ER --- padd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/padd.sh b/padd.sh index 4d697198..d8aedf33 100755 --- a/padd.sh +++ b/padd.sh @@ -433,7 +433,7 @@ GetNetworkInformation() { fi # Conditional forwarding - CONDITIONAL_FORWARDING="$(echo "${config}" | jq .config.dns.rev_server.active 2>/dev/null)" + CONDITIONAL_FORWARDING="$(echo "${config}" | jq .config.dns.revServer.active 2>/dev/null)" if [ "${CONDITIONAL_FORWARDING}" = "true" ]; then conditional_forwarding_status="Enabled" conditional_forwarding_heatmap=${green_text} From 2455fff66f8855772e6219cacc4a4cfa9f5cb76e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 7 Jan 2024 12:53:05 +0100 Subject: [PATCH 38/81] moveXOffset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/padd.sh b/padd.sh index d629b782..ecc9c8f7 100755 --- a/padd.sh +++ b/padd.sh @@ -121,7 +121,7 @@ TestAPIAvailability() { if [ ! "${digReturnCode}" = "0" ]; then # If the query was not successful - echo "API not available. Please check server address and connectivity" + moveXOffset; echo "API not available. Please check server address and connectivity" exit 1 else # Dig returned 0 (success), so get the actual response (first line) @@ -162,8 +162,8 @@ TestAPIAvailability() { # if API_PORT is empty, no working API port was found if [ -n "${API_PORT}" ]; then - echo "API not available at: ${API_URL}" - echo "Exiting." + moveXOffset; echo "API not available at: ${API_URL}" + moveXOffset; echo "Exiting." exit 1 fi } From ec305e66076ed2b422b8f71992e37e8947130a20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 7 Jan 2024 12:56:17 +0100 Subject: [PATCH 39/81] Return N/A in case FTL can't figure out the device model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/padd.sh b/padd.sh index ecc9c8f7..5da4c0a1 100755 --- a/padd.sh +++ b/padd.sh @@ -362,8 +362,9 @@ GetSystemInformation() { # Cleaning device model from useless OEM information sys_model=$(filterModel "${sys_model}") - if [ -z "$sys_model" ]; then - sys_model="Unknown" + # FTL returns null if device information is not available + if [ -z "$sys_model" ] || [ "$sys_model" = "null" ]; then + sys_model="N/A" fi } From ec5a26a705985bf754418573634b4d3b6927e403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 7 Jan 2024 13:32:09 +0100 Subject: [PATCH 40/81] Deleting a session successfully returns 204 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/padd.sh b/padd.sh index d8aedf33..cf8c1e8e 100755 --- a/padd.sh +++ b/padd.sh @@ -166,8 +166,8 @@ DeleteSession() { printf "\n\n" case "${deleteResponse}" in "200") moveXOffset; printf "%b" "A session that was not created cannot be deleted (e.g., empty API password).\n";; + "204") moveXOffset; printf "%b" "Session successfully deleted.\n";; "401") moveXOffset; printf "%b" "Logout attempt without a valid session. Unauthorized!\n";; - "410") moveXOffset; printf "%b" "Session successfully deleted.\n";; esac; fi @@ -1353,7 +1353,7 @@ StartupRoutine(){ moveXOffset; printf "%b" "Establishing connection with FTL...\n" Authenthication - printf "%b" "Starting PADD...\n" + moveXOffset; printf "%b" "Starting PADD...\n" moveXOffset; printf "%b" " [■·········] 10%\r" From 79ca42e2e7f7529a48ac90afdcba8f58daeb3f27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 7 Jan 2024 21:05:49 +0100 Subject: [PATCH 41/81] Status 200 is gone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/padd.sh b/padd.sh index cf8c1e8e..49d5801d 100755 --- a/padd.sh +++ b/padd.sh @@ -165,7 +165,6 @@ DeleteSession() { printf "\n\n" case "${deleteResponse}" in - "200") moveXOffset; printf "%b" "A session that was not created cannot be deleted (e.g., empty API password).\n";; "204") moveXOffset; printf "%b" "Session successfully deleted.\n";; "401") moveXOffset; printf "%b" "Logout attempt without a valid session. Unauthorized!\n";; esac; From d58149d5fa744515e72b235d8a5600648a76faa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 7 Jan 2024 22:03:54 +0100 Subject: [PATCH 42/81] Nicer output if no session needed to be deleted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- padd.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/padd.sh b/padd.sh index 49d5801d..1d20cdc1 100755 --- a/padd.sh +++ b/padd.sh @@ -168,6 +168,9 @@ DeleteSession() { "204") moveXOffset; printf "%b" "Session successfully deleted.\n";; "401") moveXOffset; printf "%b" "Logout attempt without a valid session. Unauthorized!\n";; esac; + else + # no session to delete, just print a newline for nicer output + echo fi } From 5f8d24fb2495d2515a3d492703bad09335797012 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 30 Mar 2024 10:10:21 +0000 Subject: [PATCH 43/81] Bump eps1lon/actions-label-merge-conflict from 2.1.0 to 3.0.0 Bumps [eps1lon/actions-label-merge-conflict](https://github.com/eps1lon/actions-label-merge-conflict) from 2.1.0 to 3.0.0. - [Release notes](https://github.com/eps1lon/actions-label-merge-conflict/releases) - [Changelog](https://github.com/eps1lon/actions-label-merge-conflict/blob/main/CHANGELOG.md) - [Commits](https://github.com/eps1lon/actions-label-merge-conflict/compare/v2.1.0...v3.0.0) --- updated-dependencies: - dependency-name: eps1lon/actions-label-merge-conflict dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/merge-conflict.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge-conflict.yml b/.github/workflows/merge-conflict.yml index 424a1c0e..89b03983 100644 --- a/.github/workflows/merge-conflict.yml +++ b/.github/workflows/merge-conflict.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check if PRs are have merge conflicts - uses: eps1lon/actions-label-merge-conflict@v2.1.0 + uses: eps1lon/actions-label-merge-conflict@v3.0.0 with: dirtyLabel: "Merge Conflict" repoToken: "${{ secrets.GITHUB_TOKEN }}" From 06c76ff746b5e307c6cb0bdc5d5e80351aa9c2d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 20 Apr 2024 10:31:36 +0000 Subject: [PATCH 44/81] Bump actions/checkout from 4.1.1 to 4.1.3 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.1...v4.1.3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codespell.yml | 2 +- .github/workflows/editorconfig-checker.yml | 2 +- .github/workflows/stale.yml | 2 +- .github/workflows/sync-back-to-dev.yml | 2 +- .github/workflows/version_bump.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index cbd7f851..e2f19e25 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.3 - name: Spell-Checking uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/editorconfig-checker.yml b/.github/workflows/editorconfig-checker.yml index 807dc02a..6d3237f0 100644 --- a/.github/workflows/editorconfig-checker.yml +++ b/.github/workflows/editorconfig-checker.yml @@ -9,6 +9,6 @@ jobs: name: editorconfig-checker runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.3 - uses: editorconfig-checker/action-editorconfig-checker@main # current tag v1.0.0 is really out-of-date - run: editorconfig-checker diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index a02ca802..d926fd0a 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.3 - name: Remove 'stale' label run: gh issue edit ${{ github.event.issue.number }} --remove-label ${{ env.stale_label }} env: diff --git a/.github/workflows/sync-back-to-dev.yml b/.github/workflows/sync-back-to-dev.yml index 3d8b7c50..1d740fba 100644 --- a/.github/workflows/sync-back-to-dev.yml +++ b/.github/workflows/sync-back-to-dev.yml @@ -11,7 +11,7 @@ jobs: name: Syncing branches steps: - name: Checkout - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.3 - name: Opening pull request run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'Internal' env: diff --git a/.github/workflows/version_bump.yml b/.github/workflows/version_bump.yml index e0f95ee5..75d60ba6 100644 --- a/.github/workflows/version_bump.yml +++ b/.github/workflows/version_bump.yml @@ -19,7 +19,7 @@ jobs: echo "latest_tag=$LATEST_TAG" >> $GITHUB_ENV - name: Checkout code - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.3 with: ref: 'development' From ae766fb76ef9906cd984d2f4c9c540b1317d64bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 27 Apr 2024 10:37:34 +0000 Subject: [PATCH 45/81] Bump actions/checkout from 4.1.3 to 4.1.4 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.3 to 4.1.4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.3...v4.1.4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codespell.yml | 2 +- .github/workflows/editorconfig-checker.yml | 2 +- .github/workflows/stale.yml | 2 +- .github/workflows/sync-back-to-dev.yml | 2 +- .github/workflows/version_bump.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index e2f19e25..5f3a9ada 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.3 + uses: actions/checkout@v4.1.4 - name: Spell-Checking uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/editorconfig-checker.yml b/.github/workflows/editorconfig-checker.yml index 6d3237f0..161e8a53 100644 --- a/.github/workflows/editorconfig-checker.yml +++ b/.github/workflows/editorconfig-checker.yml @@ -9,6 +9,6 @@ jobs: name: editorconfig-checker runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 - uses: editorconfig-checker/action-editorconfig-checker@main # current tag v1.0.0 is really out-of-date - run: editorconfig-checker diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index d926fd0a..bfab06d6 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.1.3 + uses: actions/checkout@v4.1.4 - name: Remove 'stale' label run: gh issue edit ${{ github.event.issue.number }} --remove-label ${{ env.stale_label }} env: diff --git a/.github/workflows/sync-back-to-dev.yml b/.github/workflows/sync-back-to-dev.yml index 1d740fba..2e1be7c4 100644 --- a/.github/workflows/sync-back-to-dev.yml +++ b/.github/workflows/sync-back-to-dev.yml @@ -11,7 +11,7 @@ jobs: name: Syncing branches steps: - name: Checkout - uses: actions/checkout@v4.1.3 + uses: actions/checkout@v4.1.4 - name: Opening pull request run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'Internal' env: diff --git a/.github/workflows/version_bump.yml b/.github/workflows/version_bump.yml index 75d60ba6..44f6ef1f 100644 --- a/.github/workflows/version_bump.yml +++ b/.github/workflows/version_bump.yml @@ -19,7 +19,7 @@ jobs: echo "latest_tag=$LATEST_TAG" >> $GITHUB_ENV - name: Checkout code - uses: actions/checkout@v4.1.3 + uses: actions/checkout@v4.1.4 with: ref: 'development' From b950a9947e12ae80c6ee9c4733edd6a58e4461c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 May 2024 10:38:30 +0000 Subject: [PATCH 46/81] Bump eps1lon/actions-label-merge-conflict from 3.0.0 to 3.0.1 Bumps [eps1lon/actions-label-merge-conflict](https://github.com/eps1lon/actions-label-merge-conflict) from 3.0.0 to 3.0.1. - [Release notes](https://github.com/eps1lon/actions-label-merge-conflict/releases) - [Changelog](https://github.com/eps1lon/actions-label-merge-conflict/blob/main/CHANGELOG.md) - [Commits](https://github.com/eps1lon/actions-label-merge-conflict/compare/v3.0.0...v3.0.1) --- updated-dependencies: - dependency-name: eps1lon/actions-label-merge-conflict dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/merge-conflict.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge-conflict.yml b/.github/workflows/merge-conflict.yml index 89b03983..857aef00 100644 --- a/.github/workflows/merge-conflict.yml +++ b/.github/workflows/merge-conflict.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check if PRs are have merge conflicts - uses: eps1lon/actions-label-merge-conflict@v3.0.0 + uses: eps1lon/actions-label-merge-conflict@v3.0.1 with: dirtyLabel: "Merge Conflict" repoToken: "${{ secrets.GITHUB_TOKEN }}" From 29ce0396cedc591da011d6c4dbc3ddfe0e575436 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 May 2024 12:24:34 +0000 Subject: [PATCH 47/81] Bump actions/checkout from 4.1.4 to 4.1.5 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.4 to 4.1.5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.4...v4.1.5) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codespell.yml | 2 +- .github/workflows/editorconfig-checker.yml | 2 +- .github/workflows/stale.yml | 2 +- .github/workflows/sync-back-to-dev.yml | 2 +- .github/workflows/version_bump.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 5f3a9ada..f6874d4b 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.4 + uses: actions/checkout@v4.1.5 - name: Spell-Checking uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/editorconfig-checker.yml b/.github/workflows/editorconfig-checker.yml index 161e8a53..8b612793 100644 --- a/.github/workflows/editorconfig-checker.yml +++ b/.github/workflows/editorconfig-checker.yml @@ -9,6 +9,6 @@ jobs: name: editorconfig-checker runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 - uses: editorconfig-checker/action-editorconfig-checker@main # current tag v1.0.0 is really out-of-date - run: editorconfig-checker diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index bfab06d6..d689d639 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.1.4 + uses: actions/checkout@v4.1.5 - name: Remove 'stale' label run: gh issue edit ${{ github.event.issue.number }} --remove-label ${{ env.stale_label }} env: diff --git a/.github/workflows/sync-back-to-dev.yml b/.github/workflows/sync-back-to-dev.yml index 2e1be7c4..7cc11808 100644 --- a/.github/workflows/sync-back-to-dev.yml +++ b/.github/workflows/sync-back-to-dev.yml @@ -11,7 +11,7 @@ jobs: name: Syncing branches steps: - name: Checkout - uses: actions/checkout@v4.1.4 + uses: actions/checkout@v4.1.5 - name: Opening pull request run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'Internal' env: diff --git a/.github/workflows/version_bump.yml b/.github/workflows/version_bump.yml index 44f6ef1f..92dc59cc 100644 --- a/.github/workflows/version_bump.yml +++ b/.github/workflows/version_bump.yml @@ -19,7 +19,7 @@ jobs: echo "latest_tag=$LATEST_TAG" >> $GITHUB_ENV - name: Checkout code - uses: actions/checkout@v4.1.4 + uses: actions/checkout@v4.1.5 with: ref: 'development' From d627197780ec8f8cb9fa87f4be84ed71f864bb5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 18 May 2024 10:45:43 +0000 Subject: [PATCH 48/81] Bump actions/checkout from 4.1.5 to 4.1.6 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.5 to 4.1.6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.5...v4.1.6) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codespell.yml | 2 +- .github/workflows/editorconfig-checker.yml | 2 +- .github/workflows/stale.yml | 2 +- .github/workflows/sync-back-to-dev.yml | 2 +- .github/workflows/version_bump.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index f6874d4b..a7c7604e 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Spell-Checking uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/editorconfig-checker.yml b/.github/workflows/editorconfig-checker.yml index 8b612793..e6b2821f 100644 --- a/.github/workflows/editorconfig-checker.yml +++ b/.github/workflows/editorconfig-checker.yml @@ -9,6 +9,6 @@ jobs: name: editorconfig-checker runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - uses: editorconfig-checker/action-editorconfig-checker@main # current tag v1.0.0 is really out-of-date - run: editorconfig-checker diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index d689d639..ae034ef1 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Remove 'stale' label run: gh issue edit ${{ github.event.issue.number }} --remove-label ${{ env.stale_label }} env: diff --git a/.github/workflows/sync-back-to-dev.yml b/.github/workflows/sync-back-to-dev.yml index 7cc11808..7e0c90c8 100644 --- a/.github/workflows/sync-back-to-dev.yml +++ b/.github/workflows/sync-back-to-dev.yml @@ -11,7 +11,7 @@ jobs: name: Syncing branches steps: - name: Checkout - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Opening pull request run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'Internal' env: diff --git a/.github/workflows/version_bump.yml b/.github/workflows/version_bump.yml index 92dc59cc..94e00474 100644 --- a/.github/workflows/version_bump.yml +++ b/.github/workflows/version_bump.yml @@ -19,7 +19,7 @@ jobs: echo "latest_tag=$LATEST_TAG" >> $GITHUB_ENV - name: Checkout code - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 with: ref: 'development' From ebfaf8ef0c777915af23cead6f60f832db5f217b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 10:56:23 +0000 Subject: [PATCH 49/81] Bump eps1lon/actions-label-merge-conflict from 3.0.1 to 3.0.2 Bumps [eps1lon/actions-label-merge-conflict](https://github.com/eps1lon/actions-label-merge-conflict) from 3.0.1 to 3.0.2. - [Release notes](https://github.com/eps1lon/actions-label-merge-conflict/releases) - [Changelog](https://github.com/eps1lon/actions-label-merge-conflict/blob/main/CHANGELOG.md) - [Commits](https://github.com/eps1lon/actions-label-merge-conflict/compare/v3.0.1...v3.0.2) --- updated-dependencies: - dependency-name: eps1lon/actions-label-merge-conflict dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/merge-conflict.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge-conflict.yml b/.github/workflows/merge-conflict.yml index 857aef00..c24de2c8 100644 --- a/.github/workflows/merge-conflict.yml +++ b/.github/workflows/merge-conflict.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check if PRs are have merge conflicts - uses: eps1lon/actions-label-merge-conflict@v3.0.1 + uses: eps1lon/actions-label-merge-conflict@v3.0.2 with: dirtyLabel: "Merge Conflict" repoToken: "${{ secrets.GITHUB_TOKEN }}" From b5bfe71bdbc554df3ebbd14b9f9dfe9a4faf6d6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 15 Jun 2024 10:10:20 +0000 Subject: [PATCH 50/81] Bump actions/checkout from 4.1.6 to 4.1.7 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.6 to 4.1.7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.6...v4.1.7) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codespell.yml | 2 +- .github/workflows/editorconfig-checker.yml | 2 +- .github/workflows/stale.yml | 2 +- .github/workflows/sync-back-to-dev.yml | 2 +- .github/workflows/version_bump.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index a7c7604e..693eda02 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Spell-Checking uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/editorconfig-checker.yml b/.github/workflows/editorconfig-checker.yml index e6b2821f..5cd18d49 100644 --- a/.github/workflows/editorconfig-checker.yml +++ b/.github/workflows/editorconfig-checker.yml @@ -9,6 +9,6 @@ jobs: name: editorconfig-checker runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 - uses: editorconfig-checker/action-editorconfig-checker@main # current tag v1.0.0 is really out-of-date - run: editorconfig-checker diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index ae034ef1..6f93787d 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Remove 'stale' label run: gh issue edit ${{ github.event.issue.number }} --remove-label ${{ env.stale_label }} env: diff --git a/.github/workflows/sync-back-to-dev.yml b/.github/workflows/sync-back-to-dev.yml index 7e0c90c8..db88f65e 100644 --- a/.github/workflows/sync-back-to-dev.yml +++ b/.github/workflows/sync-back-to-dev.yml @@ -11,7 +11,7 @@ jobs: name: Syncing branches steps: - name: Checkout - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Opening pull request run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'Internal' env: diff --git a/.github/workflows/version_bump.yml b/.github/workflows/version_bump.yml index 94e00474..5801f8dc 100644 --- a/.github/workflows/version_bump.yml +++ b/.github/workflows/version_bump.yml @@ -19,7 +19,7 @@ jobs: echo "latest_tag=$LATEST_TAG" >> $GITHUB_ENV - name: Checkout code - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 with: ref: 'development' From 8b8e2194487ac94c774b29d0ae19923d36cab10f Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 19 Jun 2024 22:31:12 +0200 Subject: [PATCH 51/81] Rename API functions for consistency with core code Signed-off-by: DL6ER --- padd.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/padd.sh b/padd.sh index 0eeff12b..67ef6366 100755 --- a/padd.sh +++ b/padd.sh @@ -168,9 +168,9 @@ TestAPIAvailability() { fi } -Authenthication() { +LoginAPI() { # Try to authenticate - LoginAPI + Authenticate while [ "${validSession}" = false ] || [ -z "${validSession}" ] ; do moveXOffset; echo "Authentication failed." @@ -186,7 +186,7 @@ Authenthication() { moveXOffset; secretRead; printf '\n' # Try to authenticate again - LoginAPI + Authenticate done # Loop exited, authentication was successful @@ -213,7 +213,7 @@ DeleteSession() { } -LoginAPI() { +Authenticate() { sessionResponse="$(curl -skS -X POST "${API_URL}auth" --user-agent "PADD ${padd_version}" --data "{\"password\":\"${password}\"}" )" if [ -z "${sessionResponse}" ]; then @@ -1329,7 +1329,7 @@ OutputJSON() { TestAPIAvailability # Authenticate with the FTL server printf "%b" "Establishing connection with FTL...\n" - Authenthication + LoginAPI GetSummaryInformation printf "%b" "{\"domains_being_blocked\":${domains_being_blocked_raw},\"dns_queries_today\":${dns_queries_today_raw},\"ads_blocked_today\":${ads_blocked_today_raw},\"ads_percentage_today\":${ads_percentage_today},\"clients\": ${clients}}" @@ -1351,7 +1351,7 @@ ShowVersion() { TestAPIAvailability # Authenticate with the FTL server printf "%b" "Establishing connection with FTL...\n" - Authenthication + LoginAPI GetVersionInformation GetPADDInformation @@ -1388,7 +1388,7 @@ StartupRoutine(){ # Authenticate with the FTL server moveXOffset; printf "%b" "Establishing connection with FTL...\n" - Authenthication + LoginAPI moveXOffset; printf "%b" "Starting PADD...\n" @@ -1420,7 +1420,7 @@ StartupRoutine(){ TestAPIAvailability # Authenticate with the FTL server moveXOffset; printf "%b" "Establishing connection with FTL...\n" - Authenthication + LoginAPI # Get our information for the first time moveXOffset; echo "- Gathering version info." @@ -1455,7 +1455,7 @@ StartupRoutine(){ # Authenticate with the FTL server moveXOffset; printf "%b" "Establishing connection with FTL...\n" - Authenthication + LoginAPI # Get our information for the first time @@ -1524,7 +1524,7 @@ NormalPADD() { # as $password should be set already, PADD should automatically re-authenticate authenthication_required=$(GetFTLData "info/ftl") if [ "${authenthication_required}" = 401 ]; then - LoginAPI + Authenticate fi # Get uptime, CPU load, temp, etc. every 5 seconds From 8316033d4db6d708bf9a2c4a12472e6f80aee1cc Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 19 Jun 2024 22:31:58 +0200 Subject: [PATCH 52/81] Try to use the CLI password for logins (if enabled and readable by the current user) Signed-off-by: DL6ER --- padd.sh | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/padd.sh b/padd.sh index 67ef6366..efbcbe19 100755 --- a/padd.sh +++ b/padd.sh @@ -145,6 +145,12 @@ TestAPIAvailability() { API_PORT="" else # API is available at this URL combination + + if [ "${availabilityResonse}" = 200 ]; then + # API is available without authentication + needAuth=false + fi + break fi @@ -169,9 +175,21 @@ TestAPIAvailability() { } LoginAPI() { - # Try to authenticate - Authenticate + # Exit early if no authentication is required + if [ "${needAuth}" = false ]; then + moveXOffset; echo "No password required." + return + fi + + # Try to read the CLI password (if enabled and readable by the current user) + if [ -r /etc/pihole/cli_pw ]; then + password=$(cat /etc/pihole/cli_pw) + + # Try to authenticate using the CLI password + Authenticate + fi + # If this did not work, ask the user for the password while [ "${validSession}" = false ] || [ -z "${validSession}" ] ; do moveXOffset; echo "Authentication failed." From 770ce440fa9db46b60b77a80b738718529132630 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 22 Jun 2024 20:52:18 +0200 Subject: [PATCH 53/81] Fix old spelling issue Signed-off-by: DL6ER --- padd.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/padd.sh b/padd.sh index efbcbe19..ea792efd 100755 --- a/padd.sh +++ b/padd.sh @@ -102,7 +102,7 @@ padd_logo_retro_3="${bold_text}${green_text}| ${red_text}/${yellow_text}-${gre TestAPIAvailability() { - local chaos_api_list availabilityResonse cmdResult digReturnCode + local chaos_api_list availabilityResponse cmdResult digReturnCode # Query the API URLs from FTL using CHAOS TXT # The result is a space-separated enumeration of full URLs @@ -137,16 +137,16 @@ TestAPIAvailability() { API_URL="${API_URL#\"}" # Test if the API is available at this URL - availabilityResonse=$(curl -skS -o /dev/null -w "%{http_code}" "${API_URL}auth") + availabilityResponse=$(curl -skS -o /dev/null -w "%{http_code}" "${API_URL}auth") # Test if http status code was 200 (OK) or 401 (authentication required) - if [ ! "${availabilityResonse}" = 200 ] && [ ! "${availabilityResonse}" = 401 ]; then + if [ ! "${availabilityResponse}" = 200 ] && [ ! "${availabilityResponse}" = 401 ]; then # API is not available at this port/protocol combination API_PORT="" else # API is available at this URL combination - if [ "${availabilityResonse}" = 200 ]; then + if [ "${availabilityResponse}" = 200 ]; then # API is available without authentication needAuth=false fi From 7f3d46f5a684008a769b9b970171125b3cc1fcc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 3 Jul 2024 19:45:13 +0200 Subject: [PATCH 54/81] Exit bump workflow early if latest tag is empty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/version_bump.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/version_bump.yml b/.github/workflows/version_bump.yml index 5801f8dc..14c6e83b 100644 --- a/.github/workflows/version_bump.yml +++ b/.github/workflows/version_bump.yml @@ -17,6 +17,7 @@ jobs: LATEST_TAG=$(gh -R $REPO release list -L 1 | awk '{printf $3}') echo "Latest version tag for releases in $REPO is $LATEST_TAG" echo "latest_tag=$LATEST_TAG" >> $GITHUB_ENV + [[ -z ${LATEST_TAG} ]] && echo "Error: LATEST_TAG is empty, aborting" && exit 1 - name: Checkout code uses: actions/checkout@v4.1.7 From 11723bce9704b8f4c4a36e6876262bc5330abbb8 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 14 Jul 2024 15:09:49 +0200 Subject: [PATCH 55/81] Modify PADD to comply with the changes in FTL on the same branch Signed-off-by: DL6ER --- padd.sh | 48 +++++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/padd.sh b/padd.sh index ea792efd..f66583dc 100755 --- a/padd.sh +++ b/padd.sh @@ -390,34 +390,39 @@ GetSystemInformation() { GetNetworkInformation() { interfaces_raw=$(GetFTLData "network/interfaces") + gateway_raw=$(GetFTLData "network/gateway") + gateway_v4_iface=$(echo "${gateway_raw}" | jq -r '.gateway[] | select(.family == "inet") | .interface' | head -n 1) + v4_iface_data=$(echo "${interfaces_raw}" | jq --arg iface "${gateway_v4_iface}" '.interfaces[] | select(.name==$iface)' 2>/dev/null) + gateway_v6_iface=$(echo "${gateway_raw}" | jq -r '.gateway[] | select(.family == "inet6") | .interface' | head -n 1) + v6_iface_data=$(echo "${interfaces_raw}" | jq --arg iface "${gateway_v6_iface}" '.interfaces[] | select(.name==$iface)' 2>/dev/null) config=$(GetFTLData "config") # Get pi IPv4 address of the default interface - pi_ip4_addrs="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv4[]' 2>/dev/null | wc -w)" - if [ "${pi_ip4_addrs}" -eq 0 ]; then + pi_ip4_addrs="$(echo "${v4_iface_data}" | jq --raw-output '.addresses[] | select(.family=="inet") | .address' 2>/dev/null)" + if [ $(echo "${pi_ip4_addrs}" | wc -l) -eq 0 ]; then # No IPv4 address available pi_ip4_addr="N/A" - elif [ "${pi_ip4_addrs}" -eq 1 ]; then + elif [ $(echo "${pi_ip4_addrs}" | wc -l) -eq 1 ]; then # One IPv4 address available - pi_ip4_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv4[0]' 2>/dev/null)" + pi_ip4_addr=${pi_ip4_addrs} else # More than one IPv4 address available - pi_ip4_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv4[0]' 2>/dev/null)+" + pi_ip4_addr="$(echo "${pi_ip4_addrs}" | head -n 1)+" fi # Get pi IPv6 address of the default interface - pi_ip6_addrs="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv6[]' 2>/dev/null | wc -w)" - if [ "${pi_ip6_addrs}" -eq 0 ]; then + pi_ip6_addrs="$(echo "${v6_iface_data}" | jq --raw-output '.addresses[] | select(.family=="inet6") | .address' 2>/dev/null)" + if [ $(echo "${pi_ip6_addrs}" | wc -l) -eq 0 ]; then # No IPv6 address available pi_ip6_addr="N/A" ipv6_check_box=${check_box_bad} - elif [ "${pi_ip6_addrs}" -eq 1 ]; then + elif [ $(echo "${pi_ip6_addrs}" | wc -l) -eq 1 ]; then # One IPv6 address available - pi_ip6_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv6[0]' 2>/dev/null | cut -f1 -d "%" )" + pi_ip6_addr=${pi_ip6_addrs} ipv6_check_box=${check_box_good} else # More than one IPv6 address available - pi_ip6_addr="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .ipv6[0]' 2>/dev/null | cut -f1 -d "%" )+" + pi_ip6_addr="$(echo "${pi_ip6_addrs}" | head -n 1)+" ipv6_check_box=${check_box_good} fi @@ -449,7 +454,8 @@ GetNetworkInformation() { dhcp_heatmap=${red_text} dhcp_check_box=${check_box_bad} - GATEWAY="$(GetFTLData "network/gateway" | jq --raw-output .address 2>/dev/null)" + # Display the gateway address if DHCP is disabled + GATEWAY="$(echo "${gateway_raw}" | jq -r '.gateway[] | select(.family == "inet") | .address' | head -n 1)" dhcp_info=" Router: ${GATEWAY}" dhcp_ipv6_status="N/A" dhcp_ipv6_heatmap=${yellow_text} @@ -501,15 +507,23 @@ GetNetworkInformation() { conditional_forwarding_heatmap=${red_text} fi - # Default interface data - iface_name="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .name' 2>/dev/null)" - tx_bytes="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .tx.num' 2>/dev/null)" - tx_bytes_unit="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .tx.unit' 2>/dev/null)" + # Default interface data (use IPv4 interface - we cannot show both and assume they are the same) + iface_name="${gateway_v4_iface}" + tx_bytes="$(echo "${v4_iface_data}" | jq --raw-output '.stats.tx_bytes.value' 2>/dev/null)" + tx_bytes_unit="$(echo "${v4_iface_data}" | jq --raw-output '.stats.tx_bytes.unit' 2>/dev/null)" tx_bytes=$(printf "%.1f %b" "${tx_bytes}" "${tx_bytes_unit}") - rx_bytes="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .rx.num' 2>/dev/null)" - rx_bytes_unit="$(echo "${interfaces_raw}" | jq --raw-output '.interfaces[] | select(.default==true) | .rx.unit' 2>/dev/null)" + rx_bytes="$(echo "${v4_iface_data}" | jq --raw-output '.stats.rx_bytes.value' 2>/dev/null)" + rx_bytes_unit="$(echo "${v4_iface_data}" | jq --raw-output '.stats.rx_bytes.unit' 2>/dev/null)" rx_bytes=$(printf "%.1f %b" "${rx_bytes}" "${rx_bytes_unit}") + + # If IPv4 and IPv6 interfaces are not the same, add a "*" to the interface + # name to highlight that there are two different interfaces and the + # displayed statistics are only for the IPv4 interface, while the IPv6 + # address correctly corresponds to the default IPv6 interface + if [ ! "${gateway_v4_iface}" = "${gateway_v6_iface}" ]; then + iface_name="${iface_name}*" + fi } GetPiholeInformation() { From c7f7608659618d3973c593c0e59337ebaca94d90 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 14 Jul 2024 16:45:24 +0200 Subject: [PATCH 56/81] Fix editorconfig errors even if not introduced by the PR at hand Signed-off-by: DL6ER --- padd.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/padd.sh b/padd.sh index f66583dc..37904718 100755 --- a/padd.sh +++ b/padd.sh @@ -232,22 +232,22 @@ DeleteSession() { } Authenticate() { - sessionResponse="$(curl -skS -X POST "${API_URL}auth" --user-agent "PADD ${padd_version}" --data "{\"password\":\"${password}\"}" )" + sessionResponse="$(curl -skS -X POST "${API_URL}auth" --user-agent "PADD ${padd_version}" --data "{\"password\":\"${password}\"}" )" if [ -z "${sessionResponse}" ]; then moveXOffset; echo "No response from FTL server. Please check connectivity and use the options to set the API URL" moveXOffset; echo "Usage: $0 [--server ]" exit 1 fi - # obtain validity and session ID from session response - validSession=$(echo "${sessionResponse}"| jq .session.valid 2>/dev/null) - SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid 2>/dev/null) + # obtain validity and session ID from session response + validSession=$(echo "${sessionResponse}"| jq .session.valid 2>/dev/null) + SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid 2>/dev/null) } GetFTLData() { local response # get the data from querying the API as well as the http status code - response=$(curl -skS -w "%{http_code}" -X GET "${API_URL}$1" -H "Accept: application/json" -H "sid: ${SID}" ) + response=$(curl -skS -w "%{http_code}" -X GET "${API_URL}$1" -H "Accept: application/json" -H "sid: ${SID}" ) # status are the last 3 characters status=$(printf %s "${response#"${response%???}"}") From c1adc4a6eb977eb5532e29778771503a43f947d2 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Sun, 14 Jul 2024 21:42:10 +0200 Subject: [PATCH 57/81] DHCP is a top level config object Signed-off-by: yubiuser --- padd.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/padd.sh b/padd.sh index ea792efd..105cae9d 100755 --- a/padd.sh +++ b/padd.sh @@ -422,11 +422,11 @@ GetNetworkInformation() { fi # Is Pi-Hole acting as the DHCP server? - DHCP_ACTIVE="$(echo "${config}" | jq .config.dns.dhcp.active 2>/dev/null )" + DHCP_ACTIVE="$(echo "${config}" | jq .config.dhcp.active 2>/dev/null )" if [ "${DHCP_ACTIVE}" = "true" ]; then - DHCP_START="$(echo "${config}" | jq --raw-output .config.dns.dhcp.start 2>/dev/null)" - DHCP_END="$(echo "${config}" | jq --raw-output .config.dns.dhcp.end 2>/dev/null)" + DHCP_START="$(echo "${config}" | jq --raw-output .config.dhcp.start 2>/dev/null)" + DHCP_END="$(echo "${config}" | jq --raw-output .config.dhcp.end 2>/dev/null)" dhcp_status="Enabled" dhcp_info=" Range: ${DHCP_START} - ${DHCP_END}" @@ -434,7 +434,7 @@ GetNetworkInformation() { dhcp_check_box=${check_box_good} # Is DHCP handling IPv6? - DHCP_IPv6="$(echo "${config}" | jq --raw-output .config.dns.dhcp.ipv6 2>/dev/null)" + DHCP_IPv6="$(echo "${config}" | jq --raw-output .config.dhcp.ipv6 2>/dev/null)" if [ "${DHCP_IPv6}" = "true" ]; then dhcp_ipv6_status="Enabled" dhcp_ipv6_heatmap=${green_text} From 19808bfb577e1209fa8f4890b32fd404d4de85e3 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Sun, 14 Jul 2024 21:53:28 +0200 Subject: [PATCH 58/81] Fix idention style Signed-off-by: yubiuser --- padd.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/padd.sh b/padd.sh index 105cae9d..d54f02ae 100755 --- a/padd.sh +++ b/padd.sh @@ -232,22 +232,22 @@ DeleteSession() { } Authenticate() { - sessionResponse="$(curl -skS -X POST "${API_URL}auth" --user-agent "PADD ${padd_version}" --data "{\"password\":\"${password}\"}" )" + sessionResponse="$(curl -skS -X POST "${API_URL}auth" --user-agent "PADD ${padd_version}" --data "{\"password\":\"${password}\"}" )" if [ -z "${sessionResponse}" ]; then moveXOffset; echo "No response from FTL server. Please check connectivity and use the options to set the API URL" moveXOffset; echo "Usage: $0 [--server ]" exit 1 fi - # obtain validity and session ID from session response - validSession=$(echo "${sessionResponse}"| jq .session.valid 2>/dev/null) - SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid 2>/dev/null) + # obtain validity and session ID from session response + validSession=$(echo "${sessionResponse}"| jq .session.valid 2>/dev/null) + SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid 2>/dev/null) } GetFTLData() { local response # get the data from querying the API as well as the http status code - response=$(curl -skS -w "%{http_code}" -X GET "${API_URL}$1" -H "Accept: application/json" -H "sid: ${SID}" ) + response=$(curl -skS -w "%{http_code}" -X GET "${API_URL}$1" -H "Accept: application/json" -H "sid: ${SID}" ) # status are the last 3 characters status=$(printf %s "${response#"${response%???}"}") From d1707e56a51a1398bf85c8cb482c5e901841347a Mon Sep 17 00:00:00 2001 From: yubiuser Date: Thu, 18 Jul 2024 08:51:01 +0200 Subject: [PATCH 59/81] Check for required dependencies on startup Signed-off-by: yubiuser --- padd.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/padd.sh b/padd.sh index d54f02ae..534e09e8 100755 --- a/padd.sh +++ b/padd.sh @@ -1330,6 +1330,19 @@ secretRead() { stty "${stty_orig}" } +check_dependencies() { + # Check for required dependencies + if ! command -v curl >/dev/null 2>&1; then + printf "%b" "${check_box_bad} Error!\n 'curl' is missing but required.\n" + exit 1 + fi + + if ! command -v jq >/dev/null 2>&1; then + printf "%b" "${check_box_bad} Error!\n 'jq' is missing but required.\n" + exit 1 + fi +} + ########################################## MAIN FUNCTIONS ########################################## OutputJSON() { @@ -1744,4 +1757,5 @@ while [ "$#" -gt 0 ]; do shift done +check_dependencies main From f918bff7771af0fdd71c3fb0ce3c844a3dd174ed Mon Sep 17 00:00:00 2001 From: yubiuser Date: Thu, 18 Jul 2024 09:54:10 +0200 Subject: [PATCH 60/81] No need to check for wget in update routine as we check for curl during normal runtime Signed-off-by: yubiuser --- padd.sh | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/padd.sh b/padd.sh index 534e09e8..4e9a066d 100755 --- a/padd.sh +++ b/padd.sh @@ -1613,26 +1613,12 @@ Update() { padd_script_path=$(realpath "$0") - if which wget > /dev/null 2>&1; then - echo "${check_box_info} Downloading PADD update via wget ..." - if wget -qO "${padd_script_path}" https://install.padd.sh > /dev/null 2>&1; then - echo "${check_box_good} ... done. Restart PADD for the update to take effect" - else - echo "${check_box_bad} Cannot download PADD update via wget" - echo "${check_box_info} Go to https://install.padd.sh to download the update manually" - exit 1 - fi - elif which curl > /dev/null 2>&1; then - echo "${check_box_info} Downloading PADD update via curl ..." - if curl -sSL https://install.padd.sh -o "${padd_script_path}" > /dev/null 2>&1; then - echo "${check_box_good} ... done. Restart PADD for the update to take effect" - else - echo "${check_box_bad} Cannot download PADD update via curl" - echo "${check_box_info} Go to https://install.padd.sh to download the update manually" - exit 1 - fi + echo "${check_box_info} Downloading PADD update ..." + + if curl -sSL https://install.padd.sh -o "${padd_script_path}" > /dev/null 2>&1; then + echo "${check_box_good} ... done. Restart PADD for the update to take effect" else - echo "${check_box_bad} Cannot download, neither wget nor curl are available" + echo "${check_box_bad} Cannot download PADD update" echo "${check_box_info} Go to https://install.padd.sh to download the update manually" exit 1 fi @@ -1720,6 +1706,9 @@ TerminalResize(){ } main(){ + + check_dependencies + # Hiding the cursor. # https://vt100.net/docs/vt510-rm/DECTCEM.html printf '\e[?25l' @@ -1757,5 +1746,4 @@ while [ "$#" -gt 0 ]; do shift done -check_dependencies main From ef97d5bd578b99da828fa98825afcd0ed7d17e93 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 22 Jul 2024 14:16:29 +0200 Subject: [PATCH 61/81] Fallback: If there is no default IPv6 gateway, use the default IPv4 gateway interface instead Signed-off-by: DL6ER --- padd.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/padd.sh b/padd.sh index 37904718..83e3b31c 100755 --- a/padd.sh +++ b/padd.sh @@ -394,6 +394,11 @@ GetNetworkInformation() { gateway_v4_iface=$(echo "${gateway_raw}" | jq -r '.gateway[] | select(.family == "inet") | .interface' | head -n 1) v4_iface_data=$(echo "${interfaces_raw}" | jq --arg iface "${gateway_v4_iface}" '.interfaces[] | select(.name==$iface)' 2>/dev/null) gateway_v6_iface=$(echo "${gateway_raw}" | jq -r '.gateway[] | select(.family == "inet6") | .interface' | head -n 1) + # Fallback: If there is no default IPv6 gateway, use the default IPv4 + # gateway interface instead + if [ -z "${gateway_v6_iface}" ]; then + gateway_v6_iface="${gateway_v4_iface}" + fi v6_iface_data=$(echo "${interfaces_raw}" | jq --arg iface "${gateway_v6_iface}" '.interfaces[] | select(.name==$iface)' 2>/dev/null) config=$(GetFTLData "config") From 5559796a4a574910f4797f40c9112130bb9f23e0 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 5 Aug 2024 19:01:55 +0200 Subject: [PATCH 62/81] Use new FTL api/padd endpoint for querying the data Signed-off-by: DL6ER --- padd.sh | 254 ++++++++++++++++++++++++++------------------------------ 1 file changed, 116 insertions(+), 138 deletions(-) diff --git a/padd.sh b/padd.sh index f78aa785..90fd5693 100755 --- a/padd.sh +++ b/padd.sh @@ -18,12 +18,8 @@ export LC_NUMERIC=C padd_version="v4.0.0" # LastChecks -LastCheckVersionInformation=$(date +%s) -LastCheckNetworkInformation=$(date +%s) -LastCheckSummaryInformation=$(date +%s) -LastCheckPiholeInformation=$(date +%s) -LastCheckSystemInformation=$(date +%s) LastCheckPADDInformation=$(date +%s) +LastCheckFullInformation=$(date +%s) # COLORS CSI="$(printf '\033')[" # Control Sequence Introducer @@ -247,7 +243,7 @@ Authenticate() { GetFTLData() { local response # get the data from querying the API as well as the http status code - response=$(curl -skS -w "%{http_code}" -X GET "${API_URL}$1" -H "Accept: application/json" -H "sid: ${SID}" ) + response=$(curl -skS -w "%{http_code}" -X GET "${API_URL}$1$2" -H "Accept: application/json" -H "sid: ${SID}" ) # status are the last 3 characters status=$(printf %s "${response#"${response%???}"}") @@ -268,61 +264,55 @@ GetFTLData() { ############################################# GETTERS ############################################## -GetSummaryInformation() { - summary=$(GetFTLData "stats/summary") - cache_info=$(GetFTLData "info/metrics") - ftl_info=$(GetFTLData "info/ftl") - dns_blocking=$(GetFTLData "dns/blocking") +GetAPIData() { + padd_data=$(GetFTLData "padd" "$1") + echo "$padd_data" > data.json +} - clients=$(echo "${ftl_info}" | jq .ftl.clients.active 2>/dev/null) +GetSummaryInformation() { + clients=$(echo "${padd_data}" | jq .active_clients 2>/dev/null) - blocking_enabled=$(echo "${dns_blocking}" | jq .blocking 2>/dev/null) + blocking_enabled=$(echo "${padd_data}" | jq .blocking 2>/dev/null) - domains_being_blocked_raw=$(echo "${ftl_info}" | jq .ftl.database.gravity 2>/dev/null) + domains_being_blocked_raw=$(echo "${padd_data}" | jq .gravity_size 2>/dev/null) domains_being_blocked=$(printf "%.f" "${domains_being_blocked_raw}") - dns_queries_today_raw=$(echo "$summary" | jq .queries.total 2>/dev/null) + dns_queries_today_raw=$(echo "${padd_data}" | jq .queries.total 2>/dev/null) dns_queries_today=$(printf "%.f" "${dns_queries_today_raw}") - ads_blocked_today_raw=$(echo "$summary" | jq .queries.blocked 2>/dev/null) + ads_blocked_today_raw=$(echo "${padd_data}" | jq .queries.blocked 2>/dev/null) ads_blocked_today=$(printf "%.f" "${ads_blocked_today_raw}") - ads_percentage_today_raw=$(echo "$summary" | jq .queries.percent_blocked 2>/dev/null) + ads_percentage_today_raw=$(echo "${padd_data}" | jq .queries.percent_blocked 2>/dev/null) ads_percentage_today=$(printf "%.1f" "${ads_percentage_today_raw}") - cache_size=$(echo "$cache_info" | jq .metrics.dns.cache.size 2>/dev/null) - cache_evictions=$(echo "$cache_info" | jq .metrics.dns.cache.evicted 2>/dev/null) - cache_inserts=$(echo "$cache_info"| jq .metrics.dns.cache.inserted 2>/dev/null) + cache_size=$(echo "${padd_data}" | jq .cache.size 2>/dev/null) + cache_evictions=$(echo "${padd_data}" | jq .cache.evicted 2>/dev/null) + cache_inserts=$(echo "${padd_data}"| jq .cache.inserted 2>/dev/null) - latest_blocked_raw=$(GetFTLData "stats/recent_blocked?show=1" | jq --raw-output .blocked[0] 2>/dev/null) + latest_blocked_raw=$(echo "${padd_data}" | jq --raw-output .recent_blocked 2>/dev/null) - top_blocked_raw=$(GetFTLData "stats/top_domains?blocked=true" | jq --raw-output .domains[0].domain 2>/dev/null) + top_blocked_raw=$(echo "${padd_data}" | jq --raw-output .top_domain 2>/dev/null) - top_domain_raw=$(GetFTLData "stats/top_domains" | jq --raw-output .domains[0].domain 2>/dev/null) + top_domain_raw=$(echo "${padd_data}" | jq --raw-output .top_blocked 2>/dev/null) - top_client_raw=$(GetFTLData "stats/top_clients" | jq --raw-output .clients[0].name 2>/dev/null) - if [ -z "${top_client_raw}" ]; then - # if no hostname was supplied, use IP - top_client_raw=$(GetFTLData "stats/top_clients" | jq --raw-output .clients[0].ip 2>/dev/null) - fi + top_client_raw=$(echo "${padd_data}" | jq --raw-output .top_client 2>/dev/null) } GetSystemInformation() { - sysinfo=$(GetFTLData "info/system") - # System uptime - if [ "${sysinfo}" = 000 ]; then + if [ "${padd_data}" = 000 ]; then # in case FTL connection is down, system_uptime_raw need to be set to 0 otherwise convertUptime() will complain system_uptime_raw=0 else - system_uptime_raw=$(echo "${sysinfo}" | jq .system.uptime 2>/dev/null) + system_uptime_raw=$(echo "${padd_data}" | jq .system.uptime 2>/dev/null) fi # CPU temperature and unit # in case .sensors.cpu_temp returns 'null' we substitute with 0 - cpu_temp_raw=$(GetFTLData "info/sensors" | jq '(.sensors.cpu_temp // 0)' 2>/dev/null) + cpu_temp_raw=$(echo "${padd_data}" | jq '(.sensors.cpu_temp // 0)' 2>/dev/null) cpu_temp=$(printf "%.1f" "${cpu_temp_raw}") - temp_unit=$(GetFTLData "info/sensors" | jq --raw-output .sensors.unit 2>/dev/null) + temp_unit=$(echo "${padd_data}" | jq --raw-output .sensors.unit 2>/dev/null) # Temp + Unit if [ "${temp_unit}" = "C" ]; then @@ -338,6 +328,10 @@ GetSystemInformation() { temperature="${cpu_temp}${temp_unit}" # convert to Celsius for limit checking cpu_temp_celsius="$(echo "${cpu_temp}" | awk '{print $1 - 273.15}' | awk -F '.' '{print $1}')" + else # unknown unit + temperature="${cpu_temp}°?" + # no conversion needed + cpu_temp_celsius=0 fi # CPU temperature heatmap @@ -356,22 +350,22 @@ GetSystemInformation() { fi # CPU, load, heatmap - core_count=$(echo "${sysinfo}" | jq .system.cpu.nprocs 2>/dev/null) - cpu_load_1=$(printf %.2f "$(echo "${sysinfo}" | jq .system.cpu.load.raw[0] 2>/dev/null)") - cpu_load_5=$(printf %.2f "$(echo "${sysinfo}" | jq .system.cpu.load.raw[1] 2>/dev/null)") - cpu_load_15=$(printf %.2f "$(echo "${sysinfo}" | jq .system.cpu.load.raw[2] 2>/dev/null)") + core_count=$(echo "${padd_data}" | jq .system.cpu.nprocs 2>/dev/null) + cpu_load_1=$(printf %.2f "$(echo "${padd_data}" | jq .system.cpu.load.raw[0] 2>/dev/null)") + cpu_load_5=$(printf %.2f "$(echo "${padd_data}" | jq .system.cpu.load.raw[1] 2>/dev/null)") + cpu_load_15=$(printf %.2f "$(echo "${padd_data}" | jq .system.cpu.load.raw[2] 2>/dev/null)") cpu_load_1_heatmap=$(HeatmapGenerator "${cpu_load_1}" "${core_count}") cpu_load_5_heatmap=$(HeatmapGenerator "${cpu_load_5}" "${core_count}") cpu_load_15_heatmap=$(HeatmapGenerator "${cpu_load_15}" "${core_count}") - cpu_percent=$(printf %.1f "$(echo "${sysinfo}" | jq .system.cpu.load.percent[0] 2>/dev/null)") + cpu_percent=$(printf %.1f "$(echo "${padd_data}" | jq .system.cpu.load.percent[0] 2>/dev/null)") # Memory use, heatmap and bar - memory_percent_raw="$(echo "${sysinfo}" | jq '.system.memory.ram."%used"' 2>/dev/null)" + memory_percent_raw="$(echo "${padd_data}" | jq '.system.memory.ram."%used"' 2>/dev/null)" memory_percent=$(printf %.1f "${memory_percent_raw}") memory_heatmap="$(HeatmapGenerator "${memory_percent}")" # Get device model - sys_model="$(GetFTLData "info/host" | jq --raw-output .host.model 2>/dev/null)" + sys_model="$(echo "${padd_data}" | jq --raw-output .host_model 2>/dev/null)" # DOCKER_VERSION is set during GetVersionInformation, so this needs to run first during startup if [ ! "${DOCKER_VERSION}" = "null" ]; then @@ -389,54 +383,44 @@ GetSystemInformation() { } GetNetworkInformation() { - interfaces_raw=$(GetFTLData "network/interfaces") - gateway_raw=$(GetFTLData "network/gateway") - gateway_v4_iface=$(echo "${gateway_raw}" | jq -r '.gateway[] | select(.family == "inet") | .interface' | head -n 1) - v4_iface_data=$(echo "${interfaces_raw}" | jq --arg iface "${gateway_v4_iface}" '.interfaces[] | select(.name==$iface)' 2>/dev/null) - gateway_v6_iface=$(echo "${gateway_raw}" | jq -r '.gateway[] | select(.family == "inet6") | .interface' | head -n 1) - # Fallback: If there is no default IPv6 gateway, use the default IPv4 - # gateway interface instead - if [ -z "${gateway_v6_iface}" ]; then - gateway_v6_iface="${gateway_v4_iface}" - fi - v6_iface_data=$(echo "${interfaces_raw}" | jq --arg iface "${gateway_v6_iface}" '.interfaces[] | select(.name==$iface)' 2>/dev/null) - config=$(GetFTLData "config") + gateway_v4_iface=$(echo "${padd_data}" | jq -r '.iface.v4.name') + gateway_v6_iface=$(echo "${padd_data}" | jq -r '.iface.v4.name') - # Get pi IPv4 address of the default interface - pi_ip4_addrs="$(echo "${v4_iface_data}" | jq --raw-output '.addresses[] | select(.family=="inet") | .address' 2>/dev/null)" - if [ $(echo "${pi_ip4_addrs}" | wc -l) -eq 0 ]; then + # Get IPv4 address of the default interface + pi_ip4_addrs="$(echo "${padd_data}" | jq --raw-output '.iface.v4.num_addrs' 2>/dev/null)" + pi_ip4_addr="$(echo "${padd_data}" | jq --raw-output '.iface.v4.addr' 2>/dev/null)" + if [ "${pi_ip4_addrs}" -eq 0 ]; then # No IPv4 address available pi_ip4_addr="N/A" - elif [ $(echo "${pi_ip4_addrs}" | wc -l) -eq 1 ]; then - # One IPv4 address available - pi_ip4_addr=${pi_ip4_addrs} + #elif [ "${pi_ip4_addrs}" -eq 1 ]; then + # # One IPv4 address available else # More than one IPv4 address available - pi_ip4_addr="$(echo "${pi_ip4_addrs}" | head -n 1)+" + pi_ip4_addr="${pi_ip4_addr}+" fi - # Get pi IPv6 address of the default interface - pi_ip6_addrs="$(echo "${v6_iface_data}" | jq --raw-output '.addresses[] | select(.family=="inet6") | .address' 2>/dev/null)" - if [ $(echo "${pi_ip6_addrs}" | wc -l) -eq 0 ]; then + # Get IPv6 address of the default interface + pi_ip6_addrs="$(echo "${padd_data}" | jq --raw-output '.iface.v6.num_addrs' 2>/dev/null)" + pi_ip6_addr="$(echo "${padd_data}" | jq --raw-output '.iface.v6.addr' 2>/dev/null)" + if [ "${pi_ip6_addrs}" -eq 0 ]; then # No IPv6 address available pi_ip6_addr="N/A" ipv6_check_box=${check_box_bad} - elif [ $(echo "${pi_ip6_addrs}" | wc -l) -eq 1 ]; then + elif [ "${pi_ip6_addrs}" -eq 1 ]; then # One IPv6 address available - pi_ip6_addr=${pi_ip6_addrs} ipv6_check_box=${check_box_good} else # More than one IPv6 address available - pi_ip6_addr="$(echo "${pi_ip6_addrs}" | head -n 1)+" + pi_ip6_addr="${pi_ip6_addr}+" ipv6_check_box=${check_box_good} fi # Is Pi-Hole acting as the DHCP server? - DHCP_ACTIVE="$(echo "${config}" | jq .config.dhcp.active 2>/dev/null )" + DHCP_ACTIVE="$(echo "${padd_data}" | jq .config.dhcp_active 2>/dev/null )" if [ "${DHCP_ACTIVE}" = "true" ]; then - DHCP_START="$(echo "${config}" | jq --raw-output .config.dhcp.start 2>/dev/null)" - DHCP_END="$(echo "${config}" | jq --raw-output .config.dhcp.end 2>/dev/null)" + DHCP_START="$(echo "${padd_data}" | jq --raw-output .config.dhcp_start 2>/dev/null)" + DHCP_END="$(echo "${padd_data}" | jq --raw-output .config.dhcp_end 2>/dev/null)" dhcp_status="Enabled" dhcp_info=" Range: ${DHCP_START} - ${DHCP_END}" @@ -444,7 +428,7 @@ GetNetworkInformation() { dhcp_check_box=${check_box_good} # Is DHCP handling IPv6? - DHCP_IPv6="$(echo "${config}" | jq --raw-output .config.dhcp.ipv6 2>/dev/null)" + DHCP_IPv6="$(echo "${padd_data}" | jq --raw-output .config.dhcp_ipv6 2>/dev/null)" if [ "${DHCP_IPv6}" = "true" ]; then dhcp_ipv6_status="Enabled" dhcp_ipv6_heatmap=${green_text} @@ -460,7 +444,7 @@ GetNetworkInformation() { dhcp_check_box=${check_box_bad} # Display the gateway address if DHCP is disabled - GATEWAY="$(echo "${gateway_raw}" | jq -r '.gateway[] | select(.family == "inet") | .address' | head -n 1)" + GATEWAY="$(echo "${padd_data}" | jq -r '.iface.v4.gw_addr' | head -n 1)" dhcp_info=" Router: ${GATEWAY}" dhcp_ipv6_status="N/A" dhcp_ipv6_heatmap=${yellow_text} @@ -468,11 +452,11 @@ GetNetworkInformation() { fi # Get hostname - pi_hostname="$(GetFTLData "info/host" | jq --raw-output .host.uname.nodename 2>/dev/null)" + pi_hostname="$(echo "${padd_data}" | jq --raw-output .node_name 2>/dev/null)" full_hostname=${pi_hostname} # when PI-hole is the DHCP server, append the domain to the hostname if [ "${DHCP_ACTIVE}" = "true" ]; then - PIHOLE_DOMAIN="$(echo "${config}" | jq --raw-output .config.dns.domain 2>/dev/null)" + PIHOLE_DOMAIN="$(echo "${padd_data}" | jq --raw-output .config.dns_domain 2>/dev/null)" if [ -n "${PIHOLE_DOMAIN}" ]; then count=${pi_hostname}"."${PIHOLE_DOMAIN} count=${#count} @@ -483,7 +467,7 @@ GetNetworkInformation() { fi # Get the number of configured upstream DNS servers - dns_count="$(echo "${config}" | jq --raw-output .config.dns.upstreams[] 2>/dev/null | sed '/^\s*$/d' | wc -l)" + dns_count="$(echo "${padd_data}" | jq --raw-output .config.dns_num_upstreams 2>/dev/null)" # if there's only one DNS server if [ "${dns_count}" -eq 1 ]; then dns_information="1 server" @@ -493,7 +477,7 @@ GetNetworkInformation() { # DNSSEC - DNSSEC="$(echo "${config}" | jq .config.dns.dnssec 2>/dev/null)" + DNSSEC="$(echo "${padd_data}" | jq .config.dns_dnssec 2>/dev/null)" if [ "${DNSSEC}" = "true" ]; then dnssec_status="Enabled" dnssec_heatmap=${green_text} @@ -503,7 +487,7 @@ GetNetworkInformation() { fi # Conditional forwarding - CONDITIONAL_FORWARDING="$(echo "${config}" | jq .config.dns.revServer.active 2>/dev/null)" + CONDITIONAL_FORWARDING="$(echo "${padd_data}" | jq .config.dns_revServer_active 2>/dev/null)" if [ "${CONDITIONAL_FORWARDING}" = "true" ]; then conditional_forwarding_status="Enabled" conditional_forwarding_heatmap=${green_text} @@ -514,12 +498,12 @@ GetNetworkInformation() { # Default interface data (use IPv4 interface - we cannot show both and assume they are the same) iface_name="${gateway_v4_iface}" - tx_bytes="$(echo "${v4_iface_data}" | jq --raw-output '.stats.tx_bytes.value' 2>/dev/null)" - tx_bytes_unit="$(echo "${v4_iface_data}" | jq --raw-output '.stats.tx_bytes.unit' 2>/dev/null)" + tx_bytes="$(echo "${padd_data}" | jq --raw-output '.iface.v4.tx_bytes.value' 2>/dev/null)" + tx_bytes_unit="$(echo "${padd_data}" | jq --raw-output '.iface.v4.tx_bytes.unit' 2>/dev/null)" tx_bytes=$(printf "%.1f %b" "${tx_bytes}" "${tx_bytes_unit}") - rx_bytes="$(echo "${v4_iface_data}" | jq --raw-output '.stats.rx_bytes.value' 2>/dev/null)" - rx_bytes_unit="$(echo "${v4_iface_data}" | jq --raw-output '.stats.rx_bytes.unit' 2>/dev/null)" + rx_bytes="$(echo "${padd_data}" | jq --raw-output '.iface.v4.rx_bytes.value' 2>/dev/null)" + rx_bytes_unit="$(echo "${padd_data}" | jq --raw-output '.iface.v4.rx_bytes.unit' 2>/dev/null)" rx_bytes=$(printf "%.1f %b" "${rx_bytes}" "${rx_bytes_unit}") # If IPv4 and IPv6 interfaces are not the same, add a "*" to the interface @@ -532,11 +516,9 @@ GetNetworkInformation() { } GetPiholeInformation() { - sysinfo=$(GetFTLData "info/ftl") - # If FTL is not running (sysinfo is 000), set all variables to "not running" connection_down_flag=false - if [ "${sysinfo}" = "000" ]; then + if [ "${padd_data}" = "000" ]; then ftl_status="No connection" ftl_heatmap=${red_text} ftl_check_box=${check_box_bad} @@ -549,14 +531,14 @@ GetPiholeInformation() { ftl_heatmap=${green_text} ftl_check_box=${check_box_good} # Get FTL CPU and memory usage - ftl_cpu_raw="$(echo "${sysinfo}" | jq '.ftl."%cpu"' 2>/dev/null)" - ftl_mem_percentage_raw="$(echo "${sysinfo}" | jq '.ftl."%mem"' 2>/dev/null)" + ftl_cpu_raw="$(echo "${padd_data}" | jq '."%cpu"' 2>/dev/null)" + ftl_mem_percentage_raw="$(echo "${padd_data}" | jq '."%mem"' 2>/dev/null)" ftl_cpu="$(printf "%.1f" "${ftl_cpu_raw}")%" ftl_mem_percentage="$(printf "%.1f" "${ftl_mem_percentage_raw}")%" # Get Pi-hole (blocking) status - ftl_dns_port=$(GetFTLData "config" | jq .config.dns.port 2>/dev/null) + ftl_dns_port=$(echo "${padd_data}" | jq .config.dns_port 2>/dev/null) # Get FTL's current PID - ftlPID="$(echo "${sysinfo}" | jq .ftl.pid 2>/dev/null)" + ftlPID="$(echo "${padd_data}" | jq .pid 2>/dev/null)" fi @@ -579,15 +561,14 @@ fi GetVersionInformation() { out_of_date_flag=false - versions_raw=$(GetFTLData "info/version") # Gather DOCKER version information... # returns "null" if not running Pi-hole in Docker container - DOCKER_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.docker.local 2>/dev/null)" + DOCKER_VERSION="$(echo "${padd_data}" | jq --raw-output .version.docker.local 2>/dev/null)" # If PADD is running inside docker, immediately return without checking for updated component versions if [ ! "${DOCKER_VERSION}" = "null" ] ; then - GITHUB_DOCKER_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.docker.remote 2>/dev/null)" + GITHUB_DOCKER_VERSION="$(echo "${padd_data}" | jq --raw-output .version.docker.remote 2>/dev/null)" docker_version_converted="$(VersionConverter "${DOCKER_VERSION}")" docker_version_latest_converted="$(VersionConverter "${GITHUB_DOCKER_VERSION}")" @@ -604,11 +585,11 @@ GetVersionInformation() { fi # Gather core version information... - CORE_BRANCH="$(echo "${versions_raw}" | jq --raw-output .version.core.local.branch 2>/dev/null)" - CORE_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.core.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - GITHUB_CORE_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.core.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - CORE_HASH="$(echo "${versions_raw}" | jq --raw-output .version.core.local.hash 2>/dev/null)" - GITHUB_CORE_HASH="$(echo "${versions_raw}" | jq --raw-output .version.core.remote.hash 2>/dev/null)" + CORE_BRANCH="$(echo "${padd_data}" | jq --raw-output .version.core.local.branch 2>/dev/null)" + CORE_VERSION="$(echo "${padd_data}" | jq --raw-output .version.core.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_CORE_VERSION="$(echo "${padd_data}" | jq --raw-output .version.core.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + CORE_HASH="$(echo "${padd_data}" | jq --raw-output .version.core.local.hash 2>/dev/null)" + GITHUB_CORE_HASH="$(echo "${padd_data}" | jq --raw-output .version.core.remote.hash 2>/dev/null)" if [ "${CORE_BRANCH}" = "master" ]; then core_version_converted="$(VersionConverter "${CORE_VERSION}")" @@ -642,14 +623,14 @@ GetVersionInformation() { fi # Gather web version information... - WEB_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.web.local.version 2>/dev/null)" + WEB_VERSION="$(echo "${padd_data}" | jq --raw-output .version.web.local.version 2>/dev/null)" if [ ! "$WEB_VERSION" = "null" ]; then - WEB_BRANCH="$(echo "${versions_raw}" | jq --raw-output .version.web.local.branch 2>/dev/null)" - WEB_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.web.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - GITHUB_WEB_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.web.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - WEB_HASH="$(echo "${versions_raw}" | jq --raw-output .version.web.local.hash 2>/dev/null)" - GITHUB_WEB_HASH="$(echo "${versions_raw}" | jq --raw-output .version.web.remote.hash 2>/dev/null)" + WEB_BRANCH="$(echo "${padd_data}" | jq --raw-output .version.web.local.branch 2>/dev/null)" + WEB_VERSION="$(echo "${padd_data}" | jq --raw-output .version.web.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_WEB_VERSION="$(echo "${padd_data}" | jq --raw-output .version.web.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + WEB_HASH="$(echo "${padd_data}" | jq --raw-output .version.web.local.hash 2>/dev/null)" + GITHUB_WEB_HASH="$(echo "${padd_data}" | jq --raw-output .version.web.remote.hash 2>/dev/null)" if [ "${WEB_BRANCH}" = "master" ]; then web_version_converted="$(VersionConverter "${WEB_VERSION}")" @@ -689,11 +670,11 @@ GetVersionInformation() { fi # Gather FTL version information... - FTL_BRANCH="$(echo "${versions_raw}" | jq --raw-output .version.ftl.local.branch 2>/dev/null)" - FTL_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.ftl.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - GITHUB_FTL_VERSION="$(echo "${versions_raw}" | jq --raw-output .version.ftl.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - FTL_HASH="$(echo "${versions_raw}" | jq --raw-output .version.ftl.local.hash 2>/dev/null)" - GITHUB_FTL_HASH="$(echo "${versions_raw}" | jq --raw-output .version.ftl.remote.hash 2>/dev/null)" + FTL_BRANCH="$(echo "${padd_data}" | jq --raw-output .version.ftl.local.branch 2>/dev/null)" + FTL_VERSION="$(echo "${padd_data}" | jq --raw-output .version.ftl.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_FTL_VERSION="$(echo "${padd_data}" | jq --raw-output .version.ftl.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + FTL_HASH="$(echo "${padd_data}" | jq --raw-output .version.ftl.local.hash 2>/dev/null)" + GITHUB_FTL_HASH="$(echo "${padd_data}" | jq --raw-output .version.ftl.remote.hash 2>/dev/null)" if [ "${FTL_BRANCH}" = "master" ]; then @@ -1155,7 +1136,7 @@ BarGenerator() { echo "$out" } -# Checks the size of the screen and sets the value of $padd_size +# Checks the size of the screen and sets the value of ${padd_data}_size SizeChecker(){ # adding a tiny delay here to to give the kernel a bit time to # report new sizes correctly after a terminal resize @@ -1381,6 +1362,7 @@ OutputJSON() { printf "%b" "Establishing connection with FTL...\n" LoginAPI + GetAPIData GetSummaryInformation printf "%b" "{\"domains_being_blocked\":${domains_being_blocked_raw},\"dns_queries_today\":${dns_queries_today_raw},\"ads_blocked_today\":${ads_blocked_today_raw},\"ads_percentage_today\":${ads_percentage_today},\"clients\": ${clients}}" } @@ -1444,6 +1426,9 @@ StartupRoutine(){ moveXOffset; printf "%b" " [■·········] 10%\r" + # Request API data + GetAPIData + # Check for updates moveXOffset; printf "%b" " [■■········] 20%\r" moveXOffset; printf "%b" " [■■■·······] 30%\r" @@ -1472,12 +1457,16 @@ StartupRoutine(){ moveXOffset; printf "%b" "Establishing connection with FTL...\n" LoginAPI + # Request API data + moveXOffset; echo "- Requesting API information..." + GetAPIData + # Get our information for the first time moveXOffset; echo "- Gathering version info." GetVersionInformation moveXOffset; echo "- Gathering system info." GetSystemInformation - moveXOffset; echo "- Gathering Pi-hole info." + moveXOffset; echo "- Gathering CPU/DNS info." GetPiholeInformation GetSummaryInformation moveXOffset; echo "- Gathering network info." @@ -1487,7 +1476,7 @@ StartupRoutine(){ moveXOffset; echo " - Docker Tag ${DOCKER_VERSION}" else moveXOffset; echo " - Core $CORE_VERSION, Web $WEB_VERSION" - moveXOffset; echo " - FTL $FTL_VERSION, PADD $padd_version" + moveXOffset; echo " - FTL $FTL_VERSION, PADD ${padd_data}_version" fi else @@ -1507,13 +1496,16 @@ StartupRoutine(){ moveXOffset; printf "%b" "Establishing connection with FTL...\n" LoginAPI + # Request API data + moveXOffset; echo "- Requesting API information..." + GetAPIData # Get our information for the first time moveXOffset; echo "- Gathering version information..." GetVersionInformation moveXOffset; echo "- Gathering system information..." GetSystemInformation - moveXOffset; echo "- Gathering Pi-hole information..." + moveXOffset; echo "- Gathering CPU/DNS information..." GetSummaryInformation GetPiholeInformation moveXOffset; echo "- Gathering network information..." @@ -1526,7 +1518,7 @@ StartupRoutine(){ moveXOffset; echo " - Pi-hole Core $CORE_VERSION" moveXOffset; echo " - Web Admin $WEB_VERSION" moveXOffset; echo " - FTL $FTL_VERSION" - moveXOffset; echo " - PADD $padd_version" + moveXOffset; echo " - PADD ${padd_version}" fi fi @@ -1577,35 +1569,21 @@ NormalPADD() { Authenticate fi - # Get uptime, CPU load, temp, etc. every 5 seconds - if [ $((now - LastCheckSystemInformation)) -ge 5 ]; then - GetSystemInformation - LastCheckSystemInformation="${now}" - fi - - # Get cache info, last ad domain, blocking percentage, etc. every 5 seconds - if [ $((now - LastCheckSummaryInformation)) -ge 5 ]; then - GetSummaryInformation - LastCheckSummaryInformation="${now}" - fi - - # Get FTL status every 5 seconds - if [ $((now - LastCheckPiholeInformation)) -ge 5 ]; then - GetPiholeInformation - LastCheckPiholeInformation="${now}" - fi - - # Get IPv4 address, DNS servers, DNSSEC, hostname, DHCP status, interface traffic, etc. every 30 seconds - if [ $((now - LastCheckNetworkInformation)) -ge 30 ]; then - GetNetworkInformation - LastCheckNetworkInformation="${now}" + # Request API data + if [ $((now - LastCheckFullInformation)) -ge 30 ]; then + GetAPIData + GetNetworkInformation + GetVersionInformation + LastCheckFullInformation="${now}" + else + # Request only a subset of the data + GetAPIData "?full=false" fi - # Get Pi-hole components version information every 30 seconds - if [ $((now - LastCheckVersionInformation)) -ge 30 ]; then - GetVersionInformation - LastCheckVersionInformation="${now}" - fi + # Get uptime, CPU load, temp, etc. every 5 seconds + GetSystemInformation + GetSummaryInformation + GetPiholeInformation # Get PADD version information every 24hours if [ $((now - LastCheckPADDInformation)) -ge 86400 ]; then From 113ef44b3774f2696c3bf2ad82b0372b5dd0a54b Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 7 Aug 2024 20:25:11 +0200 Subject: [PATCH 63/81] Use jq only once for parsing the entire payload after querying the API Signed-off-by: DL6ER --- padd.sh | 143 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 76 insertions(+), 67 deletions(-) diff --git a/padd.sh b/padd.sh index 90fd5693..35990d95 100755 --- a/padd.sh +++ b/padd.sh @@ -265,38 +265,47 @@ GetFTLData() { ############################################# GETTERS ############################################## GetAPIData() { - padd_data=$(GetFTLData "padd" "$1") - echo "$padd_data" > data.json + local api_data + api_data=$(GetFTLData "padd" "$1") + # Iterate over all the leaf paths in the JSON object and creates key-value + # pairs in the format "key=value". Nested objects are flattened using the dot + # notation, e.g., { "a": { "b": 1 } } becomes "a.b=1". The resulting key-value + # pairs are then stored in the variable `padd_data`. + padd_data=$(echo "$api_data" | jq -r '[leaf_paths as $path | { "key": $path | join("."), "value": getpath($path) }] | map("\(.key)=\(.value|tostring)") | .[]') +} + +GetAPIValue() { + echo "$padd_data" | sed -n "s/^$1=//p" } GetSummaryInformation() { - clients=$(echo "${padd_data}" | jq .active_clients 2>/dev/null) + clients=$(GetAPIValue active_clients 2>/dev/null) - blocking_enabled=$(echo "${padd_data}" | jq .blocking 2>/dev/null) + blocking_enabled=$(GetAPIValue blocking 2>/dev/null) - domains_being_blocked_raw=$(echo "${padd_data}" | jq .gravity_size 2>/dev/null) + domains_being_blocked_raw=$(GetAPIValue gravity_size 2>/dev/null) domains_being_blocked=$(printf "%.f" "${domains_being_blocked_raw}") - dns_queries_today_raw=$(echo "${padd_data}" | jq .queries.total 2>/dev/null) + dns_queries_today_raw=$(GetAPIValue queries.total 2>/dev/null) dns_queries_today=$(printf "%.f" "${dns_queries_today_raw}") - ads_blocked_today_raw=$(echo "${padd_data}" | jq .queries.blocked 2>/dev/null) + ads_blocked_today_raw=$(GetAPIValue queries.blocked 2>/dev/null) ads_blocked_today=$(printf "%.f" "${ads_blocked_today_raw}") - ads_percentage_today_raw=$(echo "${padd_data}" | jq .queries.percent_blocked 2>/dev/null) + ads_percentage_today_raw=$(GetAPIValue queries.percent_blocked 2>/dev/null) ads_percentage_today=$(printf "%.1f" "${ads_percentage_today_raw}") - cache_size=$(echo "${padd_data}" | jq .cache.size 2>/dev/null) - cache_evictions=$(echo "${padd_data}" | jq .cache.evicted 2>/dev/null) - cache_inserts=$(echo "${padd_data}"| jq .cache.inserted 2>/dev/null) + cache_size=$(GetAPIValue cache.size 2>/dev/null) + cache_evictions=$(GetAPIValue cache.evicted 2>/dev/null) + cache_inserts=$(echo "${padd_data}"| GetAPIValue cache.inserted 2>/dev/null) - latest_blocked_raw=$(echo "${padd_data}" | jq --raw-output .recent_blocked 2>/dev/null) + latest_blocked_raw=$(GetAPIValue recent_blocked 2>/dev/null) - top_blocked_raw=$(echo "${padd_data}" | jq --raw-output .top_domain 2>/dev/null) + top_blocked_raw=$(GetAPIValue top_blocked 2>/dev/null) - top_domain_raw=$(echo "${padd_data}" | jq --raw-output .top_blocked 2>/dev/null) + top_domain_raw=$(GetAPIValue top_domain 2>/dev/null) - top_client_raw=$(echo "${padd_data}" | jq --raw-output .top_client 2>/dev/null) + top_client_raw=$(GetAPIValue top_client 2>/dev/null) } GetSystemInformation() { @@ -305,14 +314,14 @@ GetSystemInformation() { # in case FTL connection is down, system_uptime_raw need to be set to 0 otherwise convertUptime() will complain system_uptime_raw=0 else - system_uptime_raw=$(echo "${padd_data}" | jq .system.uptime 2>/dev/null) + system_uptime_raw=$(GetAPIValue system.uptime 2>/dev/null) fi # CPU temperature and unit # in case .sensors.cpu_temp returns 'null' we substitute with 0 - cpu_temp_raw=$(echo "${padd_data}" | jq '(.sensors.cpu_temp // 0)' 2>/dev/null) + cpu_temp_raw=$(GetAPIValue sensors.cpu_temp 2>/dev/null) cpu_temp=$(printf "%.1f" "${cpu_temp_raw}") - temp_unit=$(echo "${padd_data}" | jq --raw-output .sensors.unit 2>/dev/null) + temp_unit=$(echo "${padd_data}" | GetAPIValue sensors.unit 2>/dev/null) # Temp + Unit if [ "${temp_unit}" = "C" ]; then @@ -350,22 +359,22 @@ GetSystemInformation() { fi # CPU, load, heatmap - core_count=$(echo "${padd_data}" | jq .system.cpu.nprocs 2>/dev/null) - cpu_load_1=$(printf %.2f "$(echo "${padd_data}" | jq .system.cpu.load.raw[0] 2>/dev/null)") - cpu_load_5=$(printf %.2f "$(echo "${padd_data}" | jq .system.cpu.load.raw[1] 2>/dev/null)") - cpu_load_15=$(printf %.2f "$(echo "${padd_data}" | jq .system.cpu.load.raw[2] 2>/dev/null)") + core_count=$(GetAPIValue system.cpu.nprocs 2>/dev/null) + cpu_load_1=$(printf %.2f "$(GetAPIValue system.cpu.load.0 2>/dev/null)") + cpu_load_5=$(printf %.2f "$(GetAPIValue system.cpu.load.1 2>/dev/null)") + cpu_load_15=$(printf %.2f "$(GetAPIValue system.cpu.load.2 2>/dev/null)") cpu_load_1_heatmap=$(HeatmapGenerator "${cpu_load_1}" "${core_count}") cpu_load_5_heatmap=$(HeatmapGenerator "${cpu_load_5}" "${core_count}") cpu_load_15_heatmap=$(HeatmapGenerator "${cpu_load_15}" "${core_count}") - cpu_percent=$(printf %.1f "$(echo "${padd_data}" | jq .system.cpu.load.percent[0] 2>/dev/null)") + cpu_percent=$(printf %.1f "$(GetAPIValue system.cpu.load.percent.0 2>/dev/null)") # Memory use, heatmap and bar - memory_percent_raw="$(echo "${padd_data}" | jq '.system.memory.ram."%used"' 2>/dev/null)" + memory_percent_raw="$(GetAPIValue system.memory.ram.%used 2>/dev/null)" memory_percent=$(printf %.1f "${memory_percent_raw}") memory_heatmap="$(HeatmapGenerator "${memory_percent}")" # Get device model - sys_model="$(echo "${padd_data}" | jq --raw-output .host_model 2>/dev/null)" + sys_model="$(GetAPIValue host_model 2>/dev/null)" # DOCKER_VERSION is set during GetVersionInformation, so this needs to run first during startup if [ ! "${DOCKER_VERSION}" = "null" ]; then @@ -383,12 +392,12 @@ GetSystemInformation() { } GetNetworkInformation() { - gateway_v4_iface=$(echo "${padd_data}" | jq -r '.iface.v4.name') - gateway_v6_iface=$(echo "${padd_data}" | jq -r '.iface.v4.name') + gateway_v4_iface=$(GetAPIValue iface.v4.name) + gateway_v6_iface=$(GetAPIValue iface.v4.name) # Get IPv4 address of the default interface - pi_ip4_addrs="$(echo "${padd_data}" | jq --raw-output '.iface.v4.num_addrs' 2>/dev/null)" - pi_ip4_addr="$(echo "${padd_data}" | jq --raw-output '.iface.v4.addr' 2>/dev/null)" + pi_ip4_addrs="$(GetAPIValue iface.v4.num_addrs 2>/dev/null)" + pi_ip4_addr="$(GetAPIValue iface.v4.addr 2>/dev/null)" if [ "${pi_ip4_addrs}" -eq 0 ]; then # No IPv4 address available pi_ip4_addr="N/A" @@ -400,8 +409,8 @@ GetNetworkInformation() { fi # Get IPv6 address of the default interface - pi_ip6_addrs="$(echo "${padd_data}" | jq --raw-output '.iface.v6.num_addrs' 2>/dev/null)" - pi_ip6_addr="$(echo "${padd_data}" | jq --raw-output '.iface.v6.addr' 2>/dev/null)" + pi_ip6_addrs="$(GetAPIValue iface.v6.num_addrs 2>/dev/null)" + pi_ip6_addr="$(GetAPIValue iface.v6.addr 2>/dev/null)" if [ "${pi_ip6_addrs}" -eq 0 ]; then # No IPv6 address available pi_ip6_addr="N/A" @@ -416,11 +425,11 @@ GetNetworkInformation() { fi # Is Pi-Hole acting as the DHCP server? - DHCP_ACTIVE="$(echo "${padd_data}" | jq .config.dhcp_active 2>/dev/null )" + DHCP_ACTIVE="$(GetAPIValue config.dhcp_active 2>/dev/null )" if [ "${DHCP_ACTIVE}" = "true" ]; then - DHCP_START="$(echo "${padd_data}" | jq --raw-output .config.dhcp_start 2>/dev/null)" - DHCP_END="$(echo "${padd_data}" | jq --raw-output .config.dhcp_end 2>/dev/null)" + DHCP_START="$(GetAPIValue config.dhcp_start 2>/dev/null)" + DHCP_END="$(GetAPIValue config.dhcp_end 2>/dev/null)" dhcp_status="Enabled" dhcp_info=" Range: ${DHCP_START} - ${DHCP_END}" @@ -428,7 +437,7 @@ GetNetworkInformation() { dhcp_check_box=${check_box_good} # Is DHCP handling IPv6? - DHCP_IPv6="$(echo "${padd_data}" | jq --raw-output .config.dhcp_ipv6 2>/dev/null)" + DHCP_IPv6="$(GetAPIValue config.dhcp_ipv6 2>/dev/null)" if [ "${DHCP_IPv6}" = "true" ]; then dhcp_ipv6_status="Enabled" dhcp_ipv6_heatmap=${green_text} @@ -444,7 +453,7 @@ GetNetworkInformation() { dhcp_check_box=${check_box_bad} # Display the gateway address if DHCP is disabled - GATEWAY="$(echo "${padd_data}" | jq -r '.iface.v4.gw_addr' | head -n 1)" + GATEWAY="$(GetAPIValue iface.v4.gw_addr | head -n 1)" dhcp_info=" Router: ${GATEWAY}" dhcp_ipv6_status="N/A" dhcp_ipv6_heatmap=${yellow_text} @@ -452,11 +461,11 @@ GetNetworkInformation() { fi # Get hostname - pi_hostname="$(echo "${padd_data}" | jq --raw-output .node_name 2>/dev/null)" + pi_hostname="$(GetAPIValue node_name 2>/dev/null)" full_hostname=${pi_hostname} # when PI-hole is the DHCP server, append the domain to the hostname if [ "${DHCP_ACTIVE}" = "true" ]; then - PIHOLE_DOMAIN="$(echo "${padd_data}" | jq --raw-output .config.dns_domain 2>/dev/null)" + PIHOLE_DOMAIN="$(GetAPIValue config.dns_domain 2>/dev/null)" if [ -n "${PIHOLE_DOMAIN}" ]; then count=${pi_hostname}"."${PIHOLE_DOMAIN} count=${#count} @@ -467,7 +476,7 @@ GetNetworkInformation() { fi # Get the number of configured upstream DNS servers - dns_count="$(echo "${padd_data}" | jq --raw-output .config.dns_num_upstreams 2>/dev/null)" + dns_count="$(GetAPIValue config.dns_num_upstreams 2>/dev/null)" # if there's only one DNS server if [ "${dns_count}" -eq 1 ]; then dns_information="1 server" @@ -477,7 +486,7 @@ GetNetworkInformation() { # DNSSEC - DNSSEC="$(echo "${padd_data}" | jq .config.dns_dnssec 2>/dev/null)" + DNSSEC="$(GetAPIValue config.dns_dnssec 2>/dev/null)" if [ "${DNSSEC}" = "true" ]; then dnssec_status="Enabled" dnssec_heatmap=${green_text} @@ -487,7 +496,7 @@ GetNetworkInformation() { fi # Conditional forwarding - CONDITIONAL_FORWARDING="$(echo "${padd_data}" | jq .config.dns_revServer_active 2>/dev/null)" + CONDITIONAL_FORWARDING="$(GetAPIValue config.dns_revServer_active 2>/dev/null)" if [ "${CONDITIONAL_FORWARDING}" = "true" ]; then conditional_forwarding_status="Enabled" conditional_forwarding_heatmap=${green_text} @@ -498,12 +507,12 @@ GetNetworkInformation() { # Default interface data (use IPv4 interface - we cannot show both and assume they are the same) iface_name="${gateway_v4_iface}" - tx_bytes="$(echo "${padd_data}" | jq --raw-output '.iface.v4.tx_bytes.value' 2>/dev/null)" - tx_bytes_unit="$(echo "${padd_data}" | jq --raw-output '.iface.v4.tx_bytes.unit' 2>/dev/null)" + tx_bytes="$(GetAPIValue iface.v4.tx_bytes.value 2>/dev/null)" + tx_bytes_unit="$(GetAPIValue iface.v4.tx_bytes.unit 2>/dev/null)" tx_bytes=$(printf "%.1f %b" "${tx_bytes}" "${tx_bytes_unit}") - rx_bytes="$(echo "${padd_data}" | jq --raw-output '.iface.v4.rx_bytes.value' 2>/dev/null)" - rx_bytes_unit="$(echo "${padd_data}" | jq --raw-output '.iface.v4.rx_bytes.unit' 2>/dev/null)" + rx_bytes="$(GetAPIValue iface.v4.rx_bytes.value 2>/dev/null)" + rx_bytes_unit="$(GetAPIValue iface.v4.rx_bytes.unit 2>/dev/null)" rx_bytes=$(printf "%.1f %b" "${rx_bytes}" "${rx_bytes_unit}") # If IPv4 and IPv6 interfaces are not the same, add a "*" to the interface @@ -531,14 +540,14 @@ GetPiholeInformation() { ftl_heatmap=${green_text} ftl_check_box=${check_box_good} # Get FTL CPU and memory usage - ftl_cpu_raw="$(echo "${padd_data}" | jq '."%cpu"' 2>/dev/null)" - ftl_mem_percentage_raw="$(echo "${padd_data}" | jq '."%mem"' 2>/dev/null)" + ftl_cpu_raw="$(GetAPIValue "%cpu" 2>/dev/null)" + ftl_mem_percentage_raw="$(GetAPIValue "%mem" 2>/dev/null)" ftl_cpu="$(printf "%.1f" "${ftl_cpu_raw}")%" ftl_mem_percentage="$(printf "%.1f" "${ftl_mem_percentage_raw}")%" # Get Pi-hole (blocking) status - ftl_dns_port=$(echo "${padd_data}" | jq .config.dns_port 2>/dev/null) + ftl_dns_port=$(GetAPIValue config.dns_port 2>/dev/null) # Get FTL's current PID - ftlPID="$(echo "${padd_data}" | jq .pid 2>/dev/null)" + ftlPID="$(GetAPIValue pid 2>/dev/null)" fi @@ -564,11 +573,11 @@ GetVersionInformation() { # Gather DOCKER version information... # returns "null" if not running Pi-hole in Docker container - DOCKER_VERSION="$(echo "${padd_data}" | jq --raw-output .version.docker.local 2>/dev/null)" + DOCKER_VERSION="$(GetAPIValue version.docker.local 2>/dev/null)" # If PADD is running inside docker, immediately return without checking for updated component versions if [ ! "${DOCKER_VERSION}" = "null" ] ; then - GITHUB_DOCKER_VERSION="$(echo "${padd_data}" | jq --raw-output .version.docker.remote 2>/dev/null)" + GITHUB_DOCKER_VERSION="$(GetAPIValue version.docker.remote 2>/dev/null)" docker_version_converted="$(VersionConverter "${DOCKER_VERSION}")" docker_version_latest_converted="$(VersionConverter "${GITHUB_DOCKER_VERSION}")" @@ -585,11 +594,11 @@ GetVersionInformation() { fi # Gather core version information... - CORE_BRANCH="$(echo "${padd_data}" | jq --raw-output .version.core.local.branch 2>/dev/null)" - CORE_VERSION="$(echo "${padd_data}" | jq --raw-output .version.core.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - GITHUB_CORE_VERSION="$(echo "${padd_data}" | jq --raw-output .version.core.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - CORE_HASH="$(echo "${padd_data}" | jq --raw-output .version.core.local.hash 2>/dev/null)" - GITHUB_CORE_HASH="$(echo "${padd_data}" | jq --raw-output .version.core.remote.hash 2>/dev/null)" + CORE_BRANCH="$(GetAPIValue version.core.local.branch 2>/dev/null)" + CORE_VERSION="$(GetAPIValue version.core.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_CORE_VERSION="$(GetAPIValue version.core.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + CORE_HASH="$(GetAPIValue version.core.local.hash 2>/dev/null)" + GITHUB_CORE_HASH="$(GetAPIValue version.core.remote.hash 2>/dev/null)" if [ "${CORE_BRANCH}" = "master" ]; then core_version_converted="$(VersionConverter "${CORE_VERSION}")" @@ -623,14 +632,14 @@ GetVersionInformation() { fi # Gather web version information... - WEB_VERSION="$(echo "${padd_data}" | jq --raw-output .version.web.local.version 2>/dev/null)" + WEB_VERSION="$(GetAPIValue version.web.local.version 2>/dev/null)" if [ ! "$WEB_VERSION" = "null" ]; then - WEB_BRANCH="$(echo "${padd_data}" | jq --raw-output .version.web.local.branch 2>/dev/null)" - WEB_VERSION="$(echo "${padd_data}" | jq --raw-output .version.web.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - GITHUB_WEB_VERSION="$(echo "${padd_data}" | jq --raw-output .version.web.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - WEB_HASH="$(echo "${padd_data}" | jq --raw-output .version.web.local.hash 2>/dev/null)" - GITHUB_WEB_HASH="$(echo "${padd_data}" | jq --raw-output .version.web.remote.hash 2>/dev/null)" + WEB_BRANCH="$(GetAPIValue version.web.local.branch 2>/dev/null)" + WEB_VERSION="$(GetAPIValue version.web.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_WEB_VERSION="$(GetAPIValue version.web.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + WEB_HASH="$(GetAPIValue version.web.local.hash 2>/dev/null)" + GITHUB_WEB_HASH="$(GetAPIValue version.web.remote.hash 2>/dev/null)" if [ "${WEB_BRANCH}" = "master" ]; then web_version_converted="$(VersionConverter "${WEB_VERSION}")" @@ -670,11 +679,11 @@ GetVersionInformation() { fi # Gather FTL version information... - FTL_BRANCH="$(echo "${padd_data}" | jq --raw-output .version.ftl.local.branch 2>/dev/null)" - FTL_VERSION="$(echo "${padd_data}" | jq --raw-output .version.ftl.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - GITHUB_FTL_VERSION="$(echo "${padd_data}" | jq --raw-output .version.ftl.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - FTL_HASH="$(echo "${padd_data}" | jq --raw-output .version.ftl.local.hash 2>/dev/null)" - GITHUB_FTL_HASH="$(echo "${padd_data}" | jq --raw-output .version.ftl.remote.hash 2>/dev/null)" + FTL_BRANCH="$(GetAPIValue version.ftl.local.branch 2>/dev/null)" + FTL_VERSION="$(GetAPIValue version.ftl.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_FTL_VERSION="$(GetAPIValue version.ftl.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + FTL_HASH="$(GetAPIValue version.ftl.local.hash 2>/dev/null)" + GITHUB_FTL_HASH="$(GetAPIValue version.ftl.remote.hash 2>/dev/null)" if [ "${FTL_BRANCH}" = "master" ]; then From 1310ea8f48560922297d73226328b517d95aafe5 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 7 Aug 2024 20:59:41 +0200 Subject: [PATCH 64/81] Redefine jq's paths() as its built-in function skips all pais with values null and false Signed-off-by: DL6ER --- padd.sh | 137 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 70 insertions(+), 67 deletions(-) diff --git a/padd.sh b/padd.sh index 35990d95..b9cbf28a 100755 --- a/padd.sh +++ b/padd.sh @@ -269,43 +269,46 @@ GetAPIData() { api_data=$(GetFTLData "padd" "$1") # Iterate over all the leaf paths in the JSON object and creates key-value # pairs in the format "key=value". Nested objects are flattened using the dot - # notation, e.g., { "a": { "b": 1 } } becomes "a.b=1". The resulting key-value - # pairs are then stored in the variable `padd_data`. - padd_data=$(echo "$api_data" | jq -r '[leaf_paths as $path | { "key": $path | join("."), "value": getpath($path) }] | map("\(.key)=\(.value|tostring)") | .[]') + # notation, e.g., { "a": { "b": 1 } } becomes "a.b=1". + # We have to redefine the function here, as it it is broken in jq, see + # https://github.com/jqlang/jq/issues/2872 + # We cannot use leaf_paths here as it was deprecated in jq 1.6 and removed in + # current master + padd_data=$(echo "$api_data" | jq -r 'def paths(node_filter): . as $dot|paths|select(. as $p|$dot|getpath($p)|node_filter|true); paths(scalars) as $p | [$p | join(".")] + [getpath($p)] | join("=")' 2>/dev/null) } GetAPIValue() { - echo "$padd_data" | sed -n "s/^$1=//p" + echo "$padd_data" | sed -n "s/^$1=//p" 2>/dev/null } GetSummaryInformation() { - clients=$(GetAPIValue active_clients 2>/dev/null) + clients=$(GetAPIValue active_clients) - blocking_enabled=$(GetAPIValue blocking 2>/dev/null) + blocking_enabled=$(GetAPIValue blocking) - domains_being_blocked_raw=$(GetAPIValue gravity_size 2>/dev/null) + domains_being_blocked_raw=$(GetAPIValue gravity_size) domains_being_blocked=$(printf "%.f" "${domains_being_blocked_raw}") - dns_queries_today_raw=$(GetAPIValue queries.total 2>/dev/null) + dns_queries_today_raw=$(GetAPIValue queries.total) dns_queries_today=$(printf "%.f" "${dns_queries_today_raw}") - ads_blocked_today_raw=$(GetAPIValue queries.blocked 2>/dev/null) + ads_blocked_today_raw=$(GetAPIValue queries.blocked) ads_blocked_today=$(printf "%.f" "${ads_blocked_today_raw}") - ads_percentage_today_raw=$(GetAPIValue queries.percent_blocked 2>/dev/null) + ads_percentage_today_raw=$(GetAPIValue queries.percent_blocked) ads_percentage_today=$(printf "%.1f" "${ads_percentage_today_raw}") - cache_size=$(GetAPIValue cache.size 2>/dev/null) - cache_evictions=$(GetAPIValue cache.evicted 2>/dev/null) - cache_inserts=$(echo "${padd_data}"| GetAPIValue cache.inserted 2>/dev/null) + cache_size=$(GetAPIValue cache.size) + cache_evictions=$(GetAPIValue cache.evicted) + cache_inserts=$(echo "${padd_data}"| GetAPIValue cache.inserted) - latest_blocked_raw=$(GetAPIValue recent_blocked 2>/dev/null) + latest_blocked_raw=$(GetAPIValue recent_blocked) - top_blocked_raw=$(GetAPIValue top_blocked 2>/dev/null) + top_blocked_raw=$(GetAPIValue top_blocked) - top_domain_raw=$(GetAPIValue top_domain 2>/dev/null) + top_domain_raw=$(GetAPIValue top_domain) - top_client_raw=$(GetAPIValue top_client 2>/dev/null) + top_client_raw=$(GetAPIValue top_client) } GetSystemInformation() { @@ -314,14 +317,14 @@ GetSystemInformation() { # in case FTL connection is down, system_uptime_raw need to be set to 0 otherwise convertUptime() will complain system_uptime_raw=0 else - system_uptime_raw=$(GetAPIValue system.uptime 2>/dev/null) + system_uptime_raw=$(GetAPIValue system.uptime) fi # CPU temperature and unit # in case .sensors.cpu_temp returns 'null' we substitute with 0 - cpu_temp_raw=$(GetAPIValue sensors.cpu_temp 2>/dev/null) + cpu_temp_raw=$(GetAPIValue sensors.cpu_temp) cpu_temp=$(printf "%.1f" "${cpu_temp_raw}") - temp_unit=$(echo "${padd_data}" | GetAPIValue sensors.unit 2>/dev/null) + temp_unit=$(echo "${padd_data}" | GetAPIValue sensors.unit) # Temp + Unit if [ "${temp_unit}" = "C" ]; then @@ -359,22 +362,22 @@ GetSystemInformation() { fi # CPU, load, heatmap - core_count=$(GetAPIValue system.cpu.nprocs 2>/dev/null) - cpu_load_1=$(printf %.2f "$(GetAPIValue system.cpu.load.0 2>/dev/null)") - cpu_load_5=$(printf %.2f "$(GetAPIValue system.cpu.load.1 2>/dev/null)") - cpu_load_15=$(printf %.2f "$(GetAPIValue system.cpu.load.2 2>/dev/null)") + core_count=$(GetAPIValue system.cpu.nprocs) + cpu_load_1=$(printf %.2f "$(GetAPIValue system.cpu.load.0)") + cpu_load_5=$(printf %.2f "$(GetAPIValue system.cpu.load.1)") + cpu_load_15=$(printf %.2f "$(GetAPIValue system.cpu.load.2)") cpu_load_1_heatmap=$(HeatmapGenerator "${cpu_load_1}" "${core_count}") cpu_load_5_heatmap=$(HeatmapGenerator "${cpu_load_5}" "${core_count}") cpu_load_15_heatmap=$(HeatmapGenerator "${cpu_load_15}" "${core_count}") - cpu_percent=$(printf %.1f "$(GetAPIValue system.cpu.load.percent.0 2>/dev/null)") + cpu_percent=$(printf %.1f "$(GetAPIValue system.cpu.load.percent.0)") # Memory use, heatmap and bar - memory_percent_raw="$(GetAPIValue system.memory.ram.%used 2>/dev/null)" + memory_percent_raw="$(GetAPIValue system.memory.ram.%used)" memory_percent=$(printf %.1f "${memory_percent_raw}") memory_heatmap="$(HeatmapGenerator "${memory_percent}")" # Get device model - sys_model="$(GetAPIValue host_model 2>/dev/null)" + sys_model="$(GetAPIValue host_model)" # DOCKER_VERSION is set during GetVersionInformation, so this needs to run first during startup if [ ! "${DOCKER_VERSION}" = "null" ]; then @@ -396,8 +399,8 @@ GetNetworkInformation() { gateway_v6_iface=$(GetAPIValue iface.v4.name) # Get IPv4 address of the default interface - pi_ip4_addrs="$(GetAPIValue iface.v4.num_addrs 2>/dev/null)" - pi_ip4_addr="$(GetAPIValue iface.v4.addr 2>/dev/null)" + pi_ip4_addrs="$(GetAPIValue iface.v4.num_addrs)" + pi_ip4_addr="$(GetAPIValue iface.v4.addr)" if [ "${pi_ip4_addrs}" -eq 0 ]; then # No IPv4 address available pi_ip4_addr="N/A" @@ -409,8 +412,8 @@ GetNetworkInformation() { fi # Get IPv6 address of the default interface - pi_ip6_addrs="$(GetAPIValue iface.v6.num_addrs 2>/dev/null)" - pi_ip6_addr="$(GetAPIValue iface.v6.addr 2>/dev/null)" + pi_ip6_addrs="$(GetAPIValue iface.v6.num_addrs)" + pi_ip6_addr="$(GetAPIValue iface.v6.addr)" if [ "${pi_ip6_addrs}" -eq 0 ]; then # No IPv6 address available pi_ip6_addr="N/A" @@ -425,11 +428,11 @@ GetNetworkInformation() { fi # Is Pi-Hole acting as the DHCP server? - DHCP_ACTIVE="$(GetAPIValue config.dhcp_active 2>/dev/null )" + DHCP_ACTIVE="$(GetAPIValue config.dhcp_active )" if [ "${DHCP_ACTIVE}" = "true" ]; then - DHCP_START="$(GetAPIValue config.dhcp_start 2>/dev/null)" - DHCP_END="$(GetAPIValue config.dhcp_end 2>/dev/null)" + DHCP_START="$(GetAPIValue config.dhcp_start)" + DHCP_END="$(GetAPIValue config.dhcp_end)" dhcp_status="Enabled" dhcp_info=" Range: ${DHCP_START} - ${DHCP_END}" @@ -437,7 +440,7 @@ GetNetworkInformation() { dhcp_check_box=${check_box_good} # Is DHCP handling IPv6? - DHCP_IPv6="$(GetAPIValue config.dhcp_ipv6 2>/dev/null)" + DHCP_IPv6="$(GetAPIValue config.dhcp_ipv6)" if [ "${DHCP_IPv6}" = "true" ]; then dhcp_ipv6_status="Enabled" dhcp_ipv6_heatmap=${green_text} @@ -461,11 +464,11 @@ GetNetworkInformation() { fi # Get hostname - pi_hostname="$(GetAPIValue node_name 2>/dev/null)" + pi_hostname="$(GetAPIValue node_name)" full_hostname=${pi_hostname} # when PI-hole is the DHCP server, append the domain to the hostname if [ "${DHCP_ACTIVE}" = "true" ]; then - PIHOLE_DOMAIN="$(GetAPIValue config.dns_domain 2>/dev/null)" + PIHOLE_DOMAIN="$(GetAPIValue config.dns_domain)" if [ -n "${PIHOLE_DOMAIN}" ]; then count=${pi_hostname}"."${PIHOLE_DOMAIN} count=${#count} @@ -476,7 +479,7 @@ GetNetworkInformation() { fi # Get the number of configured upstream DNS servers - dns_count="$(GetAPIValue config.dns_num_upstreams 2>/dev/null)" + dns_count="$(GetAPIValue config.dns_num_upstreams)" # if there's only one DNS server if [ "${dns_count}" -eq 1 ]; then dns_information="1 server" @@ -486,7 +489,7 @@ GetNetworkInformation() { # DNSSEC - DNSSEC="$(GetAPIValue config.dns_dnssec 2>/dev/null)" + DNSSEC="$(GetAPIValue config.dns_dnssec)" if [ "${DNSSEC}" = "true" ]; then dnssec_status="Enabled" dnssec_heatmap=${green_text} @@ -496,7 +499,7 @@ GetNetworkInformation() { fi # Conditional forwarding - CONDITIONAL_FORWARDING="$(GetAPIValue config.dns_revServer_active 2>/dev/null)" + CONDITIONAL_FORWARDING="$(GetAPIValue config.dns_revServer_active)" if [ "${CONDITIONAL_FORWARDING}" = "true" ]; then conditional_forwarding_status="Enabled" conditional_forwarding_heatmap=${green_text} @@ -507,12 +510,12 @@ GetNetworkInformation() { # Default interface data (use IPv4 interface - we cannot show both and assume they are the same) iface_name="${gateway_v4_iface}" - tx_bytes="$(GetAPIValue iface.v4.tx_bytes.value 2>/dev/null)" - tx_bytes_unit="$(GetAPIValue iface.v4.tx_bytes.unit 2>/dev/null)" + tx_bytes="$(GetAPIValue iface.v4.tx_bytes.value)" + tx_bytes_unit="$(GetAPIValue iface.v4.tx_bytes.unit)" tx_bytes=$(printf "%.1f %b" "${tx_bytes}" "${tx_bytes_unit}") - rx_bytes="$(GetAPIValue iface.v4.rx_bytes.value 2>/dev/null)" - rx_bytes_unit="$(GetAPIValue iface.v4.rx_bytes.unit 2>/dev/null)" + rx_bytes="$(GetAPIValue iface.v4.rx_bytes.value)" + rx_bytes_unit="$(GetAPIValue iface.v4.rx_bytes.unit)" rx_bytes=$(printf "%.1f %b" "${rx_bytes}" "${rx_bytes_unit}") # If IPv4 and IPv6 interfaces are not the same, add a "*" to the interface @@ -540,14 +543,14 @@ GetPiholeInformation() { ftl_heatmap=${green_text} ftl_check_box=${check_box_good} # Get FTL CPU and memory usage - ftl_cpu_raw="$(GetAPIValue "%cpu" 2>/dev/null)" - ftl_mem_percentage_raw="$(GetAPIValue "%mem" 2>/dev/null)" + ftl_cpu_raw="$(GetAPIValue "%cpu")" + ftl_mem_percentage_raw="$(GetAPIValue "%mem")" ftl_cpu="$(printf "%.1f" "${ftl_cpu_raw}")%" ftl_mem_percentage="$(printf "%.1f" "${ftl_mem_percentage_raw}")%" # Get Pi-hole (blocking) status - ftl_dns_port=$(GetAPIValue config.dns_port 2>/dev/null) + ftl_dns_port=$(GetAPIValue config.dns_port) # Get FTL's current PID - ftlPID="$(GetAPIValue pid 2>/dev/null)" + ftlPID="$(GetAPIValue pid)" fi @@ -573,11 +576,11 @@ GetVersionInformation() { # Gather DOCKER version information... # returns "null" if not running Pi-hole in Docker container - DOCKER_VERSION="$(GetAPIValue version.docker.local 2>/dev/null)" + DOCKER_VERSION="$(GetAPIValue version.docker.local)" # If PADD is running inside docker, immediately return without checking for updated component versions if [ ! "${DOCKER_VERSION}" = "null" ] ; then - GITHUB_DOCKER_VERSION="$(GetAPIValue version.docker.remote 2>/dev/null)" + GITHUB_DOCKER_VERSION="$(GetAPIValue version.docker.remote)" docker_version_converted="$(VersionConverter "${DOCKER_VERSION}")" docker_version_latest_converted="$(VersionConverter "${GITHUB_DOCKER_VERSION}")" @@ -594,11 +597,11 @@ GetVersionInformation() { fi # Gather core version information... - CORE_BRANCH="$(GetAPIValue version.core.local.branch 2>/dev/null)" - CORE_VERSION="$(GetAPIValue version.core.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - GITHUB_CORE_VERSION="$(GetAPIValue version.core.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - CORE_HASH="$(GetAPIValue version.core.local.hash 2>/dev/null)" - GITHUB_CORE_HASH="$(GetAPIValue version.core.remote.hash 2>/dev/null)" + CORE_BRANCH="$(GetAPIValue version.core.local.branch)" + CORE_VERSION="$(GetAPIValue version.core.local.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_CORE_VERSION="$(GetAPIValue version.core.remmote.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + CORE_HASH="$(GetAPIValue version.core.local.hash)" + GITHUB_CORE_HASH="$(GetAPIValue version.core.remote.hash)" if [ "${CORE_BRANCH}" = "master" ]; then core_version_converted="$(VersionConverter "${CORE_VERSION}")" @@ -632,14 +635,14 @@ GetVersionInformation() { fi # Gather web version information... - WEB_VERSION="$(GetAPIValue version.web.local.version 2>/dev/null)" + WEB_VERSION="$(GetAPIValue version.web.local.version)" if [ ! "$WEB_VERSION" = "null" ]; then - WEB_BRANCH="$(GetAPIValue version.web.local.branch 2>/dev/null)" - WEB_VERSION="$(GetAPIValue version.web.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - GITHUB_WEB_VERSION="$(GetAPIValue version.web.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - WEB_HASH="$(GetAPIValue version.web.local.hash 2>/dev/null)" - GITHUB_WEB_HASH="$(GetAPIValue version.web.remote.hash 2>/dev/null)" + WEB_BRANCH="$(GetAPIValue version.web.local.branch)" + WEB_VERSION="$(GetAPIValue version.web.local.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_WEB_VERSION="$(GetAPIValue version.web.remmote.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + WEB_HASH="$(GetAPIValue version.web.local.hash)" + GITHUB_WEB_HASH="$(GetAPIValue version.web.remote.hash)" if [ "${WEB_BRANCH}" = "master" ]; then web_version_converted="$(VersionConverter "${WEB_VERSION}")" @@ -679,11 +682,11 @@ GetVersionInformation() { fi # Gather FTL version information... - FTL_BRANCH="$(GetAPIValue version.ftl.local.branch 2>/dev/null)" - FTL_VERSION="$(GetAPIValue version.ftl.local.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - GITHUB_FTL_VERSION="$(GetAPIValue version.ftl.remmote.version 2>/dev/null | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - FTL_HASH="$(GetAPIValue version.ftl.local.hash 2>/dev/null)" - GITHUB_FTL_HASH="$(GetAPIValue version.ftl.remote.hash 2>/dev/null)" + FTL_BRANCH="$(GetAPIValue version.ftl.local.branch)" + FTL_VERSION="$(GetAPIValue version.ftl.local.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_FTL_VERSION="$(GetAPIValue version.ftl.remmote.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + FTL_HASH="$(GetAPIValue version.ftl.local.hash)" + GITHUB_FTL_HASH="$(GetAPIValue version.ftl.remote.hash)" if [ "${FTL_BRANCH}" = "master" ]; then @@ -1315,7 +1318,7 @@ secretRead() { unset key unset charcount charcount=0 - while key=$(dd ibs=1 count=1 2>/dev/null); do #read one byte of input + while key=$(dd ibs=1 count=1); do #read one byte of input if [ "${key}" = "$(printf '\0' | tr -d '\0')" ] ; then # Enter - accept password break From f1c3382bdaa277704c79366e5c08dcc6542d679b Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Wed, 7 Aug 2024 22:49:37 -0300 Subject: [PATCH 65/81] Using `paths(scalars | true)` to return `null` and `false` values. We also check if the value is exactly `null` and, in this case, return the string "null", as jq would return an empty string for nulls. Signed-off-by: RD WebDesign --- padd.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/padd.sh b/padd.sh index b9cbf28a..2d3e6fb9 100755 --- a/padd.sh +++ b/padd.sh @@ -267,14 +267,16 @@ GetFTLData() { GetAPIData() { local api_data api_data=$(GetFTLData "padd" "$1") + # Iterate over all the leaf paths in the JSON object and creates key-value # pairs in the format "key=value". Nested objects are flattened using the dot # notation, e.g., { "a": { "b": 1 } } becomes "a.b=1". - # We have to redefine the function here, as it it is broken in jq, see - # https://github.com/jqlang/jq/issues/2872 # We cannot use leaf_paths here as it was deprecated in jq 1.6 and removed in # current master - padd_data=$(echo "$api_data" | jq -r 'def paths(node_filter): . as $dot|paths|select(. as $p|$dot|getpath($p)|node_filter|true); paths(scalars) as $p | [$p | join(".")] + [getpath($p)] | join("=")' 2>/dev/null) + # Using "paths(scalars | true)" will return null and false values. + # We also check if the value is exactly `null` and, in this case, return the + # string "null", as jq would return an empty string for nulls. + padd_data=$(echo "$api_data" | jq -r 'paths(scalars | true) as $p | [$p | join(".")] + [if getpath($p)!=null then getpath($p) else "null" end] | join("=")' 2>/dev/null) } GetAPIValue() { From 285f387fe9ef93e957f4ff2b587c6742ed249f7d Mon Sep 17 00:00:00 2001 From: yubiuser Date: Fri, 9 Aug 2024 14:41:33 +0200 Subject: [PATCH 66/81] Rename functions to clarify their use Signed-off-by: yubiuser --- padd.sh | 164 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 82 insertions(+), 82 deletions(-) diff --git a/padd.sh b/padd.sh index 2d3e6fb9..8cc8d066 100755 --- a/padd.sh +++ b/padd.sh @@ -264,9 +264,9 @@ GetFTLData() { ############################################# GETTERS ############################################## -GetAPIData() { - local api_data - api_data=$(GetFTLData "padd" "$1") +GetPADDData() { + local response + response=$(GetFTLData "padd" "$1") # Iterate over all the leaf paths in the JSON object and creates key-value # pairs in the format "key=value". Nested objects are flattened using the dot @@ -276,41 +276,41 @@ GetAPIData() { # Using "paths(scalars | true)" will return null and false values. # We also check if the value is exactly `null` and, in this case, return the # string "null", as jq would return an empty string for nulls. - padd_data=$(echo "$api_data" | jq -r 'paths(scalars | true) as $p | [$p | join(".")] + [if getpath($p)!=null then getpath($p) else "null" end] | join("=")' 2>/dev/null) + padd_data=$(echo "$response" | jq -r 'paths(scalars | true) as $p | [$p | join(".")] + [if getpath($p)!=null then getpath($p) else "null" end] | join("=")' 2>/dev/null) } -GetAPIValue() { +GetPADDValue() { echo "$padd_data" | sed -n "s/^$1=//p" 2>/dev/null } GetSummaryInformation() { - clients=$(GetAPIValue active_clients) + clients=$(GetPADDValue active_clients) - blocking_enabled=$(GetAPIValue blocking) + blocking_enabled=$(GetPADDValue blocking) - domains_being_blocked_raw=$(GetAPIValue gravity_size) + domains_being_blocked_raw=$(GetPADDValue gravity_size) domains_being_blocked=$(printf "%.f" "${domains_being_blocked_raw}") - dns_queries_today_raw=$(GetAPIValue queries.total) + dns_queries_today_raw=$(GetPADDValue queries.total) dns_queries_today=$(printf "%.f" "${dns_queries_today_raw}") - ads_blocked_today_raw=$(GetAPIValue queries.blocked) + ads_blocked_today_raw=$(GetPADDValue queries.blocked) ads_blocked_today=$(printf "%.f" "${ads_blocked_today_raw}") - ads_percentage_today_raw=$(GetAPIValue queries.percent_blocked) + ads_percentage_today_raw=$(GetPADDValue queries.percent_blocked) ads_percentage_today=$(printf "%.1f" "${ads_percentage_today_raw}") - cache_size=$(GetAPIValue cache.size) - cache_evictions=$(GetAPIValue cache.evicted) - cache_inserts=$(echo "${padd_data}"| GetAPIValue cache.inserted) + cache_size=$(GetPADDValue cache.size) + cache_evictions=$(GetPADDValue cache.evicted) + cache_inserts=$(echo "${padd_data}"| GetPADDValue cache.inserted) - latest_blocked_raw=$(GetAPIValue recent_blocked) + latest_blocked_raw=$(GetPADDValue recent_blocked) - top_blocked_raw=$(GetAPIValue top_blocked) + top_blocked_raw=$(GetPADDValue top_blocked) - top_domain_raw=$(GetAPIValue top_domain) + top_domain_raw=$(GetPADDValue top_domain) - top_client_raw=$(GetAPIValue top_client) + top_client_raw=$(GetPADDValue top_client) } GetSystemInformation() { @@ -319,14 +319,14 @@ GetSystemInformation() { # in case FTL connection is down, system_uptime_raw need to be set to 0 otherwise convertUptime() will complain system_uptime_raw=0 else - system_uptime_raw=$(GetAPIValue system.uptime) + system_uptime_raw=$(GetPADDValue system.uptime) fi # CPU temperature and unit # in case .sensors.cpu_temp returns 'null' we substitute with 0 - cpu_temp_raw=$(GetAPIValue sensors.cpu_temp) + cpu_temp_raw=$(GetPADDValue sensors.cpu_temp) cpu_temp=$(printf "%.1f" "${cpu_temp_raw}") - temp_unit=$(echo "${padd_data}" | GetAPIValue sensors.unit) + temp_unit=$(echo "${padd_data}" | GetPADDValue sensors.unit) # Temp + Unit if [ "${temp_unit}" = "C" ]; then @@ -364,22 +364,22 @@ GetSystemInformation() { fi # CPU, load, heatmap - core_count=$(GetAPIValue system.cpu.nprocs) - cpu_load_1=$(printf %.2f "$(GetAPIValue system.cpu.load.0)") - cpu_load_5=$(printf %.2f "$(GetAPIValue system.cpu.load.1)") - cpu_load_15=$(printf %.2f "$(GetAPIValue system.cpu.load.2)") + core_count=$(GetPADDValue system.cpu.nprocs) + cpu_load_1=$(printf %.2f "$(GetPADDValue system.cpu.load.0)") + cpu_load_5=$(printf %.2f "$(GetPADDValue system.cpu.load.1)") + cpu_load_15=$(printf %.2f "$(GetPADDValue system.cpu.load.2)") cpu_load_1_heatmap=$(HeatmapGenerator "${cpu_load_1}" "${core_count}") cpu_load_5_heatmap=$(HeatmapGenerator "${cpu_load_5}" "${core_count}") cpu_load_15_heatmap=$(HeatmapGenerator "${cpu_load_15}" "${core_count}") - cpu_percent=$(printf %.1f "$(GetAPIValue system.cpu.load.percent.0)") + cpu_percent=$(printf %.1f "$(GetPADDValue system.cpu.load.percent.0)") # Memory use, heatmap and bar - memory_percent_raw="$(GetAPIValue system.memory.ram.%used)" + memory_percent_raw="$(GetPADDValue system.memory.ram.%used)" memory_percent=$(printf %.1f "${memory_percent_raw}") memory_heatmap="$(HeatmapGenerator "${memory_percent}")" # Get device model - sys_model="$(GetAPIValue host_model)" + sys_model="$(GetPADDValue host_model)" # DOCKER_VERSION is set during GetVersionInformation, so this needs to run first during startup if [ ! "${DOCKER_VERSION}" = "null" ]; then @@ -397,12 +397,12 @@ GetSystemInformation() { } GetNetworkInformation() { - gateway_v4_iface=$(GetAPIValue iface.v4.name) - gateway_v6_iface=$(GetAPIValue iface.v4.name) + gateway_v4_iface=$(GetPADDValue iface.v4.name) + gateway_v6_iface=$(GetPADDValue iface.v4.name) # Get IPv4 address of the default interface - pi_ip4_addrs="$(GetAPIValue iface.v4.num_addrs)" - pi_ip4_addr="$(GetAPIValue iface.v4.addr)" + pi_ip4_addrs="$(GetPADDValue iface.v4.num_addrs)" + pi_ip4_addr="$(GetPADDValue iface.v4.addr)" if [ "${pi_ip4_addrs}" -eq 0 ]; then # No IPv4 address available pi_ip4_addr="N/A" @@ -414,8 +414,8 @@ GetNetworkInformation() { fi # Get IPv6 address of the default interface - pi_ip6_addrs="$(GetAPIValue iface.v6.num_addrs)" - pi_ip6_addr="$(GetAPIValue iface.v6.addr)" + pi_ip6_addrs="$(GetPADDValue iface.v6.num_addrs)" + pi_ip6_addr="$(GetPADDValue iface.v6.addr)" if [ "${pi_ip6_addrs}" -eq 0 ]; then # No IPv6 address available pi_ip6_addr="N/A" @@ -430,11 +430,11 @@ GetNetworkInformation() { fi # Is Pi-Hole acting as the DHCP server? - DHCP_ACTIVE="$(GetAPIValue config.dhcp_active )" + DHCP_ACTIVE="$(GetPADDValue config.dhcp_active )" if [ "${DHCP_ACTIVE}" = "true" ]; then - DHCP_START="$(GetAPIValue config.dhcp_start)" - DHCP_END="$(GetAPIValue config.dhcp_end)" + DHCP_START="$(GetPADDValue config.dhcp_start)" + DHCP_END="$(GetPADDValue config.dhcp_end)" dhcp_status="Enabled" dhcp_info=" Range: ${DHCP_START} - ${DHCP_END}" @@ -442,7 +442,7 @@ GetNetworkInformation() { dhcp_check_box=${check_box_good} # Is DHCP handling IPv6? - DHCP_IPv6="$(GetAPIValue config.dhcp_ipv6)" + DHCP_IPv6="$(GetPADDValue config.dhcp_ipv6)" if [ "${DHCP_IPv6}" = "true" ]; then dhcp_ipv6_status="Enabled" dhcp_ipv6_heatmap=${green_text} @@ -458,7 +458,7 @@ GetNetworkInformation() { dhcp_check_box=${check_box_bad} # Display the gateway address if DHCP is disabled - GATEWAY="$(GetAPIValue iface.v4.gw_addr | head -n 1)" + GATEWAY="$(GetPADDValue iface.v4.gw_addr | head -n 1)" dhcp_info=" Router: ${GATEWAY}" dhcp_ipv6_status="N/A" dhcp_ipv6_heatmap=${yellow_text} @@ -466,11 +466,11 @@ GetNetworkInformation() { fi # Get hostname - pi_hostname="$(GetAPIValue node_name)" + pi_hostname="$(GetPADDValue node_name)" full_hostname=${pi_hostname} # when PI-hole is the DHCP server, append the domain to the hostname if [ "${DHCP_ACTIVE}" = "true" ]; then - PIHOLE_DOMAIN="$(GetAPIValue config.dns_domain)" + PIHOLE_DOMAIN="$(GetPADDValue config.dns_domain)" if [ -n "${PIHOLE_DOMAIN}" ]; then count=${pi_hostname}"."${PIHOLE_DOMAIN} count=${#count} @@ -481,7 +481,7 @@ GetNetworkInformation() { fi # Get the number of configured upstream DNS servers - dns_count="$(GetAPIValue config.dns_num_upstreams)" + dns_count="$(GetPADDValue config.dns_num_upstreams)" # if there's only one DNS server if [ "${dns_count}" -eq 1 ]; then dns_information="1 server" @@ -491,7 +491,7 @@ GetNetworkInformation() { # DNSSEC - DNSSEC="$(GetAPIValue config.dns_dnssec)" + DNSSEC="$(GetPADDValue config.dns_dnssec)" if [ "${DNSSEC}" = "true" ]; then dnssec_status="Enabled" dnssec_heatmap=${green_text} @@ -501,7 +501,7 @@ GetNetworkInformation() { fi # Conditional forwarding - CONDITIONAL_FORWARDING="$(GetAPIValue config.dns_revServer_active)" + CONDITIONAL_FORWARDING="$(GetPADDValue config.dns_revServer_active)" if [ "${CONDITIONAL_FORWARDING}" = "true" ]; then conditional_forwarding_status="Enabled" conditional_forwarding_heatmap=${green_text} @@ -512,12 +512,12 @@ GetNetworkInformation() { # Default interface data (use IPv4 interface - we cannot show both and assume they are the same) iface_name="${gateway_v4_iface}" - tx_bytes="$(GetAPIValue iface.v4.tx_bytes.value)" - tx_bytes_unit="$(GetAPIValue iface.v4.tx_bytes.unit)" + tx_bytes="$(GetPADDValue iface.v4.tx_bytes.value)" + tx_bytes_unit="$(GetPADDValue iface.v4.tx_bytes.unit)" tx_bytes=$(printf "%.1f %b" "${tx_bytes}" "${tx_bytes_unit}") - rx_bytes="$(GetAPIValue iface.v4.rx_bytes.value)" - rx_bytes_unit="$(GetAPIValue iface.v4.rx_bytes.unit)" + rx_bytes="$(GetPADDValue iface.v4.rx_bytes.value)" + rx_bytes_unit="$(GetPADDValue iface.v4.rx_bytes.unit)" rx_bytes=$(printf "%.1f %b" "${rx_bytes}" "${rx_bytes_unit}") # If IPv4 and IPv6 interfaces are not the same, add a "*" to the interface @@ -545,14 +545,14 @@ GetPiholeInformation() { ftl_heatmap=${green_text} ftl_check_box=${check_box_good} # Get FTL CPU and memory usage - ftl_cpu_raw="$(GetAPIValue "%cpu")" - ftl_mem_percentage_raw="$(GetAPIValue "%mem")" + ftl_cpu_raw="$(GetPADDValue "%cpu")" + ftl_mem_percentage_raw="$(GetPADDValue "%mem")" ftl_cpu="$(printf "%.1f" "${ftl_cpu_raw}")%" ftl_mem_percentage="$(printf "%.1f" "${ftl_mem_percentage_raw}")%" # Get Pi-hole (blocking) status - ftl_dns_port=$(GetAPIValue config.dns_port) + ftl_dns_port=$(GetPADDValue config.dns_port) # Get FTL's current PID - ftlPID="$(GetAPIValue pid)" + ftlPID="$(GetPADDValue pid)" fi @@ -578,11 +578,11 @@ GetVersionInformation() { # Gather DOCKER version information... # returns "null" if not running Pi-hole in Docker container - DOCKER_VERSION="$(GetAPIValue version.docker.local)" + DOCKER_VERSION="$(GetPADDValue version.docker.local)" # If PADD is running inside docker, immediately return without checking for updated component versions if [ ! "${DOCKER_VERSION}" = "null" ] ; then - GITHUB_DOCKER_VERSION="$(GetAPIValue version.docker.remote)" + GITHUB_DOCKER_VERSION="$(GetPADDValue version.docker.remote)" docker_version_converted="$(VersionConverter "${DOCKER_VERSION}")" docker_version_latest_converted="$(VersionConverter "${GITHUB_DOCKER_VERSION}")" @@ -599,11 +599,11 @@ GetVersionInformation() { fi # Gather core version information... - CORE_BRANCH="$(GetAPIValue version.core.local.branch)" - CORE_VERSION="$(GetAPIValue version.core.local.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - GITHUB_CORE_VERSION="$(GetAPIValue version.core.remmote.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - CORE_HASH="$(GetAPIValue version.core.local.hash)" - GITHUB_CORE_HASH="$(GetAPIValue version.core.remote.hash)" + CORE_BRANCH="$(GetPADDValue version.core.local.branch)" + CORE_VERSION="$(GetPADDValue version.core.local.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_CORE_VERSION="$(GetPADDValue version.core.remmote.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + CORE_HASH="$(GetPADDValue version.core.local.hash)" + GITHUB_CORE_HASH="$(GetPADDValue version.core.remote.hash)" if [ "${CORE_BRANCH}" = "master" ]; then core_version_converted="$(VersionConverter "${CORE_VERSION}")" @@ -637,14 +637,14 @@ GetVersionInformation() { fi # Gather web version information... - WEB_VERSION="$(GetAPIValue version.web.local.version)" + WEB_VERSION="$(GetPADDValue version.web.local.version)" if [ ! "$WEB_VERSION" = "null" ]; then - WEB_BRANCH="$(GetAPIValue version.web.local.branch)" - WEB_VERSION="$(GetAPIValue version.web.local.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - GITHUB_WEB_VERSION="$(GetAPIValue version.web.remmote.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - WEB_HASH="$(GetAPIValue version.web.local.hash)" - GITHUB_WEB_HASH="$(GetAPIValue version.web.remote.hash)" + WEB_BRANCH="$(GetPADDValue version.web.local.branch)" + WEB_VERSION="$(GetPADDValue version.web.local.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_WEB_VERSION="$(GetPADDValue version.web.remmote.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + WEB_HASH="$(GetPADDValue version.web.local.hash)" + GITHUB_WEB_HASH="$(GetPADDValue version.web.remote.hash)" if [ "${WEB_BRANCH}" = "master" ]; then web_version_converted="$(VersionConverter "${WEB_VERSION}")" @@ -684,11 +684,11 @@ GetVersionInformation() { fi # Gather FTL version information... - FTL_BRANCH="$(GetAPIValue version.ftl.local.branch)" - FTL_VERSION="$(GetAPIValue version.ftl.local.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - GITHUB_FTL_VERSION="$(GetAPIValue version.ftl.remmote.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" - FTL_HASH="$(GetAPIValue version.ftl.local.hash)" - GITHUB_FTL_HASH="$(GetAPIValue version.ftl.remote.hash)" + FTL_BRANCH="$(GetPADDValue version.ftl.local.branch)" + FTL_VERSION="$(GetPADDValue version.ftl.local.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + GITHUB_FTL_VERSION="$(GetPADDValue version.ftl.remmote.version | tr -d '[:alpha:]' | awk -F '-' '{printf $1}')" + FTL_HASH="$(GetPADDValue version.ftl.local.hash)" + GITHUB_FTL_HASH="$(GetPADDValue version.ftl.remote.hash)" if [ "${FTL_BRANCH}" = "master" ]; then @@ -1376,7 +1376,7 @@ OutputJSON() { printf "%b" "Establishing connection with FTL...\n" LoginAPI - GetAPIData + GetPADDData GetSummaryInformation printf "%b" "{\"domains_being_blocked\":${domains_being_blocked_raw},\"dns_queries_today\":${dns_queries_today_raw},\"ads_blocked_today\":${ads_blocked_today_raw},\"ads_percentage_today\":${ads_percentage_today},\"clients\": ${clients}}" } @@ -1440,8 +1440,8 @@ StartupRoutine(){ moveXOffset; printf "%b" " [■·········] 10%\r" - # Request API data - GetAPIData + # Request PADD data + GetPADDData # Check for updates moveXOffset; printf "%b" " [■■········] 20%\r" @@ -1471,9 +1471,9 @@ StartupRoutine(){ moveXOffset; printf "%b" "Establishing connection with FTL...\n" LoginAPI - # Request API data - moveXOffset; echo "- Requesting API information..." - GetAPIData + # Request PADD data + moveXOffset; echo "- Requesting PADD information..." + GetPADDData # Get our information for the first time moveXOffset; echo "- Gathering version info." @@ -1510,9 +1510,9 @@ StartupRoutine(){ moveXOffset; printf "%b" "Establishing connection with FTL...\n" LoginAPI - # Request API data - moveXOffset; echo "- Requesting API information..." - GetAPIData + # Request PADD data + moveXOffset; echo "- Requesting PADD information..." + GetPADDData # Get our information for the first time moveXOffset; echo "- Gathering version information..." @@ -1583,15 +1583,15 @@ NormalPADD() { Authenticate fi - # Request API data + # Request PADD data if [ $((now - LastCheckFullInformation)) -ge 30 ]; then - GetAPIData + GetPADDData GetNetworkInformation GetVersionInformation LastCheckFullInformation="${now}" else # Request only a subset of the data - GetAPIData "?full=false" + GetPADDData "?full=false" fi # Get uptime, CPU load, temp, etc. every 5 seconds From d8c6f3344faf75690699d0ed94636c51fec591de Mon Sep 17 00:00:00 2001 From: yubiuser Date: Fri, 9 Aug 2024 14:42:13 +0200 Subject: [PATCH 67/81] Re add necessary 2>/dev/null Signed-off-by: yubiuser --- padd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/padd.sh b/padd.sh index 8cc8d066..30f766e8 100755 --- a/padd.sh +++ b/padd.sh @@ -1320,7 +1320,7 @@ secretRead() { unset key unset charcount charcount=0 - while key=$(dd ibs=1 count=1); do #read one byte of input + while key=$(dd ibs=1 count=1 2>/dev/null); do #read one byte of input if [ "${key}" = "$(printf '\0' | tr -d '\0')" ] ; then # Enter - accept password break From e18403b9228ff6e0a32aa63ead6661fc11aceb1c Mon Sep 17 00:00:00 2001 From: yubiuser Date: Fri, 9 Aug 2024 15:33:42 +0200 Subject: [PATCH 68/81] Suppress curl errors Signed-off-by: yubiuser --- padd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/padd.sh b/padd.sh index 30f766e8..d4ac2c3e 100755 --- a/padd.sh +++ b/padd.sh @@ -243,7 +243,7 @@ Authenticate() { GetFTLData() { local response # get the data from querying the API as well as the http status code - response=$(curl -skS -w "%{http_code}" -X GET "${API_URL}$1$2" -H "Accept: application/json" -H "sid: ${SID}" ) + response=$(curl -sk -w "%{http_code}" -X GET "${API_URL}$1$2" -H "Accept: application/json" -H "sid: ${SID}" ) # status are the last 3 characters status=$(printf %s "${response#"${response%???}"}") From 573d36ff20d8eceb3e161219caa35c321218d13a Mon Sep 17 00:00:00 2001 From: yubiuser Date: Fri, 9 Aug 2024 15:37:57 +0200 Subject: [PATCH 69/81] padd_data is a global variable Signed-off-by: yubiuser --- padd.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/padd.sh b/padd.sh index d4ac2c3e..b5b0c9c1 100755 --- a/padd.sh +++ b/padd.sh @@ -21,6 +21,9 @@ padd_version="v4.0.0" LastCheckPADDInformation=$(date +%s) LastCheckFullInformation=$(date +%s) +# padd_data holds the data returned by FTL's /padd endpoint globally +padd_data="" + # COLORS CSI="$(printf '\033')[" # Control Sequence Introducer red_text="${CSI}91m" # Red @@ -242,6 +245,9 @@ Authenticate() { GetFTLData() { local response + local data + local status + # get the data from querying the API as well as the http status code response=$(curl -sk -w "%{http_code}" -X GET "${API_URL}$1$2" -H "Accept: application/json" -H "sid: ${SID}" ) From ed3143f79aa299e0845fc19d9eb44d5852db2270 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Fri, 9 Aug 2024 15:41:44 +0200 Subject: [PATCH 70/81] Propagate API response errors upstream Signed-off-by: yubiuser --- padd.sh | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/padd.sh b/padd.sh index b5b0c9c1..fb9339ae 100755 --- a/padd.sh +++ b/padd.sh @@ -274,15 +274,23 @@ GetPADDData() { local response response=$(GetFTLData "padd" "$1") - # Iterate over all the leaf paths in the JSON object and creates key-value - # pairs in the format "key=value". Nested objects are flattened using the dot - # notation, e.g., { "a": { "b": 1 } } becomes "a.b=1". - # We cannot use leaf_paths here as it was deprecated in jq 1.6 and removed in - # current master - # Using "paths(scalars | true)" will return null and false values. - # We also check if the value is exactly `null` and, in this case, return the - # string "null", as jq would return an empty string for nulls. - padd_data=$(echo "$response" | jq -r 'paths(scalars | true) as $p | [$p | join(".")] + [if getpath($p)!=null then getpath($p) else "null" end] | join("=")' 2>/dev/null) + if [ "${response}" = 000 ]; then + # connection lost + padd_data="000" + elif [ "${response}" = 401 ]; then + # unauthorized + padd_data="401" + else + # Iterate over all the leaf paths in the JSON object and creates key-value + # pairs in the format "key=value". Nested objects are flattened using the dot + # notation, e.g., { "a": { "b": 1 } } becomes "a.b=1". + # We cannot use leaf_paths here as it was deprecated in jq 1.6 and removed in + # current master + # Using "paths(scalars | true)" will return null and false values. + # We also check if the value is exactly `null` and, in this case, return the + # string "null", as jq would return an empty string for nulls. + padd_data=$(echo "$response" | jq -r 'paths(scalars | true) as $p | [$p | join(".")] + [if getpath($p)!=null then getpath($p) else "null" end] | join("=")' 2>/dev/null) + fi } GetPADDValue() { From 97006b0681ad38d541c7b4406e88d82bb9361849 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Fri, 9 Aug 2024 21:05:59 +0200 Subject: [PATCH 71/81] Fix --version command Signed-off-by: yubiuser --- padd.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/padd.sh b/padd.sh index fb9339ae..1f1b64ab 100755 --- a/padd.sh +++ b/padd.sh @@ -1413,6 +1413,7 @@ ShowVersion() { printf "%b" "Establishing connection with FTL...\n" LoginAPI + GetPADDData GetVersionInformation GetPADDInformation if [ -z "${padd_version_latest}" ]; then From 51fde8aa88719920995c533e1444e808f6945b50 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Fri, 9 Aug 2024 22:44:14 +0200 Subject: [PATCH 72/81] Skip all the processing if FTL is down Signed-off-by: yubiuser --- padd.sh | 156 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 124 insertions(+), 32 deletions(-) diff --git a/padd.sh b/padd.sh index 1f1b64ab..813dba18 100755 --- a/padd.sh +++ b/padd.sh @@ -20,6 +20,7 @@ padd_version="v4.0.0" # LastChecks LastCheckPADDInformation=$(date +%s) LastCheckFullInformation=$(date +%s) +LastCheckNetworkInformation=$(date +%s) # padd_data holds the data returned by FTL's /padd endpoint globally padd_data="" @@ -298,6 +299,24 @@ GetPADDValue() { } GetSummaryInformation() { + if [ "${connection_down_flag}" = true ]; then + clients="N/A" + blocking_enabled="N/A" + domains_being_blocked="N/A" + dns_queries_today="N/A" + ads_blocked_today="N/A" + ads_percentage_today="N/A" + cache_size="N/A" + cache_evictions="N/A" + cache_inserts="N/A" + latest_blocked_raw="N/A" + top_blocked_raw="N/A" + top_domain_raw="N/A" + top_client_raw="N/A" + return + fi + + clients=$(GetPADDValue active_clients) blocking_enabled=$(GetPADDValue blocking) @@ -328,16 +347,31 @@ GetSummaryInformation() { } GetSystemInformation() { - # System uptime - if [ "${padd_data}" = 000 ]; then - # in case FTL connection is down, system_uptime_raw need to be set to 0 otherwise convertUptime() will complain - system_uptime_raw=0 - else - system_uptime_raw=$(GetPADDValue system.uptime) + + if [ "${connection_down_flag}" = true ]; then + system_uptime_raw=0 + temperature="N/A" + temp_heatmap=${reset_text} + + cpu_load_1="N/A" + cpu_load_5="N/A" + cpu_load_15="N/A" + cpu_load_1_heatmap=${reset_text} + cpu_load_5_heatmap=${reset_text} + cpu_load_15_heatmap=${reset_text} + cpu_percent=0 + + memory_percent=0 + memory_heatmap=${reset_text} + + sys_model="N/A" + return fi + # System uptime + system_uptime_raw=$(GetPADDValue system.uptime) + # CPU temperature and unit - # in case .sensors.cpu_temp returns 'null' we substitute with 0 cpu_temp_raw=$(GetPADDValue sensors.cpu_temp) cpu_temp=$(printf "%.1f" "${cpu_temp_raw}") temp_unit=$(echo "${padd_data}" | GetPADDValue sensors.unit) @@ -411,6 +445,36 @@ GetSystemInformation() { } GetNetworkInformation() { + if [ "${connection_down_flag}" = true ]; then + iface_name="N/A" + pi_ip4_addr="N/A" + pi_ip6_addr="N/A" + ipv6_check_box=${check_box_question} + + dhcp_status="N/A" + dhcp_heatmap=${reset_text} + dhcp_info="" + dhcp_ipv6_status="N/A" + dhcp_ipv6_heatmap=${reset_text} + dhcp_ipv6_check_box=${check_box_question} + + pi_hostname="N/A" + full_hostname="N/A" + + dns_count="N/A" + dns_information="N/A" + + dnssec_status="N/A" + dnssec_heatmap=${reset_text} + + conditional_forwarding_status="N/A" + conditional_forwarding_heatmap=${reset_text} + + tx_bytes="N/A" + rx_bytes="N/A" + return + fi + gateway_v4_iface=$(GetPADDValue iface.v4.name) gateway_v6_iface=$(GetPADDValue iface.v4.name) @@ -544,17 +608,21 @@ GetNetworkInformation() { } GetPiholeInformation() { - # If FTL is not running (sysinfo is 000), set all variables to "not running" - connection_down_flag=false - if [ "${padd_data}" = "000" ]; then - ftl_status="No connection" - ftl_heatmap=${red_text} - ftl_check_box=${check_box_bad} - # set flag to change the status message in SetStatusMessage() - connection_down_flag=true - ftl_cpu="N/A" - ftl_mem_percentage="N/A" - else + if [ "${connection_down_flag}" = true ]; then + ftl_status="No connection" + ftl_heatmap=${red_text} + ftl_check_box=${check_box_bad} + ftl_cpu="N/A" + ftl_mem_percentage="N/A" + dns_status="DNS offline" + dns_heatmap=${red_text} + dns_check_box=${check_box_bad} + ftlPID="N/A" + dns_down_flag=true + + return + fi + ftl_status="Running" ftl_heatmap=${green_text} ftl_check_box=${check_box_good} @@ -567,13 +635,12 @@ GetPiholeInformation() { ftl_dns_port=$(GetPADDValue config.dns_port) # Get FTL's current PID ftlPID="$(GetPADDValue pid)" - fi # ${ftl_dns_port} == 0 DNS server part of dnsmasq disabled dns_down_flag=false - if [ "${ftl_dns_port}" = 0 ] || [ "${ftl_status}" = "No connection" ]; then + if [ "${ftl_dns_port}" = 0 ]; then dns_status="DNS offline" dns_heatmap=${red_text} dns_check_box=${check_box_bad} @@ -587,6 +654,16 @@ fi } GetVersionInformation() { + if [ "${connection_down_flag}" = true ]; then + DOCKER_VERSION=null + CORE_VERSION="N/A" + WEB_VERSION="N/A" + FTL_VERSION="N/A" + core_version_heatmap=${reset_text} + web_version_heatmap=${reset_text} + ftl_version_heatmap=${reset_text} + return + fi out_of_date_flag=false @@ -861,7 +938,7 @@ SetStatusMessage() { full_status=${full_status_dns_down} mega_status=${mega_status_dns_down} - elif [ "${blocking_enabled}" = "false" ]; then + elif [ "${blocking_enabled}" = "disabled" ]; then # Check if blocking status is disabled pico_status=${pico_status_off} mini_status=${mini_status_off} @@ -877,7 +954,7 @@ SetStatusMessage() { full_status=${full_status_update} mega_status=${mega_status_update} - elif [ "${blocking_enabled}" = "true" ]; then + elif [ "${blocking_enabled}" = "enabled" ]; then # if we reach this point and blocking is enabled, everything is fine pico_status=${pico_status_ok} mini_status=${mini_status_ok} @@ -1601,23 +1678,38 @@ NormalPADD() { # Request PADD data if [ $((now - LastCheckFullInformation)) -ge 30 ]; then GetPADDData - GetNetworkInformation - GetVersionInformation LastCheckFullInformation="${now}" else # Request only a subset of the data GetPADDData "?full=false" fi - # Get uptime, CPU load, temp, etc. every 5 seconds - GetSystemInformation - GetSummaryInformation - GetPiholeInformation + connection_down_flag=false + # If the connection was lost, set connection_down_flag + if [ "${padd_data}" = "000" ]; then + connection_down_flag=true + GetSystemInformation + GetSummaryInformation + GetPiholeInformation + GetNetworkInformation + GetVersionInformation + else + # Get uptime, CPU load, temp, etc. every 5 seconds + GetSystemInformation + GetSummaryInformation + GetPiholeInformation + + if [ $((now - LastCheckNetworkInformation)) -ge 30 ]; then + GetNetworkInformation + GetVersionInformation + LastCheckNetworkInformation="${now}" + fi - # Get PADD version information every 24hours - if [ $((now - LastCheckPADDInformation)) -ge 86400 ]; then - GetPADDInformation - LastCheckPADDInformation="${now}" + # Get PADD version information every 24hours + if [ $((now - LastCheckPADDInformation)) -ge 86400 ]; then + GetPADDInformation + LastCheckPADDInformation="${now}" + fi fi done From 09e33964f638e7a7a9ac577e42340425ff1bdafd Mon Sep 17 00:00:00 2001 From: yubiuser Date: Fri, 9 Aug 2024 22:53:04 +0200 Subject: [PATCH 73/81] Set --connect-timeout for curl connections Signed-off-by: yubiuser --- padd.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/padd.sh b/padd.sh index 813dba18..df6dccd9 100755 --- a/padd.sh +++ b/padd.sh @@ -137,7 +137,7 @@ TestAPIAvailability() { API_URL="${API_URL#\"}" # Test if the API is available at this URL - availabilityResponse=$(curl -skS -o /dev/null -w "%{http_code}" "${API_URL}auth") + availabilityResponse=$(curl --connect-timeout 2 -skS -o /dev/null -w "%{http_code}" "${API_URL}auth") # Test if http status code was 200 (OK) or 401 (authentication required) if [ ! "${availabilityResponse}" = 200 ] && [ ! "${availabilityResponse}" = 401 ]; then @@ -217,7 +217,7 @@ DeleteSession() { # SID is not null (successful authenthication only), delete the session if [ "${validSession}" = true ] && [ ! "${SID}" = null ]; then # Try to delete the session. Omit the output, but get the http status code - deleteResponse=$(curl -skS -o /dev/null -w "%{http_code}" -X DELETE "${API_URL}auth" -H "Accept: application/json" -H "sid: ${SID}") + deleteResponse=$(curl --connect-timeout 2 -skS -o /dev/null -w "%{http_code}" -X DELETE "${API_URL}auth" -H "Accept: application/json" -H "sid: ${SID}") printf "\n\n" case "${deleteResponse}" in @@ -232,7 +232,7 @@ DeleteSession() { } Authenticate() { - sessionResponse="$(curl -skS -X POST "${API_URL}auth" --user-agent "PADD ${padd_version}" --data "{\"password\":\"${password}\"}" )" + sessionResponse="$(curl --connect-timeout 2 -skS -X POST "${API_URL}auth" --user-agent "PADD ${padd_version}" --data "{\"password\":\"${password}\"}" )" if [ -z "${sessionResponse}" ]; then moveXOffset; echo "No response from FTL server. Please check connectivity and use the options to set the API URL" @@ -250,7 +250,7 @@ GetFTLData() { local status # get the data from querying the API as well as the http status code - response=$(curl -sk -w "%{http_code}" -X GET "${API_URL}$1$2" -H "Accept: application/json" -H "sid: ${SID}" ) + response=$(curl --connect-timeout 2 -sk -w "%{http_code}" -X GET "${API_URL}$1$2" -H "Accept: application/json" -H "sid: ${SID}" ) # status are the last 3 characters status=$(printf %s "${response#"${response%???}"}") @@ -822,7 +822,7 @@ GetPADDInformation() { fi # PADD version information... - padd_version_latest="$(curl --silent https://api.github.com/repos/pi-hole/PADD/releases/latest | grep '"tag_name":' | awk -F \" '{print $4}')" + padd_version_latest="$(curl --connect-timeout 5 --silent https://api.github.com/repos/pi-hole/PADD/releases/latest | grep '"tag_name":' | awk -F \" '{print $4}')" # is PADD up-to-date? padd_out_of_date_flag=false if [ -z "${padd_version_latest}" ]; then @@ -1733,7 +1733,7 @@ Update() { echo "${check_box_info} Downloading PADD update ..." - if curl -sSL https://install.padd.sh -o "${padd_script_path}" > /dev/null 2>&1; then + if curl --connect-timeout 5 -sSL https://install.padd.sh -o "${padd_script_path}" > /dev/null 2>&1; then echo "${check_box_good} ... done. Restart PADD for the update to take effect" else echo "${check_box_bad} Cannot download PADD update" From 0440ade345deb0a3ae6efa1c42d6e2293879f642 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Fri, 9 Aug 2024 23:20:13 +0200 Subject: [PATCH 74/81] Require all API data after connection is re-established Signed-off-by: yubiuser --- padd.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/padd.sh b/padd.sh index df6dccd9..cfb3ead9 100755 --- a/padd.sh +++ b/padd.sh @@ -1675,8 +1675,8 @@ NormalPADD() { Authenticate fi - # Request PADD data - if [ $((now - LastCheckFullInformation)) -ge 30 ]; then + # Request PADD data after 30 seconds or if the connection was lost + if [ $((now - LastCheckFullInformation)) -ge 30 ] || [ "${connection_down_flag}" = true ] ; then GetPADDData LastCheckFullInformation="${now}" else @@ -1693,16 +1693,19 @@ NormalPADD() { GetPiholeInformation GetNetworkInformation GetVersionInformation + # set flag to update network information in the next loop in case the connection is re-established + get_network_information_requried=true else # Get uptime, CPU load, temp, etc. every 5 seconds GetSystemInformation GetSummaryInformation GetPiholeInformation - if [ $((now - LastCheckNetworkInformation)) -ge 30 ]; then + if [ $((now - LastCheckNetworkInformation)) -ge 30 ] || [ "${get_network_information_requried}" = true ]; then GetNetworkInformation GetVersionInformation LastCheckNetworkInformation="${now}" + get_network_information_requried=false fi # Get PADD version information every 24hours From 9bfb33869ba855adb34808db29c515e9378d91f2 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Thu, 26 Sep 2024 22:43:49 +0200 Subject: [PATCH 75/81] Fix CPU load Signed-off-by: yubiuser --- padd.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/padd.sh b/padd.sh index cfb3ead9..1cef2138 100755 --- a/padd.sh +++ b/padd.sh @@ -413,9 +413,9 @@ GetSystemInformation() { # CPU, load, heatmap core_count=$(GetPADDValue system.cpu.nprocs) - cpu_load_1=$(printf %.2f "$(GetPADDValue system.cpu.load.0)") - cpu_load_5=$(printf %.2f "$(GetPADDValue system.cpu.load.1)") - cpu_load_15=$(printf %.2f "$(GetPADDValue system.cpu.load.2)") + cpu_load_1=$(printf %.2f "$(GetPADDValue system.cpu.load.raw.[0])") + cpu_load_5=$(printf %.2f "$(GetPADDValue system.cpu.load.raw.[1])") + cpu_load_15=$(printf %.2f "$(GetPADDValue system.cpu.load.raw.[2])") cpu_load_1_heatmap=$(HeatmapGenerator "${cpu_load_1}" "${core_count}") cpu_load_5_heatmap=$(HeatmapGenerator "${cpu_load_5}" "${core_count}") cpu_load_15_heatmap=$(HeatmapGenerator "${cpu_load_15}" "${core_count}") From f7c88ee4fb9b72a77e34ab375c5a8dab3db94a2d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 28 Sep 2024 10:37:19 +0000 Subject: [PATCH 76/81] Bump actions/checkout from 4.1.7 to 4.2.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 4.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.7...v4.2.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/codespell.yml | 2 +- .github/workflows/editorconfig-checker.yml | 2 +- .github/workflows/stale.yml | 2 +- .github/workflows/sync-back-to-dev.yml | 2 +- .github/workflows/version_bump.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 693eda02..1e8eab3d 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 - name: Spell-Checking uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/editorconfig-checker.yml b/.github/workflows/editorconfig-checker.yml index 5cd18d49..2cbc4ac5 100644 --- a/.github/workflows/editorconfig-checker.yml +++ b/.github/workflows/editorconfig-checker.yml @@ -9,6 +9,6 @@ jobs: name: editorconfig-checker runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 - uses: editorconfig-checker/action-editorconfig-checker@main # current tag v1.0.0 is really out-of-date - run: editorconfig-checker diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 6f93787d..ad28295f 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 - name: Remove 'stale' label run: gh issue edit ${{ github.event.issue.number }} --remove-label ${{ env.stale_label }} env: diff --git a/.github/workflows/sync-back-to-dev.yml b/.github/workflows/sync-back-to-dev.yml index db88f65e..bea89081 100644 --- a/.github/workflows/sync-back-to-dev.yml +++ b/.github/workflows/sync-back-to-dev.yml @@ -11,7 +11,7 @@ jobs: name: Syncing branches steps: - name: Checkout - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 - name: Opening pull request run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'Internal' env: diff --git a/.github/workflows/version_bump.yml b/.github/workflows/version_bump.yml index 14c6e83b..f082d577 100644 --- a/.github/workflows/version_bump.yml +++ b/.github/workflows/version_bump.yml @@ -20,7 +20,7 @@ jobs: [[ -z ${LATEST_TAG} ]] && echo "Error: LATEST_TAG is empty, aborting" && exit 1 - name: Checkout code - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 with: ref: 'development' From 384af25645345ecf1dfb4b82c31621e2f666681d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Oct 2024 10:52:36 +0000 Subject: [PATCH 77/81] Bump actions/checkout from 4.2.0 to 4.2.1 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.0 to 4.2.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.2.0...v4.2.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codespell.yml | 2 +- .github/workflows/editorconfig-checker.yml | 2 +- .github/workflows/stale.yml | 2 +- .github/workflows/sync-back-to-dev.yml | 2 +- .github/workflows/version_bump.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 1e8eab3d..726cdbe0 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.2.0 + uses: actions/checkout@v4.2.1 - name: Spell-Checking uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/editorconfig-checker.yml b/.github/workflows/editorconfig-checker.yml index 2cbc4ac5..b32b5af6 100644 --- a/.github/workflows/editorconfig-checker.yml +++ b/.github/workflows/editorconfig-checker.yml @@ -9,6 +9,6 @@ jobs: name: editorconfig-checker runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 - uses: editorconfig-checker/action-editorconfig-checker@main # current tag v1.0.0 is really out-of-date - run: editorconfig-checker diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index ad28295f..dc8fdc48 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.2.0 + uses: actions/checkout@v4.2.1 - name: Remove 'stale' label run: gh issue edit ${{ github.event.issue.number }} --remove-label ${{ env.stale_label }} env: diff --git a/.github/workflows/sync-back-to-dev.yml b/.github/workflows/sync-back-to-dev.yml index bea89081..4cf5c5b0 100644 --- a/.github/workflows/sync-back-to-dev.yml +++ b/.github/workflows/sync-back-to-dev.yml @@ -11,7 +11,7 @@ jobs: name: Syncing branches steps: - name: Checkout - uses: actions/checkout@v4.2.0 + uses: actions/checkout@v4.2.1 - name: Opening pull request run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'Internal' env: diff --git a/.github/workflows/version_bump.yml b/.github/workflows/version_bump.yml index f082d577..622f2002 100644 --- a/.github/workflows/version_bump.yml +++ b/.github/workflows/version_bump.yml @@ -20,7 +20,7 @@ jobs: [[ -z ${LATEST_TAG} ]] && echo "Error: LATEST_TAG is empty, aborting" && exit 1 - name: Checkout code - uses: actions/checkout@v4.2.0 + uses: actions/checkout@v4.2.1 with: ref: 'development' From 8bcf9f4b45bc46b7a163d4b81ae30230c1751e74 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 26 Oct 2024 10:38:01 +0000 Subject: [PATCH 78/81] Bump actions/checkout from 4.2.1 to 4.2.2 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.1 to 4.2.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.2.1...v4.2.2) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codespell.yml | 2 +- .github/workflows/editorconfig-checker.yml | 2 +- .github/workflows/stale.yml | 2 +- .github/workflows/sync-back-to-dev.yml | 2 +- .github/workflows/version_bump.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 726cdbe0..f81d0e56 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.2.1 + uses: actions/checkout@v4.2.2 - name: Spell-Checking uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/editorconfig-checker.yml b/.github/workflows/editorconfig-checker.yml index b32b5af6..8f104c24 100644 --- a/.github/workflows/editorconfig-checker.yml +++ b/.github/workflows/editorconfig-checker.yml @@ -9,6 +9,6 @@ jobs: name: editorconfig-checker runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 - uses: editorconfig-checker/action-editorconfig-checker@main # current tag v1.0.0 is really out-of-date - run: editorconfig-checker diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index dc8fdc48..9889992a 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.2.1 + uses: actions/checkout@v4.2.2 - name: Remove 'stale' label run: gh issue edit ${{ github.event.issue.number }} --remove-label ${{ env.stale_label }} env: diff --git a/.github/workflows/sync-back-to-dev.yml b/.github/workflows/sync-back-to-dev.yml index 4cf5c5b0..d9c7ed19 100644 --- a/.github/workflows/sync-back-to-dev.yml +++ b/.github/workflows/sync-back-to-dev.yml @@ -11,7 +11,7 @@ jobs: name: Syncing branches steps: - name: Checkout - uses: actions/checkout@v4.2.1 + uses: actions/checkout@v4.2.2 - name: Opening pull request run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'Internal' env: diff --git a/.github/workflows/version_bump.yml b/.github/workflows/version_bump.yml index 622f2002..8aeecab5 100644 --- a/.github/workflows/version_bump.yml +++ b/.github/workflows/version_bump.yml @@ -20,7 +20,7 @@ jobs: [[ -z ${LATEST_TAG} ]] && echo "Error: LATEST_TAG is empty, aborting" && exit 1 - name: Checkout code - uses: actions/checkout@v4.2.1 + uses: actions/checkout@v4.2.2 with: ref: 'development' From 689e602effce9dd74fb232708c35f9856312d65b Mon Sep 17 00:00:00 2001 From: yubiuser Date: Sun, 22 Dec 2024 23:42:12 +0100 Subject: [PATCH 79/81] Speedup response handling Signed-off-by: yubiuser --- padd.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/padd.sh b/padd.sh index 1cef2138..f4524dad 100755 --- a/padd.sh +++ b/padd.sh @@ -253,7 +253,8 @@ GetFTLData() { response=$(curl --connect-timeout 2 -sk -w "%{http_code}" -X GET "${API_URL}$1$2" -H "Accept: application/json" -H "sid: ${SID}" ) # status are the last 3 characters - status=$(printf %s "${response#"${response%???}"}") + # not using ${response#"${response%???}"}" here because it's extremely slow on big responses + status=$(printf "%s" "${response}" | tail -c 3) # data is everything from response without the last 3 characters data=$(printf %s "${response%???}") From b73487016b4e59e8cbde32bd920d86392c1966fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Jan 2025 10:39:09 +0000 Subject: [PATCH 80/81] Bump eps1lon/actions-label-merge-conflict from 3.0.2 to 3.0.3 Bumps [eps1lon/actions-label-merge-conflict](https://github.com/eps1lon/actions-label-merge-conflict) from 3.0.2 to 3.0.3. - [Release notes](https://github.com/eps1lon/actions-label-merge-conflict/releases) - [Changelog](https://github.com/eps1lon/actions-label-merge-conflict/blob/main/CHANGELOG.md) - [Commits](https://github.com/eps1lon/actions-label-merge-conflict/compare/v3.0.2...v3.0.3) --- updated-dependencies: - dependency-name: eps1lon/actions-label-merge-conflict dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/merge-conflict.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge-conflict.yml b/.github/workflows/merge-conflict.yml index c24de2c8..ea30b655 100644 --- a/.github/workflows/merge-conflict.yml +++ b/.github/workflows/merge-conflict.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check if PRs are have merge conflicts - uses: eps1lon/actions-label-merge-conflict@v3.0.2 + uses: eps1lon/actions-label-merge-conflict@v3.0.3 with: dirtyLabel: "Merge Conflict" repoToken: "${{ secrets.GITHUB_TOKEN }}" From ab940d0eec8674f111cd39433950fec0d2479ada Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 25 Jan 2025 10:12:33 +0000 Subject: [PATCH 81/81] Bump actions/stale from 9.0.0 to 9.1.0 Bumps [actions/stale](https://github.com/actions/stale) from 9.0.0 to 9.1.0. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v9.0.0...v9.1.0) --- updated-dependencies: - dependency-name: actions/stale dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/stale.yml | 2 +- .github/workflows/stale_pr.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 9889992a..558223f5 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -17,7 +17,7 @@ jobs: issues: write steps: - - uses: actions/stale@v9.0.0 + - uses: actions/stale@v9.1.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 30 diff --git a/.github/workflows/stale_pr.yml b/.github/workflows/stale_pr.yml index 171c9030..2441271e 100644 --- a/.github/workflows/stale_pr.yml +++ b/.github/workflows/stale_pr.yml @@ -17,7 +17,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@v9.0.0 + - uses: actions/stale@v9.1.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} # Do not automatically mark PR/issue as stale