Skip to content

Instantly share code, notes, and snippets.

@clausecker
Last active April 8, 2021 22:19
Show Gist options
  • Save clausecker/c1e44f7ace75763eef4afdaf03b6ec22 to your computer and use it in GitHub Desktop.
Save clausecker/c1e44f7ace75763eef4afdaf03b6ec22 to your computer and use it in GitHub Desktop.
locate(1) as a CGI script
#!/bin/sh
PATH="$PATH:/usr/local/bin"
export LC_CTYPE=C
export LC_COLLATE=C
# decode URL encoded $1 and print result to stdout
urldecode() {
gawk "BEGIN { print \"$(echo "$1" | sed -e 's/"/\\"/' -e 's/+/ /g' -e 's/%/\\x/g')\" }" </dev/null
}
# apply shell scaping to $1 and print it to stdout with a newline
# do not escape underscores (for reasons)
shellescape() {
echo "$1" | sed -e 's/[^a-zA-Z0-9,._+@%/-]/\\&/g'
}
# generates variable assignments from urlencoded $* (already splitted at &)
makeassign() {
IFS=\&
for key in $1
do
keyval="$(urldecode "$key")"
printf "key_%s=" "${keyval%%=*}"
shellescape "${keyval#*=}"
done
}
# apply HTML escaping to stdin
htmlescape() {
echo "$1" | sed -e 's/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g' -e 's/"/\&quot;/g'
}
# present the results of locate(1) in a nice way
present() {
# limit number of results?
if [ "$key_l" ]
then
# apply HTML escapes, add links, add ... if too many lines
sed -e 's/&/\&amp;/g
s/</\&lt;/g
s/>/\&gt;/g
s/"/\&quot;/g
s,^.*$,<a href="&">&</a><br />,
$s,<br />,,
'$((key_l+1))' {
s/^.*$/.../
q
}'
else
# apply HTML escapes, add links
sed -e 's/&/\&amp;/g
s/</\&lt;/g
s/>/\&gt;/g
s/"/\&quot;/g
s,^.*$,<a href="&">&</a><br />,
$s,<br />,,'
fi
}
# generate key_... variables from QUERY_STRING
eval "$(makeassign "$QUERY_STRING")"
# normalise number of results
# all is intentionally undocumented
if [ "$key_l" = 'all' ]
then
key_l=
else
[ "$key_l" -gt 0 ] 2>/dev/null || key_l=1000
fi
echo Content-Type: text/html
echo
cat <<.
<!DOCTYPE html>
<html lang="de">
<head>
<title>Location Service</title>
<meta charset="UTF-8" />
<meta name="author" content="Robert Clausecker &lt;fuz@fuz.su&gt;" />
<style>
.results {
font-family:monospace;
}
.results a {
text-decoration:none;
}
</style>
</head>
<body>
<h1>Location Service</h1>
<p>Use <a href="http://www.freebsd.org/cgi/man.cgi?query=locate">locate(1)</a> to locate files.<br />
Globs can be used.</p>
<form action="locate.sh" method="get" accept-charset="UTF-8">
<p><input name="q" type="text" size="80" value="$(htmlescape "$key_q")" />&nbsp;\
<input type="submit" value="locate" /><br />
<input name="l" type="number" value="$key_l" size="10" /> show that many results<br />
<input name="i" type="checkbox" value="yes" $(echo "${key_i:+checked}") /> ignore case</p>
</form>
.
# where we asked to search for anything?
if [ "$key_q" ]
then
printf '<hr />\n<p class="results">'
[ "$key_i" ] && key_i=-i
# need to redirect stderr to prevent "locate: [show only ### lines]" message
[ "$key_q" ] && locate $key_i -- "$key_q" | present
printf '</p>'
fi
cat <<.
</body>
</html>
.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment