diff options
-rw-r--r-- | e-util/ChangeLog | 5 | ||||
-rw-r--r-- | e-util/Makefile.am | 2 | ||||
-rw-r--r-- | e-util/e-account.c | 2 | ||||
-rw-r--r-- | e-util/e-bconf-map.c | 544 | ||||
-rw-r--r-- | e-util/e-bconf-map.h | 102 |
5 files changed, 654 insertions, 1 deletions
diff --git a/e-util/ChangeLog b/e-util/ChangeLog index 0ed9ae50a8..4a39532e6c 100644 --- a/e-util/ChangeLog +++ b/e-util/ChangeLog @@ -1,3 +1,8 @@ +2004-01-14 Jeffrey Stedfast <fejj@ximian.com> + + * e-bconf-map.[c,h]: New source files for mapping bonobo-conf keys + to gconf keys. Moved out of shell/e-config-upgrade.c + 2004-01-13 Not Zed <NotZed@Ximian.com> * e-msgport.c (em_cache*): A time-based thread-safe in-memory diff --git a/e-util/Makefile.am b/e-util/Makefile.am index 3f181ddd45..8587fbe504 100644 --- a/e-util/Makefile.am +++ b/e-util/Makefile.am @@ -14,6 +14,7 @@ privlib_LTLIBRARIES = libeutil.la libeconduit.la eutilinclude_HEADERS = \ e-account-list.h \ e-account.h \ + e-bconf-map.h \ e-categories-config.h \ e-categories-master-list-wombat.h \ e-component-listener.h \ @@ -49,6 +50,7 @@ libeutil_la_SOURCES = \ $(eutilinclude_HEADERS) \ e-account-list.c \ e-account.c \ + e-bconf-map.c \ e-categories-config.c \ e-categories-master-list-wombat.c \ e-component-listener.c \ diff --git a/e-util/e-account.c b/e-util/e-account.c index dbbfccb6e3..80e36bf0a1 100644 --- a/e-util/e-account.c +++ b/e-util/e-account.c @@ -304,7 +304,7 @@ e_account_set_from_xml (EAccount *account, const char *xml) if (!account->uid) xml_set_prop (node, "uid", &account->uid); - + changed |= xml_set_prop (node, "name", &account->name); changed |= xml_set_bool (node, "enabled", &account->enabled); diff --git a/e-util/e-bconf-map.c b/e-util/e-bconf-map.c new file mode 100644 index 0000000000..f4d57bbbcc --- /dev/null +++ b/e-util/e-bconf-map.c @@ -0,0 +1,544 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2004 Ximian, Inc. (www.ximian.com) + * + * This program 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; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <glib.h> + +#include <libxml/tree.h> +#include <libxml/parser.h> +#include <libxml/xmlmemory.h> + +#include "e-bconf-map.h" + + +#define d(x) + + +static char hexnib[256] = { + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, + -1,10,11,12,13,14,15,16,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,10,11,12,13,14,15,16,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +}; + +char * +e_bconf_hex_decode (const char *val) +{ + const unsigned char *p = (const unsigned char *) val; + char *o, *res; + + o = res = g_malloc (strlen (val) / 2 + 1); + for (p = val; (p[0] && p[1]); p += 2) + *o++ = (hexnib[p[0]] << 4) | hexnib[p[1]]; + *o = 0; + + return res; +} + +char * +e_bconf_url_decode (const char *val) +{ + const unsigned char *p = (const unsigned char *) val; + char *o, *res, c; + + o = res = g_malloc (strlen (val) + 1); + while (*p) { + c = *p++; + if (c == '%' + && hexnib[p[0]] != -1 && hexnib[p[1]] != -1) { + *o++ = (hexnib[p[0]] << 4) | hexnib[p[1]]; + p+=2; + } else + *o++ = c; + } + *o = 0; + + return res; +} + + +xmlNodePtr +e_bconf_get_path (xmlDocPtr doc, const char *path) +{ + xmlNodePtr root; + char *val; + int found; + + root = doc->children; + if (strcmp (root->name, "bonobo-config") != 0) { + g_warning ("not bonobo-config xml file"); + return NULL; + } + + root = root->children; + while (root) { + if (!strcmp (root->name, "section")) { + val = xmlGetProp (root, "path"); + found = val && strcmp (val, path) == 0; + xmlFree (val); + if (found) + break; + } + root = root->next; + } + + return root; +} + +xmlNodePtr +e_bconf_get_entry (xmlNodePtr root, const char *name) +{ + xmlNodePtr node = root->children; + int found; + char *val; + + while (node) { + if (!strcmp (node->name, "entry")) { + val = xmlGetProp (node, "name"); + found = val && strcmp (val, name) == 0; + xmlFree (val); + if (found) + break; + } + node = node->next; + } + + return node; +} + +char * +e_bconf_get_value (xmlNodePtr root, const char *name) +{ + xmlNodePtr node = e_bconf_get_entry (root, name); + char *prop, *val = NULL; + + if (node && (prop = xmlGetProp (node, "value"))) { + val = g_strdup (prop); + xmlFree (prop); + } + + return val; +} + +char * +e_bconf_get_bool (xmlNodePtr root, const char *name) +{ + char *val, *res; + + if ((val = e_bconf_get_value (root, name))) { + res = g_strdup (val[0] == '1' ? "true" : "false"); + g_free (val); + } else + res = NULL; + + return res; +} + +char * +e_bconf_get_long (xmlNodePtr root, const char *name) +{ + char *val, *res; + + if ((val = e_bconf_get_value (root, name))) { + res = g_strdup (val); + g_free (val); + } else + res = NULL; + + return res; +} + +char * +e_bconf_get_string (xmlNodePtr root, const char *name) +{ + char *val, *res; + + if ((val = e_bconf_get_value (root, name))) { + res = e_bconf_hex_decode (val); + g_free (val); + } else + res = NULL; + + return res; +} + + +/* lookup functions */ +typedef char * (* bconf_lookup_func) (xmlNodePtr root, const char *name, e_bconf_map_t *nap); + +static char * +bconf_lookup_bool (xmlNodePtr root, const char *name, e_bconf_map_t *map) +{ + return e_bconf_get_bool (root, name); +} + +static char * +bconf_lookup_long (xmlNodePtr root, const char *name, e_bconf_map_t *map) +{ + return e_bconf_get_long (root, name); +} + +static char * +bconf_lookup_string (xmlNodePtr root, const char *name, e_bconf_map_t *map) +{ + return e_bconf_get_string (root, name); +} + +static char * +bconf_lookup_enum (xmlNodePtr root, const char *name, e_bconf_map_t *map) +{ + int index = 0, i; + char *val; + + if ((val = e_bconf_get_value (root, name))) { + index = atoi (val); + g_free (val); + } + + for (i = 0; map->child[i].from; i++) { + if (i == index) + return g_strdup (map->child[i].from); + } + + return NULL; +} + + +static bconf_lookup_func lookup_table[] = { + bconf_lookup_bool, bconf_lookup_long, bconf_lookup_string, bconf_lookup_enum +}; + +static char * +get_name (const char *in, int index) +{ + GString *out = g_string_new (""); + char c, *res; + + while ((c = *in++)) { + if (c == '%') { + c = *in++; + switch (c) { + case '%': + g_string_append_c (out, '%'); + break; + case 'i': + g_string_append_printf (out, "%d", index); + break; + } + } else { + g_string_append_c (out, c); + } + } + + res = out->str; + g_string_free (out, FALSE); + + return res; +} + +static void +build_xml (xmlNodePtr root, e_bconf_map_t *map, int index, xmlNodePtr source) +{ + char *name, *value; + xmlNodePtr node; + + while (map->type != E_BCONF_MAP_END) { + if ((map->type & E_BCONF_MAP_MASK) == E_BCONF_MAP_CHILD) { + node = xmlNewChild (root, NULL, map->to, NULL); + build_xml (node, map->child, index, source); + } else { + name = get_name (map->from, index); + value = lookup_table[(map->type & E_BCONF_MAP_MASK) - 1] (source, name, map); + + d(printf ("key '%s=%s' -> ", name, value)); + + if (map->type & E_BCONF_MAP_CONTENT) { + if (value && value[0]) + xmlNewTextChild (root, NULL, map->to, value); + } else { + xmlSetProp (root, map->to, value); + } + + g_free (value); + g_free (name); + } + map++; + } +} + + +int +e_bconf_import_xml_blob (GConfClient *gconf, xmlDocPtr config_xmldb, e_bconf_map_t *map, + const char *bconf_path, const char *gconf_path, + const char *name, const char *idparam) +{ + xmlNodePtr source; + int count = 0, i; + GSList *list, *l; + char *val; + + source = e_bconf_get_path (config_xmldb, bconf_path); + if (source) { + list = NULL; + if ((val = e_bconf_get_value (source, "num"))) { + count = atoi (val); + g_free (val); + } + + d(printf("Found %d blobs at %s\n", count, bconf_path)); + + for (i = 0; i < count; i++) { + xmlDocPtr doc; + xmlNodePtr root; + xmlChar *xmlbuf; + int n; + + doc = xmlNewDoc ("1.0"); + root = xmlNewDocNode (doc, NULL, name, NULL); + xmlDocSetRootElement (doc, root); + + /* This could be set with a MAP_UID type ... */ + if (idparam) { + char buf[16]; + + sprintf (buf, "%d", i); + xmlSetProp (root, idparam, buf); + } + + build_xml (root, map, i, source); + + xmlDocDumpMemory (doc, &xmlbuf, &n); + xmlFreeDoc (doc); + + list = g_slist_append (list, xmlbuf); + } + + gconf_client_set_list (gconf, gconf_path, GCONF_VALUE_STRING, list, NULL); + + while (list) { + l = list->next; + xmlFree (list->data); + g_slist_free_1 (list); + list = l; + } + } else { + g_warning ("could not find '%s' in old config database, skipping", bconf_path); + } + + return 0; +} + + +static int gconf_type[] = { GCONF_VALUE_BOOL, GCONF_VALUE_BOOL, GCONF_VALUE_INT, GCONF_VALUE_STRING, GCONF_VALUE_STRING }; + +int +e_bconf_import (GConfClient *gconf, xmlDocPtr config_xmldb, e_gconf_map_list_t *remap_list) +{ + char *path, *val, *tmp; + e_gconf_map_t *map; + xmlNodePtr source; + GSList *list, *l; + char buf[32]; + int i, j, k; + + /* process all flat config */ + for (i = 0; remap_list[i].root; i++) { + d(printf ("Path: %s\n", remap_list[i].root)); + if (!(source = e_bconf_get_path (config_xmldb, remap_list[i].root))) + continue; + + map = remap_list[i].map; + for (j = 0; map[j].from; j++) { + if (map[j].type & E_GCONF_MAP_LIST) { + /* collapse a multi-entry indexed field into a list */ + list = NULL; + k = 0; + do { + path = get_name (map[j].from, k); + val = e_bconf_get_value (source, path); + d(printf ("finding path '%s' = '%s'\n", path, val)); + g_free (path); + if (val) { + switch (map[j].type & E_GCONF_MAP_MASK) { + case E_GCONF_MAP_BOOL: + case E_GCONF_MAP_INT: + list = g_slist_append (list, GINT_TO_POINTER (atoi (val))); + break; + case E_GCONF_MAP_STRING: + d(printf (" -> '%s'\n", e_bconf_hex_decode (val))); + list = g_slist_append (list, e_bconf_hex_decode (val)); + break; + } + + g_free (val); + k++; + } + } while (val); + + if (list) { + path = g_strdup_printf ("/apps/evolution/%s", map[j].to); + gconf_client_set_list (gconf, path, gconf_type[map[j].type & E_GCONF_MAP_MASK], list, NULL); + g_free (path); + if ((map[j].type & E_GCONF_MAP_MASK) == E_GCONF_MAP_STRING) + g_slist_foreach (list, (GFunc) g_free, NULL); + g_slist_free (list); + } + + continue; + } else if (map[j].type == E_GCONF_MAP_ANYLIST) { + val = NULL; + } else { + if (!(val = e_bconf_get_value (source, map[j].from))) + continue; + } + + d(printf (" %s = '%s' -> %s [%d]\n", + map[j].from, + val == NULL ? "(null)" : val, + map[j].to, + map[j].type)); + + path = g_strdup_printf ("/apps/evolution/%s", map[j].to); + switch (map[j].type) { + case E_GCONF_MAP_BOOL: + gconf_client_set_bool (gconf, path, atoi (val), NULL); + break; + case E_GCONF_MAP_BOOLNOT: + gconf_client_set_bool (gconf, path, !atoi (val), NULL); + break; + case E_GCONF_MAP_INT: + gconf_client_set_int (gconf, path, atoi (val), NULL); + break; + case E_GCONF_MAP_STRING: + tmp = e_bconf_hex_decode (val); + gconf_client_set_string (gconf, path, tmp, NULL); + g_free (tmp); + break; + case E_GCONF_MAP_SIMPLESTRING: + gconf_client_set_string (gconf, path, val, NULL); + break; + case E_GCONF_MAP_FLOAT: + gconf_client_set_float (gconf, path, strtod (val, NULL), NULL); + break; + case E_GCONF_MAP_STRLIST: { + char *v = e_bconf_hex_decode (val); + char **t = g_strsplit (v, " !<-->! ", 8196); + + list = NULL; + for (k = 0; t[k]; k++) { + list = g_slist_append (list, t[k]); + d(printf (" [%d] = '%s'\n", k, t[k])); + } + + gconf_client_set_list (gconf, path, GCONF_VALUE_STRING, list, NULL); + g_slist_free (list); + g_strfreev (t); + g_free (v); + break; } + case E_GCONF_MAP_ANYLIST: { + xmlNodePtr node = source->children; + list = NULL; + + /* find the entry node */ + while (node) { + if (!strcmp (node->name, "entry")) { + int found; + + if ((tmp = xmlGetProp (node, "name"))) { + found = strcmp (tmp, map[j].from) == 0; + xmlFree (tmp); + if (found) + break; + } + } + + node = node->next; + } + + /* find the the any block */ + if (node) { + node = node->children; + while (node) { + if (strcmp (node->name, "any") == 0) + break; + node = node->next; + } + } + + /* skip to the value inside it */ + if (node) { + node = node->children; + while (node) { + if (strcmp (node->name, "value") == 0) + break; + node = node->next; + } + } + + if (node) { + node = node->children; + while (node) { + if (strcmp (node->name, "value") == 0) + list = g_slist_append (list, xmlNodeGetContent (node)); + node = node->next; + } + } + + /* & store */ + if (list) { + gconf_client_set_list (gconf, path, GCONF_VALUE_STRING, list, NULL); + while (list) { + l = list->next; + xmlFree (list->data); + g_slist_free_1 (list); + list = l; + } + } + + break; } + case E_GCONF_MAP_COLOUR: + sprintf (buf, "#%06x", atoi (val) & 0xffffff); + gconf_client_set_string (gconf, path, buf, NULL); + break; + } + + /* FIXME: handle errors */ + g_free (path); + g_free (val); + } + } + + return 0; +} diff --git a/e-util/e-bconf-map.h b/e-util/e-bconf-map.h new file mode 100644 index 0000000000..8db5771401 --- /dev/null +++ b/e-util/e-bconf-map.h @@ -0,0 +1,102 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2004 Ximian, Inc. (www.ximian.com) + * + * This program 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; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef __E_BCONF_MAP_H__ +#define __E_BCONF_MAP_H__ + +#include <gconf/gconf-client.h> + +#include <libxml/tree.h> + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +enum { + E_BCONF_MAP_END = 0, /* end of table */ + E_BCONF_MAP_BOOL, /* bool -> prop of name 'to' value true or false */ + E_BCONF_MAP_LONG, /* long -> prop of name 'to' value a long */ + E_BCONF_MAP_STRING, /* string -> prop of name 'to' */ + E_BCONF_MAP_ENUM, /* long/bool -> prop of name 'to', with the value indexed into the child map table's from field */ + E_BCONF_MAP_CHILD, /* a new child of name 'to' */ + E_BCONF_MAP_MASK = 0x3f, + E_BCONF_MAP_CONTENT = 0x80, /* if set, create a new node of name 'to' instead of a property */ +}; + +typedef struct _e_bconf_map { + char *from; + char *to; + int type; + struct _e_bconf_map *child; +} e_bconf_map_t; + + +char *e_bconf_hex_decode (const char *val); +char *e_bconf_url_decode (const char *val); + +xmlNodePtr e_bconf_get_path (xmlDocPtr doc, const char *path); +xmlNodePtr e_bconf_get_entry (xmlNodePtr root, const char *name); + +char *e_bconf_get_value (xmlNodePtr root, const char *name); +char *e_bconf_get_bool (xmlNodePtr root, const char *name); +char *e_bconf_get_long (xmlNodePtr root, const char *name); +char *e_bconf_get_string (xmlNodePtr root, const char *name); + +int e_bconf_import_xml_blob (GConfClient *gconf, xmlDocPtr config_xmldb, e_bconf_map_t *map, + const char *bconf_path, const char *gconf_path, + const char *name, const char *idparam); + + +enum { + E_GCONF_MAP_BOOL, + E_GCONF_MAP_BOOLNOT, + E_GCONF_MAP_INT, + E_GCONF_MAP_STRING, + E_GCONF_MAP_SIMPLESTRING, /* a non-encoded string */ + E_GCONF_MAP_COLOUR, + E_GCONF_MAP_FLOAT, /* bloody floats, who uses floats ... idiots */ + E_GCONF_MAP_STRLIST, /* strings separated to !<-->! -> gconf list */ + E_GCONF_MAP_ANYLIST, /* corba sequence corba string -> gconf list */ + E_GCONF_MAP_MASK = 0x7f, + E_GCONF_MAP_LIST = 0x80 /* from includes a %i field for the index of the key, to be converted to a list of type MAP_* */ +}; + +typedef struct { + char *from; + char *to; + int type; +} e_gconf_map_t; + +typedef struct { + char *root; + e_gconf_map_t *map; +} e_gconf_map_list_t; + +int e_bconf_import (GConfClient *gconf, xmlDocPtr config_xmldb, e_gconf_map_list_t *remap_list); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __E_BCONF_MAP_H__ */ |