X-Git-Url: http://git.plutz.net/?p=cgilite;a=blobdiff_plain;f=cgilite.sh;h=4c6de8ca6b784a5a361fb5cd8d70208c1a4d701d;hp=13cdb3cdc347f35ffd507a2d4fcd9c1dc6f5a2e0;hb=7335b7357a3be377ba5ae85bddc603948a4d3183;hpb=6940bf78a6d2dd6080f8d7f720eb66c17d1a11db diff --git a/cgilite.sh b/cgilite.sh index 13cdb3c..4c6de8c 100755 --- a/cgilite.sh +++ b/cgilite.sh @@ -22,8 +22,9 @@ # set -o posix # ksh, not portable setopt -o OCTAL_ZEROES 2>&- -BR="$(printf '\n')" -CR="$(printf '\r')" +CR=" " +BR=' +' cgilite_timeout=2 HEADER(){ @@ -31,23 +32,24 @@ HEADER(){ # referencing HTTP_* environment variables. if [ -n "${cgilite_headers+x}" ]; then printf %s "$cgilite_headers" \ - | sed -rn 's;^'"${1}"': ([^\r]+)\r?$;\1;i; tX; d; :X;p;q;' + | sed -En 's;^'"${1}"': ([^\r]+)\r?$;\1;i; tX; d; :X;p;q;' else eval "printf %s \"\$HTTP_$(printf %s "${1}" |tr a-z A-Z |tr -c A-Z _)\"" fi } +HEX_DECODE=' + s;\\;\\\\;g; :HEXDECODE_X; s;%([^0-9A-F]);\\045\1;g; tHEXDECODE_X; + # 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; +' + HEX_DECODE(){ - printf "$(printf %s "$1" \ - | sed -r ' - s;\\;\\\\;g; :x; s;%([^0-9A-F]);\\045\1;g; tx; - # 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; - ')" + printf -- "$(printf %s "$1" |sed -E "$HEX_DECODE")" } if [ -z "$REQUEST_METHOD" ]; then @@ -69,7 +71,7 @@ if [ -z "$REQUEST_METHOD" ]; then kill $cgilite_watchdog PATH_INFO="$(HEX_DECODE "${REQUEST_URI%\?*}")" QUERY_STRING="${REQUEST_URI#*\?}" - cgilite_headers="$(sed -u '/^\r\?$/q')" + cgilite_headers="$(while read -r hl; do [ "${hl%${CR}}" ] && printf '%s\n' "$hl" || break; done )" HTTP_CONTENT_LENGTH="$(HEADER Content-Length |grep -xE '[0-9]+')" @@ -85,12 +87,12 @@ if [ -z "$REQUEST_METHOD" ]; then . "$0" | while read -r l; do case $l in Status:*) cgilite_status="${l#Status: }";; Content-Length:*) cgilite_cl="${l}";; - $CR) printf '%s %s\r\n%s\n%s\n\r\n' \ + $CR) printf '%s %s\r\n%s%s\n\r\n' \ 'HTTP/1.1' "${cgilite_status%${CR}}" \ - "$cgilite_response" "${cgilite_cl}" - cat + "${cgilite_response}${cgilite_response:+${BR}}" "${cgilite_cl}" + cat || kill $$ [ "${cgilite_cl#Connection}" = "${cgilite_cl}" ]; exit;; - *) cgilite_response="$cgilite_response${BR}$l";; + *) cgilite_response="${cgilite_response:+${cgilite_response}${BR}}${l}";; esac; done || exit 0; (sleep $cgilite_timeout && kill $$) & cgilite_watchdog=$! done @@ -103,41 +105,46 @@ fi [ -n "${DEBUG+x}" ] && env cgilite_count(){ - case $1 in - GET) printf %s "&${QUERY_STRING}";; - POST) printf %s "&${cgilite_post}";; - REF) printf %s "&${HTTP_REFERER#*\?}";; - esac \ - | grep -Eo '&'"$2"'=[^&]*' \ + printf %s "&$1" \ + | grep -oE '&'"$2"'=[^&]*' \ | wc -l } cgilite_value(){ - HEX_DECODE "$( - case $1 in - GET) printf %s "&${QUERY_STRING}";; - POST) printf %s "&${cgilite_post}";; - REF) printf %s "&${HTTP_REFERER#*\?}";; - esac \ - | grep -Eo '&'"$2"'=[^&]*' \ - | sed -rn "${3:-1}"'{s;^[^=]+=;;; s;\+; ;g; p;}' - )" + local str="&$1" name="$2" cnt="${3:-1}" + while [ $cnt -gt 0 ]; do + str=${str#*&${name}=} + cnt=$((cnt - 1)) + done + printf -- "$(printf %s "${str%%&*}" |sed -E 's;\+; ;g;'"$HEX_DECODE")" +} + +cgilite_keys(){ + local str="&$1" + while [ "${str#*&}" != "${str}" ]; do + str="${str#*&}" + printf '%s\n' "${str%%=*}" + done \ + | sort -u } -GET(){ cgilite_value GET $@; } -GET_COUNT(){ cgilite_count GET $1; } +GET(){ cgilite_value "${QUERY_STRING}" $@; } +GET_COUNT(){ cgilite_count "${QUERY_STRING}" $1; } +GET_KEYS(){ cgilite_keys "${QUERY_STRING}"; } -POST(){ cgilite_value POST $@; } -POST_COUNT(){ cgilite_count POST $1; } +POST(){ cgilite_value "${cgilite_post}" $@; } +POST_COUNT(){ cgilite_count "${cgilite_post}" $1; } +POST_KEYS(){ cgilite_keys "${cgilite_post}"; } -REF(){ cgilite_value REF $@; } -REF_COUNT(){ cgilite_count REF $1; } +REF(){ cgilite_value "${HTTP_REFERER#*\?}" $@; } +REF_COUNT(){ cgilite_count "${HTTP_REFERER#*\?}" $1; } +REF_KEYS(){ cgilite_keys "${HTTP_REFERER#*\?}"; } COOKIE(){ HEX_DECODE "$( HEADER Cookie \ | grep -oE '(^|; ?)'"$1"'=[^;]*' \ - | sed -rn "${2:-1}"'{s;^[^=]+=;;; s;\+; ;g; p;}' + | sed -En "${2:-1}"'{s;^[^=]+=;;; s;\+; ;g; p;}' )" } @@ -145,7 +152,7 @@ HTML(){ # HTML Entity Coding # Prints UTF-8 string as decimal Unicode Code Points # Useful for escaping user input for use in HTML text and attributes - printf %s "$*" \ + { [ $# -eq 0 ] && cat || printf %s "$*"; } \ | hexdump -ve '/1 "%03o\n"' \ | while read n; do case $n in @@ -158,7 +165,7 @@ HTML(){ 36?) printf '%s' ${n#36};; # 4 octet (21 bit) chain start esac done \ - | sed -r 's;.{7};&\n;g;' \ + | sed -E 's;.{7};&\n;g;' \ | while read n; do printf '&#%d;' $((0$n)) done @@ -168,24 +175,25 @@ URL(){ # Code every character in URL escape hex format # except alphanumeric ascii - printf %s "$*" \ + { [ $# -eq 0 ] && cat || printf %s "$*"; } \ | hexdump -v -e '/1 ",%02X"' \ - | tr , % + | sed 's;,;%;g; s;%2F;/;g;' } PATH(){ - printf %s "$1" \ - | sed -r 's;^.*$;/&/;; s;/+;/;g; + { [ $# -eq 0 ] && cat || printf %s "$*"; } \ + | sed -E 's;^.*$;/&/;; s;/+;/;g; :X; - s;^/../;/;; s;/./;/;g; + s;^/\.\./;/;; s;/\./;/;g; tX; - s;/[^/]+/../;/;; + s;/[^/]+/\.\./;/;; tX; s;^(/.*)/$;\1;' } SET_COOKIE(){ + local expire cookie case "$1" in ''|0|session) expire='';; [+-][0-9]*) expire="$(date -R -d @$(($(date +%s) + $1)))";; @@ -200,7 +208,7 @@ SET_COOKIE(){ } REDIRECT(){ - printf '%s: %s\r\n' + printf '%s: %s\r\n' \ Status "303 See Other" \ Content-Length 0 \ Location "$*"