📄 transfer.c
字号:
*****/ if(!k->headerline) { /* the first read header */ if((k->hbuflen>5) && !checkhttpprefix(data, data->state.headerbuff)) { /* this is not the beginning of a HTTP first header line */ k->header = FALSE; if(nread) /* since there's more, this is a partial bad header */ k->badheader = HEADER_PARTHEADER; else { /* this was all we read so its all a bad header */ k->badheader = HEADER_ALLBAD; nread = rest_length; } break; } } if (('\n' == *k->p) || ('\r' == *k->p)) { int headerlen; /* Zero-length header line means end of headers! */ if ('\r' == *k->p) k->p++; /* pass the \r byte */ if ('\n' == *k->p) k->p++; /* pass the \n byte */ if(100 == k->httpcode) { /* * We have made a HTTP PUT or POST and this is 1.1-lingo * that tells us that the server is OK with this and ready * to receive the data. * However, we'll get more headers now so we must get * back into the header-parsing state! */ k->header = TRUE; k->headerline = 0; /* restart the header line counter */ /* if we did wait for this do enable write now! */ if (k->write_after_100_header) { k->write_after_100_header = FALSE; FD_SET (conn->writesockfd, &k->writefd); /* write */ k->keepon |= KEEP_WRITE; k->wkeepfd = k->writefd; } } else k->header = FALSE; /* no more header to parse! */ if (417 == k->httpcode) { /* * we got: "417 Expectation Failed" this means: * we have made a HTTP call and our Expect Header * seems to cause a problem => abort the write operations * (or prevent them from starting). */ k->write_after_100_header = FALSE; k->keepon &= ~KEEP_WRITE; FD_ZERO(&k->wkeepfd); } /* now, only output this if the header AND body are requested: */ writetype = CLIENTWRITE_HEADER; if (data->set.http_include_header) writetype |= CLIENTWRITE_BODY; headerlen = k->p - data->state.headerbuff; result = Curl_client_write(data, writetype, data->state.headerbuff, headerlen); if(result) return result; data->info.header_size += headerlen; conn->headerbytecount += headerlen; /* *auth_act() checks what authentication methods that are available and decides which one (if any) to use. It will set 'newurl' if an auth metod was picked. */ Curl_http_auth_act(conn); if(!k->header) { /* * really end-of-headers. * * If we requested a "no body", this is a good time to get * out and return home. */ if(data->set.no_body) stop_reading = TRUE; else { /* If we know the expected size of this document, we set the maximum download size to the size of the expected document or else, we won't know when to stop reading! Note that we set the download maximum even if we read a "Connection: close" header, to make sure that "Content-Length: 0" still prevents us from attempting to read the (missing) response-body. */ if(-1 != conn->size) conn->maxdownload = conn->size; } /* If max download size is *zero* (nothing) we already have nothing and can safely return ok now! */ if(0 == conn->maxdownload) stop_reading = TRUE; if(stop_reading) { /* we make sure that this socket isn't read more now */ k->keepon &= ~KEEP_READ; FD_ZERO(&k->rkeepfd); } break; /* exit header line loop */ } /* We continue reading headers, so reset the line-based header parsing variables hbufp && hbuflen */ k->hbufp = data->state.headerbuff; k->hbuflen = 0; continue; } /* * Checks for special headers coming up. */ if (!k->headerline++) { /* This is the first header, it MUST be the error code line or else we consiser this to be the body right away! */ int httpversion_major; int nc=sscanf (k->p, " HTTP/%d.%d %3d", &httpversion_major, &k->httpversion, &k->httpcode); if (nc==3) { k->httpversion += 10 * httpversion_major; } else { /* this is the real world, not a Nirvana NCSA 1.5.x returns this crap when asked for HTTP/1.1 */ nc=sscanf (k->p, " HTTP %3d", &k->httpcode); k->httpversion = 10; /* If user has set option HTTP200ALIASES, compare header line against list of aliases */ if (!nc) { if (checkhttpprefix(data, k->p)) { nc = 1; k->httpcode = 200; k->httpversion = (data->set.httpversion==CURL_HTTP_VERSION_1_0)? 10 : 11; } } } if (nc) { data->info.httpcode = k->httpcode; data->info.httpversion = k->httpversion; /* 404 -> URL not found! */ if (data->set.http_fail_on_error && (k->httpcode >= 400)) { /* If we have been told to fail hard on HTTP-errors, here is the check for that: */ /* serious error, go home! */ failf (data, "The requested URL returned error: %d", k->httpcode); return CURLE_HTTP_RETURNED_ERROR; } if(k->httpversion == 10) /* Default action for HTTP/1.0 must be to close, unless we get one of those fancy headers that tell us the server keeps it open for us! */ conn->bits.close = TRUE; switch(k->httpcode) { case 204: /* (quote from RFC2616, section 10.2.5): The server has * fulfilled the request but does not need to return an * entity-body ... The 204 response MUST NOT include a * message-body, and thus is always terminated by the first * empty line after the header fields. */ /* FALLTHROUGH */ case 416: /* Requested Range Not Satisfiable, it has the Content-Length: set as the "real" document but no actual response is sent. */ case 304: /* (quote from RFC2616, section 10.3.5): The 304 response * MUST NOT contain a message-body, and thus is always * terminated by the first empty line after the header * fields. */ conn->size=0; conn->maxdownload=0; break; default: /* nothing */ break; } } else { k->header = FALSE; /* this is not a header line */ break; } } /* Check for Content-Length: header lines to get size. Ignore the header completely if we get a 416 response as then we're resuming a document that we don't get, and this header contains info about the true size of the document we didn't get now. */ if ((k->httpcode != 416) && checkprefix("Content-Length:", k->p) && sscanf (k->p+15, " %ld", &k->contentlength)) { if (data->set.max_filesize && k->contentlength > data->set.max_filesize) { failf(data, "Maximum file size exceeded"); return CURLE_FILESIZE_EXCEEDED; } conn->size = k->contentlength; Curl_pgrsSetDownloadSize(data, k->contentlength); } /* check for Content-Type: header lines to get the mime-type */ else if (checkprefix("Content-Type:", k->p)) { char *start; char *end; int len; /* Find the first non-space letter */ for(start=k->p+13; *start && isspace((int)*start); start++); end = strchr(start, '\r'); if(!end) end = strchr(start, '\n'); if(end) { /* skip all trailing space letters */ for(; isspace((int)*end) && (end > start); end--); /* get length of the type */ len = end-start+1; /* allocate memory of a cloned copy */ Curl_safefree(data->info.contenttype); data->info.contenttype = malloc(len + 1); if (NULL == data->info.contenttype) return CURLE_OUT_OF_MEMORY; /* copy the content-type string */ memcpy(data->info.contenttype, start, len); data->info.contenttype[len] = 0; /* zero terminate */ } } else if((k->httpversion == 10) && conn->bits.httpproxy && Curl_compareheader(k->p, "Proxy-Connection:", "keep-alive")) { /* * When a HTTP/1.0 reply comes when using a proxy, the * 'Proxy-Connection: keep-alive' line tells us the * connection will be kept alive for our pleasure. * Default action for 1.0 is to close. */ conn->bits.close = FALSE; /* don't close when done */ infof(data, "HTTP/1.0 proxy connection set to keep alive!\n"); } else if((k->httpversion == 10) && Curl_compareheader(k->p, "Connection:", "keep-alive")) { /* * A HTTP/1.0 reply with the 'Connection: keep-alive' line * tells us the connection will be kept alive for our * pleasure. Default action for 1.0 is to close. * * [RFC2068, section 19.7.1] */ conn->bits.close = FALSE; /* don't close when done */ infof(data, "HTTP/1.0 connection set to keep alive!\n"); } else if (Curl_compareheader(k->p, "Connection:", "close")) { /* * [RFC 2616, section 8.1.2.1] * "Connection: close" is HTTP/1.1 language and means that * the connection will close when this request has been * served. */ conn->bits.close = TRUE; /* close when done */ } else if (Curl_compareheader(k->p, "Transfer-Encoding:", "chunked")) { /* * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding * means that the server will send a series of "chunks". Each * chunk starts with line with info (including size of the * coming block) (terminated with CRLF), then a block of data * with the previously mentioned size. There can be any amount * of chunks, and a chunk-data set to zero signals the * end-of-chunks. */ conn->bits.chunk = TRUE; /* chunks coming our way */ /* init our chunky engine */ Curl_httpchunk_init(conn); } else if (checkprefix("Content-Encoding:", k->p) && data->set.encoding) { /* * Process Content-Encoding. Look for the values: identity, * gzip, deflate, compress, x-gzip and x-compress. x-gzip and * x-compress are the same as gzip and compress. (Sec 3.5 RFC * 2616). zlib cannot handle compress. However, errors are * handled further down when the response body is processed */ char *start; /* Find the first non-space letter */ for(start=k->p+17; *start && isspace((int)*start); start++); /* Record the content-encoding for later use. 08/27/02 jhrg */ if (checkprefix("identity", start)) k->content_encoding = IDENTITY; else if (checkprefix("deflate", start)) k->content_encoding = DEFLATE; else if (checkprefix("gzip", start) || checkprefix("x-gzip", start)) k->content_encoding = GZIP; else if (checkprefix("compress", start) || checkprefix("x-compress", start)) k->content_encoding = COMPRESS; } else if (checkprefix("Content-Range:", k->p)) { if (sscanf (k->p+14, " bytes %d-", &k->offset) || sscanf (k->p+14, " bytes: %d-", &k->offset)) { /* This second format was added August 1st 2000 by Igor Khristophorov since Sun's webserver JavaWebServer/1.1.1 obviously sends the header this way! :-( */ if (conn->resume_from == k->offset) { /* we asked for a resume and we got it */ k->content_range = TRUE; } } } else if(data->cookies && checkprefix("Set-Cookie:", k->p)) { Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); Curl_cookie_add(data, data->cookies, TRUE, k->p+11, /* If there is a custom-set Host: name, use it here, or else use real peer host name. */ conn->allocptr.cookiehost? conn->allocptr.cookiehost:conn->name, conn->ppath); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } else if(checkprefix("Last-Modified:", k->p) && (data->set.timecondition || data->set.get_filetime) ) { time_t secs=time(NULL); k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"), &secs); if(data->set.get_filetime) data->info.filetime = k->timeofdoc; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -