4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
21 #include <glib/gstdio.h>
22 #include <camel/camel.h>
23 #include <libsoup/soup.h>
24 #include <gnome-keyring.h>
26 #include <libebackend/libebackend.h>
28 /* These constants are collected from various e-source-*.h files
29 * throughout evolution-data-server and known extension packages. */
30 #define E_SOURCE_GROUP_NAME "Data Source"
31 #define E_SOURCE_EXTENSION_CONTACTS_BACKEND "Contacts Backend"
32 #define E_SOURCE_EXTENSION_LDAP_BACKEND "LDAP Backend"
33 #define E_SOURCE_EXTENSION_LOCAL_BACKEND "Local Backend"
34 #define E_SOURCE_EXTENSION_VCF_BACKEND "VCF Backend"
35 #define E_SOURCE_EXTENSION_WEATHER_BACKEND "Weather Backend"
36 #define E_SOURCE_EXTENSION_WEBDAV_BACKEND "WebDAV Backend"
38 /* These constants are copied from e-source-password.c. */
39 #define KEYRING_ITEM_ATTRIBUTE_NAME "e-source-uid"
40 #define KEYRING_ITEM_DISPLAY_FORMAT "Evolution Data Source %s"
42 typedef struct _ParseData ParseData;
44 typedef void (*PropertyFunc) (ParseData *parse_data,
45 const gchar *property_name,
46 const gchar *property_value);
50 PARSE_TYPE_ADDRESSBOOK,
59 PARSE_STATE_IN_GCONF, /* GConf XML */
60 PARSE_STATE_IN_ACCOUNTS_ENTRY, /* GConf XML */
61 PARSE_STATE_IN_ACCOUNTS_VALUE, /* GConf XML */
62 PARSE_STATE_IN_SIGNATURES_ENTRY, /* GConf XML */
63 PARSE_STATE_IN_SIGNATURES_VALUE, /* GConf XML */
64 PARSE_STATE_IN_SOURCES_ENTRY, /* GConf XML */
65 PARSE_STATE_IN_SOURCES_VALUE, /* GConf XML */
67 PARSE_STATE_IN_ACCOUNT, /* EAccount XML */
68 PARSE_STATE_IN_IDENTITY, /* EAccount XML */
69 PARSE_STATE_IN_IDENTITY_NAME, /* EAccount XML */
70 PARSE_STATE_IN_IDENTITY_ADDR_SPEC, /* EAccount XML */
71 PARSE_STATE_IN_IDENTITY_REPLY_TO, /* EAccount XML */
72 PARSE_STATE_IN_IDENTITY_ORGANIZATION, /* EAccount XML */
73 PARSE_STATE_IN_IDENTITY_SIGNATURE, /* EAccount XML */
74 PARSE_STATE_IN_MAIL_SOURCE, /* EAccount XML */
75 PARSE_STATE_IN_MAIL_SOURCE_URL, /* EAccount XML */
76 PARSE_STATE_IN_MAIL_TRANSPORT, /* EAccount XML */
77 PARSE_STATE_IN_MAIL_TRANSPORT_URL, /* EAccount XML */
78 PARSE_STATE_IN_AUTO_CC, /* EAccount XML */
79 PARSE_STATE_IN_AUTO_CC_RECIPIENTS, /* EAccount XML */
80 PARSE_STATE_IN_AUTO_BCC, /* EAccount XML */
81 PARSE_STATE_IN_AUTO_BCC_RECIPIENTS, /* EAccount XML */
82 PARSE_STATE_IN_DRAFTS_FOLDER, /* EAccount XML */
83 PARSE_STATE_IN_SENT_FOLDER, /* EAccount XML */
84 PARSE_STATE_IN_RECEIPT_POLICY, /* EAccount XML */
85 PARSE_STATE_IN_PGP, /* EAccount XML */
86 PARSE_STATE_IN_PGP_KEY_ID, /* EAccount XML */
87 PARSE_STATE_IN_SMIME, /* EAccount XML */
88 PARSE_STATE_IN_SMIME_SIGN_KEY_ID, /* EAccount XML */
89 PARSE_STATE_IN_SMIME_ENCRYPT_KEY_ID, /* EAccount XML */
91 PARSE_STATE_IN_SIGNATURE, /* ESignature XML */
92 PARSE_STATE_IN_FILENAME, /* ESignature XML */
94 PARSE_STATE_IN_GROUP, /* ESource XML */
95 PARSE_STATE_IN_SOURCE, /* ESource XML */
96 PARSE_STATE_IN_PROPERTIES /* ESource XML */
103 /* Whether to skip writing a file
104 * for this account information. */
107 /* Set by <account>, <source> and <signature> tags. */
111 /* Set by <account>/<source> tags. */
115 /* Set by <identity> tags. */
116 GFile *identity_file;
117 GKeyFile *identity_key_file;
119 /* Set by <transport> tags. */
120 GFile *transport_file;
121 GKeyFile *transport_key_file;
123 /* Set by <account> tags. */
124 GFile *collection_file;
125 GKeyFile *collection_key_file;
127 /* Set by <signature> tags. */
128 GFile *signature_file;
131 /* Set by <group> tags. */
134 /* Set by <source> tags. */
137 PropertyFunc property_func;
140 static GnomeKeyringPasswordSchema schema = {
141 GNOME_KEYRING_ITEM_GENERIC_SECRET,
143 { KEYRING_ITEM_ATTRIBUTE_NAME,
144 GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
149 /* Forward Declarations */
150 void evolution_source_registry_migrate_sources (void);
153 parse_data_new (ParseType parse_type)
155 ParseData *parse_data;
157 parse_data = g_slice_new0 (ParseData);
158 parse_data->type = parse_type;
159 parse_data->state = PARSE_STATE_INITIAL;
165 parse_data_free (ParseData *parse_data)
167 /* Normally the allocated data in ParseData is freed and the
168 * pointers are cleared before we get here. But if an error
169 * occurred we may leave data behind. This cleans it up. */
171 if (parse_data->file != NULL)
172 g_object_unref (parse_data->file);
174 if (parse_data->key_file != NULL)
175 g_key_file_free (parse_data->key_file);
177 if (parse_data->identity_file != NULL)
178 g_object_unref (parse_data->identity_file);
180 if (parse_data->identity_key_file != NULL)
181 g_key_file_free (parse_data->identity_key_file);
183 if (parse_data->transport_file != NULL)
184 g_object_unref (parse_data->transport_file);
186 if (parse_data->transport_key_file != NULL)
187 g_key_file_free (parse_data->transport_key_file);
189 if (parse_data->collection_file != NULL)
190 g_object_unref (parse_data->collection_file);
192 if (parse_data->collection_key_file != NULL)
193 g_key_file_free (parse_data->collection_key_file);
195 if (parse_data->signature_file != NULL)
196 g_object_unref (parse_data->signature_file);
198 g_free (parse_data->base_uri);
199 g_free (parse_data->mangled_uri);
201 if (parse_data->soup_uri != NULL)
202 soup_uri_free (parse_data->soup_uri);
204 g_slice_free (ParseData, parse_data);
208 is_true (const gchar *string)
210 return (g_ascii_strcasecmp (string, "1") == 0) ||
211 (g_ascii_strcasecmp (string, "true") == 0);
215 is_false (const gchar *string)
217 return (g_ascii_strcasecmp (string, "0") == 0) ||
218 (g_ascii_strcasecmp (string, "false") == 0);
222 base_uri_is_groupware (const gchar *base_uri)
224 /* Well-known scheme names from various groupware packages. */
226 /* We use a limited string comparsion here because the
227 * base_uri string may be 'scheme://' or just 'scheme'. */
229 g_return_val_if_fail (base_uri != NULL, FALSE);
231 if (g_ascii_strncasecmp (base_uri, "ews", 3) == 0)
234 if (g_ascii_strncasecmp (base_uri, "exchange", 8) == 0)
237 if (g_ascii_strncasecmp (base_uri, "groupwise", 9) == 0)
240 if (g_ascii_strncasecmp (base_uri, "kolab", 5) == 0)
243 if (g_ascii_strncasecmp (base_uri, "mapi", 4) == 0)
250 migrate_keyring_entry (const gchar *uid,
253 const gchar *protocol)
255 GnomeKeyringAttributeList *attributes;
256 GList *found_list = NULL;
259 /* This is a best-effort routine, so we don't really care about
260 * errors. We leave the old keyring entry in place since it may
261 * be reused for address book or calendar migration. */
263 display_name = g_strdup_printf (KEYRING_ITEM_DISPLAY_FORMAT, uid);
265 attributes = gnome_keyring_attribute_list_new ();
267 gnome_keyring_attribute_list_append_string (
268 attributes, "application", "Evolution");
270 gnome_keyring_attribute_list_append_string (
271 attributes, "user", user);
273 gnome_keyring_attribute_list_append_string (
274 attributes, "server", server);
275 if (protocol != NULL)
276 gnome_keyring_attribute_list_append_string (
277 attributes, "protocol", protocol);
279 gnome_keyring_find_items_sync (
280 GNOME_KEYRING_ITEM_NETWORK_PASSWORD, attributes, &found_list);
282 /* Pick the first match we find. */
283 if (found_list != NULL) {
284 GnomeKeyringFound *found = found_list->data;
287 g_return_if_fail (found->secret != NULL);
289 gnome_keyring_store_password_sync (
290 &schema, GNOME_KEYRING_DEFAULT, display_name,
291 found->secret, KEYRING_ITEM_ATTRIBUTE_NAME, uid, NULL);
294 gnome_keyring_attribute_list_free (attributes);
295 gnome_keyring_found_list_free (found_list);
297 g_free (display_name);
301 migrate_parse_commit_changes (ParseType parse_type,
304 const gchar *mangled_uri,
307 const gchar *data_dir;
308 const gchar *cache_dir;
309 const gchar *component;
310 gchar *old_directory;
311 gchar *new_directory;
316 gboolean old_directory_exists;
317 gboolean new_directory_exists;
319 data_dir = e_get_user_data_dir ();
320 cache_dir = e_get_user_cache_dir ();
322 uid = e_server_side_source_uid_from_file (file, error);
327 g_print (" * Source: %s\n", uid);
329 g_print (" Writing key file...\n");
331 /* Save the key file contents to disk. */
332 contents = g_key_file_to_data (key_file, &length, NULL);
333 success = g_file_replace_contents (
334 file, contents, length, NULL, FALSE,
335 G_FILE_CREATE_PRIVATE, NULL, NULL, error);
341 /* Rename the source's local cache directory from its mangled
342 * URI to its UID. The key file's basename contains the UID.
343 * All source types but "local" should have cache directories. */
345 /* Mail cache directories already use UIDs. */
346 switch (parse_type) {
347 case PARSE_TYPE_ADDRESSBOOK:
348 component = "addressbook";
350 case PARSE_TYPE_CALENDAR:
351 component = "calendar";
353 case PARSE_TYPE_TASKS:
356 case PARSE_TYPE_MEMOS:
363 g_assert (mangled_uri != NULL);
365 old_directory = g_build_filename (
366 cache_dir, component, mangled_uri, NULL);
368 new_directory = g_build_filename (
369 cache_dir, component, uid, NULL);
371 old_directory_exists = g_file_test (old_directory, G_FILE_TEST_EXISTS);
372 new_directory_exists = g_file_test (new_directory, G_FILE_TEST_EXISTS);
375 " Checking for old cache dir '%s'... %s\n",
377 old_directory_exists ? "found" : "not found");
379 if (old_directory_exists) {
381 " Checking for new cache dir '%s'... %s\n",
383 new_directory_exists ? "found" : "not found");
385 if (new_directory_exists)
386 g_print (" Skipping cache directory rename.\n");
388 g_print (" Renaming old cache directory...\n");
389 if (g_rename (old_directory, new_directory) < 0) {
392 g_file_error_from_errno (errno),
393 "%s", g_strerror (errno));
399 g_free (old_directory);
400 g_free (new_directory);
405 /* Rename the source's local data directory from its mangled
406 * URI to its UID. The key file's basename contains the UID.
407 * Only "local" sources have local data directores. */
409 old_directory = g_build_filename (
410 data_dir, component, mangled_uri, NULL);
412 new_directory = g_build_filename (
413 data_dir, component, uid, NULL);
415 old_directory_exists = g_file_test (old_directory, G_FILE_TEST_EXISTS);
416 new_directory_exists = g_file_test (new_directory, G_FILE_TEST_EXISTS);
419 " Checking for old data dir '%s'... %s\n",
421 old_directory_exists ? "found" : "not found");
423 if (old_directory_exists) {
425 " Checking for new data dir '%s'... %s\n",
427 new_directory_exists ? "found" : "not found");
429 if (new_directory_exists)
430 g_print (" Skipping data directory rename.\n");
432 g_print (" Renaming old data directory...\n");
433 if (g_rename (old_directory, new_directory) < 0) {
436 g_file_error_from_errno (errno),
437 "%s", g_strerror (errno));
443 g_free (old_directory);
444 g_free (new_directory);
453 migrate_setup_collection (ParseData *parse_data,
456 gchar *collection_uid;
460 g_return_if_fail (parse_data->key_file != NULL);
461 g_return_if_fail (parse_data->identity_key_file != NULL);
462 g_return_if_fail (parse_data->transport_key_file != NULL);
464 parse_data->collection_file = e_server_side_source_new_user_file (NULL);
465 parse_data->collection_key_file = g_key_file_new ();
467 collection_uid = e_server_side_source_uid_from_file (
468 parse_data->collection_file, NULL);
470 /* Copy the display name from the mail account source. */
472 display_name = g_key_file_get_string (
473 parse_data->key_file,
474 E_SOURCE_GROUP_NAME, "DisplayName", NULL);
476 g_key_file_set_string (
477 parse_data->collection_key_file,
478 E_SOURCE_GROUP_NAME, "DisplayName", display_name);
480 /* Copy the enabled state from the mail account source. */
482 enabled = g_key_file_get_boolean (
483 parse_data->key_file,
484 E_SOURCE_GROUP_NAME, "Enabled", NULL);
486 g_key_file_set_boolean (
487 parse_data->collection_key_file,
488 E_SOURCE_GROUP_NAME, "Enabled", enabled);
490 /* Collection sources are always top-level sources. */
492 g_key_file_set_string (
493 parse_data->collection_key_file,
494 E_SOURCE_GROUP_NAME, "Parent", "");
496 /* Collection backend name should match the CamelURL protocol. */
498 g_key_file_set_string (
499 parse_data->collection_key_file,
500 E_SOURCE_EXTENSION_COLLECTION,
501 "BackendName", url->protocol);
503 g_key_file_set_boolean (
504 parse_data->collection_key_file,
505 E_SOURCE_EXTENSION_COLLECTION,
506 "CalendarEnabled", TRUE);
508 g_key_file_set_boolean (
509 parse_data->collection_key_file,
510 E_SOURCE_EXTENSION_COLLECTION,
511 "ContactsEnabled", TRUE);
513 g_key_file_set_boolean (
514 parse_data->collection_key_file,
515 E_SOURCE_EXTENSION_COLLECTION,
516 "MailEnabled", TRUE);
518 /* Enable all mail sources since we set "MailEnabled=true" above. */
520 g_key_file_set_boolean (
521 parse_data->key_file,
522 E_SOURCE_GROUP_NAME, "Enabled", TRUE);
524 g_key_file_set_boolean (
525 parse_data->identity_key_file,
526 E_SOURCE_GROUP_NAME, "Enabled", TRUE);
528 g_key_file_set_boolean (
529 parse_data->transport_key_file,
530 E_SOURCE_GROUP_NAME, "Enabled", TRUE);
532 /* The other mail sources are children of the collection source. */
534 g_key_file_set_string (
535 parse_data->key_file,
537 "Parent", collection_uid);
539 g_key_file_set_string (
540 parse_data->identity_key_file,
542 "Parent", collection_uid);
544 g_key_file_set_string (
545 parse_data->transport_key_file,
547 "Parent", collection_uid);
549 /* The collection identity has to be determined case-by-case.
550 * Some are based on user name, some are based on email address. */
552 if (g_strcmp0 (url->protocol, "ews") == 0)
553 g_key_file_set_string (
554 parse_data->collection_key_file,
555 E_SOURCE_EXTENSION_COLLECTION,
556 "Identity", url->user);
558 g_free (collection_uid);
559 g_free (display_name);
563 migrate_parse_account (ParseData *parse_data,
564 const gchar *element_name,
565 const gchar **attribute_names,
566 const gchar **attribute_values,
572 gchar *transport_uid;
576 success = g_markup_collect_attributes (
581 G_MARKUP_COLLECT_STRING,
583 G_MARKUP_COLLECT_STRING,
585 G_MARKUP_COLLECT_BOOLEAN,
587 G_MARKUP_COLLECT_INVALID);
592 parse_data->file = e_server_side_source_new_user_file (uid);
594 /* If the file already exists, skip this source. It may be that we
595 * already migrated it, in which case we don't want to overwrite it. */
596 if (g_file_query_exists (parse_data->file, NULL))
599 parse_data->key_file = g_key_file_new ();
601 parse_data->identity_file = e_server_side_source_new_user_file (NULL);
602 parse_data->identity_key_file = g_key_file_new ();
604 parse_data->transport_file = e_server_side_source_new_user_file (NULL);
605 parse_data->transport_key_file = g_key_file_new ();
607 identity_uid = e_server_side_source_uid_from_file (
608 parse_data->identity_file, NULL);
610 transport_uid = e_server_side_source_uid_from_file (
611 parse_data->transport_file, NULL);
613 g_key_file_set_string (
614 parse_data->key_file,
616 "DisplayName", name);
618 g_key_file_set_boolean (
619 parse_data->key_file,
623 /* Mail account source references the identity source. */
624 g_key_file_set_string (
625 parse_data->key_file,
626 E_SOURCE_EXTENSION_MAIL_ACCOUNT,
627 "IdentityUid", identity_uid);
629 /* Mail account source references the transport source. */
630 g_key_file_set_string (
631 parse_data->identity_key_file,
632 E_SOURCE_EXTENSION_MAIL_SUBMISSION,
633 "TransportUid", transport_uid);
635 /* Identity source gets the same display name. */
636 g_key_file_set_string (
637 parse_data->identity_key_file,
639 "DisplayName", name);
641 /* Identity source is a child of the mail account. */
642 g_key_file_set_string (
643 parse_data->identity_key_file,
647 /* Transport source gets the same display name. */
648 g_key_file_set_string (
649 parse_data->transport_key_file,
651 "DisplayName", name);
653 /* Transport source is a child of the mail account. */
654 g_key_file_set_string (
655 parse_data->transport_key_file,
659 g_free (identity_uid);
660 g_free (transport_uid);
664 migrate_parse_pgp (ParseData *parse_data,
665 const gchar *element_name,
666 const gchar **attribute_names,
667 const gchar **attribute_values,
670 const gchar *hash_algo;
671 gboolean always_sign;
672 gboolean always_trust;
673 gboolean encrypt_to_self;
674 gboolean no_imip_sign;
677 success = g_markup_collect_attributes (
682 G_MARKUP_COLLECT_BOOLEAN,
683 "always-sign", &always_sign,
684 G_MARKUP_COLLECT_BOOLEAN,
685 "always-trust", &always_trust,
686 G_MARKUP_COLLECT_BOOLEAN,
687 "encrypt-to-self", &encrypt_to_self,
688 G_MARKUP_COLLECT_BOOLEAN,
689 "no-imip-sign", &no_imip_sign,
690 G_MARKUP_COLLECT_STRING |
691 G_MARKUP_COLLECT_OPTIONAL,
692 "hash-algo", &hash_algo,
693 G_MARKUP_COLLECT_INVALID);
698 g_key_file_set_boolean (
699 parse_data->identity_key_file,
700 E_SOURCE_EXTENSION_OPENPGP,
701 "AlwaysSign", always_sign);
703 g_key_file_set_boolean (
704 parse_data->identity_key_file,
705 E_SOURCE_EXTENSION_OPENPGP,
706 "AlwaysTrust", always_trust);
708 g_key_file_set_boolean (
709 parse_data->identity_key_file,
710 E_SOURCE_EXTENSION_OPENPGP,
711 "EncryptToSelf", encrypt_to_self);
713 if (hash_algo != NULL && *hash_algo != '\0')
714 g_key_file_set_string (
715 parse_data->identity_key_file,
716 E_SOURCE_EXTENSION_OPENPGP,
717 "SigningAlgorithm", hash_algo);
719 /* XXX Don't know why this is under the <pgp>
720 * element, it applies to S/MIME as well.
721 * Also note we're inverting the setting. */
722 g_key_file_set_boolean (
723 parse_data->identity_key_file,
724 E_SOURCE_EXTENSION_MAIL_COMPOSITION,
725 "SignImip", !no_imip_sign);
729 migrate_parse_recipients (ParseData *parse_data,
731 const gchar *recipients)
733 CamelAddress *address;
734 CamelInternetAddress *inet_address;
739 if (recipients == NULL || *recipients == '\0')
742 inet_address = camel_internet_address_new ();
743 address = CAMEL_ADDRESS (inet_address);
745 if (camel_address_decode (address, recipients) == -1)
748 length = camel_address_length (address);
749 string_list = g_new0 (gchar *, length + 1);
751 for (ii = 0; ii < length; ii++) {
752 const gchar *name, *addr;
754 if (!camel_internet_address_get (
755 inet_address, ii, &name, &addr))
758 string_list[index++] =
759 camel_internet_address_format_address (name, addr);
762 g_key_file_set_string_list (
763 parse_data->identity_key_file,
764 E_SOURCE_EXTENSION_MAIL_COMPOSITION, key,
765 (const gchar *const *) string_list, index);
767 g_strfreev (string_list);
770 g_object_unref (inet_address);
774 migrate_parse_smime (ParseData *parse_data,
775 const gchar *element_name,
776 const gchar **attribute_names,
777 const gchar **attribute_values,
780 const gchar *hash_algo;
781 gboolean encrypt_default;
782 gboolean encrypt_to_self;
783 gboolean sign_default;
786 success = g_markup_collect_attributes (
791 G_MARKUP_COLLECT_BOOLEAN,
792 "encrypt-default", &encrypt_default,
793 G_MARKUP_COLLECT_BOOLEAN,
794 "encrypt-to-self", &encrypt_to_self,
795 G_MARKUP_COLLECT_STRING |
796 G_MARKUP_COLLECT_OPTIONAL,
797 "hash-algo", &hash_algo,
798 G_MARKUP_COLLECT_BOOLEAN,
799 "sign-default", &sign_default,
800 G_MARKUP_COLLECT_INVALID);
805 g_key_file_set_boolean (
806 parse_data->identity_key_file,
807 E_SOURCE_EXTENSION_SMIME,
808 "EncryptByDefault", encrypt_default);
810 g_key_file_set_boolean (
811 parse_data->identity_key_file,
812 E_SOURCE_EXTENSION_SMIME,
813 "EncryptToSelf", encrypt_to_self);
815 if (hash_algo != NULL && *hash_algo != '\0')
816 g_key_file_set_string (
817 parse_data->identity_key_file,
818 E_SOURCE_EXTENSION_SMIME,
819 "SigningAlgorithm", hash_algo);
821 g_key_file_set_boolean (
822 parse_data->identity_key_file,
823 E_SOURCE_EXTENSION_SMIME,
824 "SignByDefault", sign_default);
828 migrate_parse_mail_source (ParseData *parse_data,
829 const gchar *element_name,
830 const gchar **attribute_names,
831 const gchar **attribute_values,
834 const gchar *auto_check_timeout;
835 glong interval_minutes = 0;
839 /* Disregard "keep-on-server" and "save-passwd" attributes. */
840 success = g_markup_collect_attributes (
845 G_MARKUP_COLLECT_BOOLEAN,
846 "auto-check", &auto_check,
847 G_MARKUP_COLLECT_STRING,
848 "auto-check-timeout", &auto_check_timeout,
849 G_MARKUP_COLLECT_BOOLEAN |
850 G_MARKUP_COLLECT_OPTIONAL,
851 "keep-on-server", NULL,
852 G_MARKUP_COLLECT_BOOLEAN |
853 G_MARKUP_COLLECT_OPTIONAL,
855 G_MARKUP_COLLECT_INVALID);
860 if (auto_check_timeout != NULL)
861 interval_minutes = strtol (auto_check_timeout, NULL, 10);
863 g_key_file_set_boolean (
864 parse_data->key_file,
865 E_SOURCE_EXTENSION_REFRESH,
866 "Enabled", auto_check);
868 if (interval_minutes > 0)
869 g_key_file_set_integer (
870 parse_data->key_file,
871 E_SOURCE_EXTENSION_REFRESH,
872 "IntervalMinutes", interval_minutes);
876 migrate_parse_url_rename_params (CamelURL *url)
878 /* This list includes known URL parameters from built-in providers
879 * in Camel, as well as from evolution-exchange/groupwise/mapi/ews.
880 * Add more as needed. */
882 const gchar *url_parameter;
883 const gchar *property_name;
884 } camel_url_conversion[] = {
885 { "account_uid", "account-uid" },
886 { "ad_auth", "gc-auth-method" },
887 { "ad_browse", "gc-allow-browse" },
888 { "ad_expand_groups", "gc-expand-groups" },
889 { "ad_limit", "gc-results-limit" },
890 { "ad_server", "gc-server-name" },
891 { "all_headers", "fetch-headers" },
892 { "basic_headers", "fetch-headers" },
893 { "cachedconn" "concurrent-connections" },
894 { "check_all", "check-all" },
895 { "check_lsub", "check-subscribed" },
896 { "command", "shell-command" },
897 { "delete_after", "delete-after-days" },
898 { "delete_expunged", "delete-expunged" },
899 { "disable_extensions", "disable-extensions" },
900 { "dotfolders", "use-dot-folders" },
901 { "filter", "filter-inbox" },
902 { "filter_junk", "filter-junk" },
903 { "filter_junk_inbox", "filter-junk-inbox" },
904 { "folder_hierarchy_relative", "folder-hierarchy-relative" },
905 { "imap_custom_headers", "fetch-headers-extra" },
906 { "keep_on_server", "keep-on-server" },
907 { "oab_offline", "oab-offline" },
908 { "oal_selected", "oal-selected" },
909 { "offline_sync", "stay-synchronized" },
910 { "override_namespace", "use-namespace" },
911 { "owa_path", "owa-path" },
912 { "owa_url", "owa-url" },
913 { "password_exp_warn_period", "password-exp-warn-period" },
914 { "real_junk_path", "real-junk-path" },
915 { "real_trash_path", "real-trash-path" },
916 { "show_short_notation", "short-folder-names" },
917 { "soap_port", "soap-port" },
918 { "ssl", "security-method" },
919 { "sync_offline", "stay-synchronized" },
920 { "use_command", "use-shell-command" },
921 { "use_idle", "use-idle" },
922 { "use_lsub", "use-subscriptions" },
923 { "use_qresync", "use-qresync" },
924 { "use_ssl", "security-method" },
925 { "xstatus", "use-xstatus-headers" }
929 const gchar *use_param;
932 for (ii = 0; ii < G_N_ELEMENTS (camel_url_conversion); ii++) {
936 key = camel_url_conversion[ii].url_parameter;
937 value = g_datalist_get_data (&url->params, key);
942 g_datalist_remove_no_notify (&url->params, key);
944 key = camel_url_conversion[ii].property_name;
946 /* Deal with a few special enum cases where
947 * the parameter value also needs renamed. */
949 if (strcmp (key, "all_headers") == 0) {
950 GEnumClass *enum_class;
951 GEnumValue *enum_value;
953 enum_class = g_type_class_ref (
954 CAMEL_TYPE_FETCH_HEADERS_TYPE);
955 enum_value = g_enum_get_value (
956 enum_class, CAMEL_FETCH_HEADERS_ALL);
957 if (enum_value != NULL) {
959 value = g_strdup (enum_value->value_nick);
961 g_warn_if_reached ();
962 g_type_class_unref (enum_class);
965 if (strcmp (key, "basic_headers") == 0) {
966 GEnumClass *enum_class;
967 GEnumValue *enum_value;
969 enum_class = g_type_class_ref (
970 CAMEL_TYPE_FETCH_HEADERS_TYPE);
971 enum_value = g_enum_get_value (
972 enum_class, CAMEL_FETCH_HEADERS_BASIC);
973 if (enum_value != NULL) {
975 value = g_strdup (enum_value->value_nick);
977 g_warn_if_reached ();
978 g_type_class_unref (enum_class);
981 if (strcmp (key, "imap_custom_headers") == 0)
982 g_strdelimit (value, " ", ',');
984 if (strcmp (key, "security-method") == 0) {
985 CamelNetworkSecurityMethod method;
986 GEnumClass *enum_class;
987 GEnumValue *enum_value;
989 if (strcmp (value, "always") == 0)
990 method = CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT;
991 else if (strcmp (value, "1") == 0)
992 method = CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT;
993 else if (strcmp (value, "when-possible") == 0)
994 method = CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT;
996 method = CAMEL_NETWORK_SECURITY_METHOD_NONE;
998 enum_class = g_type_class_ref (
999 CAMEL_TYPE_NETWORK_SECURITY_METHOD);
1000 enum_value = g_enum_get_value (enum_class, method);
1001 if (enum_value != NULL) {
1003 value = g_strdup (enum_value->value_nick);
1005 g_warn_if_reached ();
1006 g_type_class_unref (enum_class);
1009 g_datalist_set_data_full (&url->params, key, value, g_free);
1012 /* A few more adjustments...
1014 * These are all CAMEL_PROVIDER_CONF_CHECKSPIN settings. The spin
1015 * button value is bound to "param" and the checkbox state is bound
1016 * to "use-param". The "use-param" settings are new. If "param"
1017 * exists but no "use-param", then set "use-param" to "true". */
1019 param = g_datalist_get_data (&url->params, "gc-results-limit");
1020 use_param = g_datalist_get_data (&url->params, "use-gc-results-limit");
1021 if (param != NULL && *param != '\0' && use_param == NULL) {
1022 g_datalist_set_data_full (
1023 &url->params, "use-gc-results-limit",
1024 g_strdup ("true"), (GDestroyNotify) g_free);
1027 param = g_datalist_get_data (&url->params, "kerberos");
1028 if (g_strcmp0 (param, "required") == 0) {
1029 g_datalist_set_data_full (
1030 &url->params, "kerberos",
1031 g_strdup ("true"), (GDestroyNotify) g_free);
1034 param = g_datalist_get_data (
1035 &url->params, "password-exp-warn-period");
1036 use_param = g_datalist_get_data (
1037 &url->params, "use-password-exp-warn-period");
1038 if (param != NULL && *param != '\0' && use_param == NULL) {
1039 g_datalist_set_data_full (
1040 &url->params, "use-password-exp-warn-period",
1041 g_strdup ("true"), (GDestroyNotify) g_free);
1044 param = g_datalist_get_data (&url->params, "real-junk-path");
1045 use_param = g_datalist_get_data (&url->params, "use-real-junk-path");
1046 if (param != NULL && *param != '\0' && use_param == NULL) {
1047 g_datalist_set_data_full (
1048 &url->params, "use-real-junk-path",
1049 g_strdup ("true"), (GDestroyNotify) g_free);
1052 param = g_datalist_get_data (&url->params, "real-trash-path");
1053 use_param = g_datalist_get_data (&url->params, "use-real-trash-path");
1054 if (param != NULL && *param != '\0' && use_param == NULL) {
1055 g_datalist_set_data_full (
1056 &url->params, "use-real-trash-path",
1057 g_strdup ("true"), (GDestroyNotify) g_free);
1060 /* Remove an empty "namespace" parameter (if present) to avoid
1061 * it being converted to "true" in migrate_parse_url_foreach(). */
1062 param = g_datalist_get_data (&url->params, "namespace");
1063 if (param != NULL && *param == '\0')
1064 g_datalist_remove_data (&url->params, "namespace");
1068 migrate_parse_url_foreach (GQuark key_id,
1072 const gchar *param_name;
1077 const gchar *group_name;
1078 } *foreach_data = user_data;
1080 g_return_if_fail (value != NULL);
1082 param_name = g_quark_to_string (key_id);
1083 key = e_source_parameter_to_key (param_name);
1085 /* If the value is empty, then the mere
1086 * presence of the parameter implies TRUE. */
1090 g_key_file_set_string (
1091 foreach_data->key_file,
1092 foreach_data->group_name,
1097 migrate_parse_url (ParseData *parse_data,
1100 const gchar *group_name,
1101 const gchar *url_string,
1105 GKeyFile *backend_key_file;
1106 GFile *backend_file;
1108 gboolean setup_collection;
1113 const gchar *group_name;
1116 url = camel_url_new (url_string, error);
1117 if (url == NULL || url->protocol == NULL)
1120 /* Rename URL params as necessary to match
1121 * their ESourceExtension property names. */
1122 migrate_parse_url_rename_params (url);
1125 (key_file == parse_data->key_file) &&
1126 base_uri_is_groupware (url->protocol);
1128 if (setup_collection)
1129 migrate_setup_collection (parse_data, url);
1131 /* Store backend settings in the collection GKeyFile, if one is
1132 * defined. Otherwise store them in the GKeyFile we were passed.
1133 * Same goes for the keyring entry, which uses the GFile. */
1134 if (parse_data->collection_key_file != NULL) {
1135 backend_key_file = parse_data->collection_key_file;
1136 backend_file = parse_data->collection_file;
1138 backend_key_file = key_file;
1139 backend_file = file;
1142 /* This is not a backend setting. */
1143 g_key_file_set_string (
1144 key_file, group_name,
1145 "BackendName", url->protocol);
1147 /* Set authentication details. */
1149 if (url->host != NULL)
1150 g_key_file_set_string (
1152 E_SOURCE_EXTENSION_AUTHENTICATION,
1155 if (url->authmech != NULL)
1156 g_key_file_set_string (
1158 E_SOURCE_EXTENSION_AUTHENTICATION,
1159 "Method", url->authmech);
1162 g_key_file_set_integer (
1164 E_SOURCE_EXTENSION_AUTHENTICATION,
1167 if (url->user != NULL)
1168 g_key_file_set_string (
1170 E_SOURCE_EXTENSION_AUTHENTICATION,
1173 /* Pick out particular URL parameters we know about. */
1175 /* If set, this should be "true" or "false",
1176 * but we'll just write it like it's a string. */
1177 value = g_datalist_get_data (&url->params, "stay-synchronized");
1179 g_key_file_set_string (
1181 E_SOURCE_EXTENSION_OFFLINE,
1182 "StaySynchronized", value);
1183 g_datalist_set_data (&url->params, "stay-synchronized", NULL);
1185 value = g_datalist_get_data (&url->params, "security-method");
1187 g_key_file_set_string (
1189 E_SOURCE_EXTENSION_SECURITY,
1191 g_datalist_set_data (&url->params, "security-method", NULL);
1193 /* If we see a "goa-account-id" parameter, skip the entire
1194 * account and let the online-accounts module recreate it. */
1195 value = g_datalist_get_data (&url->params, "goa-account-id");
1196 if (value != NULL && *value != '\0')
1197 parse_data->skip = TRUE;
1199 /* The rest of the URL parameters go in the backend group. */
1201 group_name = e_source_camel_get_extension_name (url->protocol);
1203 foreach_data.key_file = backend_key_file;
1204 foreach_data.group_name = group_name;
1206 g_datalist_foreach (
1207 &url->params, (GDataForeachFunc)
1208 migrate_parse_url_foreach, &foreach_data);
1210 /* Local providers store their "path" as the url->path */
1211 if (g_strcmp0 (url->protocol, "mh") == 0 ||
1212 g_strcmp0 (url->protocol, "mbox") == 0 ||
1213 g_strcmp0 (url->protocol, "maildir") == 0 ||
1214 g_strcmp0 (url->protocol, "spool") == 0 ||
1215 g_strcmp0 (url->protocol, "spooldir") == 0)
1216 g_key_file_set_string (
1221 uid = e_server_side_source_uid_from_file (backend_file, error);
1224 migrate_keyring_entry (
1225 uid, url->user, url->host, url->protocol);
1229 camel_url_free (url);
1233 migrate_parse_account_xml_start_element (GMarkupParseContext *context,
1234 const gchar *element_name,
1235 const gchar **attribute_names,
1236 const gchar **attribute_values,
1240 ParseData *parse_data = user_data;
1242 if (g_strcmp0 (element_name, "account") == 0) {
1243 if (parse_data->state != PARSE_STATE_IN_ACCOUNTS_VALUE)
1244 goto invalid_content;
1246 parse_data->state = PARSE_STATE_IN_ACCOUNT;
1248 migrate_parse_account (
1258 if (g_strcmp0 (element_name, "addr-spec") == 0) {
1259 if (parse_data->state != PARSE_STATE_IN_IDENTITY)
1260 goto invalid_content;
1262 parse_data->state = PARSE_STATE_IN_IDENTITY_ADDR_SPEC;
1267 if (g_strcmp0 (element_name, "auto-bcc") == 0) {
1268 if (parse_data->state != PARSE_STATE_IN_ACCOUNT)
1269 goto invalid_content;
1271 parse_data->state = PARSE_STATE_IN_AUTO_BCC;
1273 g_markup_collect_attributes (
1278 G_MARKUP_COLLECT_BOOLEAN,
1279 "always", &parse_data->auto_bcc,
1280 G_MARKUP_COLLECT_INVALID);
1285 if (g_strcmp0 (element_name, "auto-cc") == 0) {
1286 if (parse_data->state != PARSE_STATE_IN_ACCOUNT)
1287 goto invalid_content;
1289 parse_data->state = PARSE_STATE_IN_AUTO_CC;
1291 g_markup_collect_attributes (
1296 G_MARKUP_COLLECT_BOOLEAN,
1297 "always", &parse_data->auto_cc,
1298 G_MARKUP_COLLECT_INVALID);
1303 if (g_strcmp0 (element_name, "drafts-folder") == 0) {
1304 if (parse_data->state != PARSE_STATE_IN_ACCOUNT)
1305 goto invalid_content;
1307 parse_data->state = PARSE_STATE_IN_DRAFTS_FOLDER;
1312 if (g_strcmp0 (element_name, "encrypt-key-id") == 0) {
1313 if (parse_data->state != PARSE_STATE_IN_SMIME)
1314 goto invalid_content;
1316 parse_data->state = PARSE_STATE_IN_SMIME_ENCRYPT_KEY_ID;
1321 if (g_strcmp0 (element_name, "identity") == 0) {
1322 if (parse_data->state != PARSE_STATE_IN_ACCOUNT)
1323 goto invalid_content;
1325 parse_data->state = PARSE_STATE_IN_IDENTITY;
1330 if (g_strcmp0 (element_name, "key-id") == 0) {
1331 if (parse_data->state != PARSE_STATE_IN_PGP)
1332 goto invalid_content;
1334 parse_data->state = PARSE_STATE_IN_PGP_KEY_ID;
1339 if (g_strcmp0 (element_name, "name") == 0) {
1340 if (parse_data->state != PARSE_STATE_IN_IDENTITY)
1341 goto invalid_content;
1343 parse_data->state = PARSE_STATE_IN_IDENTITY_NAME;
1348 if (g_strcmp0 (element_name, "reply-to") == 0) {
1349 if (parse_data->state != PARSE_STATE_IN_IDENTITY)
1350 goto invalid_content;
1352 parse_data->state = PARSE_STATE_IN_IDENTITY_REPLY_TO;
1357 if (g_strcmp0 (element_name, "organization") == 0) {
1358 if (parse_data->state != PARSE_STATE_IN_IDENTITY)
1359 goto invalid_content;
1361 parse_data->state = PARSE_STATE_IN_IDENTITY_ORGANIZATION;
1366 if (g_strcmp0 (element_name, "pgp") == 0) {
1367 if (parse_data->state != PARSE_STATE_IN_ACCOUNT)
1368 goto invalid_content;
1370 parse_data->state = PARSE_STATE_IN_PGP;
1382 if (g_strcmp0 (element_name, "receipt-policy") == 0) {
1383 const gchar *policy;
1386 if (parse_data->state != PARSE_STATE_IN_ACCOUNT)
1387 goto invalid_content;
1389 parse_data->state = PARSE_STATE_IN_RECEIPT_POLICY;
1391 success = g_markup_collect_attributes (
1396 G_MARKUP_COLLECT_STRING,
1398 G_MARKUP_COLLECT_INVALID);
1400 /* The new enum strings match the old ones. */
1401 if (success && policy != NULL)
1402 g_key_file_set_string (
1403 parse_data->key_file,
1404 E_SOURCE_EXTENSION_MDN,
1405 "ResponsePolicy", policy);
1410 if (g_strcmp0 (element_name, "recipients") == 0) {
1411 if (parse_data->state == PARSE_STATE_IN_AUTO_BCC) {
1412 parse_data->state = PARSE_STATE_IN_AUTO_BCC_RECIPIENTS;
1416 if (parse_data->state == PARSE_STATE_IN_AUTO_CC) {
1417 parse_data->state = PARSE_STATE_IN_AUTO_CC_RECIPIENTS;
1421 goto invalid_content;
1424 if (g_strcmp0 (element_name, "sent-folder") == 0) {
1425 if (parse_data->state != PARSE_STATE_IN_ACCOUNT)
1426 goto invalid_content;
1428 parse_data->state = PARSE_STATE_IN_SENT_FOLDER;
1433 if (g_strcmp0 (element_name, "signature") == 0) {
1437 if (parse_data->state != PARSE_STATE_IN_IDENTITY)
1438 goto invalid_content;
1440 parse_data->state = PARSE_STATE_IN_IDENTITY_SIGNATURE;
1442 success = g_markup_collect_attributes (
1447 G_MARKUP_COLLECT_STRING,
1449 G_MARKUP_COLLECT_INVALID);
1451 if (success && uid != NULL)
1452 g_key_file_set_string (
1453 parse_data->identity_key_file,
1454 E_SOURCE_EXTENSION_MAIL_IDENTITY,
1455 "SignatureUid", uid);
1460 if (g_strcmp0 (element_name, "sign-key-id") == 0) {
1461 if (parse_data->state != PARSE_STATE_IN_SMIME)
1462 goto invalid_content;
1464 parse_data->state = PARSE_STATE_IN_SMIME_SIGN_KEY_ID;
1469 if (g_strcmp0 (element_name, "smime") == 0) {
1470 if (parse_data->state != PARSE_STATE_IN_ACCOUNT)
1471 goto invalid_content;
1473 parse_data->state = PARSE_STATE_IN_SMIME;
1475 migrate_parse_smime (
1485 if (g_strcmp0 (element_name, "source") == 0) {
1486 if (parse_data->state != PARSE_STATE_IN_ACCOUNT)
1487 goto invalid_content;
1489 parse_data->state = PARSE_STATE_IN_MAIL_SOURCE;
1491 migrate_parse_mail_source (
1501 if (g_strcmp0 (element_name, "transport") == 0) {
1502 if (parse_data->state != PARSE_STATE_IN_ACCOUNT)
1503 goto invalid_content;
1505 parse_data->state = PARSE_STATE_IN_MAIL_TRANSPORT;
1510 if (g_strcmp0 (element_name, "url") == 0) {
1511 if (parse_data->state == PARSE_STATE_IN_MAIL_SOURCE) {
1512 parse_data->state = PARSE_STATE_IN_MAIL_SOURCE_URL;
1516 if (parse_data->state == PARSE_STATE_IN_MAIL_TRANSPORT) {
1517 parse_data->state = PARSE_STATE_IN_MAIL_TRANSPORT_URL;
1521 goto invalid_content;
1525 error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
1526 "Unknown element <%s>", element_name);
1533 error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
1534 "Element <%s> at unexpected location", element_name);
1538 migrate_parse_account_xml_end_element (GMarkupParseContext *context,
1539 const gchar *element_name,
1543 ParseData *parse_data = user_data;
1545 if (g_strcmp0 (element_name, "account") == 0) {
1546 if (parse_data->state == PARSE_STATE_IN_ACCOUNT) {
1547 parse_data->state = PARSE_STATE_IN_ACCOUNTS_VALUE;
1549 /* Clean up <account> tag data. */
1551 /* The key file will be NULL if we decided to skip it.
1552 * e.g. A file with the same UID may already exist. */
1553 if (parse_data->key_file != NULL) {
1554 GError *local_error = NULL;
1556 if (!parse_data->skip)
1557 migrate_parse_commit_changes (
1560 parse_data->key_file,
1561 NULL, &local_error);
1563 if (local_error != NULL) {
1566 local_error->message);
1567 g_error_free (local_error);
1570 g_key_file_free (parse_data->key_file);
1571 parse_data->key_file = NULL;
1574 /* Same deal for the identity key file. */
1575 if (parse_data->identity_key_file != NULL) {
1576 GError *local_error = NULL;
1578 if (!parse_data->skip)
1579 migrate_parse_commit_changes (
1581 parse_data->identity_file,
1582 parse_data->identity_key_file,
1583 NULL, &local_error);
1585 if (local_error != NULL) {
1588 local_error->message);
1589 g_error_free (local_error);
1592 g_key_file_free (parse_data->identity_key_file);
1593 parse_data->identity_key_file = NULL;
1596 /* Same deal for the transport key file. */
1597 if (parse_data->transport_key_file != NULL) {
1598 GError *local_error = NULL;
1600 if (!parse_data->skip)
1601 migrate_parse_commit_changes (
1603 parse_data->transport_file,
1604 parse_data->transport_key_file,
1605 NULL, &local_error);
1607 if (local_error != NULL) {
1610 local_error->message);
1611 g_error_free (local_error);
1614 g_key_file_free (parse_data->transport_key_file);
1615 parse_data->transport_key_file = NULL;
1618 /* The collection key file is optional anyway. */
1619 if (parse_data->collection_key_file != NULL) {
1620 GError *local_error = NULL;
1622 if (!parse_data->skip)
1623 migrate_parse_commit_changes (
1625 parse_data->collection_file,
1626 parse_data->collection_key_file,
1627 NULL, &local_error);
1629 if (local_error != NULL) {
1632 local_error->message);
1633 g_error_free (local_error);
1636 g_key_file_free (parse_data->collection_key_file);
1637 parse_data->collection_key_file = NULL;
1640 if (parse_data->file != NULL) {
1641 g_object_unref (parse_data->file);
1642 parse_data->file = NULL;
1645 if (parse_data->identity_file != NULL) {
1646 g_object_unref (parse_data->identity_file);
1647 parse_data->identity_file = NULL;
1650 if (parse_data->transport_file != NULL) {
1651 g_object_unref (parse_data->transport_file);
1652 parse_data->transport_file = NULL;
1655 if (parse_data->collection_file != NULL) {
1656 g_object_unref (parse_data->collection_file);
1657 parse_data->collection_file = NULL;
1660 parse_data->skip = FALSE;
1665 if (g_strcmp0 (element_name, "addr-spec") == 0) {
1666 if (parse_data->state == PARSE_STATE_IN_IDENTITY_ADDR_SPEC)
1667 parse_data->state = PARSE_STATE_IN_IDENTITY;
1671 if (g_strcmp0 (element_name, "auto-bcc") == 0) {
1672 if (parse_data->state == PARSE_STATE_IN_AUTO_BCC)
1673 parse_data->state = PARSE_STATE_IN_ACCOUNT;
1677 if (g_strcmp0 (element_name, "auto-cc") == 0) {
1678 if (parse_data->state == PARSE_STATE_IN_AUTO_CC)
1679 parse_data->state = PARSE_STATE_IN_ACCOUNT;
1683 if (g_strcmp0 (element_name, "drafts-folder") == 0) {
1684 if (parse_data->state == PARSE_STATE_IN_DRAFTS_FOLDER)
1685 parse_data->state = PARSE_STATE_IN_ACCOUNT;
1689 if (g_strcmp0 (element_name, "encrypt-key-id") == 0) {
1690 if (parse_data->state == PARSE_STATE_IN_SMIME_ENCRYPT_KEY_ID)
1691 parse_data->state = PARSE_STATE_IN_SMIME;
1695 if (g_strcmp0 (element_name, "identity") == 0) {
1696 if (parse_data->state == PARSE_STATE_IN_IDENTITY)
1697 parse_data->state = PARSE_STATE_IN_ACCOUNT;
1701 if (g_strcmp0 (element_name, "key-id") == 0) {
1702 if (parse_data->state == PARSE_STATE_IN_PGP_KEY_ID)
1703 parse_data->state = PARSE_STATE_IN_PGP;
1707 if (g_strcmp0 (element_name, "name") == 0) {
1708 if (parse_data->state == PARSE_STATE_IN_IDENTITY_NAME)
1709 parse_data->state = PARSE_STATE_IN_IDENTITY;
1713 if (g_strcmp0 (element_name, "organization") == 0) {
1714 if (parse_data->state == PARSE_STATE_IN_IDENTITY_ORGANIZATION)
1715 parse_data->state = PARSE_STATE_IN_IDENTITY;
1719 if (g_strcmp0 (element_name, "pgp") == 0) {
1720 if (parse_data->state == PARSE_STATE_IN_PGP)
1721 parse_data->state = PARSE_STATE_IN_ACCOUNT;
1725 if (g_strcmp0 (element_name, "receipt-policy") == 0) {
1726 if (parse_data->state == PARSE_STATE_IN_RECEIPT_POLICY)
1727 parse_data->state = PARSE_STATE_IN_ACCOUNT;
1731 if (g_strcmp0 (element_name, "recipients") == 0) {
1732 if (parse_data->state == PARSE_STATE_IN_AUTO_BCC_RECIPIENTS)
1733 parse_data->state = PARSE_STATE_IN_AUTO_BCC;
1734 if (parse_data->state == PARSE_STATE_IN_AUTO_CC_RECIPIENTS)
1735 parse_data->state = PARSE_STATE_IN_AUTO_CC;
1739 if (g_strcmp0 (element_name, "reply-to") == 0) {
1740 if (parse_data->state == PARSE_STATE_IN_IDENTITY_REPLY_TO)
1741 parse_data->state = PARSE_STATE_IN_IDENTITY;
1745 if (g_strcmp0 (element_name, "sent-folder") == 0) {
1746 if (parse_data->state == PARSE_STATE_IN_SENT_FOLDER)
1747 parse_data->state = PARSE_STATE_IN_ACCOUNT;
1751 if (g_strcmp0 (element_name, "signature") == 0) {
1752 if (parse_data->state == PARSE_STATE_IN_IDENTITY_SIGNATURE)
1753 parse_data->state = PARSE_STATE_IN_IDENTITY;
1757 if (g_strcmp0 (element_name, "sign-key-id") == 0) {
1758 if (parse_data->state == PARSE_STATE_IN_SMIME_SIGN_KEY_ID)
1759 parse_data->state = PARSE_STATE_IN_SMIME;
1763 if (g_strcmp0 (element_name, "smime") == 0) {
1764 if (parse_data->state == PARSE_STATE_IN_SMIME)
1765 parse_data->state = PARSE_STATE_IN_ACCOUNT;
1769 if (g_strcmp0 (element_name, "source") == 0) {
1770 if (parse_data->state == PARSE_STATE_IN_MAIL_SOURCE)
1771 parse_data->state = PARSE_STATE_IN_ACCOUNT;
1775 if (g_strcmp0 (element_name, "transport") == 0) {
1776 if (parse_data->state == PARSE_STATE_IN_MAIL_TRANSPORT)
1777 parse_data->state = PARSE_STATE_IN_ACCOUNT;
1781 if (g_strcmp0 (element_name, "url") == 0) {
1782 if (parse_data->state == PARSE_STATE_IN_MAIL_SOURCE_URL)
1783 parse_data->state = PARSE_STATE_IN_MAIL_SOURCE;
1784 if (parse_data->state == PARSE_STATE_IN_MAIL_TRANSPORT_URL)
1785 parse_data->state = PARSE_STATE_IN_MAIL_TRANSPORT;
1791 migrate_parse_account_xml_text (GMarkupParseContext *context,
1797 ParseData *parse_data = user_data;
1799 switch (parse_data->state) {
1800 case PARSE_STATE_IN_AUTO_BCC_RECIPIENTS:
1801 /* Disregard the recipient list if
1802 * we're not going to auto-BCC them. */
1803 if (parse_data->auto_bcc)
1804 migrate_parse_recipients (
1805 parse_data, "Bcc", text);
1808 case PARSE_STATE_IN_AUTO_CC_RECIPIENTS:
1809 /* Disregard the recipient list if
1810 * we're not going to auto-CC them. */
1811 if (parse_data->auto_cc)
1812 migrate_parse_recipients (
1813 parse_data, "Cc", text);
1816 case PARSE_STATE_IN_DRAFTS_FOLDER:
1817 g_key_file_set_string (
1818 parse_data->identity_key_file,
1819 E_SOURCE_EXTENSION_MAIL_COMPOSITION,
1820 "DraftsFolder", text);
1823 case PARSE_STATE_IN_SMIME_ENCRYPT_KEY_ID:
1824 g_key_file_set_string (
1825 parse_data->identity_key_file,
1826 E_SOURCE_EXTENSION_SMIME,
1827 "EncryptionCertificate", text);
1830 case PARSE_STATE_IN_IDENTITY_ADDR_SPEC:
1831 g_key_file_set_string (
1832 parse_data->identity_key_file,
1833 E_SOURCE_EXTENSION_MAIL_IDENTITY,
1837 case PARSE_STATE_IN_IDENTITY_NAME:
1838 g_key_file_set_string (
1839 parse_data->identity_key_file,
1840 E_SOURCE_EXTENSION_MAIL_IDENTITY,
1844 case PARSE_STATE_IN_IDENTITY_ORGANIZATION:
1845 g_key_file_set_string (
1846 parse_data->identity_key_file,
1847 E_SOURCE_EXTENSION_MAIL_IDENTITY,
1848 "Organization", text);
1851 case PARSE_STATE_IN_IDENTITY_REPLY_TO:
1852 g_key_file_set_string (
1853 parse_data->identity_key_file,
1854 E_SOURCE_EXTENSION_MAIL_IDENTITY,
1858 case PARSE_STATE_IN_MAIL_SOURCE_URL:
1861 parse_data->key_file,
1863 E_SOURCE_EXTENSION_MAIL_ACCOUNT,
1867 case PARSE_STATE_IN_MAIL_TRANSPORT_URL:
1870 parse_data->transport_key_file,
1871 parse_data->transport_file,
1872 E_SOURCE_EXTENSION_MAIL_TRANSPORT,
1876 case PARSE_STATE_IN_PGP_KEY_ID:
1877 g_key_file_set_string (
1878 parse_data->identity_key_file,
1879 E_SOURCE_EXTENSION_OPENPGP,
1883 case PARSE_STATE_IN_SENT_FOLDER:
1884 g_key_file_set_string (
1885 parse_data->identity_key_file,
1886 E_SOURCE_EXTENSION_MAIL_SUBMISSION,
1887 "SentFolder", text);
1890 case PARSE_STATE_IN_SMIME_SIGN_KEY_ID:
1891 g_key_file_set_string (
1892 parse_data->identity_key_file,
1893 E_SOURCE_EXTENSION_SMIME,
1894 "SigningCertificate", text);
1902 static GMarkupParser account_xml_parser = {
1903 migrate_parse_account_xml_start_element,
1904 migrate_parse_account_xml_end_element,
1905 migrate_parse_account_xml_text,
1906 NULL, /* passthrough */
1911 migrate_parse_signature (ParseData *parse_data,
1912 const gchar *element_name,
1913 const gchar **attribute_names,
1914 const gchar **attribute_values,
1919 const gchar *format;
1920 const gchar *config_dir;
1922 gchar *absolute_path;
1923 gboolean autogenerated;
1926 success = g_markup_collect_attributes (
1931 G_MARKUP_COLLECT_STRING,
1933 G_MARKUP_COLLECT_STRING,
1935 G_MARKUP_COLLECT_BOOLEAN,
1936 "auto", &autogenerated,
1937 G_MARKUP_COLLECT_STRING |
1938 G_MARKUP_COLLECT_OPTIONAL,
1940 G_MARKUP_COLLECT_INVALID);
1945 /* Skip the "autogenerated" signature. */
1949 parse_data->file = e_server_side_source_new_user_file (uid);
1951 config_dir = e_get_user_config_dir ();
1952 directory = g_build_filename (config_dir, "signatures", NULL);
1953 absolute_path = g_build_filename (directory, uid, NULL);
1954 parse_data->signature_file = g_file_new_for_path (absolute_path);
1955 g_mkdir_with_parents (directory, 0700);
1956 g_free (absolute_path);
1959 /* If the file already exists, skip this source. It may be that we
1960 * already migrated it, in which case we don't want to overwrite it. */
1961 if (g_file_query_exists (parse_data->file, NULL))
1964 parse_data->key_file = g_key_file_new ();
1966 g_key_file_set_string (
1967 parse_data->key_file,
1968 E_SOURCE_GROUP_NAME,
1969 "DisplayName", name);
1971 g_key_file_set_string (
1972 parse_data->key_file,
1973 E_SOURCE_EXTENSION_MAIL_SIGNATURE,
1974 "MimeType", format);
1978 migrate_parse_signature_xml_start_element (GMarkupParseContext *context,
1979 const gchar *element_name,
1980 const gchar **attribute_names,
1981 const gchar **attribute_values,
1985 ParseData *parse_data = user_data;
1987 if (g_strcmp0 (element_name, "filename") == 0) {
1988 if (parse_data->state != PARSE_STATE_IN_SIGNATURE)
1989 goto invalid_content;
1991 parse_data->state = PARSE_STATE_IN_FILENAME;
1993 g_markup_collect_attributes (
1998 G_MARKUP_COLLECT_BOOLEAN |
1999 G_MARKUP_COLLECT_OPTIONAL,
2000 "script", &parse_data->is_script,
2001 G_MARKUP_COLLECT_INVALID);
2006 if (g_strcmp0 (element_name, "signature") == 0) {
2007 if (parse_data->state != PARSE_STATE_IN_SIGNATURES_VALUE)
2008 goto invalid_content;
2010 parse_data->state = PARSE_STATE_IN_SIGNATURE;
2012 migrate_parse_signature (
2023 error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2024 "Unknown element <%s>", element_name);
2031 error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
2032 "Element <%s> at unexpected location", element_name);
2036 migrate_parse_signature_xml_end_element (GMarkupParseContext *context,
2037 const gchar *element_name,
2041 ParseData *parse_data = user_data;
2043 if (g_strcmp0 (element_name, "filename") == 0) {
2044 if (parse_data->state == PARSE_STATE_IN_FILENAME) {
2045 parse_data->state = PARSE_STATE_IN_SIGNATURE;
2051 if (g_strcmp0 (element_name, "signature") == 0) {
2052 if (parse_data->state == PARSE_STATE_IN_SIGNATURE) {
2053 parse_data->state = PARSE_STATE_IN_SIGNATURES_VALUE;
2055 /* Clean up <signature> tag data. */
2057 /* The key file will be NULL if we decided to skip it.
2058 * e.g. A file with the same UID may already exist. */
2059 if (parse_data->key_file != NULL) {
2060 GError *local_error = NULL;
2062 if (!parse_data->skip)
2063 migrate_parse_commit_changes (
2066 parse_data->key_file,
2067 NULL, &local_error);
2069 if (local_error != NULL) {
2072 local_error->message);
2073 g_error_free (local_error);
2076 g_key_file_free (parse_data->key_file);
2077 parse_data->key_file = NULL;
2080 if (parse_data->file != NULL) {
2081 g_object_unref (parse_data->file);
2082 parse_data->file = NULL;
2085 parse_data->skip = FALSE;
2093 migrate_parse_signature_xml_text (GMarkupParseContext *context,
2099 ParseData *parse_data = user_data;
2101 if (parse_data->state == PARSE_STATE_IN_FILENAME) {
2102 GFile *old_signature_file;
2103 GFile *new_signature_file;
2104 const gchar *data_dir;
2105 gchar *absolute_path;
2107 /* Note we're moving the signature files
2108 * from $XDG_DATA_HOME to $XDG_CONFIG_HOME. */
2109 data_dir = e_get_user_data_dir ();
2111 /* Text should be either an absolute file name
2112 * or a base file name with no path components. */
2113 if (g_path_is_absolute (text))
2114 absolute_path = g_strdup (text);
2116 absolute_path = g_build_filename (
2117 data_dir, "signatures", text, NULL);
2119 old_signature_file = g_file_new_for_path (absolute_path);
2120 new_signature_file = parse_data->signature_file;
2121 parse_data->signature_file = NULL;
2123 /* If the signature is a script, we symlink to it.
2124 * Otherwise we move and rename the regular file. */
2125 if (parse_data->is_script)
2126 g_file_make_symbolic_link (
2128 absolute_path, NULL, error);
2134 NULL, NULL, NULL, error);
2136 g_object_unref (old_signature_file);
2137 g_object_unref (new_signature_file);
2138 g_free (absolute_path);
2142 static GMarkupParser signature_xml_parser = {
2143 migrate_parse_signature_xml_start_element,
2144 migrate_parse_signature_xml_end_element,
2145 migrate_parse_signature_xml_text,
2146 NULL, /* passthrough */
2151 migrate_parse_local_calendar_property (ParseData *parse_data,
2152 const gchar *property_name,
2153 const gchar *property_value)
2155 if (g_strcmp0 (property_name, "custom-file") == 0) {
2158 /* Property value is a local filename. Convert it to a
2161 * Note: The key is named "CustomFile" instead of, say,
2162 * "CustomURI" because the corresponding ESourceExtension
2163 * property is a GFile. The fact that ESource saves GFile
2164 * properties as URI strings is an implementation detail. */
2165 uri = g_filename_to_uri (property_value, NULL, NULL);
2167 g_key_file_set_string (
2168 parse_data->key_file,
2169 E_SOURCE_EXTENSION_LOCAL_BACKEND,
2177 migrate_parse_local_source (ParseData *parse_data)
2179 if (parse_data->type != PARSE_TYPE_ADDRESSBOOK)
2180 parse_data->property_func =
2181 migrate_parse_local_calendar_property;
2183 /* Local ADDRESS BOOK Backend has no special properties to parse. */
2187 migrate_parse_caldav_property (ParseData *parse_data,
2188 const gchar *property_name,
2189 const gchar *property_value)
2191 if (g_strcmp0 (property_name, "autoschedule") == 0) {
2192 g_key_file_set_boolean (
2193 parse_data->key_file,
2194 E_SOURCE_EXTENSION_WEBDAV_BACKEND,
2195 "CalendarAutoSchedule",
2196 is_true (property_value));
2198 } else if (g_strcmp0 (property_name, "usermail") == 0) {
2199 g_key_file_set_string (
2200 parse_data->key_file,
2201 E_SOURCE_EXTENSION_WEBDAV_BACKEND,
2202 "EmailAddress", property_value);
2207 migrate_parse_caldav_source (ParseData *parse_data)
2209 if (parse_data->soup_uri->host != NULL)
2210 g_key_file_set_string (
2211 parse_data->key_file,
2212 E_SOURCE_EXTENSION_AUTHENTICATION,
2213 "Host", parse_data->soup_uri->host);
2215 /* We may override this later if we see an "ssl" property. */
2216 if (parse_data->soup_uri->port == 0)
2217 parse_data->soup_uri->port = 80;
2219 g_key_file_set_integer (
2220 parse_data->key_file,
2221 E_SOURCE_EXTENSION_AUTHENTICATION,
2222 "Port", parse_data->soup_uri->port);
2224 if (parse_data->soup_uri->user != NULL)
2225 g_key_file_set_string (
2226 parse_data->key_file,
2227 E_SOURCE_EXTENSION_AUTHENTICATION,
2228 "User", parse_data->soup_uri->user);
2230 if (parse_data->soup_uri->path != NULL)
2231 g_key_file_set_string (
2232 parse_data->key_file,
2233 E_SOURCE_EXTENSION_WEBDAV_BACKEND,
2234 "ResourcePath", parse_data->soup_uri->path);
2236 parse_data->property_func = migrate_parse_caldav_property;
2240 migrate_parse_google_calendar_property (ParseData *parse_data,
2241 const gchar *property_name,
2242 const gchar *property_value)
2244 if (g_strcmp0 (property_name, "username") == 0) {
2247 g_key_file_set_string (
2248 parse_data->key_file,
2249 E_SOURCE_EXTENSION_AUTHENTICATION,
2250 "User", property_value);
2252 path = g_strdup_printf (
2253 "/calendar/dav/%s/events", property_value);
2255 g_key_file_set_string (
2256 parse_data->key_file,
2257 E_SOURCE_EXTENSION_WEBDAV_BACKEND,
2258 "ResourcePath", path);
2265 migrate_parse_google_contacts_property (ParseData *parse_data,
2266 const gchar *property_name,
2267 const gchar *property_value)
2269 if (g_strcmp0 (property_name, "refresh-interval") == 0) {
2270 guint64 interval_seconds;
2273 g_ascii_strtoull (property_value, NULL, 10);
2275 if (interval_seconds >= 60) {
2276 g_key_file_set_boolean (
2277 parse_data->key_file,
2278 E_SOURCE_EXTENSION_REFRESH,
2280 g_key_file_set_uint64 (
2281 parse_data->key_file,
2282 E_SOURCE_EXTENSION_REFRESH,
2284 interval_seconds / 60);
2287 } else if (g_strcmp0 (property_name, "username") == 0) {
2288 g_key_file_set_string (
2289 parse_data->key_file,
2290 E_SOURCE_EXTENSION_AUTHENTICATION,
2291 "User", property_value);
2296 migrate_parse_google_source (ParseData *parse_data)
2298 if (parse_data->type == PARSE_TYPE_ADDRESSBOOK)
2299 parse_data->property_func =
2300 migrate_parse_google_contacts_property;
2303 g_key_file_set_string (
2304 parse_data->key_file,
2305 E_SOURCE_EXTENSION_AUTHENTICATION,
2306 "Host", "www.google.com");
2308 g_key_file_set_integer (
2309 parse_data->key_file,
2310 E_SOURCE_EXTENSION_AUTHENTICATION,
2313 g_key_file_set_string (
2314 parse_data->key_file,
2315 E_SOURCE_EXTENSION_SECURITY,
2318 parse_data->property_func =
2319 migrate_parse_google_calendar_property;
2324 migrate_parse_ldap_property (ParseData *parse_data,
2325 const gchar *property_name,
2326 const gchar *property_value)
2328 if (g_strcmp0 (property_name, "can-browse") == 0) {
2329 g_key_file_set_boolean (
2330 parse_data->key_file,
2331 E_SOURCE_EXTENSION_LDAP_BACKEND,
2333 is_true (property_value));
2335 /* This is an integer value, but we can use the string as is. */
2336 } else if (g_strcmp0 (property_name, "limit") == 0) {
2337 g_key_file_set_string (
2338 parse_data->key_file,
2339 E_SOURCE_EXTENSION_LDAP_BACKEND,
2340 "Limit", property_value);
2345 migrate_parse_ldap_source (ParseData *parse_data)
2347 if (parse_data->soup_uri->host != NULL)
2348 g_key_file_set_string (
2349 parse_data->key_file,
2350 E_SOURCE_EXTENSION_AUTHENTICATION,
2351 "Host", parse_data->soup_uri->host);
2353 if (parse_data->soup_uri->port != 0)
2354 g_key_file_set_integer (
2355 parse_data->key_file,
2356 E_SOURCE_EXTENSION_AUTHENTICATION,
2357 "Port", parse_data->soup_uri->port);
2359 if (parse_data->soup_uri->user != NULL)
2360 g_key_file_set_string (
2361 parse_data->key_file,
2362 E_SOURCE_EXTENSION_AUTHENTICATION,
2363 "User", parse_data->soup_uri->user);
2365 /* Skip the leading slash on the URI path to get the RootDn. */
2366 if (parse_data->soup_uri->path != NULL)
2367 g_key_file_set_string (
2368 parse_data->key_file,
2369 E_SOURCE_EXTENSION_LDAP_BACKEND,
2370 "RootDn", parse_data->soup_uri->path + 1);
2372 if (g_strcmp0 (parse_data->soup_uri->query, "?sub?") == 0)
2373 g_key_file_set_string (
2374 parse_data->key_file,
2375 E_SOURCE_EXTENSION_LDAP_BACKEND,
2376 "Scope", "subtree");
2378 if (g_strcmp0 (parse_data->soup_uri->query, "?one?") == 0)
2379 g_key_file_set_string (
2380 parse_data->key_file,
2381 E_SOURCE_EXTENSION_LDAP_BACKEND,
2382 "Scope", "onelevel");
2384 parse_data->property_func = migrate_parse_ldap_property;
2388 migrate_parse_vcf_source (ParseData *parse_data)
2390 if (parse_data->soup_uri->path != NULL)
2391 g_key_file_set_string (
2392 parse_data->key_file,
2393 E_SOURCE_EXTENSION_VCF_BACKEND,
2394 "Path", parse_data->soup_uri->path);
2396 /* VCF Backend has no special properties to parse. */
2400 migrate_parse_weather_property (ParseData *parse_data,
2401 const gchar *property_name,
2402 const gchar *property_value)
2404 /* XXX Temperature property was replaced by units... I think. */
2405 if (g_strcmp0 (property_name, "temperature") == 0) {
2408 metric = (g_strcmp0 (property_value, "fahrenheit") != 0);
2410 g_key_file_set_string (
2411 parse_data->key_file,
2412 E_SOURCE_EXTENSION_WEATHER_BACKEND,
2413 "Units", metric ? "metric" : "imperial");
2415 } else if (g_strcmp0 (property_name, "units") == 0) {
2418 metric = (g_strcmp0 (property_value, "metric") == 0);
2420 g_key_file_set_string (
2421 parse_data->key_file,
2422 E_SOURCE_EXTENSION_WEATHER_BACKEND,
2423 "Units", metric ? "metric" : "imperial");
2428 migrate_parse_weather_source (ParseData *parse_data)
2430 /* Oh man, we actually try to shove a weather location into
2431 * a URI! The station code winds up as the host component,
2432 * and the location name winds up as the path component. */
2433 if (parse_data->soup_uri->host != NULL) {
2436 if (parse_data->soup_uri->path != NULL)
2437 location = g_strconcat (
2438 parse_data->soup_uri->host,
2439 parse_data->soup_uri->path, NULL);
2441 location = g_strdup (parse_data->soup_uri->host);
2443 g_key_file_set_string (
2444 parse_data->key_file,
2445 E_SOURCE_EXTENSION_WEATHER_BACKEND,
2446 "Location", location);
2452 parse_data->property_func = migrate_parse_weather_property;
2456 migrate_parse_webcal_source (ParseData *parse_data)
2458 if (parse_data->soup_uri->host != NULL)
2459 g_key_file_set_string (
2460 parse_data->key_file,
2461 E_SOURCE_EXTENSION_AUTHENTICATION,
2462 "Host", parse_data->soup_uri->host);
2464 /* We may override this later if we see an "ssl" property. */
2465 if (parse_data->soup_uri->port == 0)
2466 parse_data->soup_uri->port = 80;
2468 g_key_file_set_integer (
2469 parse_data->key_file,
2470 E_SOURCE_EXTENSION_AUTHENTICATION,
2471 "Port", parse_data->soup_uri->port);
2473 if (parse_data->soup_uri->user != NULL)
2474 g_key_file_set_string (
2475 parse_data->key_file,
2476 E_SOURCE_EXTENSION_AUTHENTICATION,
2477 "User", parse_data->soup_uri->user);
2479 if (parse_data->soup_uri->path != NULL)
2480 g_key_file_set_string (
2481 parse_data->key_file,
2482 E_SOURCE_EXTENSION_WEBDAV_BACKEND,
2483 "ResourcePath", parse_data->soup_uri->path);
2485 /* Webcal Backend has no special properties to parse. */
2489 migrate_parse_webdav_property (ParseData *parse_data,
2490 const gchar *property_name,
2491 const gchar *property_value)
2493 if (g_strcmp0 (property_name, "avoid_ifmatch") == 0) {
2494 g_key_file_set_boolean (
2495 parse_data->key_file,
2496 E_SOURCE_EXTENSION_WEBDAV_BACKEND,
2498 is_true (property_value));
2503 migrate_parse_webdav_source (ParseData *parse_data)
2505 if (parse_data->soup_uri->host != NULL)
2506 g_key_file_set_string (
2507 parse_data->key_file,
2508 E_SOURCE_EXTENSION_AUTHENTICATION,
2509 "Host", parse_data->soup_uri->host);
2511 if (parse_data->soup_uri->port != 0)
2512 g_key_file_set_integer (
2513 parse_data->key_file,
2514 E_SOURCE_EXTENSION_AUTHENTICATION,
2515 "Port", parse_data->soup_uri->port);
2517 if (parse_data->soup_uri->user != NULL)
2518 g_key_file_set_string (
2519 parse_data->key_file,
2520 E_SOURCE_EXTENSION_AUTHENTICATION,
2521 "User", parse_data->soup_uri->user);
2523 if (parse_data->soup_uri->path != NULL)
2524 g_key_file_set_string (
2525 parse_data->key_file,
2526 E_SOURCE_EXTENSION_WEBDAV_BACKEND,
2527 "ResourcePath", parse_data->soup_uri->path);
2529 parse_data->property_func = migrate_parse_webdav_property;
2533 migrate_parse_group (ParseData *parse_data,
2534 const gchar *element_name,
2535 const gchar **attribute_names,
2536 const gchar **attribute_values,
2539 const gchar *base_uri;
2542 success = g_markup_collect_attributes (
2547 G_MARKUP_COLLECT_STRING,
2549 G_MARKUP_COLLECT_STRING,
2551 G_MARKUP_COLLECT_STRING,
2552 "base_uri", &base_uri,
2553 G_MARKUP_COLLECT_BOOLEAN |
2554 G_MARKUP_COLLECT_OPTIONAL,
2556 G_MARKUP_COLLECT_INVALID);
2561 /* Convert "file://" schemes to "local:". */
2562 if (g_strcmp0 (base_uri, "file://") == 0)
2563 base_uri = "local:";
2565 parse_data->base_uri = g_strdup (base_uri);
2569 migrate_parse_source (ParseData *parse_data,
2570 const gchar *element_name,
2571 const gchar **attribute_names,
2572 const gchar **attribute_values,
2577 const gchar *color_spec;
2578 const gchar *group_name;
2579 const gchar *absolute_uri;
2580 const gchar *relative_uri;
2581 gchar *backend_name;
2586 gboolean is_google_calendar;
2588 success = g_markup_collect_attributes (
2593 G_MARKUP_COLLECT_STRING,
2595 G_MARKUP_COLLECT_STRING,
2597 G_MARKUP_COLLECT_STRING |
2598 G_MARKUP_COLLECT_OPTIONAL,
2599 "color_spec", &color_spec,
2600 G_MARKUP_COLLECT_STRING,
2601 "relative_uri", &relative_uri,
2602 G_MARKUP_COLLECT_STRING |
2603 G_MARKUP_COLLECT_OPTIONAL,
2604 "uri", &absolute_uri,
2605 G_MARKUP_COLLECT_INVALID);
2610 /* Don't try and migrate the "system" sources, as
2611 * we'll defer to the built-in "system-*" key files. */
2612 if (g_strcmp0 (relative_uri, "system") == 0)
2615 /* Also skip any sources with a "contacts://" base URI, which
2616 * should just be "Birthdays & Anniversaries". We'll reset to
2617 * the built-in key file. */
2618 if (g_strcmp0 (parse_data->base_uri, "contacts://") == 0)
2621 /* Also skip any sources for groupware extensions, as these are
2622 * no longer saved to disk. We do have a mechanism in place for
2623 * remembering the UIDs of memory-only sources so that cached
2624 * data can be reused, but let's not bother with it here. Let
2625 * the sources be set up fresh. */
2626 if (base_uri_is_groupware (parse_data->base_uri))
2629 switch (parse_data->type) {
2630 case PARSE_TYPE_ADDRESSBOOK:
2631 group_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
2633 case PARSE_TYPE_CALENDAR:
2634 group_name = E_SOURCE_EXTENSION_CALENDAR;
2636 case PARSE_TYPE_TASKS:
2637 group_name = E_SOURCE_EXTENSION_TASK_LIST;
2639 case PARSE_TYPE_MEMOS:
2640 group_name = E_SOURCE_EXTENSION_MEMO_LIST;
2643 g_return_if_reached ();
2646 parse_data->file = e_server_side_source_new_user_file (uid);
2648 /* If the file already exists, skip this source. It may be that we
2649 * already migrated it, in which case we don't want to overwrite it. */
2650 if (g_file_query_exists (parse_data->file, NULL))
2653 parse_data->key_file = g_key_file_new ();
2655 /* Trim ':' or '://' off the base_uri to get the backend name. */
2656 backend_name = g_strdup (parse_data->base_uri);
2657 if ((cp = strchr (backend_name, ':')) != NULL)
2660 /* The parent name is generally the backend name + "-stub". */
2661 parent_name = g_strdup_printf ("%s-stub", backend_name);
2663 g_key_file_set_string (
2664 parse_data->key_file,
2665 E_SOURCE_GROUP_NAME,
2666 "DisplayName", name);
2668 g_key_file_set_string (
2669 parse_data->key_file,
2670 E_SOURCE_GROUP_NAME,
2671 "Parent", parent_name);
2673 if (color_spec != NULL)
2674 g_key_file_set_string (
2675 parse_data->key_file, group_name,
2676 "Color", color_spec);
2678 is_google_calendar =
2679 (parse_data->type == PARSE_TYPE_CALENDAR) &&
2680 (g_strcmp0 (parse_data->base_uri, "google://") == 0);
2682 /* For Google Calendar sources we override the backend name. */
2683 if (is_google_calendar)
2684 g_key_file_set_string (
2685 parse_data->key_file, group_name,
2686 "BackendName", "caldav");
2688 g_key_file_set_string (
2689 parse_data->key_file, group_name,
2690 "BackendName", backend_name);
2692 g_free (backend_name);
2693 g_free (parent_name);
2695 /* Prefer absolute URIs over relative URIs. All these
2696 * other strange rules are for backward-compatibility. */
2697 if (absolute_uri != NULL)
2698 uri_string = g_strdup (absolute_uri);
2699 else if (g_str_has_suffix (parse_data->base_uri, "/"))
2700 uri_string = g_strconcat (
2701 parse_data->base_uri, relative_uri, NULL);
2702 else if (g_strcmp0 (parse_data->base_uri, "local:") == 0)
2703 uri_string = g_strconcat (
2704 parse_data->base_uri, relative_uri, NULL);
2706 uri_string = g_strconcat (
2707 parse_data->base_uri, "/", relative_uri, NULL);
2709 parse_data->soup_uri = soup_uri_new (uri_string);
2711 /* Mangle the URI to not contain invalid characters. We'll need
2712 * this later to rename the source's cache and data directories. */
2713 parse_data->mangled_uri = g_strdelimit (uri_string, ":/", '_');
2715 /* g_strdelimit() modifies the input string in place, so ParseData
2716 * now owns 'uri_string'. Clear the pointer to emphasize that. */
2719 if (parse_data->soup_uri == NULL) {
2721 " Failed to parse source URI: %s",
2722 (absolute_uri != NULL) ? absolute_uri : relative_uri);
2723 g_key_file_free (parse_data->key_file);
2724 parse_data->key_file = NULL;
2728 if (g_strcmp0 (parse_data->base_uri, "local:") == 0)
2729 migrate_parse_local_source (parse_data);
2731 else if (g_strcmp0 (parse_data->base_uri, "caldav://") == 0)
2732 migrate_parse_caldav_source (parse_data);
2734 else if (g_strcmp0 (parse_data->base_uri, "google://") == 0)
2735 migrate_parse_google_source (parse_data);
2737 else if (g_strcmp0 (parse_data->base_uri, "ldap://") == 0)
2738 migrate_parse_ldap_source (parse_data);
2740 else if (g_strcmp0 (parse_data->base_uri, "vcf://") == 0)
2741 migrate_parse_vcf_source (parse_data);
2743 else if (g_strcmp0 (parse_data->base_uri, "weather://") == 0)
2744 migrate_parse_weather_source (parse_data);
2746 else if (g_strcmp0 (parse_data->base_uri, "webcal://") == 0)
2747 migrate_parse_webcal_source (parse_data);
2749 else if (g_strcmp0 (parse_data->base_uri, "webdav://") == 0)
2750 migrate_parse_webdav_source (parse_data);
2752 migrate_keyring_entry (
2754 parse_data->soup_uri->user,
2755 parse_data->soup_uri->host,
2756 parse_data->soup_uri->scheme);
2760 migrate_parse_property (ParseData *parse_data,
2761 const gchar *element_name,
2762 const gchar **attribute_names,
2763 const gchar **attribute_values,
2766 const gchar *property_name;
2767 const gchar *property_value;
2770 success = g_markup_collect_attributes (
2775 G_MARKUP_COLLECT_STRING,
2776 "name", &property_name,
2777 G_MARKUP_COLLECT_STRING,
2778 "value", &property_value,
2779 G_MARKUP_COLLECT_INVALID);
2784 if (g_strcmp0 (property_name, "alarm") == 0) {
2785 g_key_file_set_boolean (
2786 parse_data->key_file,
2787 E_SOURCE_EXTENSION_ALARMS,
2789 is_true (property_value));
2791 } else if (g_strcmp0 (property_name, "auth") == 0) {
2792 if (is_true (property_value))
2793 g_key_file_set_string (
2794 parse_data->key_file,
2795 E_SOURCE_EXTENSION_AUTHENTICATION,
2796 "Method", "plain/password");
2797 else if (is_false (property_value))
2798 g_key_file_set_string (
2799 parse_data->key_file,
2800 E_SOURCE_EXTENSION_AUTHENTICATION,
2803 g_key_file_set_string (
2804 parse_data->key_file,
2805 E_SOURCE_EXTENSION_AUTHENTICATION,
2806 "Method", property_value);
2808 } else if (g_strcmp0 (property_name, "completion") == 0) {
2809 g_key_file_set_boolean (
2810 parse_data->key_file,
2811 E_SOURCE_EXTENSION_AUTOCOMPLETE,
2813 is_true (property_value));
2815 /* If we see a "goa-account-id" property, skip the entire
2816 * source and let the online-accounts module recreate it. */
2817 } else if (g_strcmp0 (property_name, "goa-account-id") == 0) {
2818 parse_data->skip = TRUE;
2820 } else if (g_strcmp0 (property_name, "last-notified") == 0) {
2821 g_key_file_set_string (
2822 parse_data->key_file,
2823 E_SOURCE_EXTENSION_ALARMS,
2824 "LastNotified", property_value);
2826 } else if (g_strcmp0 (property_name, "offline_sync") == 0) {
2827 g_key_file_set_boolean (
2828 parse_data->key_file,
2829 E_SOURCE_EXTENSION_OFFLINE,
2831 is_true (property_value));
2833 } else if (g_strcmp0 (property_name, "refresh") == 0) {
2834 g_key_file_set_boolean (
2835 parse_data->key_file,
2836 E_SOURCE_EXTENSION_REFRESH,
2838 g_key_file_set_string (
2839 parse_data->key_file,
2840 E_SOURCE_EXTENSION_REFRESH,
2841 "IntervalMinutes", property_value);
2843 } else if (g_strcmp0 (property_name, "remember_password") == 0) {
2844 g_key_file_set_boolean (
2845 parse_data->key_file,
2846 E_SOURCE_EXTENSION_AUTHENTICATION,
2848 is_true (property_value));
2850 } else if (g_strcmp0 (property_name, "ssl") == 0) {
2851 if (is_true (property_value))
2852 g_key_file_set_string (
2853 parse_data->key_file,
2854 E_SOURCE_EXTENSION_SECURITY,
2856 else if (is_false (property_value))
2857 g_key_file_set_string (
2858 parse_data->key_file,
2859 E_SOURCE_EXTENSION_SECURITY,
2862 /* These next two are LDAP-specific. */
2863 else if (g_strcmp0 (property_value, "always") == 0)
2864 g_key_file_set_string (
2865 parse_data->key_file,
2866 E_SOURCE_EXTENSION_SECURITY,
2867 "Method", "starttls");
2868 else if (g_strcmp0 (property_value, "whenever_possible") == 0)
2869 g_key_file_set_string (
2870 parse_data->key_file,
2871 E_SOURCE_EXTENSION_SECURITY,
2874 /* For WebDAV-based backends we set the port to 80
2875 * (http://) by default. If we see that and we're
2876 * using a secure connection, bump the port to 443
2878 if (parse_data->soup_uri->port == 80)
2879 if (is_true (property_value))
2880 g_key_file_set_integer (
2881 parse_data->key_file,
2882 E_SOURCE_EXTENSION_AUTHENTICATION,
2885 } else if (g_strcmp0 (property_name, "use_ssl") == 0) {
2886 g_key_file_set_string (
2887 parse_data->key_file,
2888 E_SOURCE_EXTENSION_SECURITY,
2890 is_true (property_value) ?
2893 /* For WebDAV-based backends we set the port to 80
2894 * (http://) by default. If we see that and we're
2895 * using a secure connection, bump the port to 443
2897 if (parse_data->soup_uri->port == 80)
2898 if (is_true (property_value))
2899 g_key_file_set_integer (
2900 parse_data->key_file,
2901 E_SOURCE_EXTENSION_AUTHENTICATION,
2904 } else if (g_strcmp0 (property_name, "use-in-contacts-calendar") == 0) {
2905 g_key_file_set_boolean (
2906 parse_data->key_file,
2907 E_SOURCE_EXTENSION_CONTACTS_BACKEND,
2909 is_true (property_value));
2911 } else if (parse_data->property_func != NULL) {
2912 parse_data->property_func (
2913 parse_data, property_name, property_value);
2918 migrate_parse_source_xml_start_element (GMarkupParseContext *context,
2919 const gchar *element_name,
2920 const gchar **attribute_names,
2921 const gchar **attribute_values,
2925 ParseData *parse_data = user_data;
2927 if (g_strcmp0 (element_name, "group") == 0) {
2928 if (parse_data->state != PARSE_STATE_IN_SOURCES_VALUE)
2929 goto invalid_content;
2931 parse_data->state = PARSE_STATE_IN_GROUP;
2933 migrate_parse_group (
2943 if (g_strcmp0 (element_name, "source") == 0) {
2944 if (parse_data->state != PARSE_STATE_IN_GROUP)
2945 goto invalid_content;
2947 parse_data->state = PARSE_STATE_IN_SOURCE;
2949 migrate_parse_source (
2959 if (g_strcmp0 (element_name, "properties") == 0) {
2960 /* Disregard group properties, we're only
2961 * interested in source properties. */
2962 if (parse_data->state == PARSE_STATE_IN_GROUP)
2965 if (parse_data->state != PARSE_STATE_IN_SOURCE)
2966 goto invalid_content;
2968 parse_data->state = PARSE_STATE_IN_PROPERTIES;
2973 if (g_strcmp0 (element_name, "property") == 0) {
2974 /* Disregard group properties, we're only
2975 * interested in source properties. */
2976 if (parse_data->state == PARSE_STATE_IN_GROUP)
2979 if (parse_data->state != PARSE_STATE_IN_PROPERTIES)
2980 goto invalid_content;
2982 /* The key file will be NULL if we decided to skip it.
2983 * e.g. A file with the same UID may already exist. */
2984 if (parse_data->key_file != NULL)
2985 migrate_parse_property (
2996 error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2997 "Unknown element <%s>", element_name);
3004 error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
3005 "Element <%s> at unexpected location", element_name);
3009 migrate_parse_source_xml_end_element (GMarkupParseContext *context,
3010 const gchar *element_name,
3014 ParseData *parse_data = user_data;
3016 if (g_strcmp0 (element_name, "group") == 0) {
3017 if (parse_data->state == PARSE_STATE_IN_GROUP) {
3018 parse_data->state = PARSE_STATE_IN_SOURCES_VALUE;
3020 /* Clean up <group> tag data. */
3022 g_free (parse_data->base_uri);
3023 parse_data->base_uri = NULL;
3028 if (g_strcmp0 (element_name, "source") == 0) {
3029 if (parse_data->state == PARSE_STATE_IN_SOURCE) {
3030 parse_data->state = PARSE_STATE_IN_GROUP;
3032 /* Clean up <source> tag data. */
3034 /* The key file will be NULL if we decided to skip it.
3035 * e.g. A file with the same UID may already exist. */
3036 if (parse_data->key_file != NULL) {
3037 GError *local_error = NULL;
3039 if (!parse_data->skip)
3040 migrate_parse_commit_changes (
3043 parse_data->key_file,
3044 parse_data->mangled_uri,
3047 if (local_error != NULL) {
3050 local_error->message);
3051 g_error_free (local_error);
3054 g_key_file_free (parse_data->key_file);
3055 parse_data->key_file = NULL;
3058 if (parse_data->file != NULL) {
3059 g_object_unref (parse_data->file);
3060 parse_data->file = NULL;
3063 g_free (parse_data->mangled_uri);
3064 parse_data->mangled_uri = NULL;
3066 if (parse_data->soup_uri != NULL) {
3067 soup_uri_free (parse_data->soup_uri);
3068 parse_data->soup_uri = NULL;
3071 parse_data->property_func = NULL;
3073 parse_data->skip = FALSE;
3078 if (g_strcmp0 (element_name, "properties") == 0) {
3079 if (parse_data->state == PARSE_STATE_IN_PROPERTIES)
3080 parse_data->state = PARSE_STATE_IN_SOURCE;
3085 static GMarkupParser source_xml_parser = {
3086 migrate_parse_source_xml_start_element,
3087 migrate_parse_source_xml_end_element,
3089 NULL, /* passthrough */
3094 migrate_parse_gconf_xml_start_element (GMarkupParseContext *context,
3095 const gchar *element_name,
3096 const gchar **attribute_names,
3097 const gchar **attribute_values,
3101 ParseData *parse_data = user_data;
3103 if (g_strcmp0 (element_name, "gconf") == 0) {
3104 if (parse_data->state != PARSE_STATE_INITIAL)
3105 goto invalid_content;
3107 parse_data->state = PARSE_STATE_IN_GCONF;
3112 if (g_strcmp0 (element_name, "entry") == 0) {
3116 if (parse_data->state != PARSE_STATE_IN_GCONF)
3117 goto invalid_content;
3119 success = g_markup_collect_attributes (
3124 G_MARKUP_COLLECT_STRING,
3126 G_MARKUP_COLLECT_STRING,
3128 G_MARKUP_COLLECT_STRING |
3129 G_MARKUP_COLLECT_OPTIONAL,
3131 G_MARKUP_COLLECT_STRING |
3132 G_MARKUP_COLLECT_OPTIONAL,
3134 G_MARKUP_COLLECT_STRING |
3135 G_MARKUP_COLLECT_OPTIONAL,
3137 G_MARKUP_COLLECT_STRING |
3138 G_MARKUP_COLLECT_OPTIONAL,
3140 G_MARKUP_COLLECT_INVALID);
3142 if (success && g_strcmp0 (name, "accounts") == 0)
3143 parse_data->state = PARSE_STATE_IN_ACCOUNTS_ENTRY;
3145 if (success && g_strcmp0 (name, "signatues") == 0)
3146 parse_data->state = PARSE_STATE_IN_SIGNATURES_ENTRY;
3148 if (success && g_strcmp0 (name, "sources") == 0)
3149 parse_data->state = PARSE_STATE_IN_SOURCES_ENTRY;
3154 if (g_strcmp0 (element_name, "li") == 0)
3157 if (g_strcmp0 (element_name, "stringvalue") == 0) {
3158 if (parse_data->state == PARSE_STATE_IN_ACCOUNTS_ENTRY)
3159 parse_data->state = PARSE_STATE_IN_ACCOUNTS_VALUE;
3161 if (parse_data->state == PARSE_STATE_IN_SIGNATURES_ENTRY)
3162 parse_data->state = PARSE_STATE_IN_SIGNATURES_VALUE;
3164 if (parse_data->state == PARSE_STATE_IN_SOURCES_ENTRY)
3165 parse_data->state = PARSE_STATE_IN_SOURCES_VALUE;
3171 error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
3172 "Unknown element <%s>", element_name);
3179 error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
3180 "Element <%s> at unexpected location", element_name);
3184 migrate_parse_gconf_xml_end_element (GMarkupParseContext *context,
3185 const gchar *element_name,
3189 ParseData *parse_data = user_data;
3191 if (g_strcmp0 (element_name, "gconf") == 0) {
3192 if (parse_data->state == PARSE_STATE_IN_GCONF)
3193 parse_data->state = PARSE_STATE_INITIAL;
3198 if (g_strcmp0 (element_name, "entry") == 0) {
3199 if (parse_data->state == PARSE_STATE_IN_ACCOUNTS_ENTRY)
3200 parse_data->state = PARSE_STATE_IN_GCONF;
3202 if (parse_data->state == PARSE_STATE_IN_SIGNATURES_ENTRY)
3203 parse_data->state = PARSE_STATE_IN_GCONF;
3205 if (parse_data->state == PARSE_STATE_IN_SOURCES_ENTRY)
3206 parse_data->state = PARSE_STATE_IN_GCONF;
3211 if (g_strcmp0 (element_name, "stringvalue") == 0) {
3212 if (parse_data->state == PARSE_STATE_IN_ACCOUNTS_VALUE)
3213 parse_data->state = PARSE_STATE_IN_ACCOUNTS_ENTRY;
3215 if (parse_data->state == PARSE_STATE_IN_SIGNATURES_VALUE)
3216 parse_data->state = PARSE_STATE_IN_SIGNATURES_ENTRY;
3218 if (parse_data->state == PARSE_STATE_IN_SOURCES_VALUE)
3219 parse_data->state = PARSE_STATE_IN_SOURCES_ENTRY;
3226 migrate_parse_gconf_xml_text (GMarkupParseContext *context,
3232 ParseData *parse_data = user_data;
3234 /* The account and signature data is encoded XML stuffed into
3235 * GConf XML (yuck!). Fortunately GMarkupParseContext decodes
3236 * the XML for us, so we just have to feed it to a nested
3237 * GMarkupParseContext. */
3239 switch (parse_data->state) {
3240 case PARSE_STATE_IN_ACCOUNTS_VALUE:
3241 context = g_markup_parse_context_new (
3242 &account_xml_parser, 0, parse_data, NULL);
3245 case PARSE_STATE_IN_SIGNATURES_VALUE:
3246 context = g_markup_parse_context_new (
3247 &signature_xml_parser, 0, parse_data, NULL);
3250 case PARSE_STATE_IN_SOURCES_VALUE:
3251 context = g_markup_parse_context_new (
3252 &source_xml_parser, 0, parse_data, NULL);
3259 if (g_markup_parse_context_parse (context, text, length, error))
3260 g_markup_parse_context_end_parse (context, error);
3262 g_markup_parse_context_free (context);
3265 static GMarkupParser gconf_xml_parser = {
3266 migrate_parse_gconf_xml_start_element,
3267 migrate_parse_gconf_xml_end_element,
3268 migrate_parse_gconf_xml_text,
3269 NULL, /* passthrough */
3274 migrate_parse_gconf_xml (ParseType parse_type,
3275 const gchar *contents,
3279 GMarkupParseContext *context;
3280 ParseData *parse_data;
3281 gboolean success = FALSE;
3283 parse_data = parse_data_new (parse_type);
3285 context = g_markup_parse_context_new (
3286 &gconf_xml_parser, 0, parse_data,
3287 (GDestroyNotify) parse_data_free);
3289 if (g_markup_parse_context_parse (context, contents, length, error))
3290 if (g_markup_parse_context_end_parse (context, error))
3293 g_markup_parse_context_free (context);
3299 migrate_remove_gconf_xml (const gchar *gconf_key,
3300 const gchar *gconf_xml)
3302 /* Remove the GConf string list so the user is not haunted by
3303 * old data sources being resurrected from leftover GConf data.
3304 * Also delete the %gconf.xml file itself. If gconfd is running
3305 * then it will just recreate the file from memory when it exits
3306 * (which is why we invoke gconftool-2), otherwise the file will
3309 gchar *path_to_program;
3311 path_to_program = g_find_program_in_path ("gconftool-2");
3313 if (path_to_program != NULL) {
3314 gchar *command_line;
3315 GError *error = NULL;
3317 command_line = g_strjoin (
3322 "--list-type=string",
3323 gconf_key, "[]", NULL);
3325 /* We don't really care if the command worked or not,
3326 * just check that the program got spawned successfully. */
3327 if (!g_spawn_command_line_async (command_line, &error)) {
3329 "Failed to spawn '%s': %s\n",
3330 path_to_program, error->message);
3331 g_error_free (error);
3334 g_free (path_to_program);
3335 g_free (command_line);
3338 if (g_file_test (gconf_xml, G_FILE_TEST_IS_REGULAR)) {
3339 if (g_remove (gconf_xml) == -1) {
3341 "Failed to remove '%s': %s\n",
3342 gconf_xml, g_strerror (errno));
3348 evolution_source_registry_migrate_sources (void)
3354 const gchar *gconf_key;
3355 GError *error = NULL;
3357 base_dir = g_build_filename (
3358 g_get_home_dir (), ".gconf", "apps", "evolution", NULL);
3360 /* ------------------------------------------------------------------*/
3362 g_print ("Migrating mail accounts from GConf...\n");
3364 gconf_xml = g_build_filename (
3365 base_dir, "mail", "%gconf.xml", NULL);
3366 g_file_get_contents (gconf_xml, &contents, &length, &error);
3368 if (error == NULL) {
3369 migrate_parse_gconf_xml (
3371 contents, length, &error);
3375 if (error == NULL) {
3376 gconf_key = "/apps/evolution/mail/accounts";
3377 migrate_remove_gconf_xml (gconf_key, gconf_xml);
3379 g_printerr (" FAILED: %s\n", error->message);
3380 g_clear_error (&error);
3385 /* ------------------------------------------------------------------*/
3387 g_print ("Migrating addressbook sources from GConf...\n");
3389 gconf_xml = g_build_filename (
3390 base_dir, "addressbook", "%gconf.xml", NULL);
3391 g_file_get_contents (gconf_xml, &contents, &length, &error);
3393 if (error == NULL) {
3394 migrate_parse_gconf_xml (
3395 PARSE_TYPE_ADDRESSBOOK,
3396 contents, length, &error);
3400 if (error == NULL) {
3401 gconf_key = "/apps/evolution/addressbook/sources";
3402 migrate_remove_gconf_xml (gconf_key, gconf_xml);
3404 g_printerr (" FAILED: %s\n", error->message);
3405 g_clear_error (&error);
3410 /* ------------------------------------------------------------------*/
3412 g_print ("Migrating calendar sources from GConf...\n");
3414 gconf_xml = g_build_filename (
3415 base_dir, "calendar", "%gconf.xml", NULL);
3416 g_file_get_contents (gconf_xml, &contents, &length, &error);
3418 if (error == NULL) {
3419 migrate_parse_gconf_xml (
3420 PARSE_TYPE_CALENDAR,
3421 contents, length, &error);
3425 if (error == NULL) {
3426 gconf_key = "/apps/evolution/calendar/sources";
3427 migrate_remove_gconf_xml (gconf_key, gconf_xml);
3429 g_printerr (" FAILED: %s\n", error->message);
3430 g_clear_error (&error);
3435 /* ------------------------------------------------------------------*/
3437 g_print ("Migrating task list sources from GConf...\n");
3439 gconf_xml = g_build_filename (
3440 base_dir, "tasks", "%gconf.xml", NULL);
3441 g_file_get_contents (gconf_xml, &contents, &length, &error);
3443 if (error == NULL) {
3444 migrate_parse_gconf_xml (
3446 contents, length, &error);
3450 if (error == NULL) {
3451 gconf_key = "/apps/evolution/tasks/sources";
3452 migrate_remove_gconf_xml (gconf_key, gconf_xml);
3454 g_printerr (" FAILED: %s\n", error->message);
3455 g_clear_error (&error);
3460 /* ------------------------------------------------------------------*/
3462 g_print ("Migrating memo list sources from GConf...\n");
3464 gconf_xml = g_build_filename (
3465 base_dir, "memos", "%gconf.xml", NULL);
3466 g_file_get_contents (gconf_xml, &contents, &length, &error);
3468 if (error == NULL) {
3469 migrate_parse_gconf_xml (
3471 contents, length, &error);
3475 if (error == NULL) {
3476 gconf_key = "/apps/evolution/memos/sources";
3477 migrate_remove_gconf_xml (gconf_key, gconf_xml);
3479 g_printerr (" FAILED: %s\n", error->message);
3480 g_clear_error (&error);
3485 /* ------------------------------------------------------------------*/