]> git.plutz.net Git - confetti/blob - multipart.sh
styling for iban assignment
[confetti] / multipart.sh
1 #!/bin/sh
2
3 [ "$include_multipart" ] && return 0
4 inlude_multipart="$0"
5
6 # Copyright 2022 - 2023 Paul Hänsch
7
8 # Permission to use, copy, modify, and/or distribute this software for any
9 # purpose with or without fee is hereby granted, provided that the above
10 # copyright notice and this permission notice appear in all copies.
11
12 # THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
15 # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
18 # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 if [ "${CONTENT_TYPE}" -a ! "${CONTENT_TYPE##multipart/form-data;*}" ]; then
21   multipart_boundary="${CONTENT_TYPE#*; boundary=}"
22   multipart_boundary="${multipart_boundary%%;*}"
23   multipart_boundary="${multipart_boundary%${CR}}"
24 fi
25 multipart_cachefile="/tmp/multipart.$$"
26
27 readbytes(){
28   # read n bytes, like `head -c` but do not consume input
29   local size="$1" block
30
31   for block in 65536 32768 16384 8192 4096 2048 1024 512 256 128 64 32 16 8 4 2 1; do
32     if [ $size -ge $block ]; then
33       dd status=none bs="$block" count="$((size / block))"
34       size="$((size % block))"
35     fi
36   done
37 }
38
39 multipart_cache() {
40   multipart_cachefile="${1:-${multipart_cachefile}}"  # global
41
42   if [ "${multipart_boundary}" ]; then
43     # readbytes "$(( CONTENT_LENGTH ))" >"${multipart_cachefile}"
44     head -c "$(( CONTENT_LENGTH ))" >"${multipart_cachefile}"
45   else
46     return 1
47   fi
48 }
49
50 multipart(){
51   local name="$1" count="${2:-1}"
52   local formdata state=begin
53
54   while IFS='' read -r formdata; do case "$formdata" in
55     "--${multipart_boundary}--${CR}")
56       [ $state = data ] && return 0 \
57                         || return 1
58       ;;
59     "--${multipart_boundary}${CR}")
60       [ $state = data ] && return 0 \
61                         || state=header
62       ;;
63     "Content-Disposition: form-data; name=\"${name}\""*"${CR}")
64       [ $state = header -a $count -eq 1 ] && state=dheader
65       [ $state = header -a $count -gt 1 ] && count=$((count - 1))
66       [ $state = data ] && printf "%s\n" "$formdata"
67       ;;
68     "${CR}")
69       if [ $state = dheader ]; then
70         # Do not use `sed -n` (or busybox sed will "convert" NULL to LF)
71         sed "/--${multipart_boundary}\(--\)\?${CR}/{x;q;}" \
72         | head -c-3
73         return 0;
74       fi
75       [ $state = header ] && state=junk
76       ;;
77   esac; done <"${multipart_cachefile}"
78 }
79
80 multipart_filename(){
81   local name="$1" count="${2:-1}"
82   local formdata state=begin
83
84   while read -r formdata; do case "$formdata" in
85     "--${multipart_boundary}--${CR}")
86       return 1
87       ;;
88     "--${multipart_boundary}${CR}")
89       state=header
90       ;;
91     "Content-Disposition: form-data; name=\"${name}\"; filename=\""*"\""*"${CR}")
92       [ $state = header -a $count -eq 1 ] && break
93       [ $state = header -a $count -gt 1 ] && count=$((count - 1))
94       ;;
95     "${CR}")
96       [ $state = header ] && state=junk
97       ;;
98   esac; done <"${multipart_cachefile}"
99
100   filename="${formdata#*; filename=\"}"
101   filename="${filename%%\"${CR}}"
102   filename="${filename%%\";*}"
103
104   HEX_DECODE % "$filename"
105 }