/* * This file is part of NetSurf, http://netsurf.sourceforge.net/ * Licensed under the GNU General Public License, * http://www.opensource.org/licenses/gpl-license * Copyright 2003 Phil Mellor * Copyright 2003 John M Bell * Copyright 2004 James Bursa * Copyright 2005 Richard Wilson */ /** \file * Option reading and saving (implementation). * * Options are stored in the format key:value, one per line. For bool options, * value is "0" or "1". */ #include #include #include #include #include "libxml/HTMLparser.h" #include "libxml/HTMLtree.h" #include "netsurf/css/css.h" #include "netsurf/desktop/options.h" #include "netsurf/desktop/tree.h" #include "netsurf/utils/log.h" #include "netsurf/utils/messages.h" #include "netsurf/utils/utils.h" #ifdef riscos #include "netsurf/riscos/options.h" #else #define EXTRA_OPTION_DEFINE #define EXTRA_OPTION_TABLE #endif /** An HTTP proxy should be used. */ bool option_http_proxy = false; /** Hostname of proxy. */ char *option_http_proxy_host = 0; /** Proxy port. */ int option_http_proxy_port = 8080; /** Proxy authentication method. */ int option_http_proxy_auth = OPTION_HTTP_PROXY_AUTH_NONE; /** Proxy authentication user name */ char *option_http_proxy_auth_user = 0; /** Proxy authentication password */ char *option_http_proxy_auth_pass = 0; /** Default font size / 0.1pt. */ int option_font_size = 100; /** Minimum font size. */ int option_font_min_size = 70; /** Accept-Language header. */ char *option_accept_language = 0; /** Preferred maximum size of memory cache / bytes. */ int option_memory_cache_size = 2 * 1024 * 1024; /** Preferred expiry age of disc cache / days. */ int option_disc_cache_age = 28; /** Whether to block advertisements */ bool option_block_ads = false; /** Minimum GIF animation delay */ int option_minimum_gif_delay = 10; /** Whether to send the referer HTTP header */ bool option_send_referer = true; /** Whether to animate images */ bool option_animate_images = true; /** How many days to retain URL data for */ int option_expire_url = 28; /** Default font family */ int option_font_default = CSS_FONT_FAMILY_SANS_SERIF; /** ca-bundle location */ char *option_ca_bundle = 0; /** Cookie file location */ char *option_cookie_file = 0; /** Cookie jar loaction */ char *option_cookie_jar = 0; EXTRA_OPTION_DEFINE struct { const char *key; enum { OPTION_BOOL, OPTION_INTEGER, OPTION_STRING } type; void *p; } option_table[] = { { "http_proxy", OPTION_BOOL, &option_http_proxy }, { "http_proxy_host", OPTION_STRING, &option_http_proxy_host }, { "http_proxy_port", OPTION_INTEGER, &option_http_proxy_port }, { "http_proxy_auth", OPTION_BOOL, &option_http_proxy_auth }, { "http_proxy_auth_user", OPTION_STRING, &option_http_proxy_auth_user }, { "http_proxy_auth_pass", OPTION_STRING, &option_http_proxy_auth_pass }, { "font_size", OPTION_INTEGER, &option_font_size }, { "font_min_size", OPTION_INTEGER, &option_font_min_size }, { "accept_language", OPTION_STRING, &option_accept_language }, { "memory_cache_size", OPTION_INTEGER, &option_memory_cache_size }, { "disc_cache_age", OPTION_INTEGER, &option_disc_cache_age }, { "block_advertisements", OPTION_BOOL, &option_block_ads }, { "minimum_gif_delay", OPTION_INTEGER, &option_minimum_gif_delay }, { "send_referer", OPTION_BOOL, &option_send_referer }, { "animate_images", OPTION_BOOL, &option_animate_images }, { "expire_url", OPTION_INTEGER, &option_expire_url }, { "font_default", OPTION_INTEGER, &option_font_default }, { "ca_bundle", OPTION_STRING, &option_ca_bundle }, { "cookie_file", OPTION_STRING, &option_cookie_file }, { "cookie_jar", OPTION_STRING, &option_cookie_jar }, EXTRA_OPTION_TABLE }; #define option_table_entries (sizeof option_table / sizeof option_table[0]) static void options_load_tree_directory(xmlNode *ul, struct node *directory); static void options_load_tree_entry(xmlNode *li, struct node *directory); xmlNode *options_find_tree_element(xmlNode *node, const char *name); bool options_save_tree_directory(struct node *directory, xmlNode *node); bool options_save_tree_entry(struct node *entry, xmlNode *node); /** * Read options from a file. * * \param path name of file to read options from * * Option variables corresponding to lines in the file are updated. Missing * options are unchanged. If the file fails to open, options are unchanged. */ void options_read(const char *path) { char s[100]; FILE *fp; fp = fopen(path, "r"); if (!fp) { LOG(("failed to open file '%s'", path)); return; } while (fgets(s, 100, fp)) { char *colon, *value; unsigned int i; if (s[0] == 0 || s[0] == '#') continue; colon = strchr(s, ':'); if (colon == 0) continue; s[strlen(s) - 1] = 0; /* remove \n at end */ *colon = 0; /* terminate key */ value = colon + 1; for (i = 0; i != option_table_entries; i++) { if (strcasecmp(s, option_table[i].key) != 0) continue; switch (option_table[i].type) { case OPTION_BOOL: *((bool *) option_table[i].p) = value[0] == '1'; break; case OPTION_INTEGER: *((int *) option_table[i].p) = atoi(value); break; case OPTION_STRING: free(*((char **) option_table[i].p)); *((char **) option_table[i].p) = strdup(value); break; } break; } } fclose(fp); if (option_font_size < 50) option_font_size = 50; if (1000 < option_font_size) option_font_size = 1000; if (option_font_min_size < 10) option_font_min_size = 10; if (500 < option_font_min_size) option_font_min_size = 500; if (option_memory_cache_size < 0) option_memory_cache_size = 0; } /** * Save options to a file. * * \param path name of file to write options to * * Errors are ignored. */ void options_write(const char *path) { unsigned int i; FILE *fp; fp = fopen(path, "w"); if (!fp) { LOG(("failed to open file '%s' for writing", path)); return; } for (i = 0; i != option_table_entries; i++) { fprintf(fp, "%s:", option_table[i].key); switch (option_table[i].type) { case OPTION_BOOL: fprintf(fp, "%c", *((bool *) option_table[i].p) ? '1' : '0'); break; case OPTION_INTEGER: fprintf(fp, "%i", *((int *) option_table[i].p)); break; case OPTION_STRING: if (*((char **) option_table[i].p)) fprintf(fp, "%s", *((char **) option_table[i].p)); break; } fprintf(fp, "\n"); } fclose(fp); } /** * Dump user options to stderr */ void options_dump(void) { unsigned int i; for (i = 0; i != option_table_entries; i++) { fprintf(stderr, "%s:", option_table[i].key); switch (option_table[i].type) { case OPTION_BOOL: fprintf(stderr, "%c", *((bool *) option_table[i].p) ? '1' : '0'); break; case OPTION_INTEGER: fprintf(stderr, "%i", *((int *) option_table[i].p)); break; case OPTION_STRING: if (*((char **) option_table[i].p)) fprintf(stderr, "%s", *((char **) option_table[i].p)); break; } fprintf(stderr, "\n"); } } /** * Loads a hotlist as a tree from a specified file. * * \param filename name of file to read * \return the hotlist file represented as a tree, or NULL on failure */ struct tree *options_load_tree(const char *filename) { xmlDoc *doc; xmlNode *html, *body, *ul; struct tree *tree; doc = htmlParseFile(filename, "iso-8859-1"); if (!doc) { warn_user("HotlistLoadError", messages_get("ParsingFail")); return NULL; } html = options_find_tree_element((xmlNode *) doc, "html"); body = options_find_tree_element(html, "body"); ul = options_find_tree_element(body, "ul"); if (!ul) { xmlFreeDoc(doc); warn_user("HotlistLoadError", "(......