]> git.plutz.net Git - shellwiki/blob - multipart.sh
Merge commit 'a3e37fbe95bb7b2cca32001ac280e37c4bfdae82'
[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         # Do not use `sed -n` (or busybox sed will "convert" NULL to LF)
57         sed "/--${multipart_boundary}\(--\)\?${CR}/{x;q;}" \
58         | head -c-3
59         return 0;
60       fi
61       [ $state = header ] && state=junk
62       ;;
63   esac; done <"${multipart_cachefile}"
64 }
65
66 multipart_filename(){
67   local name="$1" count="${2:-1}"
68   local formdata state=begin
69
70   while read -r formdata; do case "$formdata" in
71     "--${multipart_boundary}--${CR}")
72       return 1
73       ;;
74     "--${multipart_boundary}${CR}")
75       state=header
76       ;;
77     "Content-Disposition: form-data; name=\"${name}\"; filename=\""*"\""*"${CR}")
78       [ $state = header -a $count -eq 1 ] && break
79       [ $state = header -a $count -gt 1 ] && count=$((count - 1))
80       ;;
81     "${CR}")
82       [ $state = header ] && state=junk
83       ;;
84   esac; done <"${multipart_cachefile}"
85
86   filename="${formdata#*; filename=\"}"
87   filename="${filename%%\"${CR}}"
88   filename="${filename%%\";*}"
89
90   HEX_DECODE % "$filename"
91 }