25 #ifndef CURL_DISABLE_HTTP 27 #ifdef HAVE_NETINET_IN_H 28 #include <netinet/in.h> 34 #ifdef HAVE_ARPA_INET_H 35 #include <arpa/inet.h> 40 #ifdef HAVE_SYS_IOCTL_H 41 #include <sys/ioctl.h> 44 #ifdef HAVE_SYS_PARAM_H 45 #include <sys/param.h> 102 #define https_connecting(x,y) CURLE_COULDNT_CONNECT 186 const char *thisheader)
189 size_t thislen = strlen(thisheader);
194 head; head = head->
next) {
218 while(*header && (*header !=
':'))
227 while(*start &&
ISSPACE(*start))
232 end = strchr(start,
'\r');
234 end = strchr(start,
'\n');
236 end = strchr(start,
'\0');
241 while((end > start) &&
ISSPACE(*end))
245 len = end - start + 1;
251 memcpy(value, start, len);
266 char *authorization = NULL;
285 out =
aprintf(
"%s:%s", user, pwd);
299 *userp =
aprintf(
"%sAuthorization: Basic %s\r\n",
300 proxy ?
"Proxy-" :
"",
322 unsigned long avail = pick->
avail & pick->
want;
422 if((expectsend == -1) || (expectsend > bytessent)) {
423 #if defined(USE_NTLM) 429 if(((expectsend - bytessent) < 2000) ||
438 infof(data,
"Rewind stream after send\n");
448 infof(data,
"NTLM send, close instead of sending %" 455 streamclose(conn,
"Mid-auth HTTP and much data left to send");
479 bool pickhost =
FALSE;
480 bool pickproxy =
FALSE;
505 if(pickhost || pickproxy) {
538 failf(data,
"The requested URL returned error: %d",
552 struct auth *authstatus,
557 const char *
auth = NULL;
559 #if !defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_SPNEGO) 563 struct negotiatedata *negdata = proxy ?
564 &data->
state.proxyneg : &data->
state.negotiate;
567 #ifdef CURL_DISABLE_CRYPTO_AUTH 573 negdata->state = GSS_AUTHNONE;
575 negdata->context && !
GSS_ERROR(negdata->status)) {
577 result = Curl_output_negotiate(conn, proxy);
581 negdata->state = GSS_AUTHSENT;
588 result = Curl_output_ntlm(conn, proxy);
594 #if defined(USE_NTLM) && defined(NTLM_WB_ENABLED) 597 result = Curl_output_ntlm_wb(conn, proxy);
603 #ifndef CURL_DISABLE_CRYPTO_AUTH 608 (
const unsigned char *)request,
609 (
const unsigned char *)path);
633 infof(data,
"%s auth using %s with user '%s'\n",
634 proxy ?
"Proxy" :
"Server", auth,
668 struct auth *authhost;
669 struct auth *authproxy;
697 #ifndef CURL_DISABLE_PROXY 743 struct negotiatedata *negdata = proxy?
746 unsigned long *availp;
778 Curl_auth_is_spnego_supported()) {
783 if(negdata->state == GSS_AUTHSENT ||
784 negdata->state == GSS_AUTHNONE) {
793 negdata->state = GSS_AUTHRECV;
808 Curl_auth_is_ntlm_supported()) {
818 #ifdef NTLM_WB_ENABLED 830 auth += strlen(
"NTLM");
834 conn->challenge_header =
strdup(auth);
835 if(!conn->challenge_header)
843 infof(data,
"Authentication problem. Ignoring this.\n");
851 #ifndef CURL_DISABLE_CRYPTO_AUTH 854 infof(data,
"Ignoring duplicate digest auth header.\n");
867 infof(data,
"Authentication problem. Ignoring this.\n");
882 infof(data,
"Authentication problem. Ignoring this.\n");
888 while(*auth && *auth !=
',')
937 if((httpcode != 401) && (httpcode != 407))
943 DEBUGASSERT((httpcode == 401) || (httpcode == 407));
986 size_t fullsize = size * nitems;
1055 long *bytes_written,
1058 size_t included_body_bytes,
1073 sockfd = conn->
sock[socketindex];
1081 headersize = size - included_body_bytes;
1117 result =
Curl_write(conn, sockfd, ptr, sendsize, &amount);
1126 size_t headlen = (
size_t)amount>headersize ? headersize : (
size_t)amount;
1127 size_t bodylen = amount - headlen;
1136 ptr + headlen, bodylen, conn);
1143 *bytes_written += (long)amount;
1150 if((
size_t)amount !=
size) {
1157 ptr = in->
buffer + amount;
1180 if((
size_t)amount !=
size)
1228 if(~size < in->size_used) {
1244 if((size > (
size_t)-1 / 2) || (in->
size_used > (
size_t)-1 / 2) ||
1255 new_rb =
malloc(new_size);
1287 const char *content)
1294 size_t hlen = strlen(header);
1304 start = &headerline[hlen];
1307 while(*start &&
ISSPACE(*start))
1311 end = strchr(start,
'\r');
1314 end = strchr(start,
'\n');
1318 end = strchr(start,
'\0');
1322 clen = strlen(content);
1325 for(; len >= clen; len--, start++) {
1395 connclose(conn,
"Failed HTTPS connection");
1400 static int https_getsock(
struct connectdata *conn,
1429 if(data->
state.proxyneg.state == GSS_AUTHSENT ||
1430 data->
state.negotiate.state == GSS_AUTHSENT) {
1437 streamclose(conn,
"Negotiate transfer completed");
1438 Curl_cleanup_negotiate(data);
1481 failf(data,
"Empty reply from server");
1544 "Expect: 100-continue\r\n");
1598 for(i = 0; i < numlists; i++) {
1602 ptr = strchr(headers->
data,
':');
1649 ptr = strchr(headers->
data,
';');
1660 if(*(--ptr) ==
';') {
1677 headers = headers->
next;
1687 const struct tm *tm;
1699 failf(data,
"Invalid TIMEVALUE");
1709 condp =
"If-Modified-Since";
1712 condp =
"If-Unmodified-Since";
1715 condp =
"Last-Modified";
1728 "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
1754 bool paste_ftp_userpwd =
FALSE;
1755 char ftp_typecode[
sizeof(
"/;type=?")] =
"";
1756 const char *host = conn->
host.
name;
1757 const char *te =
"";
1759 const char *request;
1761 #if !defined(CURL_DISABLE_COOKIES) 1762 char *addcookies = NULL;
1765 const char *httpstring;
1848 request =
"OPTIONS";
1894 #if !defined(CURL_DISABLE_COOKIES) 1923 #define TE_HEADER "TE: gzip\r\n" 1929 strdup(
"Connection: TE\r\n" TE_HEADER);
1962 for(cthdr += 13; *cthdr ==
' '; cthdr++)
1965 cthdr =
"multipart/form-data";
1997 failf(data,
"Chunky upload is not supported by HTTP 1.0");
2007 te =
"Transfer-Encoding: chunked\r\n";
2015 #if !defined(CURL_DISABLE_COOKIES) 2030 int startsearch = 0;
2031 if(*cookiehost ==
'[') {
2032 char *closingbracket;
2035 memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1);
2036 closingbracket = strchr(cookiehost,
']');
2038 *closingbracket = 0;
2041 char *colon = strchr(cookiehost + startsearch,
':');
2050 if(strcmp(
"Host:", ptr)) {
2085 #ifndef CURL_DISABLE_PROXY 2102 size_t newlen = strlen(conn->
host.
name);
2103 size_t urllen = strlen(url);
2107 newurl =
malloc(urllen + newlen - currlen + 1);
2110 memcpy(newurl, url, ptr - url);
2114 memcpy(newurl + newlen + (ptr - url),
2116 urllen - (ptr-url) - currlen + 1);
2132 char *type = strstr(ppath,
";type=");
2133 if(type && type[6] && type[7] == 0) {
2144 char *
p = ftp_typecode;
2147 if(!*data->
state.
path && ppath[strlen(ppath) - 1] !=
'/') {
2150 snprintf(p,
sizeof(ftp_typecode) - 1,
";type=%c",
2155 paste_ftp_userpwd =
TRUE;
2195 failf(data,
"Could not seek stream");
2200 size_t readthisamountnow =
2205 size_t actuallyread =
2209 passed += actuallyread;
2210 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
2214 " bytes from the input", passed);
2217 }
while(passed < data->
state.resume_from);
2225 failf(data,
"File already completely uploaded");
2269 total_expected_size);
2301 if(paste_ftp_userpwd)
2304 ppath +
sizeof(
"ftp://") - 1);
2349 "Proxy-Connection: Keep-Alive\r\n":
"",
2371 #if !defined(CURL_DISABLE_COOKIES) 2372 if(data->
cookies || addcookies) {
2373 struct Cookie *co = NULL;
2387 struct Cookie *store = co;
2397 "%s%s=%s", count?
"; ":
"",
2407 if(addcookies && !result) {
2416 if(count && !result)
2459 result =
expect100(data, conn, req_buffer);
2475 failf(data,
"Failed sending PUT request");
2497 failf(data,
"Failed sending POST request");
2542 result =
expect100(data, conn, req_buffer);
2560 http->
sending = HTTPSEND_BODY;
2566 failf(data,
"Failed sending POST request");
2602 "Content-Type: application/" 2603 "x-www-form-urlencoded\r\n");
2618 result =
expect100(data, conn, req_buffer);
2648 included_body = postsize;
2659 included_body = postsize + 2;
2677 http->
sending = HTTPSEND_BODY;
2680 data->
state.
in = (
void *)conn;
2699 "\x30\x0d\x0a\x0d\x0a", 5);
2723 failf(data,
"Failed sending HTTP POST request");
2740 failf(data,
"Failed sending HTTP request");
2789 #ifdef CURL_DOES_CONVERSIONS 2791 char *scratch =
strdup(s);
2792 if(NULL == scratch) {
2793 failf(data,
"Failed to allocate memory for conversion!");
2815 #ifdef CURL_DOES_CONVERSIONS 2821 #ifndef CURL_DISABLE_RTSP 2828 #ifdef CURL_DOES_CONVERSIONS 2830 char *scratch =
strdup(s);
2831 if(NULL == scratch) {
2832 failf(data,
"Failed to allocate memory for conversion!");
2855 #ifndef CURL_DISABLE_RTSP 2884 failf(data,
"Avoided giant realloc for header (max is %d)!",
2893 failf(data,
"Failed to alloc memory for big header!");
2914 if(!strncmp(beg,
"HTTP", 4)) {
2917 beg = strchr(beg,
' ');
2921 char end_char =
'\r';
2922 char *end = strchr(beg, end_char);
2926 end = strchr(beg, end_char);
2932 failf(data,
"The requested URL returned error: %s", beg);
2942 failf(data,
"The requested URL returned error: %d", k->
httpcode);
2990 *nread -= (
ssize_t)rest_length;
3019 *nread = (
ssize_t)rest_length;
3027 if((0x0a == *k->
p) || (0x0d == *k->
p)) {
3031 #ifdef CURL_DOES_CONVERSIONS 3072 infof(data,
"Received 101\n");
3111 infof(data,
"no chunk, no close, no size. Assume close to " 3113 streamclose(conn,
"HTTP: No end-of-message indicator");
3119 #if defined(USE_NTLM) 3125 infof(data,
"Connection closure while negotiating auth (HTTP 1.0?)\n");
3135 failf(data,
"The requested URL returned error: %d",
3196 infof(data,
"HTTP error before end of send, keep sending\n");
3203 infof(data,
"HTTP error before end of send, stop sending\n");
3204 streamclose(conn,
"Stop sending data before everything sent");
3221 infof(data,
"Keep sending data to get tossed away!\n");
3234 *stop_reading =
TRUE;
3235 #ifndef CURL_DISABLE_RTSP 3243 *stop_reading =
TRUE;
3277 #
if defined(USE_NGHTTP2)
3282 *stop_reading =
TRUE;
3309 int httpversion_major;
3310 int rtspversion_major;
3312 #ifdef CURL_DOES_CONVERSIONS 3313 #define HEADER1 scratch 3314 #define SCRATCHSIZE 21 3316 char scratch[SCRATCHSIZE + 1];
3322 strncpy(&scratch[0], k->
p, SCRATCHSIZE);
3323 scratch[SCRATCHSIZE] = 0;
3331 #define HEADER1 k->p 3344 " HTTP/%1d.%1d%c%3d",
3350 if(nc == 1 && httpversion_major == 2 &&
3357 if((nc == 4) && (
' ' == separator)) {
3363 infof(data,
"Lying server, not serving HTTP/2\n");
3385 failf(data,
"Unsupported HTTP version in response\n");
3443 infof(data,
"HTTP 1.0, assume close after body\n");
3444 connclose(conn,
"HTTP/1.0 close after body");
3448 DEBUGF(
infof(data,
"HTTP/2 found, allow multiplexing\n"));
3459 "HTTP 1.1 or later with persistent connection, " 3460 "pipelining supported\n"));
3510 failf(data,
"Maximum file size exceeded");
3513 if(contentlength >= 0) {
3514 k->
size = contentlength;
3527 ", closing after transfer\n", contentlength);
3531 infof(data,
"Illegal Content-Length: header\n");
3562 "Proxy-Connection:",
"keep-alive")) {
3569 connkeep(conn,
"Proxy-Connection keep-alive");
3570 infof(data,
"HTTP/1.0 proxy connection set to keep alive!\n");
3575 "Proxy-Connection:",
"close")) {
3580 connclose(conn,
"Proxy-Connection: asked to close after done");
3581 infof(data,
"HTTP/1.1 proxy connection set close!\n");
3591 connkeep(conn,
"Connection keep-alive");
3592 infof(data,
"HTTP/1.0 connection set to keep alive!\n");
3622 while(*start && (
ISSPACE(*start) || (*start ==
',')))
3674 while(*start &&
ISSPACE(*start))
3698 char *
ptr = k->
p + 14;
3701 while(*ptr && !
ISDIGIT(*ptr) && *ptr !=
'*')
3715 #if !defined(CURL_DISABLE_COOKIES) 3732 time_t secs = time(NULL);
int Curl_debug(struct Curl_easy *data, curl_infotype type, char *ptr, size_t size, struct connectdata *conn)
#define CONNECT_FIRSTSOCKET_PROXY_SSL()
CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part, struct curl_slist *headers, int take_ownership)
const char *const Curl_wkday[]
CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, const char *auth)
static bool checkrtspprefix(struct Curl_easy *data, const char *s)
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size)
void Curl_expire_done(struct Curl_easy *data, expire_id id)
bool Curl_pipeline_site_blacklisted(struct Curl_easy *handle, struct connectdata *conn)
#define MAX_INITIAL_POST_SIZE
void Curl_httpchunk_init(struct connectdata *conn)
#define streamclose(x, y)
CURLcode Curl_http_auth_act(struct connectdata *conn)
void Curl_add_buffer_free(Curl_send_buffer *buff)
curl_off_t set_resume_from
CURLcode Curl_add_timecondition(struct Curl_easy *data, Curl_send_buffer *req_buffer)
#define CURL_SEEKFUNC_CANTSEEK
CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
bool http_keep_sending_on_error
void Curl_mime_cleanpart(curl_mimepart *part)
char * Curl_checkProxyheaders(const struct connectdata *conn, const char *thisheader)
const char *const Curl_month[]
CURLcode Curl_base64_encode(struct Curl_easy *data, const char *inputbuff, size_t insize, char **outptr, size_t *outlen)
const struct Curl_handler * handler
#define CURL_MAX_WRITE_SIZE
static char server_name[50]
UNITTEST_START char * ptr
static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
#define BUNDLE_NO_MULTIUSE
bool http_transfer_encoding
#define EXPECT_100_THRESHOLD
#define Curl_http2_request_upgrade(x, y)
static CURLcode output_auth_headers(struct connectdata *conn, struct auth *authstatus, const char *request, const char *path, bool proxy)
CURLcode Curl_mime_prepare_headers(curl_mimepart *part, const char *contenttype, const char *disposition, enum mimestrategy strategy)
#define realloc(ptr, size)
#define Curl_http2_done(x, y)
#define Curl_ssl_connect_nonblocking(x, y, z)
struct curl_slist * headers
#define strcasecompare(a, b)
CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
static CURLcode header_append(struct Curl_easy *data, struct SingleRequest *k, size_t length)
UNITTEST_START int result
static size_t readmoredata(char *buffer, size_t size, size_t nitems, void *userp)
CURLcode Curl_input_digest(struct connectdata *conn, bool proxy, const char *header)
struct DynamicStatic change
static bool use_http_1_1plus(const struct Curl_easy *data, const struct connectdata *conn)
struct proxy_info http_proxy
curl_seek_callback seek_func
static int http_should_fail(struct connectdata *conn)
http_should_fail() determines whether an HTTP response has gotten us into an error state or not...
bool Curl_compareheader(const char *headerline, const char *header, const char *content)
int Curl_pgrsUpdate(struct connectdata *conn)
curl_off_t writebytecount
memcpy(filename, filename1, strlen(filename1))
#define CURLAUTH_NEGOTIATE
#define Curl_http2_switched(x, y, z)
size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
CURLcode Curl_readrewind(struct connectdata *conn)
bool http_follow_location
CURLSHcode Curl_share_unlock(struct Curl_easy *data, curl_lock_data type)
enum SingleRequest::@32 badheader
void Curl_setup_transfer(struct connectdata *conn, int sockindex, curl_off_t size, bool getheader, curl_off_t *bytecountp, int writesockindex, curl_off_t *writecountp)
curl_easy_setopt expects a curl_off_t argument for this option curl_easy_setopt expects a curl_write_callback argument for this option curl_easy_setopt expects a curl_ioctl_callback argument for this option curl_easy_setopt expects a curl_opensocket_callback argument for this option curl_easy_setopt expects a curl_debug_callback argument for this option curl_easy_setopt expects a curl_conv_callback argument for this option curl_easy_setopt expects a private data pointer as argument for this option curl_easy_setopt expects a FILE *argument for this option curl_easy_setopt expects a struct curl_httppost *argument for this option curl_easy_setopt expects a struct curl_slist *argument for this option curl_easy_getinfo expects a pointer to char *for this info curl_easy_getinfo expects a pointer to double for this info curl_easy_getinfo expects a pointer to struct curl_tlssessioninfo *for this info curl_easy_getinfo expects a pointer to curl_socket_t for this info size_t
curl_read_callback fread_func
struct curl_slist * http200aliases
CURLcode Curl_mime_rewind(curl_mimepart *part)
static bool pickoneauth(struct auth *pick)
static CURLcode http_perhapsrewind(struct connectdata *conn)
char * Curl_copy_header_value(const char *header)
CURLofft curlx_strtoofft(const char *str, char **endp, int base, curl_off_t *num)
bool http_disable_hostname_check_before_authentication
UNITTEST_START struct Curl_easy data
bool Curl_auth_is_digest_supported(void)
#define strncasecompare(a, b, c)
void * Curl_saferealloc(void *ptr, size_t size)
#define Curl_convert_from_network(a, b, c)
void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size)
#define BUNDLE_PIPELINING
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size)
#define Curl_convert_to_network(a, b, c)
static int http_getsock_do(struct connectdata *conn, curl_socket_t *socks, int numsocks)
CURL_TYPEOF_CURL_OFF_T curl_off_t
struct curl_httppost * httppost
#define CLIENTWRITE_HEADER
struct CookieInfo * cookies
CURLcode Curl_add_buffer_send(Curl_send_buffer *in, struct connectdata *conn, long *bytes_written, size_t included_body_bytes, int socketindex)
size_t(* curl_read_callback)(char *buffer, size_t size, size_t nitems, void *instream)
CURLcode Curl_write(struct connectdata *conn, curl_socket_t sockfd, const void *mem, size_t len, ssize_t *written)
#define GETSOCK_WRITESOCK(x)
#define GSS_ERROR(status)
const struct Curl_handler * given
void Curl_pipeline_leave_write(struct connectdata *conn)
bool Curl_pipeline_server_blacklisted(struct Curl_easy *handle, char *server_name)
CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr, size_t len)
bool Curl_connect_ongoing(struct connectdata *conn)
struct Cookie * Curl_cookie_add(struct Curl_easy *data, struct CookieInfo *c, bool httpheader, char *lineptr, const char *domain, const char *path)
#define Curl_safefree(ptr)
curl_off_t Curl_mime_size(curl_mimepart *part)
#define https_connecting(x, y)
char uploadbuffer[UPLOAD_BUFSIZE+1]
CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, struct connectdata *conn, ssize_t *nread, bool *stop_reading)
int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks)
#define CURL_MAX_HTTP_HEADER
static const char * get_http_string(const struct Curl_easy *data, const struct connectdata *conn)
struct curl_slist * proxyheaders
unsigned long proxyauthavail
#define Curl_http2_setup_req(x)
char * Curl_checkheaders(const struct connectdata *conn, const char *thisheader)
CURLcode Curl_http_output_auth(struct connectdata *conn, const char *request, const char *path, bool proxytunnel)
Curl_http_output_auth() setups the authentication headers for the host/proxy and the correct authenti...
static bool checkprotoprefix(struct Curl_easy *data, struct connectdata *conn, const char *s)
CURLcode Curl_output_digest(struct connectdata *conn, bool proxy, const unsigned char *request, const unsigned char *uripath)
CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused)
void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
CURLcode Curl_gmtime(time_t intime, struct tm *store)
curl_TimeCond timecondition
CURLcode Curl_http_setup_conn(struct connectdata *conn)
struct connectbundle * bundle
struct Cookie * Curl_cookie_getlist(struct CookieInfo *c, const char *host, const char *path, bool secure)
CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt,...)
CURLcode Curl_http_done(struct connectdata *conn, CURLcode status, bool premature)
#define Curl_http2_setup_conn(x)
UNITTEST_START int * value
CURLcode Curl_http(struct connectdata *conn, bool *done)
curl_read_callback fread_func
CURLSHcode Curl_share_lock(struct Curl_easy *data, curl_lock_data type, curl_lock_access accesstype)
CURLcode Curl_rtsp_parseheader(struct connectdata *conn, char *header)
struct curl_slist * curlheaders
Curl_send_buffer * Curl_add_buffer_init(void)
#define checkprefix(a, b)
#define CURL_HTTP_VERSION_2
#define Curl_unencode_cleanup(x)
void Curl_cookie_freelist(struct Cookie *co)
union connectdata::@34 proto
curl_seek_callback seek_func
#define PROTOPT_CREDSPERREQUEST
static bool checkhttpprefix(struct Curl_easy *data, const char *s)
#define CURLAUTH_PICKNONE
struct connectdata::dynamically_allocated_data allocptr
const struct Curl_handler Curl_handler_http
size_t curlx_sotouz(curl_off_t sonum)
static void print_http_error(struct Curl_easy *data)
#define Curl_http2_setup(x)
static CURLcode expect100(struct Curl_easy *data, struct connectdata *conn, Curl_send_buffer *req_buffer)
unsigned long httpauthavail
#define PROTO_FAMILY_HTTP
char Curl_raw_toupper(char in)
CURLcode Curl_add_custom_headers(struct connectdata *conn, bool is_connect, Curl_send_buffer *req_buffer)
#define calloc(nbelem, size)
bool proxy_connect_closed
#define CURL_FORMAT_CURL_OFF_T
CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
struct curl_llist_element * head
case 1: list has >1 element, removing head : 1: list size will be decremented by one 2: head will be ...