1
0
mirror of https://github.com/pi-hole/pi-hole synced 2025-01-09 07:30:56 +00:00

Merge pull request #2289 from pi-hole/feature/space_tab

Adjusting spacing for utility scripts.
This commit is contained in:
Dan Schaper 2018-07-20 19:23:50 -07:00 committed by GitHub
commit e32c76b059
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 2433 additions and 2436 deletions

File diff suppressed because it is too large Load Diff

View File

@ -29,19 +29,19 @@ source ${colfile}
helpFunc() { helpFunc() {
if [[ "${listMain}" == "${whitelist}" ]]; then if [[ "${listMain}" == "${whitelist}" ]]; then
param="w" param="w"
type="white" type="white"
elif [[ "${listMain}" == "${regexlist}" && "${wildcard}" == true ]]; then elif [[ "${listMain}" == "${regexlist}" && "${wildcard}" == true ]]; then
param="-wild" param="-wild"
type="wildcard black" type="wildcard black"
elif [[ "${listMain}" == "${regexlist}" ]]; then elif [[ "${listMain}" == "${regexlist}" ]]; then
param="-regex" param="-regex"
type="regex black" type="regex black"
else else
param="b" param="b"
type="black" type="black"
fi fi
echo "Usage: pihole -${param} [options] <domain> <domain2 ...> echo "Usage: pihole -${param} [options] <domain> <domain2 ...>
Example: 'pihole -${param} site.com', or 'pihole -${param} site1.com site2.com' Example: 'pihole -${param} site.com', or 'pihole -${param} site1.com site2.com'
@ -59,216 +59,216 @@ Options:
} }
EscapeRegexp() { EscapeRegexp() {
# This way we may safely insert an arbitrary # This way we may safely insert an arbitrary
# string in our regular expressions # string in our regular expressions
# This sed is intentionally executed in three steps to ease maintainability # This sed is intentionally executed in three steps to ease maintainability
# The first sed removes any amount of leading dots # The first sed removes any amount of leading dots
echo $* | sed 's/^\.*//' | sed "s/[]\.|$(){}?+*^]/\\\\&/g" | sed "s/\\//\\\\\//g" echo $* | sed 's/^\.*//' | sed "s/[]\.|$(){}?+*^]/\\\\&/g" | sed "s/\\//\\\\\//g"
} }
HandleOther() { HandleOther() {
# Convert to lowercase # Convert to lowercase
domain="${1,,}" domain="${1,,}"
# Check validity of domain (don't check for regex entries) # Check validity of domain (don't check for regex entries)
if [[ "${#domain}" -le 253 ]]; then if [[ "${#domain}" -le 253 ]]; then
if [[ "${listMain}" == "${regexlist}" && "${wildcard}" == false ]]; then if [[ "${listMain}" == "${regexlist}" && "${wildcard}" == false ]]; then
validDomain="${domain}" validDomain="${domain}"
else else
validDomain=$(grep -P "^((-|_)*[a-z\\d]((-|_)*[a-z\\d])*(-|_)*)(\\.(-|_)*([a-z\\d]((-|_)*[a-z\\d])*))*$" <<< "${domain}") # Valid chars check validDomain=$(grep -P "^((-|_)*[a-z\\d]((-|_)*[a-z\\d])*(-|_)*)(\\.(-|_)*([a-z\\d]((-|_)*[a-z\\d])*))*$" <<< "${domain}") # Valid chars check
validDomain=$(grep -P "^[^\\.]{1,63}(\\.[^\\.]{1,63})*$" <<< "${validDomain}") # Length of each label validDomain=$(grep -P "^[^\\.]{1,63}(\\.[^\\.]{1,63})*$" <<< "${validDomain}") # Length of each label
fi
fi fi
fi
if [[ -n "${validDomain}" ]]; then if [[ -n "${validDomain}" ]]; then
domList=("${domList[@]}" ${validDomain}) domList=("${domList[@]}" ${validDomain})
else else
echo -e " ${CROSS} ${domain} is not a valid argument or domain name!" echo -e " ${CROSS} ${domain} is not a valid argument or domain name!"
fi fi
} }
PoplistFile() { PoplistFile() {
# Check whitelist file exists, and if not, create it # Check whitelist file exists, and if not, create it
if [[ ! -f "${whitelist}" ]]; then if [[ ! -f "${whitelist}" ]]; then
touch "${whitelist}" touch "${whitelist}"
fi
# Check blacklist file exists, and if not, create it
if [[ ! -f "${blacklist}" ]]; then
touch "${blacklist}"
fi
for dom in "${domList[@]}"; do
# Logic: If addmode then add to desired list and remove from the other; if delmode then remove from desired list but do not add to the other
if ${addmode}; then
AddDomain "${dom}" "${listMain}"
RemoveDomain "${dom}" "${listAlt}"
else
RemoveDomain "${dom}" "${listMain}"
fi fi
# Check blacklist file exists, and if not, create it
if [[ ! -f "${blacklist}" ]]; then
touch "${blacklist}"
fi
for dom in "${domList[@]}"; do
# Logic: If addmode then add to desired list and remove from the other; if delmode then remove from desired list but do not add to the other
if ${addmode}; then
AddDomain "${dom}" "${listMain}"
RemoveDomain "${dom}" "${listAlt}"
else
RemoveDomain "${dom}" "${listMain}"
fi
done done
} }
AddDomain() { AddDomain() {
list="$2" list="$2"
domain=$(EscapeRegexp "$1") domain=$(EscapeRegexp "$1")
[[ "${list}" == "${whitelist}" ]] && listname="whitelist" [[ "${list}" == "${whitelist}" ]] && listname="whitelist"
[[ "${list}" == "${blacklist}" ]] && listname="blacklist" [[ "${list}" == "${blacklist}" ]] && listname="blacklist"
if [[ "${list}" == "${whitelist}" || "${list}" == "${blacklist}" ]]; then if [[ "${list}" == "${whitelist}" || "${list}" == "${blacklist}" ]]; then
[[ "${list}" == "${whitelist}" && -z "${type}" ]] && type="--whitelist-only" [[ "${list}" == "${whitelist}" && -z "${type}" ]] && type="--whitelist-only"
[[ "${list}" == "${blacklist}" && -z "${type}" ]] && type="--blacklist-only" [[ "${list}" == "${blacklist}" && -z "${type}" ]] && type="--blacklist-only"
bool=true bool=true
# Is the domain in the list we want to add it to? # Is the domain in the list we want to add it to?
grep -Ex -q "${domain}" "${list}" > /dev/null 2>&1 || bool=false grep -Ex -q "${domain}" "${list}" > /dev/null 2>&1 || bool=false
if [[ "${bool}" == false ]]; then if [[ "${bool}" == false ]]; then
# Domain not found in the whitelist file, add it! # Domain not found in the whitelist file, add it!
if [[ "${verbose}" == true ]]; then if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} Adding ${1} to ${listname}..." echo -e " ${INFO} Adding ${1} to ${listname}..."
fi fi
reload=true reload=true
# Add it to the list we want to add it to # Add it to the list we want to add it to
echo "$1" >> "${list}" echo "$1" >> "${list}"
else else
if [[ "${verbose}" == true ]]; then if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} ${1} already exists in ${listname}, no need to add!" echo -e " ${INFO} ${1} already exists in ${listname}, no need to add!"
fi fi
fi
elif [[ "${list}" == "${regexlist}" ]]; then
[[ -z "${type}" ]] && type="--wildcard-only"
bool=true
domain="${1}"
[[ "${wildcard}" == true ]] && domain="((^)|(\\.))${domain//\./\\.}$"
# Is the domain in the list?
# Search only for exactly matching lines
grep -Fx "${domain}" "${regexlist}" > /dev/null 2>&1 || bool=false
if [[ "${bool}" == false ]]; then
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} Adding ${domain} to regex list..."
fi
reload="restart"
echo "$domain" >> "${regexlist}"
else
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} ${domain} already exists in regex list, no need to add!"
fi
fi
fi fi
elif [[ "${list}" == "${regexlist}" ]]; then
[[ -z "${type}" ]] && type="--wildcard-only"
bool=true
domain="${1}"
[[ "${wildcard}" == true ]] && domain="((^)|(\\.))${domain//\./\\.}$"
# Is the domain in the list?
# Search only for exactly matching lines
grep -Fx "${domain}" "${regexlist}" > /dev/null 2>&1 || bool=false
if [[ "${bool}" == false ]]; then
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} Adding ${domain} to regex list..."
fi
reload="restart"
echo "$domain" >> "${regexlist}"
else
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} ${domain} already exists in regex list, no need to add!"
fi
fi
fi
} }
RemoveDomain() { RemoveDomain() {
list="$2" list="$2"
domain=$(EscapeRegexp "$1") domain=$(EscapeRegexp "$1")
[[ "${list}" == "${whitelist}" ]] && listname="whitelist" [[ "${list}" == "${whitelist}" ]] && listname="whitelist"
[[ "${list}" == "${blacklist}" ]] && listname="blacklist" [[ "${list}" == "${blacklist}" ]] && listname="blacklist"
if [[ "${list}" == "${whitelist}" || "${list}" == "${blacklist}" ]]; then if [[ "${list}" == "${whitelist}" || "${list}" == "${blacklist}" ]]; then
bool=true bool=true
[[ "${list}" == "${whitelist}" && -z "${type}" ]] && type="--whitelist-only" [[ "${list}" == "${whitelist}" && -z "${type}" ]] && type="--whitelist-only"
[[ "${list}" == "${blacklist}" && -z "${type}" ]] && type="--blacklist-only" [[ "${list}" == "${blacklist}" && -z "${type}" ]] && type="--blacklist-only"
# Is it in the list? Logic follows that if its whitelisted it should not be blacklisted and vice versa # Is it in the list? Logic follows that if its whitelisted it should not be blacklisted and vice versa
grep -Ex -q "${domain}" "${list}" > /dev/null 2>&1 || bool=false grep -Ex -q "${domain}" "${list}" > /dev/null 2>&1 || bool=false
if [[ "${bool}" == true ]]; then if [[ "${bool}" == true ]]; then
# Remove it from the other one # Remove it from the other one
echo -e " ${INFO} Removing $1 from ${listname}..." echo -e " ${INFO} Removing $1 from ${listname}..."
# /I flag: search case-insensitive # /I flag: search case-insensitive
sed -i "/${domain}/Id" "${list}" sed -i "/${domain}/Id" "${list}"
reload=true reload=true
else else
if [[ "${verbose}" == true ]]; then if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} ${1} does not exist in ${listname}, no need to remove!" echo -e " ${INFO} ${1} does not exist in ${listname}, no need to remove!"
fi fi
fi
elif [[ "${list}" == "${regexlist}" ]]; then
[[ -z "${type}" ]] && type="--wildcard-only"
domain="${1}"
[[ "${wildcard}" == true ]] && domain="((^)|(\\.))${domain//\./\\.}$"
bool=true
# Is it in the list?
grep -Fx "${domain}" "${regexlist}" > /dev/null 2>&1 || bool=false
if [[ "${bool}" == true ]]; then
# Remove it from the other one
echo -e " ${INFO} Removing $domain from regex list..."
local lineNumber
lineNumber=$(grep -Fnx "$domain" "${list}" | cut -f1 -d:)
sed -i "${lineNumber}d" "${list}"
reload=true
else
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} ${domain} does not exist in regex list, no need to remove!"
fi
fi
fi fi
elif [[ "${list}" == "${regexlist}" ]]; then
[[ -z "${type}" ]] && type="--wildcard-only"
domain="${1}"
[[ "${wildcard}" == true ]] && domain="((^)|(\\.))${domain//\./\\.}$"
bool=true
# Is it in the list?
grep -Fx "${domain}" "${regexlist}" > /dev/null 2>&1 || bool=false
if [[ "${bool}" == true ]]; then
# Remove it from the other one
echo -e " ${INFO} Removing $domain from regex list..."
local lineNumber
lineNumber=$(grep -Fnx "$domain" "${list}" | cut -f1 -d:)
sed -i "${lineNumber}d" "${list}"
reload=true
else
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} ${domain} does not exist in regex list, no need to remove!"
fi
fi
fi
} }
# Update Gravity # Update Gravity
Reload() { Reload() {
echo "" echo ""
pihole -g --skip-download "${type:-}" pihole -g --skip-download "${type:-}"
} }
Displaylist() { Displaylist() {
if [[ -f ${listMain} ]]; then if [[ -f ${listMain} ]]; then
if [[ "${listMain}" == "${whitelist}" ]]; then if [[ "${listMain}" == "${whitelist}" ]]; then
string="gravity resistant domains" string="gravity resistant domains"
else
string="domains caught in the sinkhole"
fi
verbose=false
echo -e "Displaying $string:\n"
count=1
while IFS= read -r RD || [ -n "${RD}" ]; do
echo " ${count}: ${RD}"
count=$((count+1))
done < "${listMain}"
else else
string="domains caught in the sinkhole" echo -e " ${COL_LIGHT_RED}${listMain} does not exist!${COL_NC}"
fi fi
verbose=false exit 0;
echo -e "Displaying $string:\n"
count=1
while IFS= read -r RD || [ -n "${RD}" ]; do
echo " ${count}: ${RD}"
count=$((count+1))
done < "${listMain}"
else
echo -e " ${COL_LIGHT_RED}${listMain} does not exist!${COL_NC}"
fi
exit 0;
} }
NukeList() { NukeList() {
if [[ -f "${listMain}" ]]; then if [[ -f "${listMain}" ]]; then
# Back up original list # Back up original list
cp "${listMain}" "${listMain}.bck~" cp "${listMain}" "${listMain}.bck~"
# Empty out file # Empty out file
echo "" > "${listMain}" echo "" > "${listMain}"
fi fi
} }
for var in "$@"; do for var in "$@"; do
case "${var}" in case "${var}" in
"-w" | "whitelist" ) listMain="${whitelist}"; listAlt="${blacklist}";; "-w" | "whitelist" ) listMain="${whitelist}"; listAlt="${blacklist}";;
"-b" | "blacklist" ) listMain="${blacklist}"; listAlt="${whitelist}";; "-b" | "blacklist" ) listMain="${blacklist}"; listAlt="${whitelist}";;
"--wild" | "wildcard" ) listMain="${regexlist}"; wildcard=true;; "--wild" | "wildcard" ) listMain="${regexlist}"; wildcard=true;;
"--regex" | "regex" ) listMain="${regexlist}";; "--regex" | "regex" ) listMain="${regexlist}";;
"-nr"| "--noreload" ) reload=false;; "-nr"| "--noreload" ) reload=false;;
"-d" | "--delmode" ) addmode=false;; "-d" | "--delmode" ) addmode=false;;
"-q" | "--quiet" ) verbose=false;; "-q" | "--quiet" ) verbose=false;;
"-h" | "--help" ) helpFunc;; "-h" | "--help" ) helpFunc;;
"-l" | "--list" ) Displaylist;; "-l" | "--list" ) Displaylist;;
"--nuke" ) NukeList;; "--nuke" ) NukeList;;
* ) HandleOther "${var}";; * ) HandleOther "${var}";;
esac esac
done done
shift shift
if [[ $# = 0 ]]; then if [[ $# = 0 ]]; then
helpFunc helpFunc
fi fi
PoplistFile PoplistFile
if [[ "${reload}" != false ]]; then if [[ "${reload}" != false ]]; then
# Ensure that "restart" is used for Wildcard updates # Ensure that "restart" is used for Wildcard updates
Reload "${reload}" Reload "${reload}"
fi fi

View File

@ -26,170 +26,170 @@ source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
source "${setupVars}" source "${setupVars}"
warning1() { warning1() {
echo " Please note that changing branches severely alters your Pi-hole subsystems" echo " Please note that changing branches severely alters your Pi-hole subsystems"
echo " Features that work on the master branch, may not on a development branch" echo " Features that work on the master branch, may not on a development branch"
echo -e " ${COL_LIGHT_RED}This feature is NOT supported unless a Pi-hole developer explicitly asks!${COL_NC}" echo -e " ${COL_LIGHT_RED}This feature is NOT supported unless a Pi-hole developer explicitly asks!${COL_NC}"
read -r -p " Have you read and understood this? [y/N] " response read -r -p " Have you read and understood this? [y/N] " response
case "${response}" in case "${response}" in
[yY][eE][sS]|[yY]) [yY][eE][sS]|[yY])
echo "" echo ""
return 0 return 0
;; ;;
*) *)
echo -e "\\n ${INFO} Branch change has been cancelled" echo -e "\\n ${INFO} Branch change has been cancelled"
return 1 return 1
;; ;;
esac esac
} }
checkout() { checkout() {
local corebranches local corebranches
local webbranches local webbranches
# Avoid globbing # Avoid globbing
set -f set -f
# This is unlikely # This is unlikely
if ! is_repo "${PI_HOLE_FILES_DIR}" ; then if ! is_repo "${PI_HOLE_FILES_DIR}" ; then
echo -e " ${COL_LIGHT_RED}Error: Core Pi-hole repo is missing from system! echo -e " ${COL_LIGHT_RED}Error: Core Pi-hole repo is missing from system!"
Please re-run install script from https://github.com/pi-hole/pi-hole${COL_NC}" echo -e " Please re-run install script from https://github.com/pi-hole/pi-hole${COL_NC}"
exit 1; exit 1;
fi
if [[ "${INSTALL_WEB_INTERFACE}" == "true" ]]; then
if ! is_repo "${webInterfaceDir}" ; then
echo -e " ${COL_LIGHT_RED}Error: Web Admin repo is missing from system!
Please re-run install script from https://github.com/pi-hole/pi-hole${COL_NC}"
exit 1;
fi fi
fi
if [[ -z "${1}" ]]; then
echo -e " ${COL_LIGHT_RED}Invalid option${COL_NC}
Try 'pihole checkout --help' for more information."
exit 1
fi
if ! warning1 ; then
exit 1
fi
if [[ "${1}" == "dev" ]] ; then
# Shortcut to check out development branches
echo -e " ${INFO} Shortcut \"dev\" detected - checking out development / devel branches..."
echo ""
echo -e " ${INFO} Pi-hole Core"
fetch_checkout_pull_branch "${PI_HOLE_FILES_DIR}" "development" || { echo " ${CROSS} Unable to pull Core developement branch"; exit 1; }
if [[ "${INSTALL_WEB_INTERFACE}" == "true" ]]; then if [[ "${INSTALL_WEB_INTERFACE}" == "true" ]]; then
echo "" if ! is_repo "${webInterfaceDir}" ; then
echo -e " ${INFO} Web interface" echo -e " ${COL_LIGHT_RED}Error: Web Admin repo is missing from system!"
fetch_checkout_pull_branch "${webInterfaceDir}" "devel" || { echo " ${CROSS} Unable to pull Web development branch"; exit 1; } echo -e " Please re-run install script from https://github.com/pi-hole/pi-hole${COL_NC}"
fi exit 1;
#echo -e " ${TICK} Pi-hole Core" fi
get_binary_name
local path
path="development/${binary}"
echo "development" > /etc/pihole/ftlbranch
elif [[ "${1}" == "master" ]] ; then
# Shortcut to check out master branches
echo -e " ${INFO} Shortcut \"master\" detected - checking out master branches..."
echo -e " ${INFO} Pi-hole core"
fetch_checkout_pull_branch "${PI_HOLE_FILES_DIR}" "master" || { echo " ${CROSS} Unable to pull Core master branch"; exit 1; }
if [[ ${INSTALL_WEB_INTERFACE} == "true" ]]; then
echo -e " ${INFO} Web interface"
fetch_checkout_pull_branch "${webInterfaceDir}" "master" || { echo " ${CROSS} Unable to pull Web master branch"; exit 1; }
fi
#echo -e " ${TICK} Web Interface"
get_binary_name
local path
path="master/${binary}"
echo "master" > /etc/pihole/ftlbranch
elif [[ "${1}" == "core" ]] ; then
str="Fetching branches from ${piholeGitUrl}"
echo -ne " ${INFO} $str"
if ! fully_fetch_repo "${PI_HOLE_FILES_DIR}" ; then
echo -e "${OVER} ${CROSS} $str"
exit 1
fi
corebranches=($(get_available_branches "${PI_HOLE_FILES_DIR}"))
if [[ "${corebranches[*]}" == *"master"* ]]; then
echo -e "${OVER} ${TICK} $str
${INFO} ${#corebranches[@]} branches available for Pi-hole Core"
else
# Print STDERR output from get_available_branches
echo -e "${OVER} ${CROSS} $str\\n\\n${corebranches[*]}"
exit 1
fi fi
echo "" if [[ -z "${1}" ]]; then
# Have the user choose the branch they want echo -e " ${COL_LIGHT_RED}Invalid option${COL_NC}"
if ! (for e in "${corebranches[@]}"; do [[ "$e" == "${2}" ]] && exit 0; done); then echo -e " Try 'pihole checkout --help' for more information."
echo -e " ${INFO} Requested branch \"${2}\" is not available"
echo -e " ${INFO} Available branches for Core are:"
for e in "${corebranches[@]}"; do echo " - $e"; done
exit 1
fi
checkout_pull_branch "${PI_HOLE_FILES_DIR}" "${2}"
elif [[ "${1}" == "web" ]] && [[ "${INSTALL_WEB_INTERFACE}" == "true" ]] ; then
str="Fetching branches from ${webInterfaceGitUrl}"
echo -ne " ${INFO} $str"
if ! fully_fetch_repo "${webInterfaceDir}" ; then
echo -e "${OVER} ${CROSS} $str"
exit 1
fi
webbranches=($(get_available_branches "${webInterfaceDir}"))
if [[ "${webbranches[*]}" == *"master"* ]]; then
echo -e "${OVER} ${TICK} $str
${INFO} ${#webbranches[@]} branches available for Web Admin"
else
# Print STDERR output from get_available_branches
echo -e "${OVER} ${CROSS} $str\\n\\n${webbranches[*]}"
exit 1
fi
echo ""
# Have the user choose the branch they want
if ! (for e in "${webbranches[@]}"; do [[ "$e" == "${2}" ]] && exit 0; done); then
echo -e " ${INFO} Requested branch \"${2}\" is not available"
echo -e " ${INFO} Available branches for Web Admin are:"
for e in "${webbranches[@]}"; do echo " - $e"; done
exit 1
fi
checkout_pull_branch "${webInterfaceDir}" "${2}"
elif [[ "${1}" == "ftl" ]] ; then
get_binary_name
local path
path="${2}/${binary}"
if check_download_exists "$path"; then
echo " ${TICK} Branch ${2} exists"
echo "${2}" > /etc/pihole/ftlbranch
FTLinstall "${binary}"
start_service pihole-FTL
enable_service pihole-FTL
else
echo " ${CROSS} Requested branch \"${2}\" is not available"
ftlbranches=( $(git ls-remote https://github.com/pi-hole/ftl | grep 'heads' | sed 's/refs\/heads\///;s/ //g' | awk '{print $2}') )
echo -e " ${INFO} Available branches for FTL are:"
for e in "${ftlbranches[@]}"; do echo " - $e"; done
exit 1 exit 1
fi fi
else if ! warning1 ; then
echo -e " ${INFO} Requested option \"${1}\" is not available" exit 1
exit 1 fi
fi
if [[ "${1}" == "dev" ]] ; then
# Force updating everything # Shortcut to check out development branches
if [[ ! "${1}" == "web" && ! "${1}" == "ftl" ]]; then echo -e " ${INFO} Shortcut \"dev\" detected - checking out development / devel branches..."
echo -e " ${INFO} Running installer to upgrade your installation" echo ""
if "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" --unattended; then echo -e " ${INFO} Pi-hole Core"
exit 0 fetch_checkout_pull_branch "${PI_HOLE_FILES_DIR}" "development" || { echo " ${CROSS} Unable to pull Core developement branch"; exit 1; }
else if [[ "${INSTALL_WEB_INTERFACE}" == "true" ]]; then
echo -e " ${COL_LIGHT_RED} Error: Unable to complete update, please contact support${COL_NC}" echo ""
exit 1 echo -e " ${INFO} Web interface"
fetch_checkout_pull_branch "${webInterfaceDir}" "devel" || { echo " ${CROSS} Unable to pull Web development branch"; exit 1; }
fi
#echo -e " ${TICK} Pi-hole Core"
get_binary_name
local path
path="development/${binary}"
echo "development" > /etc/pihole/ftlbranch
elif [[ "${1}" == "master" ]] ; then
# Shortcut to check out master branches
echo -e " ${INFO} Shortcut \"master\" detected - checking out master branches..."
echo -e " ${INFO} Pi-hole core"
fetch_checkout_pull_branch "${PI_HOLE_FILES_DIR}" "master" || { echo " ${CROSS} Unable to pull Core master branch"; exit 1; }
if [[ ${INSTALL_WEB_INTERFACE} == "true" ]]; then
echo -e " ${INFO} Web interface"
fetch_checkout_pull_branch "${webInterfaceDir}" "master" || { echo " ${CROSS} Unable to pull Web master branch"; exit 1; }
fi
#echo -e " ${TICK} Web Interface"
get_binary_name
local path
path="master/${binary}"
echo "master" > /etc/pihole/ftlbranch
elif [[ "${1}" == "core" ]] ; then
str="Fetching branches from ${piholeGitUrl}"
echo -ne " ${INFO} $str"
if ! fully_fetch_repo "${PI_HOLE_FILES_DIR}" ; then
echo -e "${OVER} ${CROSS} $str"
exit 1
fi
corebranches=($(get_available_branches "${PI_HOLE_FILES_DIR}"))
if [[ "${corebranches[*]}" == *"master"* ]]; then
echo -e "${OVER} ${TICK} $str"
echo -e "${INFO} ${#corebranches[@]} branches available for Pi-hole Core"
else
# Print STDERR output from get_available_branches
echo -e "${OVER} ${CROSS} $str\\n\\n${corebranches[*]}"
exit 1
fi
echo ""
# Have the user choose the branch they want
if ! (for e in "${corebranches[@]}"; do [[ "$e" == "${2}" ]] && exit 0; done); then
echo -e " ${INFO} Requested branch \"${2}\" is not available"
echo -e " ${INFO} Available branches for Core are:"
for e in "${corebranches[@]}"; do echo " - $e"; done
exit 1
fi
checkout_pull_branch "${PI_HOLE_FILES_DIR}" "${2}"
elif [[ "${1}" == "web" ]] && [[ "${INSTALL_WEB_INTERFACE}" == "true" ]] ; then
str="Fetching branches from ${webInterfaceGitUrl}"
echo -ne " ${INFO} $str"
if ! fully_fetch_repo "${webInterfaceDir}" ; then
echo -e "${OVER} ${CROSS} $str"
exit 1
fi
webbranches=($(get_available_branches "${webInterfaceDir}"))
if [[ "${webbranches[*]}" == *"master"* ]]; then
echo -e "${OVER} ${TICK} $str"
echo -e "${INFO} ${#webbranches[@]} branches available for Web Admin"
else
# Print STDERR output from get_available_branches
echo -e "${OVER} ${CROSS} $str\\n\\n${webbranches[*]}"
exit 1
fi
echo ""
# Have the user choose the branch they want
if ! (for e in "${webbranches[@]}"; do [[ "$e" == "${2}" ]] && exit 0; done); then
echo -e " ${INFO} Requested branch \"${2}\" is not available"
echo -e " ${INFO} Available branches for Web Admin are:"
for e in "${webbranches[@]}"; do echo " - $e"; done
exit 1
fi
checkout_pull_branch "${webInterfaceDir}" "${2}"
elif [[ "${1}" == "ftl" ]] ; then
get_binary_name
local path
path="${2}/${binary}"
if check_download_exists "$path"; then
echo " ${TICK} Branch ${2} exists"
echo "${2}" > /etc/pihole/ftlbranch
FTLinstall "${binary}"
start_service pihole-FTL
enable_service pihole-FTL
else
echo " ${CROSS} Requested branch \"${2}\" is not available"
ftlbranches=( $(git ls-remote https://github.com/pi-hole/ftl | grep 'heads' | sed 's/refs\/heads\///;s/ //g' | awk '{print $2}') )
echo -e " ${INFO} Available branches for FTL are:"
for e in "${ftlbranches[@]}"; do echo " - $e"; done
exit 1
fi
else
echo -e " ${INFO} Requested option \"${1}\" is not available"
exit 1
fi
# Force updating everything
if [[ ! "${1}" == "web" && ! "${1}" == "ftl" ]]; then
echo -e " ${INFO} Running installer to upgrade your installation"
if "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" --unattended; then
exit 0
else
echo -e " ${COL_LIGHT_RED} Error: Unable to complete update, please contact support${COL_NC}"
exit 1
fi
fi fi
fi
} }

File diff suppressed because it is too large Load Diff

View File

@ -18,49 +18,49 @@ source ${colfile}
# b) the setting is commented out (e.g. "#DBFILE=...") # b) the setting is commented out (e.g. "#DBFILE=...")
FTLconf="/etc/pihole/pihole-FTL.conf" FTLconf="/etc/pihole/pihole-FTL.conf"
if [ -e "$FTLconf" ]; then if [ -e "$FTLconf" ]; then
DBFILE="$(sed -n -e 's/^\s*DBFILE\s*=\s*//p' ${FTLconf})" DBFILE="$(sed -n -e 's/^\s*DBFILE\s*=\s*//p' ${FTLconf})"
fi fi
# Test for empty string. Use standard path in this case. # Test for empty string. Use standard path in this case.
if [ -z "$DBFILE" ]; then if [ -z "$DBFILE" ]; then
DBFILE="/etc/pihole/pihole-FTL.db" DBFILE="/etc/pihole/pihole-FTL.db"
fi fi
if [[ "$@" != *"quiet"* ]]; then if [[ "$@" != *"quiet"* ]]; then
echo -ne " ${INFO} Flushing /var/log/pihole.log ..." echo -ne " ${INFO} Flushing /var/log/pihole.log ..."
fi fi
if [[ "$@" == *"once"* ]]; then if [[ "$@" == *"once"* ]]; then
# Nightly logrotation # Nightly logrotation
if command -v /usr/sbin/logrotate >/dev/null; then if command -v /usr/sbin/logrotate >/dev/null; then
# Logrotate once # Logrotate once
/usr/sbin/logrotate --force /etc/pihole/logrotate /usr/sbin/logrotate --force /etc/pihole/logrotate
else else
# Copy pihole.log over to pihole.log.1 # Copy pihole.log over to pihole.log.1
# and empty out pihole.log # and empty out pihole.log
# Note that moving the file is not an option, as # Note that moving the file is not an option, as
# dnsmasq would happily continue writing into the # dnsmasq would happily continue writing into the
# moved file (it will have the same file handler) # moved file (it will have the same file handler)
cp /var/log/pihole.log /var/log/pihole.log.1 cp /var/log/pihole.log /var/log/pihole.log.1
echo " " > /var/log/pihole.log echo " " > /var/log/pihole.log
fi
else
# Manual flushing
if command -v /usr/sbin/logrotate >/dev/null; then
# Logrotate twice to move all data out of sight of FTL
/usr/sbin/logrotate --force /etc/pihole/logrotate; sleep 3
/usr/sbin/logrotate --force /etc/pihole/logrotate
else
# Flush both pihole.log and pihole.log.1 (if existing)
echo " " > /var/log/pihole.log
if [ -f /var/log/pihole.log.1 ]; then
echo " " > /var/log/pihole.log.1
fi fi
fi else
# Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history) # Manual flushing
deleted=$(sqlite3 "${DBFILE}" "DELETE FROM queries WHERE timestamp >= strftime('%s','now')-86400; select changes() from queries limit 1") if command -v /usr/sbin/logrotate >/dev/null; then
# Logrotate twice to move all data out of sight of FTL
/usr/sbin/logrotate --force /etc/pihole/logrotate; sleep 3
/usr/sbin/logrotate --force /etc/pihole/logrotate
else
# Flush both pihole.log and pihole.log.1 (if existing)
echo " " > /var/log/pihole.log
if [ -f /var/log/pihole.log.1 ]; then
echo " " > /var/log/pihole.log.1
fi
fi
# Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history)
deleted=$(sqlite3 "${DBFILE}" "DELETE FROM queries WHERE timestamp >= strftime('%s','now')-86400; select changes() from queries limit 1")
fi fi
if [[ "$@" != *"quiet"* ]]; then if [[ "$@" != *"quiet"* ]]; then
echo -e "${OVER} ${TICK} Flushed /var/log/pihole.log" echo -e "${OVER} ${TICK} Flushed /var/log/pihole.log"
echo -e " ${TICK} Deleted ${deleted} queries from database" echo -e " ${TICK} Deleted ${deleted} queries from database"
fi fi

View File

@ -26,42 +26,42 @@ source "${colfile}"
# Print each subdomain # Print each subdomain
# e.g: foo.bar.baz.com = "foo.bar.baz.com bar.baz.com baz.com com" # e.g: foo.bar.baz.com = "foo.bar.baz.com bar.baz.com baz.com com"
processWildcards() { processWildcards() {
IFS="." read -r -a array <<< "${1}" IFS="." read -r -a array <<< "${1}"
for (( i=${#array[@]}-1; i>=0; i-- )); do for (( i=${#array[@]}-1; i>=0; i-- )); do
ar="" ar=""
for (( j=${#array[@]}-1; j>${#array[@]}-i-2; j-- )); do for (( j=${#array[@]}-1; j>${#array[@]}-i-2; j-- )); do
if [[ $j == $((${#array[@]}-1)) ]]; then if [[ $j == $((${#array[@]}-1)) ]]; then
ar="${array[$j]}" ar="${array[$j]}"
else else
ar="${array[$j]}.${ar}" ar="${array[$j]}.${ar}"
fi fi
done
echo "${ar}"
done done
echo "${ar}"
done
} }
# Scan an array of files for matching strings # Scan an array of files for matching strings
scanList(){ scanList(){
# Escape full stops # Escape full stops
local domain="${1//./\\.}" lists="${2}" type="${3:-}" local domain="${1//./\\.}" lists="${2}" type="${3:-}"
# Prevent grep from printing file path # Prevent grep from printing file path
cd "$piholeDir" || exit 1 cd "$piholeDir" || exit 1
# Prevent grep -i matching slowly: http://bit.ly/2xFXtUX # Prevent grep -i matching slowly: http://bit.ly/2xFXtUX
export LC_CTYPE=C export LC_CTYPE=C
# /dev/null forces filename to be printed when only one list has been generated # /dev/null forces filename to be printed when only one list has been generated
# shellcheck disable=SC2086 # shellcheck disable=SC2086
case "${type}" in case "${type}" in
"exact" ) grep -i -E -l "(^|\\s)${domain}($|\\s|#)" ${lists} /dev/null 2>/dev/null;; "exact" ) grep -i -E -l "(^|\\s)${domain}($|\\s|#)" ${lists} /dev/null 2>/dev/null;;
"wc" ) grep -i -o -m 1 "/${domain}/" ${lists} 2>/dev/null;; "wc" ) grep -i -o -m 1 "/${domain}/" ${lists} 2>/dev/null;;
* ) grep -i "${domain}" ${lists} /dev/null 2>/dev/null;; * ) grep -i "${domain}" ${lists} /dev/null 2>/dev/null;;
esac esac
} }
if [[ "${options}" == "-h" ]] || [[ "${options}" == "--help" ]]; then if [[ "${options}" == "-h" ]] || [[ "${options}" == "--help" ]]; then
echo "Usage: pihole -q [option] <domain> echo "Usage: pihole -q [option] <domain>
Example: 'pihole -q -exact domain.com' Example: 'pihole -q -exact domain.com'
Query the adlists for a specified domain Query the adlists for a specified domain
@ -74,19 +74,19 @@ Options:
fi fi
if [[ ! -e "$adListsList" ]]; then if [[ ! -e "$adListsList" ]]; then
echo -e "${COL_LIGHT_RED}The file $adListsList was not found${COL_NC}" echo -e "${COL_LIGHT_RED}The file $adListsList was not found${COL_NC}"
exit 1 exit 1
fi fi
# Handle valid options # Handle valid options
if [[ "${options}" == *"-bp"* ]]; then if [[ "${options}" == *"-bp"* ]]; then
exact="exact"; blockpage=true exact="exact"; blockpage=true
else else
[[ "${options}" == *"-adlist"* ]] && adlist=true [[ "${options}" == *"-adlist"* ]] && adlist=true
[[ "${options}" == *"-all"* ]] && all=true [[ "${options}" == *"-all"* ]] && all=true
if [[ "${options}" == *"-exact"* ]]; then if [[ "${options}" == *"-exact"* ]]; then
exact="exact"; matchType="exact ${matchType}" exact="exact"; matchType="exact ${matchType}"
fi fi
fi fi
# Strip valid options, leaving only the domain and invalid options # Strip valid options, leaving only the domain and invalid options
@ -96,59 +96,59 @@ options=$(sed -E 's/ ?-(bp|adlists?|all|exact) ?//g' <<< "${options}")
# Handle remaining options # Handle remaining options
# If $options contain non ASCII characters, convert to punycode # If $options contain non ASCII characters, convert to punycode
case "${options}" in case "${options}" in
"" ) str="No domain specified";; "" ) str="No domain specified";;
*" "* ) str="Unknown query option specified";; *" "* ) str="Unknown query option specified";;
*[![:ascii:]]* ) domainQuery=$(idn2 "${options}");; *[![:ascii:]]* ) domainQuery=$(idn2 "${options}");;
* ) domainQuery="${options}";; * ) domainQuery="${options}";;
esac esac
if [[ -n "${str:-}" ]]; then if [[ -n "${str:-}" ]]; then
echo -e "${str}${COL_NC}\\nTry 'pihole -q --help' for more information." echo -e "${str}${COL_NC}\\nTry 'pihole -q --help' for more information."
exit 1 exit 1
fi fi
# Scan Whitelist and Blacklist # Scan Whitelist and Blacklist
lists="whitelist.txt blacklist.txt" lists="whitelist.txt blacklist.txt"
mapfile -t results <<< "$(scanList "${domainQuery}" "${lists}" "${exact}")" mapfile -t results <<< "$(scanList "${domainQuery}" "${lists}" "${exact}")"
if [[ -n "${results[*]}" ]]; then if [[ -n "${results[*]}" ]]; then
wbMatch=true wbMatch=true
# Loop through each result in order to print unique file title once # Loop through each result in order to print unique file title once
for result in "${results[@]}"; do for result in "${results[@]}"; do
fileName="${result%%.*}" fileName="${result%%.*}"
if [[ -n "${blockpage}" ]]; then if [[ -n "${blockpage}" ]]; then
echo "π ${result}" echo "π ${result}"
exit 0 exit 0
elif [[ -n "${exact}" ]]; then elif [[ -n "${exact}" ]]; then
echo " ${matchType^} found in ${COL_BOLD}${fileName^}${COL_NC}" echo " ${matchType^} found in ${COL_BOLD}${fileName^}${COL_NC}"
else else
# Only print filename title once per file # Only print filename title once per file
if [[ ! "${fileName}" == "${fileName_prev:-}" ]]; then if [[ ! "${fileName}" == "${fileName_prev:-}" ]]; then
echo " ${matchType^} found in ${COL_BOLD}${fileName^}${COL_NC}" echo " ${matchType^} found in ${COL_BOLD}${fileName^}${COL_NC}"
fileName_prev="${fileName}" fileName_prev="${fileName}"
fi fi
echo " ${result#*:}" echo " ${result#*:}"
fi fi
done done
fi fi
# Scan Wildcards # Scan Wildcards
if [[ -e "${wildcardlist}" ]]; then if [[ -e "${wildcardlist}" ]]; then
# Determine all subdomains, domain and TLDs # Determine all subdomains, domain and TLDs
mapfile -t wildcards <<< "$(processWildcards "${domainQuery}")" mapfile -t wildcards <<< "$(processWildcards "${domainQuery}")"
for match in "${wildcards[@]}"; do for match in "${wildcards[@]}"; do
# Search wildcard list for matches # Search wildcard list for matches
mapfile -t results <<< "$(scanList "${match}" "${wildcardlist}" "wc")" mapfile -t results <<< "$(scanList "${match}" "${wildcardlist}" "wc")"
if [[ -n "${results[*]}" ]]; then if [[ -n "${results[*]}" ]]; then
if [[ -z "${wcMatch:-}" ]] && [[ -z "${blockpage}" ]]; then if [[ -z "${wcMatch:-}" ]] && [[ -z "${blockpage}" ]]; then
wcMatch=true wcMatch=true
echo " ${matchType^} found in ${COL_BOLD}Wildcards${COL_NC}:" echo " ${matchType^} found in ${COL_BOLD}Wildcards${COL_NC}:"
fi fi
case "${blockpage}" in case "${blockpage}" in
true ) echo "π ${wildcardlist##*/}"; exit 0;; true ) echo "π ${wildcardlist##*/}"; exit 0;;
* ) echo " *.${match}";; * ) echo " *.${match}";;
esac esac
fi fi
done done
fi fi
# Get version sorted *.domains filenames (without dir path) # Get version sorted *.domains filenames (without dir path)
@ -159,81 +159,81 @@ mapfile -t results <<< "$(scanList "${domainQuery}" "${lists[*]}" "${exact}")"
# Handle notices # Handle notices
if [[ -z "${wbMatch:-}" ]] && [[ -z "${wcMatch:-}" ]] && [[ -z "${results[*]}" ]]; then if [[ -z "${wbMatch:-}" ]] && [[ -z "${wcMatch:-}" ]] && [[ -z "${results[*]}" ]]; then
echo -e " ${INFO} No ${exact/t/t }results found for ${COL_BOLD}${domainQuery}${COL_NC} within the block lists" echo -e " ${INFO} No ${exact/t/t }results found for ${COL_BOLD}${domainQuery}${COL_NC} within the block lists"
exit 0 exit 0
elif [[ -z "${results[*]}" ]]; then elif [[ -z "${results[*]}" ]]; then
# Result found in WL/BL/Wildcards # Result found in WL/BL/Wildcards
exit 0 exit 0
elif [[ -z "${all}" ]] && [[ "${#results[*]}" -ge 100 ]]; then elif [[ -z "${all}" ]] && [[ "${#results[*]}" -ge 100 ]]; then
echo -e " ${INFO} Over 100 ${exact/t/t }results found for ${COL_BOLD}${domainQuery}${COL_NC} echo -e " ${INFO} Over 100 ${exact/t/t }results found for ${COL_BOLD}${domainQuery}${COL_NC}
This can be overridden using the -all option" This can be overridden using the -all option"
exit 0 exit 0
fi fi
# Remove unwanted content from non-exact $results # Remove unwanted content from non-exact $results
if [[ -z "${exact}" ]]; then if [[ -z "${exact}" ]]; then
# Delete lines starting with # # Delete lines starting with #
# Remove comments after domain # Remove comments after domain
# Remove hosts format IP address # Remove hosts format IP address
mapfile -t results <<< "$(IFS=$'\n'; sed \ mapfile -t results <<< "$(IFS=$'\n'; sed \
-e "/:#/d" \ -e "/:#/d" \
-e "s/[ \\t]#.*//g" \ -e "s/[ \\t]#.*//g" \
-e "s/:.*[ \\t]/:/g" \ -e "s/:.*[ \\t]/:/g" \
<<< "${results[*]}")" <<< "${results[*]}")"
# Exit if result was in a comment # Exit if result was in a comment
[[ -z "${results[*]}" ]] && exit 0 [[ -z "${results[*]}" ]] && exit 0
fi fi
# Get adlist file content as array # Get adlist file content as array
if [[ -n "${adlist}" ]] || [[ -n "${blockpage}" ]]; then if [[ -n "${adlist}" ]] || [[ -n "${blockpage}" ]]; then
for adlistUrl in $(< "${adListsList}"); do for adlistUrl in $(< "${adListsList}"); do
if [[ "${adlistUrl:0:4}" =~ (http|www.) ]]; then if [[ "${adlistUrl:0:4}" =~ (http|www.) ]]; then
adlists+=("${adlistUrl}") adlists+=("${adlistUrl}")
fi fi
done done
fi fi
# Print "Exact matches for" title # Print "Exact matches for" title
if [[ -n "${exact}" ]] && [[ -z "${blockpage}" ]]; then if [[ -n "${exact}" ]] && [[ -z "${blockpage}" ]]; then
plural=""; [[ "${#results[*]}" -gt 1 ]] && plural="es" plural=""; [[ "${#results[*]}" -gt 1 ]] && plural="es"
echo " ${matchType^}${plural} for ${COL_BOLD}${domainQuery}${COL_NC} found in:" echo " ${matchType^}${plural} for ${COL_BOLD}${domainQuery}${COL_NC} found in:"
fi fi
for result in "${results[@]}"; do for result in "${results[@]}"; do
fileName="${result/:*/}" fileName="${result/:*/}"
# Determine *.domains URL using filename's number # Determine *.domains URL using filename's number
if [[ -n "${adlist}" ]] || [[ -n "${blockpage}" ]]; then if [[ -n "${adlist}" ]] || [[ -n "${blockpage}" ]]; then
fileNum="${fileName/list./}"; fileNum="${fileNum%%.*}" fileNum="${fileName/list./}"; fileNum="${fileNum%%.*}"
fileName="${adlists[$fileNum]}" fileName="${adlists[$fileNum]}"
# Discrepency occurs when adlists has been modified, but Gravity has not been run # Discrepency occurs when adlists has been modified, but Gravity has not been run
if [[ -z "${fileName}" ]]; then if [[ -z "${fileName}" ]]; then
fileName="${COL_LIGHT_RED}(no associated adlists URL found)${COL_NC}" fileName="${COL_LIGHT_RED}(no associated adlists URL found)${COL_NC}"
fi
fi fi
fi
if [[ -n "${blockpage}" ]]; then if [[ -n "${blockpage}" ]]; then
echo "${fileNum} ${fileName}" echo "${fileNum} ${fileName}"
elif [[ -n "${exact}" ]]; then elif [[ -n "${exact}" ]]; then
echo " ${fileName}" echo " ${fileName}"
else
if [[ ! "${fileName}" == "${fileName_prev:-}" ]]; then
count=""
echo " ${matchType^} found in ${COL_BOLD}${fileName}${COL_NC}:"
fileName_prev="${fileName}"
fi
: $((count++))
# Print matching domain if $max_count has not been reached
[[ -z "${all}" ]] && max_count="50"
if [[ -z "${all}" ]] && [[ "${count}" -ge "${max_count}" ]]; then
[[ "${count}" -gt "${max_count}" ]] && continue
echo " ${COL_GRAY}Over ${count} results found, skipping rest of file${COL_NC}"
else else
echo " ${result#*:}" if [[ ! "${fileName}" == "${fileName_prev:-}" ]]; then
count=""
echo " ${matchType^} found in ${COL_BOLD}${fileName}${COL_NC}:"
fileName_prev="${fileName}"
fi
: $((count++))
# Print matching domain if $max_count has not been reached
[[ -z "${all}" ]] && max_count="50"
if [[ -z "${all}" ]] && [[ "${count}" -ge "${max_count}" ]]; then
[[ "${count}" -gt "${max_count}" ]] && continue
echo " ${COL_GRAY}Over ${count} results found, skipping rest of file${COL_NC}"
else
echo " ${result#*:}"
fi
fi fi
fi
done done
exit 0 exit 0

View File

@ -15,28 +15,28 @@
# Borrowed from adafruit-pitft-helper < borrowed from raspi-config # Borrowed from adafruit-pitft-helper < borrowed from raspi-config
# https://github.com/adafruit/Adafruit-PiTFT-Helper/blob/master/adafruit-pitft-helper#L324-L334 # https://github.com/adafruit/Adafruit-PiTFT-Helper/blob/master/adafruit-pitft-helper#L324-L334
getInitSys() { getInitSys() {
if command -v systemctl > /dev/null && systemctl | grep -q '\-\.mount'; then if command -v systemctl > /dev/null && systemctl | grep -q '\-\.mount'; then
SYSTEMD=1 SYSTEMD=1
elif [ -f /etc/init.d/cron ] && [ ! -h /etc/init.d/cron ]; then elif [ -f /etc/init.d/cron ] && [ ! -h /etc/init.d/cron ]; then
SYSTEMD=0 SYSTEMD=0
else else
echo "Unrecognised init system" echo "Unrecognised init system"
return 1 return 1
fi fi
} }
# Borrowed from adafruit-pitft-helper: # Borrowed from adafruit-pitft-helper:
# https://github.com/adafruit/Adafruit-PiTFT-Helper/blob/master/adafruit-pitft-helper#L274-L285 # https://github.com/adafruit/Adafruit-PiTFT-Helper/blob/master/adafruit-pitft-helper#L274-L285
autoLoginPiToConsole() { autoLoginPiToConsole() {
if [ -e /etc/init.d/lightdm ]; then if [ -e /etc/init.d/lightdm ]; then
if [ ${SYSTEMD} -eq 1 ]; then if [ ${SYSTEMD} -eq 1 ]; then
systemctl set-default multi-user.target systemctl set-default multi-user.target
ln -fs /etc/systemd/system/autologin@.service /etc/systemd/system/getty.target.wants/getty@tty1.service ln -fs /etc/systemd/system/autologin@.service /etc/systemd/system/getty.target.wants/getty@tty1.service
else else
update-rc.d lightdm disable 2 update-rc.d lightdm disable 2
sed /etc/inittab -i -e "s/1:2345:respawn:\/sbin\/getty --noclear 38400 tty1/1:2345:respawn:\/bin\/login -f pi tty1 <\/dev\/tty1 >\/dev\/tty1 2>&1/" sed /etc/inittab -i -e "s/1:2345:respawn:\/sbin\/getty --noclear 38400 tty1/1:2345:respawn:\/bin\/login -f pi tty1 <\/dev\/tty1 >\/dev\/tty1 2>&1/"
fi fi
fi fi
} }
######### SCRIPT ########### ######### SCRIPT ###########

