93 lines
2.7 KiB
Bash
Executable file
93 lines
2.7 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# Configuration.
|
|
STORAGE_PREFIX="/storage/md0"
|
|
LOCATE_DB="/tmp/mirrors.db"
|
|
DEF_RESULTS=500
|
|
MAX_RESULTS=3000
|
|
MAX_CONCURRENT=10
|
|
IGNORE_REGEXES=('^/\.sandbox.*' '^/\.lftp.*' '^/dead\.letter' '.*\.rsync-tmp.*')
|
|
|
|
# Extglob is required.
|
|
shopt -s extglob
|
|
|
|
# Output an error in processing.
|
|
die() {
|
|
# $1 = The error code to output.
|
|
# 0 = Success.
|
|
# 1 = Temporary error (eg, max concurrent).
|
|
# 2 = Perminant error.
|
|
# $2 = The error message to output (if any).
|
|
printf "%s: %s\\n" "Status" "${1:-2}"
|
|
[[ -n "$2" ]] && printf "%s: %s\\n" "Error" "$2"
|
|
exit 1
|
|
}
|
|
|
|
# Initial headers.
|
|
printf "%s: %s\\n" "Content-type" "text/plain"
|
|
printf "%s: %s\\n" "Cache-Control" "no-cache, no-store, must-revalidate"
|
|
printf "%s: %s\\n" "Pragma" "no-cache"
|
|
printf "%s: %s\\n\\n" "Expires" "1"
|
|
|
|
# Limit the number of concurrent searches to avoid DoS.
|
|
if (( $(lsof -t "$LOCATE_DB" | wc -l) > (MAX_CONCURRENT - 1) )); then
|
|
die "1" "Too many concurrent searches"
|
|
else
|
|
# Lock the DB for the lsof count above.
|
|
# shellcheck disable=SC2015
|
|
exec 9<"$LOCATE_DB" && flock -s -E 10 -w 2 9 || die "1" "Too many concurrent searches"
|
|
|
|
# shellcheck disable=SC2154
|
|
while read -r -d '&' QUERY; do
|
|
# If the read returned an empty string, skip.
|
|
[[ -z "$QUERY" ]] && continue
|
|
|
|
# Extract the key and value to temporary variables.
|
|
KEY="${QUERY%%=*}"
|
|
VALUE="${QUERY#*=}"
|
|
|
|
# Check the key is valid as a variable name.
|
|
[[ ! "$KEY" =~ ^[[:digit:]_]*[[:alnum:]_]*$ ]] && die "2" "Invalid query - don't try to be clever :)"
|
|
|
|
# Remove spaces from beginning and end of value.
|
|
: "${VALUE/#+(+)}"
|
|
: "${_/%+(+)}"
|
|
|
|
# Squash multiple spaces in value.
|
|
: "${_//+(+)/+}"
|
|
|
|
# Convert values from %-encoded form.
|
|
: "${_//%/\\x}"
|
|
|
|
# Define the variable from the key name.
|
|
declare "QS_$KEY"="$(printf "%b" "${_//+/ }")"
|
|
done <<<"${QUERY_STRING,,}&" # The & at the end is required.
|
|
|
|
# Adjust 'QS_q' for the locate command by wrapping search elements in *.
|
|
: "*${QS_q// /* *}*"
|
|
QS_q="${_//\/*/*}"
|
|
|
|
# Adjust 'QS_l' to not go over maximum limit of results or use default if not supplied.
|
|
[[ -z "$QS_l" ]] && QS_l="$DEF_RESULTS"
|
|
(( QS_l > MAX_RESULTS )) && QS_l="$MAX_RESULTS"
|
|
|
|
# Give success status as checks have passed.
|
|
printf "%s: %s\\n" "Status" "0"
|
|
|
|
I=1
|
|
# shellcheck disable=SC2154
|
|
while read -r ITEM; do
|
|
# Only show specified number of items.
|
|
(( I == (QS_l + 1) )) && break
|
|
|
|
# Remove paths we don't want the user to see.
|
|
while read -r -d " " REGEX; do
|
|
[[ "${ITEM/$STORAGE_PREFIX}" =~ $REGEX ]] && continue 2
|
|
done <<<"${IGNORE_REGEXES[@]}"
|
|
|
|
# List the item.
|
|
printf "%s\\n" "${ITEM/$STORAGE_PREFIX}"
|
|
|
|
(( I++ ))
|
|
done < <(locate -A -d "$LOCATE_DB" -i -l "$(( QS_l * 2 ))" "$STORAGE_PREFIX/${QS_p##/}" "$QS_q" | sort)
|
|
fi
|