changeset 11583:2af52902e7dc

Send HTTP Cookies (reading from mozilla/netscape files) support by Dave Lambley <mplayer-dev-eng@dlambley.freeserve.co.uk>. Disabled by default.
author alex
date Mon, 08 Dec 2003 13:25:35 +0000
parents ce9c964c66c3
children 7821a35b5dcc
files DOCS/man/en/mplayer.1 cfg-common.h libmpdemux/Makefile libmpdemux/cookies.c libmpdemux/cookies.h libmpdemux/network.c
diffstat 6 files changed, 305 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/DOCS/man/en/mplayer.1	Mon Dec 08 13:11:52 2003 +0000
+++ b/DOCS/man/en/mplayer.1	Mon Dec 08 13:25:35 2003 +0000
@@ -689,6 +689,14 @@
 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 <filename>
+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 <filename>
 (old-style DVD option) This option is used to override the default location of
 libcss.so.
--- a/cfg-common.h	Mon Dec 08 13:11:52 2003 +0000
+++ b/cfg-common.h	Mon Dec 08 13:25:35 2003 +0000
@@ -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_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;
--- a/libmpdemux/Makefile	Mon Dec 08 13:11:52 2003 +0000
+++ b/libmpdemux/Makefile	Mon Dec 08 13:25:35 2003 +0000
@@ -8,7 +8,7 @@
 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmpdemux/cookies.c	Mon Dec 08 13:25:35 2003 +0000
@@ -0,0 +1,267 @@
+/*
+ * HTTP Cookies
+ * Reads Netscape and Mozilla cookies.txt files
+ *
+ * by Dave Lambley <mplayer@davel.me.uk>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmpdemux/cookies.h	Mon Dec 08 13:25:35 2003 +0000
@@ -0,0 +1,16 @@
+/*
+ * HTTP Cookies
+ * Reads Netscape and Mozilla cookies.txt files
+ * 
+ * by Dave Lambley <mplayer@davel.me.uk>
+ */
+
+#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
--- a/libmpdemux/network.c	Mon Dec 08 13:11:52 2003 +0000
+++ b/libmpdemux/network.c	Mon Dec 08 13:25:35 2003 +0000
@@ -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 @@
 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 @@
 	}
 	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 ) {