5
5
* | (__| |_| | _ <| |___
6
6
* \___|\___/|_| \_\_____|
8
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
8
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
10
10
* This software is licensed as described in the file COPYING, which
11
11
* you should have received as part of this distribution. The terms
18
18
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
* KIND, either express or implied.
21
* $Id: http.c,v 1.344 2007-10-23 10:14:24 yangtse Exp $
21
* $Id: http.c,v 1.359 2008-01-25 23:33:45 bagder Exp $
22
22
***************************************************************************/
109
109
* Forward declarations.
112
static CURLcode Curl_https_connecting(struct connectdata *conn, bool *done);
112
static CURLcode https_connecting(struct connectdata *conn, bool *done);
114
static int Curl_https_getsock(struct connectdata *conn,
114
static int https_getsock(struct connectdata *conn,
115
115
curl_socket_t *socks,
146
146
Curl_http_done, /* done */
147
147
ZERO_NULL, /* do_more */
148
148
Curl_http_connect, /* connect_it */
149
Curl_https_connecting, /* connecting */
149
https_connecting, /* connecting */
150
150
ZERO_NULL, /* doing */
151
Curl_https_getsock, /* proto_getsock */
151
https_getsock, /* proto_getsock */
152
152
ZERO_NULL, /* doing_getsock */
153
153
ZERO_NULL, /* disconnect */
154
154
PORT_HTTPS, /* defport */
179
* Curl_output_basic() sets up an Authorization: header (or the proxy version)
179
* http_output_basic() sets up an Authorization: header (or the proxy version)
180
180
* for HTTP Basic authentication.
182
182
* Returns CURLcode.
184
static CURLcode Curl_output_basic(struct connectdata *conn, bool proxy)
184
static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
186
186
char *authorization;
187
187
struct SessionHandle *data=conn->data;
275
275
static CURLcode perhapsrewind(struct connectdata *conn)
277
277
struct SessionHandle *data = conn->data;
278
struct HTTP *http = data->reqdata.proto.http;
279
struct Curl_transfer_keeper *k = &data->reqdata.keep;
278
struct HTTP *http = data->state.proto.http;
280
279
curl_off_t bytessent;
281
280
curl_off_t expectsend = -1; /* default is unknown */
369
368
return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
371
370
if(conn->bits.user_passwd &&
372
((data->reqdata.keep.httpcode == 401) ||
373
(conn->bits.authneg && data->reqdata.keep.httpcode < 300))) {
371
((data->req.httpcode == 401) ||
372
(conn->bits.authneg && data->req.httpcode < 300))) {
374
373
pickhost = pickoneauth(&data->state.authhost);
376
375
data->state.authproblem = TRUE;
378
377
if(conn->bits.proxy_user_passwd &&
379
((data->reqdata.keep.httpcode == 407) ||
380
(conn->bits.authneg && data->reqdata.keep.httpcode < 300))) {
378
((data->req.httpcode == 407) ||
379
(conn->bits.authneg && data->req.httpcode < 300))) {
381
380
pickproxy = pickoneauth(&data->state.authproxy);
383
382
data->state.authproblem = TRUE;
386
385
if(pickhost || pickproxy) {
387
data->reqdata.newurl = strdup(data->change.url); /* clone URL */
388
if (!data->reqdata.newurl)
386
data->req.newurl = strdup(data->change.url); /* clone URL */
387
if(!data->req.newurl)
389
388
return CURLE_OUT_OF_MEMORY;
391
390
if((data->set.httpreq != HTTPREQ_GET) &&
406
405
we didn't try HEAD or GET */
407
406
if((data->set.httpreq != HTTPREQ_GET) &&
408
407
(data->set.httpreq != HTTPREQ_HEAD)) {
409
data->reqdata.newurl = strdup(data->change.url); /* clone URL */
410
if (!data->reqdata.newurl)
408
data->req.newurl = strdup(data->change.url); /* clone URL */
409
if(!data->req.newurl)
411
410
return CURLE_OUT_OF_MEMORY;
412
411
data->state.authhost.done = TRUE;
415
if (Curl_http_should_fail(conn)) {
414
if(Curl_http_should_fail(conn)) {
416
415
failf (data, "The requested URL returned error: %d",
417
data->reqdata.keep.httpcode);
418
417
code = CURLE_HTTP_RETURNED_ERROR;
436
435
* @returns CURLcode
439
Curl_http_output_auth(struct connectdata *conn,
442
bool proxytunnel) /* TRUE if this is the request setting
443
up the proxy tunnel */
438
http_output_auth(struct connectdata *conn,
441
bool proxytunnel) /* TRUE if this is the request setting
442
up the proxy tunnel */
445
444
CURLcode result = CURLE_OK;
446
445
struct SessionHandle *data = conn->data;
475
474
authproxy->picked = authproxy->want;
477
476
/* Send proxy authentication header if needed */
478
if (conn->bits.httpproxy &&
477
if(conn->bits.httpproxy &&
479
478
(conn->bits.tunnel_proxy == proxytunnel)) {
480
479
#ifdef HAVE_GSSAPI
481
480
if((authproxy->picked == CURLAUTH_GSSNEGOTIATE) &&
503
502
if(conn->bits.proxy_user_passwd &&
504
503
!checkheaders(data, "Proxy-authorization:")) {
506
result = Curl_output_basic(conn, TRUE);
505
result = http_output_basic(conn, TRUE);
510
/* NOTE: Curl_output_basic() should set 'done' TRUE, as the other auth
509
/* NOTE: http_output_basic() should set 'done' TRUE, as the other auth
511
510
functions work that way */
512
511
authproxy->done = TRUE;
654
653
#ifdef HAVE_GSSAPI
655
if (checkprefix("GSS-Negotiate", start) ||
654
if(checkprefix("GSS-Negotiate", start) ||
656
655
checkprefix("Negotiate", start)) {
657
656
*availp |= CURLAUTH_GSSNEGOTIATE;
658
657
authp->avail |= CURLAUTH_GSSNEGOTIATE;
659
658
if(authp->picked == CURLAUTH_GSSNEGOTIATE) {
660
659
/* if exactly this is wanted, go */
661
660
int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start);
663
data->reqdata.newurl = strdup(data->change.url);
664
data->state.authproblem = (data->reqdata.newurl == NULL);
662
data->req.newurl = strdup(data->change.url);
663
data->state.authproblem = (data->req.newurl == NULL);
667
666
infof(data, "Authentication problem. Ignoring this.\n");
743
742
int Curl_http_should_fail(struct connectdata *conn)
745
744
struct SessionHandle *data;
746
struct Curl_transfer_keeper *k;
748
747
DEBUGASSERT(conn);
749
748
data = conn->data;
750
749
DEBUGASSERT(data);
755
k = &data->reqdata.keep;
751
httpcode = data->req.httpcode;
758
754
** If we haven't been asked to fail on error,
761
if (!data->set.http_fail_on_error)
757
if(!data->set.http_fail_on_error)
765
761
** Any code < 400 is never terminal.
767
if (k->httpcode < 400)
770
if (data->reqdata.resume_from &&
771
(data->set.httpreq==HTTPREQ_GET) &&
772
(k->httpcode == 416)) {
766
if(data->state.resume_from &&
767
(data->set.httpreq==HTTPREQ_GET) &&
773
769
/* "Requested Range Not Satisfiable", just proceed and
774
770
pretend this is no error */
779
775
** Any code >= 400 that's not 401 or 407 is always
780
776
** a terminal error
782
if ((k->httpcode != 401) &&
783
(k->httpcode != 407))
778
if((httpcode != 401) &&
787
783
** All we have left to deal with is 401 and 407
789
DEBUGASSERT((k->httpcode == 401) || (k->httpcode == 407));
785
DEBUGASSERT((httpcode == 401) || (httpcode == 407));
792
788
** Examine the current authentication state to see if this
807
803
infof(data,"%s: authavail = 0x%08x\n",__FUNCTION__,data->state.authavail);
808
804
infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode);
809
805
infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone);
810
infof(data,"%s: newurl = %s\n",__FUNCTION__,data->reqdata.newurl ? data->reqdata.newurl : "(null)");
806
infof(data,"%s: newurl = %s\n",__FUNCTION__,data->req.newurl ?
807
data->req.newurl : "(null)");
811
808
infof(data,"%s: authproblem = %d\n",__FUNCTION__,data->state.authproblem);
815
812
** Either we're not authenticating, or we're supposed to
816
813
** be authenticating something else. This is an error.
818
if((k->httpcode == 401) && !conn->bits.user_passwd)
815
if((httpcode == 401) && !conn->bits.user_passwd)
820
if((k->httpcode == 407) && !conn->bits.proxy_user_passwd)
817
if((httpcode == 407) && !conn->bits.proxy_user_passwd)
823
820
return data->state.authproblem;
943
941
ptr = in->buffer;
944
942
size = in->size_used;
944
headersize = size - included_body_bytes; /* the initial part that isn't body
947
DEBUGASSERT(size > included_body_bytes);
946
949
#ifdef CURL_DOES_CONVERSIONS
947
if(size - included_body_bytes > 0) {
948
res = Curl_convert_to_network(conn->data, ptr, size - included_body_bytes);
949
/* Curl_convert_to_network calls failf if unsuccessful */
950
if(res != CURLE_OK) {
951
/* conversion failed, free memory and return to the caller */
950
res = Curl_convert_to_network(conn->data, ptr, headersize);
951
/* Curl_convert_to_network calls failf if unsuccessful */
952
if(res != CURLE_OK) {
953
/* conversion failed, free memory and return to the caller */
958
959
#endif /* CURL_DOES_CONVERSIONS */
981
982
res = Curl_write(conn, sockfd, ptr, sendsize, &amount);
983
984
if(CURLE_OK == res) {
986
* Note that we may not send the entire chunk at once, and we have a set
987
* number of data bytes at the end of the big buffer (out of which we may
988
* only send away a part).
990
/* how much of the header that was sent */
991
size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount;
992
size_t bodylen = amount - headlen;
985
994
if(conn->data->set.verbose) {
986
995
/* this data _may_ contain binary stuff */
987
Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr,
988
(size_t)(amount-included_body_bytes), conn);
989
if (included_body_bytes)
996
Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
997
if((size_t)amount > headlen) {
998
/* there was body data sent beyond the initial header part, pass that
999
on to the debug callback too */
990
1000
Curl_debug(conn->data, CURLINFO_DATA_OUT,
991
ptr+amount-included_body_bytes,
992
(size_t)included_body_bytes, conn);
1001
ptr+headlen, bodylen, conn);
994
if (included_body_bytes)
995
1005
/* since we sent a piece of the body here, up the byte counter for it
997
http->writebytecount = included_body_bytes;
1007
http->writebytecount += bodylen;
999
1009
*bytes_written += amount;
1084
1094
size_t new_size;
1096
if(~size < in->size_used) {
1097
/* If resulting used size of send buffer would wrap size_t, cleanup
1098
the whole buffer and return error. Otherwise the required buffer
1099
size will fit into a single allocatable memory chunk */
1100
Curl_safefree(in->buffer);
1102
return CURLE_OUT_OF_MEMORY;
1086
1105
if(!in->buffer ||
1087
1106
((in->size_used + size) > (in->size_max - 1))) {
1088
new_size = (in->size_used+size)*2;
1108
/* If current buffer size isn't enough to hold the result, use a
1109
buffer size that doubles the required size. If this new size
1110
would wrap size_t, then just use the largest possible one */
1112
if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) ||
1113
(~(size*2) < (in->size_used*2)))
1114
new_size = (size_t)-1;
1116
new_size = (in->size_used+size)*2;
1090
1119
/* we have a buffer, enlarge the existing one */
1091
1120
new_rb = (char *)realloc(in->buffer, new_size);
1207
1236
conn->bits.proxy_connect_closed = FALSE;
1210
if (!conn->bits.tunnel_connecting) { /* BEGIN CONNECT PHASE */
1239
if(!conn->bits.tunnel_connecting) { /* BEGIN CONNECT PHASE */
1211
1240
char *host_port;
1212
1241
send_buffer *req_buffer;
1214
1243
infof(data, "Establish HTTP proxy tunnel to %s:%d\n",
1215
1244
hostname, remote_port);
1217
if(data->reqdata.newurl) {
1246
if(data->req.newurl) {
1218
1247
/* This only happens if we've looped here due to authentication
1219
1248
reasons, and we don't really use the newly cloned URL here
1220
1249
then. Just free() it. */
1221
free(data->reqdata.newurl);
1222
data->reqdata.newurl = NULL;
1250
free(data->req.newurl);
1251
data->req.newurl = NULL;
1225
1254
/* initialize a dynamic send-buffer */
1237
1266
/* Setup the proxy-authorization header, if any */
1238
result = Curl_http_output_auth(conn, (char *)"CONNECT", host_port, TRUE);
1267
result = http_output_auth(conn, (char *)"CONNECT", host_port, TRUE);
1240
1269
if(CURLE_OK == result) {
1241
1270
char *host=(char *)"";
1316
1345
/* if we're in multi-mode and we would block, return instead for a retry */
1317
if (Curl_if_multi == data->state.used_interface) {
1318
if (0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
1346
if(Curl_if_multi == data->state.used_interface) {
1347
if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
1319
1348
/* return so we'll be called again polling-style */
1320
1349
return CURLE_OK;
1380
1409
keepon = FALSE;
1381
1410
else if(gotbytes <= 0) {
1382
1411
keepon = FALSE;
1383
error = SELECT_ERROR;
1384
failf(data, "Proxy CONNECT aborted");
1412
if(data->set.proxyauth && data->state.authproxy.avail) {
1413
/* proxy auth was requested and there was proxy auth available,
1414
then deem this as "mere" proxy disconnect */
1415
conn->bits.proxy_connect_closed = TRUE;
1418
error = SELECT_ERROR;
1419
failf(data, "Proxy CONNECT aborted");
1571
1609
headers. 'newurl' is set to a new URL if we must loop. */
1572
1610
Curl_http_auth_act(conn);
1574
if (closeConnection && data->reqdata.newurl) {
1612
if(closeConnection && data->req.newurl) {
1575
1613
/* Connection closed by server. Don't use it anymore */
1576
1614
sclose(conn->sock[sockindex]);
1577
1615
conn->sock[sockindex] = CURL_SOCKET_BAD;
1580
1618
} /* END NEGOTIATION PHASE */
1581
} while(data->reqdata.newurl);
1619
} while(data->req.newurl);
1583
if(200 != k->httpcode) {
1621
if(200 != data->req.httpcode) {
1584
1622
failf(data, "Received HTTP code %d from proxy after CONNECT",
1623
data->req.httpcode);
1587
if (closeConnection && data->reqdata.newurl)
1625
if(closeConnection && data->req.newurl)
1588
1626
conn->bits.proxy_connect_closed = TRUE;
1590
1628
return CURLE_RECV_ERROR;
1637
if (conn->bits.tunnel_connecting) {
1675
if(conn->bits.tunnel_connecting) {
1638
1676
/* nothing else to do except wait right now - we're not done here. */
1639
1677
return CURLE_OK;
1642
1680
if(!data->state.this_is_a_follow) {
1643
1681
/* this is not a followed location, get the original host name */
1644
if (data->state.first_host)
1682
if(data->state.first_host)
1645
1683
/* Free to avoid leaking memory on multiple requests*/
1646
1684
free(data->state.first_host);
1653
1691
if(conn->protocol & PROT_HTTPS) {
1654
1692
/* perform SSL initialization */
1655
1693
if(data->state.used_interface == Curl_if_multi) {
1656
result = Curl_https_connecting(conn, done);
1694
result = https_connecting(conn, done);
1688
1726
#ifdef USE_SSLEAY
1689
1727
/* This function is OpenSSL-specific. It should be made to query the generic
1690
1728
SSL layer instead. */
1691
static int Curl_https_getsock(struct connectdata *conn,
1729
static int https_getsock(struct connectdata *conn,
1692
1730
curl_socket_t *socks,
1695
if (conn->protocol & PROT_HTTPS) {
1733
if(conn->protocol & PROT_HTTPS) {
1696
1734
struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
1699
1737
return GETSOCK_BLANK;
1701
if (connssl->connecting_state == ssl_connect_2_writing) {
1739
if(connssl->connecting_state == ssl_connect_2_writing) {
1702
1740
/* write mode */
1703
1741
socks[0] = conn->sock[FIRSTSOCKET];
1704
1742
return GETSOCK_WRITESOCK(0);
1706
else if (connssl->connecting_state == ssl_connect_2_reading) {
1744
else if(connssl->connecting_state == ssl_connect_2_reading) {
1707
1745
/* read mode */
1708
1746
socks[0] = conn->sock[FIRSTSOCKET];
1709
1747
return GETSOCK_READSOCK(0);
1758
1796
CURLcode status, bool premature)
1760
1798
struct SessionHandle *data = conn->data;
1761
struct HTTP *http =data->reqdata.proto.http;
1762
struct Curl_transfer_keeper *k = &data->reqdata.keep;
1799
struct HTTP *http =data->state.proto.http;
1763
1800
(void)premature; /* not used */
1765
1802
/* set the proper values (possibly modified on POST) */
1766
1803
conn->fread_func = data->set.fread_func; /* restore */
1767
1804
conn->fread_in = data->set.in; /* restore */
1805
conn->seek_func = data->set.seek_func; /* restore */
1806
conn->seek_client = data->set.seek_client; /* restore */
1770
1809
return CURLE_OK;
1772
1811
if(http->send_buffer) {
1790
1829
else if(HTTPREQ_PUT == data->set.httpreq)
1791
k->bytecount = http->readbytecount + http->writebytecount;
1830
data->req.bytecount = http->readbytecount + http->writebytecount;
1793
if (status != CURLE_OK)
1832
if(status != CURLE_OK)
1794
1833
return (status);
1796
1835
if(!conn->bits.retry &&
1797
1836
((http->readbytecount +
1798
data->reqdata.keep.headerbytecount -
1799
data->reqdata.keep.deductheadercount)) <= 0) {
1837
data->req.headerbytecount -
1838
data->req.deductheadercount)) <= 0) {
1800
1839
/* If this connection isn't simply closed to be retried, AND nothing was
1801
1840
read from the HTTP server (that counts), this can't be right so we
1802
1841
return an error here */
1879
1918
char *buf = data->state.buffer; /* this is a short cut to the buffer */
1880
1919
CURLcode result=CURLE_OK;
1881
1920
struct HTTP *http;
1882
char *ppath = data->reqdata.path;
1921
char *ppath = data->state.path;
1883
1922
char ftp_typecode[sizeof(";type=?")] = "";
1884
1923
char *host = conn->host.name;
1885
1924
const char *te = ""; /* transfer-encoding */
1898
1937
sessionhandle, deal with it */
1899
1938
Curl_reset_reqproto(conn);
1901
if(!data->reqdata.proto.http) {
1940
if(!data->state.proto.http) {
1902
1941
/* Only allocate this struct if we don't already have it! */
1904
1943
http = (struct HTTP *)calloc(sizeof(struct HTTP), 1);
1906
1945
return CURLE_OUT_OF_MEMORY;
1907
data->reqdata.proto.http = http;
1946
data->state.proto.http = http;
1910
http = data->reqdata.proto.http;
1949
http = data->state.proto.http;
1912
if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
1951
if( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
1913
1952
data->set.upload) {
1914
1953
httpreq = HTTPREQ_PUT;
1990
2029
Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
1993
if (httpreq == HTTPREQ_GET)
2032
if(httpreq == HTTPREQ_GET)
1994
2033
conn->bits.upload_chunky = FALSE;
1995
2034
if(conn->bits.upload_chunky)
1996
2035
te = "Transfer-Encoding: chunked\r\n";
2036
2075
if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) ||
2037
2076
(!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) )
2038
/* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include
2077
/* if(HTTPS on port 443) OR (non-HTTPS on port 80) then don't include
2039
2078
the port number in the host string */
2040
2079
conn->allocptr.host = aprintf("Host: %s%s%s\r\n",
2041
2080
conn->bits.ipv6_ip?"[":"",
2096
2135
ppath = data->change.url;
2097
/* when doing ftp, append ;type=<a|i> if not present */
2098
if (checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) {
2099
char *p = strstr(ppath, ";type=");
2100
if (p && p[6] && p[7] == 0) {
2101
switch (toupper((int)((unsigned char)p[6]))) {
2136
if (data->set.proxy_transfer_mode) {
2137
/* when doing ftp, append ;type=<a|i> if not present */
2138
if(checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) {
2139
char *p = strstr(ppath, ";type=");
2140
if(p && p[6] && p[7] == 0) {
2141
switch (toupper((int)((unsigned char)p[6]))) {
2151
snprintf(ftp_typecode, sizeof(ftp_typecode), ";type=%c",
2152
data->set.prefer_ascii ? 'a' : 'i');
2111
snprintf(ftp_typecode, sizeof(ftp_typecode), ";type=%c",
2112
data->set.prefer_ascii ? 'a' : 'i');
2115
2156
if(HTTPREQ_POST_FORM == httpreq) {
2137
2178
if(( (HTTPREQ_POST == httpreq) ||
2138
2179
(HTTPREQ_POST_FORM == httpreq) ||
2139
2180
(HTTPREQ_PUT == httpreq) ) &&
2140
data->reqdata.resume_from) {
2181
data->state.resume_from) {
2141
2182
/**********************************************************************
2142
2183
* Resuming upload in HTTP means that we PUT or POST and that we have
2143
2184
* got a resume_from value set. The resume value has already created
2146
2187
* file size before we continue this venture in the dark lands of HTTP.
2147
2188
*********************************************************************/
2149
if(data->reqdata.resume_from < 0 ) {
2190
if(data->state.resume_from < 0 ) {
2151
2192
* This is meant to get the size of the present remote-file by itself.
2152
2193
* We don't support this now. Bail out!
2154
data->reqdata.resume_from = 0;
2195
data->state.resume_from = 0;
2157
if(data->reqdata.resume_from && !data->state.this_is_a_follow) {
2198
if(data->state.resume_from && !data->state.this_is_a_follow) {
2158
2199
/* do we still game? */
2159
curl_off_t passed=0;
2161
2201
/* Now, let's read off the proper amount of bytes from the
2162
input. If we knew it was a proper file we could've just
2163
fseek()ed but we only have a stream here */
2165
size_t readthisamountnow = (size_t)(data->reqdata.resume_from - passed);
2166
size_t actuallyread;
2168
if(readthisamountnow > BUFSIZE)
2169
readthisamountnow = BUFSIZE;
2172
data->set.fread_func(data->state.buffer, 1, (size_t)readthisamountnow,
2175
passed += actuallyread;
2176
if(actuallyread != readthisamountnow) {
2177
failf(data, "Could only read %" FORMAT_OFF_T
2178
" bytes from the input",
2203
if(conn->seek_func) {
2204
curl_off_t readthisamountnow = data->state.resume_from;
2206
if(conn->seek_func(conn->seek_client,
2207
readthisamountnow, SEEK_SET) != 0) {
2208
failf(data, "Could not seek stream");
2180
2209
return CURLE_READ_ERROR;
2182
} while(passed != data->reqdata.resume_from); /* loop until done */
2213
curl_off_t passed=0;
2216
size_t readthisamountnow = (size_t)(data->state.resume_from - passed);
2217
size_t actuallyread;
2219
if(readthisamountnow > BUFSIZE)
2220
readthisamountnow = BUFSIZE;
2222
actuallyread = data->set.fread_func(data->state.buffer, 1,
2223
(size_t)readthisamountnow,
2226
passed += actuallyread;
2227
if(actuallyread != readthisamountnow) {
2228
failf(data, "Could only read %" FORMAT_OFF_T
2229
" bytes from the input",
2231
return CURLE_READ_ERROR;
2233
} while(passed != data->state.resume_from); /* loop until done */
2184
2236
/* now, decrease the size of the read */
2185
2237
if(data->set.infilesize>0) {
2186
data->set.infilesize -= data->reqdata.resume_from;
2238
data->set.infilesize -= data->state.resume_from;
2188
2240
if(data->set.infilesize <= 0) {
2189
2241
failf(data, "File already completely uploaded");
2205
2257
if(conn->allocptr.rangeline)
2206
2258
free(conn->allocptr.rangeline);
2207
2259
conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
2208
data->reqdata.range);
2210
2262
else if((httpreq != HTTPREQ_GET) &&
2211
2263
!checkheaders(data, "Content-Range:")) {
2214
2266
if(conn->allocptr.rangeline)
2215
2267
free(conn->allocptr.rangeline);
2217
if(data->reqdata.resume_from) {
2269
if(data->state.resume_from) {
2218
2270
/* This is because "resume" was selected */
2219
2271
curl_off_t total_expected_size=
2220
data->reqdata.resume_from + data->set.infilesize;
2272
data->state.resume_from + data->set.infilesize;
2221
2273
conn->allocptr.rangeline =
2222
2274
aprintf("Content-Range: bytes %s%" FORMAT_OFF_T
2223
2275
"/%" FORMAT_OFF_T "\r\n",
2224
data->reqdata.range, total_expected_size-1,
2276
data->state.range, total_expected_size-1,
2225
2277
total_expected_size);
2229
2281
append total size */
2230
2282
conn->allocptr.rangeline =
2231
2283
aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n",
2232
data->reqdata.range, data->set.infilesize);
2284
data->state.range, data->set.infilesize);
2234
2286
if(!conn->allocptr.rangeline)
2235
2287
return CURLE_OUT_OF_MEMORY;
2274
2326
conn->allocptr.proxyuserpwd?
2275
2327
conn->allocptr.proxyuserpwd:"",
2276
2328
conn->allocptr.userpwd?conn->allocptr.userpwd:"",
2277
(data->reqdata.use_range && conn->allocptr.rangeline)?
2329
(data->state.use_range && conn->allocptr.rangeline)?
2278
2330
conn->allocptr.rangeline:"",
2279
2331
(data->set.str[STRING_USERAGENT] &&
2280
2332
*data->set.str[STRING_USERAGENT] && conn->allocptr.uagent)?
2307
2359
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
2308
2360
co = Curl_cookie_getlist(data->cookies,
2309
2361
conn->allocptr.cookiehost?
2310
conn->allocptr.cookiehost:host, data->reqdata.path,
2362
conn->allocptr.cookiehost:host,
2311
2364
(bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE));
2312
2365
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
2638
/* For really small posts we don't use Expect: headers at all, and for
2639
the somewhat bigger ones we allow the app to disable it. Just make
2640
sure that the expect100header is always set to the preferred value
2642
if(postsize > TINY_INITIAL_POST_SIZE) {
2643
result = expect100(data, req_buffer);
2648
data->state.expect100header = FALSE;
2585
2650
if(data->set.postfields) {
2587
/* for really small posts we don't use Expect: headers at all, and for
2588
the somewhat bigger ones we allow the app to disable it */
2589
if(postsize > TINY_INITIAL_POST_SIZE) {
2590
result = expect100(data, req_buffer);
2595
data->state.expect100header = FALSE;
2597
2652
if(!data->state.expect100header &&
2598
2653
(postsize < MAX_INITIAL_POST_SIZE)) {
2599
2654
/* if we don't use expect: 100 AND
2656
2711
/* set the upload size to the progress meter */
2657
2712
Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
2659
/* set the pointer to mark that we will send the post body using
2660
the read callback */
2661
http->postdata = (char *)&http->postdata;
2714
/* set the pointer to mark that we will send the post body using the
2715
read callback, but only if we're not in authenticate
2717
if(!conn->bits.authneg) {
2718
http->postdata = (char *)&http->postdata;
2719
http->postsize = postsize;
2664
2723
/* issue the request */