File: | desktop/cookie_manager.c |
Warning: | line 856, column 2 Value stored to 'err' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright 2013 Michael Drake <tlsa@netsurf-browser.org> |
3 | * |
4 | * This file is part of NetSurf, http://www.netsurf-browser.org/ |
5 | * |
6 | * NetSurf is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; version 2 of the License. |
9 | * |
10 | * NetSurf is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ |
18 | |
19 | /** |
20 | * \file |
21 | * Implementation of Cookie Management |
22 | * |
23 | * This allows users to view and remove their web cookies. |
24 | * |
25 | * \todo the viewing of cookies is pretty basic and it would be good |
26 | * to apply more processing of the values and perhaps top level domain |
27 | * suffix highlighting to give a better user information as to how the |
28 | * cookies interact with the users sessions. |
29 | * |
30 | * \todo In addition to removing cookies it might be useful to allow |
31 | * users to edit them, especially to alter expiry times. |
32 | */ |
33 | |
34 | |
35 | #include <stdlib.h> |
36 | #include <string.h> |
37 | |
38 | #include "utils/messages.h" |
39 | #include "utils/utils.h" |
40 | #include "utils/log.h" |
41 | #include "content/urldb.h" |
42 | |
43 | #include "desktop/cookie_manager.h" |
44 | #include "desktop/treeview.h" |
45 | |
46 | enum cookie_manager_field { |
47 | COOKIE_M_NAME, |
48 | COOKIE_M_CONTENT, |
49 | COOKIE_M_DOMAIN, |
50 | COOKIE_M_PATH, |
51 | COOKIE_M_EXPIRES, |
52 | COOKIE_M_LAST_USED, |
53 | COOKIE_M_RESTRICTIONS, |
54 | COOKIE_M_VERSION, |
55 | COOKIE_M_DOMAIN_FOLDER, |
56 | COOKIE_M_N_FIELDS |
57 | }; |
58 | |
59 | enum cookie_manager_value { |
60 | COOKIE_M_HTTPS, |
61 | COOKIE_M_SECURE, |
62 | COOKIE_M_HTTP, |
63 | COOKIE_M_NONE, |
64 | COOKIE_M_NETSCAPE, |
65 | COOKIE_M_RFC2109, |
66 | COOKIE_M_RFC2965, |
67 | COOKIE_M_YES, |
68 | COOKIE_M_NO, |
69 | COOKIE_M_N_VALUES |
70 | }; |
71 | |
72 | struct cookie_manager_folder { |
73 | treeview_node *folder; |
74 | struct treeview_field_data data; |
75 | }; |
76 | |
77 | struct cookie_manager_ctx { |
78 | treeview *tree; |
79 | struct treeview_field_desc fields[COOKIE_M_N_FIELDS]; |
80 | struct treeview_field_data values[COOKIE_M_N_VALUES]; |
81 | bool_Bool built; |
82 | }; |
83 | struct cookie_manager_ctx cm_ctx; |
84 | |
85 | struct cookie_manager_entry { |
86 | bool_Bool user_delete; |
87 | |
88 | treeview_node *entry; |
89 | |
90 | struct treeview_field_data data[COOKIE_M_N_FIELDS - 1]; |
91 | }; |
92 | |
93 | |
94 | struct treeview_walk_ctx { |
95 | const char *title; |
96 | size_t title_len; |
97 | struct cookie_manager_folder *folder; |
98 | struct cookie_manager_entry *entry; |
99 | }; |
100 | /** Callback for treeview_walk */ |
101 | static nserror cookie_manager_walk_cb(void *ctx, void *node_data, |
102 | enum treeview_node_type type, bool_Bool *abort) |
103 | { |
104 | struct treeview_walk_ctx *tw = ctx; |
105 | |
106 | if (type == TREE_NODE_ENTRY) { |
107 | struct cookie_manager_entry *entry = node_data; |
108 | |
109 | if (entry->data[COOKIE_M_NAME].value_len == tw->title_len && |
110 | strcmp(tw->title, |
111 | entry->data[COOKIE_M_NAME].value) == 0) { |
112 | /* Found what we're looking for */ |
113 | tw->entry = entry; |
114 | *abort = true1; |
115 | } |
116 | |
117 | } else if (type == TREE_NODE_FOLDER) { |
118 | struct cookie_manager_folder *folder = node_data; |
119 | |
120 | if (folder->data.value_len == tw->title_len && |
121 | strcmp(tw->title, folder->data.value) == 0) { |
122 | /* Found what we're looking for */ |
123 | tw->folder = folder; |
124 | *abort = true1; |
125 | } |
126 | } |
127 | |
128 | return NSERROR_OK; |
129 | } |
130 | /** |
131 | * Find a cookie entry in the cookie manager's treeview |
132 | * |
133 | * \param root Search root node, or NULL to search from tree's root |
134 | * \param title ID of the node to look for |
135 | * \param title_len Byte length of title string |
136 | * \param found Updated to the matching node's cookie maanger entry |
137 | * \return NSERROR_OK on success, appropriate error otherwise |
138 | */ |
139 | static nserror cookie_manager_find_entry(treeview_node *root, |
140 | const char *title, size_t title_len, |
141 | struct cookie_manager_entry **found) |
142 | { |
143 | nserror err; |
144 | struct treeview_walk_ctx tw = { |
145 | .title = title, |
146 | .title_len = title_len, |
147 | .folder = NULL((void*)0), |
148 | .entry = NULL((void*)0) |
149 | }; |
150 | |
151 | err = treeview_walk(cm_ctx.tree, root, cookie_manager_walk_cb, NULL((void*)0), |
152 | &tw, TREE_NODE_ENTRY); |
153 | if (err != NSERROR_OK) |
154 | return err; |
155 | |
156 | *found = tw.entry; |
157 | |
158 | return NSERROR_OK; |
159 | } |
160 | /** |
161 | * Find a cookie domain folder in the cookie manager's treeview |
162 | * |
163 | * \param root Search root node, or NULL to search from tree's root |
164 | * \param title ID of the node to look for |
165 | * \param title_len Byte length of title string |
166 | * \param found Updated to the matching node's cookie maanger folder |
167 | * \return NSERROR_OK on success, appropriate error otherwise |
168 | */ |
169 | static nserror cookie_manager_find_folder(treeview_node *root, |
170 | const char *title, size_t title_len, |
171 | struct cookie_manager_folder **found) |
172 | { |
173 | nserror err; |
174 | struct treeview_walk_ctx tw = { |
175 | .title = title, |
176 | .title_len = title_len, |
177 | .folder = NULL((void*)0), |
178 | .entry = NULL((void*)0) |
179 | }; |
180 | |
181 | err = treeview_walk(cm_ctx.tree, root, cookie_manager_walk_cb, NULL((void*)0), |
182 | &tw, TREE_NODE_FOLDER); |
183 | if (err != NSERROR_OK) |
184 | return err; |
185 | |
186 | *found = tw.folder; |
187 | |
188 | return NSERROR_OK; |
189 | } |
190 | |
191 | |
192 | /** |
193 | * Free a cookie manager entry's treeview field data. |
194 | * |
195 | * \param e Cookie manager entry to free data from |
196 | */ |
197 | static void cookie_manager_free_treeview_field_data( |
198 | struct cookie_manager_entry *e) |
199 | { |
200 | /* Eww */ |
201 | free((void *)e->data[COOKIE_M_NAME].value); |
202 | free((void *)e->data[COOKIE_M_CONTENT].value); |
203 | free((void *)e->data[COOKIE_M_DOMAIN].value); |
204 | free((void *)e->data[COOKIE_M_PATH].value); |
205 | free((void *)e->data[COOKIE_M_EXPIRES].value); |
206 | free((void *)e->data[COOKIE_M_LAST_USED].value); |
207 | } |
208 | |
209 | |
210 | /** |
211 | * Build a cookie manager treeview field from given text |
212 | * |
213 | * \param field Cookie manager treeview field to build |
214 | * \param data Cookie manager entry field data to set |
215 | * \param value Text to set in field, ownership yielded |
216 | * \return NSERROR_OK on success, appropriate error otherwise |
217 | */ |
218 | static inline nserror |
219 | cookie_manager_field_builder(enum cookie_manager_field field, |
220 | struct treeview_field_data *data, |
221 | const char *value) |
222 | { |
223 | data->field = cm_ctx.fields[field].field; |
224 | data->value = value; |
225 | data->value_len = (value != NULL((void*)0)) ? strlen(value) : 0; |
226 | |
227 | return NSERROR_OK; |
228 | } |
229 | |
230 | /** |
231 | * Build a cookie manager treeview field from given time |
232 | * |
233 | * The time should be converted to text in the users locacle |
234 | * |
235 | * \param field Cookie manager treeview field to build |
236 | * \param fdata Cookie manager entry field data to set |
237 | * \param value Time to show in field |
238 | * \return NSERROR_OK on success, appropriate error otherwise |
239 | */ |
240 | static inline nserror |
241 | cookie_manager_field_builder_time(enum cookie_manager_field field, |
242 | struct treeview_field_data *fdata, |
243 | const time_t *value) |
244 | { |
245 | struct tm *ftime; |
246 | |
247 | fdata->field = cm_ctx.fields[field].field; |
248 | fdata->value = NULL((void*)0); |
249 | fdata->value_len = 0; |
250 | |
251 | if ((ftime = localtime(value)) != NULL((void*)0)) { |
252 | const size_t vsize = 256; |
253 | char *value = malloc(vsize); |
254 | if (value != NULL((void*)0)) { |
255 | fdata->value = value; |
256 | fdata->value_len = strftime(value, vsize, |
257 | "%a %b %e %H:%M:%S %Y", ftime); |
258 | } |
259 | } |
260 | |
261 | return NSERROR_OK; |
262 | } |
263 | |
264 | |
265 | /** |
266 | * Set a cookie manager entry's data from the cookie_data. |
267 | * |
268 | * \param e Cookie manager entry to set up |
269 | * \param data Data associated with entry's cookie |
270 | * \return NSERROR_OK on success, appropriate error otherwise |
271 | */ |
272 | static nserror |
273 | cookie_manager_set_treeview_field_data(struct cookie_manager_entry *e, |
274 | const struct cookie_data *data) |
275 | { |
276 | assert(e != NULL)((e != ((void*)0)) ? (void) (0) : __assert_fail ("e != NULL", "desktop/cookie_manager.c", 276, __extension__ __PRETTY_FUNCTION__ )); |
277 | assert(data != NULL)((data != ((void*)0)) ? (void) (0) : __assert_fail ("data != NULL" , "desktop/cookie_manager.c", 277, __extension__ __PRETTY_FUNCTION__ )); |
278 | |
279 | /* Set the fields up */ |
280 | cookie_manager_field_builder(COOKIE_M_NAME, |
281 | &e->data[COOKIE_M_NAME], strdup(data->name)); |
282 | cookie_manager_field_builder(COOKIE_M_CONTENT, |
283 | &e->data[COOKIE_M_CONTENT], strdup(data->value)); |
284 | cookie_manager_field_builder(COOKIE_M_DOMAIN, |
285 | &e->data[COOKIE_M_DOMAIN], strdup(data->domain)); |
286 | cookie_manager_field_builder(COOKIE_M_PATH, |
287 | &e->data[COOKIE_M_PATH], strdup(data->path)); |
288 | |
289 | /* Set the Expires date field */ |
290 | if (data->expires == -1) { |
291 | cookie_manager_field_builder(COOKIE_M_EXPIRES, |
292 | &e->data[COOKIE_M_EXPIRES], |
293 | strdup(messages_get("CookieManagerSession"))); |
294 | } else { |
295 | cookie_manager_field_builder_time(COOKIE_M_EXPIRES, |
296 | &e->data[COOKIE_M_EXPIRES], &data->expires); |
297 | } |
298 | |
299 | /* Set the Last used date field */ |
300 | cookie_manager_field_builder_time(COOKIE_M_LAST_USED, |
301 | &e->data[COOKIE_M_LAST_USED], &data->last_used); |
302 | |
303 | /* Set the Restrictions text */ |
304 | if (data->secure && data->http_only) { |
305 | e->data[COOKIE_M_RESTRICTIONS] = cm_ctx.values[COOKIE_M_HTTPS]; |
306 | } else if (data->secure) { |
307 | e->data[COOKIE_M_RESTRICTIONS] = cm_ctx.values[COOKIE_M_SECURE]; |
308 | } else if (data->http_only) { |
309 | e->data[COOKIE_M_RESTRICTIONS] = cm_ctx.values[COOKIE_M_HTTP]; |
310 | } else { |
311 | e->data[COOKIE_M_RESTRICTIONS] = cm_ctx.values[COOKIE_M_NONE]; |
312 | } |
313 | |
314 | /* Set the Version text */ |
315 | switch (data->version) { |
316 | case COOKIE_NETSCAPE: |
317 | e->data[COOKIE_M_VERSION] = cm_ctx.values[COOKIE_M_NETSCAPE]; |
318 | break; |
319 | |
320 | case COOKIE_RFC2109: |
321 | e->data[COOKIE_M_VERSION] = cm_ctx.values[COOKIE_M_RFC2109]; |
322 | break; |
323 | |
324 | case COOKIE_RFC2965: |
325 | e->data[COOKIE_M_VERSION] = cm_ctx.values[COOKIE_M_RFC2965]; |
326 | break; |
327 | } |
328 | |
329 | return NSERROR_OK; |
330 | } |
331 | |
332 | |
333 | /** |
334 | * Creates an empty tree entry for a cookie, and links it into the tree. |
335 | * |
336 | * All information is copied from the cookie_data, and as such can |
337 | * be edited and should be freed. |
338 | * |
339 | * \param parent the node to link to |
340 | * \param data the cookie data to use |
341 | * \return NSERROR_OK on success, appropriate error otherwise |
342 | */ |
343 | static nserror cookie_manager_create_cookie_node( |
344 | struct cookie_manager_folder *parent, |
345 | const struct cookie_data *data) |
346 | { |
347 | nserror err; |
348 | struct cookie_manager_entry *cookie; |
349 | |
350 | /* Create new cookie manager entry */ |
351 | cookie = malloc(sizeof(struct cookie_manager_entry)); |
352 | if (cookie == NULL((void*)0)) { |
353 | return NSERROR_NOMEM; |
354 | } |
355 | |
356 | cookie->user_delete = false0; |
357 | |
358 | err = cookie_manager_set_treeview_field_data(cookie, data); |
359 | if (err != NSERROR_OK) { |
360 | free(cookie); |
361 | return err; |
362 | } |
363 | |
364 | err = treeview_create_node_entry(cm_ctx.tree, |
365 | &(cookie->entry), |
366 | parent->folder, |
367 | TREE_REL_FIRST_CHILD, |
368 | cookie->data, |
369 | cookie, |
370 | cm_ctx.built ? TREE_OPTION_NONE : |
371 | TREE_OPTION_SUPPRESS_RESIZE | |
372 | TREE_OPTION_SUPPRESS_REDRAW); |
373 | if (err != NSERROR_OK) { |
374 | cookie_manager_free_treeview_field_data(cookie); |
375 | free(cookie); |
376 | return err; |
377 | } |
378 | |
379 | return NSERROR_OK; |
380 | } |
381 | |
382 | |
383 | /** |
384 | * Updates a cookie manager entry for updated cookie_data. |
385 | * |
386 | * All information is copied from the cookie_data, and as such can |
387 | * be edited and should be freed. |
388 | * |
389 | * \param e the entry to update |
390 | * \param data the cookie data to use |
391 | * \return NSERROR_OK on success, appropriate error otherwise |
392 | */ |
393 | static nserror cookie_manager_update_cookie_node( |
394 | struct cookie_manager_entry *e, |
395 | const struct cookie_data *data) |
396 | { |
397 | nserror err; |
398 | |
399 | assert(e != NULL)((e != ((void*)0)) ? (void) (0) : __assert_fail ("e != NULL", "desktop/cookie_manager.c", 399, __extension__ __PRETTY_FUNCTION__ )); |
400 | |
401 | /* Reset to defaults */ |
402 | e->user_delete = false0; |
403 | cookie_manager_free_treeview_field_data(e); |
404 | |
405 | /* Set new field values from the cookie_data */ |
406 | err = cookie_manager_set_treeview_field_data(e, data); |
407 | if (err != NSERROR_OK) { |
408 | return err; |
409 | } |
410 | |
411 | /* Update the treeview */ |
412 | err = treeview_update_node_entry(cm_ctx.tree, e->entry, e->data, e); |
413 | if (err != NSERROR_OK) { |
414 | return err; |
415 | } |
416 | |
417 | return NSERROR_OK; |
418 | } |
419 | |
420 | |
421 | /** |
422 | * Creates an empty tree folder for a cookie domain, and links it into the tree. |
423 | * |
424 | * All information is copied from the cookie_data, and as such can |
425 | * be edited and should be freed. |
426 | * |
427 | * \param folder updated to the new folder |
428 | * \param data the cookie data to use |
429 | * \return NSERROR_OK on success, appropriate error otherwise |
430 | */ |
431 | static nserror cookie_manager_create_domain_folder( |
432 | struct cookie_manager_folder **folder, |
433 | const struct cookie_data *data) |
434 | { |
435 | nserror err; |
436 | struct cookie_manager_folder *f; |
437 | |
438 | /* Create new cookie manager entry */ |
439 | f = malloc(sizeof(struct cookie_manager_folder)); |
440 | if (f == NULL((void*)0)) { |
441 | return NSERROR_NOMEM; |
442 | } |
443 | |
444 | f->data.field = cm_ctx.fields[COOKIE_M_N_FIELDS - 1].field; |
445 | f->data.value = strdup(data->domain); |
446 | f->data.value_len = (f->data.value != NULL((void*)0)) ? |
447 | strlen(data->domain) : 0; |
448 | |
449 | err = treeview_create_node_folder(cm_ctx.tree, &(f->folder), |
450 | NULL((void*)0), TREE_REL_FIRST_CHILD, &f->data, f, |
451 | cm_ctx.built ? TREE_OPTION_NONE : |
452 | TREE_OPTION_SUPPRESS_RESIZE | |
453 | TREE_OPTION_SUPPRESS_REDRAW); |
454 | if (err != NSERROR_OK) { |
455 | free((void *)f->data.value); |
456 | free(f); |
457 | return err; |
458 | } |
459 | |
460 | *folder = f; |
461 | |
462 | return NSERROR_OK; |
463 | } |
464 | |
465 | |
466 | /* exported interface documented in cookie_manager.h */ |
467 | bool_Bool cookie_manager_add(const struct cookie_data *data) |
468 | { |
469 | struct cookie_manager_folder *parent = NULL((void*)0); |
470 | struct cookie_manager_entry *cookie = NULL((void*)0); |
471 | nserror err; |
472 | |
473 | assert(data != NULL)((data != ((void*)0)) ? (void) (0) : __assert_fail ("data != NULL" , "desktop/cookie_manager.c", 473, __extension__ __PRETTY_FUNCTION__ )); |
474 | |
475 | /* If we don't have a cookie manager at the moment, just return true */ |
476 | if (cm_ctx.tree == NULL((void*)0)) |
477 | return true1; |
478 | |
479 | err = cookie_manager_find_folder(NULL((void*)0), data->domain, |
480 | strlen(data->domain), &parent); |
481 | if (err != NSERROR_OK) { |
482 | return false0; |
483 | } |
484 | |
485 | if (parent == NULL((void*)0)) { |
486 | /* Need to create domain directory */ |
487 | err = cookie_manager_create_domain_folder(&parent, data); |
488 | if (err != NSERROR_OK || parent == NULL((void*)0)) |
489 | return false0; |
490 | } |
491 | |
492 | /* Create cookie node */ |
493 | err = cookie_manager_find_entry(parent->folder, data->name, |
494 | strlen(data->name), &cookie); |
495 | if (err != NSERROR_OK) |
496 | return false0; |
497 | |
498 | if (cookie == NULL((void*)0)) { |
499 | err = cookie_manager_create_cookie_node(parent, data); |
500 | } else { |
501 | err = cookie_manager_update_cookie_node(cookie, data); |
502 | } |
503 | if (err != NSERROR_OK) |
504 | return false0; |
505 | |
506 | return true1; |
507 | } |
508 | |
509 | |
510 | /* exported interface documented in cookie_manager.h */ |
511 | void cookie_manager_remove(const struct cookie_data *data) |
512 | { |
513 | struct cookie_manager_folder *parent = NULL((void*)0); |
514 | struct cookie_manager_entry *cookie = NULL((void*)0); |
515 | nserror err; |
516 | |
517 | assert(data != NULL)((data != ((void*)0)) ? (void) (0) : __assert_fail ("data != NULL" , "desktop/cookie_manager.c", 517, __extension__ __PRETTY_FUNCTION__ )); |
518 | |
519 | /* If we don't have a cookie manager at the moment, just return */ |
520 | if (cm_ctx.tree == NULL((void*)0)) |
521 | return; |
522 | |
523 | err = cookie_manager_find_folder(NULL((void*)0), data->domain, |
524 | strlen(data->domain), &parent); |
525 | if (err != NSERROR_OK || parent == NULL((void*)0)) { |
526 | /* Nothing to delete */ |
527 | return; |
528 | } |
529 | |
530 | err = cookie_manager_find_entry(parent->folder, data->name, |
531 | strlen(data->name), &cookie); |
532 | if (err != NSERROR_OK || cookie == NULL((void*)0)) { |
533 | /* Nothing to delete */ |
534 | return; |
535 | } |
536 | |
537 | /* Delete the node */ |
538 | treeview_delete_node(cm_ctx.tree, cookie->entry, TREE_OPTION_NONE); |
539 | } |
540 | |
541 | |
542 | /* exported interface documented in cookie_manager.h */ |
543 | nserror cookie_manager_set_search_string( |
544 | const char *string) |
545 | { |
546 | /* If we don't have a cookie manager at the moment, just return */ |
547 | if (cm_ctx.tree == NULL((void*)0)) { |
548 | return NSERROR_NOT_FOUND; |
549 | } |
550 | |
551 | return treeview_set_search_string(cm_ctx.tree, string); |
552 | } |
553 | |
554 | |
555 | /** |
556 | * Initialise the treeview entry feilds |
557 | * |
558 | * \return true on success, false on memory exhaustion |
559 | */ |
560 | static nserror cookie_manager_init_entry_fields(void) |
561 | { |
562 | int i; |
563 | const char *label; |
564 | |
565 | for (i = 0; i < COOKIE_M_N_FIELDS; i++) |
566 | cm_ctx.fields[i].field = NULL((void*)0); |
567 | |
568 | cm_ctx.fields[COOKIE_M_NAME].flags = TREE_FLAG_DEFAULT; |
569 | label = "TreeviewLabelName"; |
570 | label = messages_get(label); |
571 | if (lwc_intern_string(label, strlen(label), |
572 | &cm_ctx.fields[COOKIE_M_NAME].field) != |
573 | lwc_error_ok) { |
574 | goto error; |
575 | } |
576 | |
577 | cm_ctx.fields[COOKIE_M_CONTENT].flags = TREE_FLAG_SHOW_NAME; |
578 | label = "TreeviewLabelContent"; |
579 | label = messages_get(label); |
580 | if (lwc_intern_string(label, strlen(label), |
581 | &cm_ctx.fields[COOKIE_M_CONTENT].field) != |
582 | lwc_error_ok) { |
583 | goto error; |
584 | } |
585 | |
586 | cm_ctx.fields[COOKIE_M_DOMAIN].flags = |
587 | TREE_FLAG_SHOW_NAME | |
588 | TREE_FLAG_SEARCHABLE; |
589 | label = "TreeviewLabelDomain"; |
590 | label = messages_get(label); |
591 | if (lwc_intern_string(label, strlen(label), |
592 | &cm_ctx.fields[COOKIE_M_DOMAIN].field) != |
593 | lwc_error_ok) { |
594 | goto error; |
595 | } |
596 | |
597 | cm_ctx.fields[COOKIE_M_PATH].flags = TREE_FLAG_SHOW_NAME; |
598 | label = "TreeviewLabelPath"; |
599 | label = messages_get(label); |
600 | if (lwc_intern_string(label, strlen(label), |
601 | &cm_ctx.fields[COOKIE_M_PATH].field) != |
602 | lwc_error_ok) { |
603 | goto error; |
604 | } |
605 | |
606 | cm_ctx.fields[COOKIE_M_EXPIRES].flags = TREE_FLAG_SHOW_NAME; |
607 | label = "TreeviewLabelExpires"; |
608 | label = messages_get(label); |
609 | if (lwc_intern_string(label, strlen(label), |
610 | &cm_ctx.fields[COOKIE_M_EXPIRES].field) != |
611 | lwc_error_ok) { |
612 | goto error; |
613 | } |
614 | |
615 | cm_ctx.fields[COOKIE_M_LAST_USED].flags = TREE_FLAG_SHOW_NAME; |
616 | label = "TreeviewLabelLastUsed"; |
617 | label = messages_get(label); |
618 | if (lwc_intern_string(label, strlen(label), |
619 | &cm_ctx.fields[COOKIE_M_LAST_USED].field) != |
620 | lwc_error_ok) { |
621 | goto error; |
622 | } |
623 | |
624 | cm_ctx.fields[COOKIE_M_RESTRICTIONS].flags = TREE_FLAG_SHOW_NAME; |
625 | label = "TreeviewLabelRestrictions"; |
626 | label = messages_get(label); |
627 | if (lwc_intern_string(label, strlen(label), |
628 | &cm_ctx.fields[COOKIE_M_RESTRICTIONS].field) != |
629 | lwc_error_ok) { |
630 | goto error; |
631 | } |
632 | |
633 | cm_ctx.fields[COOKIE_M_VERSION].flags = TREE_FLAG_SHOW_NAME; |
634 | label = "TreeviewLabelVersion"; |
635 | label = messages_get(label); |
636 | if (lwc_intern_string(label, strlen(label), |
637 | &cm_ctx.fields[COOKIE_M_VERSION].field) != |
638 | lwc_error_ok) { |
639 | goto error; |
640 | } |
641 | |
642 | cm_ctx.fields[COOKIE_M_DOMAIN_FOLDER].flags = TREE_FLAG_DEFAULT; |
643 | label = "TreeviewLabelDomainFolder"; |
644 | label = messages_get(label); |
645 | if (lwc_intern_string(label, strlen(label), |
646 | &cm_ctx.fields[COOKIE_M_DOMAIN_FOLDER].field) != |
647 | lwc_error_ok) { |
648 | return false0; |
649 | } |
650 | |
651 | return NSERROR_OK; |
652 | |
653 | error: |
654 | for (i = 0; i < COOKIE_M_N_FIELDS; i++) |
655 | if (cm_ctx.fields[i].field != NULL((void*)0)) |
656 | lwc_string_unref(cm_ctx.fields[i].field){ lwc_string *__lwc_s = (cm_ctx.fields[i].field); ((__lwc_s != ((void*)0)) ? (void) (0) : __assert_fail ("__lwc_s != NULL", "desktop/cookie_manager.c", 656, __extension__ __PRETTY_FUNCTION__ )); __lwc_s->refcnt--; if ((__lwc_s->refcnt == 0) || (( __lwc_s->refcnt == 1) && (__lwc_s->insensitive == __lwc_s))) lwc_string_destroy(__lwc_s); }; |
657 | |
658 | return NSERROR_UNKNOWN; |
659 | } |
660 | |
661 | |
662 | |
663 | /** |
664 | * Initialise the common entry values |
665 | * |
666 | * \return true on success, false on memory exhaustion |
667 | */ |
668 | static nserror cookie_manager_init_common_values(void) |
669 | { |
670 | const char *temp; |
671 | |
672 | /* Set the Restrictions text */ |
673 | temp = messages_get("CookieManagerHTTPS"); |
674 | cookie_manager_field_builder(COOKIE_M_RESTRICTIONS, |
675 | &cm_ctx.values[COOKIE_M_HTTPS], strdup(temp)); |
676 | |
677 | temp = messages_get("CookieManagerSecure"); |
678 | cookie_manager_field_builder(COOKIE_M_RESTRICTIONS, |
679 | &cm_ctx.values[COOKIE_M_SECURE], strdup(temp)); |
680 | |
681 | temp = messages_get("CookieManagerHTTP"); |
682 | cookie_manager_field_builder(COOKIE_M_RESTRICTIONS, |
683 | &cm_ctx.values[COOKIE_M_HTTP], strdup(temp)); |
684 | |
685 | temp = messages_get("None"); |
686 | cookie_manager_field_builder(COOKIE_M_RESTRICTIONS, |
687 | &cm_ctx.values[COOKIE_M_NONE], strdup(temp)); |
688 | |
689 | /* Set the Cookie version text */ |
690 | assert(COOKIE_NETSCAPE == 0)((COOKIE_NETSCAPE == 0) ? (void) (0) : __assert_fail ("COOKIE_NETSCAPE == 0" , "desktop/cookie_manager.c", 690, __extension__ __PRETTY_FUNCTION__ )); |
691 | temp = messages_get("TreeVersion0"); |
692 | cookie_manager_field_builder(COOKIE_M_VERSION, |
693 | &cm_ctx.values[COOKIE_M_NETSCAPE], strdup(temp)); |
694 | |
695 | assert(COOKIE_RFC2109 == 1)((COOKIE_RFC2109 == 1) ? (void) (0) : __assert_fail ("COOKIE_RFC2109 == 1" , "desktop/cookie_manager.c", 695, __extension__ __PRETTY_FUNCTION__ )); |
696 | temp = messages_get("TreeVersion1"); |
697 | cookie_manager_field_builder(COOKIE_M_VERSION, |
698 | &cm_ctx.values[COOKIE_M_RFC2109], strdup(temp)); |
699 | |
700 | assert(COOKIE_RFC2965 == 2)((COOKIE_RFC2965 == 2) ? (void) (0) : __assert_fail ("COOKIE_RFC2965 == 2" , "desktop/cookie_manager.c", 700, __extension__ __PRETTY_FUNCTION__ )); |
701 | temp = messages_get("TreeVersion2"); |
702 | cookie_manager_field_builder(COOKIE_M_VERSION, |
703 | &cm_ctx.values[COOKIE_M_RFC2965], strdup(temp)); |
704 | |
705 | return NSERROR_OK; |
706 | } |
707 | |
708 | |
709 | /** |
710 | * Delete cookie manager entries (and optionally delete from urldb) |
711 | * |
712 | * \param e Cookie manager entry to delete. |
713 | */ |
714 | static void cookie_manager_delete_entry(struct cookie_manager_entry *e) |
715 | { |
716 | const char *domain; |
717 | const char *path; |
718 | const char *name; |
719 | |
720 | if (e->user_delete) { |
721 | /* Delete the cookie from URLdb */ |
722 | domain = e->data[COOKIE_M_DOMAIN].value; |
723 | path = e->data[COOKIE_M_PATH].value; |
724 | name = e->data[COOKIE_M_NAME].value; |
725 | |
726 | if ((domain != NULL((void*)0)) && (path != NULL((void*)0)) && (name != NULL((void*)0))) { |
727 | |
728 | urldb_delete_cookie(domain, path, name); |
729 | } else { |
730 | NSLOG(netsurf, INFO,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf , NSLOG_LEVEL_INFO, "desktop/cookie_manager.c", sizeof("desktop/cookie_manager.c" ) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 731 , }; nslog__log(&_nslog_ctx, "Delete cookie fail: ""need domain, path, and name." ); } } while(0) |
731 | "Delete cookie fail: ""need domain, path, and name.")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf , NSLOG_LEVEL_INFO, "desktop/cookie_manager.c", sizeof("desktop/cookie_manager.c" ) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 731 , }; nslog__log(&_nslog_ctx, "Delete cookie fail: ""need domain, path, and name." ); } } while(0); |
732 | } |
733 | } |
734 | |
735 | /* Delete the cookie manager entry */ |
736 | cookie_manager_free_treeview_field_data(e); |
737 | free(e); |
738 | } |
739 | |
740 | |
741 | static nserror cookie_manager_tree_node_folder_cb( |
742 | struct treeview_node_msg msg, void *data) |
743 | { |
744 | struct cookie_manager_folder *f = data; |
745 | |
746 | switch (msg.msg) { |
747 | case TREE_MSG_NODE_DELETE: |
748 | free(f); |
749 | break; |
750 | |
751 | case TREE_MSG_NODE_EDIT: |
752 | break; |
753 | |
754 | case TREE_MSG_NODE_LAUNCH: |
755 | break; |
756 | } |
757 | |
758 | return NSERROR_OK; |
759 | } |
760 | |
761 | |
762 | static nserror cookie_manager_tree_node_entry_cb( |
763 | struct treeview_node_msg msg, void *data) |
764 | { |
765 | struct cookie_manager_entry *e = data; |
766 | |
767 | switch (msg.msg) { |
768 | case TREE_MSG_NODE_DELETE: |
769 | e->entry = NULL((void*)0); |
770 | e->user_delete = msg.data.delete.user; |
771 | cookie_manager_delete_entry(e); |
772 | break; |
773 | |
774 | case TREE_MSG_NODE_EDIT: |
775 | break; |
776 | |
777 | case TREE_MSG_NODE_LAUNCH: |
778 | break; |
779 | } |
780 | return NSERROR_OK; |
781 | } |
782 | |
783 | |
784 | struct treeview_callback_table cm_tree_cb_t = { |
785 | .folder = cookie_manager_tree_node_folder_cb, |
786 | .entry = cookie_manager_tree_node_entry_cb |
787 | }; |
788 | |
789 | |
790 | /* Exported interface, documented in cookie_manager.h */ |
791 | nserror cookie_manager_init(void *core_window_handle) |
792 | { |
793 | nserror err; |
794 | |
795 | err = treeview_init(); |
796 | if (err != NSERROR_OK) { |
797 | return err; |
798 | } |
799 | |
800 | NSLOG(netsurf, INFO, "Generating cookie manager data")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf , NSLOG_LEVEL_INFO, "desktop/cookie_manager.c", sizeof("desktop/cookie_manager.c" ) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 800 , }; nslog__log(&_nslog_ctx, "Generating cookie manager data" ); } } while(0); |
801 | |
802 | /* Init. cookie manager treeview entry fields */ |
803 | err = cookie_manager_init_entry_fields(); |
804 | if (err != NSERROR_OK) { |
805 | cm_ctx.tree = NULL((void*)0); |
806 | return err; |
807 | } |
808 | |
809 | /* Init. common treeview field values */ |
810 | err = cookie_manager_init_common_values(); |
811 | if (err != NSERROR_OK) { |
812 | cm_ctx.tree = NULL((void*)0); |
813 | return err; |
814 | } |
815 | |
816 | /* Create the cookie manager treeview */ |
817 | err = treeview_create(&cm_ctx.tree, &cm_tree_cb_t, |
818 | COOKIE_M_N_FIELDS, cm_ctx.fields, |
819 | core_window_handle, |
820 | TREEVIEW_NO_MOVES | |
821 | TREEVIEW_DEL_EMPTY_DIRS | |
822 | TREEVIEW_SEARCHABLE); |
823 | if (err != NSERROR_OK) { |
824 | cm_ctx.tree = NULL((void*)0); |
825 | return err; |
826 | } |
827 | |
828 | /* Load the cookies */ |
829 | urldb_iterate_cookies(cookie_manager_add); |
830 | |
831 | /* Cookie manager is built |
832 | * We suppress the treeview height callback on entry insertion before |
833 | * the treeview is built. */ |
834 | cm_ctx.built = true1; |
835 | |
836 | /* Inform client of window height */ |
837 | treeview_get_height(cm_ctx.tree); |
838 | |
839 | NSLOG(netsurf, INFO, "Generated cookie manager data")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf , NSLOG_LEVEL_INFO, "desktop/cookie_manager.c", sizeof("desktop/cookie_manager.c" ) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 839 , }; nslog__log(&_nslog_ctx, "Generated cookie manager data" ); } } while(0); |
840 | |
841 | return NSERROR_OK; |
842 | } |
843 | |
844 | |
845 | /* Exported interface, documented in cookie_manager.h */ |
846 | nserror cookie_manager_fini(void) |
847 | { |
848 | int i; |
849 | nserror err; |
850 | |
851 | NSLOG(netsurf, INFO, "Finalising cookie manager")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf , NSLOG_LEVEL_INFO, "desktop/cookie_manager.c", sizeof("desktop/cookie_manager.c" ) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 851 , }; nslog__log(&_nslog_ctx, "Finalising cookie manager") ; } } while(0); |
852 | |
853 | cm_ctx.built = false0; |
854 | |
855 | /* Destroy the cookie manager treeview */ |
856 | err = treeview_destroy(cm_ctx.tree); |
Value stored to 'err' is never read | |
857 | cm_ctx.tree = NULL((void*)0); |
858 | |
859 | /* Free cookie manager treeview entry fields */ |
860 | for (i = 0; i < COOKIE_M_N_FIELDS; i++) |
861 | if (cm_ctx.fields[i].field != NULL((void*)0)) |
862 | lwc_string_unref(cm_ctx.fields[i].field){ lwc_string *__lwc_s = (cm_ctx.fields[i].field); ((__lwc_s != ((void*)0)) ? (void) (0) : __assert_fail ("__lwc_s != NULL", "desktop/cookie_manager.c", 862, __extension__ __PRETTY_FUNCTION__ )); __lwc_s->refcnt--; if ((__lwc_s->refcnt == 0) || (( __lwc_s->refcnt == 1) && (__lwc_s->insensitive == __lwc_s))) lwc_string_destroy(__lwc_s); }; |
863 | |
864 | /* Free cookie manager treeview common entry values */ |
865 | for (i = 0; i < COOKIE_M_N_VALUES; i++) |
866 | if (cm_ctx.values[i].value != NULL((void*)0)) |
867 | free((void *) cm_ctx.values[i].value); |
868 | |
869 | err = treeview_fini(); |
870 | if (err != NSERROR_OK) { |
871 | return err; |
872 | } |
873 | |
874 | NSLOG(netsurf, INFO, "Finalised cookie manager")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf , NSLOG_LEVEL_INFO, "desktop/cookie_manager.c", sizeof("desktop/cookie_manager.c" ) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 874 , }; nslog__log(&_nslog_ctx, "Finalised cookie manager"); } } while(0); |
875 | |
876 | return err; |
877 | } |
878 | |
879 | |
880 | /* Exported interface, documented in cookie_manager.h */ |
881 | void cookie_manager_redraw(int x, int y, struct rect *clip, |
882 | const struct redraw_context *ctx) |
883 | { |
884 | treeview_redraw(cm_ctx.tree, x, y, clip, ctx); |
885 | } |
886 | |
887 | |
888 | /* Exported interface, documented in cookie_manager.h */ |
889 | void cookie_manager_mouse_action(enum browser_mouse_state mouse, int x, int y) |
890 | { |
891 | treeview_mouse_action(cm_ctx.tree, mouse, x, y); |
892 | } |
893 | |
894 | |
895 | /* Exported interface, documented in cookie_manager.h */ |
896 | bool_Bool cookie_manager_keypress(uint32_t key) |
897 | { |
898 | return treeview_keypress(cm_ctx.tree, key); |
899 | } |
900 | |
901 | |
902 | /* Exported interface, documented in cookie_manager.h */ |
903 | bool_Bool cookie_manager_has_selection(void) |
904 | { |
905 | return treeview_has_selection(cm_ctx.tree); |
906 | } |
907 | |
908 | |
909 | /* Exported interface, documented in cookie_manager.h */ |
910 | nserror cookie_manager_expand(bool_Bool only_folders) |
911 | { |
912 | return treeview_expand(cm_ctx.tree, only_folders); |
913 | } |
914 | |
915 | |
916 | /* Exported interface, documented in cookie_manager.h */ |
917 | nserror cookie_manager_contract(bool_Bool all) |
918 | { |
919 | return treeview_contract(cm_ctx.tree, all); |
920 | } |
921 |