📄 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)) { SSL_handle = 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) { _HTProgress(gettext("Retrying connection without TLS.")); 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 */ } X509_NAME_oneline(X509_get_subject_name(SSL_get_peer_certificate(handle)), ssl_dn, sizeof(ssl_dn)); if ((cert_host = strstr(ssl_dn, "/CN=")) == NULL) { HTSprintf0(&msg, gettext("SSL error:Can't find common name in certificate-Continue?")); if (! HTForcedPrompt(ssl_noprompt, msg, YES)) { status = HT_NOT_LOADED; FREE(msg); goto done; } } else { cert_host += 4; if ((p = strchr(cert_host, '/')) != NULL) *p = '\0'; if ((p = strchr(cert_host, ':')) != NULL) *p = '\0'; ssl_host = HTParse(url, "", PARSE_HOST); if ((p = strchr(ssl_host, ':')) != NULL) *p = '\0'; if (strcasecomp(ssl_host, cert_host)) { HTSprintf0(&msg, gettext("SSL error:host(%s)!=cert(%s)-Continue?"), ssl_host, cert_host); if (! HTForcedPrompt(ssl_noprompt, msg, YES)) { status = HT_NOT_LOADED; FREE(msg); goto done; } } } HTSprintf0(&msg, gettext("Secure %d-bit %s (%s) HTTP connection"), SSL_get_cipher_bits(handle, NULL), SSL_get_cipher_version(handle), SSL_get_cipher(handle)); _HTProgress(msg); FREE(msg); }#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"; BStrCopy0(command, "CONNECT "); } else#endif /* USE_SSL */ if (do_post) { METHOD = "POST"; BStrCopy0(command, "POST "); } else if (do_head) { METHOD = "HEAD"; BStrCopy0(command, "HEAD "); } else { METHOD = "GET"; BStrCopy0(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) BStrCat0(command, connect_host); else BStrCat0(command, p1+1); }#else if (using_proxy) BStrCat0(command, p1+1);#endif /* USE_SSL */ else BStrCat0(command, p1); FREE(p1); } if (extensions) { BStrCat0(command, " "); BStrCat0(command, HTTP_VERSION); } BStrCat0(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); HTBprintf(&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) { BStrCat0(command, crlf); HTSprintf0(&linebuf, "Accept: %s%s", HTAtom_name(pres->rep), temp); len = strlen(linebuf); } BStrCat0(command, linebuf); first_Accept = FALSE; } } HTBprintf(&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 { char *list = 0;#if defined(USE_ZLIB) || defined(GZIP_PATH) StrAllocCopy(list, "gzip");#endif#if defined(USE_ZLIB) || defined(COMPRESS_PATH) if (list != 0) StrAllocCat(list, ", "); StrAllocCat(list, "compress");#endif if (list != 0) { HTBprintf(&command, "Accept-Encoding: %s%c%c", list, CR, LF); free(list); } } if (language && *language) { HTBprintf(&command, "Accept-Language: %s%c%c", language, CR, LF); } if (pref_charset && *pref_charset) { BStrCat0(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"); BStrCat0(command, linebuf); HTBprintf(&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) { HTBprintf(&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) { HTBprintf(&command, "Pragma: no-cache%c%c", CR, LF); HTBprintf(&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') HTBprintf(&command, "User-Agent: %.*s%c%c", INIT_LINE_SIZE-15, LYUserAgent, CR, LF); } else { HTBprintf(&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) { HTBprintf(&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 */ BStrCat0(command, "Referer: "); if (isLYNXIMGMAP(cp)) { char *cp1 = trimPoundSelector(cp); BStrCat0(command, cp + LEN_LYNXIMGMAP); restorePoundSelector(cp1); } else { BStrCat0(command, cp); } HTBprintf(&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 */ HTBprintf(&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 */ BStrFree(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 */ BStrCat0(command, "Cookie2: $Version=\"1\""); BStrCat0(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 */ BStrCat0(command, "Cookie: "); BStrCat0(command, cookie); BStrCat0(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 */ HTBprintf(&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); BStrFree(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")); HTBprintf(&command, "Content-type: %s%c%c", anAnchor->post_content_type ? anAnchor->post_content_type : "lose", CR, LF); HTBprintf(&command, "Content-length: %d%c%c", !isBEmpty(anAnchor->post_data) ? BStrLen(anAnchor->post_data) : 0, CR, LF);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -