Compare commits
126 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bea63f9d2d | ||
|
|
de5e6e4163 | ||
|
|
350c9e02ea | ||
|
|
f59610081e | ||
|
|
50d67dce73 | ||
|
|
43ba31f402 | ||
|
|
3ae72114c7 | ||
|
|
783f9e5569 | ||
|
|
23f2db01bb | ||
|
|
82b60b09d4 | ||
|
|
5bdb089b7f | ||
|
|
c92826c152 | ||
|
|
85e7fc5a0e | ||
|
|
10fe85933b | ||
|
|
412079a798 | ||
|
|
f9b29cfb62 | ||
|
|
73733308ba | ||
|
|
614554f26f | ||
|
|
8d91ca874b | ||
|
|
b075e25ab9 | ||
|
|
eaded9fdb1 | ||
|
|
19d50b9669 | ||
|
|
8e5467de70 | ||
|
|
fe1618d697 | ||
|
|
a3e610dbf2 | ||
|
|
b8c3f6d999 | ||
|
|
e6ae2e98cc | ||
|
|
654e111038 | ||
|
|
cd638b102f | ||
|
|
b74c6d5120 | ||
|
|
fd4e8766e4 | ||
|
|
c95d34389b | ||
|
|
83afff953f | ||
|
|
b8ffd2700c | ||
|
|
9bcb323568 | ||
|
|
e9e0aa37f4 | ||
|
|
0df06dc2fb | ||
|
|
53d09417dd | ||
|
|
eed4b70512 | ||
|
|
8fbad01d45 | ||
|
|
1a9dbec83c | ||
|
|
5985d506f1 | ||
|
|
fc706b6cbb | ||
|
|
7eeedf1b5f | ||
|
|
364fd38996 | ||
|
|
b412e88b02 | ||
|
|
11725a0999 | ||
|
|
d065afdbb1 | ||
|
|
c36d0257ec | ||
|
|
87a612f884 | ||
|
|
dd3a7a4edb | ||
|
|
d10d59303e | ||
|
|
b9cf2d9959 | ||
|
|
aaf828117d | ||
|
|
9c4e74ffa7 | ||
|
|
2a0f720153 | ||
|
|
cc17fe18a9 | ||
|
|
61ff5b2c76 | ||
|
|
56eae4afbe | ||
|
|
66bfa606a7 | ||
|
|
32fb2e69ff | ||
|
|
c71460e4b6 | ||
|
|
d885e92674 | ||
|
|
9d4a69c1d0 | ||
|
|
0656ceb149 | ||
|
|
95b12bad34 | ||
|
|
fa116389c2 | ||
|
|
8ca5788561 | ||
|
|
1dc33129e5 | ||
|
|
c96463bda2 | ||
|
|
edbaf6d697 | ||
|
|
58275ecd13 | ||
|
|
c6d1137eb0 | ||
|
|
fb032ea6e7 | ||
|
|
536b3497c9 | ||
|
|
8f09a1d837 | ||
|
|
c255082ef5 | ||
|
|
76b7453f90 | ||
|
|
66ed7c9ea3 | ||
|
|
ac2f13adef | ||
|
|
6b919f3a2e | ||
|
|
4d21bae669 | ||
|
|
7ea0bbb85c | ||
|
|
3ddec99f4a | ||
|
|
e1f12668fa | ||
|
|
686da5a948 | ||
|
|
8a2829de87 | ||
|
|
3a592e56ba | ||
|
|
3c91b6558d | ||
|
|
b9a6970bfd | ||
|
|
20f8c6af3c | ||
|
|
c35ed68051 | ||
|
|
75a32d22a3 | ||
|
|
71e262c37f | ||
|
|
04b909c837 | ||
|
|
309ee78903 | ||
|
|
d6f5552ccf | ||
|
|
67a973a17d | ||
|
|
0b60601f86 | ||
|
|
0b5da9f0da | ||
|
|
0589641bf0 | ||
|
|
ddf972cede | ||
|
|
73de49323c | ||
|
|
16385af3ef | ||
|
|
6cb0be82ca | ||
|
|
2dd31ce6ee | ||
|
|
31a9e18997 | ||
|
|
821c7dc190 | ||
|
|
eedd93d782 | ||
|
|
c5faf3d174 | ||
|
|
1f3f849106 | ||
|
|
ca74152d1d | ||
|
|
4fd0f15d90 | ||
|
|
b9f19fc357 | ||
|
|
2380359270 | ||
|
|
d75adb49f4 | ||
|
|
90da155053 | ||
|
|
2a61a03bdf | ||
|
|
a4bdf2454b | ||
|
|
4b503a080b | ||
|
|
46fe37b4da | ||
|
|
d6275cdd7c | ||
|
|
45cab12392 | ||
|
|
5ecdfb53c2 | ||
|
|
d86b325dfe | ||
|
|
c65ea9c47c |
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout repository
|
name: Checkout repository
|
||||||
uses: actions/checkout@v3.3.0
|
uses: actions/checkout@v3.5.2
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
-
|
-
|
||||||
name: Initialize CodeQL
|
name: Initialize CodeQL
|
||||||
|
|||||||
27
.github/workflows/stale.yml
vendored
27
.github/workflows/stale.yml
vendored
@@ -4,23 +4,42 @@ on:
|
|||||||
schedule:
|
schedule:
|
||||||
- cron: '0 8 * * *'
|
- cron: '0 8 * * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
issue_comment:
|
||||||
|
|
||||||
|
env:
|
||||||
|
stale_label: stale
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
stale:
|
stale_action:
|
||||||
|
if: github.event_name != 'issue_comment'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
issues: write
|
issues: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v7.0.0
|
- uses: actions/stale@v8.0.0
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
days-before-stale: 30
|
days-before-stale: 30
|
||||||
days-before-close: 5
|
days-before-close: 5
|
||||||
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Please comment or update this issue or it will be closed in 5 days.'
|
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Please comment or update this issue or it will be closed in 5 days.'
|
||||||
stale-issue-label: 'stale'
|
stale-issue-label: $stale_label
|
||||||
exempt-issue-labels: 'Internal, Fixed in next release, Bug: Confirmed, Documentation Needed'
|
exempt-issue-labels: 'Internal, Fixed in next release, Bug: Confirmed, Documentation Needed'
|
||||||
exempt-all-issue-assignees: true
|
exempt-all-issue-assignees: true
|
||||||
operations-per-run: 300
|
operations-per-run: 300
|
||||||
close-issue-reason: 'not_planned'
|
close-issue-reason: 'not_planned'
|
||||||
|
|
||||||
|
remove_stale: # trigger "stale" removal immediately when stale issues are commented on
|
||||||
|
if: github.event_name == 'issue_comment'
|
||||||
|
permissions:
|
||||||
|
contents: read # for actions/checkout
|
||||||
|
issues: write # to edit issues label
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3.5.2
|
||||||
|
- name: Remove 'stale' label
|
||||||
|
run: gh issue edit ${{ github.event.issue.number }} --remove-label $stale_label
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/stale_pr.yml
vendored
2
.github/workflows/stale_pr.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v7.0.0
|
- uses: actions/stale@v8.0.0
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
# Do not automatically mark PR/issue as stale
|
# Do not automatically mark PR/issue as stale
|
||||||
|
|||||||
24
.github/workflows/sync-back-to-dev.yml
vendored
24
.github/workflows/sync-back-to-dev.yml
vendored
@@ -5,13 +5,35 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
|
# The section is needed to drop the default write-all permissions for all jobs
|
||||||
|
# that are granted on `push` event. By specifying any permission explicitly
|
||||||
|
# all others are set to none. By using the principle of least privilege the damage a compromised
|
||||||
|
# workflow can do (because of an injection or compromised third party tool or
|
||||||
|
# action) is restricted. Adding labels to issues, commenting
|
||||||
|
# on pull-requests, etc. may need additional permissions:
|
||||||
|
#
|
||||||
|
# Syntax for this section:
|
||||||
|
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
|
||||||
|
#
|
||||||
|
# Reference for how to assign permissions on a job-by-job basis:
|
||||||
|
# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs
|
||||||
|
#
|
||||||
|
# Reference for available permissions that we can enable if needed:
|
||||||
|
# https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
sync-branches:
|
sync-branches:
|
||||||
|
# The job needs to be able to pull the code and create a pull request.
|
||||||
|
permissions:
|
||||||
|
contents: read # for actions/checkout
|
||||||
|
pull-requests: write # to create pull request
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
name: Syncing branches
|
name: Syncing branches
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3.3.0
|
uses: actions/checkout@v3.5.2
|
||||||
- name: Opening pull request
|
- 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'
|
run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'internal'
|
||||||
env:
|
env:
|
||||||
|
|||||||
8
.github/workflows/test.yml
vendored
8
.github/workflows/test.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3.3.0
|
uses: actions/checkout@v3.5.2
|
||||||
|
|
||||||
- name: Check scripts in repository are executable
|
- name: Check scripts in repository are executable
|
||||||
run: |
|
run: |
|
||||||
@@ -53,19 +53,21 @@ jobs:
|
|||||||
debian_11,
|
debian_11,
|
||||||
ubuntu_20,
|
ubuntu_20,
|
||||||
ubuntu_22,
|
ubuntu_22,
|
||||||
|
ubuntu_23,
|
||||||
centos_8,
|
centos_8,
|
||||||
centos_9,
|
centos_9,
|
||||||
fedora_36,
|
fedora_36,
|
||||||
fedora_37,
|
fedora_37,
|
||||||
|
fedora_38,
|
||||||
]
|
]
|
||||||
env:
|
env:
|
||||||
DISTRO: ${{matrix.distro}}
|
DISTRO: ${{matrix.distro}}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3.3.0
|
uses: actions/checkout@v3.5.2
|
||||||
|
|
||||||
- name: Set up Python 3.10
|
- name: Set up Python 3.10
|
||||||
uses: actions/setup-python@v4.5.0
|
uses: actions/setup-python@v4.6.1
|
||||||
with:
|
with:
|
||||||
python-version: "3.10"
|
python-version: "3.10"
|
||||||
|
|
||||||
|
|||||||
@@ -230,10 +230,8 @@ initialize_debug() {
|
|||||||
|
|
||||||
# This is a function for visually displaying the current test that is being run.
|
# This is a function for visually displaying the current test that is being run.
|
||||||
# Accepts one variable: the name of what is being diagnosed
|
# Accepts one variable: the name of what is being diagnosed
|
||||||
# Colors do not show in the dasboard, but the icons do: [i], [✓], and [✗]
|
|
||||||
echo_current_diagnostic() {
|
echo_current_diagnostic() {
|
||||||
# Colors are used for visually distinguishing each test in the output
|
# Colors are used for visually distinguishing each test in the output
|
||||||
# These colors do not show in the GUI, but the formatting will
|
|
||||||
log_write "\\n${COL_PURPLE}*** [ DIAGNOSING ]:${COL_NC} ${1}"
|
log_write "\\n${COL_PURPLE}*** [ DIAGNOSING ]:${COL_NC} ${1}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,33 +30,6 @@ gravityDBfile="${GRAVITYDB}"
|
|||||||
colfile="/opt/pihole/COL_TABLE"
|
colfile="/opt/pihole/COL_TABLE"
|
||||||
source "${colfile}"
|
source "${colfile}"
|
||||||
|
|
||||||
# Scan an array of files for matching strings
|
|
||||||
scanList(){
|
|
||||||
# Escape full stops
|
|
||||||
local domain="${1}" esc_domain="${1//./\\.}" lists="${2}" list_type="${3:-}"
|
|
||||||
|
|
||||||
# Prevent grep from printing file path
|
|
||||||
cd "$piholeDir" || exit 1
|
|
||||||
|
|
||||||
# Prevent grep -i matching slowly: https://bit.ly/2xFXtUX
|
|
||||||
export LC_CTYPE=C
|
|
||||||
|
|
||||||
# /dev/null forces filename to be printed when only one list has been generated
|
|
||||||
case "${list_type}" in
|
|
||||||
"exact" ) grep -i -E -l "(^|(?<!#)\\s)${esc_domain}($|\\s|#)" ${lists} /dev/null 2>/dev/null;;
|
|
||||||
# Iterate through each regexp and check whether it matches the domainQuery
|
|
||||||
# If it does, print the matching regexp and continue looping
|
|
||||||
# Input 1 - regexps | Input 2 - domainQuery
|
|
||||||
"regex" )
|
|
||||||
for list in ${lists}; do
|
|
||||||
if [[ "${domain}" =~ ${list} ]]; then
|
|
||||||
printf "%b\n" "${list}";
|
|
||||||
fi
|
|
||||||
done;;
|
|
||||||
* ) grep -i "${esc_domain}" ${lists} /dev/null 2>/dev/null;;
|
|
||||||
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'
|
||||||
@@ -84,17 +57,32 @@ options=$(sed -E 's/ ?-(all|exact) ?//g' <<< "${options}")
|
|||||||
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:]]* ) rawDomainQuery=$(idn2 "${options}");;
|
||||||
* ) domainQuery="${options}";;
|
* ) rawDomainQuery="${options}";;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
# convert the domain to lowercase
|
||||||
|
domainQuery=$(echo "${rawDomainQuery}" | tr '[:upper:]' '[:lower:]')
|
||||||
|
|
||||||
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 a domain again a list of RegEX
|
||||||
|
scanRegExList(){
|
||||||
|
local domain="${1}" list="${2}"
|
||||||
|
|
||||||
|
for entry in ${list}; do
|
||||||
|
if [[ "${domain}" =~ ${entry} ]]; then
|
||||||
|
printf "%b\n" "${entry}";
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
scanDatabaseTable() {
|
scanDatabaseTable() {
|
||||||
local domain table list_type querystr result extra
|
local domain table list_type querystr result extra abpquerystr abpfound abpentry searchstr
|
||||||
domain="$(printf "%q" "${1}")"
|
domain="$(printf "%q" "${1}")"
|
||||||
table="${2}"
|
table="${2}"
|
||||||
list_type="${3:-}"
|
list_type="${3:-}"
|
||||||
@@ -104,9 +92,34 @@ scanDatabaseTable() {
|
|||||||
# behavior. The "ESCAPE '\'" clause specifies that an underscore preceded by an '\' should be matched
|
# behavior. The "ESCAPE '\'" clause specifies that an underscore preceded by an '\' should be matched
|
||||||
# as a literal underscore character. We pretreat the $domain variable accordingly to escape underscores.
|
# as a literal underscore character. We pretreat the $domain variable accordingly to escape underscores.
|
||||||
if [[ "${table}" == "gravity" ]]; then
|
if [[ "${table}" == "gravity" ]]; then
|
||||||
|
|
||||||
|
# Are there ABP entries on gravity?
|
||||||
|
# Return 1 if abp_domain=1 or Zero if abp_domain=0 or not set
|
||||||
|
abpquerystr="SELECT EXISTS (SELECT 1 FROM info WHERE property='abp_domains' and value='1')"
|
||||||
|
abpfound="$(pihole-FTL sqlite3 "${gravityDBfile}" "${abpquerystr}")" 2> /dev/null
|
||||||
|
|
||||||
|
# Create search string for ABP entries only if needed
|
||||||
|
if [ "${abpfound}" -eq 1 ]; then
|
||||||
|
abpentry="${domain}"
|
||||||
|
|
||||||
|
searchstr="'||${abpentry}^'"
|
||||||
|
|
||||||
|
# While a dot is found ...
|
||||||
|
while [ "${abpentry}" != "${abpentry/./}" ]
|
||||||
|
do
|
||||||
|
# ... remove text before the dot (including the dot) and append the result to $searchstr
|
||||||
|
abpentry=$(echo "${abpentry}" | cut -f 2- -d '.')
|
||||||
|
searchstr="$searchstr, '||${abpentry}^'"
|
||||||
|
done
|
||||||
|
|
||||||
|
# The final search string will look like:
|
||||||
|
# "domain IN ('||sub2.sub1.domain.com^', '||sub1.domain.com^', '||domain.com^', '||com^') OR"
|
||||||
|
searchstr="domain IN (${searchstr}) OR "
|
||||||
|
fi
|
||||||
|
|
||||||
case "${exact}" in
|
case "${exact}" in
|
||||||
"exact" ) querystr="SELECT gravity.domain,adlist.address,adlist.enabled FROM gravity LEFT JOIN adlist ON adlist.id = gravity.adlist_id WHERE domain = '${domain}'";;
|
"exact" ) querystr="SELECT gravity.domain,adlist.address,adlist.enabled FROM gravity LEFT JOIN adlist ON adlist.id = gravity.adlist_id WHERE domain = '${domain}'";;
|
||||||
* ) querystr="SELECT gravity.domain,adlist.address,adlist.enabled FROM gravity LEFT JOIN adlist ON adlist.id = gravity.adlist_id WHERE domain LIKE '%${domain//_/\\_}%' ESCAPE '\\'";;
|
* ) querystr="SELECT gravity.domain,adlist.address,adlist.enabled FROM gravity LEFT JOIN adlist ON adlist.id = gravity.adlist_id WHERE ${searchstr} domain LIKE '%${domain//_/\\_}%' ESCAPE '\\'";;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
case "${exact}" in
|
case "${exact}" in
|
||||||
@@ -116,7 +129,7 @@ scanDatabaseTable() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Send prepared query to gravity database
|
# Send prepared query to gravity database
|
||||||
result="$(pihole-FTL sqlite3 "${gravityDBfile}" "${querystr}")" 2> /dev/null
|
result="$(pihole-FTL sqlite3 -separator ',' "${gravityDBfile}" "${querystr}")" 2> /dev/null
|
||||||
if [[ -z "${result}" ]]; then
|
if [[ -z "${result}" ]]; then
|
||||||
# Return early when there are no matches in this table
|
# Return early when there are no matches in this table
|
||||||
return
|
return
|
||||||
@@ -136,8 +149,8 @@ scanDatabaseTable() {
|
|||||||
# Loop over results and print them
|
# Loop over results and print them
|
||||||
mapfile -t results <<< "${result}"
|
mapfile -t results <<< "${result}"
|
||||||
for result in "${results[@]}"; do
|
for result in "${results[@]}"; do
|
||||||
domain="${result/|*}"
|
domain="${result/,*}"
|
||||||
if [[ "${result#*|}" == "0" ]]; then
|
if [[ "${result#*,}" == "0" ]]; then
|
||||||
extra=" (disabled)"
|
extra=" (disabled)"
|
||||||
else
|
else
|
||||||
extra=""
|
extra=""
|
||||||
@@ -160,7 +173,7 @@ scanRegexDatabaseTable() {
|
|||||||
# Split regexps over a new line
|
# Split regexps over a new line
|
||||||
str_regexList=$(printf '%s\n' "${regexList[@]}")
|
str_regexList=$(printf '%s\n' "${regexList[@]}")
|
||||||
# Check domain against regexps
|
# Check domain against regexps
|
||||||
mapfile -t regexMatches < <(scanList "${domain}" "${str_regexList}" "regex")
|
mapfile -t regexMatches < <(scanRegExList "${domain}" "${str_regexList}")
|
||||||
# If there were regex matches
|
# If there were regex matches
|
||||||
if [[ "${#regexMatches[@]}" -ne 0 ]]; then
|
if [[ "${#regexMatches[@]}" -ne 0 ]]; then
|
||||||
# Split matching regexps over a new line
|
# Split matching regexps over a new line
|
||||||
@@ -212,10 +225,10 @@ if [[ -n "${exact}" ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
for result in "${results[@]}"; do
|
for result in "${results[@]}"; do
|
||||||
match="${result/|*/}"
|
match="${result/,*/}"
|
||||||
extra="${result#*|}"
|
extra="${result#*,}"
|
||||||
adlistAddress="${extra/|*/}"
|
adlistAddress="${extra/,*/}"
|
||||||
extra="${extra#*|}"
|
extra="${extra#*,}"
|
||||||
if [[ "${extra}" == "0" ]]; then
|
if [[ "${extra}" == "0" ]]; then
|
||||||
extra=" (disabled)"
|
extra=" (disabled)"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -57,7 +57,11 @@ addKey(){
|
|||||||
# touch file to prevent grep error if file does not exist yet
|
# touch file to prevent grep error if file does not exist yet
|
||||||
touch "${file}"
|
touch "${file}"
|
||||||
|
|
||||||
if ! grep -q "^${key}" "${file}"; then
|
# Match key against entire line, using both anchors. We assume
|
||||||
|
# that the file's keys never have bounding whitespace. Anchors
|
||||||
|
# are necessary to ensure the key is considered absent when it
|
||||||
|
# is a substring of another key present in the file.
|
||||||
|
if ! grep -q "^${key}$" "${file}"; then
|
||||||
# Key does not exist, add it.
|
# Key does not exist, add it.
|
||||||
echo "${key}" >> "${file}"
|
echo "${key}" >> "${file}"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -22,12 +22,14 @@ readonly dnscustomcnamefile="/etc/dnsmasq.d/05-pihole-custom-cname.conf"
|
|||||||
|
|
||||||
readonly gravityDBfile="/etc/pihole/gravity.db"
|
readonly gravityDBfile="/etc/pihole/gravity.db"
|
||||||
|
|
||||||
# Source install script for ${setupVars}, ${PI_HOLE_BIN_DIR} and valid_ip()
|
|
||||||
readonly PI_HOLE_FILES_DIR="/etc/.pihole"
|
|
||||||
# shellcheck disable=SC2034 # used in basic-install to source the script without running it
|
|
||||||
SKIP_INSTALL="true"
|
|
||||||
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
|
|
||||||
|
|
||||||
|
readonly setupVars="/etc/pihole/setupVars.conf"
|
||||||
|
readonly PI_HOLE_BIN_DIR="/usr/local/bin"
|
||||||
|
|
||||||
|
# Root of the web server
|
||||||
|
readonly webroot="/var/www/html"
|
||||||
|
|
||||||
|
# Source utils script
|
||||||
utilsfile="/opt/pihole/utils.sh"
|
utilsfile="/opt/pihole/utils.sh"
|
||||||
source "${utilsfile}"
|
source "${utilsfile}"
|
||||||
|
|
||||||
@@ -98,6 +100,47 @@ HashPassword() {
|
|||||||
echo "${return}"
|
echo "${return}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check an IP address to see if it is a valid one
|
||||||
|
valid_ip() {
|
||||||
|
# Local, named variables
|
||||||
|
local ip=${1}
|
||||||
|
local stat=1
|
||||||
|
|
||||||
|
# Regex matching one IPv4 component, i.e. an integer from 0 to 255.
|
||||||
|
# See https://tools.ietf.org/html/rfc1340
|
||||||
|
local ipv4elem="(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)";
|
||||||
|
# Regex matching an optional port (starting with '#') range of 1-65536
|
||||||
|
local portelem="(#(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))?";
|
||||||
|
# Build a full IPv4 regex from the above subexpressions
|
||||||
|
local regex="^${ipv4elem}\\.${ipv4elem}\\.${ipv4elem}\\.${ipv4elem}${portelem}$"
|
||||||
|
|
||||||
|
# Evaluate the regex, and return the result
|
||||||
|
[[ $ip =~ ${regex} ]]
|
||||||
|
|
||||||
|
stat=$?
|
||||||
|
return "${stat}"
|
||||||
|
}
|
||||||
|
|
||||||
|
valid_ip6() {
|
||||||
|
local ip=${1}
|
||||||
|
local stat=1
|
||||||
|
|
||||||
|
# Regex matching one IPv6 element, i.e. a hex value from 0000 to FFFF
|
||||||
|
local ipv6elem="[0-9a-fA-F]{1,4}"
|
||||||
|
# Regex matching an IPv6 CIDR, i.e. 1 to 128
|
||||||
|
local v6cidr="(\\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])){0,1}"
|
||||||
|
# Regex matching an optional port (starting with '#') range of 1-65536
|
||||||
|
local portelem="(#(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))?";
|
||||||
|
# Build a full IPv6 regex from the above subexpressions
|
||||||
|
local regex="^(((${ipv6elem}))*((:${ipv6elem}))*::((${ipv6elem}))*((:${ipv6elem}))*|((${ipv6elem}))((:${ipv6elem})){7})${v6cidr}${portelem}$"
|
||||||
|
|
||||||
|
# Evaluate the regex, and return the result
|
||||||
|
[[ ${ip} =~ ${regex} ]]
|
||||||
|
|
||||||
|
stat=$?
|
||||||
|
return "${stat}"
|
||||||
|
}
|
||||||
|
|
||||||
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!"
|
||||||
@@ -613,7 +656,6 @@ Teleporter() {
|
|||||||
host="${host//./_}"
|
host="${host//./_}"
|
||||||
filename="pi-hole-${host:-noname}-teleporter_${datetimestamp}.tar.gz"
|
filename="pi-hole-${host:-noname}-teleporter_${datetimestamp}.tar.gz"
|
||||||
fi
|
fi
|
||||||
# webroot is sourced from basic-install above
|
|
||||||
php "${webroot}/admin/scripts/pi-hole/php/teleporter.php" > "${filename}"
|
php "${webroot}/admin/scripts/pi-hole/php/teleporter.php" > "${filename}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,7 +664,7 @@ checkDomain()
|
|||||||
local domain validDomain
|
local domain validDomain
|
||||||
# Convert to lowercase
|
# Convert to lowercase
|
||||||
domain="${1,,}"
|
domain="${1,,}"
|
||||||
validDomain=$(grep -P "^((-|_)*[a-z\\d]((-|_)*[a-z\\d])*(-|_)*)(\\.(-|_)*([a-z\\d]((-|_)*[a-z\\d])*))*$" <<< "${domain}") # Valid chars check
|
validDomain=$(grep -P "^((-|_)*[a-z0-9]((-|_)*[a-z0-9)*(-|_)*)(\\.(-|_)*([a-z0-9]((-|_)*[a-z0-9])*))*$" <<< "${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
|
||||||
echo "${validDomain}"
|
echo "${validDomain}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ INSERT OR REPLACE INTO adlist SELECT * FROM OLD.adlist;
|
|||||||
DELETE FROM OLD.adlist_by_group WHERE adlist_id NOT IN (SELECT id FROM OLD.adlist);
|
DELETE FROM OLD.adlist_by_group WHERE adlist_id NOT IN (SELECT id FROM OLD.adlist);
|
||||||
INSERT OR REPLACE INTO adlist_by_group SELECT * FROM OLD.adlist_by_group;
|
INSERT OR REPLACE INTO adlist_by_group SELECT * FROM OLD.adlist_by_group;
|
||||||
|
|
||||||
INSERT OR REPLACE INTO info SELECT * FROM OLD.info;
|
|
||||||
|
|
||||||
INSERT OR REPLACE INTO client SELECT * FROM OLD.client;
|
INSERT OR REPLACE INTO client SELECT * FROM OLD.client;
|
||||||
DELETE FROM OLD.client_by_group WHERE client_id NOT IN (SELECT id FROM OLD.client);
|
DELETE FROM OLD.client_by_group WHERE client_id NOT IN (SELECT id FROM OLD.client);
|
||||||
INSERT OR REPLACE INTO client_by_group SELECT * FROM OLD.client_by_group;
|
INSERT OR REPLACE INTO client_by_group SELECT * FROM OLD.client_by_group;
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ package_manager_detect() {
|
|||||||
# These variable names match the ones for apt-get. See above for an explanation of what they are for.
|
# These variable names match the ones for apt-get. See above for an explanation of what they are for.
|
||||||
PKG_INSTALL=("${PKG_MANAGER}" install -y)
|
PKG_INSTALL=("${PKG_MANAGER}" install -y)
|
||||||
# CentOS package manager returns 100 when there are packages to update so we need to || true to prevent the script from exiting.
|
# CentOS package manager returns 100 when there are packages to update so we need to || true to prevent the script from exiting.
|
||||||
PKG_COUNT="${PKG_MANAGER} check-update | grep -E '(.i686|.x86|.noarch|.arm|.src)' | wc -l || true"
|
PKG_COUNT="${PKG_MANAGER} check-update | grep -E '(.i686|.x86|.noarch|.arm|.src|.riscv64)' | wc -l || true"
|
||||||
OS_CHECK_DEPS=(grep bind-utils)
|
OS_CHECK_DEPS=(grep bind-utils)
|
||||||
INSTALLER_DEPS=(git dialog iproute newt procps-ng chkconfig ca-certificates)
|
INSTALLER_DEPS=(git dialog iproute newt procps-ng chkconfig ca-certificates)
|
||||||
PIHOLE_DEPS=(cronie curl findutils sudo unzip libidn2 psmisc libcap nmap-ncat jq)
|
PIHOLE_DEPS=(cronie curl findutils sudo unzip libidn2 psmisc libcap nmap-ncat jq)
|
||||||
@@ -1409,7 +1409,7 @@ installConfigs() {
|
|||||||
mkdir -p /run/lighttpd
|
mkdir -p /run/lighttpd
|
||||||
chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} /run/lighttpd
|
chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} /run/lighttpd
|
||||||
|
|
||||||
if grep -q -F "FILE WILL BE OVERWRITTEN BY PI-HOLE" "${lighttpdConfig}"; then
|
if grep -q -F "OVERWRITTEN BY PI-HOLE" "${lighttpdConfig}"; then
|
||||||
# Attempt to preserve backwards compatibility with older versions
|
# Attempt to preserve backwards compatibility with older versions
|
||||||
install -D -m 644 -T ${PI_HOLE_LOCAL_REPO}/advanced/${LIGHTTPD_CFG} "${lighttpdConfig}"
|
install -D -m 644 -T ${PI_HOLE_LOCAL_REPO}/advanced/${LIGHTTPD_CFG} "${lighttpdConfig}"
|
||||||
# Make the directories if they do not exist and set the owners
|
# Make the directories if they do not exist and set the owners
|
||||||
@@ -2366,6 +2366,9 @@ get_binary_name() {
|
|||||||
# set the binary to be used
|
# set the binary to be used
|
||||||
l_binary="pihole-FTL-linux-x86_64"
|
l_binary="pihole-FTL-linux-x86_64"
|
||||||
fi
|
fi
|
||||||
|
elif [[ "${machine}" == "riscv64" ]]; then
|
||||||
|
printf "%b %b Detected riscv64 processor\\n" "${OVER}" "${TICK}"
|
||||||
|
l_binary="pihole-FTL-riscv64-linux-gnu"
|
||||||
else
|
else
|
||||||
# Something else - we try to use 32bit executable and warn the user
|
# Something else - we try to use 32bit executable and warn the user
|
||||||
if [[ ! "${machine}" == "i686" ]]; then
|
if [[ ! "${machine}" == "i686" ]]; then
|
||||||
@@ -2612,7 +2615,8 @@ main() {
|
|||||||
|
|
||||||
# Get the privacy level if it exists (default is 0)
|
# Get the privacy level if it exists (default is 0)
|
||||||
if [[ -f "${FTL_CONFIG_FILE}" ]]; then
|
if [[ -f "${FTL_CONFIG_FILE}" ]]; then
|
||||||
PRIVACY_LEVEL=$(sed -ne 's/PRIVACYLEVEL=\(.*\)/\1/p' "${FTL_CONFIG_FILE}")
|
# get the value from $FTL_CONFIG_FILE (and ignoring all commented lines)
|
||||||
|
PRIVACY_LEVEL=$(sed -e '/^[[:blank:]]*#/d' "${FTL_CONFIG_FILE}" | grep "PRIVACYLEVEL" | awk -F "=" 'NR==1{printf$2}')
|
||||||
|
|
||||||
# If no setting was found, default to 0
|
# If no setting was found, default to 0
|
||||||
PRIVACY_LEVEL="${PRIVACY_LEVEL:-0}"
|
PRIVACY_LEVEL="${PRIVACY_LEVEL:-0}"
|
||||||
|
|||||||
@@ -193,6 +193,18 @@ removeNoPurge() {
|
|||||||
else
|
else
|
||||||
service pihole-FTL stop
|
service pihole-FTL stop
|
||||||
fi
|
fi
|
||||||
|
${SUDO} rm -f /etc/systemd/system/pihole-FTL.service
|
||||||
|
if [[ -d '/etc/systemd/system/pihole-FTL.service.d' ]]; then
|
||||||
|
read -rp " ${QST} FTL service override directory /etc/systemd/system/pihole-FTL.service.d detected. Do you wish to remove this from your system? [y/N] " answer
|
||||||
|
case $answer in
|
||||||
|
[yY]*)
|
||||||
|
echo -ne " ${INFO} Removing /etc/systemd/system/pihole-FTL.service.d..."
|
||||||
|
${SUDO} rm -R /etc/systemd/system/pihole-FTL.service.d
|
||||||
|
echo -e "${OVER} ${INFO} Removed /etc/systemd/system/pihole-FTL.service.d"
|
||||||
|
;;
|
||||||
|
*) echo -e " ${INFO} Leaving /etc/systemd/system/pihole-FTL.service.d in place.";;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
${SUDO} rm -f /etc/init.d/pihole-FTL
|
${SUDO} rm -f /etc/init.d/pihole-FTL
|
||||||
${SUDO} rm -f /usr/bin/pihole-FTL
|
${SUDO} rm -f /usr/bin/pihole-FTL
|
||||||
echo -e "${OVER} ${TICK} Removed pihole-FTL"
|
echo -e "${OVER} ${TICK} Removed pihole-FTL"
|
||||||
|
|||||||
272
gravity.sh
272
gravity.sh
@@ -52,6 +52,14 @@ else
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Set up tmp dir variable in case it's not configured
|
||||||
|
: "${GRAVITY_TMPDIR:=/tmp}"
|
||||||
|
|
||||||
|
if [ ! -d "${GRAVITY_TMPDIR}" ] || [ ! -w "${GRAVITY_TMPDIR}" ]; then
|
||||||
|
echo -e " ${COL_LIGHT_RED}Gravity temporary directory does not exist or is not a writeable directory, falling back to /tmp. ${COL_NC}"
|
||||||
|
GRAVITY_TMPDIR="/tmp"
|
||||||
|
fi
|
||||||
|
|
||||||
# Source pihole-FTL from install script
|
# Source pihole-FTL from install script
|
||||||
pihole_FTL="${piholeDir}/pihole-FTL.conf"
|
pihole_FTL="${piholeDir}/pihole-FTL.conf"
|
||||||
if [[ -f "${pihole_FTL}" ]]; then
|
if [[ -f "${pihole_FTL}" ]]; then
|
||||||
@@ -121,7 +129,7 @@ gravity_swap_databases() {
|
|||||||
echo -e "${OVER} ${TICK} ${str}"
|
echo -e "${OVER} ${TICK} ${str}"
|
||||||
|
|
||||||
if $oldAvail; then
|
if $oldAvail; then
|
||||||
echo -e " ${TICK} The old database remains available."
|
echo -e " ${TICK} The old database remains available"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +153,10 @@ database_table_from_file() {
|
|||||||
src="${2}"
|
src="${2}"
|
||||||
backup_path="${piholeDir}/migration_backup"
|
backup_path="${piholeDir}/migration_backup"
|
||||||
backup_file="${backup_path}/$(basename "${2}")"
|
backup_file="${backup_path}/$(basename "${2}")"
|
||||||
tmpFile="$(mktemp -p "/tmp" --suffix=".gravity")"
|
# Create a temporary file. We don't use '--suffix' here because not all
|
||||||
|
# implementations of mktemp support it, e.g. on Alpine
|
||||||
|
tmpFile="$(mktemp -p "${GRAVITY_TMPDIR}")"
|
||||||
|
mv "${tmpFile}" "${tmpFile%.*}.gravity"
|
||||||
|
|
||||||
local timestamp
|
local timestamp
|
||||||
timestamp="$(date --utc +'%s')"
|
timestamp="$(date --utc +'%s')"
|
||||||
@@ -216,17 +227,6 @@ database_table_from_file() {
|
|||||||
echo -e " ${CROSS} Unable to remove ${tmpFile}"
|
echo -e " ${CROSS} Unable to remove ${tmpFile}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Update timestamp of last update of this list. We store this in the "old" database as all values in the new database will later be overwritten
|
|
||||||
database_adlist_updated() {
|
|
||||||
output=$( { printf ".timeout 30000\\nUPDATE adlist SET date_updated = (cast(strftime('%%s', 'now') as int)) WHERE id = %i;\\n" "${1}" | pihole-FTL sqlite3 "${gravityDBfile}"; } 2>&1 )
|
|
||||||
status="$?"
|
|
||||||
|
|
||||||
if [[ "${status}" -ne 0 ]]; then
|
|
||||||
echo -e "\\n ${CROSS} Unable to update timestamp of adlist with ID ${1} in database ${gravityDBfile}\\n ${output}"
|
|
||||||
gravity_Cleanup "error"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check if a column with name ${2} exists in gravity table with name ${1}
|
# Check if a column with name ${2} exists in gravity table with name ${1}
|
||||||
gravity_column_exists() {
|
gravity_column_exists() {
|
||||||
output=$( { printf ".timeout 30000\\nSELECT EXISTS(SELECT * FROM pragma_table_info('%s') WHERE name='%s');\\n" "${1}" "${2}" | pihole-FTL sqlite3 "${gravityDBfile}"; } 2>&1 )
|
output=$( { printf ".timeout 30000\\nSELECT EXISTS(SELECT * FROM pragma_table_info('%s') WHERE name='%s');\\n" "${1}" "${2}" | pihole-FTL sqlite3 "${gravityDBfile}"; } 2>&1 )
|
||||||
@@ -244,7 +244,7 @@ database_adlist_number() {
|
|||||||
return;
|
return;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
output=$( { printf ".timeout 30000\\nUPDATE adlist SET number = %i, invalid_domains = %i WHERE id = %i;\\n" "${num_domains}" "${num_non_domains}" "${1}" | pihole-FTL sqlite3 "${gravityDBfile}"; } 2>&1 )
|
output=$( { printf ".timeout 30000\\nUPDATE adlist SET number = %i, invalid_domains = %i WHERE id = %i;\\n" "${2}" "${3}" "${1}" | pihole-FTL sqlite3 "${gravityDBfile}"; } 2>&1 )
|
||||||
status="$?"
|
status="$?"
|
||||||
|
|
||||||
if [[ "${status}" -ne 0 ]]; then
|
if [[ "${status}" -ne 0 ]]; then
|
||||||
@@ -401,7 +401,7 @@ gravity_DownloadBlocklists() {
|
|||||||
unset sources
|
unset sources
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local url domain agent cmd_ext str target compression
|
local url domain agent str target compression
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Prepare new gravity database
|
# Prepare new gravity database
|
||||||
@@ -418,7 +418,24 @@ gravity_DownloadBlocklists() {
|
|||||||
echo -e "${OVER} ${TICK} ${str}"
|
echo -e "${OVER} ${TICK} ${str}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
target="$(mktemp -p "/tmp" --suffix=".gravity")"
|
str="Creating new gravity databases"
|
||||||
|
echo -ne " ${INFO} ${str}..."
|
||||||
|
|
||||||
|
# Gravity copying SQL script
|
||||||
|
copyGravity="$(cat "${gravityDBcopy}")"
|
||||||
|
if [[ "${gravityDBfile}" != "${gravityDBfile_default}" ]]; then
|
||||||
|
# Replace default gravity script location by custom location
|
||||||
|
copyGravity="${copyGravity//"${gravityDBfile_default}"/"${gravityDBfile}"}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
output=$( { pihole-FTL sqlite3 "${gravityTEMPfile}" <<< "${copyGravity}"; } 2>&1 )
|
||||||
|
status="$?"
|
||||||
|
|
||||||
|
if [[ "${status}" -ne 0 ]]; then
|
||||||
|
echo -e "\\n ${CROSS} Unable to copy data from ${gravityDBfile} to ${gravityTEMPfile}\\n ${output}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo -e "${OVER} ${TICK} ${str}"
|
||||||
|
|
||||||
# Use compression to reduce the amount of data that is transferred
|
# Use compression to reduce the amount of data that is transferred
|
||||||
# between the Pi-hole and the ad list provider. Use this feature
|
# between the Pi-hole and the ad list provider. Use this feature
|
||||||
@@ -443,12 +460,6 @@ gravity_DownloadBlocklists() {
|
|||||||
# Default user-agent (for Cloudflare's Browser Integrity Check: https://support.cloudflare.com/hc/en-us/articles/200170086-What-does-the-Browser-Integrity-Check-do-)
|
# Default user-agent (for Cloudflare's Browser Integrity Check: https://support.cloudflare.com/hc/en-us/articles/200170086-What-does-the-Browser-Integrity-Check-do-)
|
||||||
agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"
|
agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"
|
||||||
|
|
||||||
# Provide special commands for blocklists which may need them
|
|
||||||
case "${domain}" in
|
|
||||||
"pgl.yoyo.org") cmd_ext="-d mimetype=plaintext -d hostformat=hosts";;
|
|
||||||
*) cmd_ext="";;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo -e " ${INFO} Target: ${url}"
|
echo -e " ${INFO} Target: ${url}"
|
||||||
local regex check_url
|
local regex check_url
|
||||||
# Check for characters NOT allowed in URLs
|
# Check for characters NOT allowed in URLs
|
||||||
@@ -461,138 +472,14 @@ gravity_DownloadBlocklists() {
|
|||||||
if [[ "${check_url}" =~ ${regex} ]]; then
|
if [[ "${check_url}" =~ ${regex} ]]; then
|
||||||
echo -e " ${CROSS} Invalid Target"
|
echo -e " ${CROSS} Invalid Target"
|
||||||
else
|
else
|
||||||
gravity_DownloadBlocklistFromUrl "${url}" "${cmd_ext}" "${agent}" "${sourceIDs[$i]}" "${saveLocation}" "${target}" "${compression}"
|
gravity_DownloadBlocklistFromUrl "${url}" "${agent}" "${sourceIDs[$i]}" "${saveLocation}" "${target}" "${compression}"
|
||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
str="Creating new gravity databases"
|
|
||||||
echo -ne " ${INFO} ${str}..."
|
|
||||||
|
|
||||||
# Gravity copying SQL script
|
|
||||||
copyGravity="$(cat "${gravityDBcopy}")"
|
|
||||||
if [[ "${gravityDBfile}" != "${gravityDBfile_default}" ]]; then
|
|
||||||
# Replace default gravity script location by custom location
|
|
||||||
copyGravity="${copyGravity//"${gravityDBfile_default}"/"${gravityDBfile}"}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
output=$( { pihole-FTL sqlite3 "${gravityTEMPfile}" <<< "${copyGravity}"; } 2>&1 )
|
|
||||||
status="$?"
|
|
||||||
|
|
||||||
if [[ "${status}" -ne 0 ]]; then
|
|
||||||
echo -e "\\n ${CROSS} Unable to copy data from ${gravityDBfile} to ${gravityTEMPfile}\\n ${output}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
echo -e "${OVER} ${TICK} ${str}"
|
|
||||||
|
|
||||||
str="Storing downloaded domains in new gravity database"
|
|
||||||
echo -ne " ${INFO} ${str}..."
|
|
||||||
output=$( { printf ".timeout 30000\\n.mode csv\\n.import \"%s\" gravity\\n" "${target}" | pihole-FTL sqlite3 "${gravityTEMPfile}"; } 2>&1 )
|
|
||||||
status="$?"
|
|
||||||
|
|
||||||
if [[ "${status}" -ne 0 ]]; then
|
|
||||||
echo -e "\\n ${CROSS} Unable to fill gravity table in database ${gravityTEMPfile}\\n ${output}"
|
|
||||||
gravity_Cleanup "error"
|
|
||||||
else
|
|
||||||
echo -e "${OVER} ${TICK} ${str}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${status}" -eq 0 && -n "${output}" ]]; then
|
|
||||||
echo -e " Encountered non-critical SQL warnings. Please check the suitability of the lists you're using!\\n\\n SQL warnings:"
|
|
||||||
local warning file line lineno
|
|
||||||
while IFS= read -r line; do
|
|
||||||
echo " - ${line}"
|
|
||||||
warning="$(grep -oh "^[^:]*:[0-9]*" <<< "${line}")"
|
|
||||||
file="${warning%:*}"
|
|
||||||
lineno="${warning#*:}"
|
|
||||||
if [[ -n "${file}" && -n "${lineno}" ]]; then
|
|
||||||
echo -n " Line contains: "
|
|
||||||
awk "NR==${lineno}" < "${file}"
|
|
||||||
fi
|
|
||||||
done <<< "${output}"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm "${target}" > /dev/null 2>&1 || \
|
|
||||||
echo -e " ${CROSS} Unable to remove ${target}"
|
|
||||||
|
|
||||||
gravity_Blackbody=true
|
gravity_Blackbody=true
|
||||||
}
|
}
|
||||||
|
|
||||||
# num_total_imported_domains increases for each list processed
|
|
||||||
num_total_imported_domains=0
|
|
||||||
num_domains=0
|
|
||||||
num_non_domains=0
|
|
||||||
parseList() {
|
|
||||||
local adlistID="${1}" src="${2}" target="${3}" non_domains sample_non_domains tmp_non_domains_str false_positive
|
|
||||||
# This sed does the following things:
|
|
||||||
# 1. Remove all lines containing no domains
|
|
||||||
# 2. Remove all domains containing invalid characters. Valid are: a-z, A-Z, 0-9, dot (.), minus (-), underscore (_)
|
|
||||||
# 3. Append ,adlistID to every line
|
|
||||||
# 4. Remove trailing period (see https://github.com/pi-hole/pi-hole/issues/4701)
|
|
||||||
# 5. Ensures there is a newline on the last line
|
|
||||||
sed -r "/([^\.]+\.)+[^\.]{2,}/!d;/[^a-zA-Z0-9.\_-]/d;s/\.$//;s/$/,${adlistID}/;/.$/a\\" "${src}" >> "${target}"
|
|
||||||
|
|
||||||
# Find lines containing no domains or with invalid characters (see above)
|
|
||||||
# Remove duplicates from the list
|
|
||||||
mapfile -t non_domains <<< "$(sed -r "/([^\.]+\.)+[^\.]{2,}/d" < "${src}")"
|
|
||||||
mapfile -t -O "${#non_domains[@]}" non_domains <<< "$(sed -r "/[^a-zA-Z0-9.\_-]/!d" < "${src}")"
|
|
||||||
IFS=" " read -r -a non_domains <<< "$(tr ' ' '\n' <<< "${non_domains[@]}" | sort -u | tr '\n' ' ')"
|
|
||||||
|
|
||||||
# A list of items of common local hostnames not to report as unusable
|
|
||||||
# Some lists (i.e StevenBlack's) contain these as they are supposed to be used as HOST files
|
|
||||||
# but flagging them as unusable causes more confusion than it's worth - so we suppress them from the output
|
|
||||||
false_positives=(
|
|
||||||
"localhost"
|
|
||||||
"localhost.localdomain"
|
|
||||||
"local"
|
|
||||||
"broadcasthost"
|
|
||||||
"localhost"
|
|
||||||
"ip6-localhost"
|
|
||||||
"ip6-loopback"
|
|
||||||
"lo0 localhost"
|
|
||||||
"ip6-localnet"
|
|
||||||
"ip6-mcastprefix"
|
|
||||||
"ip6-allnodes"
|
|
||||||
"ip6-allrouters"
|
|
||||||
"ip6-allhosts"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Read the unusable lines into a string
|
|
||||||
tmp_non_domains_str=" ${non_domains[*]} "
|
|
||||||
for false_positive in "${false_positives[@]}"; do
|
|
||||||
# Remove false positives from tmp_non_domains_str
|
|
||||||
tmp_non_domains_str="${tmp_non_domains_str/ ${false_positive} / }"
|
|
||||||
done
|
|
||||||
# Read the string back into an array
|
|
||||||
IFS=" " read -r -a non_domains <<< "${tmp_non_domains_str}"
|
|
||||||
|
|
||||||
# Get a sample of non-domain entries, limited to 5 (the list should already have been de-duplicated)
|
|
||||||
IFS=" " read -r -a sample_non_domains <<< "$(tr ' ' '\n' <<< "${non_domains[@]}" | head -n 5 | tr '\n' ' ')"
|
|
||||||
|
|
||||||
local tmp_new_imported_total
|
|
||||||
# Get the new number of domains in destination file
|
|
||||||
tmp_new_imported_total="$(grep -c "^" "${target}")"
|
|
||||||
# Number of imported lines for this file is the difference between the new total and the old total. (Or, the number of domains we just added.)
|
|
||||||
num_domains="$(( tmp_new_imported_total-num_total_imported_domains ))"
|
|
||||||
# Replace the running total with the new total.
|
|
||||||
num_total_imported_domains="$tmp_new_imported_total"
|
|
||||||
# Get the number of non_domains (this is the number of entries left after stripping the source of comments/duplicates/false positives/domains)
|
|
||||||
num_non_domains="${#non_domains[@]}"
|
|
||||||
|
|
||||||
# If there are unusable lines, we display some information about them. This is not error or major cause for concern.
|
|
||||||
if [[ "${num_non_domains}" -ne 0 ]]; then
|
|
||||||
echo " ${INFO} Imported ${num_domains} domains, ignoring ${num_non_domains} non-domain entries"
|
|
||||||
echo " Sample of non-domain entries:"
|
|
||||||
for each in "${sample_non_domains[@]}"
|
|
||||||
do
|
|
||||||
echo " - ${each}"
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo " ${INFO} Imported ${num_domains} domains"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
compareLists() {
|
compareLists() {
|
||||||
local adlistID="${1}" target="${2}"
|
local adlistID="${1}" target="${2}"
|
||||||
|
|
||||||
@@ -603,7 +490,6 @@ compareLists() {
|
|||||||
sha1sum "${target}" > "${target}.sha1"
|
sha1sum "${target}" > "${target}.sha1"
|
||||||
echo " ${INFO} List has been updated"
|
echo " ${INFO} List has been updated"
|
||||||
database_adlist_status "${adlistID}" "1"
|
database_adlist_status "${adlistID}" "1"
|
||||||
database_adlist_updated "${adlistID}"
|
|
||||||
else
|
else
|
||||||
echo " ${INFO} List stayed unchanged"
|
echo " ${INFO} List stayed unchanged"
|
||||||
database_adlist_status "${adlistID}" "2"
|
database_adlist_status "${adlistID}" "2"
|
||||||
@@ -613,17 +499,18 @@ compareLists() {
|
|||||||
sha1sum "${target}" > "${target}.sha1"
|
sha1sum "${target}" > "${target}.sha1"
|
||||||
# We assume here it was changed upstream
|
# We assume here it was changed upstream
|
||||||
database_adlist_status "${adlistID}" "1"
|
database_adlist_status "${adlistID}" "1"
|
||||||
database_adlist_updated "${adlistID}"
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Download specified URL and perform checks on HTTP status and file content
|
# Download specified URL and perform checks on HTTP status and file content
|
||||||
gravity_DownloadBlocklistFromUrl() {
|
gravity_DownloadBlocklistFromUrl() {
|
||||||
local url="${1}" cmd_ext="${2}" agent="${3}" adlistID="${4}" saveLocation="${5}" target="${6}" compression="${7}"
|
local url="${1}" agent="${2}" adlistID="${3}" saveLocation="${4}" target="${5}" compression="${6}"
|
||||||
local heisenbergCompensator="" patternBuffer str httpCode success="" ip
|
local heisenbergCompensator="" listCurlBuffer str httpCode success="" ip cmd_ext
|
||||||
|
|
||||||
# Create temp file to store content on disk instead of RAM
|
# Create temp file to store content on disk instead of RAM
|
||||||
patternBuffer=$(mktemp -p "/tmp" --suffix=".phgpb")
|
# We don't use '--suffix' here because not all implementations of mktemp support it, e.g. on Alpine
|
||||||
|
listCurlBuffer="$(mktemp -p "${GRAVITY_TMPDIR}")"
|
||||||
|
mv "${listCurlBuffer}" "${listCurlBuffer%.*}.phgpb"
|
||||||
|
|
||||||
# Determine if $saveLocation has read permission
|
# Determine if $saveLocation has read permission
|
||||||
if [[ -r "${saveLocation}" && $url != "file"* ]]; then
|
if [[ -r "${saveLocation}" && $url != "file"* ]]; then
|
||||||
@@ -673,16 +560,16 @@ gravity_DownloadBlocklistFromUrl() {
|
|||||||
bad_list=$(pihole -q -adlist "${domain}" | head -n1 | awk -F 'Match found in ' '{print $2}')
|
bad_list=$(pihole -q -adlist "${domain}" | head -n1 | awk -F 'Match found in ' '{print $2}')
|
||||||
echo -e "${OVER} ${CROSS} ${str} ${domain} is blocked by ${bad_list%:}. Using DNS on ${PIHOLE_DNS_1} to download ${url}";
|
echo -e "${OVER} ${CROSS} ${str} ${domain} is blocked by ${bad_list%:}. Using DNS on ${PIHOLE_DNS_1} to download ${url}";
|
||||||
echo -ne " ${INFO} ${str} Pending..."
|
echo -ne " ${INFO} ${str} Pending..."
|
||||||
cmd_ext="--resolve $domain:$port:$ip $cmd_ext"
|
cmd_ext="--resolve $domain:$port:$ip"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L ${compression} ${cmd_ext} ${heisenbergCompensator} -w "%{http_code}" -A "${agent}" "${url}" -o "${patternBuffer}" 2> /dev/null)
|
httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L ${compression} ${cmd_ext} ${heisenbergCompensator} -w "%{http_code}" -A "${agent}" "${url}" -o "${listCurlBuffer}" 2> /dev/null)
|
||||||
|
|
||||||
case $url in
|
case $url in
|
||||||
# Did we "download" a local file?
|
# Did we "download" a local file?
|
||||||
"file"*)
|
"file"*)
|
||||||
if [[ -s "${patternBuffer}" ]]; then
|
if [[ -s "${listCurlBuffer}" ]]; then
|
||||||
echo -e "${OVER} ${TICK} ${str} Retrieval successful"; success=true
|
echo -e "${OVER} ${TICK} ${str} Retrieval successful"; success=true
|
||||||
else
|
else
|
||||||
echo -e "${OVER} ${CROSS} ${str} Not found / empty list"
|
echo -e "${OVER} ${CROSS} ${str} Not found / empty list"
|
||||||
@@ -711,24 +598,22 @@ gravity_DownloadBlocklistFromUrl() {
|
|||||||
if [[ "${success}" == true ]]; then
|
if [[ "${success}" == true ]]; then
|
||||||
if [[ "${httpCode}" == "304" ]]; then
|
if [[ "${httpCode}" == "304" ]]; then
|
||||||
# Add domains to database table file
|
# Add domains to database table file
|
||||||
parseList "${adlistID}" "${saveLocation}" "${target}"
|
pihole-FTL gravity parseList "${saveLocation}" "${gravityTEMPfile}" "${adlistID}"
|
||||||
database_adlist_status "${adlistID}" "2"
|
database_adlist_status "${adlistID}" "2"
|
||||||
database_adlist_number "${adlistID}"
|
|
||||||
done="true"
|
done="true"
|
||||||
# Check if $patternbuffer is a non-zero length file
|
# Check if $listCurlBuffer is a non-zero length file
|
||||||
elif [[ -s "${patternBuffer}" ]]; then
|
elif [[ -s "${listCurlBuffer}" ]]; then
|
||||||
# Determine if blocklist is non-standard and parse as appropriate
|
# Determine if blocklist is non-standard and parse as appropriate
|
||||||
gravity_ParseFileIntoDomains "${patternBuffer}" "${saveLocation}"
|
gravity_ParseFileIntoDomains "${listCurlBuffer}" "${saveLocation}"
|
||||||
|
# Remove curl buffer file after its use
|
||||||
|
rm "${listCurlBuffer}"
|
||||||
# Add domains to database table file
|
# Add domains to database table file
|
||||||
parseList "${adlistID}" "${saveLocation}" "${target}"
|
pihole-FTL gravity parseList "${saveLocation}" "${gravityTEMPfile}" "${adlistID}"
|
||||||
# Compare lists, are they identical?
|
# Compare lists, are they identical?
|
||||||
compareLists "${adlistID}" "${saveLocation}"
|
compareLists "${adlistID}" "${saveLocation}"
|
||||||
# Update gravity database table (status and updated timestamp are set in
|
|
||||||
# compareLists)
|
|
||||||
database_adlist_number "${adlistID}"
|
|
||||||
done="true"
|
done="true"
|
||||||
else
|
else
|
||||||
# Fall back to previously cached list if $patternBuffer is empty
|
# Fall back to previously cached list if $listCurlBuffer is empty
|
||||||
echo -e " ${INFO} Received empty file"
|
echo -e " ${INFO} Received empty file"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -739,15 +624,12 @@ gravity_DownloadBlocklistFromUrl() {
|
|||||||
if [[ -r "${saveLocation}" ]]; then
|
if [[ -r "${saveLocation}" ]]; then
|
||||||
echo -e " ${CROSS} List download failed: ${COL_LIGHT_GREEN}using previously cached list${COL_NC}"
|
echo -e " ${CROSS} List download failed: ${COL_LIGHT_GREEN}using previously cached list${COL_NC}"
|
||||||
# Add domains to database table file
|
# Add domains to database table file
|
||||||
parseList "${adlistID}" "${saveLocation}" "${target}"
|
pihole-FTL gravity parseList "${saveLocation}" "${gravityTEMPfile}" "${adlistID}"
|
||||||
database_adlist_number "${adlistID}"
|
|
||||||
database_adlist_status "${adlistID}" "3"
|
database_adlist_status "${adlistID}" "3"
|
||||||
else
|
else
|
||||||
echo -e " ${CROSS} List download failed: ${COL_LIGHT_RED}no cached list available${COL_NC}"
|
echo -e " ${CROSS} List download failed: ${COL_LIGHT_RED}no cached list available${COL_NC}"
|
||||||
# Manually reset these two numbers because we do not call parseList here
|
# Manually reset these two numbers because we do not call parseList here
|
||||||
num_domains=0
|
database_adlist_number "${adlistID}" 0 0
|
||||||
num_non_domains=0
|
|
||||||
database_adlist_number "${adlistID}"
|
|
||||||
database_adlist_status "${adlistID}" "4"
|
database_adlist_status "${adlistID}" "4"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -761,18 +643,26 @@ gravity_ParseFileIntoDomains() {
|
|||||||
# Most of the lists downloaded are already in hosts file format but the spacing/formatting is not contiguous
|
# Most of the lists downloaded are already in hosts file format but the spacing/formatting is not contiguous
|
||||||
# This helps with that and makes it easier to read
|
# This helps with that and makes it easier to read
|
||||||
# It also helps with debugging so each stage of the script can be researched more in depth
|
# It also helps with debugging so each stage of the script can be researched more in depth
|
||||||
# 1) Remove carriage returns
|
# 1) Convert all characters to lowercase
|
||||||
# 2) Convert all characters to lowercase
|
tr '[:upper:]' '[:lower:]' < "${src}" > "${destination}"
|
||||||
# 3) Remove comments (text starting with "#", include possible spaces before the hash sign)
|
|
||||||
# 4) Remove lines containing "/"
|
# 2) Remove carriage returns
|
||||||
# 5) Remove leading tabs, spaces, etc.
|
# 3) Remove lines starting with ! (ABP Comments)
|
||||||
# 6) Remove empty lines
|
# 4) Remove lines starting with [ (ABP Header)
|
||||||
< "${src}" tr -d '\r' | \
|
# 5) Remove lines containing ABP extended CSS selectors ("##", "#!#", "#@#", "#?#") preceded by a letter
|
||||||
tr '[:upper:]' '[:lower:]' | \
|
# 6) Remove comments (text starting with "#", include possible spaces before the hash sign)
|
||||||
sed 's/\s*#.*//g' | \
|
# 7) Remove leading tabs, spaces, etc. (Also removes leading IP addresses)
|
||||||
sed -r '/(\/).*$/d' | \
|
# 8) Remove empty lines
|
||||||
sed -r 's/^.*\s+//g' | \
|
|
||||||
sed '/^$/d'> "${destination}"
|
sed -i -r \
|
||||||
|
-e 's/\r$//' \
|
||||||
|
-e 's/\s*!.*//g' \
|
||||||
|
-e 's/\s*\[.*//g' \
|
||||||
|
-e '/[a-z]\#[$?@]{0,1}\#/d' \
|
||||||
|
-e 's/\s*#.*//g' \
|
||||||
|
-e 's/^.*\s+//g' \
|
||||||
|
-e '/^$/d' "${destination}"
|
||||||
|
|
||||||
chmod 644 "${destination}"
|
chmod 644 "${destination}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -782,9 +672,9 @@ gravity_Table_Count() {
|
|||||||
local str="${2}"
|
local str="${2}"
|
||||||
local num
|
local num
|
||||||
num="$(pihole-FTL sqlite3 "${gravityDBfile}" "SELECT COUNT(*) FROM ${table};")"
|
num="$(pihole-FTL sqlite3 "${gravityDBfile}" "SELECT COUNT(*) FROM ${table};")"
|
||||||
if [[ "${table}" == "vw_gravity" ]]; then
|
if [[ "${table}" == "gravity" ]]; then
|
||||||
local unique
|
local unique
|
||||||
unique="$(pihole-FTL sqlite3 "${gravityDBfile}" "SELECT COUNT(DISTINCT domain) FROM ${table};")"
|
unique="$(pihole-FTL sqlite3 "${gravityDBfile}" "SELECT COUNT(*) FROM (SELECT DISTINCT domain FROM ${table});")"
|
||||||
echo -e " ${INFO} Number of ${str}: ${num} (${COL_BOLD}${unique} unique domains${COL_NC})"
|
echo -e " ${INFO} Number of ${str}: ${num} (${COL_BOLD}${unique} unique domains${COL_NC})"
|
||||||
pihole-FTL sqlite3 "${gravityDBfile}" "INSERT OR REPLACE INTO info (property,value) VALUES ('gravity_count',${unique});"
|
pihole-FTL sqlite3 "${gravityDBfile}" "INSERT OR REPLACE INTO info (property,value) VALUES ('gravity_count',${unique});"
|
||||||
else
|
else
|
||||||
@@ -794,7 +684,9 @@ gravity_Table_Count() {
|
|||||||
|
|
||||||
# Output count of blacklisted domains and regex filters
|
# Output count of blacklisted domains and regex filters
|
||||||
gravity_ShowCount() {
|
gravity_ShowCount() {
|
||||||
gravity_Table_Count "vw_gravity" "gravity domains" ""
|
# Here we use the table "gravity" instead of the view "vw_gravity" for speed.
|
||||||
|
# It's safe to replace it here, because right after a gravity run both will show the exactly same number of domains.
|
||||||
|
gravity_Table_Count "gravity" "gravity domains" ""
|
||||||
gravity_Table_Count "vw_blacklist" "exact blacklisted domains"
|
gravity_Table_Count "vw_blacklist" "exact blacklisted domains"
|
||||||
gravity_Table_Count "vw_regex_blacklist" "regex blacklist filters"
|
gravity_Table_Count "vw_regex_blacklist" "regex blacklist filters"
|
||||||
gravity_Table_Count "vw_whitelist" "exact whitelisted domains"
|
gravity_Table_Count "vw_whitelist" "exact whitelisted domains"
|
||||||
@@ -828,7 +720,10 @@ gravity_Cleanup() {
|
|||||||
# Delete tmp content generated by Gravity
|
# Delete tmp content generated by Gravity
|
||||||
rm ${piholeDir}/pihole.*.txt 2> /dev/null
|
rm ${piholeDir}/pihole.*.txt 2> /dev/null
|
||||||
rm ${piholeDir}/*.tmp 2> /dev/null
|
rm ${piholeDir}/*.tmp 2> /dev/null
|
||||||
rm /tmp/*.phgpb 2> /dev/null
|
# listCurlBuffer location
|
||||||
|
rm "${GRAVITY_TMPDIR}"/*.phgpb 2> /dev/null
|
||||||
|
# invalid_domains location
|
||||||
|
rm "${GRAVITY_TMPDIR}"/*.ph-non-domains 2> /dev/null
|
||||||
|
|
||||||
# Ensure this function only runs when gravity_SetDownloadOptions() has completed
|
# Ensure this function only runs when gravity_SetDownloadOptions() has completed
|
||||||
if [[ "${gravity_Blackbody:-}" == true ]]; then
|
if [[ "${gravity_Blackbody:-}" == true ]]; then
|
||||||
@@ -991,7 +886,10 @@ if ! gravity_CheckDNSResolutionAvailable; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
gravity_DownloadBlocklists
|
if ! gravity_DownloadBlocklists; then
|
||||||
|
echo -e " ${CROSS} Unable to create gravity database. Please try again later. If the problem persists, please contact support."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Create local.list
|
# Create local.list
|
||||||
gravity_generateLocalList
|
gravity_generateLocalList
|
||||||
|
|||||||
18
test/_fedora_38.Dockerfile
Normal file
18
test/_fedora_38.Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
FROM fedora:38
|
||||||
|
RUN dnf install -y git initscripts
|
||||||
|
|
||||||
|
ENV GITDIR /etc/.pihole
|
||||||
|
ENV SCRIPTDIR /opt/pihole
|
||||||
|
|
||||||
|
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
|
||||||
|
ADD . $GITDIR
|
||||||
|
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $SCRIPTDIR/
|
||||||
|
ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
||||||
|
|
||||||
|
RUN true && \
|
||||||
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
|
ENV SKIP_INSTALL true
|
||||||
|
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
18
test/_ubuntu_23.Dockerfile
Normal file
18
test/_ubuntu_23.Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
FROM buildpack-deps:lunar-scm
|
||||||
|
|
||||||
|
ENV GITDIR /etc/.pihole
|
||||||
|
ENV SCRIPTDIR /opt/pihole
|
||||||
|
|
||||||
|
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
|
||||||
|
ADD . $GITDIR
|
||||||
|
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $SCRIPTDIR/
|
||||||
|
ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
RUN true && \
|
||||||
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
|
ENV SKIP_INSTALL true
|
||||||
|
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
docker-compose == 1.29.2
|
docker-compose == 1.29.2
|
||||||
pytest == 7.2.1
|
pytest == 7.3.1
|
||||||
pytest-xdist == 3.1.0
|
pytest-xdist == 3.3.1
|
||||||
pytest-testinfra == 7.0.0
|
pytest-testinfra == 8.1.0
|
||||||
tox == 4.4.4
|
tox == 4.5.1
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,26 @@ def test_key_addition_works(host):
|
|||||||
assert expected_stdout == output.stdout
|
assert expected_stdout == output.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_key_addition_substr(host):
|
||||||
|
"""Confirms addKey adds substring keys (no value) to a file"""
|
||||||
|
host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/utils.sh
|
||||||
|
addKey "./testoutput" "KEY_ONE"
|
||||||
|
addKey "./testoutput" "KEY_O"
|
||||||
|
addKey "./testoutput" "KEY_TWO"
|
||||||
|
addKey "./testoutput" "Y_TWO"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
output = host.run(
|
||||||
|
"""
|
||||||
|
cat ./testoutput
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "KEY_ONE\nKEY_O\nKEY_TWO\nY_TWO\n"
|
||||||
|
assert expected_stdout == output.stdout
|
||||||
|
|
||||||
|
|
||||||
def test_key_removal_works(host):
|
def test_key_removal_works(host):
|
||||||
"""Confirms removeKey removes a key or key/value pair"""
|
"""Confirms removeKey removes a key or key/value pair"""
|
||||||
host.run(
|
host.run(
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ envlist = py3
|
|||||||
[testenv:py3]
|
[testenv:py3]
|
||||||
allowlist_externals = docker
|
allowlist_externals = docker
|
||||||
deps = -rrequirements.txt
|
deps = -rrequirements.txt
|
||||||
commands = docker build -f _centos_8.Dockerfile -t pytest_pihole:test_container ../
|
commands = docker buildx build --load --progress plain -f _centos_8.Dockerfile -t pytest_pihole:test_container ../
|
||||||
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py ./test_centos_common_support.py
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py ./test_centos_common_support.py
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ envlist = py3
|
|||||||
[testenv:py3]
|
[testenv:py3]
|
||||||
allowlist_externals = docker
|
allowlist_externals = docker
|
||||||
deps = -rrequirements.txt
|
deps = -rrequirements.txt
|
||||||
commands = docker build -f _centos_9.Dockerfile -t pytest_pihole:test_container ../
|
commands = docker buildx build --load --progress plain -f _centos_9.Dockerfile -t pytest_pihole:test_container ../
|
||||||
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py ./test_centos_common_support.py
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py ./test_centos_common_support.py
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ envlist = py3
|
|||||||
[testenv:py3]
|
[testenv:py3]
|
||||||
allowlist_externals = docker
|
allowlist_externals = docker
|
||||||
deps = -rrequirements.txt
|
deps = -rrequirements.txt
|
||||||
commands = docker build -f _debian_10.Dockerfile -t pytest_pihole:test_container ../
|
commands = docker buildx build --load --progress plain -f _debian_10.Dockerfile -t pytest_pihole:test_container ../
|
||||||
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ envlist = py3
|
|||||||
[testenv:py3]
|
[testenv:py3]
|
||||||
allowlist_externals = docker
|
allowlist_externals = docker
|
||||||
deps = -rrequirements.txt
|
deps = -rrequirements.txt
|
||||||
commands = docker build -f _debian_11.Dockerfile -t pytest_pihole:test_container ../
|
commands = docker buildx build --load --progress plain -f _debian_11.Dockerfile -t pytest_pihole:test_container ../
|
||||||
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ envlist = py3
|
|||||||
[testenv:py3]
|
[testenv:py3]
|
||||||
allowlist_externals = docker
|
allowlist_externals = docker
|
||||||
deps = -rrequirements.txt
|
deps = -rrequirements.txt
|
||||||
commands = docker build -f _fedora_36.Dockerfile -t pytest_pihole:test_container ../
|
commands = docker buildx build --load --progress plain -f _fedora_36.Dockerfile -t pytest_pihole:test_container ../
|
||||||
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py ./test_fedora_support.py
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py ./test_fedora_support.py
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ envlist = py3
|
|||||||
[testenv]
|
[testenv]
|
||||||
allowlist_externals = docker
|
allowlist_externals = docker
|
||||||
deps = -rrequirements.txt
|
deps = -rrequirements.txt
|
||||||
commands = docker build -f _fedora_37.Dockerfile -t pytest_pihole:test_container ../
|
commands = docker buildx build --load --progress plain -f _fedora_37.Dockerfile -t pytest_pihole:test_container ../
|
||||||
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py ./test_fedora_support.py
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py ./test_fedora_support.py
|
||||||
|
|||||||
8
test/tox.fedora_38.ini
Normal file
8
test/tox.fedora_38.ini
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[tox]
|
||||||
|
envlist = py3
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
allowlist_externals = docker
|
||||||
|
deps = -rrequirements.txt
|
||||||
|
commands = docker buildx build --load --progress plain -f _fedora_38.Dockerfile -t pytest_pihole:test_container ../
|
||||||
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py ./test_fedora_support.py
|
||||||
@@ -4,5 +4,5 @@ envlist = py3
|
|||||||
[testenv:py3]
|
[testenv:py3]
|
||||||
allowlist_externals = docker
|
allowlist_externals = docker
|
||||||
deps = -rrequirements.txt
|
deps = -rrequirements.txt
|
||||||
commands = docker build -f _ubuntu_20.Dockerfile -t pytest_pihole:test_container ../
|
commands = docker buildx build --load --progress plain -f _ubuntu_20.Dockerfile -t pytest_pihole:test_container ../
|
||||||
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ envlist = py3
|
|||||||
[testenv:py3]
|
[testenv:py3]
|
||||||
allowlist_externals = docker
|
allowlist_externals = docker
|
||||||
deps = -rrequirements.txt
|
deps = -rrequirements.txt
|
||||||
commands = docker build -f _ubuntu_22.Dockerfile -t pytest_pihole:test_container ../
|
commands = docker buildx build --load --progress plain -f _ubuntu_22.Dockerfile -t pytest_pihole:test_container ../
|
||||||
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
||||||
|
|||||||
8
test/tox.ubuntu_23.ini
Normal file
8
test/tox.ubuntu_23.ini
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[tox]
|
||||||
|
envlist = py3
|
||||||
|
|
||||||
|
[testenv:py3]
|
||||||
|
allowlist_externals = docker
|
||||||
|
deps = -rrequirements.txt
|
||||||
|
commands = docker buildx build --load --progress plain -f _ubuntu_23.Dockerfile -t pytest_pihole:test_container ../
|
||||||
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
||||||
Reference in New Issue
Block a user