From e3600a042e80cf279cfcb7f4c5e5f236b02bba7a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 13 Nov 2009 09:37:50 +0100 Subject: httpd_post_upload.txt example: handle binary files too Signed-off-by: Denys Vlasenko --- networking/httpd_post_upload.txt | 63 +++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/networking/httpd_post_upload.txt b/networking/httpd_post_upload.txt index fd7fc2b..9d504f4 100644 --- a/networking/httpd_post_upload.txt +++ b/networking/httpd_post_upload.txt @@ -24,53 +24,42 @@ post_upload.cgi # ^M <--------- extra empty line # -----------------------------29995809218093749221856446032--^M -# Beware: bashism $'\r' is used to handle ^M - file=/tmp/$$-$RANDOM +CR=`printf '\r'` + # CGI output must start with at least empty line (or headers) printf '\r\n' -IFS=$'\r' +IFS="$CR" read -r delim_line - -IFS='' -delim_line="${delim_line}--"$'\r' +IFS="" while read -r line; do - test "$line" = '' && break - test "$line" = $'\r' && break + test x"$line" = x"" && break + test x"$line" = x"$CR" && break done -# This will not work well for binary files: bash 3.2 is upset -# by reading NUL bytes and loses chunks of data. -# If you are not bothered by having junk appended to the uploaded file, -# consider using simple "cat >file" instead of the entire -# fragment below. +cat >"$file" -while read -r line; do +# We need to delete the tail of "\r\ndelim_line--\r\n" +tail_len=$((${#delim_line} + 6)) - while test "$line" = $'\r'; do - read -r line - test "$line" = "$delim_line" && { - # Aha! Empty line + delimiter! All done - cat < - -File upload has been accepted -EOF - exit 0 - } - # Empty line + NOT delimiter. Save empty line, - # and go check next line - printf "%s\n" $'\r' >&3 - done - # Not empty line - just save - printf "%s\n" "$line" >&3 -done 3>"$file" +# Get and check file size +filesize=`stat -c"%s" "$file"` +test "$filesize" -lt "$tail_len" && exit 1 -cat < - -File upload was not terminated with '$delim_line' - ??! -EOF +# Check that tail is correct +dd if="$file" skip=$((filesize - tail_len)) bs=1 count=1000 >"$file.tail" 2>/dev/null +printf "\r\n%s--\r\n" "$delim_line" >"$file.tail.expected" +if ! diff -q "$file.tail" "$file.tail.expected" >/dev/null; then + printf "\n\nMalformed file upload" + exit 1 +fi +rm "$file.tail" +rm "$file.tail.expected" + +# Truncate the file +dd of="$file" seek=$((filesize - tail_len)) bs=1 count=0 >/dev/null 2>/dev/null + +printf "\n\nFile upload has been accepted" -- cgit v1.1