http.c
来自「elinks下lynx是最重要的二个文本浏览器, 在linux下非常实用, el」· C语言 代码 · 共 1,812 行 · 第 1/4 页
C
1,812 行
return 0; for (s = buggy_servers; *s; s++) { if (strstr(server, *s)) { add_blacklist_entry(uri, SERVER_BLACKLIST_HTTP10); break; } } mem_free(server); return (*s != NULL);}static voidhttp_end_request(struct connection *conn, enum connection_state state, int notrunc){ shutdown_connection_stream(conn); if (state == S_OK && conn->cached) { normalize_cache_entry(conn->cached, !notrunc ? conn->from : -1); } if (conn->info && !((struct http_connection_info *) conn->info)->close && (!conn->socket->ssl) /* We won't keep alive ssl connections */ && (!get_opt_bool("protocol.http.bugs.post_no_keepalive") || !conn->uri->post)) { set_connection_state(conn, state); add_keepalive_connection(conn, HTTP_KEEPALIVE_TIMEOUT, NULL); } else { abort_connection(conn, state); }}static void http_send_header(struct socket *);voidhttp_protocol_handler(struct connection *conn){ /* setcstate(conn, S_CONN); */ if (!has_keepalive_connection(conn)) { make_connection(conn->socket, conn->uri, http_send_header, conn->cache_mode >= CACHE_MODE_FORCE_RELOAD); } else { http_send_header(conn->socket); }}voidproxy_protocol_handler(struct connection *conn){ http_protocol_handler(conn);}#define IS_PROXY_URI(x) ((x)->protocol == PROTOCOL_PROXY)#define connection_is_https_proxy(conn) \ (IS_PROXY_URI((conn)->uri) && (conn)->proxied_uri->protocol == PROTOCOL_HTTPS)struct http_connection_info *init_http_connection_info(struct connection *conn, int major, int minor, int close){ struct http_connection_info *http; http = mem_calloc(1, sizeof(*http)); if (!http) { http_end_request(conn, S_OUT_OF_MEM, 0); return NULL; } http->sent_version.major = major; http->sent_version.minor = minor; http->close = close; /* The CGI code uses this too and blacklisting expects a host name. */ if (conn->proxied_uri->protocol != PROTOCOL_FILE) http->bl_flags = get_blacklist_flags(conn->proxied_uri); if (http->bl_flags & SERVER_BLACKLIST_HTTP10 || get_opt_bool("protocol.http.bugs.http10")) { http->sent_version.major = 1; http->sent_version.minor = 0; } /* If called from HTTPS proxy connection the connection info might have * already been allocated. */ mem_free_set(&conn->info, http); return http;}static voidhttp_send_header(struct socket *socket){ struct connection *conn = socket->conn; struct http_connection_info *http; int trace = get_opt_bool("protocol.http.trace"); struct string header; unsigned char *post_data = NULL; struct auth_entry *entry; struct uri *uri = conn->proxied_uri; /* Set to the real uri */ unsigned char *optstr; int use_connect, talking_to_proxy; /* Sanity check for a host */ if (!uri || !uri->host || !*uri->host || !uri->hostlen) { http_end_request(conn, S_BAD_URL, 0); return; } http = init_http_connection_info(conn, 1, 1, 0); if (!http) return; if (!init_string(&header)) { http_end_request(conn, S_OUT_OF_MEM, 0); return; } talking_to_proxy = IS_PROXY_URI(conn->uri) && !conn->socket->ssl; use_connect = connection_is_https_proxy(conn) && !conn->socket->ssl; if (trace) { add_to_string(&header, "TRACE "); } else if (use_connect) { add_to_string(&header, "CONNECT "); } else if (uri->post) { add_to_string(&header, "POST "); conn->unrestartable = 1; } else { add_to_string(&header, "GET "); } if (!talking_to_proxy) { add_char_to_string(&header, '/'); } if (use_connect) { /* Add port if it was specified or the default port */ add_uri_to_string(&header, uri, URI_HTTP_CONNECT); } else { if (connection_is_https_proxy(conn) && conn->socket->ssl) { add_url_to_http_string(&header, uri, URI_DATA); } else if (talking_to_proxy) { add_url_to_http_string(&header, uri, URI_PROXY); } else { add_url_to_http_string(&header, conn->uri, URI_DATA); } } add_to_string(&header, " HTTP/"); add_long_to_string(&header, http->sent_version.major); add_char_to_string(&header, '.'); add_long_to_string(&header, http->sent_version.minor); add_crlf_to_string(&header); add_to_string(&header, "Host: "); add_uri_to_string(&header, uri, URI_HTTP_HOST); add_crlf_to_string(&header); if (talking_to_proxy) { unsigned char *user = get_opt_str("protocol.http.proxy.user"); unsigned char *passwd = get_opt_str("protocol.http.proxy.passwd"); if (proxy_auth.digest) { unsigned char *response; int userlen = int_min(strlen(user), AUTH_USER_MAXLEN - 1); int passwordlen = int_min(strlen(passwd), AUTH_PASSWORD_MAXLEN - 1); if (userlen) memcpy(proxy_auth.user, user, userlen); proxy_auth.user[userlen] = '\0'; if (passwordlen) memcpy(proxy_auth.password, passwd, passwordlen); proxy_auth.password[passwordlen] = '\0'; /* FIXME: @uri is the proxied URI. Maybe the passed URI * should be the proxy URI aka conn->uri. --jonas */ response = get_http_auth_digest_response(&proxy_auth, uri); if (response) { add_to_string(&header, "Proxy-Authorization: Digest "); add_to_string(&header, response); add_crlf_to_string(&header); mem_free(response); } } else { if (user[0]) { unsigned char *proxy_data; proxy_data = straconcat(user, ":", passwd, NULL); if (proxy_data) { unsigned char *proxy_64 = base64_encode(proxy_data); if (proxy_64) { add_to_string(&header, "Proxy-Authorization: Basic "); add_to_string(&header, proxy_64); add_crlf_to_string(&header); mem_free(proxy_64); } mem_free(proxy_data); } } } } optstr = get_opt_str("protocol.http.user_agent"); if (*optstr && strcmp(optstr, " ")) { unsigned char *ustr, ts[64] = ""; add_to_string(&header, "User-Agent: "); if (!list_empty(terminals)) { unsigned int tslen = 0; struct terminal *term = terminals.prev; ulongcat(ts, &tslen, term->width, 3, 0); ts[tslen++] = 'x'; ulongcat(ts, &tslen, term->height, 3, 0); } ustr = subst_user_agent(optstr, VERSION_STRING, system_name, ts); if (ustr) { add_to_string(&header, ustr); mem_free(ustr); } add_crlf_to_string(&header); } switch (get_opt_int("protocol.http.referer.policy")) { case REFERER_NONE: /* oh well */ break; case REFERER_FAKE: optstr = get_opt_str("protocol.http.referer.fake"); if (!optstr[0]) break; add_to_string(&header, "Referer: "); add_to_string(&header, optstr); add_crlf_to_string(&header); break; case REFERER_TRUE: if (!conn->referrer) break; add_to_string(&header, "Referer: "); add_url_to_http_string(&header, conn->referrer, URI_HTTP_REFERRER); add_crlf_to_string(&header); break; case REFERER_SAME_URL: add_to_string(&header, "Referer: "); add_url_to_http_string(&header, uri, URI_HTTP_REFERRER); add_crlf_to_string(&header); break; } add_to_string(&header, "Accept: */*"); add_crlf_to_string(&header); /* TODO: Make this encoding.c function. */#if defined(CONFIG_GZIP) || defined(CONFIG_BZIP2) add_to_string(&header, "Accept-Encoding: ");#ifdef BUG_517#ifdef CONFIG_BZIP2 add_to_string(&header, "bzip2");#endif#endif#ifdef CONFIG_GZIP#ifdef BUG_517#ifdef CONFIG_BZIP2 add_to_string(&header, ", ");#endif#endif add_to_string(&header, "gzip");#endif add_crlf_to_string(&header);#endif if (!accept_charset) { init_accept_charset(); } if (!(http->bl_flags & SERVER_BLACKLIST_NO_CHARSET) && !get_opt_bool("protocol.http.bugs.accept_charset") && accept_charset) { add_to_string(&header, accept_charset); } optstr = get_opt_str("protocol.http.accept_language"); if (optstr[0]) { add_to_string(&header, "Accept-Language: "); add_to_string(&header, optstr); add_crlf_to_string(&header); }#ifdef CONFIG_NLS else if (get_opt_bool("protocol.http.accept_ui_language")) { unsigned char *code = language_to_iso639(current_language); if (code) { add_to_string(&header, "Accept-Language: "); add_to_string(&header, code); add_crlf_to_string(&header); } }#endif /* FIXME: What about post-HTTP/1.1?? --Zas */ if (HTTP_1_1(http->sent_version)) { if (!IS_PROXY_URI(conn->uri)) { add_to_string(&header, "Connection: "); } else { add_to_string(&header, "Proxy-Connection: "); } if (!uri->post || !get_opt_bool("protocol.http.bugs.post_no_keepalive")) { add_to_string(&header, "Keep-Alive"); } else { add_to_string(&header, "close"); } add_crlf_to_string(&header); } if (conn->cached) { if (!conn->cached->incomplete && conn->cached->head && conn->cached->last_modified && conn->cache_mode <= CACHE_MODE_CHECK_IF_MODIFIED) { add_to_string(&header, "If-Modified-Since: "); add_to_string(&header, conn->cached->last_modified); add_crlf_to_string(&header); } } if (conn->cache_mode >= CACHE_MODE_FORCE_RELOAD) { add_to_string(&header, "Pragma: no-cache"); add_crlf_to_string(&header); add_to_string(&header, "Cache-Control: no-cache"); add_crlf_to_string(&header); } if (conn->from || conn->progress->start > 0) { /* conn->from takes precedence. conn->progress.start is set only the first * time, then conn->from gets updated and in case of any retries * etc we have everything interesting in conn->from already. */ add_to_string(&header, "Range: bytes="); add_long_to_string(&header, conn->from ? conn->from : conn->progress->start); add_char_to_string(&header, '-'); add_crlf_to_string(&header); } entry = find_auth(uri); if (entry) { if (entry->digest) { unsigned char *response; response = get_http_auth_digest_response(entry, uri); if (response) { add_to_string(&header, "Authorization: Digest "); add_to_string(&header, response); add_crlf_to_string(&header); mem_free(response); } } else { /* RFC2617 section 2 [Basic Authentication Scheme] * * To receive authorization, the client sends the userid * and password, separated by a single colon (":") * character, within a base64 [7] encoded string in the * credentials. */ unsigned char *id; /* Create base64 encoded string. */ id = straconcat(entry->user, ":", entry->password, NULL); if (id) { unsigned char *base64 = base64_encode(id); mem_free_set(&id, base64); } if (id) { add_to_string(&header, "Authorization: Basic "); add_to_string(&header, id); add_crlf_to_string(&header); mem_free(id); } } } if (uri->post) { /* We search for first '\n' in uri->post to get content type * as set by get_form_uri(). This '\n' is dropped if any * and replaced by correct '\r\n' termination here. */ unsigned char *postend = strchr(uri->post, '\n'); if (postend) { add_to_string(&header, "Content-Type: "); add_bytes_to_string(&header, uri->post, postend - uri->post); add_crlf_to_string(&header); } post_data = postend ? postend + 1 : uri->post; add_to_string(&header, "Content-Length: "); add_long_to_string(&header, strlen(post_data) / 2); add_crlf_to_string(&header); }#ifdef CONFIG_COOKIES { struct string *cookies = send_cookies(uri); if (cookies) { add_to_string(&header, "Cookie: "); add_string_to_string(&header, cookies); add_crlf_to_string(&header); done_string(cookies); } }#endif add_crlf_to_string(&header); if (post_data) {#define POST_BUFFER_SIZE 4096 unsigned char *post = post_data; unsigned char buffer[POST_BUFFER_SIZE]; int n = 0; while (post[0] && post[1]) { int h1, h2; h1 = unhx(post[0]); assert(h1 >= 0 && h1 < 16); if_assert_failed h1 = 0; h2 = unhx(post[1]); assert(h2 >= 0 && h2 < 16); if_assert_failed h2 = 0; buffer[n++] = (h1<<4) + h2; post += 2; if (n == POST_BUFFER_SIZE) { add_bytes_to_string(&header, buffer, n); n = 0; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?