View File

@ -35,157 +35,157 @@ source "/opt/pihole/COL_TABLE"
# FTLcheckUpdate() sourced from basic-install.sh # FTLcheckUpdate() sourced from basic-install.sh
GitCheckUpdateAvail() { GitCheckUpdateAvail() {
local directory local directory
directory="${1}" directory="${1}"
curdir=$PWD curdir=$PWD
cd "${directory}" || return cd "${directory}" || return
# Fetch latest changes in this repo # Fetch latest changes in this repo
git fetch --quiet origin git fetch --quiet origin
# @ alone is a shortcut for HEAD. Older versions of git # @ alone is a shortcut for HEAD. Older versions of git
# need @{0} # need @{0}
LOCAL="$(git rev-parse "@{0}")" LOCAL="$(git rev-parse "@{0}")"
# The suffix @{upstream} to a branchname # The suffix @{upstream} to a branchname
# (short form <branchname>@{u}) refers # (short form <branchname>@{u}) refers
# to the branch that the branch specified # to the branch that the branch specified
# by branchname is set to build on top of# # by branchname is set to build on top of#
# (configured with branch.<name>.remote and # (configured with branch.<name>.remote and
# branch.<name>.merge). A missing branchname # branch.<name>.merge). A missing branchname
# defaults to the current one. # defaults to the current one.
REMOTE="$(git rev-parse "@{upstream}")" REMOTE="$(git rev-parse "@{upstream}")"
if [[ "${#LOCAL}" == 0 ]]; then if [[ "${#LOCAL}" == 0 ]]; then
echo -e "\\n ${COL_LIGHT_RED}Error: Local revision could not be obtained, please contact Pi-hole Support echo -e "\\n ${COL_LIGHT_RED}Error: Local revision could not be obtained, please contact Pi-hole Support"
Additional debugging output:${COL_NC}" echo -e " Additional debugging output:${COL_NC}"
git status git status
exit exit
fi fi
if [[ "${#REMOTE}" == 0 ]]; then if [[ "${#REMOTE}" == 0 ]]; then
echo -e "\\n ${COL_LIGHT_RED}Error: Remote revision could not be obtained, please contact Pi-hole Support echo -e "\\n ${COL_LIGHT_RED}Error: Remote revision could not be obtained, please contact Pi-hole Support"
Additional debugging output:${COL_NC}" echo -e " Additional debugging output:${COL_NC}"
git status git status
exit exit
fi fi
# Change back to original directory # Change back to original directory
cd "${curdir}" || exit cd "${curdir}" || exit
if [[ "${LOCAL}" != "${REMOTE}" ]]; then if [[ "${LOCAL}" != "${REMOTE}" ]]; then
# Local branch is behind remote branch -> Update # Local branch is behind remote branch -> Update
return 0 return 0
else else
# Local branch is up-to-date or in a situation # Local branch is up-to-date or in a situation
# where this updater cannot be used (like on a # where this updater cannot be used (like on a
# branch that exists only locally) # branch that exists only locally)
return 1 return 1
fi fi
} }
main() { main() {
local basicError="\\n ${COL_LIGHT_RED}Unable to complete update, please contact Pi-hole Support${COL_NC}" local basicError="\\n ${COL_LIGHT_RED}Unable to complete update, please contact Pi-hole Support${COL_NC}"
local core_update local core_update
local web_update local web_update
local FTL_update local FTL_update
core_update=false
web_update=false
FTL_update=false
# shellcheck disable=1090,2154
source "${setupVars}"
# This is unlikely
if ! is_repo "${PI_HOLE_FILES_DIR}" ; then
echo -e "\\n ${COL_LIGHT_RED}Error: Core Pi-hole repo is missing from system!
Please re-run install script from https://pi-hole.net${COL_NC}"
exit 1;
fi
echo -e " ${INFO} Checking for updates..."
if GitCheckUpdateAvail "${PI_HOLE_FILES_DIR}" ; then
core_update=true
echo -e " ${INFO} Pi-hole Core:\\t${COL_YELLOW}update available${COL_NC}"
else
core_update=false core_update=false
echo -e " ${INFO} Pi-hole Core:\\t${COL_LIGHT_GREEN}up to date${COL_NC}" web_update=false
fi
if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
if ! is_repo "${ADMIN_INTERFACE_DIR}" ; then
echo -e "\\n ${COL_LIGHT_RED}Error: Web Admin repo is missing from system!
Please re-run install script from https://pi-hole.net${COL_NC}"
exit 1;
fi
if GitCheckUpdateAvail "${ADMIN_INTERFACE_DIR}" ; then
web_update=true
echo -e " ${INFO} Web Interface:\\t${COL_YELLOW}update available${COL_NC}"
else
web_update=false
echo -e " ${INFO} Web Interface:\\t${COL_LIGHT_GREEN}up to date${COL_NC}"
fi
fi
if FTLcheckUpdate > /dev/null; then
FTL_update=true
echo -e " ${INFO} FTL:\\t\\t${COL_YELLOW}update available${COL_NC}"
else
case $? in
1)
echo -e " ${INFO} FTL:\\t\\t${COL_LIGHT_GREEN}up to date${COL_NC}"
;;
2)
echo -e " ${INFO} FTL:\\t\\t${COL_LIGHT_RED}Branch is not available.${COL_NC}\\n\\t\\t\\tUse ${COL_LIGHT_GREEN}pihole checkout ftl [branchname]${COL_NC} to switch to a valid branch."
;;
*)
echo -e " ${INFO} FTL:\\t\\t${COL_LIGHT_RED}Something has gone wrong, contact support${COL_NC}"
esac
FTL_update=false FTL_update=false
fi
if [[ "${core_update}" == false && "${web_update}" == false && "${FTL_update}" == false ]]; then # shellcheck disable=1090,2154
echo "" source "${setupVars}"
echo -e " ${TICK} Everything is up to date!"
exit 0
fi
if [[ "${CHECK_ONLY}" == true ]]; then # This is unlikely
if ! is_repo "${PI_HOLE_FILES_DIR}" ; then
echo -e "\\n ${COL_LIGHT_RED}Error: Core Pi-hole repo is missing from system!"
echo -e " Please re-run install script from https://pi-hole.net${COL_NC}"
exit 1;
fi
echo -e " ${INFO} Checking for updates..."
if GitCheckUpdateAvail "${PI_HOLE_FILES_DIR}" ; then
core_update=true
echo -e " ${INFO} Pi-hole Core:\\t${COL_YELLOW}update available${COL_NC}"
else
core_update=false
echo -e " ${INFO} Pi-hole Core:\\t${COL_LIGHT_GREEN}up to date${COL_NC}"
fi
if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
if ! is_repo "${ADMIN_INTERFACE_DIR}" ; then
echo -e "\\n ${COL_LIGHT_RED}Error: Web Admin repo is missing from system!"
echo -e " Please re-run install script from https://pi-hole.net${COL_NC}"
exit 1;
fi
if GitCheckUpdateAvail "${ADMIN_INTERFACE_DIR}" ; then
web_update=true
echo -e " ${INFO} Web Interface:\\t${COL_YELLOW}update available${COL_NC}"
else
web_update=false
echo -e " ${INFO} Web Interface:\\t${COL_LIGHT_GREEN}up to date${COL_NC}"
fi
fi
if FTLcheckUpdate > /dev/null; then
FTL_update=true
echo -e " ${INFO} FTL:\\t\\t${COL_YELLOW}update available${COL_NC}"
else
case $? in
1)
echo -e " ${INFO} FTL:\\t\\t${COL_LIGHT_GREEN}up to date${COL_NC}"
;;
2)
echo -e " ${INFO} FTL:\\t\\t${COL_LIGHT_RED}Branch is not available.${COL_NC}\\n\\t\\t\\tUse ${COL_LIGHT_GREEN}pihole checkout ftl [branchname]${COL_NC} to switch to a valid branch."
;;
*)
echo -e " ${INFO} FTL:\\t\\t${COL_LIGHT_RED}Something has gone wrong, contact support${COL_NC}"
esac
FTL_update=false
fi
if [[ "${core_update}" == false && "${web_update}" == false && "${FTL_update}" == false ]]; then
echo ""
echo -e " ${TICK} Everything is up to date!"
exit 0
fi
if [[ "${CHECK_ONLY}" == true ]]; then
echo ""
exit 0
fi
if [[ "${core_update}" == true ]]; then
echo ""
echo -e " ${INFO} Pi-hole core files out of date, updating local repo."
getGitFiles "${PI_HOLE_FILES_DIR}" "${PI_HOLE_GIT_URL}"
echo -e " ${INFO} If you had made any changes in '/etc/.pihole/', they have been stashed using 'git stash'"
fi
if [[ "${web_update}" == true ]]; then
echo ""
echo -e " ${INFO} Pi-hole Web Admin files out of date, updating local repo."
getGitFiles "${ADMIN_INTERFACE_DIR}" "${ADMIN_INTERFACE_GIT_URL}"
echo -e " ${INFO} If you had made any changes in '/var/www/html/admin/', they have been stashed using 'git stash'"
fi
if [[ "${FTL_update}" == true ]]; then
echo ""
echo -e " ${INFO} FTL out of date, it will be updated by the installer."
fi
if [[ "${FTL_update}" == true || "${core_update}" == true ]]; then
${PI_HOLE_FILES_DIR}/automated\ install/basic-install.sh --reconfigure --unattended || \
echo -e "${basicError}" && exit 1
fi
echo "" echo ""
exit 0 exit 0
fi
if [[ "${core_update}" == true ]]; then
echo ""
echo -e " ${INFO} Pi-hole core files out of date, updating local repo."
getGitFiles "${PI_HOLE_FILES_DIR}" "${PI_HOLE_GIT_URL}"
echo -e " ${INFO} If you had made any changes in '/etc/.pihole/', they have been stashed using 'git stash'"
fi
if [[ "${web_update}" == true ]]; then
echo ""
echo -e " ${INFO} Pi-hole Web Admin files out of date, updating local repo."
getGitFiles "${ADMIN_INTERFACE_DIR}" "${ADMIN_INTERFACE_GIT_URL}"
echo -e " ${INFO} If you had made any changes in '/var/www/html/admin/', they have been stashed using 'git stash'"
fi
if [[ "${FTL_update}" == true ]]; then
echo ""
echo -e " ${INFO} FTL out of date, it will be updated by the installer."
fi
if [[ "${FTL_update}" == true || "${core_update}" == true ]]; then
${PI_HOLE_FILES_DIR}/automated\ install/basic-install.sh --reconfigure --unattended || \
echo -e "${basicError}" && exit 1
fi
echo ""
exit 0
} }
if [[ "$1" == "--check-only" ]]; then if [[ "$1" == "--check-only" ]]; then
CHECK_ONLY=true CHECK_ONLY=true
fi fi
main main

View File

@ -10,57 +10,57 @@
# Credit: https://stackoverflow.com/a/46324904 # Credit: https://stackoverflow.com/a/46324904
function json_extract() { function json_extract() {
local key=$1 local key=$1
local json=$2 local json=$2
local string_regex='"([^"\]|\\.)*"' local string_regex='"([^"\]|\\.)*"'
local number_regex='-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?' local number_regex='-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?'
local value_regex="${string_regex}|${number_regex}|true|false|null" local value_regex="${string_regex}|${number_regex}|true|false|null"
local pair_regex="\"${key}\"[[:space:]]*:[[:space:]]*(${value_regex})" local pair_regex="\"${key}\"[[:space:]]*:[[:space:]]*(${value_regex})"
if [[ ${json} =~ ${pair_regex} ]]; then if [[ ${json} =~ ${pair_regex} ]]; then
echo $(sed 's/^"\|"$//g' <<< "${BASH_REMATCH[1]}") echo $(sed 's/^"\|"$//g' <<< "${BASH_REMATCH[1]}")
else else
return 1 return 1
fi fi
} }
function get_local_branch() { function get_local_branch() {
# Return active branch # Return active branch
cd "${1}" 2> /dev/null || return 1 cd "${1}" 2> /dev/null || return 1
git rev-parse --abbrev-ref HEAD || return 1 git rev-parse --abbrev-ref HEAD || return 1
} }
function get_local_version() { function get_local_version() {
# Return active branch # Return active branch
cd "${1}" 2> /dev/null || return 1 cd "${1}" 2> /dev/null || return 1
git describe --long --dirty --tags || return 1 git describe --long --dirty --tags || return 1
} }
if [[ "$2" == "remote" ]]; then if [[ "$2" == "remote" ]]; then
if [[ "$3" == "reboot" ]]; then if [[ "$3" == "reboot" ]]; then
sleep 30 sleep 30
fi fi
GITHUB_CORE_VERSION="$(json_extract tag_name "$(curl -q 'https://api.github.com/repos/pi-hole/pi-hole/releases/latest' 2> /dev/null)")" GITHUB_CORE_VERSION="$(json_extract tag_name "$(curl -q 'https://api.github.com/repos/pi-hole/pi-hole/releases/latest' 2> /dev/null)")"
GITHUB_WEB_VERSION="$(json_extract tag_name "$(curl -q 'https://api.github.com/repos/pi-hole/AdminLTE/releases/latest' 2> /dev/null)")" GITHUB_WEB_VERSION="$(json_extract tag_name "$(curl -q 'https://api.github.com/repos/pi-hole/AdminLTE/releases/latest' 2> /dev/null)")"
GITHUB_FTL_VERSION="$(json_extract tag_name "$(curl -q 'https://api.github.com/repos/pi-hole/FTL/releases/latest' 2> /dev/null)")" GITHUB_FTL_VERSION="$(json_extract tag_name "$(curl -q 'https://api.github.com/repos/pi-hole/FTL/releases/latest' 2> /dev/null)")"
echo -n "${GITHUB_CORE_VERSION} ${GITHUB_WEB_VERSION} ${GITHUB_FTL_VERSION}" > "/etc/pihole/GitHubVersions" echo -n "${GITHUB_CORE_VERSION} ${GITHUB_WEB_VERSION} ${GITHUB_FTL_VERSION}" > "/etc/pihole/GitHubVersions"
else else
CORE_BRANCH="$(get_local_branch /etc/.pihole)" CORE_BRANCH="$(get_local_branch /etc/.pihole)"
WEB_BRANCH="$(get_local_branch /var/www/html/admin)" WEB_BRANCH="$(get_local_branch /var/www/html/admin)"
FTL_BRANCH="$(pihole-FTL branch)" FTL_BRANCH="$(pihole-FTL branch)"
echo -n "${CORE_BRANCH} ${WEB_BRANCH} ${FTL_BRANCH}" > "/etc/pihole/localbranches" echo -n "${CORE_BRANCH} ${WEB_BRANCH} ${FTL_BRANCH}" > "/etc/pihole/localbranches"
CORE_VERSION="$(get_local_version /etc/.pihole)" CORE_VERSION="$(get_local_version /etc/.pihole)"
WEB_VERSION="$(get_local_version /var/www/html/admin)" WEB_VERSION="$(get_local_version /var/www/html/admin)"
FTL_VERSION="$(pihole-FTL version)" FTL_VERSION="$(pihole-FTL version)"
echo -n "${CORE_VERSION} ${WEB_VERSION} ${FTL_VERSION}" > "/etc/pihole/localversions" echo -n "${CORE_VERSION} ${WEB_VERSION} ${FTL_VERSION}" > "/etc/pihole/localversions"
fi fi

