2007-11-14 Matthew Barnes <mbarnes@redhat.com> ** Remove trailing whitespace from source code. svn path=/trunk/; revision=34537
545 lines
12 KiB
C
545 lines
12 KiB
C
/* -*- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 signed 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 = (const unsigned char *)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 ((char *)root->name, "bonobo-config") != 0) {
|
|
g_warning ("not bonobo-config xml file");
|
|
return NULL;
|
|
}
|
|
|
|
root = root->children;
|
|
while (root) {
|
|
if (!strcmp ((char *)root->name, "section")) {
|
|
val = (char *)xmlGetProp (root, (const unsigned char *)"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 ((char *)node->name, "entry")) {
|
|
val = (char *)xmlGetProp (node, (const unsigned char *)"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 = (char *)xmlGetProp (node, (const unsigned char *)"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, (unsigned char *)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, (unsigned char *)map->to, (unsigned char *)value);
|
|
} else {
|
|
xmlSetProp (root, (unsigned char *)map->to, (unsigned char *)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 ((const unsigned char *)"1.0");
|
|
root = xmlNewDocNode (doc, NULL, (unsigned char *)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, (unsigned char *)idparam, (unsigned char *)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 ((char *)node->name, "entry")) {
|
|
int found;
|
|
|
|
if ((tmp = (char *)xmlGetProp (node, (const unsigned char *)"name"))) {
|
|
found = strcmp ((char *)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 ((char *)node->name, "any") == 0)
|
|
break;
|
|
node = node->next;
|
|
}
|
|
}
|
|
|
|
/* skip to the value inside it */
|
|
if (node) {
|
|
node = node->children;
|
|
while (node) {
|
|
if (strcmp ((char *)node->name, "value") == 0)
|
|
break;
|
|
node = node->next;
|
|
}
|
|
}
|
|
|
|
if (node) {
|
|
node = node->children;
|
|
while (node) {
|
|
if (strcmp ((char *)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;
|
|
}
|