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