📄 cookies.c
字号:
}/* * Return a local timestamp from a GMT date string * Accept: RFC-1123 | RFC-850 | ANSI asctime * (return 0 on malformed date string syntax) */static time_t Cookies_create_timestamp(const char *expires){ gchar *E_msg = "Cookies: Expire date is malformed! Ignoring cookie...\n"; time_t ret; int day, month, year, hour, minutes, seconds; gchar *cp; if (!(cp = strchr(expires, ',')) && strlen(expires) == 24) { /* Looks like ANSI asctime format... */ cp = (gchar *)expires; day = strtol(cp + 8, NULL, 10); /* day */ month = Cookies_get_month(cp + 4); /* month */ year = strtol(cp + 20, NULL, 10); /* year */ hour = strtol(cp + 11, NULL, 10); /* hour */ minutes = strtol(cp + 14, NULL, 10); /* minutes */ seconds = strtol(cp + 17, NULL, 10); /* seconds */ } else if (cp && ((cp - expires == 3 && strlen(cp) == 26) || (cp - expires > 5 && strlen(cp) == 24))) { /* RFC-1123 | RFC-850 format */ day = strtol(cp + 2, NULL, 10); month = Cookies_get_month(cp + 5); year = strtol(cp + 9, &cp, 10); /* todo: tricky, because two digits for year IS ambiguous! */ year += (year < 70) ? 2000 : ((year < 100) ? 1900 : 0); hour = strtol(cp + 1, NULL, 10); minutes = strtol(cp + 4, NULL, 10); seconds = strtol(cp + 7, NULL, 10); } else { DEBUG_MSG(5, E_msg); return (time_t) 0; } /* Error checks --this may be overkill */ if (!(day > 0 && day < 32 && month > 0 && month && year > 1970 && hour >= 0 && hour < 24 && minutes >= 0 && minutes < 60 && seconds >= 0 && seconds < 60)) { DEBUG_MSG(5, E_msg); 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(CookieData_t *cookie, const char *port_str){ if (port_str[0] == '\0') { /* There was no list, so only the calling urls port should * be allowed. We set the first one to -1 and continues in * a_Cookies_set */ cookie->ports = g_list_append(cookie->ports, GINT_TO_POINTER(-1)); } 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; int port; gstr = g_string_new("\""); for (list = g_list_first(cookie->ports); list; list = g_list_next(list)) { port = GPOINTER_TO_INT(list->data); g_string_sprintfa(gstr, "%d,", port); } /* 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;}/* * Parse optional fields * (domain, path, expires, max-age, comment, * commenturl, secure, version, discard) */static void Cookies_parse_optional(CookieData_t *cookie, char *cookie_string){ char *value_string; gboolean discard, max_age; max_age = FALSE; discard = FALSE; while (cookie_string) { if (*cookie_string == ',' || *cookie_string == '\0') return; cookie_string++; g_strstrip(cookie_string); if (*cookie_string == '\0') return; value_string = Cookies_try_header(&cookie_string, "Path", FALSE); if (value_string) { cookie->path = value_string; continue; } value_string = Cookies_try_header(&cookie_string, "Domain", FALSE); if (value_string) { cookie->domain = value_string; continue; } value_string = Cookies_try_header(&cookie_string, "Discard", FALSE); if (value_string) { /* The server wants us to toss this cookie away at exit */ cookie->session_only = TRUE; discard = TRUE; g_free(value_string); continue; } if (!discard) { value_string = Cookies_try_header(&cookie_string, "Max-Age", FALSE); if (value_string) { cookie->expires_at = time(NULL) + strtol(value_string, NULL, 10); cookie->session_only = FALSE; max_age = TRUE; g_free(value_string); continue; } if (!max_age) { value_string = Cookies_try_header(&cookie_string, "Expires", TRUE); if (value_string) { cookie->expires_at = Cookies_create_timestamp(value_string); cookie->session_only = FALSE; g_free(value_string); continue; } } } value_string = Cookies_try_header(&cookie_string, "Port", TRUE); if (value_string) { Cookies_parse_ports(cookie, value_string); g_free(value_string); continue; } value_string = Cookies_try_header(&cookie_string, "Comment", FALSE); if (value_string) { cookie->comment = value_string; continue; } value_string = Cookies_try_header(&cookie_string, "CommentURL", FALSE); if (value_string) { cookie->comment_url = value_string; continue; } value_string = Cookies_try_header(&cookie_string, "Version", FALSE); if (value_string) { cookie->version = strtol(value_string, NULL, 10); g_free(value_string); continue; } value_string = Cookies_try_header(&cookie_string, "Secure", FALSE); if (value_string) { cookie->secure = TRUE; DEBUG_MSG(4, "Secure cookie requested.\n"); g_free(value_string); } }}/* * Remove the domain from the hash table and free its key. */static void Cookies_free_domain(const char *domain){ gpointer orig_key; if (g_hash_table_lookup_extended(cookies, domain, &orig_key, NULL)) { g_hash_table_remove(cookies, domain); g_free(orig_key); }}/* * Parse the supplied string and return a newly allocated cookie. */static CookieData_t *Cookies_parse_string(char *cookie_string){ CookieData_t *cookie = g_new0(CookieData_t, 1); char *marker; DEBUG_MSG(4, "Parsing cookie string `%s'\n", cookie_string); cookie->session_only = TRUE; /* Parse the name and value */ marker = strchr(cookie_string, '='); if (marker == NULL) { /* Malformed cookie */ Cookies_free_cookie(cookie); return NULL; } cookie->name = g_strndup(cookie_string, marker-cookie_string); marker++; if (*marker == '"') { /* Quoted string */ char *value_start = ++marker; marker = strchr(value_start, '\"'); if (marker == NULL) { Cookies_free_cookie(cookie); return NULL; } cookie->value = g_strndup(cookie_string, marker-value_start); marker++; } else { char *value_start = marker; marker = strchr(value_start, ';'); if (marker == NULL) { /* No path etc, maybe ended with ',' */ marker = strchr(value_start, ','); if (marker == NULL) { /* No more stuff, value is entire rest */ marker = value_start + strlen(value_start); } } cookie->value = g_strndup(value_start, marker-value_start); } /* Parse optional fields (domain, path, expires, max-age, comment, secure, version) */ Cookies_parse_optional(cookie, marker); return cookie;}/* * Compare cookies (return 1 if equal, 0 otherwise) */static gboolean Cookies_equals(CookieData_t *cookie1, CookieData_t *cookie2){ return ((!strcmp(cookie1->name, cookie2->name)) && (!(cookie1->domain && cookie2->domain && strcmp(cookie1->domain, cookie2->domain))) && (!(cookie1->path && cookie2->path && strcmp(cookie1->path, cookie2->path))));}/* * Validate cookies domain against some security checks. */static gboolean Cookies_validate_domain(CookieData_t *cookie, const DilloUrl *set_url){ const char *host; int dots, diff, i; gboolean is_ip; /* If the server never set a domain, or set one without a leading * dot (which isn't allowed), we use the calling URL's hostname. */ if (cookie->domain == NULL || cookie->domain[0] != '.') { cookie->domain = g_strdup(URL_HOST(set_url)); return TRUE; } /* Count the number of dots and also find out if it is an IP-address */ is_ip = TRUE; for (i = 0, dots = 0; cookie->domain[i] != '\0'; i++) { if (cookie->domain[i] == '.') dots++; else if (!isdigit(cookie->domain[i])) is_ip = FALSE; } /* A valid domain must have at least two dots in it */ /* NOTE: this breaks cookies on localhost... */ if (dots < 2) { return FALSE; } /* Now see if the url matches the domain */ host = URL_HOST(set_url); diff = strlen(host) - i; if (diff > 0) { if (g_strcasecmp(host + diff, cookie->domain)) return FALSE; if (!is_ip) { /* "x.y.test.com" is not allowed to set cookies for ".test.com"; * only an url of the form "y.test.com" would be. */ while ( diff-- ) if (host[diff] == '.') return FALSE; } } return TRUE;}/* * Strip of the filename from a full path */static char *Cookies_strip_path(const char *path){ char *ret; int len; if (path) { len = strlen(path); while(len && path[len] != '/')
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -