#!/bin/sh -e # # # DASHT-SERVER-HTTP 1 2020-05-16 2.4.0 # # ## NAME # # dasht-server-http - simple search engine that powers dasht-server(1) # # ## SYNOPSIS # # `dasht-server-http` # # ### Examples # # printf 'GET / HTTP/1.1\r\n' | `dasht-server-http` # Shows topics (A-Z) from each installed [Dash] docset. # # printf 'GET /?docsets=*DOCSETS* HTTP/1.1\r\n' | `dasht-server-http` # Shows topics (A-Z) from installed [Dash] docsets matching *DOCSETS*. # # printf 'GET /?query=*PATTERN* HTTP/1.1\r\n' | `dasht-server-http` # Searches for *PATTERN* in all installed [Dash] docsets. # # printf 'GET /?query=*PATTERN*&docsets=*DOCSETS* HTTP/1.1\r\n' | `dasht-server-http` # Searches for *PATTERN* in installed [Dash] docsets matching *DOCSETS*. # # ## DESCRIPTION # # Reads a single HTTP request from stdin and writes a HTTP response to stdout. # Any `query=`*PATTERN* and `docsets=`*DOCSETS* parameters in the request URL # are passed to dasht-query-html(1) as its *PATTERN* and *DOCSETS* arguments. # # ## ENVIRONMENT # # `DASHT_DOCSETS_DIR` # Defines the filesystem location where your [Dash] docsets are installed. # If undefined, its value is assumed to be `$XDG_DATA_HOME/dasht/docsets/` # or, if `XDG_DATA_HOME` is undefined, `$HOME/.local/share/dasht/docsets/`. # # ## SEE ALSO # # dasht-query-html(1), dasht-server(1), dasht-docsets(1), dasht(1), [Dash] # # [Dash]: https://kapeli.com/dash # # ## AUTHOR # # Written in 2016 by Suraj N. Kurapati # Distributed under the terms of the ISC license (refer to README file). # Escapes XML "predefined entities" in given arguments. # See http://www.w3.org/TR/REC-xml/#sec-predefined-ent entities() { echo "$*" | sed -e 's/&/\&/g' \ -e 's/"/\"/g' \ -e "s/'/\'/g" \ -e 's//\>/g' } # Converts the given 2-xdigit string into a byte value. # See http://mywiki.wooledge.org/BashFAQ/071 hex2byte() { dec=$(( 0x$1 )) oct=$(printf '%03o' "$dec") printf "\\$oct" } # parse URL from request: only GET is supported url=$(awk ' /^GET [[:print:]]+ HTTP\/1.+\r$/ { print $2 } /^\r$/ { exit } # reached end of HTTP request ') # serve translated local file:// URLs over HTTP # (skip the / homepage and /? form submissions) if ! test "$url" = / -o -z "${url##/\?*}"; then file=${url%#*} # strip URI fragment, if any if test -f "$file"; then printf 'HTTP/1.0 200 OK\r\n' printf 'Content-Type: %s\r\n' "$(file -b --mime "$file" 2>&1)" printf '\r\n' cat "$file" 2>&1 || : else printf 'HTTP/1.0 400 Bad Request\r\n' printf '\r\n' fi exit fi # parse URL query parameters as shell variables eval "$( # split URL on query parameter delimiters (?&) IFS='?&' set -- $url shift # protocol, hostname, port number, path # convert segments into safely eval()able assignments for segment; do # split param=value param=${segment%%=*} value=${segment#*=} # only accept known parameters to prevent injection case "$param" in (query|docsets) # decode URL-encoded characters in parameter value value=$(echo "$value" | tr '+' ' ' | # + is space sed 's/%\([[:xdigit:]]\{2\}\)/$(hex2byte \1)/g') if test -n "$value"; then echo "$param=\"\$$param\${$param:+ }$value\"" echo "${param}_html=\$(entities \"\$$param\")" fi ;;esac done )" # emit response header printf 'HTTP/1.0 200 OK\r\n' printf 'Content-Type: text/html\r\n' printf '\r\n' # emit response body docsets_menu=$( { dasht-docsets # all installed docsets dasht-docsets $docsets # the current selection } | sort | uniq -c | awk '{ $1 = $1 > 1; print }' ) set -- $(echo "$docsets_menu" | awk ' BEGIN { matched = ignored = 0 } $1 { matched++ } !$1 { ignored++ } END { print matched, ignored, NR } ') cat <
dasht $query_html $docsets_html




HEADER if test $1 -eq 0; then # notify user when no docsets are installed so they can go install them echo "

${docsets_html} docsets not installed so $query_html not searched

" elif results_html=$(dasht-query-html "$query" $docsets); then # translate local file:// URLs into HTTP ones so that we can serve them echo "$results_html" | sed 's,file://,,' else # notify user when no results are found so they can refine their search echo "

$query_html not found in $1 docsets matching ${docsets_html:-.*}

" fi cat <