]> git.plutz.net Git - shellwiki/blob - multipart.sh
Merge commit '7a171a7dd5c5fcfc1e53c5e5d8165fac01291c0b'
[shellwiki] / multipart.sh
1 #!/bin/sh
2
3 [ "$include_multipart" ] && return 0
4 inlude_multipart="$0"
5
6 if [ "${CONTENT_TYPE}" -a ! "${CONTENT_TYPE##multipart/form-data;*}" ]; then
7   multipart_boundary="${CONTENT_TYPE#*; boundary=}"
8   multipart_boundary="${multipart_boundary%%;*}"
9   multipart_boundary="${multipart_boundary%${CR}}"
10 fi
11 multipart_cachefile="/tmp/multipart.$$"
12
13 readbytes(){
14   # read n bytes, like `head -c` but do not consume input
15   local size="$1" block
16
17   for block in 65536 32768 16384 8192 4096 2048 1024 512 256 128 64 32 16 8 4 2 1; do
18     if [ $size -ge $block ]; then
19       dd status=none bs="$block" count="$((size / block))"
20       size="$((size % block))"
21     fi
22   done
23 }
24
25 multipart_cache() {
26   multipart_cachefile="${1:-${multipart_cachefile}}"  # global
27
28   if [ "${multipart_boundary}" ]; then
29     # readbytes "$(( CONTENT_LENGTH ))" >"${multipart_cachefile}"
30     head -c "$(( CONTENT_LENGTH ))" >"${multipart_cachefile}"
31   else
32     return 1
33   fi
34 }
35
36 multipart(){
37   local name="$1" count="${2:-1}"
38   local formdata state=begin
39
40   while IFS='' read -r formdata; do case "$formdata" in
41     "--${multipart_boundary}--${CR}")
42       [ $state = data ] && return 0 \
43                         || return 1
44       ;;
45     "--${multipart_boundary}${CR}")
46       [ $state = data ] && return 0 \
47                         || state=header
48       ;;
49     "Content-Disposition: form-data; name=\"${name}\""*"${CR}")
50       [ $state = header -a $count -eq 1 ] && state=dheader
51       [ $state = header -a $count -gt 1 ] && count=$((count - 1))
52       [ $state = data ] && printf "%s\n" "$formdata"
53       ;;
54     "${CR}")
55       if [ $state = dheader ]; then
56         sed -n "/--${multipart_boundary}\(--\)\?${CR}/q; p;" \
57         | head -c-2
58         return 0;
59       fi
60       [ $state = header ] && state=junk
61       ;;
62   esac; done <"${multipart_cachefile}"
63 }
64
65 multipart_filename(){
66   local name="$1" count="${2:-1}"
67   local formdata state=begin
68
69   while read -r formdata; do case "$formdata" in
70     "--${multipart_boundary}--${CR}")
71       return 1
72       ;;
73     "--${multipart_boundary}${CR}")
74       state=header
75       ;;
76     "Content-Disposition: form-data; name=\"${name}\"; filename=\""*"\""*"${CR}")
77       [ $state = header -a $count -eq 1 ] && break
78       [ $state = header -a $count -gt 1 ] && count=$((count - 1))
79       ;;
80     "${CR}")
81       [ $state = header ] && state=junk
82       ;;
83   esac; done <"${multipart_cachefile}"
84
85   filename="${formdata#*; filename=\"}"
86   filename="${filename%%\"${CR}}"
87   filename="${filename%%\";*}"
88
89   HEX_DECODE % "$filename"
90 }