diff --git a/cgi-bin/searchapi.cgi b/cgi-bin/searchapi.cgi index b6bfa43..3f6fce7 100755 --- a/cgi-bin/searchapi.cgi +++ b/cgi-bin/searchapi.cgi @@ -18,24 +18,25 @@ die() { # 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" + printf "%s: %s%b" "Status" "${1:-2}" "\0" + [[ -n "$2" ]] && printf "%s: %s%b" "Error" "$2" "\0" exit 1 } # Initial headers. -printf "%s: %s\\n" "Content-type" "text/plain" +#printf "%s: %s\\n" "Content-type" "text/plain" +printf "%s: %s\\n" "Content-type" "application/octet-stream" 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" + 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" + 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 @@ -49,34 +50,41 @@ else # 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" "${_//+/ }")" + declare "QS_$KEY"="$VALUE" 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="${_//\/*/*}" + # Remove spaces from beginning and end of query. + QS_q="${QS_q/##+(+)}" + QS_q="${QS_q/%%+(+)}" - # Adjust 'QS_l' to not go over maximum limit of results or use default if not supplied. + # Squash multiple +s in query. + QS_q="${QS_q//+(+)/+}" + + # Convert any +s in the path and query into spaces. + QS_p="${QS_p//+/ }" + QS_q="${QS_q//+/ }" + + # Don't allow /s in the query. + # [[ "$QS_q" == */* ]] || [[ "$QS_q" == *%2F* ]] && die "2" "Searches may not include the '/' character." + + # Convert path and query from %-encoded form. + QS_p="$(printf "%b" "${QS_p//%/\\x}")" + QS_q="$(printf "%b" "${QS_q//%/\\x}")" + + # 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" + printf "%s: %s%b" "Status" "0" "\0" I=1 # shellcheck disable=SC2154 - while read -r ITEM; do + while read -r -d $'\0' ITEM; do # Only show specified number of items. (( I == (QS_l + 1) )) && break @@ -91,21 +99,21 @@ else # List the item. if [[ -f "$ITEM" ]]; then # File type. - printf "%s %s\\n" "f" "${ITEM/$STORAGE_PREFIX}" + printf "%s %s%b" "f" "${ITEM/$STORAGE_PREFIX}" "\0" elif [[ -d "$ITEM" ]]; then # Directory type. - printf "%s %s\\n" "d" "${ITEM/$STORAGE_PREFIX}" + printf "%s %s%b" "d" "${ITEM/$STORAGE_PREFIX}" "\0" elif [[ -L "$ITEM" ]]; then # Symbolic link type. - printf "%s %s\\n" "l" "${ITEM/$STORAGE_PREFIX}" + printf "%s %s%b" "l" "${ITEM/$STORAGE_PREFIX}" "\0" elif [[ -e "$ITEM" ]]; then # Other type. - printf "%s %s\\n" "o" "${ITEM/$STORAGE_PREFIX}" + printf "%s %s%b" "o" "${ITEM/$STORAGE_PREFIX}" "\0" else # Stale file in database. - printf "%s %s\\n" "?" "${ITEM/$STORAGE_PREFIX}" + printf "%s %s%b" "?" "${ITEM/$STORAGE_PREFIX}" "\0" fi (( I++ )) - done < <(locate -A -d "$LOCATE_DB" -i -l "$(( QS_l * 2 ))" "$STORAGE_PREFIX/${QS_p##/}" $QS_q | sort) + done < <(locate -0 -A -d "$LOCATE_DB" -i -l "$(( QS_l * 2 ))" "$STORAGE_PREFIX/${QS_p/#+(\/)}" $QS_q | sort) fi