summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/mplayer.18
-rw-r--r--cfg-common.h7
-rw-r--r--libmpdemux/Makefile2
-rw-r--r--libmpdemux/cookies.c267
-rw-r--r--libmpdemux/cookies.h16
-rw-r--r--libmpdemux/network.c10
6 files changed, 305 insertions, 5 deletions
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 <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.
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 <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);
+}
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 <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
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 ) {