From 6173bb0e6c3bf51cd463f7bc4f725429d9087b2b Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Tue, 5 Oct 2010 19:14:46 +0000 Subject: Merge treeview-redux to trunk svn path=/trunk/netsurf/; revision=10865 --- desktop/cookies.c | 531 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 531 insertions(+) create mode 100644 desktop/cookies.c (limited to 'desktop/cookies.c') diff --git a/desktop/cookies.c b/desktop/cookies.c new file mode 100644 index 000000000..c5dac5101 --- /dev/null +++ b/desktop/cookies.c @@ -0,0 +1,531 @@ +/* + * Copyright 2006 Richard Wilson + * Copyright 2009 Paul Blokus + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * Cookies (implementation). + */ + +#include +#include +#include +#include +#include +#include +#include "content/content.h" +#include "content/hlcache.h" +#include "content/urldb.h" +#include "desktop/cookies.h" +#include "desktop/options.h" +#include "desktop/tree.h" +#include "utils/messages.h" +#include "utils/log.h" +#include "utils/url.h" +#include "utils/utils.h" + +/** Flags for each type of cookie tree node. */ +enum tree_element_cookie { + TREE_ELEMENT_PERSISTENT = 0x01, + TREE_ELEMENT_VERSION = 0x02, + TREE_ELEMENT_SECURE = 0x03, + TREE_ELEMENT_LAST_USED = 0x04, + TREE_ELEMENT_EXPIRES = 0x05, + TREE_ELEMENT_PATH = 0x06, + TREE_ELEMENT_DOMAIN = 0x07, + TREE_ELEMENT_COMMENT = 0x08, + TREE_ELEMENT_VALUE = 0x09, +}; + +static struct tree *cookies_tree; +static struct node *cookies_tree_root; +static bool user_delete; +static hlcache_handle *folder_icon; +static hlcache_handle *cookie_icon; + + +/** + * Find an entry in the cookie tree + * + * \param node the node to check the children of + * \param title The title to find + * \return Pointer to node, or NULL if not found + */ +static struct node *cookies_find(struct node *node, const char *title) +{ + struct node *search; + struct node_element *element; + + for (search = tree_node_get_child(node); search; + search = tree_node_get_next(search)) { + element = tree_node_find_element(search, TREE_ELEMENT_TITLE, + NULL); + if (strcmp(title, tree_node_element_get_text(element)) == 0) + return search; + } + return NULL; +} + +/** + * Callback for all cookie tree nodes. + */ +static node_callback_resp cookies_node_callback(void *user_data, struct node_msg_data *msg_data) +{ + struct node *node = msg_data->node; + struct node_element *domain, *path; + const char *domain_t, *path_t, *name_t; + char *space; + bool is_folder = tree_node_is_folder(node); + + /* we don't remove any icons here */ + if (msg_data->msg == NODE_DELETE_ELEMENT_IMG) + return NODE_CALLBACK_HANDLED; + + /* let the tree handle events other than text data removal */ + if (msg_data->msg != NODE_DELETE_ELEMENT_TXT) + return NODE_CALLBACK_NOT_HANDLED; + + /* check if it's a domain folder */ + if (is_folder) + return NODE_CALLBACK_NOT_HANDLED; + + switch (msg_data->flag) { + case TREE_ELEMENT_TITLE: + if (!user_delete) + break; + /* get the rest of the cookie data */ + domain = tree_node_find_element(node, + TREE_ELEMENT_DOMAIN, NULL); + path = tree_node_find_element(node, TREE_ELEMENT_PATH, + NULL); + + if ((domain != NULL) && + (path != NULL)) { + domain_t = tree_node_element_get_text(domain) + + strlen(messages_get( + "TreeDomain")) - 4; + space = strchr(domain_t, ' '); + if (space != NULL) + *space = '\0'; + path_t = tree_node_element_get_text(path) + + strlen(messages_get("TreePath")) + - 4; + space = strchr(path_t, ' '); + if (space != NULL) + *space = '\0'; + name_t = msg_data->data.text; + urldb_delete_cookie(domain_t, path_t, name_t); + } + break; + default: + break; + } + + free(msg_data->data.text); + + return NODE_CALLBACK_HANDLED; +} + + +/** + * Updates a tree entry for a cookie. + * + * All information is copied from the cookie_data, and as such can + * be edited and should be freed. + * + * \param node The node to update + * \param data The cookie data to use + * \return true if node updated, or false for failure + */ +static bool cookies_update_cookie_node(struct node *node, + const struct cookie_data *data) +{ + struct node_element *element; + char buffer[32]; + + assert(data != NULL); + + /* update the value text */ + element = tree_node_find_element(node, TREE_ELEMENT_VALUE, NULL); + tree_update_element_text(cookies_tree, + element, + messages_get_buff("TreeValue", + data->value != NULL ? + data->value : + messages_get("TreeUnused"))); + + + /* update the comment text */ + if ((data->comment != NULL) && + (strcmp(data->comment, "") != 0)) { + element = tree_node_find_element(node, TREE_ELEMENT_COMMENT, NULL); + tree_update_element_text(cookies_tree, + element, + messages_get_buff("TreeComment", + data->comment)); + } + + /* update domain text */ + element = tree_node_find_element(node, TREE_ELEMENT_DOMAIN, element); + tree_update_element_text(cookies_tree, + element, + messages_get_buff("TreeDomain", + data->domain, + data->domain_from_set ? + messages_get("TreeHeaders") : + "")); + + /* update path text */ + element = tree_node_find_element(node, TREE_ELEMENT_PATH, element); + tree_update_element_text(cookies_tree, + element, + messages_get_buff("TreePath", data->path, + data->path_from_set ? + messages_get("TreeHeaders") : + "")); + + /* update expiry text */ + element = tree_node_find_element(node, TREE_ELEMENT_EXPIRES, element); + tree_update_element_text(cookies_tree, + element, + messages_get_buff("TreeExpires", + (data->expires > 0) + ? (data->expires == 1) + ? messages_get("TreeSession") + : ctime(&data->expires) + : messages_get("TreeUnknown"))); + + /* update last used text */ + element = tree_node_find_element(node, TREE_ELEMENT_LAST_USED, element); + tree_update_element_text(cookies_tree, + element, + messages_get_buff("TreeLastUsed", + (data->last_used > 0) ? + ctime(&data->last_used) : + messages_get("TreeUnknown"))); + + /* update secure text */ + element = tree_node_find_element(node, TREE_ELEMENT_SECURE, element); + tree_update_element_text(cookies_tree, + element, + messages_get_buff("TreeSecure", + data->secure ? + messages_get("Yes") : + messages_get("No"))); + + /* update version text */ + element = tree_node_find_element(node, TREE_ELEMENT_VERSION, element); + snprintf(buffer, sizeof(buffer), "TreeVersion%i", data->version); + tree_update_element_text(cookies_tree, + element, + messages_get_buff("TreeVersion", + messages_get(buffer))); + + /* update persistant text */ + element = tree_node_find_element(node, TREE_ELEMENT_PERSISTENT, element); + tree_update_element_text(cookies_tree, + element, + messages_get_buff("TreePersistent", + data->no_destroy ? + messages_get("Yes") : + messages_get("No"))); + + return node; +} + +/** + * Creates an empty tree entry for a cookie, and links it into the tree. + * + * All information is copied from the cookie_data, and as such can + * be edited and should be freed. + * + * \param parent the node to link to + * \param data the cookie data to use + * \return the node created, or NULL for failure + */ +static struct node *cookies_create_cookie_node(struct node *parent, + const struct cookie_data *data) +{ + struct node *node; + char *name; + + name = strdup(data->name); + if (name == NULL) { + LOG(("malloc failed")); + warn_user("NoMemory", 0); + return NULL; + } + + node = tree_create_leaf_node(cookies_tree, NULL, name, + false, false, false); + if (node == NULL) { + free(name); + return NULL; + } + + tree_set_node_user_callback(node, cookies_node_callback, NULL); + + tree_create_node_element(node, NODE_ELEMENT_TEXT, + TREE_ELEMENT_PERSISTENT, false); + + tree_create_node_element(node, NODE_ELEMENT_TEXT, + TREE_ELEMENT_VERSION, false); + + tree_create_node_element(node, NODE_ELEMENT_TEXT, + TREE_ELEMENT_SECURE, false); + + tree_create_node_element(node, NODE_ELEMENT_TEXT, + TREE_ELEMENT_LAST_USED, false); + + tree_create_node_element(node, NODE_ELEMENT_TEXT, + TREE_ELEMENT_EXPIRES, false); + + tree_create_node_element(node, NODE_ELEMENT_TEXT, + TREE_ELEMENT_PATH, false); + + tree_create_node_element(node, NODE_ELEMENT_TEXT, + TREE_ELEMENT_DOMAIN, false); + + if ((data->comment) && (strcmp(data->comment, ""))) + tree_create_node_element(node, NODE_ELEMENT_TEXT, + TREE_ELEMENT_COMMENT, false); + tree_create_node_element(node, NODE_ELEMENT_TEXT, + TREE_ELEMENT_VALUE, false); + tree_set_node_icon(cookies_tree, node, cookie_icon); + + if (!cookies_update_cookie_node(node, data)) + { + tree_delete_node(NULL, node, false); + return NULL; + } + + tree_link_node(cookies_tree, parent, node, false); + return node; +} + + +/** + * Called when scheduled event gets fired. Actually performs the update. + */ +static void cookies_schedule_callback(void *scheduled_data) +{ + const struct cookie_data *data = scheduled_data; + struct node *node = NULL; + struct node *cookie_node = NULL; + char *domain_cp; + + assert(data != NULL); + + node = cookies_find(cookies_tree_root, data->domain); + + if (node == NULL) { + domain_cp = strdup(data->domain); + if (domain_cp == NULL) { + LOG(("malloc failed")); + warn_user("NoMemory", 0); + return; + } + node = tree_create_folder_node(cookies_tree, + cookies_tree_root, domain_cp, + false, false, false); + if (node != NULL) { + tree_set_node_user_callback(node, cookies_node_callback, + NULL); + tree_set_node_icon(cookies_tree, node, folder_icon); + } + } + + if (node == NULL) + return; + + cookie_node = cookies_find(node, data->name); + if (cookie_node == NULL) + cookies_create_cookie_node(node, data); + else + cookies_update_cookie_node(cookie_node, data); + + return; +} + +/** + * Initialises cookies tree. + * + * \param data user data for the callbacks + * \param start_redraw callback function called before every redraw + * \param end_redraw callback function called after every redraw + * \return true on success, false on memory exhaustion + */ +bool cookies_initialise(struct tree *tree) +{ + + if (tree == NULL) + return false; + + folder_icon = tree_load_icon(tree_directory_icon_name); + cookie_icon = tree_load_icon(tree_content_icon_name); + + /* Create an empty tree */ + cookies_tree = tree; + cookies_tree_root = tree_get_root(cookies_tree); + + user_delete = false; + urldb_iterate_cookies(cookies_schedule_update); + tree_set_node_expanded(cookies_tree, cookies_tree_root, + true, true, true); + + return true; +} + + +/** + * Get flags with which the cookies tree should be created; + * + * \return the flags + */ +unsigned int cookies_get_tree_flags(void) +{ + return TREE_DELETE_EMPTY_DIRS; +} + + +/* exported interface documented in cookies.h */ +bool cookies_schedule_update(const struct cookie_data *data) +{ + assert(data != NULL); + assert(user_delete == false); + + schedule(100, cookies_schedule_callback, (void *)data); + + return true; +} + + +/* exported interface documented in cookies.h */ +void cookies_remove(const struct cookie_data *data) +{ + assert(data != NULL); + + schedule_remove(cookies_schedule_callback, (void *)data); +} + + +/** + * Free memory and release all other resources. + */ +void cookies_cleanup(void) +{ +} + +/* Actions to be connected to front end specific toolbars */ + +/** + * Delete nodes which are currently selected. + */ +void cookies_delete_selected(void) +{ + user_delete = true; + tree_delete_selected_nodes(cookies_tree, cookies_tree_root); + user_delete = false; +} + +/** + * Delete all nodes. + */ +void cookies_delete_all(void) +{ + bool needs_redraw = tree_get_redraw(cookies_tree); + if (needs_redraw) + tree_set_redraw(cookies_tree, false); + + user_delete = true; + tree_set_node_selected(cookies_tree, cookies_tree_root, true, true); + tree_delete_selected_nodes(cookies_tree, cookies_tree_root); + user_delete = false; + + if (needs_redraw) + tree_set_redraw(cookies_tree, true); +} + +/** + * Select all nodes in the tree. + */ +void cookies_select_all(void) +{ + tree_set_node_selected(cookies_tree, cookies_tree_root, true, true); +} + +/** + * Unselect all nodes. + */ +void cookies_clear_selection(void) +{ + tree_set_node_selected(cookies_tree, cookies_tree_root, true, false); +} + +/** + * Expand both domain and cookie nodes. + */ +void cookies_expand_all(void) +{ + tree_set_node_expanded(cookies_tree, cookies_tree_root, + true, true, true); +} + +/** + * Expand domain nodes only. + */ +void cookies_expand_domains(void) +{ + tree_set_node_expanded(cookies_tree, cookies_tree_root, + true, true, false); +} + +/** + * Expand cookie nodes only. + */ +void cookies_expand_cookies(void) +{ + tree_set_node_expanded(cookies_tree, cookies_tree_root, + true, false, true); +} + +/** + * Collapse both domain and cookie nodes. + */ +void cookies_collapse_all(void) +{ + tree_set_node_expanded(cookies_tree, cookies_tree_root, + false, true, true); +} + +/** + * Collapse domain nodes only. + */ +void cookies_collapse_domains(void) +{ + tree_set_node_expanded(cookies_tree, cookies_tree_root, + false, true, false); +} + +/** + * Collapse cookie nodes only. + */ +void cookies_collapse_cookies(void) +{ + tree_set_node_expanded(cookies_tree, cookies_tree_root, + false, false, true); +} -- cgit v1.2.3