From f4036c328087fb0d5502af825ebea7ad4120a1c1 Mon Sep 17 00:00:00 2001 From: Darren 'Tadgy' Austin Date: Tue, 30 Aug 2022 02:04:59 +0100 Subject: [PATCH] Forgot to add the new search.cgi. --- cgi-bin/search.cgi | 222 ++++++++++++++++++++++++++------------------- 1 file changed, 130 insertions(+), 92 deletions(-) diff --git a/cgi-bin/search.cgi b/cgi-bin/search.cgi index e8b2522..4010a95 100755 --- a/cgi-bin/search.cgi +++ b/cgi-bin/search.cgi @@ -1,9 +1,13 @@ #!/bin/bash # Configuration options +BASE_DIR="/data/sites" STORAGE_PREFIX="/storage/md0" -HEADER="/data/sites/slackware.uk/html/search_header.html" -FOOTER="/data/sites/slackware.uk/html/search_footer.html" +IGNORE_REGEXES=('^/\.sandbox.*' '^/\.lftp.*' '^/dead\.letter' '.*\.rsync-tmp.*') +HEADER_DARK="$BASE_DIR/${SERVER_NAME:-slackware.uk}/html/includes/search-header-dark.html" +FOOTER_DARK="$BASE_DIR/${SERVER_NAME:-slackware.uk}/html/includes/search-footer-dark.html" +HEADER_LIGHT="$BASE_DIR/${SERVER_NAME:-slackware.uk}/html/includes/search-header-light.html" +FOOTER_LIGHT="$BASE_DIR/${SERVER_NAME:-slackware.uk}/html/includes/search-footer-light.html" LOCATEDB="/tmp/mirrors.db" LIMIT=1000 MAX_CONCURRENT=5 @@ -13,118 +17,147 @@ shopt -s extglob # Output an error in processing. die() { - echo "

Error: $1


" - exit 1 -} - -# A content type is required for CGI scripts. -echo -ne "Content-type: text/html\r\n\r\n" - -# Include the header in the output. -# Note: The header cannot include PHP scripting. -cat "$HEADER" - -# Limit the number of concurrent searches to avoid DoS. -if (( $(lsof -t "$LOCATEDB" | wc -l) > MAX_CONCURRENT - 1 )); then - die "Too many concurrent searches - please try your search again in a few moments." -else - exec 9<"$LOCATEDB" && flock -s -E 10 -w 2 9 || die "Too many concurrent searches - please try your search again in a few moments." -fi - -while read -r -d '&'; do - # If the read returned an empty string, skip. - [[ -z "$REPLY" ]] && continue - - # Extract the key and value to temporary variables. - KEY="${REPLY%%=*}" - VALUE="${REPLY##*=}" - - # Check the key is valid as a variable name. - [[ ! "$KEY" =~ ^[[:alpha:]]+[[:digit:]_]*[[:alnum:]_]*$ ]] && die "Invalid key - please try your search again." - - # Remove spaces from beginning and end of value. - : "${VALUE/#+(+)}" - : "${_/%+(+)}" - - # Squash multiple spaces in value and add *s. - : "${_//+(+)/+}" - - # Convert values from %-encoded form. - : "${_//%/\\x}" - - # Define the variable from the key name. - declare $KEY="$(echo -e "${_//+/ }")" -done <<<"${QUERY_STRING,,}&" - -# Take a copy of q before it's modified, for the heading. -Q_COPY="${q:-(empty)}" - -# Adjust 'q' for the locate command by wrapping search elements in *s. -: "*${q// /* *}*" -q="${_//\/*/*}" - -# HTML boilerplate. -cat <
- Showing search results for: $Q_COPY

- Searches may contain multiple terms, include (basic) globs, and descend down from the current directory. + Error: $1$([[ "${2,,}" != "false" ]] && printf "
\n Please click here to retry your search." "${REQUEST_SCHEME:-https}://${SERVER_NAME:-slackware.uk}/search?$QUERY_STRING")
- + + +EOF + exit 1 +} + +# Initial headers. +printf "%s: %s\\n\\n" "Content-type" "text/html" +printf "%s: %s\\n\\n" "Cache-Control" "no-cache, no-store, must-revalidate" +printf "%s: %s\\n\\n" "Pragma" "no-cache" +printf "%s: %s\\n\\n" "Expires" "1" + +# Extract cookies. +while read -r -d " " RAW; do + KEY="${RAW%%=*}" + VALUE="${RAW#*=}" + declare -A COOKIES+=( ["${KEY,,}"]="${VALUE,,}" ) +done <<<"$HTTP_COOKIE " # The space at the end is required. + +# Include the themed header. +if [[ "${COOKIES['theme']}" == "dark" ]]; then + cat "$HEADER_DARK" +else + cat "$HEADER_LIGHT" +fi + +# Limit the number of concurrent searches to avoid DoS. +if (( $(lsof -t "$LOCATEDB" | wc -l) > (MAX_CONCURRENT - 1) )); then + die "too many concurrent searches!" +else + exec 9<"$LOCATEDB" && flock -s -E 10 -w 2 9 || die "too many concurrent searches!" + + 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 "invalid query - don't try to be clever :)" "false" + + # 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 "X_$KEY"="$(printf "%b" "${_//+/ }")" + done <<<"${QUERY_STRING,,}&" # The & at the end is required. + + # Take a copy of q before it's modified, for the heading. + Q_COPY="${X_q:-(empty)}" + + # Adjust 'X_q' for the locate command by wrapping search elements in *s. + : "*${X_q// /* *}*" + X_q="${_//\/*/*}" + + # HTML boilerplate. + cat < +
+ + + +
+ Search Results

+ Search query: $Q_COPY
+ Searches may contain multiple terms, include (basic) globs,
+ and descend down from the current directory. +
+ + - - + + -
+ +
- - @@ -132,5 +165,10 @@ cat < EOF -# Include footer. -cat "$FOOTER" + # Include footer. + if [[ "${COOKIES['theme']}" == "dark" ]]; then + cat "$FOOTER_DARK" + else + cat "$FOOTER_LIGHT" + fi +fi
+
EOF -I=1 -COUNT=0 -while read -r; do - # Only show 1000 items to prevent long load times. - (( I == LIMIT + 1 )) && break + I=1 + COUNT=0 + while read -r ITEM; do + # Only show 1000 items to prevent long load times. + (( I == LIMIT + 1 )) && break - # Remove paths we don't want the user to see. - [[ "${REPLY/$STORAGE_PREFIX}" =~ ^/\.sandbox.* ]] && continue - [[ "${REPLY/$STORAGE_PREFIX}" =~ ^/\.lftp.* ]] && continue - [[ "${REPLY/$STORAGE_PREFIX}" =~ ^/dead\.letter ]] && continue - [[ "${REPLY/$STORAGE_PREFIX}" =~ .*\.rsync-tmp.* ]] && continue + # 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. - echo " • ${REPLY/$STORAGE_PREFIX}
" + # List the item. + printf " • %s
\\n" "${ITEM/$STORAGE_PREFIX}" "${ITEM/$STORAGE_PREFIX}" "${ITEM/$STORAGE_PREFIX}" - (( I++ )) - (( COUNT++ )) -done < <(locate -A -d "$LOCATEDB" -i -l "$(( LIMIT * 2 ))" "$STORAGE_PREFIX/${p##/}" $q | sort) + (( I++ )) + (( COUNT++ )) + done < <(locate -A -d "$LOCATEDB" -i -l "$(( LIMIT * 2 ))" "$STORAGE_PREFIX/${X_p##/}" $X_q | sort) -# If there's no results, tell the user. -if (( COUNT == 0 )); then - echo " No results - try to widen your search." -elif (( COUNT == LIMIT )); then - echo " Maximum $LIMIT items shown - try to refine your search." -else - echo " $COUNT items found." -fi + # Tell the user about the results. + if (( COUNT == 0 )); then + printf " %s" "No results - try to widen your search." + elif (( COUNT == LIMIT )); then + printf " %s" "Maximum $LIMIT items shown - try to refine your search." + else + printf " %s" "$COUNT items found." + fi # HTML boilerplate. -cat <