Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2006 Richard Wilson <info@tinct.net>
  3.  * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
  4.  *
  5.  * This file is part of NetSurf, http://www.netsurf-browser.org/
  6.  *
  7.  * NetSurf is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; version 2 of the License.
  10.  *
  11.  * NetSurf is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  */
  19.  
  20. /** \file
  21.  * Cookies (implementation).
  22.  */
  23.  
  24. #include <assert.h>
  25. #include <stdbool.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <time.h>
  30. #include "content/content.h"
  31. #include "content/hlcache.h"
  32. #include "content/urldb.h"
  33. #include "desktop/cookies.h"
  34. #include "desktop/options.h"
  35. #include "desktop/tree.h"
  36. #include "utils/log.h"
  37. #include "utils/messages.h"
  38. #include "utils/schedule.h"
  39. #include "utils/url.h"
  40. #include "utils/utils.h"
  41.  
  42. /** Flags for each type of cookie tree node. */
  43. enum tree_element_cookie {
  44.         TREE_ELEMENT_PERSISTENT = 0x01,
  45.         TREE_ELEMENT_VERSION = 0x02,
  46.         TREE_ELEMENT_SECURE = 0x03,
  47.         TREE_ELEMENT_LAST_USED = 0x04,
  48.         TREE_ELEMENT_EXPIRES = 0x05,
  49.         TREE_ELEMENT_PATH = 0x06,
  50.         TREE_ELEMENT_DOMAIN = 0x07,
  51.         TREE_ELEMENT_COMMENT = 0x08,
  52.         TREE_ELEMENT_VALUE = 0x09,
  53. };
  54.  
  55. static struct tree *cookies_tree;
  56. static struct node *cookies_tree_root;
  57. static bool user_delete;
  58. static hlcache_handle *folder_icon;
  59. static hlcache_handle *cookie_icon;
  60.  
  61.  
  62. /**
  63.  * Find an entry in the cookie tree
  64.  *
  65.  * \param node the node to check the children of
  66.  * \param title The title to find
  67.  * \return Pointer to node, or NULL if not found
  68.  */
  69. static struct node *cookies_find(struct node *node, const char *title)
  70. {
  71.         struct node *search;
  72.         struct node_element *element;
  73.  
  74.         assert(node !=NULL);
  75.  
  76.         for (search = tree_node_get_child(node); search;
  77.              search = tree_node_get_next(search)) {
  78.                 element = tree_node_find_element(search, TREE_ELEMENT_TITLE,
  79.                                                  NULL);
  80.                 if (strcmp(title, tree_node_element_get_text(element)) == 0)
  81.                         return search;
  82.         }
  83.         return NULL;
  84. }
  85.  
  86. /**
  87.  * Callback for all cookie tree nodes.
  88.  */
  89. static node_callback_resp cookies_node_callback(void *user_data, struct node_msg_data *msg_data)
  90. {
  91.         struct node *node = msg_data->node;
  92.         struct node_element *domain, *path;
  93.         const char *domain_t, *path_t, *name_t;
  94.         char *space;
  95.         bool is_folder = tree_node_is_folder(node);
  96.  
  97.         /* we don't remove any icons here */
  98.         if (msg_data->msg == NODE_DELETE_ELEMENT_IMG)
  99.                 return NODE_CALLBACK_HANDLED;
  100.  
  101.         /* let the tree handle events other than text data removal */
  102.         if (msg_data->msg != NODE_DELETE_ELEMENT_TXT)
  103.                 return NODE_CALLBACK_NOT_HANDLED;
  104.  
  105.         /* check if it's a domain folder */
  106.         if (is_folder)
  107.                 return NODE_CALLBACK_NOT_HANDLED;
  108.  
  109.         switch (msg_data->flag) {
  110.         case TREE_ELEMENT_TITLE:
  111.                 if (!user_delete)
  112.                         break;
  113.                 /* get the rest of the cookie data */
  114.                 domain = tree_node_find_element(node,
  115.                                                 TREE_ELEMENT_DOMAIN, NULL);
  116.                 path = tree_node_find_element(node, TREE_ELEMENT_PATH,
  117.                                               NULL);
  118.  
  119.                 if ((domain != NULL) &&
  120.                     (path != NULL)) {
  121.                         domain_t = tree_node_element_get_text(domain) +
  122.                                 strlen(messages_get(
  123.                                                "TreeDomain")) - 4;
  124.                         space = strchr(domain_t, ' ');
  125.                         if (space != NULL)
  126.                                 *space = '\0';
  127.                         path_t = tree_node_element_get_text(path) +
  128.                                 strlen(messages_get("TreePath"))
  129.                                 - 4;
  130.                         space = strchr(path_t, ' ');
  131.                         if (space != NULL)
  132.                                 *space = '\0';
  133.                         name_t = msg_data->data.text;
  134.                         urldb_delete_cookie(domain_t, path_t, name_t);
  135.                 }
  136.                 break;
  137.         default:
  138.                 break;
  139.         }
  140.  
  141.         free(msg_data->data.text);
  142.  
  143.         return NODE_CALLBACK_HANDLED;
  144. }
  145.  
  146.  
  147. /**
  148.  * Updates a tree entry for a cookie.
  149.  *
  150.  * All information is copied from the cookie_data, and as such can
  151.  * be edited and should be freed.
  152.  *
  153.  * \param node The node to update
  154.  * \param data The cookie data to use
  155.  * \return true if node updated, or false for failure
  156.  */
  157. static bool cookies_update_cookie_node(struct node *node,
  158.                                        const struct cookie_data *data)
  159. {
  160.         struct node_element *element;
  161.         char buffer[32];
  162.  
  163.         assert(data != NULL);
  164.  
  165.         /* update the value text */
  166.         element = tree_node_find_element(node, TREE_ELEMENT_VALUE, NULL);
  167.         tree_update_element_text(cookies_tree,
  168.                                  element,
  169.                             messages_get_buff("TreeValue",
  170.                                               data->value != NULL ?
  171.                                               data->value :
  172.                                               messages_get("TreeUnused")));
  173.  
  174.  
  175.         /* update the comment text */
  176.         if ((data->comment != NULL) &&
  177.             (strcmp(data->comment, "") != 0)) {
  178.                 element = tree_node_find_element(node, TREE_ELEMENT_COMMENT, NULL);
  179.                 tree_update_element_text(cookies_tree,
  180.                                          element,
  181.                                     messages_get_buff("TreeComment",
  182.                                                       data->comment));
  183.         }
  184.  
  185.         /* update domain text */
  186.         element = tree_node_find_element(node, TREE_ELEMENT_DOMAIN, element);
  187.         tree_update_element_text(cookies_tree,
  188.                                  element,
  189.                             messages_get_buff("TreeDomain",
  190.                                               data->domain,
  191.                                               data->domain_from_set ?
  192.                                               messages_get("TreeHeaders") :
  193.                                               ""));
  194.  
  195.         /* update path text */
  196.         element = tree_node_find_element(node, TREE_ELEMENT_PATH, element);
  197.         tree_update_element_text(cookies_tree,
  198.                                  element,
  199.                             messages_get_buff("TreePath", data->path,
  200.                                               data->path_from_set ?
  201.                                               messages_get("TreeHeaders") :
  202.                                               ""));
  203.  
  204.         /* update expiry text */
  205.         element = tree_node_find_element(node, TREE_ELEMENT_EXPIRES, element);
  206.         tree_update_element_text(cookies_tree,
  207.                                  element,
  208.                             messages_get_buff("TreeExpires",
  209.                                               (data->expires > 0)
  210.                                               ? (data->expires == 1)
  211.                                               ? messages_get("TreeSession")
  212.                                               : ctime(&data->expires)
  213.                                               : messages_get("TreeUnknown")));
  214.  
  215.         /* update last used text */
  216.         element = tree_node_find_element(node, TREE_ELEMENT_LAST_USED, element);
  217.         tree_update_element_text(cookies_tree,
  218.                                  element,
  219.                             messages_get_buff("TreeLastUsed",
  220.                                               (data->last_used > 0) ?
  221.                                               ctime(&data->last_used) :
  222.                                               messages_get("TreeUnknown")));
  223.  
  224.         /* update secure text */
  225.         element = tree_node_find_element(node, TREE_ELEMENT_SECURE, element);
  226.         tree_update_element_text(cookies_tree,
  227.                                  element,
  228.                             messages_get_buff("TreeSecure",
  229.                                               data->secure ?
  230.                                               messages_get("Yes") :
  231.                                               messages_get("No")));
  232.  
  233.         /* update version text */
  234.         element = tree_node_find_element(node, TREE_ELEMENT_VERSION, element);
  235.         snprintf(buffer, sizeof(buffer), "TreeVersion%i", data->version);
  236.         tree_update_element_text(cookies_tree,
  237.                                  element,
  238.                             messages_get_buff("TreeVersion",
  239.                                               messages_get(buffer)));
  240.  
  241.         /* update persistant text */
  242.         element = tree_node_find_element(node, TREE_ELEMENT_PERSISTENT, element);
  243.         tree_update_element_text(cookies_tree,
  244.                                  element,
  245.                             messages_get_buff("TreePersistent",
  246.                                               data->no_destroy ?
  247.                                               messages_get("Yes") :
  248.                                               messages_get("No")));
  249.  
  250.         return true;
  251. }
  252.  
  253. /**
  254.  * Creates an empty tree entry for a cookie, and links it into the tree.
  255.  *
  256.  * All information is copied from the cookie_data, and as such can
  257.  * be edited and should be freed.
  258.  *
  259.  * \param parent      the node to link to
  260.  * \param data        the cookie data to use
  261.  * \return the node created, or NULL for failure
  262.  */
  263. static struct node *cookies_create_cookie_node(struct node *parent,
  264.                                                const struct cookie_data *data)
  265. {
  266.         struct node *node;
  267.         char *name;
  268.  
  269.         name = strdup(data->name);
  270.         if (name == NULL) {
  271.                 LOG(("malloc failed"));
  272.                 warn_user("NoMemory", 0);
  273.                 return NULL;
  274.         }
  275.  
  276.         node = tree_create_leaf_node(cookies_tree, NULL, name,
  277.                                      false, false, false);
  278.         if (node == NULL) {
  279.                 free(name);
  280.                 return NULL;
  281.         }
  282.  
  283.         tree_set_node_user_callback(node, cookies_node_callback, NULL);
  284.  
  285.         tree_create_node_element(node, NODE_ELEMENT_TEXT,
  286.                                  TREE_ELEMENT_PERSISTENT, false);
  287.  
  288.         tree_create_node_element(node, NODE_ELEMENT_TEXT,
  289.                                  TREE_ELEMENT_VERSION, false);
  290.  
  291.         tree_create_node_element(node, NODE_ELEMENT_TEXT,
  292.                                  TREE_ELEMENT_SECURE, false);
  293.  
  294.         tree_create_node_element(node, NODE_ELEMENT_TEXT,
  295.                                  TREE_ELEMENT_LAST_USED, false);
  296.  
  297.         tree_create_node_element(node, NODE_ELEMENT_TEXT,
  298.                                  TREE_ELEMENT_EXPIRES, false);
  299.  
  300.         tree_create_node_element(node, NODE_ELEMENT_TEXT,
  301.                                  TREE_ELEMENT_PATH, false);
  302.  
  303.         tree_create_node_element(node, NODE_ELEMENT_TEXT,
  304.                                  TREE_ELEMENT_DOMAIN, false);
  305.  
  306.         if ((data->comment) && (strcmp(data->comment, "")))
  307.                 tree_create_node_element(node, NODE_ELEMENT_TEXT,
  308.                                          TREE_ELEMENT_COMMENT, false);
  309.         tree_create_node_element(node, NODE_ELEMENT_TEXT,
  310.                                  TREE_ELEMENT_VALUE, false);
  311.         tree_set_node_icon(cookies_tree, node, cookie_icon);
  312.  
  313.         if (!cookies_update_cookie_node(node, data))
  314.         {
  315.                 tree_delete_node(NULL, node, false);
  316.                 return NULL;
  317.         }
  318.  
  319.         tree_link_node(cookies_tree, parent, node, false);
  320.         return node;
  321. }
  322.  
  323.  
  324. /**
  325.  * Called when scheduled event gets fired. Actually performs the update.
  326.  */
  327. static void cookies_schedule_callback(const void *scheduled_data)
  328. {
  329.         const struct cookie_data *data = scheduled_data;
  330.         struct node *node = NULL;
  331.         struct node *cookie_node = NULL;
  332.         char *domain_cp;
  333.  
  334.         assert(data != NULL);
  335.  
  336.         node = cookies_find(cookies_tree_root, data->domain);
  337.  
  338.         if (node == NULL) {
  339.                 domain_cp = strdup(data->domain);
  340.                 if (domain_cp == NULL) {
  341.                         LOG(("malloc failed"));
  342.                         warn_user("NoMemory", 0);
  343.                         return;
  344.                 }
  345.                 /* ownership of domain_cp passed to tree, if node creation
  346.                  * does not fail */
  347.                 node = tree_create_folder_node(cookies_tree,
  348.                                                cookies_tree_root, domain_cp,
  349.                                                false, false, false);
  350.                 if (node != NULL) {
  351.                         tree_set_node_user_callback(node, cookies_node_callback,
  352.                                                     NULL);
  353.                         tree_set_node_icon(cookies_tree, node, folder_icon);
  354.  
  355.                 } else {
  356.                         free(domain_cp);
  357.                 }
  358.         }
  359.  
  360.         if (node == NULL)
  361.                 return;
  362.  
  363.         cookie_node = cookies_find(node, data->name);
  364.         if (cookie_node == NULL)
  365.                 cookies_create_cookie_node(node, data);
  366.         else
  367.                 cookies_update_cookie_node(cookie_node, data);
  368.  
  369.         return;
  370. }
  371.  
  372. /**
  373.  * Initialises cookies tree.
  374.  *
  375.  * \param data          user data for the callbacks
  376.  * \param start_redraw  callback function called before every redraw
  377.  * \param end_redraw    callback function called after every redraw
  378.  * \return true on success, false on memory exhaustion
  379.  */
  380. bool cookies_initialise(struct tree *tree, const char* folder_icon_name, const char* cookie_icon_name)
  381. {
  382.  
  383.         if (tree == NULL)
  384.                 return false;
  385.  
  386.         folder_icon = tree_load_icon(folder_icon_name);
  387.         cookie_icon = tree_load_icon(cookie_icon_name);
  388.  
  389.         /* Create an empty tree */
  390.         cookies_tree = tree;
  391.         cookies_tree_root = tree_get_root(cookies_tree);
  392.  
  393.         user_delete = false;
  394.         urldb_iterate_cookies(cookies_schedule_update);
  395.         tree_set_node_expanded(cookies_tree, cookies_tree_root,
  396.                                false, true, true);
  397.  
  398.         return true;
  399. }
  400.  
  401.  
  402. /**
  403.  * Get flags with which the cookies tree should be created;
  404.  *
  405.  * \return the flags
  406.  */
  407. unsigned int cookies_get_tree_flags(void)
  408. {
  409.         return TREE_DELETE_EMPTY_DIRS;
  410. }
  411.  
  412.  
  413. /* exported interface documented in cookies.h */
  414. bool cookies_schedule_update(const struct cookie_data *data)
  415. {
  416.         assert(data != NULL);
  417.         assert(user_delete == false);
  418.  
  419.         if (cookies_tree_root != NULL)
  420.                 cookies_schedule_callback(data);
  421.  
  422.         return true;
  423. }
  424.  
  425.  
  426. /* exported interface documented in cookies.h */
  427. void cookies_remove(const struct cookie_data *data)
  428. {
  429.         assert(data != NULL);
  430.  
  431.         if (cookies_tree_root != NULL)
  432.                 cookies_schedule_callback(data);
  433. }
  434.  
  435.  
  436. /**
  437.  * Free memory and release all other resources.
  438.  */
  439. void cookies_cleanup(void)
  440. {
  441.         hlcache_handle_release(folder_icon);
  442.         hlcache_handle_release(cookie_icon);
  443. }
  444.  
  445. /* Actions to be connected to front end specific toolbars */
  446.  
  447. /**
  448.  * Delete nodes which are currently selected.
  449.  */
  450. void cookies_delete_selected(void)
  451. {
  452.         user_delete = true;
  453.         tree_delete_selected_nodes(cookies_tree, cookies_tree_root);
  454.         user_delete = false;
  455. }
  456.  
  457. /**
  458.  * Delete all nodes.
  459.  */
  460. void cookies_delete_all(void)
  461. {
  462.         bool needs_redraw = tree_get_redraw(cookies_tree);
  463.         if (needs_redraw)
  464.                 tree_set_redraw(cookies_tree, false);
  465.  
  466.         user_delete = true;
  467.         tree_set_node_selected(cookies_tree, cookies_tree_root, true, true);
  468.         tree_delete_selected_nodes(cookies_tree, cookies_tree_root);
  469.         user_delete = false;
  470.  
  471.         if (needs_redraw)
  472.                 tree_set_redraw(cookies_tree, true);
  473. }
  474.  
  475. /**
  476.  * Select all nodes in the tree.
  477.  */
  478. void cookies_select_all(void)
  479. {
  480.         tree_set_node_selected(cookies_tree, cookies_tree_root, true, true);
  481. }
  482.  
  483. /**
  484.  * Unselect all nodes.
  485.  */
  486. void cookies_clear_selection(void)
  487. {
  488.         tree_set_node_selected(cookies_tree, cookies_tree_root, true, false);
  489. }
  490.  
  491. /**
  492.  * Expand both domain and cookie nodes.
  493.  */
  494. void cookies_expand_all(void)
  495. {
  496.         tree_set_node_expanded(cookies_tree, cookies_tree_root,
  497.                                true, true, true);
  498. }
  499.  
  500. /**
  501.  * Expand domain nodes only.
  502.  */
  503. void cookies_expand_domains(void)
  504. {
  505.         tree_set_node_expanded(cookies_tree, cookies_tree_root,
  506.                                true, true, false);
  507. }
  508.  
  509. /**
  510.  * Expand cookie nodes only.
  511.  */
  512. void cookies_expand_cookies(void)
  513. {
  514.         tree_set_node_expanded(cookies_tree, cookies_tree_root,
  515.                                true, false, true);
  516. }
  517.  
  518. /**
  519.  * Collapse both domain and cookie nodes.
  520.  */
  521. void cookies_collapse_all(void)
  522. {
  523.         tree_set_node_expanded(cookies_tree, cookies_tree_root,
  524.                                false, true, true);
  525. }
  526.  
  527. /**
  528.  * Collapse domain nodes only.
  529.  */
  530. void cookies_collapse_domains(void)
  531. {
  532.         tree_set_node_expanded(cookies_tree, cookies_tree_root,
  533.                                false, true, false);
  534. }
  535.  
  536. /**
  537.  * Collapse cookie nodes only.
  538.  */
  539. void cookies_collapse_cookies(void)
  540. {
  541.         tree_set_node_expanded(cookies_tree, cookies_tree_root,
  542.                                false, false, true);
  543. }
  544.