📄 cookies.c
字号:
/* cookies.c * Cookies * (c) 2002 Mikulas Patocka * This file is a part of the Links program, released under GPL */#include "links.h"#define ACCEPT_NONE 0#define ACCEPT_ASK 1#define ACCEPT_ALL 2int accept_cookies = ACCEPT_ALL;tcount cookie_id = 0;struct list_head cookies = { &cookies, &cookies };struct list_head c_domains = { &c_domains, &c_domains };struct c_server { struct c_server *next; struct c_server *prev; int accept; unsigned char server[1];};struct list_head c_servers = { &c_servers, &c_servers };void accept_cookie(struct cookie *);void delete_cookie(struct cookie *);/* prototypes */int check_domain_security(unsigned char *, unsigned char *);struct cookie *find_cookie_id(void *);void reject_cookie(void *);void cookie_default(void *, int);void accept_cookie_always(void *);void accept_cookie_never(void *);void free_cookie(struct cookie *c){ mem_free(c->name); if (c->value) mem_free(c->value); if (c->server) mem_free(c->server); if (c->path) mem_free(c->path); if (c->domain) mem_free(c->domain);}int check_domain_security(unsigned char *server, unsigned char *domain){ size_t i, j, dl; int nd; if (domain[0] == '.') domain++; dl = strlen(domain); if (dl > strlen(server)) return 1; for (i = strlen(server) - dl, j = 0; server[i]; i++, j++) if (upcase(server[i]) != upcase(domain[j])) return 1; nd = 2; if (dl > 4 && domain[dl - 4] == '.') { unsigned char *tld[] = { "com", "edu", "net", "org", "gov", "mil", "int", NULL }; for (i = 0; tld[i]; i++) if (!casecmp(tld[i], &domain[dl - 3], 3)) { nd = 1; break; } } for (i = 0; domain[i]; i++) if (domain[i] == '.') if (!--nd) break; if (nd > 0) return 1; return 0;}/* sezere 1 cookie z retezce str, na zacatku nesmi byt zadne whitechars * na konci muze byt strednik nebo 0 * cookie musi byt ve tvaru nazev=hodnota, kolem rovnase nesmi byt zadne mezery * (respektive mezery se budou pocitat do nazvu a do hodnoty) */int set_cookie(struct terminal *term, unsigned char *url, unsigned char *str){ int noval = 0; struct cookie *cookie; struct c_server *cs; unsigned char *p, *q, *s, *server, *date, *document; if (accept_cookies == ACCEPT_NONE) return 0; for (p = str; *p != ';' && *p; p++) /*if (WHITECHAR(*p)) return 0*/; for (q = str; *q != '='; q++) if (!*q || q >= p) { noval = 1; break; } if (str == q || q + 1 == p) return 0; cookie = mem_alloc(sizeof(struct cookie)); document = get_url_data(url); server = get_host_name(url); cookie->name = memacpy(str, q - str); cookie->value = !noval ? memacpy(q + 1, p - q - 1) : NULL; cookie->server = stracpy(server); date = parse_header_param(str, "expires"); if (date) { cookie->expires = parse_http_date(date); /* kdo tohle napsal a proc ?? */ /*if (! cookie->expires) cookie->expires++;*/ /* no harm and we can use zero then */ mem_free(date); } else cookie->expires = 0; if (!(cookie->path = parse_header_param(str, "path"))) { /*unsigned char *w;*/ cookie->path = stracpy("/"); /* add_to_strn(&cookie->path, document); for (w = cookie->path; *w; w++) if (end_of_dir(cookie->path, *w)) { *w = 0; break; } for (w = cookie->path + strlen(cookie->path) - 1; w >= cookie->path; w--) if (*w == '/') { w[1] = 0; break; } */ } else { if (cookie->path[0] != '/') { add_to_strn(&cookie->path, "x"); memmove(cookie->path + 1, cookie->path, strlen(cookie->path) - 1); cookie->path[0] = '/'; } } if (!(cookie->domain = parse_header_param(str, "domain"))) cookie->domain = stracpy(server); if (cookie->domain[0] == '.') memmove(cookie->domain, cookie->domain + 1, strlen(cookie->domain)); if ((s = parse_header_param(str, "secure"))) { cookie->secure = 1; mem_free(s); } else cookie->secure = 0; if (check_domain_security(server, cookie->domain)) { mem_free(cookie->domain); cookie->domain = stracpy(server); } cookie->id = cookie_id++; foreach (cs, c_servers) if (!strcasecmp(cs->server, server)) { if (cs->accept) goto ok; else { free_cookie(cookie); mem_free(cookie); mem_free(server); return 0; } } if (accept_cookies != ACCEPT_ALL) { free_cookie(cookie); mem_free(cookie); mem_free(server); return 1; } ok: accept_cookie(cookie); mem_free(server); return 0;}void accept_cookie(struct cookie *c){ struct c_domain *cd; struct cookie *d, *e; foreach(d, cookies) if (!strcasecmp(d->name, c->name) && !strcasecmp(d->domain, c->domain)) { e = d; d = d->prev; del_from_list(e); free_cookie(e); mem_free(e); } if (c->value && !strcasecmp(c->value, "deleted")) { free_cookie(c); mem_free(c); return; } add_to_list(cookies, c); foreach(cd, c_domains) if (!strcasecmp(cd->domain, c->domain)) return; cd = mem_alloc(sizeof(struct c_domain) + strlen(c->domain) + 1); strcpy(cd->domain, c->domain); add_to_list(c_domains, cd);}void delete_cookie(struct cookie *c){ struct c_domain *cd; struct cookie *d; foreach(d, cookies) if (!strcasecmp(d->domain, c->domain)) goto x; foreach(cd, c_domains) if (!strcasecmp(cd->domain, c->domain)) { del_from_list(cd); mem_free(cd); break; } x: del_from_list(c); free_cookie(c); mem_free(c);}struct cookie *find_cookie_id(void *idp){ long id = (my_intptr_t)idp; struct cookie *c; foreach(c, cookies) if (c->id == id) return c; return NULL;}void reject_cookie(void *idp){ struct cookie *c; if (!(c = find_cookie_id(idp))) return; delete_cookie(c);}void cookie_default(void *idp, int a){ struct cookie *c; struct c_server *s; if (!(c = find_cookie_id(idp))) return; foreach(s, c_servers) if (!strcasecmp(s->server, c->server)) goto found; s = mem_alloc(sizeof(struct c_server) + strlen(c->server) + 1); strcpy(s->server, c->server); add_to_list(c_servers, s); found: s->accept = a;}void accept_cookie_always(void *idp){ cookie_default(idp, 1);}void accept_cookie_never(void *idp){ cookie_default(idp, 0); reject_cookie(idp);}int is_in_domain(unsigned char *d, unsigned char *s){ int dl = strlen(d); int sl = strlen(s); if (dl > sl) return 0; if (dl == sl) return !strcasecmp(d, s); if (s[sl - dl - 1] != '.') return 0; return !casecmp(d, s + sl - dl, dl);}int is_path_prefix(unsigned char *d, unsigned char *s){ int dl = strlen(d); int sl = strlen(s); if (!dl) return 1; if (dl > sl) return 0; if (memcmp(d, s, dl)) return 0; return d[dl - 1] == '/' || !s[dl] || s[dl] == '/' || s[dl] == POST_CHAR || s[dl] == '?' || s[dl] == '&';}int cookie_expired(struct cookie *c) /* parse_http_date is broken */{ return 0 && (c->expires && c->expires < time(NULL));}void send_cookies(unsigned char **s, int *l, unsigned char *url){ int nc = 0; struct c_domain *cd; struct cookie *c, *d; unsigned char *server = get_host_name(url); unsigned char *data = get_url_data(url); if (data > url) data--; foreach (cd, c_domains) if (is_in_domain(cd->domain, server)) goto ok; mem_free(server); return; ok: foreach (c, cookies) if (is_in_domain(c->domain, server)) if (is_path_prefix(c->path, data)) { if (cookie_expired(c)) { d = c; c = c->prev; del_from_list(d); free_cookie(d); mem_free(d); continue; } if (c->secure && casecmp(url, "https://", 8)) continue; if (!nc) add_to_str(s, l, "Cookie: "), nc = 1; else add_to_str(s, l, "; "); add_to_str(s, l, c->name); if (c->value) { add_to_str(s, l, "="); add_to_str(s, l, c->value); } } if (nc) add_to_str(s, l, "\r\n"); mem_free(server);}void init_cookies(void){ /* !!! FIXME: read cookies */}void cleanup_cookies(void){ struct cookie *c; free_list(c_domains); /* !!! FIXME: save cookies */ foreach (c, cookies) free_cookie(c); free_list(cookies);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -