From 28a127d80bb6363d47a3212409f05b5b0b687240 Mon Sep 17 00:00:00 2001 From: alex Date: Mon, 8 Dec 2003 13:25:35 +0000 Subject: Send HTTP Cookies (reading from mozilla/netscape files) support by Dave Lambley . Disabled by default. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@11584 b3059339-0415-0410-9bf9-f77b7e298cf2 --- DOCS/man/en/mplayer.1 | 8 ++ cfg-common.h | 7 +- libmpdemux/Makefile | 2 +- libmpdemux/cookies.c | 267 ++++++++++++++++++++++++++++++++++++++++++++++++++ libmpdemux/cookies.h | 16 +++ libmpdemux/network.c | 10 +- 6 files changed, 305 insertions(+), 5 deletions(-) create mode 100644 libmpdemux/cookies.c create mode 100644 libmpdemux/cookies.h diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1 index 21117ec374..1db60949c5 100644 --- a/DOCS/man/en/mplayer.1 +++ b/DOCS/man/en/mplayer.1 @@ -689,6 +689,14 @@ Specify which chapter to start playing at. Optionally specify which chapter to end playing at (default: 1). Examples can be found below. .TP +.B \-cookies +Send cookies when making HTTP requests. +.TP +.B \-cookies-file +Read HTTP cookies from this file. The file is assumed to be in Netscape format. +If you give this option, MPlayer will not look for cookies in "~/.netscape/" +and "~/.mozilla/". +.TP .B \-csslib (old-style DVD option) This option is used to override the default location of libcss.so. diff --git a/cfg-common.h b/cfg-common.h index 11a6a1654d..8cca54946f 100644 --- a/cfg-common.h +++ b/cfg-common.h @@ -42,10 +42,11 @@ {"passwd", &network_password, CONF_TYPE_STRING, 0, 0, 0, NULL}, {"bandwidth", &network_bandwidth, CONF_TYPE_INT, CONF_MIN, 0, 0, NULL}, {"user-agent", &network_useragent, CONF_TYPE_STRING, 0, 0, 0, NULL}, - + {"cookies", &network_cookies_enabled, CONF_TYPE_FLAG, 0, 0, 1, NULL}, + {"nocookies", &network_cookies_enabled, CONF_TYPE_FLAG, 0, 1, 0, NULL}, + {"cookies-file", &cookies_file, CONF_TYPE_STRING, 0, 0, 0, NULL}, {"prefer-ipv4", &network_prefer_ipv4, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"ipv4-only-proxy", &network_ipv4_only_proxy, CONF_TYPE_FLAG, 0, 0, 1, NULL}, - #ifdef HAVE_AF_INET6 {"prefer-ipv6", &network_prefer_ipv4, CONF_TYPE_FLAG, 0, 1, 0, NULL}, #else @@ -287,6 +288,8 @@ extern char *network_username; extern char *network_password; extern int network_bandwidth; extern char *network_useragent; +extern int network_cookies_enabled; +extern char *cookies_file; extern int network_prefer_ipv4; extern int network_ipv4_only_proxy; diff --git a/libmpdemux/Makefile b/libmpdemux/Makefile index e5abb4b811..456f617b70 100644 --- a/libmpdemux/Makefile +++ b/libmpdemux/Makefile @@ -8,7 +8,7 @@ ifeq ($(XMMS_PLUGINS),yes) SRCS += demux_xmms.c endif ifeq ($(MPLAYER_NETWORK),yes) -SRCS += asf_streaming.c http.c network.c asf_mmst_streaming.c pnm.c +SRCS += asf_streaming.c http.c network.c cookies.c asf_mmst_streaming.c pnm.c SRCS += realrtsp/asmrp.c realrtsp/real.c realrtsp/rmff.c realrtsp/rtsp.c realrtsp/rtsp_session.c realrtsp/sdpplin.c realrtsp/xbuffer.c ifeq ($(STREAMING_LIVE_DOT_COM),yes) CPLUSPLUSSRCS = demux_rtp.cpp demux_rtp_codec.cpp diff --git a/libmpdemux/cookies.c b/libmpdemux/cookies.c new file mode 100644 index 0000000000..b177f253a6 --- /dev/null +++ b/libmpdemux/cookies.c @@ -0,0 +1,267 @@ +/* + * HTTP Cookies + * Reads Netscape and Mozilla cookies.txt files + * + * by Dave Lambley + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "cookies.h" +#include "http.c" +#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; + char *p, *end; + + 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; + } + + 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() +{ + 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; + + + asprintf(&buf, "%s/.mozilla/default", homedir); + dir = opendir(buf); + free(buf); + + if (dir) { + while ((ent = readdir(dir)) != NULL) { + if ((ent->d_name)[0] != '.') { + asprintf(&buf, "%s/.mozilla/default/%s/cookies.txt", + getenv("HOME"), ent->d_name); + list = load_cookies_from(buf, list); + free(buf); + } + } + closedir(dir); + } + + asprintf(&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 = index(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) == 0) { + cookies[i] = list; + } else if (strlen(list->path) > + strlen(cookies[i]->path) == 0) { + cookies[i] = list; + } + } + } + if (found_cookies > MAX_COOKIES) { + /* Cookie jar overflow! */ + break; + } + if (!replacing) + cookies[found_cookies++] = list; + } + list = list->next; + } + + + asprintf(&buf, "Cookie:"); + + for (i = 0; i < found_cookies; i++) { + char *nbuf; + + asprintf(&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); +} diff --git a/libmpdemux/cookies.h b/libmpdemux/cookies.h new file mode 100644 index 0000000000..e4b1f13f9b --- /dev/null +++ b/libmpdemux/cookies.h @@ -0,0 +1,16 @@ +/* + * HTTP Cookies + * Reads Netscape and Mozilla cookies.txt files + * + * by Dave Lambley + */ + +#ifndef __COOKIES_H +#define __COOKIES_H + +#include "http.h" + +extern void cookies_set(HTTP_header_t * http_hdr, const char *hostname, + const char *url); + +#endif diff --git a/libmpdemux/network.c b/libmpdemux/network.c index c074628745..d31c891870 100644 --- a/libmpdemux/network.c +++ b/libmpdemux/network.c @@ -29,6 +29,7 @@ #include "network.h" #include "http.h" +#include "cookies.h" #include "url.h" #include "asf.h" #ifndef STREAMING_LIVE_DOT_COM @@ -47,11 +48,13 @@ extern int mp_input_check_interrupt(int time); int asf_streaming_start( stream_t *stream, int *demuxer_type ); int rtsp_streaming_start( stream_t *stream ); -/* Variables for the command line option -user, -passwd, -bandwidth - and -user-agent */ +/* Variables for the command line option -user, -passwd, -bandwidth, + -user-agent and -nocookies */ + char *network_username=NULL; char *network_password=NULL; int network_bandwidth=0; +int network_cookies_enabled = 0; char *network_useragent=NULL; /* IPv6 options */ @@ -452,6 +455,9 @@ http_send_request( URL_t *url ) { } else http_set_field( http_hdr, "User-Agent: MPlayer/"VERSION); + + if (network_cookies_enabled) cookies_set( http_hdr, server_url->hostname, server_url->url ); + http_set_field( http_hdr, "Connection: closed"); http_add_basic_authentication( http_hdr, url->username, url->password ); if( http_build_request( http_hdr )==NULL ) { -- cgit v1.2.3