Mercurial > mplayer.hg
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 } |