Commit 465e19db authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

Adrian Schuur added trailer support in the chunked encoding stream. The

trailer is then sent to the normal header callback/stream.
parent 86660c73
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -7,6 +7,12 @@
                                  Changelog


Daniel (12 July 2005)
- Adrian Schuur added trailer support in the chunked encoding stream. The
  trailer is then sent to the normal header callback/stream. I wrote up test
  case 266 to verify the basic functionality. Do note that test case 34
  contains a flawed chunked encoding stream that still works the same.

Daniel (5 July 2005)
- Gisle Vanem came up with a nice little work-around for bug #1230118. It
  seems the Windows (MSVC) libc time functions may return data one hour off if
+4 −2
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ Curl and libcurl 7.14.1

This release includes the following changes:

 o trailer support for chunked encoded data streams 
 o -x/CURL_PROXY strings may now contain user+password
 o --trace-time now outputs the full microsecond, all 6 digits

@@ -41,6 +42,7 @@ This release would not have looked like this without help, code, reports and
advice from friends like these:

 John McGowan, Georg Wicherski, Andres Garcia, Eric Cooper, Todd Kulesza,
 Tupone Alfredo, Gisle Vanem, David Shaw, Andrew Bushnell, Dan Fandrich
 Tupone Alfredo, Gisle Vanem, David Shaw, Andrew Bushnell, Dan Fandrich,
 Adrian Schuur

        Thanks! (and sorry if I forgot to mention someone)
+69 −4
Original line number Diff line number Diff line
@@ -153,12 +153,19 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
      if(*datap == '\n') {
        /* we're now expecting data to come, unless size was zero! */
        if(0 == ch->datasize) {
          ch->state = CHUNK_STOP; /* stop reading! */
          if (conn->bits.trailerHdrPresent!=TRUE) {
            /* No Trailer: header found - revert to original Curl processing */
            ch->state = CHUNK_STOP;
            if (1 == length) {
            /* This was the final byte, return right now */
               /* This is the final byte, return right now */
               return CHUNKE_STOP;
            }
          }
          else {
            ch->state = CHUNK_TRAILER; /* attempt to read trailers */
            conn->trlPos=0;
          }
        }
        else
          ch->state = CHUNK_DATA;
      }
@@ -250,6 +257,64 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
        return CHUNKE_BAD_CHUNK;
      break;

    case CHUNK_TRAILER:
      /* conn->trailer is assumed to be freed in url.c on a
         connection basis */
      if (conn->trlPos >= conn->trlMax) {
        char *ptr;
        if(conn->trlMax) {
          conn->trlMax *= 2;
          ptr = (char*)realloc(conn->trailer,conn->trlMax);
        }
        else {
          conn->trlMax=128;
          ptr = (char*)malloc(conn->trlMax);
        }
        if(!ptr)
          return CHUNKE_OUT_OF_MEMORY;
        conn->trailer = ptr;
      }
      conn->trailer[conn->trlPos++]=*datap;

      if(*datap == '\r')
        ch->state = CHUNK_TRAILER_CR;
      else {
        datap++;
        length--;
     }
      break;

    case CHUNK_TRAILER_CR:
      if(*datap == '\r') {
        ch->state = CHUNK_TRAILER_POSTCR;
        datap++;
        length--;
      }
      else
        return CHUNKE_BAD_CHUNK;
      break;

    case CHUNK_TRAILER_POSTCR:
      if (*datap == '\n') {
        conn->trailer[conn->trlPos++]='\n';
        conn->trailer[conn->trlPos]=0;
        if (conn->trlPos==2) {
          ch->state = CHUNK_STOP;
          return CHUNKE_STOP;
        }
        else {
          Curl_client_write(conn->data, CLIENTWRITE_HEADER,
                            conn->trailer, conn->trlPos);
        }
        ch->state = CHUNK_TRAILER;
        conn->trlPos=0;
        datap++;
        length--;
      }
      else
        return CHUNKE_BAD_CHUNK;
      break;

    case CHUNK_STOP:
      /* If we arrive here, there is data left in the end of the buffer
         even if there's no more chunks to read */
+18 −2
Original line number Diff line number Diff line
@@ -52,8 +52,8 @@ typedef enum {
  /* POSTCR should get a CR and nothing else, then move to POSTLF */
  CHUNK_POSTCR,

  /* POSTLF should get a LF and nothing else, then move back to HEX as
     the CRLF combination marks the end of a chunk */
  /* POSTLF should get a LF and nothing else, then move back to HEX as the
     CRLF combination marks the end of a chunk */
  CHUNK_POSTLF,

  /* This is mainly used to really mark that we're out of the game.
@@ -62,7 +62,22 @@ typedef enum {
     buffer! */
  CHUNK_STOP,

  /* At this point optional trailer headers can be found, unless the next line
     is CRLF */
  CHUNK_TRAILER,

  /* A trailer CR has been found - next state is CHUNK_TRAILER_POSTCR.
     Next char must be a LF */
  CHUNK_TRAILER_CR,

  /* A trailer LF must be found now, otherwise CHUNKE_BAD_CHUNK will be
     signalled If this is an empty trailer CHUNKE_STOP will be signalled.
     Otherwise the trailer will be broadcasted via Curl_client_write() and the
     next state will be CHUNK_TRAILER */
  CHUNK_TRAILER_POSTCR,

  CHUNK_LAST /* never use */

} ChunkyState;

typedef enum {
@@ -74,6 +89,7 @@ typedef enum {
  CHUNKE_WRITE_ERROR,
  CHUNKE_STATE_ERROR,
  CHUNKE_BAD_ENCODING,
  CHUNKE_OUT_OF_MEMORY,
  CHUNKE_LAST
} CHUNKcode;

+15 −0
Original line number Diff line number Diff line
@@ -833,6 +833,20 @@ CURLcode Curl_readwrite(struct connectdata *conn,
              /* init our chunky engine */
              Curl_httpchunk_init(conn);
            }

            else if (checkprefix("Trailer:", k->p) ||
                     checkprefix("Trailers:", k->p)) {
              /*
               * This test helps Curl_httpchunk_read() to determine to look
               * for well formed trailers after the zero chunksize record. In
               * this case a CRLF is required after the zero chunksize record
               * when no trailers are sent, or after the last trailer record.
               *
               * It seems both Trailer: and Trailers: occur in the wild.
               */
              conn->bits.trailerHdrPresent = TRUE;
            }

            else if (checkprefix("Content-Encoding:", k->p) &&
                     data->set.encoding) {
              /*
@@ -1074,6 +1088,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
             * the name says read, this function both reads and writes away
             * the data. The returned 'nread' holds the number of actual
             * data it wrote to the client.  */

            CHUNKcode res =
              Curl_httpchunk_read(conn, k->str, nread, &nread);

Loading