📄 cookies.c
字号:
return (time_t) 0; } /* Calculate local timestamp. * [stolen from Lynx... (http://lynx.browser.org)] */ month -= 3; if (month < 0) { month += 12; year--; } day += (year - 1968) * 1461 / 4; day += ((((month * 153) + 2) / 5) - 672); ret = (time_t)((day * 60 * 60 * 24) + (hour * 60 * 60) + (minutes * 60) + seconds); DEBUG_MSG(4, "\tExpires in %ld seconds, at %s", (long)ret - time(NULL), ctime(&ret)); return ret;}/* * Parse a string containing a list of port numbers. */static void Cookies_parse_ports(const DilloUrl *set_url, CookieData_t *cookie, const char *port_str){ if ((!port_str || !port_str[0]) && set_url) { /* There was no list, so only the calling urls port should be allowed. */ cookie->ports = g_list_append(cookie->ports, GINT_TO_POINTER(URL_PORT(set_url))); } else if (port_str[0] == '"' && port_str[1] != '"') { char **tokens, **i; int port; tokens = g_strsplit(port_str + 1, ",", -1); for (i = tokens; *i; ++i) { port = strtol(*i, NULL, 10); if (port > 0) { cookie->ports = g_list_append(cookie->ports, GINT_TO_POINTER(port)); } } g_strfreev(tokens); }}/* * Build a string of the ports in 'cookie'. */static char *Cookies_build_ports_str(CookieData_t *cookie){ GString *gstr; GList *list; char *ret; gstr = g_string_new("\""); for (list = cookie->ports; list; list = g_list_next(list)) g_string_sprintfa(gstr, "%d,", GPOINTER_TO_INT(list->data)); /* Remove any trailing comma */ if (gstr->len > 1) g_string_erase(gstr, gstr->len - 1, 1); g_string_append(gstr, "\""); ret = gstr->str; g_string_free(gstr, FALSE); return ret;}/* * Used by g_list_insert_sorted() to sort the cookies by most specific path */static gint Cookies_compare(gconstpointer a, gconstpointer b){ const CookieData_t *ca = a, *cb = b; return strcmp(ca->path, cb->path);}static void Cookies_add_cookie(CookieData_t *cookie){ GList *domain_cookies, *tmp; char *domain_str; /* Don't add an expired cookie */ if (!cookie->session_only && cookie->expires_at < time(NULL)) { Cookies_free_cookie(cookie); return; } domain_cookies = g_hash_table_lookup(cookies, cookie->domain); if (domain_cookies) { /* Respect the limit of 20 cookies per domain */ if (g_list_length(domain_cookies) > 20) { DEBUG_MSG(8, "There are too many cookies for this domain (%s)\n", cookie->domain); Cookies_free_cookie(cookie); return; } /* Remove any cookies with the same name and path */ while ((tmp = g_list_find_custom(domain_cookies, cookie, Cookies_equals))) { Cookies_remove_cookie(tmp->data); domain_cookies = g_hash_table_lookup(cookies, cookie->domain); } } /* Allocate string key when no domain_cookies are left * (because remove_cookie has then killed the key, when it was there) */ domain_str = domain_cookies ? cookie->domain : g_strdup(cookie->domain); DEBUG_MSG(5, "Adding cookie '%s' for %s\n", cookie->name, cookie->domain); domain_cookies = g_list_insert_sorted(domain_cookies, cookie, Cookies_compare); g_hash_table_insert(cookies, domain_str, domain_cookies);}/* * Remove the cookie from the domain list. * If the domain list is empty, free the hash table entry. * Free the cookie. */static void Cookies_remove_cookie(CookieData_t *cookie){ GList *list; gpointer orig_key; gpointer orig_val; if (g_hash_table_lookup_extended(cookies, cookie->domain, &orig_key, &orig_val)) { list = g_list_remove(orig_val, cookie); if (list) { /* Make sure that we have the correct start of the list stored */ g_hash_table_insert(cookies, cookie->domain, list); } else { g_hash_table_remove(cookies, cookie->domain); g_free(orig_key); } } else { DEBUG_MSG(5, "Attempting to remove a cookie that doesn't exist!\n"); } Cookies_free_cookie(cookie);}/* * Return the attribute that is present at *cookie_str. This function * will also attempt to advance cookie_str past any equal-sign. */static char *Cookies_parse_attr(char **cookie_str){ char *str = *cookie_str; int i, end = 0; gboolean got_attr = FALSE; for (i = 0; ; i++) { switch (str[i]) { case ' ': case '\t': case '=': case ';': got_attr = TRUE; if (end == 0) end = i; break; case ',': *cookie_str = str + i; return g_strndup(str, i); break; case '\0': if (!got_attr) { end = i; got_attr = TRUE; } /* fall through! */ default: if (got_attr) { *cookie_str = str + i; return g_strndup(str, end); } break; } } return NULL;}/* * Get the value starting at *cookie_str. * broken_syntax: watch out for stupid syntax (comma in unquoted string...) */static char *Cookies_parse_value(char **cookie_str, gboolean broken_syntax, gboolean keep_quotes){ char *str = *cookie_str; int i = -1, end = 0; while (!end) { ++i; switch (str[i]) { case ' ': case '\t': if (!broken_syntax && str[0] != '\'' && str[0] != '"') { *cookie_str = str + i + 1; end = 1; } break; case '\'': case '"': if (i != 0 && str[i] == str[0]) { char *tmp = str + i; while (*tmp != '\0' && *tmp != ';' && *tmp != ',') tmp++; *cookie_str = (*tmp == ';') ? tmp + 1 : tmp; if (keep_quotes) i++; end = 1; } break; case '\0': *cookie_str = str + i; end = 1; break; case ',': if (str[0] != '\'' && str[0] != '"' && !broken_syntax) { /* A new cookie starts here! */ *cookie_str = str + i; end = 1; } break; case ';': if (str[0] != '\'' && str[0] != '"') { *cookie_str = str + i + 1; end = 1; } break; default: break; } } if ((str[0] == '\'' || str[0] == '"') && !keep_quotes) { return i > 1 ? g_strndup(str + 1, i - 1) : NULL; } else { return g_strndup(str, i); }}/* * Parse one cookie... */static CookieData_t *Cookies_parse_one(const DilloUrl *set_url, char **cookie_str){ CookieData_t *cookie; char *str = *cookie_str; char *attr; char *value; int num_attr = 0; gboolean max_age = FALSE; gboolean discard = FALSE; cookie = g_new0(CookieData_t, 1); cookie->session_only = TRUE; /* Iterate until there is nothing left of the string OR we come * across a comma representing the start of another cookie */ while (*str != '\0' && *str != ',') { /* Skip whitespace */ while (isspace(*str)) str++; /* Get attribute */ attr = Cookies_parse_attr(&str); if (!attr) { DEBUG_MSG(8, "Failed to parse cookie attribute!\n"); Cookies_free_cookie(cookie); return NULL; } /* Get the value for the attribute and store it */ if (num_attr == 0) { /* The first attr, which always is the user supplied attr, may * have the same name as an ordinary attr. Hence this workaround. */ cookie->name = g_strdup(attr); cookie->value = Cookies_parse_value(&str, FALSE, TRUE); } else if (g_strcasecmp(attr, "Path") == 0) { value = Cookies_parse_value(&str, FALSE, FALSE); cookie->path = value; } else if (g_strcasecmp(attr, "Domain") == 0) { value = Cookies_parse_value(&str, FALSE, FALSE); cookie->domain = value; } else if (g_strcasecmp(attr, "Discard") == 0) { cookie->session_only = TRUE; discard = TRUE; } else if (g_strcasecmp(attr, "Max-Age") == 0) { if (!discard) { value = Cookies_parse_value(&str, FALSE, FALSE); if (value) { cookie->expires_at = time(NULL) + strtol(value, NULL, 10); cookie->session_only = FALSE; max_age = TRUE; g_free(value); } else { DEBUG_MSG(8, "Failed to parse cookie value!\n"); Cookies_free_cookie(cookie); return NULL; } } } else if (g_strcasecmp(attr, "Expires") == 0) { if (!max_age && !discard) { DEBUG_MSG(8,"Cookie has 'Expires' attribute " "which isn't RFC-2965 compliant.\n"); value = Cookies_parse_value(&str, TRUE, FALSE); if (value) { cookie->expires_at = Cookies_create_timestamp(value); cookie->session_only = FALSE; g_free(value); } else { DEBUG_MSG(8, "Failed to parse cookie value!\n"); Cookies_free_cookie(cookie); return NULL; } } } else if (g_strcasecmp(attr, "Port") == 0) { value = Cookies_parse_value(&str, FALSE, TRUE); Cookies_parse_ports(set_url, cookie, value); g_free(value); } else if (g_strcasecmp(attr, "Comment") == 0) { value = Cookies_parse_value(&str, FALSE, FALSE); cookie->comment = value; } else if (g_strcasecmp(attr, "CommentURL") == 0) { value = Cookies_parse_value(&str, FALSE, FALSE); cookie->comment_url = value; } else if (g_strcasecmp(attr, "Version") == 0) { value = Cookies_parse_value(&str, FALSE, FALSE); if (value) { cookie->version = strtol(value, NULL, 10); g_free(value); } else { DEBUG_MSG(8, "Failed to parse cookie value!\n"); Cookies_free_cookie(cookie); return NULL; } } else if (g_strcasecmp(attr, "Secure") == 0) { cookie->secure = TRUE; } else { /* Oops! this can't be good... */ g_free(attr); Cookies_free_cookie(cookie); DEBUG_MSG(8, "Cookie contains illegal attribute!\n"); return NULL; } g_free(attr); num_attr++; } *cookie_str = (*str == ',') ? str + 1 : str; if (cookie->name && cookie->value) { return cookie; } else { DEBUG_MSG(8, "Cookie missing name and/or value!\n"); Cookies_free_cookie(cookie); return NULL; }}/* * Iterate the cookie string until we catch all cookies. * Return Value: a list with all the cookies! (or NULL upon error) */static GSList *Cookies_parse_string(const DilloUrl *set_url, char *cookie_string){ CookieData_t *cookie; GSList *ret = NULL; char *str = cookie_string;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -