From 49867bd432352d19172ab26cf873bd5651e69e25 Mon Sep 17 00:00:00 2001 From: ben Date: Mon, 31 Jul 2006 17:39:17 +0000 Subject: introduce new 'stream' directory for all stream layer related components and split them from libmpdemux git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@19277 b3059339-0415-0410-9bf9-f77b7e298cf2 --- stream/cookies.c | 278 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 stream/cookies.c (limited to 'stream/cookies.c') diff --git a/stream/cookies.c b/stream/cookies.c new file mode 100644 index 0000000000..3a828f8d5e --- /dev/null +++ b/stream/cookies.c @@ -0,0 +1,278 @@ +/* + * HTTP Cookies + * Reads Netscape and Mozilla cookies.txt files + * + * by Dave Lambley + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cookies.h" +#include "http.h" +#include "mp_msg.h" + +#define MAX_COOKIES 20 + +char *cookies_file = NULL; + +typedef struct cookie_list_type { + char *name; + char *value; + char *domain; + char *path; + + int secure; + + struct cookie_list_type *next; +} cookie_list_t; + +/* Pointer to the linked list of cookies */ +static struct cookie_list_type *cookie_list = NULL; + + +/* Like strdup, but stops at anything <31. */ +static char *col_dup(const char *src) +{ + char *dst; + int length = 0; + + while (src[length] > 31) + length++; + + dst = malloc(length + 1); + strncpy(dst, src, length); + dst[length] = 0; + + return dst; +} + +static int right_hand_strcmp(const char *cookie_domain, const char *url_domain) +{ + int c_l; + int u_l; + + c_l = strlen(cookie_domain); + u_l = strlen(url_domain); + + if (c_l > u_l) + return -1; + return strcmp(cookie_domain, url_domain + u_l - c_l); +} + +static int left_hand_strcmp(const char *cookie_path, const char *url_path) +{ + return strncmp(cookie_path, url_path, strlen(cookie_path)); +} + +/* Finds the start of all the columns */ +static int parse_line(char **ptr, char *cols[6]) +{ + int col; + cols[0] = *ptr; + + for (col = 1; col < 7; col++) { + for (; (**ptr) > 31; (*ptr)++); + if (**ptr == 0) + return 0; + (*ptr)++; + if ((*ptr)[-1] != 9) + return 0; + cols[col] = (*ptr); + } + + return 1; +} + +/* Loads a file into RAM */ +static char *load_file(const char *filename, off_t * length) +{ + int fd; + char *buffer; + + mp_msg(MSGT_NETWORK, MSGL_V, "Loading cookie file: %s\n", filename); + + fd = open(filename, O_RDONLY); + if (fd < 0) { + mp_msg(MSGT_NETWORK, MSGL_V, "Could not open"); + return NULL; + } + + *length = lseek(fd, 0, SEEK_END); + + if (*length < 0) { + mp_msg(MSGT_NETWORK, MSGL_V, "Could not find EOF"); + return NULL; + } + + if (*length > SIZE_MAX - 1) { + mp_msg(MSGT_NETWORK, MSGL_V, "File too big, could not malloc."); + return NULL; + } + + lseek(fd, SEEK_SET, 0); + + if (!(buffer = malloc(*length + 1))) { + mp_msg(MSGT_NETWORK, MSGL_V, "Could not malloc."); + return NULL; + } + + if (read(fd, buffer, *length) != *length) { + mp_msg(MSGT_NETWORK, MSGL_V, "Read is behaving funny."); + return NULL; + } + close(fd); + buffer[*length] = 0; + + return buffer; +} + +/* Loads a cookies.txt file into a linked list. */ +static struct cookie_list_type *load_cookies_from(const char *filename, + struct cookie_list_type + *list) +{ + char *ptr; + off_t length; + + mp_msg(MSGT_NETWORK, MSGL_V, "Loading cookie file: %s\n", filename); + + ptr = load_file(filename, &length); + if (!ptr) + return list; + + while (*ptr > 0) { + char *cols[7]; + if (parse_line(&ptr, cols)) { + struct cookie_list_type *new; + new = malloc(sizeof(cookie_list_t)); + new->name = col_dup(cols[5]); + new->value = col_dup(cols[6]); + new->path = col_dup(cols[2]); + new->domain = col_dup(cols[0]); + new->secure = (*(cols[3]) == 't') || (*(cols[3]) == 'T'); + new->next = list; + list = new; + } + } + return list; +} + +/* Attempt to load cookies.txt from various locations. Returns a pointer to the linked list contain the cookies. */ +static struct cookie_list_type *load_cookies(void) +{ + DIR *dir; + struct dirent *ent; + struct cookie_list_type *list = NULL; + char *buf; + + char *homedir; + + if (cookies_file) + return load_cookies_from(cookies_file, list); + + homedir = getenv("HOME"); + if (!homedir) + return list; + + + buf = malloc(strlen(homedir) + sizeof("/.mozilla/default") + 1); + sprintf(buf, "%s/.mozilla/default", homedir); + dir = opendir(buf); + free(buf); + + if (dir) { + while ((ent = readdir(dir)) != NULL) { + if ((ent->d_name)[0] != '.') { + buf = malloc(strlen(getenv("HOME")) + + sizeof("/.mozilla/default/") + + strlen(ent->d_name) + sizeof("cookies.txt") + 1); + sprintf(buf, "%s/.mozilla/default/%s/cookies.txt", + getenv("HOME"), ent->d_name); + list = load_cookies_from(buf, list); + free(buf); + } + } + closedir(dir); + } + + buf = malloc(strlen(homedir) + sizeof("/.netscape/cookies.txt") + 1); + sprintf(buf, "%s/.netscape/cookies.txt", homedir); + list = load_cookies_from(buf, list); + free(buf); + + return list; +} + +/* Take an HTTP_header_t, and insert the correct headers. The cookie files are read if necessary. */ +void +cookies_set(HTTP_header_t * http_hdr, const char *domain, const char *url) +{ + int found_cookies = 0; + struct cookie_list_type *cookies[MAX_COOKIES]; + struct cookie_list_type *list, *start; + int i; + char *path; + char *buf; + + path = strchr(url, '/'); + if (!path) + path = ""; + + if (!cookie_list) + cookie_list = load_cookies(); + + + list = start = cookie_list; + + /* Find which cookies we want, removing duplicates. Cookies with the longest domain, then longest path take priority */ + while (list) { + /* Check the cookie domain and path. Also, we never send "secure" cookies. These should only be sent over HTTPS. */ + if ((right_hand_strcmp(list->domain, domain) == 0) + && (left_hand_strcmp(list->path, path) == 0) && !list->secure) { + int replacing = 0; + for (i = 0; i < found_cookies; i++) { + if (strcmp(list->name, cookies[i]->name) == 0) { + replacing = 0; + if (strlen(list->domain) <= strlen(cookies[i]->domain)) { + cookies[i] = list; + } else if (strlen(list->path) <= strlen(cookies[i]->path)) { + cookies[i] = list; + } + } + } + if (found_cookies > MAX_COOKIES) { + /* Cookie jar overflow! */ + break; + } + if (!replacing) + cookies[found_cookies++] = list; + } + list = list->next; + } + + + buf = strdup("Cookie:"); + + for (i = 0; i < found_cookies; i++) { + char *nbuf; + + nbuf = malloc(strlen(buf) + strlen(" ") + strlen(cookies[i]->name) + + strlen("=") + strlen(cookies[i]->value) + strlen(";") + 1); + sprintf(nbuf, "%s %s=%s;", buf, cookies[i]->name, + cookies[i]->value); + free(buf); + buf = nbuf; + } + + if (found_cookies) + http_set_field(http_hdr, buf); + else + free(buf); +} -- cgit v1.2.3