📄 http.c
字号:
#ifdef USE_SSLuse_tunnel: /* ** If this is an https document ** then do the SSL stuff here */ if (did_connect || !strncmp(url, "https", 5)) { handle = HTGetSSLHandle(); SSL_set_fd(handle, s);#if SSLEAY_VERSION_NUMBER >= 0x0900 if (!try_tls) handle->options|=SSL_OP_NO_TLSv1;#endif /* SSLEAY_VERSION_NUMBER >= 0x0900 */ HTSSLInitPRNG(); status = SSL_connect(handle); if (status <= 0) {#if SSLEAY_VERSION_NUMBER >= 0x0900 if (try_tls) { CTRACE((tfp, "HTTP: Retrying connection without TLS\n")); _HTProgress("Retrying connection."); try_tls = FALSE; if (did_connect) HTTP_NETCLOSE(s, handle); goto try_again; } else { unsigned long SSLerror; CTRACE((tfp,"HTTP: Unable to complete SSL handshake for '%s', SSL_connect=%d, SSL error stack dump follows\n", url, status)); SSL_load_error_strings(); while((SSLerror=ERR_get_error())!=0) { CTRACE((tfp,"HTTP: SSL: %s\n",ERR_error_string(SSLerror,NULL))); } HTAlert("Unable to make secure connection to remote host."); if (did_connect) HTTP_NETCLOSE(s, handle); status = HT_NOT_LOADED; goto done; }#else unsigned long SSLerror; CTRACE((tfp,"HTTP: Unable to complete SSL handshake for '%s', SSL_connect=%d, SSL error stack dump follows\n", url, status)); SSL_load_error_strings(); while((SSLerror=ERR_get_error())!=0) { CTRACE((tfp,"HTTP: SSL: %s\n",ERR_error_string(SSLerror,NULL))); } HTAlert("Unable to make secure connection to remote host."); if (did_connect) HTTP_NETCLOSE(s, handle); status = HT_NOT_LOADED; goto done;#endif /* SSLEAY_VERSION_NUMBER >= 0x0900 */ } sprintf(SSLprogress,"Secure %d-bit %s (%s) HTTP connection",SSL_get_cipher_bits(handle,NULL),SSL_get_cipher_version(handle),SSL_get_cipher(handle)); _HTProgress(SSLprogress);#ifdef NOTDEFINED if (strcmp(HTParse(url, "", PARSE_HOST), strstr(X509_NAME_oneline( X509_get_subject_name( handle->session->peer)),"/CN=")+4)) { HTAlert("Certificate is for different host name"); HTAlert(strstr(X509_NAME_oneline( X509_get_subject_name( handle->session->peer)),"/CN=")+4); }#endif /* NOTDEFINED */ }#endif /* USE_SSL */ /* Ask that node for the document, ** omitting the host name & anchor */ { char * p1 = (HTParse(url, "", PARSE_PATH|PARSE_PUNCTUATION));#ifdef USE_SSL if (do_connect) { METHOD = "CONNECT"; StrAllocCopy(command, "CONNECT "); } else#endif /* USE_SSL */ if (do_post) { METHOD = "POST"; StrAllocCopy(command, "POST "); } else if (do_head) { METHOD = "HEAD"; StrAllocCopy(command, "HEAD "); } else { METHOD = "GET"; StrAllocCopy(command, "GET "); } /* ** If we are using a proxy gateway don't copy in the first slash ** of say: /gopher://a;lkdjfl;ajdf;lkj/;aldk/adflj ** so that just gopher://.... is sent. */#ifdef USE_SSL if (using_proxy && !did_connect) { if (do_connect) StrAllocCat(command, connect_host); else StrAllocCat(command, p1+1); }#else if (using_proxy) StrAllocCat(command, p1+1);#endif /* USE_SSL */ else StrAllocCat(command, p1); FREE(p1); } if (extensions) { StrAllocCat(command, " "); StrAllocCat(command, HTTP_VERSION); } StrAllocCat(command, crlf); /* CR LF, as in rfc 977 */ if (extensions) { int n, i; char * host = NULL; if ((host = HTParse(anAnchor->address, "", PARSE_HOST)) != NULL) { strip_userid(host); HTSprintf(&command, "Host: %s%c%c", host, CR,LF); FREE(host); } if (!HTPresentations) HTFormatInit(); n = HTList_count(HTPresentations); first_Accept = TRUE; len = 0; for (i = 0; i < n; i++) { HTPresentation *pres = (HTPresentation *)HTList_objectAt(HTPresentations, i); if (pres->get_accept) { if (pres->quality < 1.0) { if (pres->maxbytes > 0) { sprintf(temp, ";q=%4.3f;mxb=%ld", pres->quality, pres->maxbytes); } else { sprintf(temp, ";q=%4.3f", pres->quality); } } else if (pres->maxbytes > 0) { sprintf(temp, ";mxb=%ld", pres->maxbytes); } else { temp[0] = '\0'; } HTSprintf0(&linebuf, "%s%s%s", (first_Accept ? "Accept: " : ", "), HTAtom_name(pres->rep), temp); len += strlen(linebuf); if (len > 252 && !first_Accept) { StrAllocCat(command, crlf); HTSprintf0(&linebuf, "Accept: %s%s", HTAtom_name(pres->rep), temp); len = strlen(linebuf); } StrAllocCat(command, linebuf); first_Accept = FALSE; } } HTSprintf(&command, "%s*/*;q=0.01%c%c", (first_Accept ? "Accept: " : ", "), CR, LF); first_Accept = FALSE; len = 0; /* * FIXME: suppressing the "Accept-Encoding" in this case is done to work * around limitations of the presentation logic used for the command-line * "-base" option. The remote site may transmit the document gzip'd, but * the ensuing logic in HTSaveToFile() would see the mime-type as gzip * rather than text/html, and not prepend the base URL. This is less * efficient than accepting the compressed data and uncompressing it, * adding the base URL but is simpler than augmenting the dump's * presentation logic -TD */ if (LYPrependBaseToSource && dump_output_immediately) { CTRACE((tfp, "omit Accept-Encoding to work-around interaction with -source\n")); } else { HTSprintf(&command, "Accept-Encoding: %s, %s%c%c", "gzip", "compress", CR, LF); } if (language && *language) { HTSprintf(&command, "Accept-Language: %s%c%c", language, CR, LF); } if (pref_charset && *pref_charset) { StrAllocCat(command, "Accept-Charset: "); StrAllocCopy(linebuf, pref_charset); if (linebuf[strlen(linebuf)-1] == ',') linebuf[strlen(linebuf)-1] = '\0'; LYLowerCase(linebuf); if (strstr(linebuf, "iso-8859-1") == NULL) StrAllocCat(linebuf, ", iso-8859-1;q=0.01"); if (strstr(linebuf, "us-ascii") == NULL) StrAllocCat(linebuf, ", us-ascii;q=0.01"); StrAllocCat(command, linebuf); HTSprintf(&command, "%c%c", CR, LF); }#if 0 /* ** Promote 300 (Multiple Choices) replies, if supported, ** over 406 (Not Acceptable) replies. - FM ** ** This used to be done in versions 2.7 and 2.8*, but violates ** the specs for transparent content negotiation and has the ** effect that servers supporting those specs will send 300 ** (Multiple Choices) instead of a normal response (e.g. 200 OK), ** since they will assume that the client wants to make the ** choice. It is not clear whether there are any servers or sites ** for which sending this header really improves anything. ** ** If there ever is a need to send "Negotiate: trans" and really ** mean it, we should send "Negotiate: trans,trans" or similar, ** since that is semantically equivalent and some servers may ** ignore "Negotiate: trans" as a special case when it comes from ** Lynx (to work around the old faulty behavior). - kw ** ** References: ** RFC 2295 (see also RFC 2296), and mail to lynx-dev and ** new-httpd@apache.org from Koen Holtman, Jan 1999. */ if (!do_post) { HTSprintf(&command, "Negotiate: trans%c%c", CR, LF); }#endif /* 0 */ /* ** When reloading give no-cache pragma to proxy server to make ** it refresh its cache. -- Ari L. <luotonen@dxcern.cern.ch> ** ** Also send it as a Cache-Control header for HTTP/1.1. - FM */ if (reloading) { HTSprintf(&command, "Pragma: no-cache%c%c", CR, LF); HTSprintf(&command, "Cache-Control: no-cache%c%c", CR, LF); } if (LYUserAgent && *LYUserAgent) { char *cp = LYSkipBlanks(LYUserAgent); /* Won't send it at all if all blank - kw */ if (*cp != '\0') HTSprintf(&command, "User-Agent: %.*s%c%c", INIT_LINE_SIZE-15, LYUserAgent, CR, LF); } else { HTSprintf(&command, "User-Agent: %s/%s libwww-FM/%s%c%c", HTAppName ? HTAppName : "unknown", HTAppVersion ? HTAppVersion : "0.0", HTLibraryVersion, CR, LF); } if (personal_mail_address && !LYNoFromHeader) { HTSprintf(&command, "From: %s%c%c", personal_mail_address, CR,LF); } if (!(LYUserSpecifiedURL || LYNoRefererHeader || LYNoRefererForThis) && strcmp(HTLoadedDocumentURL(), "")) { char *cp = LYRequestReferer; if (!cp) cp = HTLoadedDocumentURL(); /* @@@ Try both? - kw */ StrAllocCat(command, "Referer: "); if (!strncasecomp(cp, "LYNXIMGMAP:", 11)) { char *cp1 = strchr(cp, '#'); if (cp1) *cp1 = '\0'; StrAllocCat(command, cp + 11); if (cp1) *cp1 = '#'; } else { StrAllocCat(command, cp); } HTSprintf(&command, "%c%c", CR, LF); } { char *abspath; char *docname; char *hostname; char *colon; int portnumber; char *auth, *cookie = NULL; BOOL secure = (BOOL) (strncmp(anAnchor->address, "https", 5) ? FALSE : TRUE); abspath = HTParse(arg, "", PARSE_PATH|PARSE_PUNCTUATION); docname = HTParse(arg, "", PARSE_PATH); hostname = HTParse(arg, "", PARSE_HOST); if (hostname && NULL != (colon = strchr(hostname, ':'))) { *(colon++) = '\0'; /* Chop off port number */ portnumber = atoi(colon); } else if (!strncmp(arg, "https", 5)) { portnumber = HTTPS_PORT; } else { portnumber = HTTP_PORT; } /* ** Add Authorization, Proxy-Authorization, ** and/or Cookie headers, if applicable. */ if (using_proxy) { /* ** If we are using a proxy, first determine if ** we should include an Authorization header ** and/or Cookie header for the ultimate target ** of this request. - FM & AJL */ char *host2 = NULL, *path2 = NULL; int port2 = (strncmp(docname, "https", 5) ? HTTP_PORT : HTTPS_PORT); host2 = HTParse(docname, "", PARSE_HOST); path2 = HTParse(docname, "", PARSE_PATH|PARSE_PUNCTUATION); if (host2) { if ((colon = strchr(host2, ':')) != NULL) { /* Use non-default port number */ *colon = '\0'; colon++; port2 = atoi(colon); } } /* ** This composeAuth() does file access, i.e., for ** the ultimate target of the request. - AJL */ auth_proxy = NO; if ((auth = HTAA_composeAuth(host2, port2, path2, auth_proxy)) != NULL && *auth != '\0') { /* ** If auth is not NULL nor zero-length, it's ** an Authorization header to be included. - FM */ HTSprintf(&command, "%s%c%c", auth, CR, LF); CTRACE((tfp, "HTTP: Sending authorization: %s\n", auth)); } else if (auth && *auth == '\0') { /* ** If auth is a zero-length string, the user either ** cancelled or goofed at the username and password ** prompt. - FM */ if (!(traversal || dump_output_immediately) && HTConfirm(CONFIRM_WO_PASSWORD)) { show_401 = TRUE; } else { if (traversal || dump_output_immediately) HTAlert(FAILED_NEED_PASSWD);#ifdef USE_SSL if (did_connect) HTTP_NETCLOSE(s, handle);#endif /* USE_SSL */ FREE(command); FREE(hostname); FREE(docname); FREE(abspath); FREE(host2); FREE(path2); status = HT_NOT_LOADED; goto done; } } else { CTRACE((tfp, "HTTP: Not sending authorization (yet).\n")); } /* ** Add 'Cookie:' header, if it's HTTP or HTTPS ** document being proxied. */ if (!strncmp(docname, "http", 4)) { cookie = LYAddCookieHeader(host2, path2, port2, secure); } FREE(host2); FREE(path2); /* ** The next composeAuth() will be for the proxy. - AJL */ auth_proxy = YES; } else { /* ** Add cookie for a non-proxied request. - FM */ cookie = LYAddCookieHeader(hostname, abspath, portnumber, secure); auth_proxy = NO; } /* ** If we do have a cookie set, add it to the request buffer. - FM */ if (cookie != NULL) { if (*cookie != '$') { /* ** It's a historical cookie, so signal to the ** server that we support modern cookies. - FM */ StrAllocCat(command, "Cookie2: $Version=\"1\""); StrAllocCat(command, crlf); CTRACE((tfp, "HTTP: Sending Cookie2: $Version =\"1\"\n")); } if (*cookie != '\0') { /* ** It's not a zero-length string, so add the header. ** Note that any folding of long strings has been ** done already in LYCookie.c. - FM */ StrAllocCat(command, "Cookie: "); StrAllocCat(command, cookie); StrAllocCat(command, crlf); CTRACE((tfp, "HTTP: Sending Cookie: %s\n", cookie)); } FREE(cookie); } FREE(abspath); /* ** If we are using a proxy, auth_proxy should be YES, and ** we check here whether we want a Proxy-Authorization header ** for it. If we are not using a proxy, auth_proxy should ** still be NO, and we check here for whether we want an ** Authorization header. - FM & AJL */ if ((auth = HTAA_composeAuth(hostname, portnumber, docname, auth_proxy)) != NULL && *auth != '\0') { /* ** If auth is not NULL nor zero-length, it's ** an Authorization or Proxy-Authorization ** header to be included. - FM */ HTSprintf(&command, "%s%c%c", auth, CR, LF); CTRACE((tfp, (auth_proxy ? "HTTP: Sending proxy authorization: %s\n" : "HTTP: Sending authorization: %s\n"), auth)); } else if (auth && *auth == '\0') { /* ** If auth is a zero-length string, the user either ** cancelled or goofed at the username and password ** prompt. - FM */ if (!(traversal || dump_output_immediately) && HTConfirm(CONFIRM_WO_PASSWORD)) { if (auth_proxy == TRUE) { show_407 = TRUE; } else { show_401 = TRUE; } } else { if (traversal || dump_output_immediately) HTAlert(FAILED_NEED_PASSWD); FREE(command); FREE(hostname); FREE(docname); status = HT_NOT_LOADED; goto done; } } else { CTRACE((tfp, (auth_proxy ? "HTTP: Not sending proxy authorization (yet).\n" : "HTTP: Not sending authorization (yet).\n"))); } FREE(hostname); FREE(docname); } auth_proxy = NO; } if (#ifdef USE_SSL !do_connect &&#endif /* USE_SSL */ do_post) { CTRACE((tfp, "HTTP: Doing post, content-type '%s'\n", anAnchor->post_content_type ? anAnchor->post_content_type : "lose")); HTSprintf(&command, "Content-type: %s%c%c", anAnchor->post_content_type ? anAnchor->post_content_type : "lose", CR, LF); /* * FIXME: Ack! This assumes non-binary data! Icky! */ HTSprintf(&command, "Content-length: %d%c%c", (anAnchor->post_data) ? strlen (anAnchor->post_data) : 0, CR, LF); StrAllocCat(command, crlf); /* Blank line means "end" of headers */ StrAllocCat(command, anAnchor->post_data); } else StrAllocCat(command, crlf); /* Blank line means "end" of headers */#ifdef USE_SSL CTRACE((tfp, "Writing:\n%s%s----------------------------------\n", command, (anAnchor->post_data && !do_connect ? crlf : "")));#else CTRACE((tfp, "Writing:\n%s%s----------------------------------\n", command, (anAnchor->post_data ? crlf : "")));#endif /* USE_SSL */ _HTProgress (gettext("Sending HTTP request."));#ifdef NOT_ASCII /* S/390 -- gil -- 0548 */ { char *p;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -