Get rid of code I neither know nor use anymore.
[mplayer/glamo.git] / stream / cookies.c
blob3a828f8d5ee689ac13a91fb175348a7d4dfaa37e
1 /*
2 * HTTP Cookies
3 * Reads Netscape and Mozilla cookies.txt files
5 * by Dave Lambley <mplayer@davel.me.uk>
6 */
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>
17 #include "cookies.h"
18 #include "http.h"
19 #include "mp_msg.h"
21 #define MAX_COOKIES 20
23 char *cookies_file = NULL;
25 typedef struct cookie_list_type {
26 char *name;
27 char *value;
28 char *domain;
29 char *path;
31 int secure;
33 struct cookie_list_type *next;
34 } cookie_list_t;
36 /* Pointer to the linked list of cookies */
37 static struct cookie_list_type *cookie_list = NULL;
40 /* Like strdup, but stops at anything <31. */
41 static char *col_dup(const char *src)
43 char *dst;
44 int length = 0;
46 while (src[length] > 31)
47 length++;
49 dst = malloc(length + 1);
50 strncpy(dst, src, length);
51 dst[length] = 0;
53 return dst;
56 static int right_hand_strcmp(const char *cookie_domain, const char *url_domain)
58 int c_l;
59 int u_l;
61 c_l = strlen(cookie_domain);
62 u_l = strlen(url_domain);
64 if (c_l > u_l)
65 return -1;
66 return strcmp(cookie_domain, url_domain + u_l - c_l);
69 static int left_hand_strcmp(const char *cookie_path, const char *url_path)
71 return strncmp(cookie_path, url_path, strlen(cookie_path));
74 /* Finds the start of all the columns */
75 static int parse_line(char **ptr, char *cols[6])
77 int col;
78 cols[0] = *ptr;
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);
90 return 1;
93 /* Loads a file into RAM */
94 static char *load_file(const char *filename, off_t * length)
96 int fd;
97 char *buffer;
99 mp_msg(MSGT_NETWORK, MSGL_V, "Loading cookie file: %s\n", filename);
101 fd = open(filename, O_RDONLY);
102 if (fd < 0) {
103 mp_msg(MSGT_NETWORK, MSGL_V, "Could not open");
104 return NULL;
107 *length = lseek(fd, 0, SEEK_END);
109 if (*length < 0) {
110 mp_msg(MSGT_NETWORK, MSGL_V, "Could not find EOF");
111 return NULL;
114 if (*length > SIZE_MAX - 1) {
115 mp_msg(MSGT_NETWORK, MSGL_V, "File too big, could not malloc.");
116 return NULL;
119 lseek(fd, SEEK_SET, 0);
121 if (!(buffer = malloc(*length + 1))) {
122 mp_msg(MSGT_NETWORK, MSGL_V, "Could not malloc.");
123 return NULL;
126 if (read(fd, buffer, *length) != *length) {
127 mp_msg(MSGT_NETWORK, MSGL_V, "Read is behaving funny.");
128 return NULL;
130 close(fd);
131 buffer[*length] = 0;
133 return buffer;
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)
141 char *ptr;
142 off_t length;
144 mp_msg(MSGT_NETWORK, MSGL_V, "Loading cookie file: %s\n", filename);
146 ptr = load_file(filename, &length);
147 if (!ptr)
148 return list;
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;
164 return list;
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)
170 DIR *dir;
171 struct dirent *ent;
172 struct cookie_list_type *list = NULL;
173 char *buf;
175 char *homedir;
177 if (cookies_file)
178 return load_cookies_from(cookies_file, list);
180 homedir = getenv("HOME");
181 if (!homedir)
182 return list;
185 buf = malloc(strlen(homedir) + sizeof("/.mozilla/default") + 1);
186 sprintf(buf, "%s/.mozilla/default", homedir);
187 dir = opendir(buf);
188 free(buf);
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);
202 closedir(dir);
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);
210 return list;
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)
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;
224 path = strchr(url, '/');
225 if (!path)
226 path = "";
228 if (!cookie_list)
229 cookie_list = load_cookies();
232 list = start = cookie_list;
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;
250 if (found_cookies > MAX_COOKIES) {
251 /* Cookie jar overflow! */
252 break;
254 if (!replacing)
255 cookies[found_cookies++] = list;
257 list = list->next;
261 buf = strdup("Cookie:");
263 for (i = 0; i < found_cookies; i++) {
264 char *nbuf;
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;
274 if (found_cookies)
275 http_set_field(http_hdr, buf);
276 else
277 free(buf);