From f87a4712a154664f640ad5078a4d282bb22795a2 Mon Sep 17 00:00:00 2001 From: Mikkel Jensen Date: Wed, 27 Aug 2014 12:31:45 +0200 Subject: No line break required after close-delimiter RFC 1341 does not specify this and indeed some upload clients (for example Flash) do not terminate the request with line breaks --- src/cow_multipart.erl | 52 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/src/cow_multipart.erl b/src/cow_multipart.erl index c412497..d2b45a4 100644 --- a/src/cow_multipart.erl +++ b/src/cow_multipart.erl @@ -47,7 +47,7 @@ "\r\n" "PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg\r\n" "Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg==\r\n" - "--frontier--\r\n" + "--frontier--" >>). -define(TEST1_BOUNDARY, <<"frontier">>). @@ -72,10 +72,32 @@ "\r\n" "...contents of file2.gif...\r\n" "--BbC04y--\r\n" - "--AaB03x--\r\n" + "--AaB03x--" >>). -define(TEST2_BOUNDARY, <<"AaB03x">>). +-define(TEST3_MIME, << + "This is the preamble.\r\n" + "--boundary\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + "This is the body of the message.\r\n" + "--boundary--" + "\r\nThis is the epilogue. Here it includes leading CRLF" +>>). +-define(TEST3_BOUNDARY, <<"boundary">>). + +-define(TEST4_MIME, << + "This is the preamble.\r\n" + "--boundary\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + "This is the body of the message.\r\n" + "--boundary--" + "\r\n" +>>). +-define(TEST4_BOUNDARY, <<"boundary">>). + %% Parsing. %% %% The multipart format is defined in RFC 2045. @@ -98,7 +120,7 @@ parse_headers(<< "--", Stream/bits >>, Boundary) -> BoundarySize = byte_size(Boundary), case Stream of %% Last boundary. Return the epilogue. - << Boundary:BoundarySize/binary, "--\r\n", Stream2/bits >> -> + << Boundary:BoundarySize/binary, "--", Stream2/bits >> -> {done, Stream2}; << Boundary:BoundarySize/binary, Stream2/bits >> -> %% We have all the headers only if there is a \r\n\r\n @@ -144,7 +166,7 @@ skip_preamble(Stream, Boundary) -> << _:Start2/binary, Stream2/bits >> = Stream, case Stream2 of %% Last boundary. Return the epilogue. - << "--\r\n", Stream3/bits >> -> + << "--", Stream3/bits >> -> {done, Stream3}; _ -> case binary:match(Stream, <<"\r\n\r\n">>) of @@ -298,6 +320,26 @@ parse_interleaved_test() -> {done, <<>>} = parse_headers(Rest4, ?TEST2_BOUNDARY), ok. +parse_epilogue_test() -> + H1 = [{<<"content-type">>, <<"text/plain">>}], + Body1 = <<"This is the body of the message.">>, + Epilogue = <<"\r\nThis is the epilogue. Here it includes leading CRLF">>, + {ok, H1, Rest} = parse_headers(?TEST3_MIME, ?TEST3_BOUNDARY), + {done, Body1, Rest2} = parse_body(Rest, ?TEST3_BOUNDARY), + done = parse_body(Rest2, ?TEST3_BOUNDARY), + {done, Epilogue} = parse_headers(Rest2, ?TEST3_BOUNDARY), + ok. + +parse_epilogue_crlf_test() -> + H1 = [{<<"content-type">>, <<"text/plain">>}], + Body1 = <<"This is the body of the message.">>, + Epilogue = <<"\r\n">>, + {ok, H1, Rest} = parse_headers(?TEST4_MIME, ?TEST4_BOUNDARY), + {done, Body1, Rest2} = parse_body(Rest, ?TEST4_BOUNDARY), + done = parse_body(Rest2, ?TEST4_BOUNDARY), + {done, Epilogue} = parse_headers(Rest2, ?TEST4_BOUNDARY), + ok. + parse_partial_test() -> {ok, <<0:8000, "abcdef">>, <<"\rghij">>} = parse_body(<<0:8000, "abcdef\rghij">>, <<"boundary">>), @@ -376,7 +418,7 @@ headers_to_iolist([{N, V}|Tail], Acc) -> -spec close(binary()) -> iodata(). close(Boundary) -> - [<<"\r\n--">>, Boundary, <<"--\r\n">>]. + [<<"\r\n--">>, Boundary, <<"--">>]. -ifdef(TEST). build_test() -> -- cgit v1.2.3