Skip to content

Commit

Permalink
Cli argument configuration 47 (#71)
Browse files Browse the repository at this point in the history
* initial implementation of cli-arguments (#47)
* implement run without config & ENV based configuration
* implement option for privoxy-config & lists-path
* add apparmore support

---------

Signed-off-by: Andrwe@Gitlab <[email protected]>
  • Loading branch information
Andrwe authored May 25, 2024
1 parent 57dae33 commit e13b931
Show file tree
Hide file tree
Showing 6 changed files with 408 additions and 78 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
run: |
export DEBIAN_FRONTEND=noninteractive
sudo apt-get update -qq --yes
sudo apt-get install python3-pip --yes
sudo apt-get install python3-pip apparmor --yes
sudo --preserve-env=HTTPS_SUPPORT sh helper/install_deps.sh
# install via sudo to run pytest as root - see below
sudo pip install -r ./tests/requirements.txt
Expand Down
223 changes: 160 additions & 63 deletions privoxy-blocklist.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,27 +48,40 @@ FILTERTYPES=(
"id_global"
)

DEFAULT_URLS=(
"https://easylist-downloads.adblockplus.org/easylistgermany.txt"
"https://easylist-downloads.adblockplus.org/easylist.txt"
)

######################################################################
#
# No changes needed after this line.
#
######################################################################

SCRIPTNAME="$(basename "$(readlink -f "${0}")")"

function usage() {
get_config_path
echo "${TMPNAME:-This} is a script to convert AdBlockPlus-lists into Privoxy-lists and install them."
echo " "
echo "Options:"
echo " -h: Show this help."
echo " -c: Path to script configuration file. (default = ${SCRIPTCONF} - OS specific)"
echo " -f filter: only activate given content filter, can be used multiple times. (default: empty, content-filter disabled)"
echo " -c path: Path to script configuration file. (default = ${SCRIPTCONF} - OS specific) [env: SCRIPTCONF='']"
echo " -C: Don't write configuration file [env: NO_CONFIG=1]"
echo " -d path: Path to store generated list files (*.action & *.filter) in. (default = directory of privoxy-config - OS specific) [env: LISTS_DIR='']"
echo " -f filter: Only activate given content filter, can be used multiple times. (default: empty, content-filter disabled) [env: FILTERS=()]"
echo " Supported values: ${FILTERTYPES[*]}"
echo " -q: Don't give any output."
echo " -v 1: Enable verbosity 1. Show a little bit more output."
echo " -v 2: Enable verbosity 2. Show a lot more output."
echo " -v 3: Enable verbosity 3. Show all possible output and don't delete temporary files.(For debugging only!!)"
echo " -V: Show version."
echo " -p path: Path to Privoxy config file. (default = OS specific) [env: PRIVOXY_CONF='']"
echo " -q: Don't give any output. [env: DBG='-1']"
echo " -r: Remove all lists build by this script."
echo " -t path: Define path for temporary files. (default: /tmp/${SCRIPTNAME}) [env: TMPDIR='']"
echo " -u URL: Process given list URL, can be used multiple times. (default: ${DEFAULT_URLS[*]}) [env: URLS=()]"
echo " -U: Update configuration file based on given parameters and exit."
echo " -v 1: Enable verbosity 1. Show a little bit more output. [env: DBG=1]"
echo " -v 2: Enable verbosity 2. Show a lot more output. [env: DBG=2]"
echo " -v 3: Enable verbosity 3. Show all possible output and don't delete temporary files.(For debugging only!!) [env: DBG=3]"
echo " -V: Show version."
}

# shellcheck disable=SC2317 # function is called in case of FILTERS not empty
Expand All @@ -86,14 +99,14 @@ function activate_config() {
option="filterfile"
;;
esac
copy "${file_path}" "${PRIVOXY_DIR}"
if ! grep -q "${file_name}" "${PRIVOXY_CONF}"; then
copy "${file_path}" "${LISTS_DIR}"
if ! grep -q "${LISTS_DIR}/${file_name}" "${PRIVOXY_CONF}"; then
debug 0 "Modifying ${PRIVOXY_CONF} ..."
# ensure generated config is above user.* to allow overriding
if [ "${OS_FLAVOR}" = "openwrt" ]; then
sed "s%^\(\s*#*\s*list\s\s*${option}\s\s*'user\.${file_type}'\)%\tlist\t${option}\t'${PRIVOXY_DIR}/${file_name}'\n\1%" "${PRIVOXY_CONF}" > "${TMPDIR}/config"
sed "s%^\(\s*#*\s*list\s\s*${option}\s\s*'user\.${file_type}'\)%\tlist\t${option}\t'${LISTS_DIR}/${file_name}'\n\1%" "${PRIVOXY_CONF}" > "${TMPDIR}/config"
else
sed "s/^\(#*\s*${option} user\.${file_type}\)/${option} ${file_name}\n\1/" "${PRIVOXY_CONF}" > "${TMPDIR}/config"
sed "s%^\(#*\s*${option} user\.${file_type}\)%${option} ${LISTS_DIR}/${file_name}\n\1%" "${PRIVOXY_CONF}" > "${TMPDIR}/config"
fi
debug 0 "... modification done."
debug 0 "Installing new config ..."
Expand Down Expand Up @@ -151,10 +164,10 @@ function get_user_group() {
# shellcheck disable=SC2012
ls -l "/etc/privoxy/default.action" | sed 's/^[^ ]*\s\s*[0-9][0-9]*\s\s*\([^ ][^ ]*\)\s\s*\([^ ][^ ]*\)\s\s*.*/\1 \2/'
else
if LANG=C stat --help |& grep ' \-c' | grep -q '\-\-format'; then
if LANG=C stat --help |& grep -- ' -c' | grep -q -- '--format'; then
# Linux stat-command
stat -c "%U %G" /etc/privoxy/default.action
elif LANG=C stat --help |& grep ' \-f' | grep -q 'format'; then
elif LANG=C stat --help |& grep -- ' -f' | grep -q 'format'; then
# MacOS stat-command
local user_id group_id
user_id="$(stat -f "%u" /etc/privoxy/default.action)"
Expand All @@ -177,47 +190,27 @@ function get_group() {
get_user_group | cut -d' ' -f2
}

function prepare() {
if [ ${UID} -ne 0 ]; then
error "Root privileges needed. Exit."
usage
exit 1
fi

for dep in "${DEPENDS[@]}"; do
if ! type -p "${dep}" > /dev/null; then
error "The command '${dep}' can't be found. Please install the package providing '${dep}' and run $0 again. Exit"
info "To install all dependencies at once you can run 'https://raw.githubusercontent.com/Andrwe/privoxy-blocklist/main/helper/install_deps.sh'"
exit 1
fi
function write_config() {
local filters="" urls=""
# convert to list of quoted strings
for filter in "${OPT_FILTERS[@]:-"${FILTERS[@]}"}"; do
filters+="\"${filter}\" "
done

if [ -z "${SCRIPTCONF:-}" ]; then
get_config_path
fi

if [[ ! -d "$(dirname "${SCRIPTCONF}")" ]]; then
info "creating missing config directory '$(dirname "${SCRIPTCONF}")'"
mkdir -p "$(dirname "${SCRIPTCONF}")"
chmod 755 "$(dirname "${SCRIPTCONF}")"
fi

if [[ ! -f "${SCRIPTCONF}" ]]; then
info "No config found in ${SCRIPTCONF}. Creating default one and exiting because you might have to adjust it."
cat > "${SCRIPTCONF}" << EOF
# convert to list of quoted strings
for url in "${OPT_URLS[@]:-"${URLS[@]:-"${DEFAULT_URLS[@]}"}"}"; do
urls+="\"${url}\" "
done
cat > "${SCRIPTCONF}" << EOF
# Config of privoxy-blocklist
# array of URL for AdblockPlus lists
# for more sources just add it within the round brackets
URLS=(
"https://easylist-downloads.adblockplus.org/easylistgermany.txt"
"https://easylist-downloads.adblockplus.org/easylist.txt"
)
URLS=(${urls})
# array of content filters to convert
# for supported values check: $0 -h
# empty by default to deactivate as content filters slowdown privoxy a lot
FILTERS=()
FILTERS=(${filters})
# config for privoxy initscript providing PRIVOXY_CONF, PRIVOXY_USER and PRIVOXY_GROUP
INIT_CONF="/etc/conf.d/privoxy"
Expand All @@ -231,7 +224,7 @@ INIT_CONF="/etc/conf.d/privoxy"
# name for lock file (default: script name)
TMPNAME="\$(basename "\$(readlink -f "\${0}")")"
# directory for temporary files
TMPDIR="/tmp/\${TMPNAME}"
TMPDIR="${OPT_TMPDIR:-"/tmp/\${TMPNAME}"}"
# Debug-level
# -1 = quiet
Expand All @@ -241,22 +234,77 @@ TMPDIR="/tmp/\${TMPNAME}"
# 3 = incredibly loud (function debugging)
DBG=0
EOF
exit 2
}

function prepare() {
if [ ${UID} -ne 0 ]; then
error "Root privileges needed. Exit."
usage
exit 1
fi

for dep in "${DEPENDS[@]}"; do
if ! type -p "${dep}" > /dev/null; then
error "The command '${dep}' can't be found. Please install the package providing '${dep}' and run $0 again. Exit"
info "To install all dependencies at once you can run 'https://raw.githubusercontent.com/Andrwe/privoxy-blocklist/main/helper/install_deps.sh'"
exit 1
fi
done

if [ -z "${SCRIPTCONF:-}" ]; then
get_config_path
fi

if [[ ! -r "${SCRIPTCONF}" ]]; then
debug -1 "Can't read ${SCRIPTCONF}. Permission denied."
if [ "${NO_CONFIG}" -eq 0 ]; then
if [[ ! -d "$(dirname "${SCRIPTCONF}")" ]]; then
info "creating missing config directory '$(dirname "${SCRIPTCONF}")'"
mkdir -p "$(dirname "${SCRIPTCONF}")"
chmod 755 "$(dirname "${SCRIPTCONF}")"
fi

if [[ ! -f "${SCRIPTCONF}" ]]; then
info "No config found in ${SCRIPTCONF}. Creating default one and exiting because you might have to adjust it."
write_config
exit 2
fi
if [ "${OPT_UPDATE_CONFIG}" -eq 1 ]; then
info "Updating configuration as -U was specified."
# shellcheck disable=SC1090
source "${SCRIPTCONF}"
if [ -z "${OPT_FILTERS[*]}" ]; then
OPT_FILTERS=("${FILTERS[@]}")
fi
if [ -z "${OPT_TMPDIR}" ]; then
OPT_TMPDIR="${TMPDIR}"
fi
write_config
exit 0
fi

if [[ ! -r "${SCRIPTCONF}" ]]; then
debug -1 "Can't read ${SCRIPTCONF}. Permission denied."
fi

# shellcheck disable=SC1090
source "${SCRIPTCONF}"
fi

# shellcheck disable=SC1090
source "${SCRIPTCONF}"
if [ -n "${OPT_DBG:-}" ]; then
DBG="${OPT_DBG}"
fi
if [ -n "${OPT_FILTERS[*]}" ]; then
FILTERS=("${OPT_FILTERS[@]}")
fi
debug 2 "Content filters: ${OPT_FILTERS[*]:-disabled}"
debug 2 "Content filters: ${FILTERS[*]:-disabled}"
if [ -n "${OPT_URLS[*]}" ]; then
URLS=("${OPT_URLS[@]}")
fi
debug 2 "URLs: ${URLS[*]:-}"
if [ -n "${OPT_TMPDIR}" ]; then
TMPDIR="${OPT_TMPDIR}"
fi
debug 2 "TMPDIR: ${TMPDIR:-}"
TMPNAME="${TMPNAME:-"$(basename "$(readlink -f "${0}")")"}"

# load privoxy config
# shellcheck disable=SC1090
Expand All @@ -265,7 +313,7 @@ EOF
fi

# set command to be run on exit
if [ "${DBG}" -gt 2 ]; then
if [ "${DBG:-0}" -gt 2 ]; then
trap - INT TERM EXIT
fi

Expand All @@ -291,13 +339,30 @@ EOF
fi

# set privoxy config dir
PRIVOXY_DIR="$(dirname "${PRIVOXY_CONF}")"
LISTS_DIR="${LISTS_DIR:-"$(dirname "${PRIVOXY_CONF}")"}"
if ! [ -d "${LISTS_DIR}" ]; then
mkdir -p "${LISTS_DIR}"
chown "${PRIVOXY_USER}:${PRIVOXY_GROUP}" "${LISTS_DIR}"
fi

if [ -z "${URLS[*]:-}" ]; then
error "no URLs given. Either provide -u or set environment variable URLS."
exit 3
fi
if [ -z "${TMPDIR:-}" ]; then
error "no TMPDIR given. Either provide -t or set environment variable TMPDIR."
exit 3
fi
if [ -z "${PRIVOXY_CONF:-}" ]; then
error "no PRIVOXY_CONF given. Either provide -p or set environment variable PRIVOXY_CONF."
exit 3
fi
}

function debug() {
local expected_level="${1}"
shift 1
if [ "${DBG}" -ge "${expected_level}" ]; then
if [ "${DBG:-0}" -ge "${expected_level}" ]; then
if [ "${expected_level}" -eq 0 ]; then
info "${@}"
else
Expand Down Expand Up @@ -821,20 +886,24 @@ function remove() {
if [ "${choice}" != "y" ]; then
exit 0
fi
if rm -rf "${PRIVOXY_DIR}/"*.script.{action,filter} \
if rm -rf "${LISTS_DIR}/"*.script.{action,filter} \
&& sed '/^\(\s\s*list\s\s*\)\?actionsfile\s\s*.*\.script\.action.\?$/d;/^\(\s\s*list\s\s*\)\?filterfile\s\s*.*\.script\.filter.\?$/d' -i "${PRIVOXY_CONF}"; then
echo "Lists removed."
exit 0
fi
error "An error occured while removing the lists."
error "Please have a look into ${PRIVOXY_DIR} whether there are .script.* files and search for *.script.* in ${PRIVOXY_CONF}."
error "Please have a look into ${LISTS_DIR} whether there are .script.* files and search for *.script.* in ${PRIVOXY_CONF}."
exit 1
}

VERBOSE=()
method="main"
OS="$(uname)"
NO_CONFIG="${NO_CONFIG:-0}"
OPT_TMPDIR=""
OPT_UPDATE_CONFIG=0
OPT_FILTERS=()
OPT_URLS=()

# ID_LIKE is mainly used to check for openwrt and set via os-release
ID_LIKE="unset"
Expand All @@ -852,20 +921,38 @@ case "${ID_LIKE}" in
esac

# loop for options
while getopts ":c:f:hrqv:V" opt; do
while getopts ":c:Cd:f:hp:qrt:u:Uv:V" opt; do
case "${opt}" in
"c")
SCRIPTCONF="${OPTARG}"
;;
"C")
NO_CONFIG=1
;;
"d")
LISTS_DIR="${OPTARG}"
;;
"f")
OPT_FILTERS+=("${OPTARG,,}")
;;
"p")
PRIVOXY_CONF="${OPTARG}"
;;
"q")
OPT_DBG=-1
;;
"r")
method="remove"
;;
"t")
OPT_TMPDIR="${OPTARG}"
;;
"u")
OPT_URLS+=("${OPTARG}")
;;
"U")
OPT_UPDATE_CONFIG=1
;;
"v")
OPT_DBG="${OPTARG}"
if [ "${OS_FLAVOR}" != "openwrt" ]; then
Expand All @@ -878,18 +965,28 @@ while getopts ":c:f:hrqv:V" opt; do
exit 0
;;
":")
echo "${TMPNAME}: -${OPTARG} requires an argument" >&2
error "-${OPTARG} requires an argument" >&2
echo
usage
exit 1
;;
"h" | *)
"h")
usage
exit 0
;;
"?" | *)
error "Unknown option: ${OPTARG}"
echo
usage
exit 1
;;
esac
done
#PRIVOXY_USER
#PRIVOXY_GROUP

if [ -n "${OPT_FILTERS[*]}" ]; then
if unknown="$(grep -vxFf <(printf '%s\n' "${FILTERTYPES[@]}") <(printf '%s\n' "${OPT_FILTERS[@]}"))"; then
if [ -n "${OPT_FILTERS[*]:-"${FILTERS[*]}"}" ]; then
if unknown="$(grep -vxFf <(printf '%s\n' "${FILTERTYPES[@]}") <(printf '%s\n' "${OPT_FILTERS[@]:-"${FILTERS[@]}"}"))"; then
error "Unknown filters: ${unknown}"
exit 1
fi
Expand All @@ -901,7 +998,7 @@ trap 'rm -fr "${TMPDIR}";exit' INT TERM EXIT

lock
debug 2 "URL-List: ${URLS[*]}"
debug 2 "Privoxy-Configdir: ${PRIVOXY_DIR}"
debug 2 "Target directory for lists: ${LISTS_DIR}"
debug 2 "Temporary directory: ${TMPDIR}"
"${method}"

Expand Down
Loading

0 comments on commit e13b931

Please sign in to comment.