]> git.plutz.net Git - cgilite/blobdiff - cgilite.sh
debug function
[cgilite] / cgilite.sh
index 6a4a64881faa4bc2836061399974e733bcdba010..b2467c335ed55a298651e485ff84143b7dfb23ea 100755 (executable)
@@ -1,22 +1,21 @@
 #!/bin/sh
 
-# Copyright 2017 - 2021 Paul Hänsch
-#
 # This is CGIlite.
 # A collection of posix shell functions for writing CGI scripts.
+
+# Copyright 2017 - 2023 Paul Hänsch
 # 
-# 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.
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
 # 
-# You should have received a copy of the GNU Affero General Public License
-# along with CGIlite.  If not, see <http://www.gnu.org/licenses/>. 
+# THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+# IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 [ -n "$include_cgilite" ] && return 0
 # guard set after webserver part
@@ -44,11 +43,13 @@ for cgilite_arg in "$@"; do case $cgilite_arg in
 esac; done
 unset cgilite_arg
 
-_EXEC="${EXEC:-${0%/*}}"
-_DATA="${DATA:-.}"
-_EXEC="${_EXEC%/}" _DATA="${_DATA%/}" _BASE="${BASE%/}"
+_EXEC="${_EXEC:-${0%/*}}"
+_DATA="${_DATA:-.}"
+_EXEC="${_EXEC%/}" _DATA="${_DATA%/}" _BASE="${_BASE%/}"
+
+export _EXEC _DATA _BASE
 
-# Carriare Return and Line Break characters for convenience
+# Carriage Return and Line Break characters for convenience
 CR="\r"
 BR='
 '
@@ -83,14 +84,21 @@ HEX_DECODE(){
   # will be copied to the output literally
 
   while [ "$in" ]; do
+    [ "$pfx" ] || case $in in
+      [0-9a-fA-F][0-9a-fA-F]*):;;
+      ?*) out="${out}${in%%"${in#?}"}"
+          in="${in#?}"; continue;;
+    esac
+
     case $in in
-      "$pfx"[0-9a-fA-F][0-9a-fA-F]*) in="${in#${pfx}}";;
+      "$pfx"[0-9a-fA-F][0-9a-fA-F]*) in="${in#"${pfx}"}";;
       \\*) in="${in#?}"; out="${out}\\\\"; continue;;
        %*) in="${in#?}"; out="${out}%%";  continue;;
-        *) out="${out}${in%"${in#?}"}"; in="${in#?}"; continue;;
+        *) att="${in%%"${pfx}"*}"; att="${att%%%*}"; att="${att%%\\*}"
+           out="${out}${att}"; in="${in#"${att}"}"; continue;;
     esac;
 
-    # Hex escaes for printf (e.g. \x41) are not portable 
+    # Hex escapes for printf (e.g. \x41) are not portable 
     # The portable way for Hex output is transforming Hex to Octal
     # (e.g. \x41 = \101)
     case $in in
@@ -141,6 +149,8 @@ if [ -z "$REQUEST_METHOD" ]; then
 
   (sleep $cgilite_timeout && kill $$) & cgilite_watchdog=$!
   while read REQUEST_METHOD REQUEST_URI SERVER_PROTOCOL; do
+    unset PATH_INFO QUERY_STRING cgilite_headers CONTENT_LENGTH CONTENT_TYPE
+
     [ "${SERVER_PROTOCOL#HTTP/1.[01]${CR}}" ] && break
     kill $cgilite_watchdog
 
@@ -149,7 +159,7 @@ if [ -z "$REQUEST_METHOD" ]; then
     [ "${REQUEST_URI}" = "${REQUEST_URI#*\?}" ] \
     && QUERY_STRING='' \
     || QUERY_STRING="${REQUEST_URI#*\?}"
-    cgilite_headers=''; while read -r hl; do
+    while read -r hl; do
       hl="${hl%${CR}}"; [ "$hl" ] || break
       case $hl in
         'Content-Length: '*) CONTENT_LENGTH="${hl#*: }";;
@@ -159,7 +169,7 @@ if [ -z "$REQUEST_METHOD" ]; then
     done
 
     export REMOTE_ADDR SERVER_NAME SERVER_PORT REQUEST_METHOD REQUEST_URI SERVER_PROTOCOL \
-           PATH_INFO QUERY_STRING CONTENT_TYPE CONTENT_LENGTH
+           PATH_INFO QUERY_STRING CONTENT_TYPE CONTENT_LENGTH cgilite_headers
 
     # Try to serve multiple requests, provided that script serves a
     # Content-Length header.
@@ -195,6 +205,8 @@ if [ "${REQUEST_METHOD}" = POST -a "${CONTENT_LENGTH:-0}" -gt 0 -a \
   cgilite_post="$(head -c "$CONTENT_LENGTH")"
 fi
 
+PATH_INFO="$(PATH "/${PATH_INFO#${_BASE}}")"
+
 debug(){ [ $# -gt 0 ] && printf '%s\n' "$@" >&2 || tee -a /dev/stderr; }
 [ "${DEBUG+x}" ] && env >&2
 
@@ -257,7 +269,7 @@ HEADER(){
     str="${str#*${BR}${1}: }"
     printf %s "${str%%${BR}*}"
   else
-    local var="HTTP_$(printf %s "$1" |tr a-z- A-Z-)"
+    local var="HTTP_$(printf %s "$1" |tr a-z- A-Z_)"
     eval "[ \"\$$var\" ] && printf %s \"\$$var\" || return 1"
     # eval "printf %s \"\$HTTP_$(printf %s "${1}" |tr a-z A-Z |tr -c A-Z _)\""
   fi
@@ -277,21 +289,18 @@ HTML(){
   # Also escape [, ], and \n for use in html-sh
   local str out
   [ $# -eq 0 ] && str="$(cat)" || str="$*"
-  while [ "$str" ]; do
-    case $str in
-      \&*) out="${out}&amp;";;
-      \<*) out="${out}&lt;";;
-      \>*) out="${out}&gt;";;
-      \"*) out="${out}&quot;";;
-      \'*) out="${out}&#x27;";;
-      \[*) out="${out}&#x5B;";;
-      \]*) out="${out}&#x5D;";;
-      "${CR}"*) out="${out}&#x0D;";;
-      "${BR}"*) out="${out}&#x0A;";;
-      *) out="${out}${str%"${str#?}"}";;
-    esac
-    str="${str#?}"
-  done
+  while [ "$str" ]; do case $str in
+    \&*) out="${out}&amp;";       str="${str#?}";;
+    \<*) out="${out}&lt;";        str="${str#?}";;
+    \>*) out="${out}&gt;";        str="${str#?}";;
+    \"*) out="${out}&quot;";      str="${str#?}";;
+    \'*) out="${out}&#x27;";      str="${str#?}";;
+    \[*) out="${out}&#x5B;";      str="${str#?}";;
+    \]*) out="${out}&#x5D;";      str="${str#?}";;
+    "${CR}"*) out="${out}&#x0D;"; str="${str#?}";;
+    "${BR}"*) out="${out}&#x0A;"; str="${str#?}";;
+    *) out="${out}${str%%[]&<>\"\'${CR}${BR}[]*}"; str="${str#"${str%%[]&<>\"\'${CR}${BR}[]*}"}";;
+  esac; done
   printf %s "$out"
 }
 
@@ -299,24 +308,22 @@ URL(){
   # Escape pathes, so they can be used in link tags and HTTP Headers
   local str out
   [ $# -eq 0 ] && str="$(cat)" || str="$*"
-  while [ "$str" ]; do
-    case $str in
-      \&*) out="${out}%26";;
-      \"*) out="${out}%22";;
-      \'*) out="${out}%27";;
-      \?*) out="${out}%3F";;
-      \#*) out="${out}%23";;
-      \[*) out="${out}%5B";;
-      \]*) out="${out}%5D";;
-      \ *) out="${out}%20";;
-      "        "*) out="${out}%09";;
-      "${CR}"*) out="${out}%0D";;
-      "${BR}"*) out="${out}%0A";;
-      %*) out="${out}%25";;
-      *) out="${out}${str%"${str#?}"}";;
-    esac
-    str="${str#?}"
-  done
+  while [ "$str" ]; do case $str in
+    \&*) out="${out}%26"; str="${str#?}";;
+    \"*) out="${out}%22"; str="${str#?}";;
+    \'*) out="${out}%27"; str="${str#?}";;
+    \`*) out="${out}%60"; str="${str#?}";;
+    \?*) out="${out}%3F"; str="${str#?}";;
+    \#*) out="${out}%23"; str="${str#?}";;
+    \[*) out="${out}%5B"; str="${str#?}";;
+    \]*) out="${out}%5D"; str="${str#?}";;
+    \ *) out="${out}%20"; str="${str#?}";;
+    "  "*) out="${out}%09"; str="${str#?}";;
+    "${CR}"*) out="${out}%0D"; str="${str#?}";;
+    "${BR}"*) out="${out}%0A"; str="${str#?}";;
+    %*) out="${out}%25"; str="${str#?}";;
+    *) out="${out}${str%%[]&\"\'\?#    ${CR}${BR}%[]*}"; str="${str#"${str%%[]&\"\'\?#         ${CR}${BR}%[]*}"}";;
+  esac; done
   printf %s "$out"
 }