httpd_post_upload.txt example: handle binary files too
No binary (build failed)
—
(log yok)
| @@ -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 <<EOF |
| - | <html> |
| - | <body> |
| - | 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 <<EOF |
| - | <html> |
| - | <body> |
| - | 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 "<html>\n<body>\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 "<html>\n<body>\nFile upload has been accepted" |