diff options
author | JP Rosevear <jpr@ximian.com> | 2004-01-15 23:56:11 +0800 |
---|---|---|
committer | JP Rosevear <jpr@src.gnome.org> | 2004-01-15 23:56:11 +0800 |
commit | babacb9101cf739612cb8079f3dd936a53c5d63e (patch) | |
tree | b80b00b503dbcd6bd14304d76bc351d5e083942f | |
parent | fbd28cca81f1f67342d94d956003ac09aa7f5b25 (diff) | |
download | gsoc2013-evolution-babacb9101cf739612cb8079f3dd936a53c5d63e.tar.gz gsoc2013-evolution-babacb9101cf739612cb8079f3dd936a53c5d63e.tar.zst gsoc2013-evolution-babacb9101cf739612cb8079f3dd936a53c5d63e.zip |
move version detection here
2004-01-15 JP Rosevear <jpr@ximian.com>
* main.c (detect_version): move version detection here
* e-config-upgrade.c: remove it from here; clean out all the
mailer and bonobo conf conversion stuff, its been moved to the
mailer and e-util
* e-config-upgrade.h: remove proto
svn path=/trunk/; revision=24242
-rw-r--r-- | shell/ChangeLog | 10 | ||||
-rw-r--r-- | shell/e-config-upgrade.c | 1847 | ||||
-rw-r--r-- | shell/e-config-upgrade.h | 4 | ||||
-rw-r--r-- | shell/main.c | 64 |
4 files changed, 168 insertions, 1757 deletions
diff --git a/shell/ChangeLog b/shell/ChangeLog index a13a03b7ea..86b741cba5 100644 --- a/shell/ChangeLog +++ b/shell/ChangeLog @@ -1,3 +1,13 @@ +2004-01-15 JP Rosevear <jpr@ximian.com> + + * main.c (detect_version): move version detection here + + * e-config-upgrade.c: remove it from here; clean out all the + mailer and bonobo conf conversion stuff, its been moved to the + mailer and e-util + + * e-config-upgrade.h: remove proto + 2004-01-15 Not Zed <NotZed@Ximian.com> * e-config-upgrade.c (e_upgrade_detect_version): fix the check for diff --git a/shell/e-config-upgrade.c b/shell/e-config-upgrade.c index 7c51adf5ec..e59c7e9264 100644 --- a/shell/e-config-upgrade.c +++ b/shell/e-config-upgrade.c @@ -24,1368 +24,171 @@ #include <sys/types.h> #include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> #include <stdio.h> -#include <errno.h> -#include <regex.h> -#include <string.h> #include <ctype.h> #include <glib.h> #include <gconf/gconf.h> #include <gconf/gconf-client.h> -#include <libxml/xmlmemory.h> -#include <libxml/parser.h> -#include <libxml/tree.h> - +#include "e-util/e-bconf-map.h" #include "e-config-upgrade.h" -#define d(x) - -/* output revision of configuration */ -#define CONF_MAJOR (1) -#define CONF_MINOR (4) -#define CONF_REVISION (0) - -/* major/minor/revision of existing config */ -static unsigned int major = -1; -static unsigned int minor = -1; -static unsigned int revision = -1; - -/* 1.0 details, if required */ -static GHashTable *accounts_1_0 = NULL; -static GHashTable *accounts_name_1_0 = NULL; - -/* where files are stored */ -static const char *evolution_dir; - -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, -}; - -static char *hex_decode(const char *val) -{ - char *o, *res; - const unsigned char *p = (const unsigned char *)val; - - 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; -} - -static char *url_decode(const char *val) -{ - char *o, *res, c; - const unsigned char *p = (const unsigned char *)val; - - 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; -} - -/* so we dont need camel, just copy here */ -static int -camel_file_util_decode_uint32 (FILE *in, guint32 *dest) -{ - guint32 value = 0; - int v; - - /* until we get the last byte, keep decoding 7 bits at a time */ - while ( ((v = fgetc (in)) & 0x80) == 0 && v!=EOF) { - value |= v; - value <<= 7; - } - if (v == EOF) { - *dest = value >> 7; - return -1; - } - *dest = value | (v & 0x7f); - - return 0; -} - -static int -camel_file_util_decode_string (FILE *in, char **str) -{ - guint32 len; - register char *ret; - - if (camel_file_util_decode_uint32 (in, &len) == -1) { - *str = NULL; - return -1; - } - - len--; - if (len > 65536) { - *str = NULL; - return -1; - } - - ret = g_malloc (len+1); - if (len > 0 && fread (ret, len, 1, in) != 1) { - g_free (ret); - *str = NULL; - return -1; - } - - ret[len] = 0; - *str = ret; - return 0; -} - -/* For 1.0.8 conversion */ - -/* as much info as we have on a given account */ -struct _account_info { - char *name; - char *uri; - char *base_uri; - union { - struct { - /* for imap */ - char *namespace; - char *namespace_full; - guint32 capabilities; - GHashTable *folders; - char dir_sep; - } imap; - } u; -}; - -struct _imap_folder_info { - char *folder; - /* encoded? decoded? canonicalised? */ - char dir_sep; -}; - -static char *parse_lsub(const char *lsub, char *dir_sep) -{ - static int comp; - static regex_t pat; - regmatch_t match[3]; - char *m = "^\\* LSUB \\([^)]*\\) \"?([^\" ]+)\"? \"?(.*)\"?$"; - - if (!comp) { - if (regcomp(&pat, m, REG_EXTENDED|REG_ICASE) == -1) { - g_warning("reg comp '%s' failed: %s", m, g_strerror(errno)); - return NULL; - } - comp = 1; - } - - if (regexec(&pat, lsub, 3, match, 0) == 0) { - if (match[1].rm_so != -1 && match[2].rm_so != -1) { - if (dir_sep) - *dir_sep = (match[1].rm_eo - match[1].rm_so == 1) ? lsub[match[1].rm_so] : 0; - return g_strndup(lsub + match[2].rm_so, match[2].rm_eo - match[2].rm_so); - } - } - - return NULL; -} - -static int read_imap_storeinfo(struct _account_info *si) -{ - FILE *storeinfo; - guint32 tmp; - char *buf, *folder, dir_sep, *path, *name, *p; - struct _imap_folder_info *fi; - - si->u.imap.folders = g_hash_table_new(g_str_hash, g_str_equal); - - /* get details from uri first */ - name = strstr(si->uri, ";override_namespace"); - if (name) { - name = strstr(si->uri, ";namespace="); - if (name) { - char *end; - - name += strlen(";namespace="); - if (*name == '\"') { - name++; - end = strchr(name, '\"'); - } else { - end = strchr(name, ';'); - } - - if (end) { - /* try get the dir_sep from the namespace */ - si->u.imap.namespace = g_strndup(name, end-name); - - p = si->u.imap.namespace; - while ((dir_sep = *p++)) { - if (dir_sep < '0' - || (dir_sep > '9' && dir_sep < 'A') - || (dir_sep > 'Z' && dir_sep < 'a') - || (dir_sep > 'z')) { - si->u.imap.dir_sep = dir_sep; - break; - } - p++; - } - } - } - } - - /* now load storeinfo if it exists */ - path = g_build_filename(evolution_dir, "mail/imap", si->base_uri+7, "storeinfo", NULL); - storeinfo = fopen(path, "r"); - g_free(path); - if (storeinfo == NULL) { - g_warning("could not find imap store info '%s'", path); - return -1; - } - - /* ignore version */ - camel_file_util_decode_uint32(storeinfo, &tmp); - camel_file_util_decode_uint32(storeinfo, &si->u.imap.capabilities); - g_free(si->u.imap.namespace); - camel_file_util_decode_string (storeinfo, &si->u.imap.namespace); - camel_file_util_decode_uint32 (storeinfo, &tmp); - si->u.imap.dir_sep = tmp; - /* strip trailing dir_sep or / */ - if (si->u.imap.namespace - && (si->u.imap.namespace[strlen(si->u.imap.namespace)-1] == si->u.imap.dir_sep - || si->u.imap.namespace[strlen(si->u.imap.namespace)-1] == '/')) { - si->u.imap.namespace[strlen(si->u.imap.namespace)-1] = 0; - } - - d(printf("namespace '%s' dir_sep '%c'\n", si->u.imap.namespace, si->u.imap.dir_sep?si->u.imap.dir_sep:'?')); - - while (camel_file_util_decode_string (storeinfo, &buf) == 0) { - folder = parse_lsub(buf, &dir_sep); - if (folder) { - fi = g_malloc0(sizeof(*fi)); - fi->folder = folder; - fi->dir_sep = dir_sep; -#if d(!)0 - printf(" add folder '%s' ", folder); - if (dir_sep) - printf("'%c'\n", dir_sep); - else - printf("NIL\n"); -#endif - g_hash_table_insert(si->u.imap.folders, fi->folder, fi); - } else { - g_warning("Could not parse LIST result '%s'\n", buf); - } - } - fclose(storeinfo); - - return 0; -} - -static char *get_base_uri(const char *val) -{ - const char *tmp; - - tmp = strchr(val, ':'); - if (tmp) { - tmp++; - if (strncmp(tmp, "//", 2) == 0) - tmp += 2; - tmp = strchr(tmp, '/'); - } - - if (tmp) - return g_strndup(val, tmp-val); - else - return g_strdup(val); -} - -static char *upgrade_uri(const char *uri) -{ - char *out = NULL; - - /* upgrades camel uri's */ - - if (major <=1 && minor < 2) { - if (strncmp(uri, "imap:", 5) == 0) { - char *base_uri, dir_sep, *folder, *p; - struct _account_info *ai; - - /* add namespace, canonicalise dir_sep to / */ - base_uri = get_base_uri(uri); - ai = g_hash_table_lookup(accounts_1_0, base_uri); - - if (ai == NULL) { - g_free(base_uri); - return NULL; - } - - dir_sep = ai->u.imap.dir_sep; - if (dir_sep == 0) { - /* no dir_sep listed, try get it from the namespace, if set */ - if (ai->u.imap.namespace != NULL) { - p = ai->u.imap.namespace; - while ((dir_sep = *p++)) { - if (dir_sep < '0' - || (dir_sep > '9' && dir_sep < 'A') - || (dir_sep > 'Z' && dir_sep < 'a') - || (dir_sep > 'z')) { - break; - } - p++; - } - } - - /* give up ... */ - if (dir_sep == 0) { - g_free(base_uri); - return NULL; - } - } - - folder = g_strdup(uri + strlen(base_uri)+1); - - /* Add the namespace before the mailbox name, unless the mailbox is INBOX */ - if (ai->u.imap.namespace && strcmp(folder, "INBOX") != 0) - out = g_strdup_printf("%s/%s/%s", base_uri, ai->u.imap.namespace, folder); - else - out = g_strdup_printf("%s/%s", base_uri, folder); - - p = out; - while (*p) { - if (*p == dir_sep) - *p = '/'; - p++; - } - - g_free(folder); - g_free(base_uri); - } else if (strncmp(uri, "exchange:", 9) == 0) { - char *base_uri, *folder, *p; - - /* exchange://user@host/exchange/ * -> exchange://user@host/personal/ * */ - /* Any url encoding (%xx) in the folder name is also removed */ - base_uri = get_base_uri(uri); - uri += strlen(base_uri) + 1; - if (strncmp(uri, "exchange/", 9) == 0) { - folder = url_decode(uri+9); - p = strchr(folder, '/'); - out = g_strdup_printf("%s/personal%s", base_uri, p?p:"/"); - g_free(folder); - } - } else if (strncmp(uri, "exchanget:", 10) == 0) { - /* these should be converted in the accounts table when it is loaded */ - g_warning("exchanget: uri not converted: '%s'", uri); - } - } - - return out; -} - -static char *upgrade_evolution_uri(const char *uri) -{ - char *out = NULL; - - if (!strcmp (uri, "evolution:/local/Inbox")) { - return g_strdup("default:mail"); - } else if (!strcmp (uri, "evolution:/local/Calendar")) { - return g_strdup("default:calendar"); - } else if (!strcmp (uri, "evolution:/local/Contacts")) { - return g_strdup("default:contacts"); - } else if (!strcmp (uri, "evolution:/local/Tasks")) { - return g_strdup("default:tasks"); - } if (!strncmp(uri, "evolution:/", 11)) { - char *account, *tmp, *folder, *p; - struct _account_info *ai; - - d(printf("convert url '%s'\n", uri)); - tmp = strchr(uri+11, '/'); - if (tmp == NULL) - return NULL; - - folder = *tmp?tmp+1:tmp; - account = g_strndup(uri+11, tmp-uri-11); - d(printf(" looking for account '%s'\n", account)); - ai = g_hash_table_lookup(accounts_name_1_0, account); - if (ai && !strncmp(ai->base_uri, "imap:", 5)) { - /* Add namespace to evolution url's of imap accounts, if the account uses a namespace */ - d(printf("found account ... '%s', folder = '%s'\n", ai->name, folder)); - - if (ai->u.imap.namespace && strcmp(folder, "INBOX") != 0) - out = g_strdup_printf("evolution:/%s/%s/%s", account, ai->u.imap.namespace, folder); - else - out = g_strdup_printf("evolution:/%s/%s", account, folder); - - if (ai->u.imap.dir_sep) { - p = out + strlen("evolution://") + strlen(account); - while (*p) { - if (*p == ai->u.imap.dir_sep) - *p = '/'; - p++; - } - } - } else if (ai && !strncmp(ai->base_uri, "exchange:", 9)) { - /* add personal to exchange url's */ - folder = url_decode(folder); - out = g_strdup_printf("evolution:/%s/personal/%s", account, folder); - g_free(folder); - } - g_free(account); - } - - return out; -} - -static char *upgrade_type(const char *type) -{ - char *res = NULL; - - /* - <item type="ldap-contacts ...> - to - <item type="contacts/ldap ...> - */ - - if (strcmp(type, "ldap-contacts") == 0) - res = g_strdup("contacts/ldap"); - - return res; -} - -enum { - CONVERT_CONTENT, - CONVERT_ARG, -}; - -struct _convert { - int type; - char *tag; - char *arg; - char *(*convert)(const char *val); -} convert_table [] = { - /* fix evolution uri's in shortcuts file */ - { CONVERT_CONTENT, "item", NULL, upgrade_evolution_uri }, - /* ldap item/type's converted from ldap-contacts to contacts/ldap */ - { CONVERT_ARG, "item", "type", upgrade_type }, - /* fix folder uri's in filters/vfolders */ - { CONVERT_ARG, "folder", "uri", upgrade_uri }, -}; - -#define CONVERT_SIZEOF (sizeof(convert_table)/sizeof(convert_table[0])) - -static int upgrade_xml_1_0_rec(xmlNodePtr node) -{ - int i; - struct _convert *ct; - int scan = TRUE; - int work = FALSE; - char *txt, *newtxt; - - for (i=0;i<CONVERT_SIZEOF;i++) { - ct = &convert_table[i]; - if (!strcmp(node->name, ct->tag)) { - switch(ct->type) { - case CONVERT_CONTENT: - txt = xmlNodeGetContent(node); - newtxt = ct->convert(txt); - d(printf("Upgrade content '%s': '%s' -> '%s'\n", ct->tag, txt, newtxt?newtxt:"unchanged")); - xmlFree(txt); - if (newtxt) { - xmlNodeSetContent(node, newtxt); - g_free(newtxt); - work = TRUE; - } - scan = FALSE; - break; - case CONVERT_ARG: - txt = xmlGetProp(node, ct->arg); - if (txt) { - newtxt = ct->convert(txt); - d(printf("Upgrade prop '%s' '%s': '%s' -> '%s'\n", ct->tag, ct->arg, txt, newtxt?newtxt:"unchanged")); - xmlFree(txt); - if (newtxt) { - xmlSetProp(node, ct->arg, newtxt); - g_free(newtxt); - work = TRUE; - } - } - break; - } - } - } - - if (scan) { - node = node->children; - while (node) { - work |= upgrade_xml_1_0_rec(node); - node = node->next; - } - } - - return work; -} - -/* ********************************************************************** */ -/* XML 1 content encoding */ - -static int -is_xml1encoded(const char *txt) -{ - const unsigned char *p; - int isxml1 = FALSE; - int is8bit = FALSE; - - p = (const unsigned char *)txt; - while (*p) { - if (p[0] == '\\' && p[1] == 'U' && p[2] == '+' - && isxdigit(p[3]) && isxdigit(p[4]) && isxdigit(p[5]) && isxdigit(p[6]) - && p[7] == '\\') { - isxml1 = TRUE; - p+=7; - } else if (p[0] >= 0x80) - is8bit = TRUE; - p++; - } - - /* check for invalid utf8 that needs cleaning */ - if (is8bit && (!isxml1)) - isxml1 = !g_utf8_validate(txt, -1, NULL); - - return isxml1; -} - -static char * -decode_xml1(const char *txt) -{ - GString *out = g_string_new(""); - const unsigned char *p; - char *res; - - /* convert: - \U+XXXX\ -> utf8 - 8 bit characters -> utf8 (iso-8859-1) */ - - p = (const unsigned char *)txt; - while (*p) { - if (p[0] > 0x80 - || (p[0] == '\\' && p[1] == 'U' && p[2] == '+' - && isxdigit(p[3]) && isxdigit(p[4]) && isxdigit(p[5]) && isxdigit(p[6]) - && p[7] == '\\')) { - char utf8[8]; - gunichar u; - - if (p[0] == '\\') { - memcpy(utf8, p+3, 4); - utf8[4] = 0; - u = strtoul(utf8, NULL, 16); - p+=7; - } else - u = p[0]; - utf8[g_unichar_to_utf8(u, utf8)] = 0; - g_string_append(out, utf8); - } else { - g_string_append_c(out, *p); - } - p++; - } - - res = out->str; - g_string_free(out, FALSE); - - return res; -} - -static char * -utf8_reencode (const char * txt) -{ - GString *out = g_string_new(""); - const unsigned char *p; - char *res; - - /* convert: - libxml1 8 bit utf8 converted to xml entities byte-by-byte chars -> utf8 */ - - p = (const unsigned char *) txt; - - while (*p) { - g_string_append_c(out,(char) g_utf8_get_char(p)); - p = g_utf8_next_char (p); - } - res = out->str; - if (g_utf8_validate (res, -1, NULL)) { - g_string_free(out, FALSE); - return res; - } else { - g_string_free (out, TRUE); - return g_strdup (txt); - } -} - - -static int -upgrade_xml_1_2_rec(xmlNodePtr node) -{ - const char *value_tags[] = { "string", "address", "regex", "file", "command", NULL }; - const char *rule_tags[] = { "title", NULL }; - const char *item_props[] = { "name", NULL }; - struct { - const char *name; - const char **tags; - const char **props; - } tags[] = { - { "value", value_tags, NULL }, - { "rule", rule_tags, NULL }, - { "item", NULL, item_props }, - { 0 }, - }; - int changed = 0; - xmlNodePtr work; - int i,j; - char *txt, *tmp; - - /* upgrades the content of a node, if the node has a specific parent/node name */ - - for (i=0;tags[i].name;i++) { - if (!strcmp(node->name, tags[i].name)) { - if (tags[i].tags != NULL) { - work = node->children; - while (work) { - for (j=0;tags[i].tags[j];j++) { - if (!strcmp(work->name, tags[i].tags[j])) { - txt = xmlNodeGetContent(work); - if (is_xml1encoded(txt)) { - tmp = decode_xml1(txt); - d(printf("upgrading xml node %s/%s '%s' -> '%s'\n", tags[i].name, tags[i].tags[j], txt, tmp)); - xmlNodeSetContent(work, tmp); - changed = 1; - g_free(tmp); - } - xmlFree(txt); - } - } - work = work->next; - } - break; - } - if (tags[i].props != NULL) { - for (j=0; tags[i].props[j];j++) { - txt = xmlGetProp (node, tags[i].props[j]); - d(printf("upgrading xml property %s on node %s '%s' -> '%s'\n", tags[i].props[j],tags[i].name,txt,tmp)); - tmp = utf8_reencode(txt); - xmlSetProp(node, tags[i].props[j],tmp); - changed = 1; - g_free(tmp); - xmlFree(txt); - } - } - } - } - - node = node->children; - while (node) { - changed |= upgrade_xml_1_2_rec(node); - node = node->next; - } - - return changed; -} - -/* ********************************************************************** */ - -static int upgrade_xml_file(const char *filename, int (*upgrade_rec)(xmlNodePtr root)) -{ - xmlDocPtr doc; - char *savename; - struct stat st; - int res; - - /* FIXME: do something nicer with the errors */ - - savename = alloca(strlen(filename)+64); - sprintf(savename, "%s.save-%u.%u.%u", filename, major, minor, revision); - if (stat(savename, &st) == 0) { - fprintf(stderr, "xml file `%s' already upgraded\n", filename); - return 0; - } - - /* no file, no error */ - if (stat(filename, &st) == -1) - return 0; - - doc = xmlParseFile (filename); - if (!doc || !doc->xmlRootNode) { - fprintf (stderr, "Failed to load %s\n", filename); - return -1; - } - - if (!upgrade_rec(doc->xmlRootNode)) { - xmlFreeDoc(doc); - printf("file %s contains nothing to upgrade\n", filename); - return 0; - } - - d(printf("backing up %s to %s\n", filename, savename)); - - if (rename(filename, savename) == -1) { - xmlFreeDoc(doc); - fprintf(stderr, "could not rename '%s' to '%s': %s\n", filename, savename, strerror(errno)); - return -1; - } - - res = xmlSaveFormatFile(filename, doc, 1); - - xmlFreeDoc(doc); - - return res; -} - -/* ********************************************************************** */ -/* Tables for converting flat bonobo conf -> gconf xml blob */ -/* ********************************************************************** */ - -/* for remapping bonobo-conf account data into the new xml blob format */ -/* These are used in build_xml, and order must match the lookup_table */ -enum _map_t { - MAP_END = 0, /* end of line*/ - MAP_BOOL, /* bool -> prop of name 'to' value true or false */ - MAP_LONG, /* long -> prop of name 'to' value a long */ - MAP_STRING, /* string -> prop of name 'to' */ - MAP_ENUM, /* long/bool -> prop of name 'to', with the value indexed into the child map table's from field */ - MAP_CHILD, /* a new child of name 'to' */ - MAP_MASK = 0x3f, - MAP_URI_UPGRADE = 0x40, /* if from 1.0.x, upgrade any uri's present */ - MAP_CONTENT = 0x80, /* if set, create a new node of name 'to' instead of a property */ -}; - -struct _map_table { - char *from; - char *to; - int type; - struct _map_table *child; -}; - -/* Mail/Accounts/ * */ -struct _map_table cc_map[] = { - { "account_always_cc_%i", "always", MAP_BOOL }, - { "account_always_cc_addrs_%i", "recipients", MAP_STRING|MAP_CONTENT }, - { NULL }, -}; - -struct _map_table bcc_map[] = { - { "account_always_cc_%i", "always", MAP_BOOL }, - { "account_always_bcc_addrs_%i", "recipients", MAP_STRING|MAP_CONTENT }, - { NULL }, -}; - -struct _map_table pgp_map[] = { - { "account_pgp_encrypt_to_self_%i", "encrypt-to-self", MAP_BOOL }, - { "account_pgp_always_trust_%i", "always-trust", MAP_BOOL }, - { "account_pgp_always_sign_%i", "always-sign", MAP_BOOL }, - { "account_pgp_no_imip_sign_%i", "no-imip-sign", MAP_BOOL }, - { "account_pgp_key_%i", "key-id", MAP_STRING|MAP_CONTENT }, - { NULL }, -}; - -struct _map_table smime_map[] = { - { "account_smime_encrypt_to_self_%i", "encrypt-to-self", MAP_BOOL }, - { "account_smime_always_sign_%i", "always-sign", MAP_BOOL }, - { "account_smime_key_%i", "key-id", MAP_STRING|MAP_CONTENT }, - { NULL }, -}; - -struct _map_table identity_sig_map[] = { - { "identity_autogenerated_signature_%i", "auto", MAP_BOOL }, - { "identity_def_signature_%i", "default", MAP_LONG }, - { NULL }, -}; - -struct _map_table identity_map[] = { - { "identity_name_%i", "name", MAP_STRING|MAP_CONTENT }, - { "identity_address_%i", "addr-spec", MAP_STRING|MAP_CONTENT }, - { "identity_reply_to_%i", "reply-to", MAP_STRING|MAP_CONTENT }, - { "identity_organization_%i", "organization", MAP_STRING|MAP_CONTENT }, - { NULL, "signature", MAP_CHILD, identity_sig_map }, - { NULL }, -}; - -struct _map_table source_map[] = { - { "source_save_passwd_%i", "save-passwd", MAP_BOOL }, - { "source_keep_on_server_%i", "keep-on-server", MAP_BOOL }, - { "source_auto_check_%i", "auto-check", MAP_BOOL }, - { "source_auto_check_time_%i", "auto-check-timeout", MAP_LONG }, - { "source_url_%i", "url", MAP_STRING|MAP_CONTENT }, - { NULL }, -}; - -struct _map_table transport_map[] = { - { "transport_save_passwd_%i", "save-passwd", MAP_BOOL }, - { "transport_url_%i", "url", MAP_STRING|MAP_CONTENT|MAP_URI_UPGRADE }, - { NULL }, -}; - -struct _map_table account_map[] = { - { "account_name_%i", "name", MAP_STRING }, - { "source_enabled_%i", "enabled", MAP_BOOL }, - { NULL, "identity", MAP_CHILD, identity_map }, - { NULL, "source", MAP_CHILD, source_map }, - { NULL, "transport", MAP_CHILD, transport_map }, - { "account_drafts_folder_uri_%i", "drafts-folder", MAP_STRING|MAP_CONTENT|MAP_URI_UPGRADE }, - { "account_sent_folder_uri_%i", "sent-folder", MAP_STRING|MAP_CONTENT|MAP_URI_UPGRADE }, - { NULL, "auto-cc", MAP_CHILD, cc_map }, - { NULL, "auto-bcc", MAP_CHILD, bcc_map }, - { NULL, "pgp", MAP_CHILD, pgp_map }, - { NULL, "smime", MAP_CHILD, smime_map }, - { NULL }, -}; - -/* /Mail/Signatures/ * */ -struct _map_table signature_format_map[] = { - { "text/plain", }, - { "text/html", }, - { NULL } -}; - -struct _map_table signature_map[] = { - { "name_%i", "name", MAP_STRING }, - { "html_%i", "format", MAP_ENUM, signature_format_map }, - { "filename_%i", "filename", MAP_STRING|MAP_CONTENT }, - { "script_%i", "script", MAP_STRING|MAP_CONTENT }, - { NULL }, -}; - - -static char *get_name(const char *in, int index) -{ - char c, *res; - GString *out = g_string_new(""); - - 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 xmlNodePtr lookup_bconf_entry(xmlNodePtr source, const char *name) -{ - xmlNodePtr node = source->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; -} - -static char *lookup_bconf_value(xmlNodePtr source, const char *name) -{ - xmlNodePtr node = lookup_bconf_entry(source, name); - - if (node) - return xmlGetProp(node, "value"); - else - return NULL; -} - -static xmlNodePtr lookup_bconf_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\n"); - 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; -} - - -static char *lookup_bool(xmlNodePtr source, const char *name, struct _map_table *map) -{ - char *val, *res; - - val = lookup_bconf_value(source, name); - if (val) { - res = g_strdup(val[0] == '1'?"true":"false"); - xmlFree(val); - } else - res = NULL; - - return res; -} - -static char *lookup_long(xmlNodePtr source, const char *name, struct _map_table *map) -{ - char *val, *res; - - val = lookup_bconf_value(source, name); - if (val) { - res = g_strdup(val); - xmlFree(val); - } else - res = NULL; - - return res; -} - -static char *lookup_string(xmlNodePtr source, const char *name, struct _map_table *map) -{ - char *val, *res; - - val = lookup_bconf_value(source, name); - if (val) { - res = hex_decode(val); - xmlFree(val); - } else - res = NULL; - - return res; -} - -static char *lookup_enum(xmlNodePtr source, const char *name, struct _map_table *map) -{ - char *val; - int index = 0, i; - - val = lookup_bconf_value(source, name); - if (val) { - index = atoi(val); - xmlFree(val); - } - - for (i=0;map->child[i].from;i++) - if (i == index) - return g_strdup(map->child[i].from); - - return NULL; -} - -typedef char * (*lookup_func) (xmlNodePtr, const char *, struct _map_table *); - -static void -build_xml(xmlNodePtr root, struct _map_table *map, int index, xmlNodePtr source) -{ - char *name, *value; - xmlNodePtr node; - lookup_func lookup_table[] = { lookup_bool, lookup_long, lookup_string, lookup_enum }; - - while (map->type != MAP_END) { - if ((map->type & MAP_MASK) == 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&MAP_MASK)-1](source, name, map); - - d(printf("key '%s=%s' -> ", name, value)); - - if (map->type & MAP_URI_UPGRADE) { - char *tmp = value; - - value = upgrade_uri(tmp); - if (value) - g_free(tmp); - else - value = tmp; - } - - d(printf("'%s=%s'\n", map->to, value)); - - if (map->type & 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++; - } -} - -static int convert_xml_blob(GConfClient *gconf, xmlDocPtr doc, struct _map_table *map, const char *path, const char *outpath, const char *name, const char *idparam) -{ - xmlNodePtr source; - int count = 0, i; - GSList *list, *l; - char *val; - - source = lookup_bconf_path(doc, path); - if (source) { - list = NULL; - val = lookup_bconf_value(source, "num"); - if (val) { - count = atoi(val); - xmlFree(val); - } - - d(printf("Found %d blobs at %s\n", count, path)); - - for (i = 0; i<count;i++) { - xmlDocPtr docout; - xmlChar *xmlbuf; - int n; - xmlNodePtr root; - - docout = xmlNewDoc ("1.0"); - root = xmlNewDocNode (docout, NULL, name, NULL); - xmlDocSetRootElement (docout, 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 (docout, &xmlbuf, &n); - xmlFreeDoc (docout); - - list = g_slist_append(list, xmlbuf); - } - - gconf_client_set_list(gconf, outpath, 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", path); - } - - return 0; -} - /* ********************************************************************** */ /* Tables for bonobo conf -> gconf conversion */ /* ********************************************************************** */ -/* order important here, used to index a few tables below */ -enum { - BMAP_BOOL, - BMAP_BOOLNOT, - BMAP_INT, - BMAP_STRING, - BMAP_SIMPLESTRING, /* a non-encoded string */ - BMAP_COLOUR, - BMAP_FLOAT, /* bloody floats, who uses floats ... idiots */ - BMAP_STRLIST, /* strings separated to !<-->! -> gconf list */ - BMAP_ANYLIST, /* corba sequence corba string -> gconf list */ - BMAP_MASK = 0x7f, - BMAP_LIST = 0x80 /* from includes a %i field for the index of the key, to be converted to a list of type BMAP_* */ -}; - -struct _gconf_map { - char *from; - char *to; - int type; -}; - /* ********************************************************************** */ -static struct _gconf_map mail_accounts_map[] = { - /* /Mail/Accounts - most entries are processed via the xml blob routine */ - /* This also works because the initial uid mapping is 1:1 with the list order */ - { "default_account", "mail/default_account", BMAP_SIMPLESTRING }, - { 0 }, -}; - -static struct _gconf_map mail_display_map[] = { - /* /Mail/Display */ - { "thread_list", "mail/display/thread_list", BMAP_BOOL }, - { "thread_subject", "mail/display/thread_subject", BMAP_BOOL }, - { "hide_deleted", "mail/display/show_deleted", BMAP_BOOLNOT }, - { "preview_pane", "mail/display/show_preview", BMAP_BOOL }, - { "paned_size", "mail/display/paned_size", BMAP_INT }, - { "seen_timeout", "mail/display/mark_seen_timeout", BMAP_INT }, - { "do_seen_timeout", "mail/display/mark_seen", BMAP_BOOL }, - { "http_images", "mail/display/load_http_images", BMAP_INT }, - { "citation_highlight", "mail/display/mark_citations", BMAP_BOOL }, - { "citation_color", "mail/display/citation_colour", BMAP_COLOUR }, - { "x_mailer_display_style", "mail/display/xmailer_mask", BMAP_INT }, - { 0 }, -}; - -static struct _gconf_map mail_format_map[] = { - /* /Mail/Format */ - { "message_display_style", "mail/display/message_style", BMAP_INT }, - { "send_html", "mail/composer/send_html", BMAP_BOOL }, - { "default_reply_style", "mail/format/reply_style", BMAP_INT }, - { "default_forward_style", "mail/format/forward_style", BMAP_INT }, - { "default_charset", "mail/composer/charset", BMAP_STRING }, - { "confirm_unwanted_html", "mail/prompts/unwanted_html", BMAP_BOOL }, - { 0 }, -}; - -static struct _gconf_map mail_trash_map[] = { - /* /Mail/Trash */ - { "empty_on_exit", "mail/trash/empty_on_exit", BMAP_BOOL }, - { 0 }, -}; - -static struct _gconf_map mail_prompts_map[] = { - /* /Mail/Prompts */ - { "confirm_expunge", "mail/prompts/expunge", BMAP_BOOL }, - { "empty_subject", "mail/prompts/empty_subject", BMAP_BOOL }, - { "only_bcc", "mail/prompts/only_bcc", BMAP_BOOL }, - { 0 } -}; - -static struct _gconf_map mail_filters_map[] = { - /* /Mail/Filters */ - { "log", "mail/filters/log", BMAP_BOOL }, - { "log_path", "mail/filters/logfile", BMAP_STRING }, - { 0 } -}; - -static struct _gconf_map mail_notify_map[] = { - /* /Mail/Notify */ - { "new_mail_notification", "mail/notify/type", BMAP_INT }, - { "new_mail_notification_sound_file", "mail/notify/sound", BMAP_STRING }, - { 0 } -}; - -static struct _gconf_map mail_filesel_map[] = { - /* /Mail/Filesel */ - { "last_filesel_dir", "mail/save_dir", BMAP_STRING }, - { 0 } -}; - -static struct _gconf_map mail_composer_map[] = { - /* /Mail/Composer */ - { "ViewFrom", "mail/composer/view/From", BMAP_BOOL }, - { "ViewReplyTo", "mail/composer/view/ReplyTo", BMAP_BOOL }, - { "ViewCC", "mail/composer/view/Cc", BMAP_BOOL }, - { "ViewBCC", "mail/composer/view/Bcc", BMAP_BOOL }, - { "ViewSubject", "mail/composer/view/Subject", BMAP_BOOL }, - { 0 }, -}; - -/* ********************************************************************** */ - -static struct _gconf_map importer_elm_map[] = { +static e_gconf_map_t importer_elm_map[] = { /* /Importer/Elm */ - { "mail", "importer/elm/mail", BMAP_BOOL }, - { "mail-imported", "importer/elm/mail-imported", BMAP_BOOL }, + { "mail", "importer/elm/mail", E_GCONF_MAP_BOOL }, + { "mail-imported", "importer/elm/mail-imported", E_GCONF_MAP_BOOL }, { 0 }, }; -static struct _gconf_map importer_pine_map[] = { +static e_gconf_map_t importer_pine_map[] = { /* /Importer/Pine */ - { "mail", "importer/elm/mail", BMAP_BOOL }, - { "address", "importer/elm/address", BMAP_BOOL }, + { "mail", "importer/elm/mail", E_GCONF_MAP_BOOL }, + { "address", "importer/elm/address", E_GCONF_MAP_BOOL }, { 0 }, }; -static struct _gconf_map importer_netscape_map[] = { +static e_gconf_map_t importer_netscape_map[] = { /* /Importer/Netscape */ - { "mail", "importer/netscape/mail", BMAP_BOOL }, - { "settings", "importer/netscape/settings", BMAP_BOOL }, - { "filters", "importer/netscape/filters", BMAP_BOOL }, + { "mail", "importer/netscape/mail", E_GCONF_MAP_BOOL }, + { "settings", "importer/netscape/settings", E_GCONF_MAP_BOOL }, + { "filters", "importer/netscape/filters", E_GCONF_MAP_BOOL }, { 0 }, }; /* ********************************************************************** */ /* This grabs the defaults from the first view ... (?) */ -static struct _gconf_map shell_views_map[] = { +static e_gconf_map_t shell_views_map[] = { /* /Shell/Views/0 */ - { "Width", "shell/view_defaults/width", BMAP_INT }, - { "Height", "shell/view_defaults/height", BMAP_INT }, - { "CurrentShortcutsGroupNum", "shell/view_defaults/selected_shortcut_group", BMAP_INT }, - { "FolderBarShown", "shell/view_defaults/show_folder_bar", BMAP_BOOL }, - { "ShortcutBarShown", "shell/view_defaults/show_shortcut_bar", BMAP_BOOL }, - { "HPanedPosition", "shell/view_defaults/shortcut_bar/width", BMAP_INT }, - { "ViewPanedPosition", "shell/view_defaults/folder_bar/width", BMAP_INT }, - { "DisplayedURI", "shell/view_defaults/folder_path", BMAP_STRING }, + { "Width", "shell/view_defaults/width", E_GCONF_MAP_INT }, + { "Height", "shell/view_defaults/height", E_GCONF_MAP_INT }, + { "CurrentShortcutsGroupNum", "shell/view_defaults/selected_shortcut_group", E_GCONF_MAP_INT }, + { "FolderBarShown", "shell/view_defaults/show_folder_bar", E_GCONF_MAP_BOOL }, + { "ShortcutBarShown", "shell/view_defaults/show_shortcut_bar", E_GCONF_MAP_BOOL }, + { "HPanedPosition", "shell/view_defaults/shortcut_bar/width", E_GCONF_MAP_INT }, + { "ViewPanedPosition", "shell/view_defaults/folder_bar/width", E_GCONF_MAP_INT }, + { "DisplayedURI", "shell/view_defaults/folder_path", E_GCONF_MAP_STRING }, { 0 }, }; -static struct _gconf_map offlinefolders_map[] = { +static e_gconf_map_t offlinefolders_map[] = { /* /OfflineFolders */ - { "paths", "shell/offline/folder_paths", BMAP_ANYLIST }, + { "paths", "shell/offline/folder_paths", E_GCONF_MAP_ANYLIST }, { 0 }, }; -static struct _gconf_map defaultfolders_map[] = { +static e_gconf_map_t defaultfolders_map[] = { /* /DefaultFolders */ - { "mail_path", "shell/default_folders/mail_path", BMAP_STRING }, - { "mail_uri", "shell/default_folders/mail_uri", BMAP_STRING }, - { "contacts_path", "shell/default_folders/contacts_path", BMAP_STRING }, - { "contacts_uri", "shell/default_folders/contacts_uri", BMAP_STRING }, - { "calendar_path", "shell/default_folders/calendar_path", BMAP_STRING }, - { "calendar_uri", "shell/default_folders/calendar_uri", BMAP_STRING }, - { "tasks_path", "shell/default_folders/tasks_path", BMAP_STRING }, - { "tasks_uri", "shell/default_folders/tasks_uri", BMAP_STRING }, + { "mail_path", "shell/default_folders/mail_path", E_GCONF_MAP_STRING }, + { "mail_uri", "shell/default_folders/mail_uri", E_GCONF_MAP_STRING }, + { "contacts_path", "shell/default_folders/contacts_path", E_GCONF_MAP_STRING }, + { "contacts_uri", "shell/default_folders/contacts_uri", E_GCONF_MAP_STRING }, + { "calendar_path", "shell/default_folders/calendar_path", E_GCONF_MAP_STRING }, + { "calendar_uri", "shell/default_folders/calendar_uri", E_GCONF_MAP_STRING }, + { "tasks_path", "shell/default_folders/tasks_path", E_GCONF_MAP_STRING }, + { "tasks_uri", "shell/default_folders/tasks_uri", E_GCONF_MAP_STRING }, { 0 }, }; -static struct _gconf_map shell_map[] = { +static e_gconf_map_t shell_map[] = { /* /Shell */ - { "StartOffline", "shell/start_offline", BMAP_BOOL }, + { "StartOffline", "shell/start_offline", E_GCONF_MAP_BOOL }, { 0 }, }; /* ********************************************************************** */ -static struct _gconf_map addressbook_map[] = { +static e_gconf_map_t addressbook_map[] = { /* /Addressbook */ - { "select_names_uri", "addressbook/select_names/last_used_uri", BMAP_STRING }, + { "select_names_uri", "addressbook/select_names/last_used_uri", E_GCONF_MAP_STRING }, { 0 }, }; -static struct _gconf_map addressbook_completion_map[] = { +static e_gconf_map_t addressbook_completion_map[] = { /* /Addressbook/Completion */ - { "uris", "addressbook/completion/uris", BMAP_STRING }, + { "uris", "addressbook/completion/uris", E_GCONF_MAP_STRING }, { 0 }, }; /* ********************************************************************** */ -static struct _gconf_map calendar_display_map[] = { +static e_gconf_map_t calendar_display_map[] = { /* /Calendar/Display */ - { "Timezone", "calendar/display/timezone", BMAP_STRING }, - { "Use24HourFormat", "calendar/display/use_24hour_format", BMAP_BOOL }, - { "WeekStartDay", "calendar/display/week_start_day", BMAP_INT }, - { "DayStartHour", "calendar/display/day_start_hour", BMAP_INT }, - { "DayStartMinute", "calendar/display/day_start_minute", BMAP_INT }, - { "DayEndHour", "calendar/display/day_end_hour", BMAP_INT }, - { "DayEndMinute", "calendar/display/day_end_minute", BMAP_INT }, - { "TimeDivisions", "calendar/display/time_divisions", BMAP_INT }, - { "View", "calendar/display/default_view", BMAP_INT }, - { "HPanePosition", "calendar/display/hpane_position", BMAP_FLOAT }, - { "VPanePosition", "calendar/display/vpane_position", BMAP_FLOAT }, - { "MonthHPanePosition", "calendar/display/month_hpane_position", BMAP_FLOAT }, - { "MonthVPanePosition", "calendar/display/month_vpane_position", BMAP_FLOAT }, - { "CompressWeekend", "calendar/display/compress_weekend", BMAP_BOOL }, - { "ShowEventEndTime", "calendar/display/show_event_end", BMAP_BOOL }, - { "WorkingDays", "calendar/display/working_days", BMAP_INT }, - { 0 }, -}; - -static struct _gconf_map calendar_tasks_map[] = { + { "Timezone", "calendar/display/timezone", E_GCONF_MAP_STRING }, + { "Use24HourFormat", "calendar/display/use_24hour_format", E_GCONF_MAP_BOOL }, + { "WeekStartDay", "calendar/display/week_start_day", E_GCONF_MAP_INT }, + { "DayStartHour", "calendar/display/day_start_hour", E_GCONF_MAP_INT }, + { "DayStartMinute", "calendar/display/day_start_minute", E_GCONF_MAP_INT }, + { "DayEndHour", "calendar/display/day_end_hour", E_GCONF_MAP_INT }, + { "DayEndMinute", "calendar/display/day_end_minute", E_GCONF_MAP_INT }, + { "TimeDivisions", "calendar/display/time_divisions", E_GCONF_MAP_INT }, + { "View", "calendar/display/default_view", E_GCONF_MAP_INT }, + { "HPanePosition", "calendar/display/hpane_position", E_GCONF_MAP_FLOAT }, + { "VPanePosition", "calendar/display/vpane_position", E_GCONF_MAP_FLOAT }, + { "MonthHPanePosition", "calendar/display/month_hpane_position", E_GCONF_MAP_FLOAT }, + { "MonthVPanePosition", "calendar/display/month_vpane_position", E_GCONF_MAP_FLOAT }, + { "CompressWeekend", "calendar/display/compress_weekend", E_GCONF_MAP_BOOL }, + { "ShowEventEndTime", "calendar/display/show_event_end", E_GCONF_MAP_BOOL }, + { "WorkingDays", "calendar/display/working_days", E_GCONF_MAP_INT }, + { 0 }, +}; + +static e_gconf_map_t calendar_tasks_map[] = { /* /Calendar/Tasks */ - { "HideCompletedTasks", "calendar/tasks/hide_completed", BMAP_BOOL }, - { "HideCompletedTasksUnits", "calendar/tasks/hide_completed_units", BMAP_STRING }, - { "HideCompletedTasksValue", "calendar/tasks/hide_completed_value", BMAP_INT }, + { "HideCompletedTasks", "calendar/tasks/hide_completed", E_GCONF_MAP_BOOL }, + { "HideCompletedTasksUnits", "calendar/tasks/hide_completed_units", E_GCONF_MAP_STRING }, + { "HideCompletedTasksValue", "calendar/tasks/hide_completed_value", E_GCONF_MAP_INT }, { 0 }, }; -static struct _gconf_map calendar_tasks_colours_map[] = { +static e_gconf_map_t calendar_tasks_colours_map[] = { /* /Calendar/Tasks/Colors */ - { "TasksDueToday", "calendar/tasks/colors/due_today", BMAP_STRING }, - { "TasksOverDue", "calendar/tasks/colors/overdue", BMAP_STRING }, - { "TasksDueToday", "calendar/tasks/colors/due_today", BMAP_STRING }, + { "TasksDueToday", "calendar/tasks/colors/due_today", E_GCONF_MAP_STRING }, + { "TasksOverDue", "calendar/tasks/colors/overdue", E_GCONF_MAP_STRING }, + { "TasksDueToday", "calendar/tasks/colors/due_today", E_GCONF_MAP_STRING }, { 0 }, }; -static struct _gconf_map calendar_other_map[] = { +static e_gconf_map_t calendar_other_map[] = { /* /Calendar/Other */ - { "ConfirmDelete", "calendar/prompts/confirm_delete", BMAP_BOOL }, - { "ConfirmExpunge", "calendar/prompts/confirm_expunge", BMAP_BOOL }, - { "UseDefaultReminder", "calendar/other/use_default_reminder", BMAP_BOOL }, - { "DefaultReminderInterval", "calendar/other/default_reminder_interval", BMAP_INT }, - { "DefaultReminderUnits", "calendar/other/default_reminder_units", BMAP_STRING }, + { "ConfirmDelete", "calendar/prompts/confirm_delete", E_GCONF_MAP_BOOL }, + { "ConfirmExpunge", "calendar/prompts/confirm_expunge", E_GCONF_MAP_BOOL }, + { "UseDefaultReminder", "calendar/other/use_default_reminder", E_GCONF_MAP_BOOL }, + { "DefaultReminderInterval", "calendar/other/default_reminder_interval", E_GCONF_MAP_INT }, + { "DefaultReminderUnits", "calendar/other/default_reminder_units", E_GCONF_MAP_STRING }, { 0 }, }; -static struct _gconf_map calendar_datenavigator_map[] = { +static e_gconf_map_t calendar_datenavigator_map[] = { /* /Calendar/DateNavigator */ - { "ShowWeekNumbers", "calendar/date_navigator/show_week_numbers", BMAP_BOOL }, + { "ShowWeekNumbers", "calendar/date_navigator/show_week_numbers", E_GCONF_MAP_BOOL }, { 0 }, }; -static struct _gconf_map calendar_alarmnotify_map[] = { +static e_gconf_map_t calendar_alarmnotify_map[] = { /* /Calendar/AlarmNotify */ - { "LastNotificationTime", "calendar/notify/last_notification_time", BMAP_INT }, - { "CalendarToLoad%i", "calendar/notify/calendars", BMAP_STRING|BMAP_LIST }, - { "BlessedProgram%i", "calendar/notify/programs", BMAP_STRING|BMAP_LIST }, + { "LastNotificationTime", "calendar/notify/last_notification_time", E_GCONF_MAP_INT }, + { "CalendarToLoad%i", "calendar/notify/calendars", E_GCONF_MAP_STRING|E_GCONF_MAP_LIST }, + { "BlessedProgram%i", "calendar/notify/programs", E_GCONF_MAP_STRING|E_GCONF_MAP_LIST }, { 0 }, }; -static struct _gconf_map general_map[] = { +static e_gconf_map_t general_map[] = { /* /General */ - { "CategoryMasterList", "general/category_master_list", BMAP_STRING } + { "CategoryMasterList", "general/category_master_list", E_GCONF_MAP_STRING } }; /* ********************************************************************** */ -static struct { - char *root; - struct _gconf_map *map; -} gconf_remap_list[] = { - { "/Mail/Accounts", mail_accounts_map }, - { "/Mail/Display", mail_display_map }, - { "/Mail/Format", mail_format_map }, - { "/Mail/Trash", mail_trash_map }, - { "/Mail/Prompts", mail_prompts_map }, - { "/Mail/Filters", mail_filters_map }, - { "/Mail/Notify", mail_notify_map }, - { "/Mail/Filesel", mail_filesel_map }, - { "/Mail/Composer", mail_composer_map }, - +e_gconf_map_list_t remap_list[] = { { "/Importer/Elm", importer_elm_map }, { "/Importer/Pine", importer_pine_map }, { "/Importer/Netscape", importer_netscape_map }, @@ -1410,492 +213,34 @@ static struct { { 0 }, }; -#define N_(x) x - -struct { - char *label; - char *colour; -} label_default[5] = { - { N_("Important"), "#ff0000" }, /* red */ - { N_("Work"), "#ff8c00" }, /* orange */ - { N_("Personal"), "#008b00" }, /* forest green */ - { N_("To Do"), "#0000ff" }, /* blue */ - { N_("Later"), "#8b008b" } /* magenta */ -}; - -/* remaps mail config from bconf to gconf */ -static int import_bonobo_config(xmlDocPtr config_doc, GConfClient *gconf) -{ - xmlNodePtr source; - int i, j, k; - struct _gconf_map *map; - char *path, *val, *tmp; - GSList *list, *l; - char buf[32]; - - /* process all flat config */ - for (i=0;gconf_remap_list[i].root;i++) { - d(printf("Path: %s\n", gconf_remap_list[i].root)); - source = lookup_bconf_path(config_doc, gconf_remap_list[i].root); - if (source == NULL) - continue; - map = gconf_remap_list[i].map; - for (j=0;map[j].from;j++) { - if (map[j].type & BMAP_LIST) { - /* collapse a multi-entry indexed field into a list */ - list = NULL; - k = 0; - do { - path = get_name(map[j].from, k); - val = lookup_bconf_value(source, path); - d(printf("finding path '%s' = '%s'\n", path, val)); - g_free(path); - if (val) { - switch(map[j].type & BMAP_MASK) { - case BMAP_BOOL: - case BMAP_INT: - list = g_slist_append(list, GINT_TO_POINTER(atoi(val))); - break; - case BMAP_STRING: - d(printf(" -> '%s'\n", hex_decode(val))); - list = g_slist_append(list, hex_decode(val)); - break; - } - xmlFree(val); - k++; - } - } while (val); - - if (list) { - const int gconf_type[] = { GCONF_VALUE_BOOL, GCONF_VALUE_BOOL, GCONF_VALUE_INT, GCONF_VALUE_STRING, GCONF_VALUE_STRING }; - - path = g_strdup_printf("/apps/evolution/%s", map[j].to); - gconf_client_set_list(gconf, path, gconf_type[map[j].type & BMAP_MASK], list, NULL); - g_free(path); - if ((map[j].type & BMAP_MASK) == BMAP_STRING) - g_slist_foreach(list, (GFunc)g_free, NULL); - g_slist_free(list); - } - - continue; - } else if (map[j].type == BMAP_ANYLIST) - val = NULL; - else { - val = lookup_bconf_value(source, map[j].from); - if (val == NULL) - 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 BMAP_BOOL: - gconf_client_set_bool(gconf, path, atoi(val), NULL); - break; - case BMAP_BOOLNOT: - gconf_client_set_bool(gconf, path, !atoi(val), NULL); - break; - case BMAP_INT: - gconf_client_set_int(gconf, path, atoi(val), NULL); - break; - case BMAP_STRING: - tmp = hex_decode(val); - gconf_client_set_string(gconf, path, tmp, NULL); - g_free(tmp); - break; - case BMAP_SIMPLESTRING: - gconf_client_set_string(gconf, path, val, NULL); - break; - case BMAP_FLOAT: - gconf_client_set_float(gconf, path, strtod(val, NULL), NULL); - break; - case BMAP_STRLIST:{ - char *v = 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 BMAP_ANYLIST:{ - xmlNodePtr node = source->children; - list = NULL; - - /* find the entry node */ - while (node) { - if (!strcmp(node->name, "entry")) { - int found; - - tmp = xmlGetProp(node, "name"); - if (tmp) { - 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 BMAP_COLOUR: - sprintf(buf, "#%06x", atoi(val) & 0xffffff); - gconf_client_set_string(gconf, path, buf, NULL); - break; - } - /* FIXME: handle errors */ - g_free(path); - xmlFree(val); - } - } - - /* Labels: - label string + label colour as integer - -> label string:# colour as hex */ - source = lookup_bconf_path(config_doc, "/Mail/Labels"); - if (source) { - list = NULL; - for (i=0;i<5;i++) { - char labx[16], colx[16]; - char *lab, *col; - - sprintf(labx, "label_%d", i); - sprintf(colx, "color_%d", i); - lab = lookup_string(source, labx, NULL); - col = lookup_bconf_value(source, colx); - if (col) { - sprintf(colx, "#%06x", atoi(col) & 0xffffff); - xmlFree(col); - } else - strcpy(colx, label_default[i].colour); - val = g_strdup_printf("%s:%s", lab?lab:label_default[i].label, colx); - list = g_slist_append(list, val); - g_free(lab); - } - - gconf_client_set_list(gconf, "/apps/evolution/mail/labels", GCONF_VALUE_STRING, list, NULL); - while (list) { - l = list->next; - g_free(list->data); - g_slist_free_1(list); - list = l; - } - } else { - g_warning("could not find /Mail/Labels in old config database, skipping"); - } - - /* Accounts: The flat bonobo-config structure is remapped to a list of xml blobs. Upgrades as necessary */ - convert_xml_blob(gconf, config_doc, account_map, "/Mail/Accounts", "/apps/evolution/mail/accounts", "account", "uid"); - /* Same for signatures */ - convert_xml_blob(gconf, config_doc, signature_map, "/Mail/Signatures", "/apps/evolution/mail/signatures", "signature", NULL); - - /* My-Evolution folder lists */ - source = lookup_bconf_path(config_doc, "My-Evolution/Mail"); - if (source) { - char **t; - - list = NULL; - l = NULL; - - val = lookup_string(source, "display_folders-1.2", NULL); - /* FIXME: what needs upgrading here? Anything? */ - if (val == NULL) - val = lookup_string(source, "display_folders", NULL); - - if (val) { - t = g_strsplit (val, " !<-->! ", 8196); - for (i=0;t[i] && t[i+1];i+=2) { - list = g_slist_append(list, t[i]); - l = g_slist_append(l, t[i+1]); - d(printf(" [%d] = euri: '%s', puri: '%s'\n", i, t[i], t[i+1])); - } - if (list) { - gconf_client_set_list(gconf, "/apps/evolution/summary/mail/folder_evolution_uris", GCONF_VALUE_STRING, list, NULL); - g_slist_free(list); - } - if (l) { - gconf_client_set_list(gconf, "/apps/evolution/summary/mail/folder_physical_uris", GCONF_VALUE_STRING, l, NULL); - g_slist_free(l); - } - g_strfreev(t); - } - } - - return 0; -} - - -static int load_accounts_1_0(xmlDocPtr doc) -{ - xmlNodePtr source; - char *val, *tmp; - int count = 0, i; - char key[32]; - - source = lookup_bconf_path(doc, "/Mail/Accounts"); - if (source == NULL) - return 0; - - val = lookup_bconf_value(source, "num"); - if (val) { - count = atoi(val); - xmlFree(val); - } - - /* load account upgrade info for each account */ - for (i=0;i<count;i++) { - struct _account_info *ai; - char *rawuri; - - sprintf(key, "source_url_%d", i); - rawuri = lookup_bconf_value(source, key); - if (rawuri == NULL) - continue; - ai = g_malloc0(sizeof(*ai)); - ai->uri = hex_decode(rawuri); - ai->base_uri = get_base_uri(ai->uri); - sprintf(key, "account_name_%d", i); - ai->name = lookup_string(source, key, NULL); - - d(printf("load account '%s'\n", ai->uri)); - - if (!strncmp(ai->uri, "imap:", 5)) { - read_imap_storeinfo(ai); - } else if (!strncmp(ai->uri, "exchange:", 9)) { - xmlNodePtr node; - - d(printf(" upgrade exchange account\n")); - /* small hack, poke the source_url into the transport_url for exchanget: transports - - this will be picked up later in the conversion */ - sprintf(key, "transport_url_%d", i); - node = lookup_bconf_entry(source, key); - if (node - && (val = xmlGetProp(node, "value"))) { - tmp = hex_decode(val); - xmlFree(val); - if (strncmp(tmp, "exchanget:", 10) == 0) - xmlSetProp(node, "value", rawuri); - g_free(tmp); - } else { - d(printf(" couldn't find transport uri?\n")); - } - } - xmlFree(rawuri); - - g_hash_table_insert(accounts_1_0, ai->base_uri, ai); - if (ai->name) - g_hash_table_insert(accounts_name_1_0, ai->name, ai); - } - - return 0; -} - -/** - * e_config_upgrade: - * @edir: - * - * Upgrade evolution configuration from prior versions of evolution to - * the current one. - * - * No work is performed if the configuration version is up to date. - * - * The tracked version is upgraded to the latest even if no - * configuration upgrades are required for that version. - * - * Further information about how this is intended to work: - * - * There are 3 basic steps, numbered in the comments below. - * 1. Determine the current config verison - * 2. Upgrade to the current source version - * 3. Save the version number, as defined by CONF_MAJOR, CONF_MINOR, - * CONF_REVISION. These are all treated as integers, so 10 is - * greater than 9. - * - * 1 and 3 should not need changing. After an upgrade to 1.3.x and - * until the config system changes again (!), step one becomes - * trivial. Any changes to part 2 should be added to the end of the - * section, or as required. This allows for very fine-grained version - * upgrades, including pre-release and patch-level changes to fix - * config problems which may have lasted for a single version or - * patch, in which case CONF_REVISION can be bumped. - * - * At any time, the CONF_VERSION/MAJOR/REVISION can be increased to - * match the source release, even if no new configuration changes will - * be required from the previous version. This should be done at each - * release in case bugs in that configuration version are required to - * be fixed at any time in the future. - * - * Return value: -1 on an error. - **/ int e_config_upgrade(int major, int minor, int revision) { xmlDocPtr config_doc = NULL; - int i; - GConfClient *gconf; - int res = -1; - - /* 2. Now perform any upgrade duties */ - - d(printf("current config version is '%u.%u.%u'\n", major, minor, revision)); - - /* For 1.0.x we need to load the accounts first, as data it initialises is used elsewhere */ - if (major <=1 && minor < 2) { - char *xml_files[] = { "vfolders.xml", "filters.xml", "shortcuts.xml" }; - - /* load in 1.0 info */ - if (config_doc) { - accounts_1_0 = g_hash_table_new(g_str_hash, g_str_equal); - accounts_name_1_0 = g_hash_table_new(g_str_hash, g_str_equal); - load_accounts_1_0(config_doc); - } - - /* upgrade xml uri fields */ - for (i=0;i<sizeof(xml_files)/sizeof(xml_files[0]);i++) { - char *path; + char *conf_file; + struct stat st; + int res = 0; - path = g_build_filename(evolution_dir, xml_files[i], NULL); - if (upgrade_xml_file(path, upgrade_xml_1_0_rec) == -1) - g_warning("Could not upgrade xml file %s", xml_files[i]); - - g_free(path); - } - } + conf_file = g_build_filename (g_get_home_dir (), "evolution", "config.xmldb", NULL); + if (lstat (conf_file, &st) == 0 && S_ISREG (st.st_mode)) + config_doc = xmlParseFile (conf_file); + g_free (conf_file); + if (config_doc && major <=1 && minor < 3) { - /* move bonobo config to gconf */ - if (import_bonobo_config(config_doc, gconf) == -1) { - g_warning("Could not move config from bonobo-conf to gconf"); - goto error; - } - } - - if (major <=1 && minor <=3 && revision < 1) { - /* check for xml 1 encoding from version 1.2 upgrade or from a previous previous 1.3.0 upgrade */ - char *xml_files[] = { "vfolders.xml", "filters.xml", "shortcuts.xml"}; + GConfClient *gconf; - d(printf("Checking for xml1 format xml files\n")); - - for (i=0;i<sizeof(xml_files)/sizeof(xml_files[0]);i++) { - char *path; - - path = g_build_filename(evolution_dir, xml_files[i], NULL); - if (upgrade_xml_file(path, upgrade_xml_1_2_rec) == -1) - g_warning("Could not upgrade xml file %s", xml_files[i]); + /* move bonobo config to gconf */ + gconf = gconf_client_get_default (); - g_free(path); - } - } + res = e_bconf_import (gconf, config_doc, remap_list); + if (res != 0) + g_warning("Could not move config from bonobo-conf to gconf"); - res = 0; + g_object_unref (gconf); -error: - if (config_doc) xmlFreeDoc(config_doc); - - return res; -} - -gboolean -e_upgrade_detect_version (int *major, int *minor, int *revision) -{ - GConfClient *gconf; - xmlNodePtr source; - xmlDocPtr config_doc = NULL; - char *val; - struct stat st; - char *evolution_dir = g_build_filename(g_get_home_dir (), "evolution", NULL); - char *filename = g_build_filename(evolution_dir, "config.xmldb", NULL); - - - gconf = gconf_client_get_default(); - val = gconf_client_get_string(gconf, "/apps/evolution/version", NULL); - g_object_unref (gconf); - - if (val) { - /* Since 1.4.0 We've been keeping the version key in gconf */ - sscanf(val, "%u.%u.%u", major, minor, revision); - g_free(val); - } else if (lstat(filename, &st) != 0 || !S_ISDIR(st.st_mode)) { - /* If ~/evolution does not exit or is not a directory it must be a new installation */ - *major = 0; - *minor = 0; - *revision = 0; - } else { - char *filename = g_build_filename(g_get_home_dir (), "evolution", "config.xmldb", NULL); - char *tmp; - - if (lstat(filename, &st) == 0 - && S_ISREG(st.st_mode)) - config_doc = xmlParseFile (filename); - g_free(filename); - - tmp = NULL; - if ( config_doc - && (source = lookup_bconf_path(config_doc, "/Shell")) - && (tmp = lookup_bconf_value(source, "upgrade_from_1_0_to_1_2_performed")) - && tmp[0] == '1' ) { - *major = 1; - *minor = 2; - *revision = 0; - } else { - *major = 1; - *minor = 0; - *revision = 0; - } - if (tmp) - xmlFree(tmp); } - return TRUE; + return res; } - diff --git a/shell/e-config-upgrade.h b/shell/e-config-upgrade.h index f52801ce07..a11fe504e7 100644 --- a/shell/e-config-upgrade.h +++ b/shell/e-config-upgrade.h @@ -23,8 +23,6 @@ #ifndef _E_CONFIG_UPGRADE_H #define _E_CONFIG_UPGRADE_H -gboolean e_upgrade_detect_version (int *major, int *minor, int *revision); - -int e_config_upgrade(int major, int minor, int revision); +int e_config_upgrade (int major, int minor, int revision); #endif /* _E_CONFIG_UPGRADE_H */ diff --git a/shell/main.c b/shell/main.c index 5d7cebf635..6fc007c6e8 100644 --- a/shell/main.c +++ b/shell/main.c @@ -24,6 +24,7 @@ #include "e-util/e-dialog-utils.h" #include "e-util/e-gtk-utils.h" +#include "e-util/e-bconf-map.h" #include "e-icon-factory.h" #include "e-shell-constants.h" @@ -31,6 +32,10 @@ #include "e-shell.h" +#include <libxml/xmlmemory.h> +#include <libxml/parser.h> +#include <libxml/tree.h> + #include <gconf/gconf-client.h> #include <gtk/gtkalignment.h> @@ -338,21 +343,74 @@ new_window_created_callback (EShell *shell, #endif /* DEVELOPMENT_WARNING */ +static gboolean +detect_version (GConfClient *gconf, int *major, int *minor, int *revision) +{ + char *val, *evolution_dir, *filename; + struct stat st; + + evolution_dir = g_build_filename (g_get_home_dir (), "evolution", NULL); + filename = g_build_filename (evolution_dir, "config.xmldb", NULL); + + val = gconf_client_get_string(gconf, "/apps/evolution/version", NULL); + if (val) { + /* Since 1.4.0 We've been keeping the version key in gconf */ + sscanf(val, "%u.%u.%u", major, minor, revision); + g_free(val); + } else if (lstat (filename, &st) != 0 || !S_ISDIR (st.st_mode)) { + /* If ~/evolution does not exit or is not a directory it must be a new installation */ + *major = 0; + *minor = 0; + *revision = 0; + } else { + xmlDocPtr config_doc = NULL; + xmlNodePtr source; + char *tmp; + + if (lstat(filename, &st) == 0 + && S_ISREG(st.st_mode)) + config_doc = xmlParseFile (filename); + + tmp = NULL; + if (config_doc + && (source = e_bconf_get_path (config_doc, "/Shell")) + && (tmp = e_bconf_get_value (source, "upgrade_from_1_0_to_1_2_performed")) + && tmp[0] == '1' ) { + *major = 1; + *minor = 2; + *revision = 0; + } else { + *major = 1; + *minor = 0; + *revision = 0; + } + if (tmp) + xmlFree(tmp); + if (config_doc) + xmlFreeDoc (config_doc); + } + + g_free (evolution_dir); + g_free (filename); + + return TRUE; +} + static void attempt_upgrade (EShell *shell) { GConfClient *gconf_client; int major = 0, minor = 0, revision = 0; - if (!e_upgrade_detect_version (&major, &minor, &revision) + gconf_client = gconf_client_get_default (); + + if (!detect_version (gconf_client, &major, &minor, &revision) || !e_shell_attempt_upgrade (shell, major, minor, revision)) e_notice (NULL, GTK_MESSAGE_ERROR, _("Warning: Evolution could not upgrade all your data from version %d.%d.%d.\n" "The data hasn't been deleted, but it will not be seen by this version of Evolution.\n"), major, minor, revision); - - gconf_client = gconf_client_get_default (); gconf_client_set_string (gconf_client, "/apps/evolution/version", VERSION, NULL); g_object_unref (gconf_client); } |