From 3fdb8e7e2ed8fcf3129de33147d1dd3b4a204b21 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Thu, 21 Jun 2018 16:00:29 +0200 Subject: [PATCH] forking cgilite into separate project --- cgi.sh | 147 ----------------------------------------------- debug.sh | 39 ------------- files.sh | 73 ----------------------- forms.sh | 54 ----------------- htaccess.example | 3 - index.cgi | 62 -------------------- local.opts | 8 --- misc.sh | 54 ----------------- page.sh | 33 ----------- server.sh | 99 ------------------------------- static.sh | 67 --------------------- 11 files changed, 639 deletions(-) delete mode 100755 cgi.sh delete mode 100755 debug.sh delete mode 100755 files.sh delete mode 100755 forms.sh delete mode 100644 htaccess.example delete mode 100755 index.cgi delete mode 100644 local.opts delete mode 100755 misc.sh delete mode 100755 page.sh delete mode 100755 server.sh delete mode 100755 static.sh diff --git a/cgi.sh b/cgi.sh deleted file mode 100755 index f79d416..0000000 --- a/cgi.sh +++ /dev/null @@ -1,147 +0,0 @@ -#!/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 . - -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' -} diff --git a/debug.sh b/debug.sh deleted file mode 100755 index 259407b..0000000 --- a/debug.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/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 . - -# 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 -} diff --git a/files.sh b/files.sh deleted file mode 100755 index bf8b7b9..0000000 --- a/files.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/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 . - -# 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 . - -# 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 '' \ - "$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 '' \ - "$id" "$name" "$value" "$check" "$id" "$label" -} diff --git a/htaccess.example b/htaccess.example deleted file mode 100644 index 2c8b66e..0000000 --- a/htaccess.example +++ /dev/null @@ -1,3 +0,0 @@ -Options +ExecCGI -AddHandler cgi-script .cgi -DirectoryIndex index.cgi diff --git a/index.cgi b/index.cgi deleted file mode 100755 index 907041e..0000000 --- a/index.cgi +++ /dev/null @@ -1,62 +0,0 @@ -#!/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 . - -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 $@ diff --git a/local.opts b/local.opts deleted file mode 100644 index a473b58..0000000 --- a/local.opts +++ /dev/null @@ -1,8 +0,0 @@ -# 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 diff --git a/misc.sh b/misc.sh deleted file mode 100755 index 9639309..0000000 --- a/misc.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/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 . - -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" -} diff --git a/page.sh b/page.sh deleted file mode 100755 index def7280..0000000 --- a/page.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/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 . - -. "${_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" diff --git a/server.sh b/server.sh deleted file mode 100755 index c49c0d8..0000000 --- a/server.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/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 . - -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 diff --git a/static.sh b/static.sh deleted file mode 100755 index bf109ed..0000000 --- a/static.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/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 . - - -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 - -- 2.39.2