diff options
author | Dan Winship <danw@src.gnome.org> | 2002-06-07 13:38:05 +0000 |
---|---|---|
committer | Dan Winship <danw@src.gnome.org> | 2002-06-07 13:38:05 +0000 |
commit | b7f8dfc8f8feb1a69b730e3ca669336e92016703 (patch) | |
tree | 532004e2741cdcac355ec7e41e70c5c58f1cc73a | |
parent | ed21953cb6ef08a32026a22b184efa7cc1fa0067 (diff) | |
download | libsoup-b7f8dfc8f8feb1a69b730e3ca669336e92016703.tar.gz |
Rewrite this a bunch to handle trailing entity headers, and not crash on
* src/libsoup/soup-transfer.c (decode_chunk): Rewrite this a bunch
to handle trailing entity headers, and not crash on an assertion
failure if the server sends the final "\r\n" in a separate packet
from the preceding "0\r\n".
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | libsoup/soup-transfer.c | 130 |
2 files changed, 56 insertions, 81 deletions
@@ -1,3 +1,10 @@ +2002-06-06 Dan Winship <danw@ximian.com> + + * src/libsoup/soup-transfer.c (decode_chunk): Rewrite this a bunch + to handle trailing entity headers, and not crash on an assertion + failure if the server sends the final "\r\n" in a separate packet + from the preceding "0\r\n". + 2002-05-31 Joe Shaw <joe@ximian.com> * acinclude.m4: Added. Includes the pkg-config, glib1 and glib2 diff --git a/libsoup/soup-transfer.c b/libsoup/soup-transfer.c index 332cd7c0..2393afc5 100644 --- a/libsoup/soup-transfer.c +++ b/libsoup/soup-transfer.c @@ -50,7 +50,7 @@ DUMP_WRITE (guchar *data, gint bytes_written) typedef struct { /* - * Length remaining to be downloaded of the current chunk data. + * Length of the current chunk data. */ guint len; @@ -219,34 +219,6 @@ remove_block_at_index (GByteArray *arr, gint offset, gint length) g_byte_array_set_size (arr, arr->len - length); } -/* - * Count number of hex digits, and convert to decimal. Store number of hex - * digits read in @width. - */ -static gint -decode_hex (const gchar *src, gint *width) -{ - gint new_len = 0, j; - - *width = 0; - - while (isxdigit (*src)) { - (*width)++; - src++; - } - src -= *width; - - for (j = *width - 1; j + 1; j--) { - if (isdigit (*src)) - new_len += (*src - 0x30) << (4*j); - else - new_len += (tolower (*src) - 0x57) << (4*j); - src++; - } - - return new_len; -} - static gboolean decode_chunk (SoupTransferChunkState *s, GByteArray *arr, @@ -259,73 +231,68 @@ decode_chunk (SoupTransferChunkState *s, while (TRUE) { gint new_len = 0; gint len = 0; - gchar *i = &arr->data [s->idx + s->len]; - - /* - * Not enough data to finish the chunk (and the smallest - * possible next chunk header), break - */ - if (s->idx + s->len + 5 > arr->len) - break; - /* - * Check for end of chunk header, otherwise break. Avoid - * trailing \r\n from previous chunk body if this is not the - * opening chunk. - */ if (s->len) { - if (soup_substring_index ( - i + 2, - arr->len - s->idx - s->len - 2, - "\r\n") <= 0) - break; - } else if (soup_substring_index (arr->data, - arr->len, - "\r\n") <= 0) + /* We're in the middle of a chunk. If we don't + * have the entire chunk and the trailing CRLF + * yet, read more. + */ + if (s->idx + s->len + 2 > arr->len) break; - /* - * Remove trailing \r\n after previous chunk body + /* + * Increment datalen and s->idx, and remove + * the trailing CRLF. + */ + s->idx += s->len; + *datalen += s->len; + remove_block_at_index (arr, s->idx, 2); + + /* + * Ready for the next chunk. + */ + s->len = 0; + } + + /* + * We're at the start of a new chunk. If we don't have + * the complete chunk header, wait for more. */ - if (s->len) - remove_block_at_index (arr, s->idx + s->len, 2); + len = soup_substring_index (&arr->data [s->idx], + arr->len - s->idx, + "\r\n"); + if (len < 0) + break; + len += 2; - new_len = decode_hex (i, &len); + new_len = strtol (&arr->data [s->idx], NULL, 16); g_assert (new_len >= 0); - /* - * Previous chunk is now processed, add its length to index and - * datalen. + /* + * If this is the final (zero-length) chunk, we need + * to have all of the trailing entity headers as well. */ - s->idx += s->len; - *datalen += s->len; + if (new_len == 0) { + len = soup_substring_index (&arr->data [s->idx], + arr->len - s->idx, + "\r\n\r\n"); + if (len < 0) + break; - /* - * Update length for next chunk's size - */ - s->len = new_len; - - /* - * FIXME: Add entity headers we find here to - * req->response_headers. - */ - len += soup_substring_index (&arr->data [s->idx + len], - arr->len - s->idx - len, - "\r\n"); + /* + * FIXME: Add entity headers we find here to + * req->response_headers. + */ - /* - * Zero-length chunk closes transfer. Include final \r\n after - * empty chunk. - */ - if (s->len == 0) { - len += 2; + len += 4; ret = TRUE; } /* - * Remove hexified length, entity headers, and trailing \r\n + * Remove chunk header and get ready for chunk data. */ - remove_block_at_index (arr, s->idx, len + 2); + remove_block_at_index (arr, s->idx, len); + s->len = new_len; } return ret; @@ -378,7 +345,8 @@ read_chunk (SoupReader *r, gboolean *cancelled) if (*cancelled) goto CANCELLED; /* - * If overwrite, remove datalen worth of data from start of buffer + * If overwrite, remove already-processed data from start + * of buffer */ if (r->overwrite_chunks) { remove_block_at_index (arr, 0, s->idx); |