aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--e-util/ChangeLog5
-rw-r--r--e-util/Makefile.am2
-rw-r--r--e-util/e-account.c2
-rw-r--r--e-util/e-bconf-map.c544
-rw-r--r--e-util/e-bconf-map.h102
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__ */