123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- #!/bin/bash
- set -o noglob
- _WWW='/www'
- _HTDOCS="${_WWW}/htdocs"
- _TMP="${_WWW}/tmp"
- _LOG="${_TMP}/post.log"
- _DEBUG=1
- logThis() {
- [[ $_DEBUG -gt 0 ]] || return 0
- [[ $_ERR -gt 0 ]] && _TYPE='E:' || _TYPE='I:'
- local _TIME=$(printf '%(%d.%m.%Y %H:%M:%S)T' -1)
- printf '%b\n' "$_TIME $_TYPE ${1} " >> $_LOG
- [[ $_DEBUG -gt 1 ]] && printf '%b\n' "[verbose] $_TYPE ${1}"
- return 0
- }
- wTf() {
- local _WTF="$(printf '%s -> ' '| trace: '${FUNCNAME[*]:1})"
- _OUT="$_OUT $_WTF"
- }
- urlDecode() {
- local encoded="${1//+/ }"
- printf '%b' "${encoded//%/\x}"
- }
- headerPrint() {
- case ${1} in
- 200) printf '%b' 'HTTP/1.1 200 OK\nAccess-Control-Allow-Origin: *\n\n';;
- 405) printf '%b' 'HTTP/1.1 405 Method Not Allowed\n\n';;
- 406) printf '%b' 'HTTP/1.1 406 Not Acceptable\n\n';;
- esac
- return 0
- }
- errorCheck() {
- _ERR=${1}
- [[ $_ERR -gt 0 ]] || return 0
- local _MSG=${2}
-
-
- [[ $_OUT ]] && _OUT="${_OUT%%$'\n'*}" || { _OUT=${_MSG:='unknown error occured'}; wTf; }
- [[ -e $_POST_TMP ]] && rm -f $_POST_TMP
- headerPrint '406'
- logThis "${_OUT}";
- exit $_ERR
- }
- postUrlenc() {
-
- _POST=$(urlDecode "$(< $_POST_TMP)")
- case "${_REQUEST_URI}" in
- \/cmd) postCmd ;;
- *) postHtml ;;
- esac
- }
- postCmd() {
- local _CMD=( ${_POST} )
- [[ ${#_CMD[@]} -lt 5 ]] || errorCheck '1' "'${_CMD[*]}': too many arguments"
- local _EXE="${_CMD[0]}"
- local _ARG="${_CMD[@]:1}"
-
- [[ ! "$_ARG" =~ (\.\.|^/| /) ]] || errorCheck '1' "'$_ARG': illegal path"
-
- lss() {
- _D='\t'
- while getopts 'la' _OPT; do
- case $_OPT in
- l) local _LNG="$_D%F$_D%s$_D%y$_D%U$_D%G$_D%a" ;;
- a) shopt -s dotglob
- esac
- done
- shift $((OPTIND-1))
- [[ -z "${@}" ]] && _PT="./*"
- [[ -d "${@}" ]] && _PT="/*"
-
- stat --printf "%n$_LNG\n" -- "${@%%/}"$_PT 2>/dev/null || _ERR=0
- return $_ERR
- }
- case "$_EXE" in
- ls|lss) _EXE="lss"; _ARG="${_ARG}" ;;
- cp) _ARG="${_ARG}" ;;
- rm) _ARG="${_ARG}" ;;
- mv) _ARG="${_ARG}" ;;
- mkdir) _ARG="${_ARG}" ;;
- log) _EXE="tail"; _ARG="${_ARG} ${_LOG}" ;;
- wget) _ARG="-q ${_ARG/ */} -O ${_ARG/* /}" ;;
- *) errorCheck '1' "'$_EXE': bad command" ;;
- esac
-
- set +o noglob
- _OUT=$($_EXE $_ARG 2>&1)
- _ERR=$?
-
- set -o noglob
- logThis "$_EXE $_ARG"
- errorCheck $_ERR
- }
- postHtml() {
-
- _OUT=$( (printf '%b' "${_POST}" > "${_HTDOCS}${_REQUEST_URI}") 2>&1)
- _ERR=$?
- errorCheck $_ERR
- }
- postOctet() {
-
- local IFS=','; read -d',' -r _DH < $_POST_TMP
- case "${_ENC}" in
- base64) postBase64Enc;;
- binary) postBinary ;;
- *) postGuessEnc ;;
- esac
- }
- postGuessEnc() {
- shopt -s nocasematch
- local _DTP="^.*\;([[:alnum:]].+)$"
-
- [[ "${_DH}" =~ ${_DTP} ]] && _ENC="${BASH_REMATCH[1]}"
- logThis "'$_ENC:' encoding is the best guess";
- shopt -u nocasematch
- case "$_ENC" in
- base64) postBase64Enc ;;
-
-
-
- *) _ERR=1; _OUT="'${_ENC:='unknown'}' encoding, unknown POST failed";;
- esac
- errorCheck $_ERR
- }
- postBase64Enc() {
- logThis "'${_ENC}:' decoding stream"
- _DL=${#_DH}
- [[ $_DL -lt 10 ]] && { _DL=23; _SKP=0; } || { let _DL+=1; _SKP=1; }
-
-
- _OUT=$( dd if=${_POST_TMP} bs=${_DL} skip=${_SKP} | base64 -d > "${_HTDOCS}${_REQUEST_URI}" 2>&1)
- _ERR=$?
- errorCheck $_ERR
- }
- postBinary() {
- logThis "'binary': decoding stream"
-
- _OUT=$( dd if="${_POST_TMP}" of="${_HTDOCS}${_REQUEST_URI}" 2>&1 )
- _ERR=$?
- errorCheck $_ERR
- }
- postMpart() {
- logThis "'multipart': decoding stream"
- local _BND=$(findPostOpt 'boundary')
-
-
- function cutFile() {
- gawk -v "want=$1" -v "bnd=$_BND" '
- BEGIN { RS="\r\n"; ORS="\r\n" }
- # reset based on boundaries
- $0 == "--"bnd"" { st=1; next; }
- $0 == "--"bnd"--" { st=0; next; }
- $0 == "--"bnd"--\r" { st=0; next; }
- # search for wanted file
- st == 1 && $0 ~ "^Content-Disposition:.* name=\""want"\"" { st=2; next; }
- st == 1 && $0 == "" { st=9; next; }
- # wait for newline, then start printing
- st == 2 && $0 == "" { st=3; next; }
- st == 3 { print $0 }
- ' 2>&1
- }
- cutFile 'userimage' < "${_POST_TMP}" > "${_HTDOCS}${_REQUEST_URI}"
- _ERR=$?
- errorCheck $_ERR
- }
- findPostOpt() {
- for i in "${CONTENT_TYPE[@]:1}"; do
- case "${i/=*}" in
- "$1") printf '%b' "${i/*=}" ;;
- esac
- done
- return 0
- }
- escapeStr() {
- printf "%q" "${*}"
- }
- cleanFname() {
- shopt -s extglob
- local _STR="${*}"
- echo -n "${_STR//[^[:alnum:]._\-\/\\]/_}"
- shopt -u extglob
- }
- read t z < /proc/uptime
- cd $_HTDOCS || errorCheck $? 'htdocs unavailable'
- [[ ${PWD} == ${_HTDOCS} ]] || errorCheck $? 'htdocs misconfigured'
- [[ $CONTENT_LENGTH -gt 0 ]] || errorCheck $? 'content length zero'
- _REQUEST_URI="${REQUEST_URI/%\///index.html}"
- _REQUEST_URI="$(urlDecode $_REQUEST_URI)"
- _PATH="${_REQUEST_URI%/*}"
- CONTENT_TYPE=( ${CONTENT_TYPE} )
- _CONTENT_TYPE="${CONTENT_TYPE[0]/;}"
- _ENC="${HTTP_CONTENT_ENCODING}"
- findPostOpt 'verbose' || { _DEBUG=2; logThis 'verbose mode is requested'; }
- _POST_TMP=$(mktemp -p $_TMP)
- cat > $_POST_TMP
- case "${_CONTENT_TYPE}" in
- application\/x-www-form-urlencoded) postUrlenc ;;
- application\/octet-stream) postOctet ;;
- multipart/form-data) postMpart ;;
- *) _ERR=1; _OUT='this is not a post' ;;
- esac
- [[ -e $_POST_TMP ]] && rm -f $_POST_TMP
- errorCheck $_ERR
- [[ -z $_OUT ]] || _OUT="${_OUT}\n"
- headerPrint '200'
- printf '%b' "${_OUT}"
- logThis 'OK 200'
- read d z < /proc/uptime
- logThis $((${d/./}-${t/./}))"/100s"
- exit 0
|