View File

@ -14,135 +14,135 @@ COREGITDIR="/etc/.pihole/"
WEBGITDIR="/var/www/html/admin/" WEBGITDIR="/var/www/html/admin/"
getLocalVersion() { getLocalVersion() {
# FTL requires a different method # FTL requires a different method
if [[ "$1" == "FTL" ]]; then if [[ "$1" == "FTL" ]]; then
pihole-FTL version pihole-FTL version
return 0
fi
# Get the tagged version of the local repository
local directory="${1}"
local version
cd "${directory}" 2> /dev/null || { echo "${DEFAULT}"; return 1; }
version=$(git describe --tags --always || echo "$DEFAULT")
if [[ "${version}" =~ ^v ]]; then
echo "${version}"
elif [[ "${version}" == "${DEFAULT}" ]]; then
echo "ERROR"
return 1
else
echo "Untagged"
fi
return 0 return 0
fi
# Get the tagged version of the local repository
local directory="${1}"
local version
cd "${directory}" 2> /dev/null || { echo "${DEFAULT}"; return 1; }
version=$(git describe --tags --always || echo "$DEFAULT")
if [[ "${version}" =~ ^v ]]; then
echo "${version}"
elif [[ "${version}" == "${DEFAULT}" ]]; then
echo "ERROR"
return 1
else
echo "Untagged"
fi
return 0
} }
getLocalHash() { getLocalHash() {
# Local FTL hash does not exist on filesystem # Local FTL hash does not exist on filesystem
if [[ "$1" == "FTL" ]]; then if [[ "$1" == "FTL" ]]; then
echo "N/A" echo "N/A"
return 0
fi
# Get the short hash of the local repository
local directory="${1}"
local hash
cd "${directory}" 2> /dev/null || { echo "${DEFAULT}"; return 1; }
hash=$(git rev-parse --short HEAD || echo "$DEFAULT")
if [[ "${hash}" == "${DEFAULT}" ]]; then
echo "ERROR"
return 1
else
echo "${hash}"
fi
return 0 return 0
fi
# Get the short hash of the local repository
local directory="${1}"
local hash
cd "${directory}" 2> /dev/null || { echo "${DEFAULT}"; return 1; }
hash=$(git rev-parse --short HEAD || echo "$DEFAULT")
if [[ "${hash}" == "${DEFAULT}" ]]; then
echo "ERROR"
return 1
else
echo "${hash}"
fi
return 0
} }
getRemoteHash(){ getRemoteHash(){
# Remote FTL hash is not applicable # Remote FTL hash is not applicable
if [[ "$1" == "FTL" ]]; then if [[ "$1" == "FTL" ]]; then
echo "N/A" echo "N/A"
return 0
fi
local daemon="${1}"
local branch="${2}"
hash=$(git ls-remote --heads "https://github.com/pi-hole/${daemon}" | \
awk -v bra="$branch" '$0~bra {print substr($0,0,8);exit}')
if [[ -n "$hash" ]]; then
echo "$hash"
else
echo "ERROR"
return 1
fi
return 0 return 0
fi
local daemon="${1}"
local branch="${2}"
hash=$(git ls-remote --heads "https://github.com/pi-hole/${daemon}" | \
awk -v bra="$branch" '$0~bra {print substr($0,0,8);exit}')
if [[ -n "$hash" ]]; then
echo "$hash"
else
echo "ERROR"
return 1
fi
return 0
} }
getRemoteVersion(){ getRemoteVersion(){
# Get the version from the remote origin # Get the version from the remote origin
local daemon="${1}" local daemon="${1}"
local version local version
version=$(curl --silent --fail "https://api.github.com/repos/pi-hole/${daemon}/releases/latest" | \ version=$(curl --silent --fail "https://api.github.com/repos/pi-hole/${daemon}/releases/latest" | \
awk -F: '$1 ~/tag_name/ { print $2 }' | \ awk -F: '$1 ~/tag_name/ { print $2 }' | \
tr -cd '[[:alnum:]]._-') tr -cd '[[:alnum:]]._-')
if [[ "${version}" =~ ^v ]]; then if [[ "${version}" =~ ^v ]]; then
echo "${version}" echo "${version}"
else else
echo "ERROR" echo "ERROR"
return 1 return 1
fi fi
return 0 return 0
} }
versionOutput() { versionOutput() {
[[ "$1" == "pi-hole" ]] && GITDIR=$COREGITDIR [[ "$1" == "pi-hole" ]] && GITDIR=$COREGITDIR
[[ "$1" == "AdminLTE" ]] && GITDIR=$WEBGITDIR [[ "$1" == "AdminLTE" ]] && GITDIR=$WEBGITDIR
[[ "$1" == "FTL" ]] && GITDIR="FTL" [[ "$1" == "FTL" ]] && GITDIR="FTL"
[[ "$2" == "-c" ]] || [[ "$2" == "--current" ]] || [[ -z "$2" ]] && current=$(getLocalVersion $GITDIR) [[ "$2" == "-c" ]] || [[ "$2" == "--current" ]] || [[ -z "$2" ]] && current=$(getLocalVersion $GITDIR)
[[ "$2" == "-l" ]] || [[ "$2" == "--latest" ]] || [[ -z "$2" ]] && latest=$(getRemoteVersion "$1") [[ "$2" == "-l" ]] || [[ "$2" == "--latest" ]] || [[ -z "$2" ]] && latest=$(getRemoteVersion "$1")
if [[ "$2" == "-h" ]] || [[ "$2" == "--hash" ]]; then if [[ "$2" == "-h" ]] || [[ "$2" == "--hash" ]]; then
[[ "$3" == "-c" ]] || [[ "$3" == "--current" ]] || [[ -z "$3" ]] && curHash=$(getLocalHash "$GITDIR") [[ "$3" == "-c" ]] || [[ "$3" == "--current" ]] || [[ -z "$3" ]] && curHash=$(getLocalHash "$GITDIR")
[[ "$3" == "-l" ]] || [[ "$3" == "--latest" ]] || [[ -z "$3" ]] && latHash=$(getRemoteHash "$1" "$(cd "$GITDIR" 2> /dev/null && git rev-parse --abbrev-ref HEAD)") [[ "$3" == "-l" ]] || [[ "$3" == "--latest" ]] || [[ -z "$3" ]] && latHash=$(getRemoteHash "$1" "$(cd "$GITDIR" 2> /dev/null && git rev-parse --abbrev-ref HEAD)")
fi fi
if [[ -n "$current" ]] && [[ -n "$latest" ]]; then if [[ -n "$current" ]] && [[ -n "$latest" ]]; then
output="${1^} version is $current (Latest: $latest)" output="${1^} version is $current (Latest: $latest)"
elif [[ -n "$current" ]] && [[ -z "$latest" ]]; then elif [[ -n "$current" ]] && [[ -z "$latest" ]]; then
output="Current ${1^} version is $current" output="Current ${1^} version is $current"
elif [[ -z "$current" ]] && [[ -n "$latest" ]]; then elif [[ -z "$current" ]] && [[ -n "$latest" ]]; then
output="Latest ${1^} version is $latest" output="Latest ${1^} version is $latest"
elif [[ "$curHash" == "N/A" ]] || [[ "$latHash" == "N/A" ]]; then elif [[ "$curHash" == "N/A" ]] || [[ "$latHash" == "N/A" ]]; then
output="${1^} hash is not applicable" output="${1^} hash is not applicable"
elif [[ -n "$curHash" ]] && [[ -n "$latHash" ]]; then elif [[ -n "$curHash" ]] && [[ -n "$latHash" ]]; then
output="${1^} hash is $curHash (Latest: $latHash)" output="${1^} hash is $curHash (Latest: $latHash)"
elif [[ -n "$curHash" ]] && [[ -z "$latHash" ]]; then elif [[ -n "$curHash" ]] && [[ -z "$latHash" ]]; then
output="Current ${1^} hash is $curHash" output="Current ${1^} hash is $curHash"
elif [[ -z "$curHash" ]] && [[ -n "$latHash" ]]; then elif [[ -z "$curHash" ]] && [[ -n "$latHash" ]]; then
output="Latest ${1^} hash is $latHash" output="Latest ${1^} hash is $latHash"
else else
errorOutput errorOutput
fi fi
[[ -n "$output" ]] && echo " $output" [[ -n "$output" ]] && echo " $output"
} }
errorOutput() { errorOutput() {
echo " Invalid Option! Try 'pihole -v --help' for more information." echo " Invalid Option! Try 'pihole -v --help' for more information."
exit 1 exit 1
} }
defaultOutput() { defaultOutput() {
versionOutput "pi-hole" "$@" versionOutput "pi-hole" "$@"
versionOutput "AdminLTE" "$@" versionOutput "AdminLTE" "$@"
versionOutput "FTL" "$@" versionOutput "FTL" "$@"
} }
helpFunc() { helpFunc() {
echo "Usage: pihole -v [repo | option] [option] echo "Usage: pihole -v [repo | option] [option]
Example: 'pihole -v -p -l' Example: 'pihole -v -p -l'
Show Pi-hole, Admin Console & FTL versions Show Pi-hole, Admin Console & FTL versions
@ -160,9 +160,9 @@ Options:
} }
case "${1}" in case "${1}" in
"-p" | "--pihole" ) shift; versionOutput "pi-hole" "$@";; "-p" | "--pihole" ) shift; versionOutput "pi-hole" "$@";;
"-a" | "--admin" ) shift; versionOutput "AdminLTE" "$@";; "-a" | "--admin" ) shift; versionOutput "AdminLTE" "$@";;
"-f" | "--ftl" ) shift; versionOutput "FTL" "$@";; "-f" | "--ftl" ) shift; versionOutput "FTL" "$@";;
"-h" | "--help" ) helpFunc;; "-h" | "--help" ) helpFunc;;
* ) defaultOutput "$@";; * ) defaultOutput "$@";;
esac esac

View File

@ -19,11 +19,11 @@ readonly dhcpstaticconfig="/etc/dnsmasq.d/04-pihole-static-dhcp.conf"
coltable="/opt/pihole/COL_TABLE" coltable="/opt/pihole/COL_TABLE"
if [[ -f ${coltable} ]]; then if [[ -f ${coltable} ]]; then
source ${coltable} source ${coltable}
fi fi
helpFunc() { helpFunc() {
echo "Usage: pihole -a [options] echo "Usage: pihole -a [options]
Example: pihole -a -p password Example: pihole -a -p password
Set options for the Admin Console Set options for the Admin Console
@ -37,277 +37,277 @@ Options:
-h, --help Show this help dialog -h, --help Show this help dialog
-i, interface Specify dnsmasq's interface listening behavior -i, interface Specify dnsmasq's interface listening behavior
-l, privacylevel Set privacy level (0 = lowest, 3 = highest)" -l, privacylevel Set privacy level (0 = lowest, 3 = highest)"
exit 0 exit 0
} }
add_setting() { add_setting() {
echo "${1}=${2}" >> "${setupVars}" echo "${1}=${2}" >> "${setupVars}"
} }
delete_setting() { delete_setting() {
sed -i "/${1}/d" "${setupVars}" sed -i "/${1}/d" "${setupVars}"
} }
change_setting() { change_setting() {
delete_setting "${1}" delete_setting "${1}"
add_setting "${1}" "${2}" add_setting "${1}" "${2}"
} }
addFTLsetting() { addFTLsetting() {
echo "${1}=${2}" >> "${FTLconf}" echo "${1}=${2}" >> "${FTLconf}"
} }
deleteFTLsetting() { deleteFTLsetting() {
sed -i "/${1}/d" "${FTLconf}" sed -i "/${1}/d" "${FTLconf}"
} }
changeFTLsetting() { changeFTLsetting() {
deleteFTLsetting "${1}" deleteFTLsetting "${1}"
addFTLsetting "${1}" "${2}" addFTLsetting "${1}" "${2}"
} }
add_dnsmasq_setting() { add_dnsmasq_setting() {
if [[ "${2}" != "" ]]; then if [[ "${2}" != "" ]]; then
echo "${1}=${2}" >> "${dnsmasqconfig}" echo "${1}=${2}" >> "${dnsmasqconfig}"
else else
echo "${1}" >> "${dnsmasqconfig}" echo "${1}" >> "${dnsmasqconfig}"
fi fi
} }
delete_dnsmasq_setting() { delete_dnsmasq_setting() {
sed -i "/${1}/d" "${dnsmasqconfig}" sed -i "/${1}/d" "${dnsmasqconfig}"
} }
SetTemperatureUnit() { SetTemperatureUnit() {
change_setting "TEMPERATUREUNIT" "${unit}" change_setting "TEMPERATUREUNIT" "${unit}"
echo -e " ${TICK} Set temperature unit to ${unit}" echo -e " ${TICK} Set temperature unit to ${unit}"
} }
HashPassword() { HashPassword() {
# Compute password hash twice to avoid rainbow table vulnerability # Compute password hash twice to avoid rainbow table vulnerability
return=$(echo -n ${1} | sha256sum | sed 's/\s.*$//') return=$(echo -n ${1} | sha256sum | sed 's/\s.*$//')
return=$(echo -n ${return} | sha256sum | sed 's/\s.*$//') return=$(echo -n ${return} | sha256sum | sed 's/\s.*$//')
echo ${return} echo ${return}
} }
SetWebPassword() { SetWebPassword() {
if [ "${SUDO_USER}" == "www-data" ]; then if [ "${SUDO_USER}" == "www-data" ]; then
echo "Security measure: user www-data is not allowed to change webUI password!" echo "Security measure: user www-data is not allowed to change webUI password!"
echo "Exiting" echo "Exiting"
exit 1 exit 1
fi fi
if [ "${SUDO_USER}" == "lighttpd" ]; then if [ "${SUDO_USER}" == "lighttpd" ]; then
echo "Security measure: user lighttpd is not allowed to change webUI password!" echo "Security measure: user lighttpd is not allowed to change webUI password!"
echo "Exiting" echo "Exiting"
exit 1 exit 1
fi fi
if (( ${#args[2]} > 0 )) ; then if (( ${#args[2]} > 0 )) ; then
readonly PASSWORD="${args[2]}" readonly PASSWORD="${args[2]}"
readonly CONFIRM="${PASSWORD}" readonly CONFIRM="${PASSWORD}"
else else
# Prevents a bug if the user presses Ctrl+C and it continues to hide the text typed. # Prevents a bug if the user presses Ctrl+C and it continues to hide the text typed.
# So we reset the terminal via stty if the user does press Ctrl+C # So we reset the terminal via stty if the user does press Ctrl+C
trap '{ echo -e "\nNo password will be set" ; stty sane ; exit 1; }' INT trap '{ echo -e "\nNo password will be set" ; stty sane ; exit 1; }' INT
read -s -p "Enter New Password (Blank for no password): " PASSWORD read -s -p "Enter New Password (Blank for no password): " PASSWORD
echo "" echo ""
if [ "${PASSWORD}" == "" ]; then if [ "${PASSWORD}" == "" ]; then
change_setting "WEBPASSWORD" "" change_setting "WEBPASSWORD" ""
echo -e " ${TICK} Password Removed" echo -e " ${TICK} Password Removed"
exit 0 exit 0
fi fi
read -s -p "Confirm Password: " CONFIRM read -s -p "Confirm Password: " CONFIRM
echo "" echo ""
fi fi
if [ "${PASSWORD}" == "${CONFIRM}" ] ; then if [ "${PASSWORD}" == "${CONFIRM}" ] ; then
hash=$(HashPassword "${PASSWORD}") hash=$(HashPassword "${PASSWORD}")
# Save hash to file # Save hash to file
change_setting "WEBPASSWORD" "${hash}" change_setting "WEBPASSWORD" "${hash}"
echo -e " ${TICK} New password set" echo -e " ${TICK} New password set"
else else
echo -e " ${CROSS} Passwords don't match. Your password has not been changed" echo -e " ${CROSS} Passwords don't match. Your password has not been changed"
exit 1 exit 1
fi fi
} }
ProcessDNSSettings() { ProcessDNSSettings() {
source "${setupVars}" source "${setupVars}"
delete_dnsmasq_setting "server" delete_dnsmasq_setting "server"
COUNTER=1 COUNTER=1
while [[ 1 ]]; do while [[ 1 ]]; do
var=PIHOLE_DNS_${COUNTER} var=PIHOLE_DNS_${COUNTER}
if [ -z "${!var}" ]; then if [ -z "${!var}" ]; then
break; break;
fi fi
add_dnsmasq_setting "server" "${!var}" add_dnsmasq_setting "server" "${!var}"
let COUNTER=COUNTER+1 let COUNTER=COUNTER+1
done done
# The option LOCAL_DNS_PORT is deprecated # The option LOCAL_DNS_PORT is deprecated
# We apply it once more, and then convert it into the current format # We apply it once more, and then convert it into the current format
if [ ! -z "${LOCAL_DNS_PORT}" ]; then if [ ! -z "${LOCAL_DNS_PORT}" ]; then
add_dnsmasq_setting "server" "127.0.0.1#${LOCAL_DNS_PORT}" add_dnsmasq_setting "server" "127.0.0.1#${LOCAL_DNS_PORT}"
add_setting "PIHOLE_DNS_${COUNTER}" "127.0.0.1#${LOCAL_DNS_PORT}" add_setting "PIHOLE_DNS_${COUNTER}" "127.0.0.1#${LOCAL_DNS_PORT}"
delete_setting "LOCAL_DNS_PORT" delete_setting "LOCAL_DNS_PORT"
fi fi
delete_dnsmasq_setting "domain-needed" delete_dnsmasq_setting "domain-needed"
if [[ "${DNS_FQDN_REQUIRED}" == true ]]; then if [[ "${DNS_FQDN_REQUIRED}" == true ]]; then
add_dnsmasq_setting "domain-needed" add_dnsmasq_setting "domain-needed"
fi fi
delete_dnsmasq_setting "bogus-priv" delete_dnsmasq_setting "bogus-priv"
if [[ "${DNS_BOGUS_PRIV}" == true ]]; then if [[ "${DNS_BOGUS_PRIV}" == true ]]; then
add_dnsmasq_setting "bogus-priv" add_dnsmasq_setting "bogus-priv"
fi fi
delete_dnsmasq_setting "dnssec" delete_dnsmasq_setting "dnssec"
delete_dnsmasq_setting "trust-anchor=" delete_dnsmasq_setting "trust-anchor="
if [[ "${DNSSEC}" == true ]]; then if [[ "${DNSSEC}" == true ]]; then
echo "dnssec echo "dnssec
trust-anchor=.,19036,8,2,49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5 trust-anchor=.,19036,8,2,49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D
" >> "${dnsmasqconfig}" " >> "${dnsmasqconfig}"
fi fi
delete_dnsmasq_setting "host-record" delete_dnsmasq_setting "host-record"
if [ ! -z "${HOSTRECORD}" ]; then if [ ! -z "${HOSTRECORD}" ]; then
add_dnsmasq_setting "host-record" "${HOSTRECORD}" add_dnsmasq_setting "host-record" "${HOSTRECORD}"
fi fi
# Setup interface listening behavior of dnsmasq # Setup interface listening behavior of dnsmasq
delete_dnsmasq_setting "interface" delete_dnsmasq_setting "interface"
delete_dnsmasq_setting "local-service" delete_dnsmasq_setting "local-service"
if [[ "${DNSMASQ_LISTENING}" == "all" ]]; then if [[ "${DNSMASQ_LISTENING}" == "all" ]]; then
# Listen on all interfaces, permit all origins # Listen on all interfaces, permit all origins
add_dnsmasq_setting "except-interface" "nonexisting" add_dnsmasq_setting "except-interface" "nonexisting"
elif [[ "${DNSMASQ_LISTENING}" == "local" ]]; then elif [[ "${DNSMASQ_LISTENING}" == "local" ]]; then
# Listen only on all interfaces, but only local subnets # Listen only on all interfaces, but only local subnets
add_dnsmasq_setting "local-service" add_dnsmasq_setting "local-service"
else else
# Listen only on one interface # Listen only on one interface
# Use eth0 as fallback interface if interface is missing in setupVars.conf # Use eth0 as fallback interface if interface is missing in setupVars.conf
if [ -z "${PIHOLE_INTERFACE}" ]; then if [ -z "${PIHOLE_INTERFACE}" ]; then
PIHOLE_INTERFACE="eth0" PIHOLE_INTERFACE="eth0"
fi fi
add_dnsmasq_setting "interface" "${PIHOLE_INTERFACE}" add_dnsmasq_setting "interface" "${PIHOLE_INTERFACE}"
fi fi
if [[ "${CONDITIONAL_FORWARDING}" == true ]]; then if [[ "${CONDITIONAL_FORWARDING}" == true ]]; then
add_dnsmasq_setting "server=/${CONDITIONAL_FORWARDING_DOMAIN}/${CONDITIONAL_FORWARDING_IP}" add_dnsmasq_setting "server=/${CONDITIONAL_FORWARDING_DOMAIN}/${CONDITIONAL_FORWARDING_IP}"
add_dnsmasq_setting "server=/${CONDITIONAL_FORWARDING_REVERSE}/${CONDITIONAL_FORWARDING_IP}" add_dnsmasq_setting "server=/${CONDITIONAL_FORWARDING_REVERSE}/${CONDITIONAL_FORWARDING_IP}"
fi fi
} }
SetDNSServers() { SetDNSServers() {
# Save setting to file # Save setting to file
delete_setting "PIHOLE_DNS" delete_setting "PIHOLE_DNS"
IFS=',' read -r -a array <<< "${args[2]}" IFS=',' read -r -a array <<< "${args[2]}"
for index in "${!array[@]}" for index in "${!array[@]}"
do do
add_setting "PIHOLE_DNS_$((index+1))" "${array[index]}" add_setting "PIHOLE_DNS_$((index+1))" "${array[index]}"
done done
if [[ "${args[3]}" == "domain-needed" ]]; then if [[ "${args[3]}" == "domain-needed" ]]; then
change_setting "DNS_FQDN_REQUIRED" "true" change_setting "DNS_FQDN_REQUIRED" "true"
else else
change_setting "DNS_FQDN_REQUIRED" "false" change_setting "DNS_FQDN_REQUIRED" "false"
fi fi
if [[ "${args[4]}" == "bogus-priv" ]]; then if [[ "${args[4]}" == "bogus-priv" ]]; then
change_setting "DNS_BOGUS_PRIV" "true" change_setting "DNS_BOGUS_PRIV" "true"
else else
change_setting "DNS_BOGUS_PRIV" "false" change_setting "DNS_BOGUS_PRIV" "false"
fi fi
if [[ "${args[5]}" == "dnssec" ]]; then if [[ "${args[5]}" == "dnssec" ]]; then
change_setting "DNSSEC" "true" change_setting "DNSSEC" "true"
else else
change_setting "DNSSEC" "false" change_setting "DNSSEC" "false"
fi fi
if [[ "${args[6]}" == "conditional_forwarding" ]]; then if [[ "${args[6]}" == "conditional_forwarding" ]]; then
change_setting "CONDITIONAL_FORWARDING" "true" change_setting "CONDITIONAL_FORWARDING" "true"
change_setting "CONDITIONAL_FORWARDING_IP" "${args[7]}" change_setting "CONDITIONAL_FORWARDING_IP" "${args[7]}"
change_setting "CONDITIONAL_FORWARDING_DOMAIN" "${args[8]}" change_setting "CONDITIONAL_FORWARDING_DOMAIN" "${args[8]}"
change_setting "CONDITIONAL_FORWARDING_REVERSE" "${args[9]}" change_setting "CONDITIONAL_FORWARDING_REVERSE" "${args[9]}"
else else
change_setting "CONDITIONAL_FORWARDING" "false" change_setting "CONDITIONAL_FORWARDING" "false"
delete_setting "CONDITIONAL_FORWARDING_IP" delete_setting "CONDITIONAL_FORWARDING_IP"
delete_setting "CONDITIONAL_FORWARDING_DOMAIN" delete_setting "CONDITIONAL_FORWARDING_DOMAIN"
delete_setting "CONDITIONAL_FORWARDING_REVERSE" delete_setting "CONDITIONAL_FORWARDING_REVERSE"
fi fi
ProcessDNSSettings ProcessDNSSettings
# Restart dnsmasq to load new configuration # Restart dnsmasq to load new configuration
RestartDNS RestartDNS
} }
SetExcludeDomains() { SetExcludeDomains() {
change_setting "API_EXCLUDE_DOMAINS" "${args[2]}" change_setting "API_EXCLUDE_DOMAINS" "${args[2]}"
} }
SetExcludeClients() { SetExcludeClients() {
change_setting "API_EXCLUDE_CLIENTS" "${args[2]}" change_setting "API_EXCLUDE_CLIENTS" "${args[2]}"
} }
Poweroff(){ Poweroff(){
nohup bash -c "sleep 5; poweroff" &> /dev/null </dev/null & nohup bash -c "sleep 5; poweroff" &> /dev/null </dev/null &
} }
Reboot() { Reboot() {
nohup bash -c "sleep 5; reboot" &> /dev/null </dev/null & nohup bash -c "sleep 5; reboot" &> /dev/null </dev/null &
} }
RestartDNS() { RestartDNS() {
/usr/local/bin/pihole restartdns /usr/local/bin/pihole restartdns
} }
SetQueryLogOptions() { SetQueryLogOptions() {
change_setting "API_QUERY_LOG_SHOW" "${args[2]}" change_setting "API_QUERY_LOG_SHOW" "${args[2]}"
} }
ProcessDHCPSettings() { ProcessDHCPSettings() {
source "${setupVars}" source "${setupVars}"
if [[ "${DHCP_ACTIVE}" == "true" ]]; then if [[ "${DHCP_ACTIVE}" == "true" ]]; then
interface="${PIHOLE_INTERFACE}" interface="${PIHOLE_INTERFACE}"
# Use eth0 as fallback interface # Use eth0 as fallback interface
if [ -z ${interface} ]; then if [ -z ${interface} ]; then
interface="eth0" interface="eth0"
fi fi
if [[ "${PIHOLE_DOMAIN}" == "" ]]; then if [[ "${PIHOLE_DOMAIN}" == "" ]]; then
PIHOLE_DOMAIN="lan" PIHOLE_DOMAIN="lan"
change_setting "PIHOLE_DOMAIN" "${PIHOLE_DOMAIN}" change_setting "PIHOLE_DOMAIN" "${PIHOLE_DOMAIN}"
fi fi
if [[ "${DHCP_LEASETIME}" == "0" ]]; then if [[ "${DHCP_LEASETIME}" == "0" ]]; then
leasetime="infinite" leasetime="infinite"
elif [[ "${DHCP_LEASETIME}" == "" ]]; then elif [[ "${DHCP_LEASETIME}" == "" ]]; then
leasetime="24" leasetime="24"
change_setting "DHCP_LEASETIME" "${leasetime}" change_setting "DHCP_LEASETIME" "${leasetime}"
elif [[ "${DHCP_LEASETIME}" == "24h" ]]; then elif [[ "${DHCP_LEASETIME}" == "24h" ]]; then
#Installation is affected by known bug, introduced in a previous version. #Installation is affected by known bug, introduced in a previous version.
#This will automatically clean up setupVars.conf and remove the unnecessary "h" #This will automatically clean up setupVars.conf and remove the unnecessary "h"
leasetime="24" leasetime="24"
change_setting "DHCP_LEASETIME" "${leasetime}" change_setting "DHCP_LEASETIME" "${leasetime}"
else else
leasetime="${DHCP_LEASETIME}h" leasetime="${DHCP_LEASETIME}h"
fi fi
# Write settings to file # Write settings to file
@ -322,12 +322,12 @@ dhcp-leasefile=/etc/pihole/dhcp.leases
#quiet-dhcp #quiet-dhcp
" > "${dhcpconfig}" " > "${dhcpconfig}"
if [[ "${PIHOLE_DOMAIN}" != "none" ]]; then if [[ "${PIHOLE_DOMAIN}" != "none" ]]; then
echo "domain=${PIHOLE_DOMAIN}" >> "${dhcpconfig}" echo "domain=${PIHOLE_DOMAIN}" >> "${dhcpconfig}"
fi fi
if [[ "${DHCP_IPv6}" == "true" ]]; then if [[ "${DHCP_IPv6}" == "true" ]]; then
echo "#quiet-dhcp6 echo "#quiet-dhcp6
#enable-ra #enable-ra
dhcp-option=option6:dns-server,[::] dhcp-option=option6:dns-server,[::]
dhcp-range=::100,::1ff,constructor:${interface},ra-names,slaac,${leasetime} dhcp-range=::100,::1ff,constructor:${interface},ra-names,slaac,${leasetime}
@ -335,160 +335,160 @@ ra-param=*,0,0
" >> "${dhcpconfig}" " >> "${dhcpconfig}"
fi fi
else else
if [[ -f "${dhcpconfig}" ]]; then if [[ -f "${dhcpconfig}" ]]; then
rm "${dhcpconfig}" &> /dev/null rm "${dhcpconfig}" &> /dev/null
fi fi
fi fi
} }
EnableDHCP() { EnableDHCP() {
change_setting "DHCP_ACTIVE" "true" change_setting "DHCP_ACTIVE" "true"
change_setting "DHCP_START" "${args[2]}" change_setting "DHCP_START" "${args[2]}"
change_setting "DHCP_END" "${args[3]}" change_setting "DHCP_END" "${args[3]}"
change_setting "DHCP_ROUTER" "${args[4]}" change_setting "DHCP_ROUTER" "${args[4]}"
change_setting "DHCP_LEASETIME" "${args[5]}" change_setting "DHCP_LEASETIME" "${args[5]}"
change_setting "PIHOLE_DOMAIN" "${args[6]}" change_setting "PIHOLE_DOMAIN" "${args[6]}"
change_setting "DHCP_IPv6" "${args[7]}" change_setting "DHCP_IPv6" "${args[7]}"
# Remove possible old setting from file # Remove possible old setting from file
delete_dnsmasq_setting "dhcp-" delete_dnsmasq_setting "dhcp-"
delete_dnsmasq_setting "quiet-dhcp" delete_dnsmasq_setting "quiet-dhcp"
ProcessDHCPSettings ProcessDHCPSettings
RestartDNS RestartDNS
} }
DisableDHCP() { DisableDHCP() {
change_setting "DHCP_ACTIVE" "false" change_setting "DHCP_ACTIVE" "false"
# Remove possible old setting from file # Remove possible old setting from file
delete_dnsmasq_setting "dhcp-" delete_dnsmasq_setting "dhcp-"
delete_dnsmasq_setting "quiet-dhcp" delete_dnsmasq_setting "quiet-dhcp"
ProcessDHCPSettings ProcessDHCPSettings
RestartDNS RestartDNS
} }
SetWebUILayout() { SetWebUILayout() {
change_setting "WEBUIBOXEDLAYOUT" "${args[2]}" change_setting "WEBUIBOXEDLAYOUT" "${args[2]}"
} }
CustomizeAdLists() { CustomizeAdLists() {
list="/etc/pihole/adlists.list" list="/etc/pihole/adlists.list"
if [[ "${args[2]}" == "enable" ]]; then if [[ "${args[2]}" == "enable" ]]; then
sed -i "\\@${args[3]}@s/^#http/http/g" "${list}" sed -i "\\@${args[3]}@s/^#http/http/g" "${list}"
elif [[ "${args[2]}" == "disable" ]]; then elif [[ "${args[2]}" == "disable" ]]; then
sed -i "\\@${args[3]}@s/^http/#http/g" "${list}" sed -i "\\@${args[3]}@s/^http/#http/g" "${list}"
elif [[ "${args[2]}" == "add" ]]; then elif [[ "${args[2]}" == "add" ]]; then
if [[ $(grep -c "^${args[3]}$" "${list}") -eq 0 ]] ; then if [[ $(grep -c "^${args[3]}$" "${list}") -eq 0 ]] ; then
echo "${args[3]}" >> ${list} echo "${args[3]}" >> ${list}
fi fi
elif [[ "${args[2]}" == "del" ]]; then elif [[ "${args[2]}" == "del" ]]; then
var=$(echo "${args[3]}" | sed 's/\//\\\//g') var=$(echo "${args[3]}" | sed 's/\//\\\//g')
sed -i "/${var}/Id" "${list}" sed -i "/${var}/Id" "${list}"
else else
echo "Not permitted" echo "Not permitted"
return 1 return 1
fi fi
} }
SetPrivacyMode() { SetPrivacyMode() {
if [[ "${args[2]}" == "true" ]]; then if [[ "${args[2]}" == "true" ]]; then
change_setting "API_PRIVACY_MODE" "true" change_setting "API_PRIVACY_MODE" "true"
else else
change_setting "API_PRIVACY_MODE" "false" change_setting "API_PRIVACY_MODE" "false"
fi fi
} }
ResolutionSettings() { ResolutionSettings() {
typ="${args[2]}" typ="${args[2]}"
state="${args[3]}" state="${args[3]}"
if [[ "${typ}" == "forward" ]]; then if [[ "${typ}" == "forward" ]]; then
change_setting "API_GET_UPSTREAM_DNS_HOSTNAME" "${state}" change_setting "API_GET_UPSTREAM_DNS_HOSTNAME" "${state}"
elif [[ "${typ}" == "clients" ]]; then elif [[ "${typ}" == "clients" ]]; then
change_setting "API_GET_CLIENT_HOSTNAME" "${state}" change_setting "API_GET_CLIENT_HOSTNAME" "${state}"
fi fi
} }
AddDHCPStaticAddress() { AddDHCPStaticAddress() {
mac="${args[2]}" mac="${args[2]}"
ip="${args[3]}" ip="${args[3]}"
host="${args[4]}" host="${args[4]}"
if [[ "${ip}" == "noip" ]]; then if [[ "${ip}" == "noip" ]]; then
# Static host name # Static host name
echo "dhcp-host=${mac},${host}" >> "${dhcpstaticconfig}" echo "dhcp-host=${mac},${host}" >> "${dhcpstaticconfig}"
elif [[ "${host}" == "nohost" ]]; then elif [[ "${host}" == "nohost" ]]; then
# Static IP # Static IP
echo "dhcp-host=${mac},${ip}" >> "${dhcpstaticconfig}" echo "dhcp-host=${mac},${ip}" >> "${dhcpstaticconfig}"
else else
# Full info given # Full info given
echo "dhcp-host=${mac},${ip},${host}" >> "${dhcpstaticconfig}" echo "dhcp-host=${mac},${ip},${host}" >> "${dhcpstaticconfig}"
fi fi
} }
RemoveDHCPStaticAddress() { RemoveDHCPStaticAddress() {
mac="${args[2]}" mac="${args[2]}"
sed -i "/dhcp-host=${mac}.*/d" "${dhcpstaticconfig}" sed -i "/dhcp-host=${mac}.*/d" "${dhcpstaticconfig}"
} }
SetHostRecord() { SetHostRecord() {
if [[ "${1}" == "-h" ]] || [[ "${1}" == "--help" ]]; then if [[ "${1}" == "-h" ]] || [[ "${1}" == "--help" ]]; then
echo "Usage: pihole -a hostrecord <domain> [IPv4-address],[IPv6-address] echo "Usage: pihole -a hostrecord <domain> [IPv4-address],[IPv6-address]
Example: 'pihole -a hostrecord home.domain.com 192.168.1.1,2001:db8:a0b:12f0::1' Example: 'pihole -a hostrecord home.domain.com 192.168.1.1,2001:db8:a0b:12f0::1'
Add a name to the DNS associated to an IPv4/IPv6 address Add a name to the DNS associated to an IPv4/IPv6 address
Options: Options:
\"\" Empty: Remove host record \"\" Empty: Remove host record
-h, --help Show this help dialog" -h, --help Show this help dialog"
exit 0 exit 0
fi fi
if [[ -n "${args[3]}" ]]; then if [[ -n "${args[3]}" ]]; then
change_setting "HOSTRECORD" "${args[2]},${args[3]}" change_setting "HOSTRECORD" "${args[2]},${args[3]}"
echo -e " ${TICK} Setting host record for ${args[2]} to ${args[3]}" echo -e " ${TICK} Setting host record for ${args[2]} to ${args[3]}"
else else
change_setting "HOSTRECORD" "" change_setting "HOSTRECORD" ""
echo -e " ${TICK} Removing host record" echo -e " ${TICK} Removing host record"
fi fi
ProcessDNSSettings ProcessDNSSettings
# Restart dnsmasq to load new configuration # Restart dnsmasq to load new configuration
RestartDNS RestartDNS
} }
SetAdminEmail() { SetAdminEmail() {
if [[ "${1}" == "-h" ]] || [[ "${1}" == "--help" ]]; then if [[ "${1}" == "-h" ]] || [[ "${1}" == "--help" ]]; then
echo "Usage: pihole -a email <address> echo "Usage: pihole -a email <address>
Example: 'pihole -a email admin@address.com' Example: 'pihole -a email admin@address.com'
Set an administrative contact address for the Block Page Set an administrative contact address for the Block Page
Options: Options:
\"\" Empty: Remove admin contact \"\" Empty: Remove admin contact
-h, --help Show this help dialog" -h, --help Show this help dialog"
exit 0 exit 0
fi fi
if [[ -n "${args[2]}" ]]; then if [[ -n "${args[2]}" ]]; then
change_setting "ADMIN_EMAIL" "${args[2]}" change_setting "ADMIN_EMAIL" "${args[2]}"
echo -e " ${TICK} Setting admin contact to ${args[2]}" echo -e " ${TICK} Setting admin contact to ${args[2]}"
else else
change_setting "ADMIN_EMAIL" "" change_setting "ADMIN_EMAIL" ""
echo -e " ${TICK} Removing admin contact" echo -e " ${TICK} Removing admin contact"
fi fi
} }
SetListeningMode() { SetListeningMode() {
source "${setupVars}" source "${setupVars}"
if [[ "$3" == "-h" ]] || [[ "$3" == "--help" ]]; then if [[ "$3" == "-h" ]] || [[ "$3" == "--help" ]]; then
echo "Usage: pihole -a -i [interface] echo "Usage: pihole -a -i [interface]
Example: 'pihole -a -i local' Example: 'pihole -a -i local'
Specify dnsmasq's network interface listening behavior Specify dnsmasq's network interface listening behavior
@ -497,82 +497,82 @@ Interfaces:
devices that are at most one hop away (local devices) devices that are at most one hop away (local devices)
single Listen only on ${PIHOLE_INTERFACE} interface single Listen only on ${PIHOLE_INTERFACE} interface
all Listen on all interfaces, permit all origins" all Listen on all interfaces, permit all origins"
exit 0 exit 0
fi fi
if [[ "${args[2]}" == "all" ]]; then if [[ "${args[2]}" == "all" ]]; then
echo -e " ${INFO} Listening on all interfaces, permiting all origins. Please use a firewall!" echo -e " ${INFO} Listening on all interfaces, permiting all origins. Please use a firewall!"
change_setting "DNSMASQ_LISTENING" "all" change_setting "DNSMASQ_LISTENING" "all"
elif [[ "${args[2]}" == "local" ]]; then elif [[ "${args[2]}" == "local" ]]; then
echo -e " ${INFO} Listening on all interfaces, permiting origins from one hop away (LAN)" echo -e " ${INFO} Listening on all interfaces, permiting origins from one hop away (LAN)"
change_setting "DNSMASQ_LISTENING" "local" change_setting "DNSMASQ_LISTENING" "local"
else else
echo -e " ${INFO} Listening only on interface ${PIHOLE_INTERFACE}" echo -e " ${INFO} Listening only on interface ${PIHOLE_INTERFACE}"
change_setting "DNSMASQ_LISTENING" "single" change_setting "DNSMASQ_LISTENING" "single"
fi fi
# Don't restart DNS server yet because other settings # Don't restart DNS server yet because other settings
# will be applied afterwards if "-web" is set # will be applied afterwards if "-web" is set
if [[ "${args[3]}" != "-web" ]]; then if [[ "${args[3]}" != "-web" ]]; then
ProcessDNSSettings ProcessDNSSettings
# Restart dnsmasq to load new configuration # Restart dnsmasq to load new configuration
RestartDNS RestartDNS
fi fi
} }
Teleporter() { Teleporter() {
local datetimestamp=$(date "+%Y-%m-%d_%H-%M-%S") local datetimestamp=$(date "+%Y-%m-%d_%H-%M-%S")
php /var/www/html/admin/scripts/pi-hole/php/teleporter.php > "pi-hole-teleporter_${datetimestamp}.zip" php /var/www/html/admin/scripts/pi-hole/php/teleporter.php > "pi-hole-teleporter_${datetimestamp}.zip"
} }
audit() audit()
{ {
echo "${args[2]}" >> /etc/pihole/auditlog.list echo "${args[2]}" >> /etc/pihole/auditlog.list
} }
SetPrivacyLevel() { SetPrivacyLevel() {
# Set privacy level. Minimum is 0, maximum is 3 # Set privacy level. Minimum is 0, maximum is 3
if [ "${args[2]}" -ge 0 ] && [ "${args[2]}" -le 3 ]; then if [ "${args[2]}" -ge 0 ] && [ "${args[2]}" -le 3 ]; then
changeFTLsetting "PRIVACYLEVEL" "${args[2]}" changeFTLsetting "PRIVACYLEVEL" "${args[2]}"
fi fi
} }
main() { main() {
args=("$@") args=("$@")
case "${args[1]}" in case "${args[1]}" in
"-p" | "password" ) SetWebPassword;; "-p" | "password" ) SetWebPassword;;
"-c" | "celsius" ) unit="C"; SetTemperatureUnit;; "-c" | "celsius" ) unit="C"; SetTemperatureUnit;;
"-f" | "fahrenheit" ) unit="F"; SetTemperatureUnit;; "-f" | "fahrenheit" ) unit="F"; SetTemperatureUnit;;
"-k" | "kelvin" ) unit="K"; SetTemperatureUnit;; "-k" | "kelvin" ) unit="K"; SetTemperatureUnit;;
"setdns" ) SetDNSServers;; "setdns" ) SetDNSServers;;
"setexcludedomains" ) SetExcludeDomains;; "setexcludedomains" ) SetExcludeDomains;;
"setexcludeclients" ) SetExcludeClients;; "setexcludeclients" ) SetExcludeClients;;
"poweroff" ) Poweroff;; "poweroff" ) Poweroff;;
"reboot" ) Reboot;; "reboot" ) Reboot;;
"restartdns" ) RestartDNS;; "restartdns" ) RestartDNS;;
"setquerylog" ) SetQueryLogOptions;; "setquerylog" ) SetQueryLogOptions;;
"enabledhcp" ) EnableDHCP;; "enabledhcp" ) EnableDHCP;;
"disabledhcp" ) DisableDHCP;; "disabledhcp" ) DisableDHCP;;
"layout" ) SetWebUILayout;; "layout" ) SetWebUILayout;;
"-h" | "--help" ) helpFunc;; "-h" | "--help" ) helpFunc;;
"privacymode" ) SetPrivacyMode;; "privacymode" ) SetPrivacyMode;;
"resolve" ) ResolutionSettings;; "resolve" ) ResolutionSettings;;
"addstaticdhcp" ) AddDHCPStaticAddress;; "addstaticdhcp" ) AddDHCPStaticAddress;;
"removestaticdhcp" ) RemoveDHCPStaticAddress;; "removestaticdhcp" ) RemoveDHCPStaticAddress;;
"-r" | "hostrecord" ) SetHostRecord "$3";; "-r" | "hostrecord" ) SetHostRecord "$3";;
"-e" | "email" ) SetAdminEmail "$3";; "-e" | "email" ) SetAdminEmail "$3";;
"-i" | "interface" ) SetListeningMode "$@";; "-i" | "interface" ) SetListeningMode "$@";;
"-t" | "teleporter" ) Teleporter;; "-t" | "teleporter" ) Teleporter;;
"adlist" ) CustomizeAdLists;; "adlist" ) CustomizeAdLists;;
"audit" ) audit;; "audit" ) audit;;
"-l" | "privacylevel" ) SetPrivacyLevel;; "-l" | "privacylevel" ) SetPrivacyLevel;;
* ) helpFunc;; * ) helpFunc;;
esac esac
shift shift
if [[ $# = 0 ]]; then if [[ $# = 0 ]]; then
helpFunc helpFunc
fi fi
} }

View File

@ -13,16 +13,16 @@
wildcardFile="/etc/dnsmasq.d/03-pihole-wildcard.conf" wildcardFile="/etc/dnsmasq.d/03-pihole-wildcard.conf"
convert_wildcard_to_regex() { convert_wildcard_to_regex() {
if [ ! -f "${wildcardFile}" ]; then if [ ! -f "${wildcardFile}" ]; then
return return
fi fi
local addrlines domains uniquedomains local addrlines domains uniquedomains
# Obtain wildcard domains from old file # Obtain wildcard domains from old file
addrlines="$(grep -oE "/.*/" ${wildcardFile})" addrlines="$(grep -oE "/.*/" ${wildcardFile})"
# Strip "/" from domain names and convert "." to regex-compatible "\." # Strip "/" from domain names and convert "." to regex-compatible "\."
domains="$(sed 's/\///g;s/\./\\./g' <<< "${addrlines}")" domains="$(sed 's/\///g;s/\./\\./g' <<< "${addrlines}")"
# Remove repeated domains (may have been inserted two times due to A and AAAA blocking) # Remove repeated domains (may have been inserted two times due to A and AAAA blocking)
uniquedomains="$(uniq <<< "${domains}")" uniquedomains="$(uniq <<< "${domains}")"
# Automatically generate regex filters and remove old wildcards file # Automatically generate regex filters and remove old wildcards file
awk '{print "((^)|(\\.))"$0"$"}' <<< "${uniquedomains}" >> "${regexFile:?}" && rm "${wildcardFile}" awk '{print "((^)|(\\.))"$0"$"}' <<< "${uniquedomains}" >> "${regexFile:?}" && rm "${wildcardFile}"
} }