int set_cookie_header_cb (const char *hdr, void *closure) { struct url *u = (struct url *)closure; struct cookie *cookie; cookies_now = time (NULL); cookie = parse_set_cookies (hdr); if (!cookie) goto out; /* Sanitize parts of cookie. */ if (!cookie->domain) cookie->domain = xstrdup (u->host); else { if (!check_domain_match (cookie->domain, u->host)) { DEBUGP (("Attempt to fake the domain: %s, %s\n", cookie->domain, u->host)); goto out; } } if (!cookie->path) cookie->path = xstrdup (u->path); else { if (!check_path_match (cookie->path, u->path)) { DEBUGP (("Attempt to fake the path: %s, %s\n", cookie->path, u->path)); goto out; } } cookie->port = u->port; if (cookie->discard_requested) { discard_matching_cookie (cookie); delete_cookie (cookie); return 1; } store_cookie (cookie); return 1; out: if (cookie) delete_cookie (cookie); return 1; }
static void process_altavista_cookie(const char *cookie, char **new_cookie) { CookieNodeType *cl; ustring ucookie = USTRING_INITIALIZER; *new_cookie = NULL; cl = parse_cookies(cookie); if(!cl) { nag("Error parsing cookies\n"); goto cleanup; } delete_cookie(&cl, "AV_ALL"); if(set_cookie_value(&cl, " AV_PG", "1")) { nag("Error setting new cookie value\n"); goto cleanup; } if(rebuild_cookie(cl, &ucookie)) { nag("Error rebuilding cookie\n"); goto cleanup; } *new_cookie = Strdup(ucookie.string); cleanup: delete_cookie_list(cl); reset_ustring(&ucookie); }
static void soup_cookie_jar_text_changed (SoupCookieJar *jar, SoupCookie *old_cookie, SoupCookie *new_cookie) { FILE *out; SoupCookieJarTextPrivate *priv = SOUP_COOKIE_JAR_TEXT_GET_PRIVATE (jar); /* We can sort of ignore the semantics of the 'changed' * signal here and simply delete the old cookie if present * and write the new cookie if present. That will do the * right thing for all 'added', 'deleted' and 'modified' * meanings. */ /* Also, delete_cookie takes the filename and write_cookie * a FILE pointer. Seems more convenient that way considering * the implementations of the functions */ if (old_cookie) delete_cookie (priv->filename, old_cookie); if (new_cookie) { gboolean write_header = FALSE; if (!g_file_test (priv->filename, G_FILE_TEST_EXISTS)) write_header = TRUE; out = fopen (priv->filename, "a"); if (!out) { /* FIXME: error? */ return; } if (write_header) { fprintf (out, "# HTTP Cookie File\n"); fprintf (out, "# http://www.netscape.com/newsref/std/cookie_spec.html\n"); fprintf (out, "# This is a generated file! Do not edit.\n"); fprintf (out, "# To delete cookies, use the Cookie Manager.\n\n"); } if (new_cookie->expires) write_cookie (out, new_cookie); if (fclose (out) != 0) { /* FIXME: error? */ return; } } }
static void discard_matching_cookie (struct cookie *cookie) { struct cookie *prev, *victim; if (!cookies_hash_table || !hash_table_count (cookies_hash_table)) /* No elements == nothing to discard. */ return; victim = find_matching_cookie (cookie, &prev); if (victim) { if (prev) /* Simply unchain the victim. */ prev->next = victim->next; else { /* VICTIM was head of its chain. We need to place a new cookie at the head. */ char *hostport; char *chain_key = NULL; int res; SET_HOSTPORT (victim->domain, victim->port, hostport); res = hash_table_get_pair (cookies_hash_table, hostport, &chain_key, NULL); assert (res != 0); if (!victim->next) { /* VICTIM was the only cookie in the chain. Destroy the chain and deallocate the chain key. */ hash_table_remove (cookies_hash_table, hostport); xfree (chain_key); } else hash_table_put (cookies_hash_table, chain_key, victim->next); } delete_cookie (victim); DEBUGP (("Discarded old cookie.\n")); } }
static void delete_cookie_item(struct listbox_item *item, int last) { struct cookie *cookie = (struct cookie *)item->udata; if (item->type == BI_FOLDER) { struct listbox_item *next, *root = item; /* Releasing refcounts on the cookie_server will automagically * delete it. */ foreachsafe (item, next, root->child) delete_cookie_item(item, 0); } else { assert(!is_object_used(cookie)); delete_cookie(cookie); set_cookies_dirty(); } }
static int delete_cookie_chain_mapper (void *value, void *key, void *arg_ignored) { char *chain_key = (char *)value; struct cookie *chain = (struct cookie *)key; /* Remove the chain from the table and free the key. */ hash_table_remove (cookies_hash_table, chain_key); xfree (chain_key); /* Then delete all the cookies in the chain. */ while (chain) { struct cookie *next = chain->next; delete_cookie (chain); chain = next; } /* Keep mapping. */ return 0; }
static struct cookie * parse_set_cookies (const char *sc) { struct cookie *cookie = cookie_new (); enum { S_NAME_PRE, S_NAME, S_NAME_POST, S_VALUE_PRE, S_VALUE, S_VALUE_TRAILSPACE_MAYBE, S_QUOTED_VALUE, S_QUOTED_VALUE_POST, S_ATTR_ACTION, S_DONE, S_ERROR } state = S_NAME_PRE; const char *p = sc; char c; const char *name_b = NULL, *name_e = NULL; const char *value_b = NULL, *value_e = NULL; FETCH (c, p); while (state != S_DONE && state != S_ERROR) { switch (state) { case S_NAME_PRE: if (ISSPACE (c)) FETCH (c, p); else if (ATTR_NAME_CHAR (c)) { name_b = p - 1; FETCH1 (c, p); state = S_NAME; } else /* empty attr name not allowed */ state = S_ERROR; break; case S_NAME: if (ATTR_NAME_CHAR (c)) FETCH1 (c, p); else if (!c || c == ';' || c == '=' || ISSPACE (c)) { name_e = p - 1; state = S_NAME_POST; } else state = S_ERROR; break; case S_NAME_POST: if (ISSPACE (c)) FETCH1 (c, p); else if (!c || c == ';') { value_b = value_e = NULL; state = S_ATTR_ACTION; } else if (c == '=') { FETCH1 (c, p); state = S_VALUE_PRE; } else state = S_ERROR; break; case S_VALUE_PRE: if (ISSPACE (c)) FETCH1 (c, p); else if (c == '"') { value_b = p; FETCH (c, p); state = S_QUOTED_VALUE; } else if (c == ';' || c == '\0') { value_b = value_e = p - 1; state = S_ATTR_ACTION; } else { value_b = p - 1; value_e = NULL; state = S_VALUE; } break; case S_VALUE: if (c == ';' || c == '\0') { if (!value_e) value_e = p - 1; state = S_ATTR_ACTION; } else if (ISSPACE (c)) { value_e = p - 1; FETCH1 (c, p); state = S_VALUE_TRAILSPACE_MAYBE; } else { value_e = NULL; /* no trailing space */ FETCH1 (c, p); } break; case S_VALUE_TRAILSPACE_MAYBE: if (ISSPACE (c)) FETCH1 (c, p); else state = S_VALUE; break; case S_QUOTED_VALUE: if (c == '"') { value_e = p - 1; FETCH1 (c, p); state = S_QUOTED_VALUE_POST; } else FETCH (c, p); break; case S_QUOTED_VALUE_POST: if (c == ';' || !c) state = S_ATTR_ACTION; else if (ISSPACE (c)) FETCH1 (c, p); else state = S_ERROR; break; case S_ATTR_ACTION: { int legal = update_cookie_field (cookie, name_b, name_e, value_b, value_e); if (!legal) { char *name; BOUNDED_TO_ALLOCA (name_b, name_e, name); logprintf (LOG_NOTQUIET, _("Error in Set-Cookie, field `%s'"), name); state = S_ERROR; break; } if (c) FETCH1 (c, p); if (!c) state = S_DONE; else state = S_NAME_PRE; } break; case S_DONE: case S_ERROR: /* handled by loop condition */ break; } } if (state == S_DONE) return cookie; delete_cookie (cookie); if (state == S_ERROR) logprintf (LOG_NOTQUIET, _("Syntax error in Set-Cookie at character `%c'.\n"), c); else abort (); return NULL; eof: delete_cookie (cookie); logprintf (LOG_NOTQUIET, _("Syntax error in Set-Cookie: premature end of string.\n")); return NULL; }
static void store_cookie (struct cookie *cookie) { struct cookie *chain_head; char *hostport; char *chain_key; if (!cookies_hash_table) /* If the hash table is not initialized, do so now, because we'll need to store things. */ cookies_hash_table = make_nocase_string_hash_table (0); /* Initialize hash table key. */ SET_HOSTPORT (cookie->domain, cookie->port, hostport); if (hash_table_get_pair (cookies_hash_table, hostport, &chain_key, &chain_head)) { /* There already exists a chain of cookies with this exact domain. We need to check for duplicates -- if an existing cookie exactly matches our domain, path and name, we replace it. */ struct cookie *prev; struct cookie *victim = find_matching_cookie (cookie, &prev); if (victim) { /* Remove VICTIM from the chain. COOKIE will be placed at the head. */ if (prev) { prev->next = victim->next; cookie->next = chain_head; } else { /* prev is NULL; apparently VICTIM was at the head of the chain. This place will be taken by COOKIE, so all we need to do is: */ cookie->next = victim->next; } delete_cookie (victim); DEBUGP (("Deleted old cookie (to be replaced.)\n")); } else cookie->next = chain_head; } else { /* We are now creating the chain. Allocate the string that will be used as a key. It is unsafe to use cookie->domain for that, because it might get deallocated by the above code at some point later. */ cookie->next = NULL; chain_key = xstrdup (hostport); } hash_table_put (cookies_hash_table, chain_key, cookie); DEBUGP (("\nStored cookie %s %d %s %s %d %s %s %s\n", cookie->domain, cookie->port, cookie->path, cookie->permanent ? "permanent" : "nonpermanent", cookie->secure, asctime (localtime ((time_t *)&cookie->expiry_time)), cookie->attr, cookie->value)); }
void load_cookies (const char *file) { char *line; FILE *fp = fopen (file, "r"); if (!fp) { logprintf (LOG_NOTQUIET, "Cannot open cookies file `%s': %s\n", file, strerror (errno)); return; } cookies_now = time (NULL); for (; ((line = read_whole_line (fp)) != NULL); xfree (line)) { struct cookie *cookie; char *p = line; int port; char *domain_b = NULL, *domain_e = NULL; char *ignore_b = NULL, *ignore_e = NULL; char *path_b = NULL, *path_e = NULL; char *secure_b = NULL, *secure_e = NULL; char *expires_b = NULL, *expires_e = NULL; char *name_b = NULL, *name_e = NULL; char *value_b = NULL, *value_e = NULL; SKIP_WS (p); if (!*p || *p == '#') /* empty line */ continue; SET_WORD_BOUNDARIES (p, domain_b, domain_e); SET_WORD_BOUNDARIES (p, ignore_b, ignore_e); SET_WORD_BOUNDARIES (p, path_b, path_e); SET_WORD_BOUNDARIES (p, secure_b, secure_e); SET_WORD_BOUNDARIES (p, expires_b, expires_e); SET_WORD_BOUNDARIES (p, name_b, name_e); /* Don't use SET_WORD_BOUNDARIES for value because it may contain whitespace. Instead, set value_e to the end of line, modulo trailing space (this will skip the line separator.) */ SKIP_WS (p); value_b = p; value_e = p + strlen (p); while (value_e > value_b && ISSPACE (*(value_e - 1))) --value_e; if (value_b == value_e) /* Hmm, should we check for empty value? I guess that's legal, so I leave it. */ ; cookie = cookie_new (); cookie->attr = strdupdelim (name_b, name_e); cookie->value = strdupdelim (value_b, value_e); cookie->path = strdupdelim (path_b, path_e); if (BOUNDED_EQUAL (secure_b, secure_e, "TRUE")) cookie->secure = 1; /* DOMAIN needs special treatment because we might need to extract the port. */ port = domain_port (domain_b, domain_e, (const char **)&domain_e); if (port) cookie->port = port; else cookie->port = cookie->secure ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT; cookie->domain = strdupdelim (domain_b, domain_e); /* safe default in case EXPIRES field is garbled. */ cookie->expiry_time = cookies_now - 1; /* I don't like changing the line, but it's completely safe. (line is malloced.) */ *expires_e = '\0'; sscanf (expires_b, "%lu", &cookie->expiry_time); if (cookie->expiry_time < cookies_now) /* ignore stale cookie. */ goto abort; cookie->permanent = 1; store_cookie (cookie); next: continue; abort: delete_cookie (cookie); } fclose (fp); }