|
@@ -6672,6 +6672,22 @@ mg_read(struct mg_connection *conn, void *buf, size_t len)
|
|
|
if (mg_read_inner(conn, lenbuf + i, 1) != 1) {
|
|
|
lenbuf[i] = 0;
|
|
|
}
|
|
|
+ if ((i > 0) && (lenbuf[i] == ';'))
|
|
|
+ {
|
|
|
+ // chunk extension --> skip chars until next CR
|
|
|
+ //
|
|
|
+ // RFC 2616, 3.6.1 Chunked Transfer Coding
|
|
|
+ // (https://www.rfc-editor.org/rfc/rfc2616#page-25)
|
|
|
+ //
|
|
|
+ // chunk = chunk-size [ chunk-extension ] CRLF
|
|
|
+ // chunk-data CRLF
|
|
|
+ // ...
|
|
|
+ // chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
|
|
|
+ do
|
|
|
+ ++conn->content_len;
|
|
|
+ while (mg_read_inner(conn, lenbuf + i, 1) == 1 &&
|
|
|
+ lenbuf[i] != '\r');
|
|
|
+ }
|
|
|
if ((i > 0) && (lenbuf[i] == '\r')
|
|
|
&& (lenbuf[i - 1] != '\r')) {
|
|
|
continue;
|
|
@@ -6697,13 +6713,56 @@ mg_read(struct mg_connection *conn, void *buf, size_t len)
|
|
|
conn->is_chunked = 2;
|
|
|
return -1;
|
|
|
}
|
|
|
- if (chunkSize == 0) {
|
|
|
+ if (conn->is_chunked == 3) {
|
|
|
/* try discarding trailer for keep-alive */
|
|
|
- conn->content_len += 2;
|
|
|
- if ((mg_read_inner(conn, lenbuf, 2) == 2)
|
|
|
- && (lenbuf[0] == '\r') && (lenbuf[1] == '\n')) {
|
|
|
- conn->is_chunked = 4;
|
|
|
+
|
|
|
+ // We found the last chunk (length 0) including the
|
|
|
+ // CRLF that terminates that chunk. Now follows a possibly
|
|
|
+ // empty trailer and a final CRLF.
|
|
|
+ //
|
|
|
+ // see RFC 2616, 3.6.1 Chunked Transfer Coding
|
|
|
+ // (https://www.rfc-editor.org/rfc/rfc2616#page-25)
|
|
|
+ //
|
|
|
+ // Chunked-Body = *chunk
|
|
|
+ // last-chunk
|
|
|
+ // trailer
|
|
|
+ // CRLF
|
|
|
+ // ...
|
|
|
+ // last-chunk = 1*("0") [ chunk-extension ] CRLF
|
|
|
+ // ...
|
|
|
+ // trailer = *(entity-header CRLF)
|
|
|
+
|
|
|
+ int crlf_count = 2; // one CRLF already determined
|
|
|
+
|
|
|
+ while (crlf_count < 4 && conn->is_chunked == 3) {
|
|
|
+ ++conn->content_len;
|
|
|
+ if (mg_read_inner(conn, lenbuf, 1) == 1) {
|
|
|
+ if ((crlf_count == 0 || crlf_count == 2)) {
|
|
|
+ if (lenbuf[0] == '\r')
|
|
|
+ ++crlf_count;
|
|
|
+ else
|
|
|
+ crlf_count = 0;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ // previous character was a CR
|
|
|
+ // --> next character must be LF
|
|
|
+
|
|
|
+ if (lenbuf[0] == '\n')
|
|
|
+ ++crlf_count;
|
|
|
+ else
|
|
|
+ conn->is_chunked = 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ // premature end of trailer
|
|
|
+ conn->is_chunked = 2;
|
|
|
}
|
|
|
+
|
|
|
+ if (conn->is_chunked == 2)
|
|
|
+ return -1;
|
|
|
+ else
|
|
|
+ conn->is_chunked = 4;
|
|
|
+
|
|
|
break;
|
|
|
}
|
|
|
|