+++ /dev/null
-#!/bin/zsh
-
-# Copyright 2014 - 2016 Paul Hänsch
-#
-# This file is part of shcgi.
-#
-# shcgi is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# shcgi is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with shcgi. If not, see <http://www.gnu.org/licenses/>.
-
-unset _GET _POST _REF _COOKIE
-declare -A _GET
-declare -A _POST
-declare -A _REF
-declare -A _COOKIE
-
-[ -z "$HTTP_REFERER" ] && HTTP_REFERER="./"
-
-# parse HTTP GET string
-debug "== CGI DATA: GET =="
-printf '%s\n' "$QUERY_STRING" |tr '&' '\n' |while read query; do
- key="$(printf %s "$query" |sed -r 's:^([\.a-zA-Z0-9_-]+)=(.*)$:\1:')"
- val="$(printf %s "$query" |sed -r 's:^([\.a-zA-Z0-9_-]+)=(.*)$:\2:')"
- _GET[$key]="$(printf "$(printf %s "$val" |sed 's:+: :g;s:\\:\\\\:g;s:%:\\x:g')")"
- debug "_GET[$key] => $val"
-done
-
-if [ "$REQUEST_METHOD" = POST -a "${HTTP_CONTENT_LENGTH:=$CONTENT_LENGTH}" -gt 0 ]; then
- # parse HTTP POST string
- debug "== CGI DATA: POST =="
- head -c "$HTTP_CONTENT_LENGTH" \
- | sed -un 's;&;\n;g; p; q' \
- | while read query; do
- key="$(printf %s "$query" |sed -r 's:^([\.a-zA-Z0-9_-]+)=(.*)$:\1:')"
- val="$(printf %s "$query" |sed -r 's:^([\.a-zA-Z0-9_-]+)=(.*)$:\2:')"
- value="$(printf "$(printf %s "$val" |sed 's:+: :g;s:\\:\\\\:g;s:%:\\x:g;')")"
- n=''
- if [ -n "${_POST[$key$n]+x}" ]; then
- n=0
- while [ -n "${_POST[$key$n]+x}" ]; do n=$(($n + 1)); done
- fi
- _POST[$key$n]="$value"
- debug "_POST[$key$n] => $value"
- done
-fi
-
-cgi_refdata() { # Parse GET data from referer
- debug "== CGI DATA: REFERER =="
- printf '%s\n' "${HTTP_REFERER#*\?}" |tr '&' '\n' |while read query; do
- key="$(printf %s "$query" |sed -r 's:^([\.a-zA-Z0-9_-]+)=(.*)$:\1:')"
- val="$(printf %s "$query" |sed -r 's:^([\.a-zA-Z0-9_-]+)=(.*)$:\2:')"
- _REF[$key]="$(printf "$(printf %s "$val" |sed 's:+: :g;s:\\:\\\\:g;s:%:\\x:g')")"
- debug "_REF[$key] => $val"
- done
-}
-
-cgi_cookie() { # Parse GET data from referer
- debug "== CGI DATA: COOKIE =="
- printf '%s\n' "$HTTP_COOKIE" |tr ';' '\n' |while read query; do
- key="$(printf %s "$query" |sed -r 's:^ *([\.a-zA-Z0-9_-]+)=(.*)$:\1:')"
- val="$(printf %s "$query" |sed -r 's:^ *([\.a-zA-Z0-9_-]+)=(.*)$:\2:')"
- _COOKIE[$key]="$(printf "$(printf %s "$val" |sed 's:+: :g;s:\\:\\\\:g;s:%:\\x:g')")"
- debug "_COOKIE[$key] => $val"
- done
-}
-
-htmlsafe(){
- # escape HTML code from string
-
- printf %s "$*" \
- | sed 's;&;\&\;;g;
- s;<;\<\;;g;
- s;>;\>\;;g;
- s;";\"\;;g;
- s;/;\/\;;g;
- s;'\'';\'\;;g;'
-}
-
-urlsafe(){
- # Code every character in URL escape hex format
- # except alphanumeric ascii
-
- printf %s "$*" \
- | hexdump -v -e '/1 ",%02X"' \
- | tr , % \
- | sed 's;%30;0;g; s;%31;1;g; s;%32;2;g; s;%33;3;g; s;%34;4;g; s;%35;5;g;
- s;%36;6;g; s;%37;7;g; s;%38;8;g; s;%39;9;g;
- s;%41;A;g; s;%42;B;g; s;%43;C;g; s;%44;D;g; s;%45;E;g; s;%46;F;g;
- s;%47;G;g; s;%48;H;g; s;%49;I;g; s;%4A;J;g; s;%4B;K;g; s;%4C;L;g;
- s;%4D;M;g; s;%4E;N;g; s;%4F;O;g; s;%50;P;g; s;%51;Q;g; s;%52;R;g;
- s;%53;S;g; s;%54;T;g; s;%55;U;g; s;%56;V;g; s;%57;W;g; s;%58;X;g;
- s;%59;Y;g; s;%5A;Z;g;
- s;%61;a;g; s;%62;b;g; s;%63;c;g; s;%64;d;g; s;%65;e;g; s;%66;f;g;
- s;%67;g;g; s;%68;h;g; s;%69;i;g; s;%6A;j;g; s;%6B;k;g; s;%6C;l;g;
- s;%6D;m;g; s;%6E;n;g; s;%6F;o;g; s;%70;p;g; s;%71;q;g; s;%72;r;g;
- s;%73;s;g; s;%74;t;g; s;%75;u;g; s;%76;v;g; s;%77;w;g; s;%78;x;g;
- s;%79;y;g; s;%7A;z;g; s;%2D;-;g; s;%2E;.;g; s;%2F;/;g; s;%5F;_;g'
-}
-
-attribsafe(){
- # Code every character in HTML escape hex format
- # except alphanumerig ascii
-
- printf %s "$*" \
- | iconv -f utf-8 -t utf32le \
- | hexdump -v -e '/4 "&#x%02X;"' \
- | sed 's;0\;;0;g; s;1\;;1;g; s;2\;;2;g; s;3\;;3;g; s;4\;;4;g; s;5\;;5;g;
- s;6\;;6;g; s;7\;;7;g; s;8\;;8;g; s;9\;;9;g;
- s;A\;;A;g; s;B\;;B;g; s;C\;;C;g; s;D\;;D;g; s;E\;;E;g; s;F\;;F;g;
- s;G\;;G;g; s;H\;;H;g; s;I\;;I;g; s;J\;;J;g; s;K\;;K;g; s;L\;;L;g;
- s;M\;;M;g; s;N\;;N;g; s;O\;;O;g; s;P\;;P;g; s;Q\;;Q;g; s;R\;;R;g;
- s;S\;;S;g; s;T\;;T;g; s;U\;;U;g; s;V\;;V;g; s;W\;;W;g; s;X\;;X;g;
- s;Y\;;Y;g; s;Z\;;Z;g;
- s;a\;;a;g; s;b\;;b;g; s;c\;;c;g; s;d\;;d;g; s;e\;;e;g; s;f\;;f;g;
- s;g\;;g;g; s;h\;;h;g; s;i\;;i;g; s;j\;;j;g; s;k\;;k;g; s;l\;;l;g;
- s;m\;;m;g; s;n\;;n;g; s;o\;;o;g; s;p\;;p;g; s;q\;;q;g; s;r\;;r;g;
- s;s\;;s;g; s;t\;;t;g; s;u\;;u;g; s;v\;;v;g; s;w\;;w;g; s;x\;;x;g;
- s;y\;;y;g; s;z\;;z;g;'
-}
-
-redirect(){
- printf 'Status: 303 See Other\r\nLocation: %s\r\n\r\n' "$*"
- exit 0
-}
-
-set_cookie(){
- case "$1" in
- session|0) expire='';;
- ''|default) expire="$(LANG=C date -d "+ 1 week" +'%a, %d %b %Y %T %Z')";;
- *) expire="$(LANG=C date -d "$1" +'%a, %d %b %Y %T %Z' 2>&-)";;
- esac
- cookie="$2"
-
- printf 'Set-Cookie: %s' "$cookie"
- [ -n "$expire" ] && printf '; Expires=%s' "$expire"
- [ $# -ge 3 ] && shift 2 && printf '; %s' "$@"
- printf '\r\n'
-}
+++ /dev/null
-#!/bin/zsh
-
-# Copyright 2014, 2015 Paul Hänsch
-#
-# This file is part of shcgi.
-#
-# shcgi is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# shcgi is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with shcgi. If not, see <http://www.gnu.org/licenses/>.
-
-# put debug options in the local.opts file
-DBG_ENABLED=false
-DBG_FILE=/dev/stderr
-
-# basic functions
-debug() { #change to false to disable debugging
- if [ "$DBG_ENABLED" = true -a -n "$*" ]; then
- printf '%s\n' "$*" >>"$DBG_FILE"
- elif [ "$DBG_ENABLED" = true -a -z "$*" ]; then
- tee -a "$DBG_FILE"
- elif [ -z "$*" ]; then
- cat
- fi
-}
-
-die() {
- debug FATAL: "$*"
- printf '%s\n' "$*" >&2
- exit 1
-}
+++ /dev/null
-#!/bin/sh
-
-# Copyright 2018 Paul Hänsch
-#
-# This is a file format helper, part of CGIlite.
-#
-# CGIlite is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# CGIlite is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with CGIlite. If not, see <http://www.gnu.org/licenses/>.
-
-# ksh and zsh workaround
-case "${0##*/}" in
- zsh) setopt -o OCTAL_ZEROES 2>&- ;; # zsh, mostly ignored by other shells
- ksh) set -o posix ;; # ksh, will crash most other shells
-esac
-
-STORE(){
- # Store fields from a HTTP GET or POST string in a file
- # usage: STORE "${QUERY_STRING}"
- # or: STORE "$(head -n $HTTP_CONTENT_LENGTH)"
- # backslashes and newline characters will be escaped in field values,
- # the escape symbol is a backslash
- # hexadecimal character descriptions (%00 - %FF) will be expanded
- # the + character will be converted to [space]
- # one line in the output corresponds to exactly one field, so you can
- # use grep to filter which fields of a query should be stored
- printf "$(
- printf '%s' "$@" \
- | sed -r ':X; $bY; N; bX; :Y;
- s;\+; ;g; s;(\\|5[Cc]);\\\\\\\\;g; s;(\n|%0[Aa]);\\\\n;g; s;(^|&)([^=]+)=;\1\2:;g; s;&;\n;g;
- s;^\n+;;; s;$;\\n;; s;\n+;\n;g;
- # Hexadecimal { %00 - %FF } will be transformed to octal { \000 - \377 } for posix printf
- s;%[0123].;&\\0;g; s;%[4567].;&\\1;g; s;%[89AB].;&\\2;g; s;%[CDEF].;&\\3;g;
- s;%[048C][0-7]\\.;&0;g; s;%[048C][89A-F]\\.;&1;g; s;%[159D][0-7]\\.;&2;g; s;%[159D][89A-F]\\.;&3;g;
- s;%[26AE][0-7]\\.;&4;g; s;%[26AE][89A-F]\\.;&5;g; s;%[37BF][0-7]\\.;&6;g; s;%[37BF][89A-F]\\.;&7;g;
- s;%.[08](\\..);\10;g; s;%.[19](\\..);\11;g; s;%.[2A](\\..);\12;g; s;%.[3B](\\..);\13;g;
- s;%.[4C](\\..);\14;g; s;%.[5D](\\..);\15;g; s;%.[6E](\\..);\16;g; s;%.[7F](\\..);\17;g;
- '
- )"
-}
-
-LOAD(){
- # read a file written by STORE and assign all fields to variables
- # usage: eval "$(LOAD <file)"
- #
- # fields will be assigned to shell variables of the same name, but with the following constraints:
- # * small letters will be converted to capitals
- # * all non-alphanumeric characters will be converted to underscore (_)
- # * an underscore will be prepended
- # as a consequence variable names are guaranteed to match the regex /_[A-Z0-9_]+/
- #
- # field values may contain any character, proper escaping for safe use in eval is taken care of
- # Your shell may or may not purge certain binary characters from variable values during processing
-
- sed -r 'h; s;^[^:]+:;;
- s;'\'';'\''\\'\'\'';g;
- s;^.*$;'\''&'\'';;
- s;\\n;\n;g;
- x; s;^([^:]+):.*$;\1;
- y;abcdefghijklmnopqrstuvwxyz;ABCDEFGHIJKLMNOPQRSTUVWXYZ;
- s;[^A-Z0-9_];_;g; s;^.*$;_&=;;
- G; s;^([A-Z0-9_]+=)\n;\1;;
- '
-}
+++ /dev/null
-#!/bin/sh
-
-# Copyright 2018 Paul Hänsch
-#
-# This is the forms helper, part of CGIlite.
-#
-# CGIlite is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# CGIlite is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with CGIlite. If not, see <http://www.gnu.org/licenses/>.
-
-# ksh and zsh workaround
-# set -o posix # ksh, not portable
-setopt -o OCTAL_ZEROES 2>&-
-
-form_radio(){
- # Usage: form_radio Name Value Condition Label
- # if "Condition" is the same as "Value", the button will be checked
-
- name="$1"
- value="$2"
- cond="$3"
- label="$4"
- id="rd_${name}_${value}"
-
- [ "$value" = "$cond" ] && check='checked="checked"' || check=''
-
- printf '<input type="radio" id="%s" name="%s" value="%s" %s /><label for="%s">%s</label>' \
- "$id" "$name" "$value" "$check" "$id" "$label"
-}
-
-form_check(){
- # Usage: form_check Name Value Condition Label
- # if "Condition" is the same as "Value", the Checkbox will be checked
-
- name="$1"
- value="$2"
- cond="$3"
- label="$4"
- id="rd_${name}_${value}"
-
- [ "$value" = "$cond" ] && check='checked="checked"' || check=''
-
- printf '<input type="checkbox" id="%s" name="%s" value="%s" %s /><label for="%s">%s</label>' \
- "$id" "$name" "$value" "$check" "$id" "$label"
-}
+++ /dev/null
-Options +ExecCGI
-AddHandler cgi-script .cgi
-DirectoryIndex index.cgi
+++ /dev/null
-#!/bin/zsh
-
-# Copyright 2014 - 2016 Paul Hänsch
-#
-# This file is part of shcgi.
-#
-# shcgi is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# shcgi is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with shcgi. If not, see <http://www.gnu.org/licenses/>.
-
-export LC_ALL=C LANG=C
-
-# this program is supposed to be symlinked into a http root directory
-# we will use the http root as object storage (data directory) and call sub
-# programs from the directory in which the real executable resides
-# therefore we need to identify the code and data directories _EXEC and _DATA
-call="$0"
-real="$(readlink -f $call)"
-export _DATA="$(dirname "$call")" #storage directory
-export _EXEC="${real%/shcgi/index.cgi}" #execution directory
-
-# put debug options in the local.opts file
-. "$_EXEC/shcgi/misc.sh"
-. "$_EXEC/shcgi/debug.sh"
-[ -r "$_DATA/local.opts" ] && . "$_DATA/local.opts"
-
-if [ "$1" = '--server' -o "$1" = '--inetd' -o "$1" = '--ncat' ]; then
- . "$_EXEC/shcgi/server.sh" $@
-else
- HTTP_format(){ cat }
-fi
-
-. "$_EXEC/shcgi/cgi.sh"
-
-[ -x "$_EXEC/globals.sh" ] && . "$_EXEC/globals.sh"
-
- PAGE=$(validate "${PAGE:-${_GET[page]}}" '[a-zA-Z0-9_-]+' '')
-ACTION=$(validate "${ACTION:-${_GET[action]}}" '[a-zA-Z0-9_-]+' '')
-STATIC=$(invalidate "${STATIC:-${_GET[static]}}" '(^|.*/)\.\./.*' '')
-
-if [ -n "$STATIC" ] && [ -e "${_EXEC}/static/${STATIC}" ]; then
- . "$_EXEC/shcgi/static.sh" "$_EXEC/static/$STATIC"
-elif [ -n "$ACTION" ] && [ -x "${_EXEC}/actions/${ACTION}.sh" ]; then
- . "${_EXEC}/actions/${ACTION}.sh"
-elif [ -n "$PAGE" ] && [ -x "${_EXEC}/pages/${PAGE}.sh" ]; then
- . "$_EXEC/shcgi/page.sh"
-else
- printf 'Status: 404 Not Found\r\n'
- PAGE=error
- [ -x "${_EXEC}/pages/${PAGE}.sh" ] \
- && . "$_EXEC/shcgi/page.sh" \
- || printf '\r\n'
-fi |HTTP_format $@
+++ /dev/null
-# This file is meaningless in the exec directory
-# You can copy it to your data directory (usually
-# your HTTP root) to set per instance debug
-# options and the like
-# beware that the file is sourced as a shell script
-
-DBG_ENABLED=false
-DBG_FILE=/dev/stderr
+++ /dev/null
-#!/bin/zsh
-
-# Copyright 2014 - 2017 Paul Hänsch
-#
-# This file is part of shcgi.
-#
-# shcgi is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# shcgi is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with shcgi. If not, see <http://www.gnu.org/licenses/>.
-
-BR='
-'
-
-data_dirs(){
- # set up directories for object storage
-
- [ -d "$_DATA" -a -w "$_DATA" ] || die "storage directory must be writable"
- for each in "$@"; do
- [ ! -e "$_DATA/$each" ] && mkdir "$_DATA/$each"
- [ -d "$_DATA/$each" -a -w "$_DATA/$each" ] || die "storage \"$_DATA/$each\" must be a writable directory"
- done
-}
-
-validate(){
- # print value if value matches regex; otherwise print default
- value="$1"
- regex="$2"
- default="$3"
-
- printf %s "${value%%${BR}*}" |grep -xE "$regex" || printf %s "$default"
-}
-
-invalidate(){
- # print default if value matches regex; otherwise print value
- value="$1"
- regex="$2"
- default="$3"
-
- printf %s "${value%%${BR}*}" |grep -qxE "$regex" && printf %s "$default" || printf %s "${value%%${BR}*}"
-}
-
-declare -A item_name
-l10n(){
- [ -n "${item_name[$1]+x}" ] && printf %s "$item_name[$1]" || printf %s "$1"
-}
+++ /dev/null
-#!/bin/zsh
-
-# Copyright 2014 - 2016 Paul Hänsch
-#
-# This file is part of shcgi.
-#
-# shcgi is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# shcgi is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with shcgi. If not, see <http://www.gnu.org/licenses/>.
-
-. "${_EXEC}/shcgi/forms.sh"
-
-[ -z "$NAVIGATION" ] \
-&& NAVIGATION=($(printf %s\\n "${_EXEC}"/pages/*.sh |sed -r 's;^.*/([^/]*)\.sh$;\1;'))
-
-CSS="${CSS:-${_EXEC}/templates/${PAGE}.css.sh}"
-BODY="${BODY:-${_EXEC}/templates/${PAGE}.html.sh}"
-
-. "${_EXEC}/pages/${PAGE}.sh"
-
-# prevent browsers from caching generated pages
-printf "Cache-Control: no-cache, no-store, must-revalidate\r\nPragma: no-cache\r\nExpires: 0\r\n"
-printf "Content-Type: text/html;charset=utf-8\r\n\r\n"
-. "${_EXEC}/templates/frame.html.sh"
+++ /dev/null
-#!/bin/zsh
-
-# Copyright 2016 Paul Hänsch
-#
-# This file is part of shcgi.
-#
-# shcgi is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# shcgi is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with shcgi. If not, see <http://www.gnu.org/licenses/>.
-
-if [ "$1" = '--server' ]; then
- shift 1
- ncat -klc "$call --ncat" $@
- exit $?
-fi
-
-export REMOTE_ADDR="${NCAT_REMOTE_ADDR}"
-export SERVER_NAME="${NCAT_LOCAL_ADDR}"
-export SERVER_PORT="${NCAT_LOCAL_PORT}"
-
-eval $(
-sed -unr '
- w/dev/stderr
- /^(GET|HEAD|POST) ([^\?]*)\??(.+)? (HTTP\/[0-9]\.[0-9])\r?$/{
- h
- s;^(GET|HEAD|POST) ([^\?]*)\??(.+)? (HTTP\/[0-9]\.[0-9])\r?$;export REQUEST_METHOD='\''\1'\'';p
- g
- s;^(GET|HEAD|POST) ([^\?]*\??.*) (HTTP\/[0-9]\.[0-9])\r?$;\2;
- s;'\'';'\''\\'\'''\'';g
- s;^.*$;export REQUEST_URI='\''&'\'';p
- g
- s;^(GET|HEAD|POST) ([^\?]*)\??(.+)? (HTTP\/[0-9]\.[0-9])\r?$;\2;
- s;'\'';'\''\\'\'''\'';g
- s;^.*$;export PATH_INFO='\''&'\'';p
- g
- s;^(GET|HEAD|POST) ([^\?]*)\??(.+)? (HTTP\/[0-9]\.[0-9])\r?$;\3;
- s;'\'';'\''\\'\'''\'';g
- s;^.*$;export QUERY_STRING='\''&'\'';p
- g
- s;^(GET|HEAD|POST) ([^\?]*)\??(.+)? (HTTP\/[0-9]\.[0-9])\r?$;export SERVER_PROTOCOL='\''\4'\'';p
- g
- }
-
- /^[Pp][Rr][Oo][Xx][Yy]: /d
-
- /^[a-zA-Z_-]+: .*$/{
- h
- s;^[^:]+: (.*)\r$;\1;
- s;'\'';'\''\\'\'''\'';g
- s;^.*$;'\''&'\'';
- x
- s;: .*$;;
- y;abcdefghijklmnopqrstuvwxyz-;ABCDEFGHIJKLMNOPQRSTUVWXYZ_;
- s;^.+$;export HTTP_&=;
- G
- s;\n;;
- p
- }
- /^\r?$/q
-'
-)
-
-HTTP_format(){
- LC_ALL=C sed -urn '
- :A
- /^\r?$/!{H;n;bA}
-
- g
- s;^(\r?\n)*;;;
- s;([^\r])\n;\1\r\n;g;
- aConnection: close\r\n\r
- /^Status: *[1-5][0-9][0-9] .*/{s;^Status: *;HTTP/1.1 ;; bX}
- s;^(.+\n)?Location: .*$;HTTP/1.1 302 Found\r\n&;
- s;^(.+\n)?Content-Type: .*$;HTTP/1.1 200 OK\r\n&;
-
- :X
- p
- $q
- n
- bX
- '
-}
-
-
-if [ -z "$QUERY_STRING" ]; then
- PATH_INFO="$(printf "$(printf %s "$PATH_INFO" |sed 's:+: :g;s:\\:\\\\:g;s:%:\\x:g')")"
- PATH_INFO="$(invalidate "${PATH_INFO}" '(^|.*/)\.\./.*' '')"
- [ -f "${treeroot:-${_DATA}}/$PATH_INFO" ] && . "$_EXEC/shcgi/static.sh" "${treeroot:-${_DATA}}/$PATH_INFO"
- exit 0
-fi |HTTP_format
+++ /dev/null
-#!/bin/zsh
-
-# Copyright 2016 Paul Hänsch
-#
-# This file is part of shcgi.
-#
-# shcgi is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# shcgi is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with shcgi. If not, see <http://www.gnu.org/licenses/>.
-
-
-unset length date file suffix
-file="$1"
-date="$(stat -Lc %Y "$file")"
-
-# allow overriding magic file recognition
-# don't use this if `file` returns type correctly
-declare -A suffix
-suffix[css]="text/css"
-
-[ -n "$HTTP_IF_MODIFIED_SINCE" ] && cachedate="$(date -d "$HTTP_IF_MODIFIED_SINCE" +%s)"
-
-if printf '%s' "${HTTP_RANGE}" |grep -qE '^bytes=[0-9]+-[0-9]*\r?$'; then
- _range="${HTTP_RANGE#bytes=}"
- _bstart="${_range%-*}"
- _bend="${_range#*-}"
-fi
-
-if ! [ -f "$file" ] || [ -x "$file" ] || ! grep -qm1 '' "$file" ; then
- printf 'Status:403 Forbidden\r\n\r\n'
-elif [ "$date" = "$cachedate" ]; then
- printf 'Status:304 Not Modified\r\n'
- printf 'Last-Modified: %s\r\n\r\n' "$(date -Rd "@$date")"
-elif [ "$_bstart" -gt 0 ] ; then
- length="$(stat -Lc %s "$file")"
- magic="${suffix[${file##*.}]:-$(file -bi "$file")}"
-
- printf 'Status:206 Partial Content\r\n'
- printf 'Last-Modified: %s\r\n' "$(date -Rd "@$date")"
- printf 'Content-Type: %s\r\n' "${magic:-all/all}"
- printf 'Content-Range: bytes %i-%i/%i\r\n' $_bstart $(($length - 1)) $length |debug
- printf 'Content-Length: %i\r\n' $(($length - $_bstart))
- printf '\r\n'
-
- tail -c+"$(($_bstart + 1))" "$file"
-else
- length="$(stat -Lc %s "$file")"
- magic="${suffix[${file##*.}]:-$(file -bi "$file")}"
-
- printf 'Accept-Ranges: bytes\r\n'
- printf 'Last-Modified: %s\r\n' "$(date -Rd "@$date")"
- printf 'Content-Type: %s\r\n' "${magic:-all/all}"
- printf 'Content-Length: %i\r\n' "$length"
- printf '\r\n'
-
- cat "$file"
-fi
-