comparison stream/cookies.c @ 19271:64d82a45a05d

introduce new 'stream' directory for all stream layer related components and split them from libmpdemux
author ben
date Mon, 31 Jul 2006 17:39:17 +0000
parents libmpdemux/cookies.c@4928dd61f136
children b2e4f162dc36
comparison
equal deleted inserted replaced
19270:7d39b911f0bd 19271:64d82a45a05d
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 #include <inttypes.h>
16
17 #include "cookies.h"
18 #include "http.h"
19 #include "mp_msg.h"
20
21 #define MAX_COOKIES 20
22
23 char *cookies_file = NULL;
24
25 typedef struct cookie_list_type {
26 char *name;
27 char *value;
28 char *domain;
29 char *path;
30
31 int secure;
32
33 struct cookie_list_type *next;
34 } cookie_list_t;
35
36 /* Pointer to the linked list of cookies */
37 static struct cookie_list_type *cookie_list = NULL;
38
39
40 /* Like strdup, but stops at anything <31. */
41 static char *col_dup(const char *src)
42 {
43 char *dst;
44 int length = 0;
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 if (*length > SIZE_MAX - 1) {
115 mp_msg(MSGT_NETWORK, MSGL_V, "File too big, could not malloc.");
116 return NULL;
117 }
118
119 lseek(fd, SEEK_SET, 0);
120
121 if (!(buffer = malloc(*length + 1))) {
122 mp_msg(MSGT_NETWORK, MSGL_V, "Could not malloc.");
123 return NULL;
124 }
125
126 if (read(fd, buffer, *length) != *length) {
127 mp_msg(MSGT_NETWORK, MSGL_V, "Read is behaving funny.");
128 return NULL;
129 }
130 close(fd);
131 buffer[*length] = 0;
132
133 return buffer;
134 }
135
136 /* Loads a cookies.txt file into a linked list. */
137 static struct cookie_list_type *load_cookies_from(const char *filename,
138 struct cookie_list_type
139 *list)
140 {
141 char *ptr;
142 off_t length;
143
144 mp_msg(MSGT_NETWORK, MSGL_V, "Loading cookie file: %s\n", filename);
145
146 ptr = load_file(filename, &length);
147 if (!ptr)
148 return list;
149
150 while (*ptr > 0) {
151 char *cols[7];
152 if (parse_line(&ptr, cols)) {
153 struct cookie_list_type *new;
154 new = malloc(sizeof(cookie_list_t));
155 new->name = col_dup(cols[5]);
156 new->value = col_dup(cols[6]);
157 new->path = col_dup(cols[2]);
158 new->domain = col_dup(cols[0]);
159 new->secure = (*(cols[3]) == 't') || (*(cols[3]) == 'T');
160 new->next = list;
161 list = new;
162 }
163 }
164 return list;
165 }
166
167 /* Attempt to load cookies.txt from various locations. Returns a pointer to the linked list contain the cookies. */
168 static struct cookie_list_type *load_cookies(void)
169 {
170 DIR *dir;
171 struct dirent *ent;
172 struct cookie_list_type *list = NULL;
173 char *buf;
174
175 char *homedir;
176
177 if (cookies_file)
178 return load_cookies_from(cookies_file, list);
179
180 homedir = getenv("HOME");
181 if (!homedir)
182 return list;
183
184
185 buf = malloc(strlen(homedir) + sizeof("/.mozilla/default") + 1);
186 sprintf(buf, "%s/.mozilla/default", homedir);
187 dir = opendir(buf);
188 free(buf);
189
190 if (dir) {
191 while ((ent = readdir(dir)) != NULL) {
192 if ((ent->d_name)[0] != '.') {
193 buf = malloc(strlen(getenv("HOME")) +
194 sizeof("/.mozilla/default/") +
195 strlen(ent->d_name) + sizeof("cookies.txt") + 1);
196 sprintf(buf, "%s/.mozilla/default/%s/cookies.txt",
197 getenv("HOME"), ent->d_name);
198 list = load_cookies_from(buf, list);
199 free(buf);
200 }
201 }
202 closedir(dir);
203 }
204
205 buf = malloc(strlen(homedir) + sizeof("/.netscape/cookies.txt") + 1);
206 sprintf(buf, "%s/.netscape/cookies.txt", homedir);
207 list = load_cookies_from(buf, list);
208 free(buf);
209
210 return list;
211 }
212
213 /* Take an HTTP_header_t, and insert the correct headers. The cookie files are read if necessary. */
214 void
215 cookies_set(HTTP_header_t * http_hdr, const char *domain, const char *url)
216 {
217 int found_cookies = 0;
218 struct cookie_list_type *cookies[MAX_COOKIES];
219 struct cookie_list_type *list, *start;
220 int i;
221 char *path;
222 char *buf;
223
224 path = strchr(url, '/');
225 if (!path)
226 path = "";
227
228 if (!cookie_list)
229 cookie_list = load_cookies();
230
231
232 list = start = cookie_list;
233
234 /* Find which cookies we want, removing duplicates. Cookies with the longest domain, then longest path take priority */
235 while (list) {
236 /* Check the cookie domain and path. Also, we never send "secure" cookies. These should only be sent over HTTPS. */
237 if ((right_hand_strcmp(list->domain, domain) == 0)
238 && (left_hand_strcmp(list->path, path) == 0) && !list->secure) {
239 int replacing = 0;
240 for (i = 0; i < found_cookies; i++) {
241 if (strcmp(list->name, cookies[i]->name) == 0) {
242 replacing = 0;
243 if (strlen(list->domain) <= strlen(cookies[i]->domain)) {
244 cookies[i] = list;
245 } else if (strlen(list->path) <= strlen(cookies[i]->path)) {
246 cookies[i] = list;
247 }
248 }
249 }
250 if (found_cookies > MAX_COOKIES) {
251 /* Cookie jar overflow! */
252 break;
253 }
254 if (!replacing)
255 cookies[found_cookies++] = list;
256 }
257 list = list->next;
258 }
259
260
261 buf = strdup("Cookie:");
262
263 for (i = 0; i < found_cookies; i++) {
264 char *nbuf;
265
266 nbuf = malloc(strlen(buf) + strlen(" ") + strlen(cookies[i]->name) +
267 strlen("=") + strlen(cookies[i]->value) + strlen(";") + 1);
268 sprintf(nbuf, "%s %s=%s;", buf, cookies[i]->name,
269 cookies[i]->value);
270 free(buf);
271 buf = nbuf;
272 }
273
274 if (found_cookies)
275 http_set_field(http_hdr, buf);
276 else
277 free(buf);
278 }