Mercurial > gftp.yaz
changeset 209:d79e2782eb1b
2003-7-5 Brian Masney <masneyb@gftp.org>
* lib/protocols.c (gftp_get_line) - fixed bug where the read function
was being called one extra time after the end of file was reached
* lib/rfc2068.c - fixes for chunked file transfers. All known issues with the
HTTP protocol should be (hopefully) fixed now
* lib/httpcommon.h (struct rfc2068_params_tag) - added eof variable
author | masneyb |
---|---|
date | Sat, 05 Jul 2003 17:30:14 +0000 |
parents | 86a3e0da176d |
children | 82ebd1b05345 |
files | ChangeLog lib/httpcommon.h lib/protocols.c lib/rfc2068.c |
diffstat | 4 files changed, 118 insertions(+), 70 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Thu Jul 03 08:29:01 2003 +0000 +++ b/ChangeLog Sat Jul 05 17:30:14 2003 +0000 @@ -1,8 +1,11 @@ -2003-07-01 gettextize <bug-gnu-gettext@gnu.org> +2003-7-5 Brian Masney <masneyb@gftp.org> + * lib/protocols.c (gftp_get_line) - fixed bug where the read function + was being called one extra time after the end of file was reached - * Makefile.am (SUBDIRS): Add intl. - (EXTRA_DIST): Add config.rpath mkinstalldirs. - * configure.in (AC_OUTPUT): Add intl/Makefile, + * lib/rfc2068.c - fixes for chunked file transfers. All known issues with the + HTTP protocol should be (hopefully) fixed now + + * lib/httpcommon.h (struct rfc2068_params_tag) - added eof variable 2003-7-1 Brian Masney <masneyb@gftp.org> * lib/misc.c (base64_encode) - alphabet fix (+ wasn't a valid @@ -1164,7 +1167,7 @@ * cvsclean - added this script - * *.[ch] - added $Id: ChangeLog,v 1.104 2003/07/02 01:44:54 masneyb Exp $ tags + * *.[ch] - added $Id: ChangeLog,v 1.105 2003/07/05 17:30:13 masneyb Exp $ tags * debian/* - updated files from Debian maintainer
--- a/lib/httpcommon.h Thu Jul 03 08:29:01 2003 +0000 +++ b/lib/httpcommon.h Sat Jul 05 17:30:14 2003 +0000 @@ -25,7 +25,8 @@ unsigned long read_bytes, content_length; long chunk_size; - unsigned int chunked_transfer : 1; + unsigned int chunked_transfer : 1, + eof : 1; ssize_t (*real_read_function) ( gftp_request * request, void *ptr, size_t size,
--- a/lib/protocols.c Thu Jul 03 08:29:01 2003 +0000 +++ b/lib/protocols.c Sat Jul 05 17:30:14 2003 +0000 @@ -2048,7 +2048,12 @@ (*rbuf)->curpos = (*rbuf)->buffer; - if ((ret = read_function (request, pos, rlen, fd)) < 0) + if ((*rbuf)->eof) + ret = 0; + else + ret = read_function (request, pos, rlen, fd); + + if (ret < 0) { gftp_free_getline_buffer (rbuf); return (ret);
--- a/lib/rfc2068.c Thu Jul 03 08:29:01 2003 +0000 +++ b/lib/rfc2068.c Sat Jul 05 17:30:14 2003 +0000 @@ -55,11 +55,11 @@ int ret, chunked; params = request->protocol_data; + *tempstr = '\0'; chunked = 0; params->chunk_size = 0; - params->rbuf = NULL; - *tempstr = '\0'; params->content_length = 0; + params->eof = 0; if (request->last_ftp_response) { @@ -71,6 +71,7 @@ { g_free (params->extra_read_buffer); params->extra_read_buffer = NULL; + params->extra_read_buffer_len = 0; } do @@ -104,7 +105,8 @@ if (sscanf ((char *) tempstr, "%lx", ¶ms->chunk_size) != 1) { request->logging_function (gftp_logging_recv, request, - _("Received wrong response from server, disconnecting.\nExpecting a chunk size in the response from the remote server\n")); + _("Received wrong response from server, disconnecting\nInvalid chunk size '%s' returned by the remote server\n"), + tempstr); gftp_disconnect (request); return (GFTP_EFATAL); } @@ -116,15 +118,13 @@ if (params->chunk_size < 0) { params->extra_read_buffer_len = params->chunk_size * -1; + params->chunk_size = 0; params->extra_read_buffer = g_malloc (params->extra_read_buffer_len + 1); memcpy (params->extra_read_buffer, params->rbuf->curpos + (params->rbuf->cur_bufsize - params->extra_read_buffer_len), params->extra_read_buffer_len); params->extra_read_buffer[params->extra_read_buffer_len] = '\0'; params->rbuf->cur_bufsize -= params->extra_read_buffer_len; - params->chunk_size = 0; + params->rbuf->curpos[params->rbuf->cur_bufsize] = '\0'; } - - - params->chunk_size = 0; } params->chunked_transfer = chunked; @@ -379,6 +379,7 @@ params->content_length = 0; params->chunked_transfer = 0; params->chunk_size = 0; + params->eof = 0; return (0); } @@ -709,6 +710,7 @@ { g_free (params->extra_read_buffer); params->extra_read_buffer = NULL; + params->extra_read_buffer_len = 0; } } @@ -716,22 +718,38 @@ static ssize_t rfc2068_chunked_read (gftp_request * request, void *ptr, size_t size, int fd) { + size_t read_size, begin_ptr_len; rfc2068_params * params; char *stpos, *endpos; - size_t read_size; + void *read_ptr_pos; ssize_t retval; params = request->protocol_data; - /* FIXME - left off here */ if (params->extra_read_buffer != NULL) { - read_size = params->extra_read_buffer_len > size ? size : params->extra_read_buffer_len; - memcpy (ptr, params->extra_read_buffer, read_size); - retval = read_size; + g_return_val_if_fail (params->extra_read_buffer_len <= size, GFTP_EFATAL); + + memcpy (ptr, params->extra_read_buffer, params->extra_read_buffer_len); + + begin_ptr_len = params->extra_read_buffer_len; + read_ptr_pos = (char *) ptr + begin_ptr_len; + + /* Check for end of chunk */ + if (begin_ptr_len > 5 && strncmp ("\r\n0\r\n", (char *) ptr, 5) == 0) + read_size = 0; + else + read_size = size - begin_ptr_len; + + g_free (params->extra_read_buffer); + params->extra_read_buffer = NULL; + params->extra_read_buffer_len = 0; } else { + begin_ptr_len = 0; + read_ptr_pos = ptr; + read_size = size; if (params->content_length > 0) { @@ -744,72 +762,93 @@ else if (params->chunked_transfer && params->chunk_size > 0 && params->chunk_size < read_size) read_size = params->chunk_size; - - retval = params->real_read_function (request, ptr, read_size, fd); } - if (retval > 0) - params->read_bytes += retval; + if (read_size > 0 && !params->eof) + { + retval = params->real_read_function (request, read_ptr_pos, read_size, fd); + + if (retval > 0) + params->read_bytes += retval; + else if (retval == 0) + params->eof = 1; + else if (retval < 0) + return (retval); + + if (params->chunk_size > 0 && retval > 0) + { + params->chunk_size -= retval; + return (retval); + } + + retval += begin_ptr_len; + } + else + retval = begin_ptr_len; if (!params->chunked_transfer || retval <= 0) return (retval); - if (params->chunk_size == 0) + stpos = (char *) ptr; + while (params->chunk_size == 0) { - stpos = (char *) ptr; - - while (params->chunk_size == 0) + if (*stpos != '\r' || *(stpos + 1) != '\n') { - if (*stpos != '\r' || *(stpos + 1) != '\n') - { - request->logging_function (gftp_logging_recv, request, - _("Received wrong response from server, disconnecting\nExpecting a carriage return and line feed before the chunk size in the server response\n")); - gftp_disconnect (request); - return (GFTP_EFATAL); - } + request->logging_function (gftp_logging_recv, request, + _("Received wrong response from server, disconnecting\nExpecting a carriage return and line feed before the chunk size in the server response\n")); + gftp_disconnect (request); + return (GFTP_EFATAL); + } + + for (endpos = stpos + 2; + *endpos != '\n' && endpos < stpos + retval; + endpos++); - for (endpos = stpos + 2; - *endpos != '\n' && endpos < stpos + retval; - endpos++); + if (*endpos != '\n') + { + /* The current chunk size is split between multiple packets. + Save this chunk and read the next */ - if (*endpos != '\n') - { - request->logging_function (gftp_logging_recv, request, - "FIXME 2.0.15 - disconnecting, chunk size is in next packet\n"); - gftp_disconnect (request); - return (GFTP_EFATAL); - } + params->extra_read_buffer = g_malloc (retval + 1); + memcpy (params->extra_read_buffer, ptr, retval); + params->extra_read_buffer[retval] = '\0'; + params->extra_read_buffer_len = retval; + return (rfc2068_chunked_read (request, ptr, size, fd)); + } - *endpos = '\0'; - if (*(endpos - 1) == '\r') - *(endpos - 1) = '\0'; - - if (sscanf (stpos + 2, "%lx", ¶ms->chunk_size) != 1) - { - request->logging_function (gftp_logging_recv, request, - _("Received wrong response from server, disconnecting\nInvalid chunk size '%s' returned by the remote server\n"), - params->chunk_size); - gftp_disconnect (request); - return (GFTP_EFATAL); - } - - if (params->chunk_size == 0) + *endpos = '\0'; + if (*(endpos - 1) == '\r') + *(endpos - 1) = '\0'; + + if (sscanf (stpos + 2, "%lx", ¶ms->chunk_size) != 1) + { + request->logging_function (gftp_logging_recv, request, + _("Received wrong response from server, disconnecting\nInvalid chunk size '%s' returned by the remote server\n"), + stpos + 2); + gftp_disconnect (request); + return (GFTP_EFATAL); + } + + if (params->chunk_size == 0) + { + if (params->eof) return (0); - - retval -= endpos - (char *) ptr + 1; - params->chunk_size -= retval; - memmove (stpos, endpos + 1, retval); - ((char *) stpos)[retval] = '\0'; + + params->eof = 1; + return (retval); + } + + retval -= endpos - (char *) stpos + 1; - if (params->chunk_size == 0) - { - stpos += params->chunk_size; - continue; - } + memmove (stpos, endpos + 1, retval - (stpos - (char *) ptr)); + + params->chunk_size -= retval; + if (params->chunk_size < 0) + { + stpos += retval + params->chunk_size; /* chunk size is negative */ + params->chunk_size = 0; } } - else if (retval > 0) - params->chunk_size -= retval; return (retval); }