174
196
struct Curl_transfer_keeper *k = &conn->keep;
175
197
struct SessionHandle *data = conn->data;
177
199
ssize_t nread; /* number of bytes read */
202
/* These two are used only if no other select() or _fdset() have been
203
invoked before this. This typicly happens if you use the multi interface
204
and call curl_multi_perform() without calling curl_multi_fdset()
209
fd_set *readfdp = k->readfdp;
210
fd_set *writefdp = k->writefdp;
211
curl_off_t contentlength;
213
if((k->keepon & KEEP_READ) && !readfdp) {
214
/* reading is requested, but no socket descriptor pointer was set */
215
FD_ZERO(&extrareadfd);
216
FD_SET(conn->sockfd, &extrareadfd);
217
readfdp = &extrareadfd;
219
/* no write, no exceptions, no timeout */
220
select(conn->sockfd+1, readfdp, NULL, NULL, ¬imeout);
222
if((k->keepon & KEEP_WRITE) && !writefdp) {
223
/* writing is requested, but no socket descriptor pointer was set */
224
FD_ZERO(&extrawritefd);
225
FD_SET(conn->writesockfd, &extrawritefd);
226
writefdp = &extrawritefd;
228
/* no read, no exceptions, no timeout */
229
select(conn->writesockfd+1, NULL, writefdp, NULL, ¬imeout);
233
/* If we still have reading to do, we check if we have a readable
234
socket. Sometimes the reafdp is NULL, if no fd_set was done using
235
the multi interface and then we can do nothing but to attempt a
181
237
if((k->keepon & KEEP_READ) &&
182
FD_ISSET(conn->sockfd, &k->readfd)) {
185
result = Curl_read(conn, conn->sockfd, k->buf,
189
break; /* get out of loop */
193
if ((k->bytecount == 0) && (k->writebytecount == 0))
194
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
196
didwhat |= KEEP_READ;
198
/* NULL terminate, allowing string ops to be used */
202
/* if we receive 0 or less here, the server closed the connection and
203
we bail out from this! */
204
else if (0 >= nread) {
205
k->keepon &= ~KEEP_READ;
206
FD_ZERO(&k->rkeepfd);
210
/* Default buffer to use when we write the buffer, it may be changed
211
in the flow below before the actual storing is done. */
214
/* Since this is a two-state thing, we check if we are parsing
215
headers at the moment or not. */
217
/* we are in parse-the-header-mode */
219
/* header line within buffer loop */
223
/* str_start is start of line within buf */
224
k->str_start = k->str;
226
k->end_ptr = strchr (k->str_start, '\n');
229
/* no more complete header lines within buffer */
230
/* copy what is remaining into headerbuff */
231
int str_length = (int)strlen(k->str);
238
(!readfdp || FD_ISSET(conn->sockfd, readfdp))) {
240
bool readdone = TRUE;
242
/* This is where we loop until we have read everything there is to
243
read or we get a EWOULDBLOCK */
245
int buffersize = data->set.buffer_size?
246
data->set.buffer_size:BUFSIZE -1;
248
/* receive data from the network! */
249
int readrc = Curl_read(conn, conn->sockfd, k->buf, buffersize, &nread);
251
/* subzero, this would've blocked */
253
break; /* get out of loop */
255
/* get the CURLcode from the int */
256
result = (CURLcode)readrc;
261
if ((k->bytecount == 0) && (k->writebytecount == 0)) {
262
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
263
if(k->wait100_after_headers)
264
/* set time stamp to compare with when waiting for the 100 */
265
k->start100 = Curl_tvnow();
268
didwhat |= KEEP_READ;
270
/* NULL terminate, allowing string ops to be used */
274
/* if we receive 0 or less here, the server closed the connection and
275
we bail out from this! */
276
else if (0 >= nread) {
277
k->keepon &= ~KEEP_READ;
278
FD_ZERO(&k->rkeepfd);
283
/* Default buffer to use when we write the buffer, it may be changed
284
in the flow below before the actual storing is done. */
287
/* Since this is a two-state thing, we check if we are parsing
288
headers at the moment or not. */
290
/* we are in parse-the-header-mode */
291
bool stop_reading = FALSE;
293
/* header line within buffer loop */
300
/* str_start is start of line within buf */
301
k->str_start = k->str;
303
k->end_ptr = strchr (k->str_start, '\n');
306
/* Not a complete header line within buffer, append the data to
307
the end of the headerbuff. */
309
if (k->hbuflen + nread >= data->state.headersize) {
310
/* We enlarge the header buffer as it is too small */
312
long newsize=CURLMAX((k->hbuflen+nread)*3/2,
313
data->state.headersize*2);
314
hbufp_index = k->hbufp - data->state.headerbuff;
315
newbuff = (char *)realloc(data->state.headerbuff, newsize);
317
failf (data, "Failed to alloc memory for big header!");
318
return CURLE_OUT_OF_MEMORY;
320
data->state.headersize=newsize;
321
data->state.headerbuff = newbuff;
322
k->hbufp = data->state.headerbuff + hbufp_index;
324
memcpy(k->hbufp, k->str, nread);
327
if (!k->headerline && (k->hbuflen>5)) {
328
/* make a first check that this looks like a HTTP header */
329
if(!checkhttpprefix(data, data->state.headerbuff)) {
330
/* this is not the beginning of a HTTP first header line */
332
k->badheader = HEADER_ALLBAD;
337
break; /* read more and try again */
340
/* decrease the size of the remaining (supposed) header line */
341
rest_length = (k->end_ptr - k->str)+1;
342
nread -= rest_length;
344
k->str = k->end_ptr + 1; /* move past new line */
346
full_length = k->str - k->str_start;
234
* We enlarge the header buffer if it seems to be too
349
* We're about to copy a chunk of data to the end of the
350
* already received header. We make sure that the full string
351
* fit in the allocated header buffer, or else we enlarge
237
if (k->hbuflen + (int)str_length >=
354
if (k->hbuflen + full_length >=
238
355
data->state.headersize) {
240
long newsize=MAX((k->hbuflen+str_length)*3/2,
241
data->state.headersize*2);
357
long newsize=CURLMAX((k->hbuflen+full_length)*3/2,
358
data->state.headersize*2);
242
359
hbufp_index = k->hbufp - data->state.headerbuff;
243
360
newbuff = (char *)realloc(data->state.headerbuff, newsize);
245
362
failf (data, "Failed to alloc memory for big header!");
246
return CURLE_READ_ERROR;
363
return CURLE_OUT_OF_MEMORY;
248
data->state.headersize=newsize;
365
data->state.headersize= newsize;
249
366
data->state.headerbuff = newbuff;
250
367
k->hbufp = data->state.headerbuff + hbufp_index;
252
strcpy (k->hbufp, k->str);
253
k->hbufp += strlen (k->str);
254
k->hbuflen += strlen (k->str);
255
break; /* read more and try again */
258
k->str = k->end_ptr + 1; /* move past new line */
261
* We're about to copy a chunk of data to the end of the
262
* already received header. We make sure that the full string
263
* fit in the allocated header buffer, or else we enlarge
266
if (k->hbuflen + (k->str - k->str_start) >=
267
data->state.headersize) {
269
long newsize=MAX((k->hbuflen+
270
(k->str-k->str_start))*3/2,
271
data->state.headersize*2);
272
hbufp_index = k->hbufp - data->state.headerbuff;
273
newbuff = (char *)realloc(data->state.headerbuff, newsize);
275
failf (data, "Failed to alloc memory for big header!");
276
return CURLE_READ_ERROR;
370
/* copy to end of line */
371
strncpy (k->hbufp, k->str_start, full_length);
372
k->hbufp += full_length;
373
k->hbuflen += full_length;
375
k->end_ptr = k->hbufp;
377
k->p = data->state.headerbuff;
380
* We now have a FULL header line that p points to
384
/* the first read header */
386
!checkhttpprefix(data, data->state.headerbuff)) {
387
/* this is not the beginning of a HTTP first header line */
390
/* since there's more, this is a partial bad header */
391
k->badheader = HEADER_PARTHEADER;
393
/* this was all we read so its all a bad header */
394
k->badheader = HEADER_ALLBAD;
278
data->state.headersize= newsize;
279
data->state.headerbuff = newbuff;
280
k->hbufp = data->state.headerbuff + hbufp_index;
283
/* copy to end of line */
284
strncpy (k->hbufp, k->str_start, k->str - k->str_start);
285
k->hbufp += k->str - k->str_start;
286
k->hbuflen += k->str - k->str_start;
289
k->p = data->state.headerbuff;
292
* We now have a FULL header line that p points to
295
if (('\n' == *k->p) || ('\r' == *k->p)) {
296
/* Zero-length header line means end of headers! */
299
k->p++; /* pass the \r byte */
301
k->p++; /* pass the \n byte */
303
if(100 == k->httpcode) {
305
* we have made a HTTP PUT or POST and this is 1.1-lingo
306
* that tells us that the server is OK with this and ready
307
* to receive our stuff.
308
* However, we'll get more headers now so we must get
309
* back into the header-parsing state!
312
k->headerline = 0; /* restart the header line counter */
313
/* if we did wait for this do enable write now! */
314
if (k->write_after_100_header) {
401
if (('\n' == *k->p) || ('\r' == *k->p)) {
403
/* Zero-length header line means end of headers! */
406
k->p++; /* pass the \r byte */
408
k->p++; /* pass the \n byte */
410
if(100 == k->httpcode) {
412
* We have made a HTTP PUT or POST and this is 1.1-lingo
413
* that tells us that the server is OK with this and ready
414
* to receive the data.
415
* However, we'll get more headers now so we must get
416
* back into the header-parsing state!
419
k->headerline = 0; /* restart the header line counter */
420
/* if we did wait for this do enable write now! */
421
if (k->write_after_100_header) {
423
k->write_after_100_header = FALSE;
424
FD_SET (conn->writesockfd, &k->writefd); /* write */
425
k->keepon |= KEEP_WRITE;
426
k->wkeepfd = k->writefd;
430
k->header = FALSE; /* no more header to parse! */
432
if (417 == k->httpcode) {
434
* we got: "417 Expectation Failed" this means:
435
* we have made a HTTP call and our Expect Header
436
* seems to cause a problem => abort the write operations
437
* (or prevent them from starting).
316
439
k->write_after_100_header = FALSE;
317
FD_SET (conn->writesockfd, &k->writefd); /* write */
318
k->keepon |= KEEP_WRITE;
319
k->wkeepfd = k->writefd;
323
k->header = FALSE; /* no more header to parse! */
325
if (417 == k->httpcode) {
327
* we got: "417 Expectation Failed" this means:
328
* we have made a HTTP call and our Expect Header
329
* seems to cause a problem => abort the write operations
330
* (or prevent them from starting
332
k->write_after_100_header = FALSE;
333
k->keepon &= ~KEEP_WRITE;
334
FD_ZERO(&k->wkeepfd);
337
/* now, only output this if the header AND body are requested:
339
k->writetype = CLIENTWRITE_HEADER;
340
if (data->set.http_include_header)
341
k->writetype |= CLIENTWRITE_BODY;
343
result = Curl_client_write(data, k->writetype,
344
data->state.headerbuff,
345
k->p - data->state.headerbuff);
349
data->info.header_size += k->p - data->state.headerbuff;
350
conn->headerbytecount += k->p - data->state.headerbuff;
354
* really end-of-headers.
356
* If we requested a "no body", this is a good time to get
357
* out and return home.
359
bool stop_reading = FALSE;
361
if(data->set.no_body)
363
else if(!conn->bits.close) {
364
/* If this is not the last request before a close, we must
365
set the maximum download size to the size of the
366
expected document or else, we won't know when to stop
440
k->keepon &= ~KEEP_WRITE;
441
FD_ZERO(&k->wkeepfd);
445
** Now that all of the headers have been parsed, see
446
** if we should give up and return an error.
448
if (Curl_http_should_fail(conn)) {
449
failf (data, "The requested URL returned error: %d",
451
return CURLE_HTTP_RETURNED_ERROR;
454
/* now, only output this if the header AND body are requested:
456
writetype = CLIENTWRITE_HEADER;
457
if (data->set.include_header)
458
writetype |= CLIENTWRITE_BODY;
460
headerlen = k->p - data->state.headerbuff;
462
result = Curl_client_write(data, writetype,
463
data->state.headerbuff,
468
data->info.header_size += headerlen;
469
conn->headerbytecount += headerlen;
471
conn->deductheadercount =
472
(100 == k->httpcode)?conn->headerbytecount:0;
474
if (conn->resume_from &&
476
(data->set.httpreq==HTTPREQ_GET)) {
477
if(k->httpcode == 416) {
478
/* "Requested Range Not Satisfiable" */
482
/* we wanted to resume a download, although the server
483
doesn't seem to support this and we did this with a GET
484
(if it wasn't a GET we did a POST or PUT resume) */
485
failf (data, "HTTP server doesn't seem to support "
486
"byte ranges. Cannot resume.");
487
return CURLE_HTTP_RANGE_ERROR;
492
/* *auth_act() checks what authentication methods that are
493
available and decides which one (if any) to use. It will
494
set 'newurl' if an auth metod was picked. */
495
Curl_http_auth_act(conn);
499
* really end-of-headers.
501
* If we requested a "no body", this is a good time to get
502
* out and return home.
504
if(conn->bits.no_body)
507
/* If we know the expected size of this document, we set the
508
maximum download size to the size of the expected
509
document or else, we won't know when to stop reading!
511
Note that we set the download maximum even if we read a
512
"Connection: close" header, to make sure that
513
"Content-Length: 0" still prevents us from attempting to
514
read the (missing) response-body.
516
/* According to RFC2616 section 4.4, we MUST ignore
517
Content-Length: headers if we are now receiving data
518
using chunked Transfer-Encoding.
524
if(-1 != conn->size) {
525
/* We do this operation even if no_body is true, since this
526
data might be retrieved later with curl_easy_getinfo()
527
and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
529
Curl_pgrsSetDownloadSize(data, conn->size);
369
530
conn->maxdownload = conn->size;
371
532
/* If max download size is *zero* (nothing) we already
372
533
have nothing and can safely return ok now! */
373
534
if(0 == conn->maxdownload)
374
535
stop_reading = TRUE;
376
/* What to do if the size is *not* known? */
380
/* we make sure that this socket isn't read more now */
381
k->keepon &= ~KEEP_READ;
382
FD_ZERO(&k->rkeepfd);
383
/* for a progress meter/info update before going away */
384
Curl_pgrsUpdate(conn);
388
break; /* exit header line loop */
391
/* We continue reading headers, so reset the line-based
392
header parsing variables hbufp && hbuflen */
393
k->hbufp = data->state.headerbuff;
399
* Checks for special headers coming up.
402
if (!k->headerline++) {
403
/* This is the first header, it MUST be the error code line
404
or else we consiser this to be the body right away! */
405
int httpversion_major;
406
int nc=sscanf (k->p, " HTTP/%d.%d %3d",
411
k->httpversion += 10 * httpversion_major;
414
/* this is the real world, not a Nirvana
415
NCSA 1.5.x returns this crap when asked for HTTP/1.1
417
nc=sscanf (k->p, " HTTP %3d", &k->httpcode);
422
data->info.httpcode = k->httpcode;
423
data->info.httpversion = k->httpversion;
425
/* 404 -> URL not found! */
426
if (data->set.http_fail_on_error &&
427
(k->httpcode >= 400)) {
428
/* If we have been told to fail hard on HTTP-errors,
429
here is the check for that: */
430
/* serious error, go home! */
431
failf (data, "The requested file was not found");
432
return CURLE_HTTP_NOT_FOUND;
435
if(k->httpversion == 10)
436
/* Default action for HTTP/1.0 must be to close, unless
437
we get one of those fancy headers that tell us the
438
server keeps it open for us! */
439
conn->bits.close = TRUE;
441
switch(k->httpcode) {
443
/* (quote from RFC2616, section 10.2.5): The server has
444
* fulfilled the request but does not need to return an
445
* entity-body ... The 204 response MUST NOT include a
446
* message-body, and thus is always terminated by the first
447
* empty line after the header fields. */
450
/* (quote from RFC2616, section 10.3.5): The 304 response MUST
451
* NOT contain a message-body, and thus is always terminated
452
* by the first empty line after the header fields. */
461
k->header = FALSE; /* this is not a header line */
465
/* check for Content-Length: header lines to get size */
466
if (strnequal("Content-Length:", k->p, 15) &&
467
sscanf (k->p+15, " %ld", &k->contentlength)) {
468
conn->size = k->contentlength;
469
Curl_pgrsSetDownloadSize(data, k->contentlength);
471
/* check for Content-Type: header lines to get the mime-type */
472
else if (strnequal("Content-Type:", k->p, 13)) {
477
/* Find the first non-space letter */
479
*start && isspace((int)*start);
482
/* count all non-space letters following */
483
for(end=start, len=0;
484
*end && !isspace((int)*end);
487
/* allocate memory of a cloned copy */
488
data->info.contenttype = malloc(len + 1);
489
if (NULL == data->info.contenttype)
490
return CURLE_OUT_OF_MEMORY;
492
/* copy the content-type string */
493
memcpy(data->info.contenttype, start, len);
494
data->info.contenttype[len] = 0; /* zero terminate */
496
else if((k->httpversion == 10) &&
497
conn->bits.httpproxy &&
498
compareheader(k->p, "Proxy-Connection:", "keep-alive")) {
500
* When a HTTP/1.0 reply comes when using a proxy, the
501
* 'Proxy-Connection: keep-alive' line tells us the
502
* connection will be kept alive for our pleasure.
503
* Default action for 1.0 is to close.
505
conn->bits.close = FALSE; /* don't close when done */
506
infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
508
else if((k->httpversion == 10) &&
509
compareheader(k->p, "Connection:", "keep-alive")) {
511
* A HTTP/1.0 reply with the 'Connection: keep-alive' line
512
* tells us the connection will be kept alive for our
513
* pleasure. Default action for 1.0 is to close.
515
* [RFC2068, section 19.7.1] */
516
conn->bits.close = FALSE; /* don't close when done */
517
infof(data, "HTTP/1.0 connection set to keep alive!\n");
519
else if (compareheader(k->p, "Connection:", "close")) {
521
* [RFC 2616, section 8.1.2.1]
522
* "Connection: close" is HTTP/1.1 language and means that
523
* the connection will close when this request has been
526
conn->bits.close = TRUE; /* close when done */
528
else if (compareheader(k->p, "Transfer-Encoding:", "chunked")) {
530
* [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
531
* means that the server will send a series of "chunks". Each
532
* chunk starts with line with info (including size of the
533
* coming block) (terminated with CRLF), then a block of data
534
* with the previously mentioned size. There can be any amount
535
* of chunks, and a chunk-data set to zero signals the
537
conn->bits.chunk = TRUE; /* chunks coming our way */
539
/* init our chunky engine */
540
Curl_httpchunk_init(conn);
542
else if (strnequal("Content-Range:", k->p, 14)) {
543
if (sscanf (k->p+14, " bytes %d-", &k->offset) ||
544
sscanf (k->p+14, " bytes: %d-", &k->offset)) {
545
/* This second format was added August 1st 2000 by Igor
538
/* we make sure that this socket isn't read more now */
539
k->keepon &= ~KEEP_READ;
540
FD_ZERO(&k->rkeepfd);
543
break; /* exit header line loop */
546
/* We continue reading headers, so reset the line-based
547
header parsing variables hbufp && hbuflen */
548
k->hbufp = data->state.headerbuff;
554
* Checks for special headers coming up.
557
if (!k->headerline++) {
558
/* This is the first header, it MUST be the error code line
559
or else we consiser this to be the body right away! */
560
int httpversion_major;
561
int nc=sscanf(k->p, " HTTP/%d.%d %3d",
566
k->httpversion += 10 * httpversion_major;
569
/* this is the real world, not a Nirvana
570
NCSA 1.5.x returns this crap when asked for HTTP/1.1
572
nc=sscanf(k->p, " HTTP %3d", &k->httpcode);
575
/* If user has set option HTTP200ALIASES,
576
compare header line against list of aliases
579
if (checkhttpprefix(data, k->p)) {
583
(data->set.httpversion==CURL_HTTP_VERSION_1_0)? 10 : 11;
589
data->info.httpcode = k->httpcode;
590
data->info.httpversion = k->httpversion;
593
** This code executes as part of processing
594
** the header. As a result, it's not
595
** totally clear how to interpret the
596
** response code yet as that depends on what
597
** other headers may be present. 401 and
598
** 407 may be errors, but may be OK
599
** depending on how authentication is
600
** working. Other codes are definitely
601
** errors, so give up here.
603
if (data->set.http_fail_on_error &&
604
(k->httpcode >= 400) &&
605
(k->httpcode != 401) &&
606
(k->httpcode != 407)) {
607
/* If we have been told to fail hard on HTTP-errors,
608
here is the check for that: */
609
/* serious error, go home! */
610
failf (data, "The requested URL returned error: %d",
612
return CURLE_HTTP_RETURNED_ERROR;
615
if(k->httpversion == 10)
616
/* Default action for HTTP/1.0 must be to close, unless
617
we get one of those fancy headers that tell us the
618
server keeps it open for us! */
619
conn->bits.close = TRUE;
621
switch(k->httpcode) {
623
/* (quote from RFC2616, section 10.2.5): The server has
624
* fulfilled the request but does not need to return an
625
* entity-body ... The 204 response MUST NOT include a
626
* message-body, and thus is always terminated by the first
627
* empty line after the header fields. */
629
case 416: /* Requested Range Not Satisfiable, it has the
630
Content-Length: set as the "real" document but no
631
actual response is sent. */
633
/* (quote from RFC2616, section 10.3.5): The 304 response
634
* MUST NOT contain a message-body, and thus is always
635
* terminated by the first empty line after the header
646
k->header = FALSE; /* this is not a header line */
651
/* Check for Content-Length: header lines to get size. Ignore
652
the header completely if we get a 416 response as then we're
653
resuming a document that we don't get, and this header contains
654
info about the true size of the document we didn't get now. */
655
if ((k->httpcode != 416) &&
656
checkprefix("Content-Length:", k->p)) {
657
contentlength = curlx_strtoofft(k->p+15, NULL, 10);
658
if (data->set.max_filesize && contentlength >
659
data->set.max_filesize) {
660
failf(data, "Maximum file size exceeded");
661
return CURLE_FILESIZE_EXCEEDED;
663
conn->size = contentlength;
665
/* check for Content-Type: header lines to get the mime-type */
666
else if (checkprefix("Content-Type:", k->p)) {
671
/* Find the first non-space letter */
673
*start && isspace((int)*start);
676
end = strchr(start, '\r');
678
end = strchr(start, '\n');
681
/* skip all trailing space letters */
682
for(; isspace((int)*end) && (end > start); end--);
684
/* get length of the type */
687
/* allocate memory of a cloned copy */
688
Curl_safefree(data->info.contenttype);
690
data->info.contenttype = malloc(len + 1);
691
if (NULL == data->info.contenttype)
692
return CURLE_OUT_OF_MEMORY;
694
/* copy the content-type string */
695
memcpy(data->info.contenttype, start, len);
696
data->info.contenttype[len] = 0; /* zero terminate */
699
else if((k->httpversion == 10) &&
700
conn->bits.httpproxy &&
701
Curl_compareheader(k->p,
702
"Proxy-Connection:", "keep-alive")) {
704
* When a HTTP/1.0 reply comes when using a proxy, the
705
* 'Proxy-Connection: keep-alive' line tells us the
706
* connection will be kept alive for our pleasure.
707
* Default action for 1.0 is to close.
709
conn->bits.close = FALSE; /* don't close when done */
710
infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
712
else if((k->httpversion == 10) &&
713
Curl_compareheader(k->p, "Connection:", "keep-alive")) {
715
* A HTTP/1.0 reply with the 'Connection: keep-alive' line
716
* tells us the connection will be kept alive for our
717
* pleasure. Default action for 1.0 is to close.
719
* [RFC2068, section 19.7.1] */
720
conn->bits.close = FALSE; /* don't close when done */
721
infof(data, "HTTP/1.0 connection set to keep alive!\n");
723
else if (Curl_compareheader(k->p, "Connection:", "close")) {
725
* [RFC 2616, section 8.1.2.1]
726
* "Connection: close" is HTTP/1.1 language and means that
727
* the connection will close when this request has been
730
conn->bits.close = TRUE; /* close when done */
732
else if (Curl_compareheader(k->p,
733
"Transfer-Encoding:", "chunked")) {
735
* [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
736
* means that the server will send a series of "chunks". Each
737
* chunk starts with line with info (including size of the
738
* coming block) (terminated with CRLF), then a block of data
739
* with the previously mentioned size. There can be any amount
740
* of chunks, and a chunk-data set to zero signals the
742
conn->bits.chunk = TRUE; /* chunks coming our way */
744
/* init our chunky engine */
745
Curl_httpchunk_init(conn);
747
else if (checkprefix("Content-Encoding:", k->p) &&
748
data->set.encoding) {
750
* Process Content-Encoding. Look for the values: identity,
751
* gzip, deflate, compress, x-gzip and x-compress. x-gzip and
752
* x-compress are the same as gzip and compress. (Sec 3.5 RFC
753
* 2616). zlib cannot handle compress. However, errors are
754
* handled further down when the response body is processed
758
/* Find the first non-space letter */
760
*start && isspace((int)*start);
763
/* Record the content-encoding for later use */
764
if (checkprefix("identity", start))
765
k->content_encoding = IDENTITY;
766
else if (checkprefix("deflate", start))
767
k->content_encoding = DEFLATE;
768
else if (checkprefix("gzip", start)
769
|| checkprefix("x-gzip", start))
770
k->content_encoding = GZIP;
771
else if (checkprefix("compress", start)
772
|| checkprefix("x-compress", start))
773
k->content_encoding = COMPRESS;
775
else if (Curl_compareheader(k->p, "Content-Range:", "bytes")) {
776
/* Content-Range: bytes [num]-
777
Content-Range: bytes: [num]-
779
The second format was added August 1st 2000 by Igor
546
780
Khristophorov since Sun's webserver JavaWebServer/1.1.1
547
781
obviously sends the header this way! :-( */
548
if (conn->resume_from == k->offset) {
783
char *ptr = strstr(k->p, "bytes");
787
/* stupid colon skip */
790
k->offset = curlx_strtoofft(ptr, NULL, 10);
792
if (conn->resume_from == k->offset)
549
793
/* we asked for a resume and we got it */
550
794
k->content_range = TRUE;
554
else if(data->cookies &&
555
strnequal("Set-Cookie:", k->p, 11)) {
556
Curl_cookie_add(data->cookies, TRUE, k->p+12, conn->name);
558
else if(strnequal("Last-Modified:", k->p,
559
strlen("Last-Modified:")) &&
560
(data->set.timecondition || data->set.get_filetime) ) {
561
time_t secs=time(NULL);
562
k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
564
if(data->set.get_filetime)
565
data->info.filetime = k->timeofdoc;
567
else if ((k->httpcode >= 300 && k->httpcode < 400) &&
568
(data->set.http_follow_location) &&
569
strnequal("Location:", k->p, 9)) {
570
/* this is the URL that the server advices us to get instead */
575
start += 9; /* pass "Location:" */
577
/* Skip spaces and tabs. We do this to support multiple
578
white spaces after the "Location:" keyword. */
579
while(*start && isspace((int)*start ))
581
ptr = start; /* start scanning here */
583
/* scan through the string to find the end */
584
while(*ptr && !isspace((int)*ptr))
586
backup = *ptr; /* store the ending letter */
587
*ptr = '\0'; /* zero terminate */
588
conn->newurl = strdup(start); /* clone string */
589
*ptr = backup; /* restore ending letter */
593
* End of header-checks. Write them to the client.
596
k->writetype = CLIENTWRITE_HEADER;
597
if (data->set.http_include_header)
598
k->writetype |= CLIENTWRITE_BODY;
600
result = Curl_client_write(data, k->writetype, k->p,
605
data->info.header_size += k->hbuflen;
606
conn->headerbytecount += k->hbuflen;
796
else if(data->cookies &&
797
checkprefix("Set-Cookie:", k->p)) {
798
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
799
CURL_LOCK_ACCESS_SINGLE);
800
Curl_cookie_add(data,
801
data->cookies, TRUE, k->p+11,
802
/* If there is a custom-set Host: name, use it
803
here, or else use real peer host name. */
804
conn->allocptr.cookiehost?
805
conn->allocptr.cookiehost:conn->hostname,
807
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
809
else if(checkprefix("Last-Modified:", k->p) &&
810
(data->set.timecondition || data->set.get_filetime) ) {
811
time_t secs=time(NULL);
812
k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
814
if(data->set.get_filetime)
815
data->info.filetime = k->timeofdoc;
817
else if((checkprefix("WWW-Authenticate:", k->p) &&
818
(401 == k->httpcode)) ||
819
(checkprefix("Proxy-authenticate:", k->p) &&
820
(407 == k->httpcode))) {
821
result = Curl_http_auth(conn, k->httpcode, k->p);
825
else if ((k->httpcode >= 300 && k->httpcode < 400) &&
826
checkprefix("Location:", k->p)) {
827
if(data->set.http_follow_location) {
828
/* this is the URL that the server advices us to get instead */
833
start += 9; /* pass "Location:" */
835
/* Skip spaces and tabs. We do this to support multiple
836
white spaces after the "Location:" keyword. */
837
while(*start && isspace((int)*start ))
840
/* Scan through the string from the end to find the last
841
non-space. k->end_ptr points to the actual terminating zero
842
letter, move pointer one letter back and start from
843
there. This logic strips off trailing whitespace, but keeps
844
any embedded whitespace. */
846
while((ptr>=start) && isspace((int)*ptr))
850
backup = *ptr; /* store the ending letter */
852
*ptr = '\0'; /* zero terminate */
853
conn->newurl = strdup(start); /* clone string */
854
*ptr = backup; /* restore ending letter */
857
#if 0 /* for consideration */
859
/* This is a Location: but we have not been instructed to
861
infof(data, "We ignore this location header as instructed\n");
867
* End of header-checks. Write them to the client.
870
writetype = CLIENTWRITE_HEADER;
871
if (data->set.include_header)
872
writetype |= CLIENTWRITE_BODY;
874
if(data->set.verbose)
875
Curl_debug(data, CURLINFO_HEADER_IN,
878
result = Curl_client_write(data, writetype, k->p, k->hbuflen);
882
data->info.header_size += k->hbuflen;
883
conn->headerbytecount += k->hbuflen;
608
/* reset hbufp pointer && hbuflen */
609
k->hbufp = data->state.headerbuff;
612
while (*k->str); /* header line within buffer */
614
/* We might have reached the end of the header part here, but
615
there might be a non-header part left in the end of the read
619
/* the next token and forward is not part of
622
/* we subtract the remaining header size from the buffer */
623
nread -= (k->str - k->buf);
626
} /* end if header mode */
628
/* This is not an 'else if' since it may be a rest from the header
629
parsing, where the beginning of the buffer is headers and the end
631
if (k->str && !k->header && (nread > 0)) {
885
/* reset hbufp pointer && hbuflen */
886
k->hbufp = data->state.headerbuff;
889
while (!stop_reading && *k->str); /* header line within buffer */
892
/* We've stopped dealing with input, get out of the do-while loop */
895
/* We might have reached the end of the header part here, but
896
there might be a non-header part left in the end of the read
899
} /* end if header mode */
901
/* This is not an 'else if' since it may be a rest from the header
902
parsing, where the beginning of the buffer is headers and the end
904
if (k->str && !k->header && (nread > 0)) {
633
if(0 == k->bodywrites) {
634
/* These checks are only made the first time we are about to
635
write a piece of the body */
636
if(conn->protocol&PROT_HTTP) {
637
/* HTTP-only checks */
639
/* abort after the headers if "follow Location" is set */
640
infof (data, "Follow to new URL: %s\n", conn->newurl);
641
k->keepon &= ~KEEP_READ;
642
FD_ZERO(&k->rkeepfd);
645
else if (conn->resume_from &&
647
(data->set.httpreq==HTTPREQ_GET)) {
648
/* we wanted to resume a download, although the server
649
doesn't seem to support this and we did this with a GET
650
(if it wasn't a GET we did a POST or PUT resume) */
651
failf (data, "HTTP server doesn't seem to support "
652
"byte ranges. Cannot resume.");
653
return CURLE_HTTP_RANGE_ERROR;
655
else if(data->set.timecondition && !conn->range) {
656
/* A time condition has been set AND no ranges have been
657
requested. This seems to be what chapter 13.3.4 of
658
RFC 2616 defines to be the correct action for a
660
if((k->timeofdoc > 0) && (data->set.timevalue > 0)) {
661
switch(data->set.timecondition) {
662
case TIMECOND_IFMODSINCE:
664
if(k->timeofdoc < data->set.timevalue) {
666
"The requested document is not new enough\n");
670
case TIMECOND_IFUNMODSINCE:
671
if(k->timeofdoc > data->set.timevalue) {
673
"The requested document is not old enough\n");
678
} /* two valid time strings */
679
} /* we have a time condition */
682
} /* this is the first time we write a body part */
685
if(conn->bits.chunk) {
687
* Bless me father for I have sinned. Here comes a chunked
688
* transfer flying and we need to decode this properly. While
689
* the name says read, this function both reads and writes away
690
* the data. The returned 'nread' holds the number of actual
691
* data it wrote to the client. */
693
Curl_httpchunk_read(conn, k->str, nread, &nread);
695
if(CHUNKE_OK < res) {
696
failf(data, "Receeived problem in the chunky parser");
697
return CURLE_READ_ERROR;
699
else if(CHUNKE_STOP == res) {
700
/* we're done reading chunks! */
701
k->keepon &= ~KEEP_READ; /* read no more */
906
if(0 == k->bodywrites) {
907
/* These checks are only made the first time we are about to
908
write a piece of the body */
909
if(conn->protocol&PROT_HTTP) {
910
/* HTTP-only checks */
913
if(conn->bits.close) {
914
/* Abort after the headers if "follow Location" is set
915
and we're set to close anyway. */
916
k->keepon &= ~KEEP_READ;
917
FD_ZERO(&k->rkeepfd);
921
/* We have a new url to load, but since we want to be able
922
to re-use this connection properly, we read the full
923
response in "ignore more" */
924
k->ignorebody = TRUE;
925
infof(data, "Ignoring the response-body\n");
927
if(data->set.timecondition && !conn->range) {
928
/* A time condition has been set AND no ranges have been
929
requested. This seems to be what chapter 13.3.4 of
930
RFC 2616 defines to be the correct action for a
932
if((k->timeofdoc > 0) && (data->set.timevalue > 0)) {
933
switch(data->set.timecondition) {
934
case CURL_TIMECOND_IFMODSINCE:
936
if(k->timeofdoc < data->set.timevalue) {
938
"The requested document is not new enough\n");
943
case CURL_TIMECOND_IFUNMODSINCE:
944
if(k->timeofdoc > data->set.timevalue) {
946
"The requested document is not old enough\n");
952
} /* two valid time strings */
953
} /* we have a time condition */
956
} /* this is the first time we write a body part */
959
/* pass data to the debug function before it gets "dechunked" */
960
if(data->set.verbose) {
962
Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff,
964
if(k->badheader == HEADER_PARTHEADER)
965
Curl_debug(data, CURLINFO_DATA_IN, k->str, nread);
968
Curl_debug(data, CURLINFO_DATA_IN, k->str, nread);
971
if(conn->bits.chunk) {
973
* Bless me father for I have sinned. Here comes a chunked
974
* transfer flying and we need to decode this properly. While
975
* the name says read, this function both reads and writes away
976
* the data. The returned 'nread' holds the number of actual
977
* data it wrote to the client. */
979
Curl_httpchunk_read(conn, k->str, nread, &nread);
981
if(CHUNKE_OK < res) {
982
if(CHUNKE_WRITE_ERROR == res) {
983
failf(data, "Failed writing data");
984
return CURLE_WRITE_ERROR;
986
failf(data, "Received problem %d in the chunky parser", res);
987
return CURLE_RECV_ERROR;
989
else if(CHUNKE_STOP == res) {
990
/* we're done reading chunks! */
991
k->keepon &= ~KEEP_READ; /* read no more */
992
FD_ZERO(&k->rkeepfd);
994
/* There are now possibly N number of bytes at the end of the
995
str buffer that weren't written to the client, but we don't
996
care about them right now. */
998
/* If it returned OK, we just keep going */
1001
if((-1 != conn->maxdownload) &&
1002
(k->bytecount + nread >= conn->maxdownload)) {
1003
nread = (ssize_t) (conn->maxdownload - k->bytecount);
1004
if(nread < 0 ) /* this should be unusual */
1007
k->keepon &= ~KEEP_READ; /* we're done reading */
702
1008
FD_ZERO(&k->rkeepfd);
704
/* There are now possibly N number of bytes at the end of the
705
str buffer that weren't written to the client, but we don't
706
care about them right now. */
708
/* If it returned OK, we just keep going */
711
if((-1 != conn->maxdownload) &&
712
(k->bytecount + nread >= conn->maxdownload)) {
713
nread = conn->maxdownload - k->bytecount;
714
if(nread < 0 ) /* this should be unusual */
717
k->keepon &= ~KEEP_READ; /* we're done reading */
718
FD_ZERO(&k->rkeepfd);
721
k->bytecount += nread;
723
Curl_pgrsSetDownloadCounter(data, (double)k->bytecount);
1011
k->bytecount += nread;
1013
Curl_pgrsSetDownloadCounter(data, k->bytecount);
725
if(!conn->bits.chunk && nread) {
726
/* If this is chunky transfer, it was already written */
727
result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
733
} /* if (! header and data to read ) */
1015
if(!conn->bits.chunk && (nread || k->badheader)) {
1016
/* If this is chunky transfer, it was already written */
1018
if(k->badheader && !k->ignorebody) {
1019
/* we parsed a piece of data wrongly assuming it was a header
1020
and now we output it as body instead */
1021
result = Curl_client_write(data, CLIENTWRITE_BODY,
1022
data->state.headerbuff,
1025
if(k->badheader < HEADER_ALLBAD) {
1026
/* This switch handles various content encodings. If there's an
1027
error here, be sure to check over the almost identical code
1029
Make sure that ALL_CONTENT_ENCODINGS contains all the
1030
encodings handled here. */
1032
switch (k->content_encoding) {
1035
/* This is the default when the server sends no
1036
Content-Encoding header. See Curl_readwrite_init; the
1037
memset() call initializes k->content_encoding to zero. */
1039
result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
1045
/* Assume CLIENTWRITE_BODY; headers are not encoded. */
1046
result = Curl_unencode_deflate_write(data, k, nread);
1050
/* Assume CLIENTWRITE_BODY; headers are not encoded. */
1051
result = Curl_unencode_gzip_write(data, k, nread);
1056
failf (data, "Unrecognized content encoding type. "
1057
"libcurl understands `identity', `deflate' and `gzip' "
1058
"content encodings.");
1059
result = CURLE_BAD_CONTENT_ENCODING;
1064
k->badheader = HEADER_NORMAL; /* taken care of now */
1070
} /* if (! header and data to read ) */
734
1074
} /* if( read from socket ) */
1076
/* If we still have writing to do, we check if we have a writable
1077
socket. Sometimes the writefdp is NULL, if no fd_set was done using
1078
the multi interface and then we can do nothing but to attempt a
1079
write to be sure. */
736
1080
if((k->keepon & KEEP_WRITE) &&
737
FD_ISSET(conn->writesockfd, &k->writefd)) {
1081
(!writefdp || FD_ISSET(conn->writesockfd, writefdp)) ) {
741
1085
ssize_t bytes_written;
1086
bool writedone=TRUE;
743
1088
if ((k->bytecount == 0) && (k->writebytecount == 0))
744
1089
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
746
1091
didwhat |= KEEP_WRITE;
748
/* only read more data if there's no upload data already
749
present in the upload buffer */
750
if(0 == conn->upload_present) {
751
/* init the "upload from here" pointer */
752
conn->upload_fromhere = k->uploadbuf;
754
nread = data->set.fread(conn->upload_fromhere, 1,
755
BUFSIZE, data->set.in);
757
/* the signed int typecase of nread of for systems that has
761
k->keepon &= ~KEEP_WRITE; /* we're done writing */
762
FD_ZERO(&k->wkeepfd);
766
/* store number of bytes available for upload */
767
conn->upload_present = nread;
769
/* convert LF to CRLF if so asked */
770
if (data->set.crlf) {
771
for(i = 0, si = 0; i < nread; i++, si++) {
772
if (k->buf[i] == 0x0a) {
773
data->state.scratch[si++] = 0x0d;
774
data->state.scratch[si] = 0x0a;
777
data->state.scratch[si] = k->uploadbuf[i];
781
k->buf = data->state.scratch; /* point to the new buffer */
785
/* We have a partial buffer left from a previous "round". Use
786
that instead of reading more data */
789
/* write to socket */
790
result = Curl_write(conn,
792
conn->upload_fromhere,
793
conn->upload_present,
797
else if(conn->upload_present != bytes_written) {
798
/* we only wrote a part of the buffer (if anything), deal with it! */
800
/* store the amount of bytes left in the buffer to write */
801
conn->upload_present -= bytes_written;
803
/* advance the pointer where to find the buffer when the next send
805
conn->upload_fromhere += bytes_written;
807
else if(data->set.crlf)
808
k->buf = data->state.buffer; /* put it back on the buffer */
810
/* we've uploaded that buffer now */
811
conn->upload_fromhere = k->uploadbuf;
812
conn->upload_present = 0; /* no more bytes left */
815
k->writebytecount += bytes_written;
816
Curl_pgrsSetUploadCounter(data, (double)k->writebytecount);
1094
* We loop here to do the READ and SEND loop until we run out of
1095
* data to send or until we get EWOULDBLOCK back
1099
/* only read more data if there's no upload data already
1100
present in the upload buffer */
1101
if(0 == conn->upload_present) {
1102
/* init the "upload from here" pointer */
1103
conn->upload_fromhere = k->uploadbuf;
1105
if(!k->upload_done) {
1106
/* HTTP pollution, this should be written nicer to become more
1107
protocol agnostic. */
1109
if(k->wait100_after_headers &&
1110
(conn->proto.http->sending == HTTPSEND_BODY)) {
1111
/* If this call is to send body data, we must take some action:
1112
We have sent off the full HTTP 1.1 request, and we shall now
1113
go into the Expect: 100 state and await such a header */
1114
k->wait100_after_headers = FALSE; /* headers sent */
1115
k->write_after_100_header = TRUE; /* wait for the header */
1116
FD_ZERO (&k->writefd); /* clear it */
1117
k->wkeepfd = k->writefd; /* set the keeper variable */
1118
k->keepon &= ~KEEP_WRITE; /* disable writing */
1119
k->start100 = Curl_tvnow(); /* timeout count starts now */
1120
didwhat &= ~KEEP_WRITE; /* we didn't write anything actually */
1124
nread = fillbuffer(conn, BUFSIZE);
1127
nread = 0; /* we're done uploading/reading */
1129
/* the signed int typecase of nread of for systems that has
1133
k->keepon &= ~KEEP_WRITE; /* we're done writing */
1134
FD_ZERO(&k->wkeepfd);
1139
/* store number of bytes available for upload */
1140
conn->upload_present = nread;
1142
/* convert LF to CRLF if so asked */
1143
if (data->set.crlf) {
1144
if(data->state.scratch == NULL)
1145
data->state.scratch = malloc(2*BUFSIZE);
1146
if(data->state.scratch == NULL) {
1147
failf (data, "Failed to alloc scratch buffer!");
1148
return CURLE_OUT_OF_MEMORY;
1150
for(i = 0, si = 0; i < nread; i++, si++) {
1151
if (conn->upload_fromhere[i] == 0x0a) {
1152
data->state.scratch[si++] = 0x0d;
1153
data->state.scratch[si] = 0x0a;
1156
data->state.scratch[si] = conn->upload_fromhere[i];
1159
/* only perform the special operation if we really did replace
1163
/* upload from the new (replaced) buffer instead */
1164
conn->upload_fromhere = data->state.scratch;
1166
/* set the new amount too */
1167
conn->upload_present = nread;
1172
/* We have a partial buffer left from a previous "round". Use
1173
that instead of reading more data */
1176
/* write to socket (send away data) */
1177
result = Curl_write(conn,
1178
conn->writesockfd, /* socket to send to */
1179
conn->upload_fromhere, /* buffer pointer */
1180
conn->upload_present, /* buffer size */
1181
&bytes_written); /* actually send away */
1185
if(data->set.verbose)
1186
/* show the data before we change the pointer upload_fromhere */
1187
Curl_debug(data, CURLINFO_DATA_OUT, conn->upload_fromhere,
1190
if(conn->upload_present != bytes_written) {
1191
/* we only wrote a part of the buffer (if anything), deal with it! */
1193
/* store the amount of bytes left in the buffer to write */
1194
conn->upload_present -= bytes_written;
1196
/* advance the pointer where to find the buffer when the next send
1198
conn->upload_fromhere += bytes_written;
1200
writedone = TRUE; /* we are done, stop the loop */
1203
/* we've uploaded that buffer now */
1204
conn->upload_fromhere = k->uploadbuf;
1205
conn->upload_present = 0; /* no more bytes left */
1207
if(k->upload_done) {
1208
/* switch off writing, we're done! */
1209
k->keepon &= ~KEEP_WRITE; /* we're done writing */
1210
FD_ZERO(&k->wkeepfd);
1215
k->writebytecount += bytes_written;
1216
Curl_pgrsSetUploadCounter(data, k->writebytecount);
1218
} while(!writedone); /* loop until we're done writing! */
820
1222
} while(0); /* just to break out from! */
1224
k->now = Curl_tvnow();
823
1226
/* Update read/write counters */
824
1227
if(conn->bytecountp)