comparison libmpdemux/cookies.c @ 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
children b44bf57aef04
comparison
equal deleted inserted replaced
11582:ce9c964c66c3 11583:2af52902e7dc
1 /*
2 * HTTP Cookies
3 * Reads Netscape and Mozilla cookies.txt files
4 *
5 * by Dave Lambley <mplayer@davel.me.uk>
6 */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <fcntl.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <sys/types.h>
14 #include <dirent.h>
15
16 #include "cookies.h"
17 #include "http.c"
18 #include "mp_msg.h"
19
20 #define MAX_COOKIES 20
21
22 char *cookies_file = NULL;
23
24 typedef struct cookie_list_type {
25 char *name;
26 char *value;
27 char *domain;
28 char *path;
29
30 int secure;
31
32 struct cookie_list_type *next;
33 } cookie_list_t;
34
35 /* Pointer to the linked list of cookies */
36 static struct cookie_list_type *cookie_list = NULL;
37
38
39 /* Like strdup, but stops at anything <31. */
40 static char *col_dup(const char *src)
41 {
42 char *dst;
43 int length = 0;
44 char *p, *end;
45
46 while (src[length] > 31)
47 length++;
48
49 dst = malloc(length + 1);
50 strncpy(dst, src, length);
51 dst[length] = 0;
52
53 return dst;
54 }
55
56 static int right_hand_strcmp(const char *cookie_domain, const char *url_domain)
57 {
58 int c_l;
59 int u_l;
60
61 c_l = strlen(cookie_domain);
62 u_l = strlen(url_domain);
63
64 if (c_l > u_l)
65 return -1;
66 return strcmp(cookie_domain, url_domain + u_l - c_l);
67 }
68
69 static int left_hand_strcmp(const char *cookie_path, const char *url_path)
70 {
71 return strncmp(cookie_path, url_path, strlen(cookie_path));
72 }
73
74 /* Finds the start of all the columns */
75 static int parse_line(char **ptr, char *cols[6])
76 {
77 int col;
78 cols[0] = *ptr;
79
80 for (col = 1; col < 7; col++) {
81 for (; (**ptr) > 31; (*ptr)++);
82 if (**ptr == 0)
83 return 0;
84 (*ptr)++;
85 if ((*ptr)[-1] != 9)
86 return 0;
87 cols[col] = (*ptr);
88 }
89
90 return 1;
91 }
92
93 /* Loads a file into RAM */
94 static char *load_file(const char *filename, off_t * length)
95 {
96 int fd;
97 char *buffer;
98
99 mp_msg(MSGT_NETWORK, MSGL_V, "Loading cookie file: %s\n", filename);
100
101 fd = open(filename, O_RDONLY);
102 if (fd < 0) {
103 mp_msg(MSGT_NETWORK, MSGL_V, "Could not open");
104 return NULL;
105 }
106
107 *length = lseek(fd, 0, SEEK_END);
108
109 if (*length < 0) {
110 mp_msg(MSGT_NETWORK, MSGL_V, "Could not find EOF");
111 return NULL;
112 }
113
114 lseek(fd, SEEK_SET, 0);
115
116 if (!(buffer = malloc(*length + 1))) {
117 mp_msg(MSGT_NETWORK, MSGL_V, "Could not malloc.");
118 return NULL;
119 }
120
121 if (read(fd, buffer, *length) != *length) {
122 mp_msg(MSGT_NETWORK, MSGL_V, "Read is behaving funny.");
123 return NULL;
124 }
125 close(fd);
126 buffer[*length] = 0;
127
128 return buffer;
129 }
130
131 /* Loads a cookies.txt file into a linked list. */
132 static struct cookie_list_type *load_cookies_from(const char *filename,
133 struct cookie_list_type
134 *list)
135 {
136 char *ptr;
137 off_t length;
138
139 mp_msg(MSGT_NETWORK, MSGL_V, "Loading cookie file: %s\n", filename);
140
141 ptr = load_file(filename, &length);
142 if (!ptr)
143 return list;
144
145 while (*ptr > 0) {
146 char *cols[7];
147 if (parse_line(&ptr, cols)) {
148 struct cookie_list_type *new;
149 new = malloc(sizeof(cookie_list_t));
150 new->name = col_dup(cols[5]);
151 new->value = col_dup(cols[6]);
152 new->path = col_dup(cols[2]);
153 new->domain = col_dup(cols[0]);
154 new->secure = (*(cols[3]) == 't') || (*(cols[3]) == 'T');
155 new->next = list;
156 list = new;
157 }
158 }
159 return list;
160 }
161
162 /* Attempt to load cookies.txt from various locations. Returns a pointer to the linked list contain the cookies. */
163 static struct cookie_list_type *load_cookies()
164 {
165 DIR *dir;
166 struct dirent *ent;
167 struct cookie_list_type *list = NULL;
168 char *buf;
169
170 char *homedir;
171
172 if (cookies_file)
173 return load_cookies_from(cookies_file, list);
174
175 homedir = getenv("HOME");
176 if (!homedir)
177 return list;
178
179
180 asprintf(&buf, "%s/.mozilla/default", homedir);
181 dir = opendir(buf);
182 free(buf);
183
184 if (dir) {
185 while ((ent = readdir(dir)) != NULL) {
186 if ((ent->d_name)[0] != '.') {
187 asprintf(&buf, "%s/.mozilla/default/%s/cookies.txt",
188 getenv("HOME"), ent->d_name);
189 list = load_cookies_from(buf, list);
190 free(buf);
191 }
192 }
193 closedir(dir);
194 }
195
196 asprintf(&buf, "%s/.netscape/cookies.txt", homedir);
197 list = load_cookies_from(buf, list);
198 free(buf);
199
200 return list;
201 }
202
203 /* Take an HTTP_header_t, and insert the correct headers. The cookie files are read if necessary. */
204 void
205 cookies_set(HTTP_header_t * http_hdr, const char *domain, const char *url)
206 {
207 int found_cookies = 0;
208 struct cookie_list_type *cookies[MAX_COOKIES];
209 struct cookie_list_type *list, *start;
210 int i;
211 char *path;
212 char *buf;
213
214 path = index(url, '/');
215 if (!path)
216 path = "";
217
218 if (!cookie_list)
219 cookie_list = load_cookies();
220
221
222 list = start = cookie_list;
223
224 /* Find which cookies we want, removing duplicates. Cookies with the longest domain, then longest path take priority */
225 while (list) {
226 /* Check the cookie domain and path. Also, we never send "secure" cookies. These should only be sent over HTTPS. */
227 if ((right_hand_strcmp(list->domain, domain) == 0)
228 && (left_hand_strcmp(list->path, path) == 0) && !list->secure) {
229 int replacing = 0;
230 for (i = 0; i < found_cookies; i++) {
231 if (strcmp(list->name, cookies[i]->name) == 0) {
232 replacing = 0;
233 if (strlen(list->domain) >
234 strlen(cookies[i]->domain) == 0) {
235 cookies[i] = list;
236 } else if (strlen(list->path) >
237 strlen(cookies[i]->path) == 0) {
238 cookies[i] = list;
239 }
240 }
241 }
242 if (found_cookies > MAX_COOKIES) {
243 /* Cookie jar overflow! */
244 break;
245 }
246 if (!replacing)
247 cookies[found_cookies++] = list;
248 }
249 list = list->next;
250 }
251
252
253 asprintf(&buf, "Cookie:");
254
255 for (i = 0; i < found_cookies; i++) {
256 char *nbuf;
257
258 asprintf(&nbuf, "%s %s=%s;", buf, cookies[i]->name,
259 cookies[i]->value);
260 free(buf);
261 buf = nbuf;
262 }
263 if (found_cookies)
264 http_set_field(http_hdr, buf);
265 else
266 free(buf);
267 }