Skip to content

Commit 8199e42

Browse files
committed
unholy atrocities
1 parent 52aaeb8 commit 8199e42

File tree

6 files changed

+40
-13
lines changed

6 files changed

+40
-13
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ not sure
2323
- [x] form data parsing
2424
- [x] cookie parsing
2525
- [x] url search param parsing
26-
- [ ] multipart file uploads
26+
- [x] multipart file uploads
2727
- [ ] better example apps
2828
- [ ] docs?
2929
- [ ] database abstraction

core.sh

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#!/usr/bin/env bash
22

33
declare -A HTTP_HEADERS
4+
declare -A FILE_UPLOADS
5+
declare -A FILE_UPLOAD_TYPES
6+
declare -A FILE_UPLOAD_NAMES
47
declare -A QUERY_PARAMS
58
declare -A FORM_DATA
69
declare -A COOKIES
@@ -9,6 +12,12 @@ debug() {
912
printf "%s\n" "$@" 1>&2
1013
}
1114

15+
trim_quotes() {
16+
# Usage: trim_quotes "string"
17+
: "${1//\'}"
18+
printf '%s\n' "${_//\"}"
19+
}
20+
1221
urlencode() {
1322
# Usage: urlencode "string"
1423
local LC_ALL=C
@@ -172,7 +181,6 @@ EOF
172181
if [[ ${HTTP_HEADERS["Content-Type"]} == "multipart/form-data; "* ]]; then
173182
BOUNDARY="${HTTP_HEADERS["Content-Type"]}"
174183
BOUNDARY="${BOUNDARY#*=}"
175-
debug "BOUNDARY=$BOUNDARY"
176184
fi
177185

178186

@@ -185,11 +193,14 @@ ${HTTP_HEADERS["Cookie"]};
185193
EOF
186194
fi
187195

196+
CLEN=${HTTP_HEADERS["Content-Length"]}
197+
188198
# Read multipart body
189199
if [[ ! -z "$BOUNDARY" ]]; then
190200
state="start"
191201
reader="reading"
192202
local -A MULTIPART_HEADERS
203+
local -A DISPOSITIONS
193204
while read -n2 byte; do
194205
# we have to implement our own readline because of reasons
195206
if [[ "$reader" == "reading" ]]; then
@@ -206,6 +217,7 @@ EOF
206217
if [[ "$state" == "start" ]] && [[ "$PARSED" == "--$BOUNDARY"* ]]; then
207218
state="headers"
208219
MULTIPART_HEADERS=()
220+
DISPOSITIONS=()
209221
elif [[ "$state" == "headers" ]]; then
210222
PARSED="${PARSED%%$'\r'}"
211223
if [[ -z "$PARSED" ]]; then
@@ -220,11 +232,24 @@ EOF
220232
echo -n "${line}00" | xxd -r -p >> "$UPLOAD_TO"
221233
else
222234
# this is a newline char
223-
if [[ "$PARSED" == "--$BOUNDARY--"* ]]; then
224-
# sadly, we cannot goto
225-
break
226-
elif [[ "$PARSED" == "--$BOUNDARY"* ]]; then
235+
if [[ "$PARSED" == "--$BOUNDARY"* ]]; then
236+
while read -r -d ';' line; do
237+
DISPOSITIONS["${line%%=*}"]=$(urldecode "${line#*=}")
238+
done << EOF
239+
${MULTIPART_HEADERS["Content-Disposition"]};
240+
EOF
241+
NAME=$(trim_quotes "${DISPOSITIONS[name]}")
242+
FILENAME=$(trim_quotes "${DISPOSITIONS[filename]}")
243+
FILE_UPLOADS["$NAME"]="$UPLOAD_TO"
244+
FILE_UPLOAD_NAMES["$NAME"]="$FILENAME"
245+
FILE_UPLOAD_TYPES["$NAME"]="${MULTIPART_HEADERS[Content-Type]}"
246+
MULTIPART_HEADERS=()
247+
DISPOSITIONS=()
227248
state="headers"
249+
if [[ "$PARSED" == "--$BOUNDARY--"* ]]; then
250+
# i dont know how, but we made it out alive
251+
break
252+
fi
228253
else
229254
echo -n "${line}0a" | xxd -r -p >> "$UPLOAD_TO"
230255
fi
@@ -234,10 +259,9 @@ EOF
234259
line=''
235260
fi
236261
# wheeeeeeeeeeeeeeeee
237-
done < <(stdbuf -o0 -i0 hexdump -v -e '/1 "%02x"')
262+
done < <(stdbuf -o0 -i0 hexdump -v -e '/1 "%02x"' -n $CLEN)
238263
else
239264
# Read body
240-
CLEN=${HTTP_HEADERS["Content-Length"]}
241265
[[ "$CLEN" =~ ^[0-9]+$ ]] && \
242266
test $CLEN -gt 0 && read -rN $CLEN REQUEST_BODY;
243267
fi

examples/file-upload/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
data/
22
pubsub/
3+
uploads/
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11

22
htmx_page << EOF
33
<h1>File Upload Example</h1>
4-
<form id='form' hx-encoding='multipart/form-data' hx-post='/upload'
5-
_='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'>
4+
<form id='form' hx-encoding='multipart/form-data' hx-post='/upload'>
65
<input type='file' name='file'>
76
<button>Upload</button>
8-
<progress id='progress' value='0' max='100'></progress>
97
</form>
108
EOF
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11

2-
3-
debug "WE GOT IT"
2+
debug "hello"
3+
echo "<pre>"
4+
printf "%s\n" "${FILE_UPLOADS[@]@K}"
5+
printf "%s\n" "${FILE_UPLOAD_NAMES[@]@K}"
6+
printf "%s\n" "${FILE_UPLOAD_TYPES[@]@K}"
7+
echo "</pre>"
-121 KB
Binary file not shown.

0 commit comments

Comments
 (0)