diff options
Diffstat (limited to 'daemon/gvfsbackendftp.c')
-rw-r--r-- | daemon/gvfsbackendftp.c | 96 |
1 files changed, 47 insertions, 49 deletions
diff --git a/daemon/gvfsbackendftp.c b/daemon/gvfsbackendftp.c index 8df8efe7..bbadf991 100644 --- a/daemon/gvfsbackendftp.c +++ b/daemon/gvfsbackendftp.c @@ -364,58 +364,56 @@ ftp_connection_receive (FtpConnection *conn, conn->read_bytes = 0; while (reply_state != DONE) { - if (conn->read_buffer_size - conn->read_bytes < 128) - { - gsize new_size = conn->read_buffer_size + 1024; - /* FIXME: upper limit for size? */ - gchar *new = g_try_realloc (conn->read_buffer, new_size); - if (new) - { - conn->read_buffer = new; - conn->read_buffer_size = new_size; - } - else - { - g_set_error_literal (&conn->error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid reply")); - return 0; - } - } last_line = conn->read_buffer + conn->read_bytes; - status = soup_socket_read_until (conn->commands, - last_line, - /* -1 byte for nul-termination */ - conn->read_buffer_size - conn->read_bytes - 1, - "\r\n", - 2, - &n_bytes, - &got_boundary, - conn->job->cancellable, - &conn->error); - - conn->read_bytes += n_bytes; - conn->read_buffer[conn->read_bytes] = 0; - DEBUG ("<-- %s", last_line); - - switch (status) - { - case SOUP_SOCKET_OK: - case SOUP_SOCKET_EOF: - if (got_boundary) - break; - if (n_bytes > 0) - continue; + do { + /* the available size must at least allow for boundary size (2) + * bytes to be available for reading */ + if (conn->read_buffer_size - conn->read_bytes < 128) + { + gsize new_size = conn->read_buffer_size + 1024; + /* FIXME: upper limit for size? */ + gchar *new = g_try_realloc (conn->read_buffer, new_size); + if (new) + { + /* make last line relative to new allocation */ + last_line = new + (last_line - conn->read_buffer); + conn->read_buffer = new; + conn->read_buffer_size = new_size; + } + else + { + g_set_error_literal (&conn->error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Invalid reply")); + return 0; + } + } + status = soup_socket_read_until (conn->commands, + conn->read_buffer + conn->read_bytes, + /* -1 byte for nul-termination */ + conn->read_buffer_size - conn->read_bytes - 1, + "\r\n", + 2, + &n_bytes, + &got_boundary, + conn->job->cancellable, + &conn->error); + + conn->read_bytes += n_bytes; + conn->read_buffer[conn->read_bytes] = 0; + + g_assert (status != SOUP_SOCKET_WOULD_BLOCK); + if (status == SOUP_SOCKET_ERROR) + return 0; + + if (n_bytes == 0) + { g_set_error_literal (&conn->error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Invalid reply")); - /* fall through */ - case SOUP_SOCKET_ERROR: - conn->read_buffer[conn->read_bytes] = 0; - return 0; - case SOUP_SOCKET_WOULD_BLOCK: - default: - g_assert_not_reached (); - break; - } + return 0; + } + } while (!got_boundary); + + DEBUG ("<-- %s", last_line); if (reply_state == FIRST_LINE) { |