📄 cookies.c
字号:
uri->hostlen, uri->host);#endif mem_free(cookie->domain); cookie->domain = memacpy(uri->host, uri->hostlen); } /* We have already check COOKIES_ACCEPT_NONE */ if (get_cookies_accept_policy() == COOKIES_ACCEPT_ASK) { add_to_list(cookie_queries, cookie); add_questions_entry(accept_cookie_dialog, cookie); return; } accept_cookie(cookie);}static voiddel_from_cookie_list(struct cookie *cookie){ del_from_list(cookie); free_cookie(cookie);}voidaccept_cookie(struct cookie *cookie){ struct c_domain *cd; struct listbox_item *root = cookie->server->box_item; int domain_len; if (root) cookie->box_item = add_listbox_leaf(&cookie_browser, root, cookie); /* Do not weed out duplicates when loading the cookie file. It doesn't * scale at all, being O(N^2) and taking about 2s with my 500 cookies * (so if you don't notice that 100ms with your 100 cookies, that's * not an argument). --pasky */ if (!cookies_nosave) { struct cookie *c, *next; foreachsafe (c, next, cookies) { if (strcasecmp(c->name, cookie->name) || strcasecmp(c->domain, cookie->domain)) continue; del_from_cookie_list(c); } } add_to_list(cookies, cookie); cookies_dirty = 1; /* XXX: This crunches CPU too. --pasky */ foreach (cd, c_domains) if (!strcasecmp(cd->domain, cookie->domain)) return; domain_len = strlen(cookie->domain); /* One byte is reserved for domain in struct c_domain. */ cd = mem_alloc(sizeof(*cd) + domain_len); if (!cd) return; memcpy(cd->domain, cookie->domain, domain_len + 1); add_to_list(c_domains, cd); if (get_cookies_save() && get_cookies_resave()) save_cookies();}#if 0static unsigned int cookie_id = 0;static voiddelete_cookie(struct cookie *c){ struct c_domain *cd; struct cookie *d; foreach (d, cookies) if (!strcasecmp(d->domain, c->domain)) goto end; foreach (cd, c_domains) { if (!strcasecmp(cd->domain, c->domain)) { del_from_list(cd); mem_free(cd); break; } }end: del_from_list(c); free_cookie(c); if (get_cookies_save() && get_cookies_resave()) save_cookies();}static structcookie *find_cookie_id(void *idp){ int id = (int) idp; struct cookie *c; foreach (c, cookies) if (c->id == id) return c; return NULL;}static voidreject_cookie(void *idp){ struct cookie *c = find_cookie_id(idp); if (!c) return; delete_cookie(c);}static voidcookie_default(void *idp, int a){ struct cookie *c = find_cookie_id(idp); if (c) c->server->accept = a;}static voidaccept_cookie_always(void *idp){ cookie_default(idp, 1);}static voidaccept_cookie_never(void *idp){ cookie_default(idp, 0); reject_cookie(idp);}#endif/* Check whether domain is matching server * Ie. * example.com matches www.example.com/ * example.com doesn't match www.example.com.org/ * example.com doesn't match www.example.comm/ * example.com doesn't match example.co */static intis_in_domain(unsigned char *domain, unsigned char *server, int server_len){ int domain_len = strlen(domain); int len; if (domain_len > server_len) return 0; if (domain_len == server_len) return !strncasecmp(domain, server, server_len); len = server_len - domain_len; if (server[len - 1] != '.') return 0; return !strncasecmp(domain, server + len, domain_len);}static inline intis_path_prefix(unsigned char *d, unsigned char *s){ int dl = strlen(d); /* TODO: strlcmp()? --pasky */ if (dl > strlen(s)) return 0; return !memcmp(d, s, dl);}#define is_expired(t) ((t) && (t) <= time(NULL))#define is_dead(t) (!(t) || (t) <= time(NULL))struct string *send_cookies(struct uri *uri){ struct c_domain *cd; struct cookie *c, *next; unsigned char *path = NULL; static struct string header; if (!uri->host || !uri->data) return NULL; foreach (cd, c_domains) if (is_in_domain(cd->domain, uri->host, uri->hostlen)) { path = get_uri_string(uri, URI_PATH); break; } if (!path) return NULL; init_string(&header); foreachsafe (c, next, cookies) { if (!is_in_domain(c->domain, uri->host, uri->hostlen) || !is_path_prefix(c->path, path)) continue; if (is_expired(c->expires)) {#ifdef DEBUG_COOKIES DBG("Cookie %s=%s (exp %d) expired.", c->name, c->value, c->expires);#endif del_from_cookie_list(c); cookies_dirty = 1; continue; } /* Not sure if this is 100% right..? --pasky */ if (c->secure && uri->protocol != PROTOCOL_HTTPS) continue; if (header.length) add_to_string(&header, "; "); add_to_string(&header, c->name); add_char_to_string(&header, '='); add_to_string(&header, c->value);#ifdef DEBUG_COOKIES DBG("Cookie: %s=%s", c->name, c->value);#endif } mem_free(path); if (cookies_dirty && get_cookies_save() && get_cookies_resave()) save_cookies(); if (!header.length) { done_string(&header); return NULL; } return &header;}static void done_cookies(struct module *module);voidload_cookies(void) { /* Buffer size is set to be enough to read long lines that * save_cookies may write. 6 is choosen after the fprintf(..) call * in save_cookies(). --Zas */ unsigned char in_buffer[6 * MAX_STR_LEN]; unsigned char *cookfile = COOKIES_FILENAME; FILE *fp; if (elinks_home) { cookfile = straconcat(elinks_home, cookfile, NULL); if (!cookfile) return; } /* Do it here, as we will delete whole cookies list if the file was * removed */ cookies_nosave = 1; done_cookies(&cookies_module); cookies_nosave = 0; fp = fopen(cookfile, "rb"); if (elinks_home) mem_free(cookfile); if (!fp) return; /* XXX: We don't want to overwrite the cookies file * periodically to our death. */ cookies_nosave = 1; while (fgets(in_buffer, 6 * MAX_STR_LEN, fp)) { struct cookie *cookie; unsigned char *p, *q = in_buffer; enum { NAME = 0, VALUE, SERVER, PATH, DOMAIN, EXPIRES, SECURE, MEMBERS } member; struct { unsigned char *pos; int len; } members[MEMBERS]; ttime expires; /* First find all members. */ for (member = NAME; member < MEMBERS; member++, q = ++p) { p = strchr(q, '\t'); if (!p) { if (member + 1 != MEMBERS) break; /* last field ? */ p = strchr(q, '\n'); if (!p) break; } members[member].pos = q; members[member].len = p - q; } if (member != MEMBERS) continue; /* Invalid line. */ /* Skip expired cookies if any. */ expires = str_to_ttime(members[EXPIRES].pos); if (is_dead(expires)) { cookies_dirty = 1; continue; } /* Prepare cookie if all members and fields was read. */ cookie = mem_calloc(1, sizeof(*cookie)); if (!cookie) continue; cookie->server = get_cookie_server(members[SERVER].pos, members[SERVER].len); cookie->name = memacpy(members[NAME].pos, members[NAME].len); cookie->value = memacpy(members[VALUE].pos, members[VALUE].len); cookie->path = memacpy(members[PATH].pos, members[PATH].len); cookie->domain = memacpy(members[DOMAIN].pos, members[DOMAIN].len); /* Check whether all fields were correctly allocated. */ if (!cookie->server || !cookie->name || !cookie->value || !cookie->path || !cookie->domain) { free_cookie(cookie); continue; } cookie->expires = expires; cookie->secure = !!atoi(members[SECURE].pos); accept_cookie(cookie); } cookies_nosave = 0; fclose(fp);}voidsave_cookies(void) { struct cookie *c; unsigned char *cookfile; struct secure_save_info *ssi; if (cookies_nosave || !elinks_home || !cookies_dirty || get_cmd_opt_bool("anonymous")) return; cookfile = straconcat(elinks_home, COOKIES_FILENAME, NULL); if (!cookfile) return; ssi = secure_open(cookfile, 0177); /* rw for user only */ mem_free(cookfile); if (!ssi) return; foreach (c, cookies) { if (is_dead(c->expires)) continue; if (secure_fprintf(ssi, "%s\t%s\t%s\t%s\t%s\t%ld\t%d\n", c->name, c->value, c->server->host, empty_string_or_(c->path), empty_string_or_(c->domain), c->expires, c->secure) < 0) break; } if (!secure_close(ssi)) cookies_dirty = 0;}static voidinit_cookies(struct module *module){ if (get_cookies_save()) load_cookies();}static voidfree_cookies_list(struct list_head *list){ while (!list_empty(*list)) { struct cookie *cookie = list->next; del_from_list(cookie); free_cookie(cookie); }}static voiddone_cookies(struct module *module){ free_list(c_domains); if (!cookies_nosave && get_cookies_save()) save_cookies(); free_cookies_list(&cookies); free_cookies_list(&cookie_queries);}struct module cookies_module = struct_module( /* name: */ N_("Cookies"), /* options: */ cookies_options, /* events: */ NULL, /* submodules: */ NULL, /* data: */ NULL, /* init: */ init_cookies, /* done: */ done_cookies);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -