http.c
来自「this is the file used to browse web」· C语言 代码 · 共 684 行 · 第 1/2 页
C
684 行
#include "links.h"struct http_connection_info { int bl_flags; int http10; int close; int length; int version; int chunk_remaining;};unsigned char *parse_http_header(unsigned char *head, unsigned char *item, unsigned char **ptr){ unsigned char *i, *f, *g, *h; if (!head) return NULL; h = NULL; for (f = head; *f; f++) { if (*f != 10) continue; f++; for (i = item; *i && *f; i++, f++) if (upcase(*i) != upcase(*f)) goto cont; if (!*f) break; if (f[0] == ':') { while (f[1] == ' ') f++; for (g = ++f; *g >= ' '; g++) ; while (g > f && g[-1] == ' ') g--; if (h) mem_free(h); h = mem_alloc(g - f + 1); memcpy(h, f, g - f); h[g - f] = 0; if (ptr) { *ptr = f; break; } return h; } cont:; f--; } return h;}unsigned char *parse_header_param(unsigned char *x, unsigned char *e){ unsigned char u; size_t le = strlen(e); int lp; unsigned char *y = x; a: if (!(y = strchr(y, ';'))) return NULL; while (*y && (*y == ';' || *y <= ' ')) y++; if (strlen(y) < le) return NULL; if (casecmp(y, e, le)) goto a; y += le; while (*y && (*y <= ' ' || *y == '=')) y++; u = ';'; if (*y == '\'' || *y == '"') u = *y++; lp = 0; while (y[lp] >= ' ' && y[lp] != u) { lp++; if (lp == MAXINT) overalloc(); } return memacpy(y, lp);}/* Parse string param="value", return value as new string or NULL if any error.*/unsigned char *get_param(unsigned char *e, unsigned char *name){ unsigned char *n, *start; int i = 0;again: while (*e && upcase(*e++) != upcase(*name)); if (!*e) return NULL; n = name + 1; while (*n && upcase(*e) == upcase(*n)) e++, n++; if (*n) goto again; while (WHITECHAR(*e)) e++; if (*e++ != '=') return NULL; while (WHITECHAR(*e)) e++; start = e; if (!U(*e)) while (*e && !WHITECHAR(*e)) e++; else { char uu = *e++; start++; while (*e != uu) { if (!*e) return NULL; e++; } } while (start < e && *start == ' ') start++; while (start < e && *(e - 1) == ' ') e--; if (start == e) return NULL; n = mem_alloc(e - start + 1); while (start < e) { if (*start < ' ') n[i] = '.'; else n[i] = *start; i++; start++; } n[i] = 0; return n;}static int get_http_code(unsigned char *head, int *code, int *version){ while (head[0] == ' ') head++; if (upcase(head[0]) != 'H' || upcase(head[1]) != 'T' || upcase(head[2]) != 'T' || upcase(head[3]) != 'P') return -1; if (head[4] == '/' && head[5] >= '0' && head[5] <= '9' && head[6] == '.' && head[7] >= '0' && head[7] <= '9' && head[8] <= ' ') { *version = (head[5] - '0') * 10 + head[7] - '0'; } else *version = 0; for (head += 4; *head > ' '; head++) ; if (*head++ != ' ') return -1; if (head[0] < '1' || head [0] > '9' || head[1] < '0' || head[1] > '9' || head[2] < '0' || head [2] > '9') return -1; *code = (head[0]-'0')*100 + (head[1]-'0')*10 + head[2]-'0'; return 0;}struct { unsigned char *name; int bugs;} buggy_servers[] = { { "mod_czech/3.1.0", BL_HTTP10 }, { "Purveyor", BL_HTTP10 }, { "Netscape-Enterprise", BL_HTTP10 | BL_NO_ACCEPT_LANGUAGE }, { "Apache Coyote", BL_HTTP10 }, { "lighttpd", BL_HTTP10 }, { "FORPSI", BL_NO_RANGE },
{ NULL, 0 }};int check_http_server_bugs(unsigned char *url, struct http_connection_info *info, unsigned char *head){ unsigned char *server; int i, bugs; if (!http_bugs.allow_blacklist || info->http10) return 0; if (!(server = parse_http_header(head, "Server", NULL))) return 0; bugs = 0; for (i = 0; buggy_servers[i].name; i++) if (strstr(server, buggy_servers[i].name)) bugs |= buggy_servers[i].bugs; mem_free(server); if (bugs && (server = get_host_name(url))) { add_blacklist_entry(server, bugs); mem_free(server); return bugs & ~BL_NO_RANGE;
} return 0; }void http_end_request(struct connection *c, int notrunc){ if (c->state == S_OK) { if (c->cache) { if (!notrunc) truncate_entry(c->cache, c->from, 1); c->cache->incomplete = 0; } } if (c->info && !((struct http_connection_info *)c->info)->close #ifdef HAVE_SSL && (!c->ssl) /* We won't keep alive ssl connections */#endif && (!http_bugs.bug_post_no_keepalive || !strchr(c->url, POST_CHAR))) { add_keepalive_socket(c, HTTP_KEEPALIVE_TIMEOUT); } else abort_connection(c);}void http_send_header(struct connection *);void http_func(struct connection *c){ /*setcstate(c, S_CONN);*/ /*set_timeout(c);*/ if (get_keepalive_socket(c)) { int p; if ((p = get_port(c->url)) == -1) { setcstate(c, S_INTERNAL); abort_connection(c); return; } make_connection(c, p, &c->sock1, http_send_header); } else http_send_header(c);}void proxy_func(struct connection *c){ http_func(c);}void http_get_header(struct connection *);void http_send_header(struct connection *c){ static unsigned char *accept_charset = NULL; struct http_connection_info *info; int http10 = http_bugs.http10; struct cache_entry *e = NULL; unsigned char *hdr; unsigned char *h, *u, *uu, *sp; int l = 0; int la; unsigned char *post; unsigned char *host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url); set_timeout(c); info = mem_alloc(sizeof(struct http_connection_info)); memset(info, 0, sizeof(struct http_connection_info)); c->info = info; if ((h = get_host_name(host))) { info->bl_flags = get_blacklist_flags(h); mem_free(h); } if (info->bl_flags & BL_HTTP10) http10 = 1; info->http10 = http10; post = strchr(c->url, POST_CHAR); if (post) post++; hdr = init_str(); if (!post) add_to_str(&hdr, &l, "GET "); else { add_to_str(&hdr, &l, "POST "); c->unrestartable = 2; } if (upcase(c->url[0]) != 'P') add_to_str(&hdr, &l, "/"); if (!(u = get_url_data(c->url))) { mem_free(hdr); setcstate(c, S_BAD_URL); http_end_request(c, 0); return; } if (post && post < u) { mem_free(hdr); setcstate(c, S_BAD_URL); http_end_request(c, 0); return; } if (!post) uu = stracpy(u); else uu = memacpy(u, post - u - 1); a: for (sp = uu; *sp; sp++) if (*sp <= ' ') { unsigned char *nu = mem_alloc(strlen(uu) + 3); memcpy(nu, uu, sp - uu); sprintf(nu + (sp - uu), "%%%02X", (int)*sp); strcat(nu, sp + 1); mem_free(uu); uu = nu; goto a; } else if (*sp == '\\') *sp = '/'; add_to_str(&hdr, &l, uu); mem_free(uu); if (!http10) add_to_str(&hdr, &l, " HTTP/1.1\r\n"); else add_to_str(&hdr, &l, " HTTP/1.0\r\n"); if ((h = get_host_name(host))) { add_to_str(&hdr, &l, "Host: "); add_to_str(&hdr, &l, h); mem_free(h); if ((h = get_port_str(host))) { add_to_str(&hdr, &l, ":"); add_to_str(&hdr, &l, h); mem_free(h); } add_to_str(&hdr, &l, "\r\n"); } add_to_str(&hdr, &l, "User-Agent: Links (" VERSION_STRING "; "); add_to_str(&hdr, &l, system_name); if (!list_empty(terminals)) { struct terminal *t = terminals.prev; add_to_str(&hdr, &l, "; "); add_num_to_str(&hdr, &l, t->x); add_to_str(&hdr, &l, "x"); add_num_to_str(&hdr, &l, t->y); } add_to_str(&hdr, &l, ")\r\n"); add_to_str(&hdr, &l, "Accept: */*\r\n"); if (!(accept_charset)) { int i; unsigned char *cs, *ac; int aclen = 0; ac = init_str(); for (i = 0; (cs = get_cp_mime_name(i)); i++) { if (aclen) add_to_str(&ac, &aclen, ", "); else add_to_str(&ac, &aclen, "Accept-Charset: "); add_to_str(&ac, &aclen, cs); } if (aclen) add_to_str(&ac, &aclen, "\r\n"); if ((accept_charset = malloc(strlen(ac) + 1))) strcpy(accept_charset, ac); else accept_charset = ""; mem_free(ac); } if (!(info->bl_flags & BL_NO_CHARSET) && !http_bugs.no_accept_charset) add_to_str(&hdr, &l, accept_charset); if (!(info->bl_flags & BL_NO_ACCEPT_LANGUAGE)) { add_to_str(&hdr, &l, "Accept-Language: "); la = l; add_to_str(&hdr, &l, _(TEXT(T__ACCEPT_LANGUAGE), NULL)); add_to_str(&hdr, &l, ", "); if (!strstr(hdr + la, "en,") && !strstr(hdr + la, "en;")) add_to_str(&hdr, &l, "en;q=0.2, "); add_to_str(&hdr, &l, "*;q=0.1\r\n"); } if (!http10) { if (upcase(c->url[0]) != 'P') add_to_str(&hdr, &l, "Connection: "); else add_to_str(&hdr, &l, "Proxy-Connection: "); if (!post || !http_bugs.bug_post_no_keepalive) add_to_str(&hdr, &l, "Keep-Alive\r\n"); else add_to_str(&hdr, &l, "close\r\n"); } if ((e = c->cache)) { int code, vers; if (get_http_code(e->head, &code, &vers) || code >= 400) goto skip_ifmod_and_range; if (!e->incomplete && e->head && c->no_cache <= NC_IF_MOD && e->last_modified) { add_to_str(&hdr, &l, "If-Modified-Since: "); add_to_str(&hdr, &l, e->last_modified); add_to_str(&hdr, &l, "\r\n"); } } if (c->from && (c->est_length == -1 || c->from < c->est_length) && c->no_cache < NC_IF_MOD && !(info->bl_flags & BL_NO_RANGE)) { add_to_str(&hdr, &l, "Range: bytes="); add_num_to_str(&hdr, &l, c->from); add_to_str(&hdr, &l, "-\r\n"); } skip_ifmod_and_range: if (c->no_cache >= NC_PR_NO_CACHE) add_to_str(&hdr, &l, "Pragma: no-cache\r\nCache-Control: no-cache\r\n"); if (post) { unsigned char *pd = strchr(post, '\n'); if (pd) { add_to_str(&hdr, &l, "Content-Type: "); add_bytes_to_str(&hdr, &l, post, pd - post); add_to_str(&hdr, &l, "\r\n"); post = pd + 1; } add_to_str(&hdr, &l, "Content-Length: "); add_num_to_str(&hdr, &l, strlen(post) / 2); add_to_str(&hdr, &l, "\r\n"); } send_cookies(&hdr, &l, host); add_to_str(&hdr, &l, "\r\n"); if (post) { while (post[0] && post[1]) { int h1, h2; h1 = post[0] <= '9' ? post[0] - '0' : post[0] >= 'A' ? upcase(post[0]) - 'A' + 10 : 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?