Commit 84b4e9ff authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

Fixed the FTP response reader function to properly deal with responses split

up in several chunks when read.
parent 677a74fa
Loading
Loading
Loading
Loading
+26 −18
Original line number Diff line number Diff line
@@ -234,6 +234,17 @@ static CURLcode AllowServerConnect(struct connectdata *conn)
  return CURLE_OK;
}

/* initialize stuff to prepare for reading a fresh new response */
static void ftp_respinit(struct connectdata *conn)
{
  struct FTP *ftp = conn->proto.ftp;
  ftp->nread_resp = 0;
  ftp->linestart_resp = conn->data->state.buffer;
}

/* macro to check for the last line in an FTP server response */
#define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \
                        isdigit((int)line[2]) && (' ' == line[3]))

static CURLcode ftp_readresp(curl_socket_t sockfd,
                             struct connectdata *conn,
@@ -245,7 +256,6 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
  ssize_t gotbytes;
  char *ptr;
  struct SessionHandle *data = conn->data;
  char *line_start;
  char *buf = data->state.buffer;
  CURLcode result = CURLE_OK;
  struct FTP *ftp = conn->proto.ftp;
@@ -254,10 +264,10 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
  if (ftpcode)
    *ftpcode = 0; /* 0 for errors or not done */

  ptr=buf;
  line_start = buf;
  ptr=buf + ftp->nread_resp;

  perline=0;
  perline= ptr-ftp->linestart_resp; /* number of bytes in the current line,
                                       so far */
  keepon=TRUE;

  while((ftp->nread_resp<BUFSIZE) && (keepon && !result)) {
@@ -312,7 +322,8 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,

          /* output debug output if that is requested */
          if(data->set.verbose)
            Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline, conn);
            Curl_debug(data, CURLINFO_HEADER_IN,
                       ftp->linestart_resp, perline, conn);

          /*
           * We pass all response-lines to the callback function registered
@@ -320,24 +331,21 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
           * headers.
           */
          result = Curl_client_write(data, CLIENTWRITE_HEADER,
                                     line_start, perline);
                                     ftp->linestart_resp, perline);
          if(result)
            return result;

#define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \
                        isdigit((int)line[2]) && (' ' == line[3]))

          if(perline>3 && lastline(line_start)) {
          if(perline>3 && lastline(ftp->linestart_resp)) {
            /* This is the end of the last line, copy the last line to the
               start of the buffer and zero terminate, for old times sake (and
               krb4)! */
            char *meow;
            int n;
            for(meow=line_start, n=0; meow<ptr; meow++, n++)
            for(meow=ftp->linestart_resp, n=0; meow<ptr; meow++, n++)
              buf[n] = *meow;
            *meow=0; /* zero terminate */
            keepon=FALSE;
            line_start = ptr+1; /* advance pointer */
            ftp->linestart_resp = ptr+1; /* advance pointer */
            i++; /* skip this before getting out */

            *size = ftp->nread_resp; /* size of the response */
@@ -345,7 +353,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
            break;
          }
          perline=0; /* line starts over here */
          line_start = ptr+1;
          ftp->linestart_resp = ptr+1;
        }
      }
      if(!keepon && (i != gotbytes)) {
@@ -356,7 +364,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
        ftp->cache_size = gotbytes - i;
        ftp->cache = (char *)malloc((int)ftp->cache_size);
        if(ftp->cache)
          memcpy(ftp->cache, line_start, (int)ftp->cache_size);
          memcpy(ftp->cache, ftp->linestart_resp, (int)ftp->cache_size);
        else
          return CURLE_OUT_OF_MEMORY; /**BANG**/
      }
@@ -549,9 +557,6 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
            if(result)
              return result;

#define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \
                        isdigit((int)line[2]) && (' ' == line[3]))

            if(perline>3 && lastline(line_start)) {
              /* This is the end of the last line, copy the last
               * line to the start of the buffer and zero terminate,
@@ -2749,6 +2754,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn,

  /* When we connect, we start in the state where we await the 220
     response */
  ftp_respinit(conn); /* init the response reader stuff */
  state(conn, FTP_WAIT220);
  ftp->response = Curl_tvnow(); /* start response time-out now! */

@@ -3221,6 +3227,8 @@ CURLcode Curl_nbftpsendf(struct connectdata *conn,
  bytes_written=0;
  write_len = strlen(s);

  ftp_respinit(conn);

  res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
                   &bytes_written);

+4 −0
Original line number Diff line number Diff line
@@ -327,7 +327,11 @@ struct FTP {
  bool cwddone;     /* if it has been determined that the proper CWD combo
                       already has been done */
  char *prevpath;   /* conn->path from the previous transfer */

  size_t nread_resp; /* number of bytes currently read of a server response */
  char *linestart_resp; /* line start pointer for the FTP server response
                           reader function */

  int count1; /* general purpose counter for the state machine */
  int count2; /* general purpose counter for the state machine */
  int count3; /* general purpose counter for the state machine */