2 * Copyright (C) 2009 Collabora Ltd.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
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 * General Public License for more details.
14 * You should have received a copy of the GNU General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301 USA
19 * Authors: Arnaud Maillet <arnaud.maillet@collabora.co.uk>
25 #include <glib/gi18n.h>
26 #include <gconf/gconf-client.h>
27 #include <telepathy-glib/account-manager.h>
28 #include <telepathy-glib/util.h>
29 #include <telepathy-glib/defs.h>
30 #include <dbus/dbus-protocol.h>
31 #include <gnome-keyring.h>
32 #include <libempathy/empathy-account-settings.h>
33 #include <libempathy/empathy-connection-managers.h>
35 #include "empathy-import-mc4-accounts.h"
37 #define DEBUG_FLAG EMPATHY_DEBUG_IMPORT_MC4_ACCOUNTS
38 #include <libempathy/empathy-debug.h>
40 #define MC_ACCOUNTS_GCONF_BASE "/apps/telepathy/mc/accounts"
41 #define IMPORTED_MC4_ACCOUNTS "/apps/empathy/accounts/imported_mc4_accounts"
47 } ProfileProtocolMapItem;
49 static ProfileProtocolMapItem profile_protocol_map[] =
53 { "gtalk", "jabber" },
54 { "msn-haze", "msn" },
55 { "salut", "local-xmpp" },
56 { "sipphone", "sip" },
57 { "sofiasip", "sip" },
66 _account_name_from_key (const gchar *key)
68 guint base_len = strlen (MC_ACCOUNTS_GCONF_BASE);
69 const gchar *base, *slash;
71 g_assert (g_str_has_prefix (key, MC_ACCOUNTS_GCONF_BASE));
72 g_assert (strlen (key) > base_len + 1);
74 base = key + base_len + 1;
75 slash = strchr (base, '/');
78 return g_strdup (base);
80 return g_strndup (base, slash - base);
84 _param_name_from_key (const gchar *key)
86 const gchar *base, *slash;
90 account_name = _account_name_from_key (key);
91 base = strstr (key, account_name);
92 slash = strchr (base, '/');
94 ret = g_strdup (slash+1);
95 g_free (account_name);
101 _create_default_display_name (const gchar *protocol)
103 if (!tp_strdiff (protocol, "local-xmpp"))
104 return g_strdup (_("People Nearby"));
106 return g_strdup_printf (_("%s account"), protocol);
110 _get_manager_for_protocol (EmpathyConnectionManagers *managers,
111 const gchar *protocol)
113 GList *cms = empathy_connection_managers_get_cms (managers);
115 TpConnectionManager *haze = NULL;
116 TpConnectionManager *cm = NULL;
118 for (l = cms; l; l = l->next)
120 TpConnectionManager *tp_cm = l->data;
122 /* Only use haze if no other cm provides this protocol */
123 if (!tp_strdiff (tp_connection_manager_get_name (tp_cm), "haze"))
129 if (tp_connection_manager_has_protocol (tp_cm, protocol))
136 if (haze != NULL && tp_connection_manager_has_protocol (haze, protocol))
137 return tp_connection_manager_get_name (haze);
140 return cm != NULL ? tp_connection_manager_get_name (cm) : NULL;
144 _move_contents (const gchar *old, const gchar *new)
150 ret = g_mkdir_with_parents (new, 0777);
154 source = g_dir_open (old, 0, NULL);
158 while ((f = g_dir_read_name (source)) != NULL)
163 old_path = g_build_path (G_DIR_SEPARATOR_S, old, f, NULL);
164 new_path = g_build_path (G_DIR_SEPARATOR_S, new, f, NULL);
166 if (g_file_test (old_path, G_FILE_TEST_IS_DIR))
168 _move_contents (old_path, new_path);
172 GFile *f_old, *f_new;
174 f_old = g_file_new_for_path (old_path);
175 f_new = g_file_new_for_path (new_path);
177 g_file_move (f_old, f_new, G_FILE_COPY_NONE,
178 NULL, NULL, NULL, NULL);
180 g_object_unref (f_old);
181 g_object_unref (f_new);
188 g_dir_close (source);
192 _move_logs (TpAccount *account, const gchar *account_name)
194 gchar *old_path, *new_path, *escaped;
197 name = tp_proxy_get_object_path (account);
198 if (g_str_has_prefix (name, TP_ACCOUNT_OBJECT_PATH_BASE))
199 name += strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
201 escaped = g_strdelimit (g_strdup (name), "/", '_');
202 new_path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (),
203 PACKAGE_NAME, "logs", escaped, NULL);
206 old_path = g_build_path (G_DIR_SEPARATOR_S,
208 ".gnome2", PACKAGE_NAME, "logs", account_name, NULL);
210 _move_contents (old_path, new_path);
214 _create_account_cb (GObject *source,
215 GAsyncResult *result,
219 GError *error = NULL;
220 Misc *misc = (Misc *) user_data;
222 if (!empathy_account_settings_apply_finish (
223 EMPATHY_ACCOUNT_SETTINGS (source), result, &error))
225 DEBUG ("Failed to create account: %s", error->message);
226 g_error_free (error);
230 DEBUG ("account created");
231 account = empathy_account_settings_get_account (
232 EMPATHY_ACCOUNT_SETTINGS (source));
234 _move_logs (account, misc->account_name);
236 tp_account_set_enabled_async (account,
237 misc->enable, NULL, NULL);
239 g_free (misc->account_name);
240 g_slice_free (Misc, misc);
243 g_object_unref (source);
247 _get_protocol_from_profile (const gchar *profile)
251 DEBUG ("profile: %s", profile);
253 for (i = 0; i < G_N_ELEMENTS (profile_protocol_map); i++)
254 if (!tp_strdiff (profile, profile_protocol_map[i].profile))
255 return g_strdup (profile_protocol_map[i].protocol);
257 return g_strdup (profile);
261 _set_password_from_keyring (EmpathyAccountSettings *settings,
262 const gchar *account_name, const gchar *key)
264 GnomeKeyringResult res;
266 GnomeKeyringPasswordSchema keyring_schema = {
267 GNOME_KEYRING_ITEM_GENERIC_SECRET,
269 { "account", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
270 { "param", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
275 res = gnome_keyring_find_password_sync (&keyring_schema,
277 "account", account_name,
281 if (res == GNOME_KEYRING_RESULT_OK)
283 empathy_account_settings_set_string (settings, key, password);
284 gnome_keyring_free_password (password);
289 _handle_entry (EmpathyAccountSettings *settings, const gchar *account_name,
293 const gchar *signature;
295 signature = empathy_account_settings_get_dbus_signature (settings, key);
296 if (signature == NULL)
298 DEBUG ("Parameter %s is unknown", signature);
302 switch ((int)*signature)
304 case DBUS_TYPE_INT16:
305 case DBUS_TYPE_INT32:
307 gint v = gconf_value_get_int (gconf_entry_get_value (entry));
308 empathy_account_settings_set_int32 (settings, key, v);
311 case DBUS_TYPE_UINT16:
312 case DBUS_TYPE_UINT32:
314 gint v = gconf_value_get_int (gconf_entry_get_value (entry));
315 empathy_account_settings_set_uint32 (settings, key, v);
318 case DBUS_TYPE_STRING:
320 const gchar *v = gconf_value_get_string (
321 gconf_entry_get_value (entry));
323 /* MC 4 would put password in the keyring and leave the password in
326 if (!tp_strdiff (key, "password") && !tp_strdiff (v, "keyring"))
327 _set_password_from_keyring (settings, account_name, key);
329 empathy_account_settings_set_string (settings, key, v);
332 case DBUS_TYPE_BOOLEAN:
334 gboolean v = gconf_value_get_bool (
335 gconf_entry_get_value (entry));
337 empathy_account_settings_set_boolean (settings, key, v);
341 DEBUG ("Unsupported type in signature: %s", signature);
346 _recurse_account (GSList *entries, EmpathyAccountSettings *settings,
347 const gchar *account_name)
351 for (tmp = entries; tmp != NULL; tmp = tmp->next)
357 entry = (GConfEntry *) tmp->data;
358 param = _param_name_from_key (gconf_entry_get_key (entry));
360 if (g_str_has_prefix (param, "param-"))
362 _handle_entry (settings, account_name, param + strlen ("param-"),
367 gconf_entry_unref (entry);
372 import_one_account (const char *path,
373 EmpathyConnectionManagers *managers,
376 gchar *account_name = _account_name_from_key (path);
377 EmpathyAccountSettings *settings = NULL;
378 GError *error = NULL;
379 GSList *entries = NULL;
380 gchar *profile = NULL;
381 gchar *protocol = NULL;
382 const gchar *manager;
385 gboolean enabled = FALSE;
386 gboolean ret = FALSE;
389 DEBUG ("Starting import of %s (%s)", path, account_name);
391 key = g_strdup_printf ("%s/profile", path);
392 profile = gconf_client_get_string (client, key, NULL);
397 DEBUG ("Account is missing a profile entry");
401 protocol = _get_protocol_from_profile (profile);
402 manager = _get_manager_for_protocol (managers, protocol);
405 DEBUG ("No manager available for this protocol %s", protocol);
409 key = g_strdup_printf ("%s/display_name", path);
410 display_name = gconf_client_get_string (client, key, NULL);
413 if (display_name == NULL)
414 display_name = _create_default_display_name (protocol);
416 settings = empathy_account_settings_new (manager, protocol, display_name);
417 g_free (display_name);
419 /* Bit of a hack, as we know EmpathyConnectionManagers is ready the
420 * EmpathyAccountSettings should be ready right away as well */
421 g_assert (empathy_account_settings_is_ready (settings));
423 entries = gconf_client_all_entries (client, path, &error);
427 DEBUG ("Failed to get all entries: %s", error->message);
428 g_error_free (error);
432 _recurse_account (entries, settings, account_name);
434 key = g_strdup_printf ("%s/enabled", path);
435 enabled = gconf_client_get_bool (client, key, NULL);
438 misc = g_slice_new (Misc);
439 misc->account_name = account_name;
440 misc->enable = enabled;
442 empathy_account_settings_apply_async (settings,
443 _create_account_cb, misc);
449 g_slist_free (entries);
454 DEBUG ("Failed to import %s", path);
455 g_free (account_name);
456 if (settings != NULL)
457 g_object_unref (settings);
462 empathy_import_mc4_has_imported (void)
467 client = gconf_client_get_default ();
469 ret = gconf_client_get_bool (client, IMPORTED_MC4_ACCOUNTS, NULL);
470 g_object_unref (client);
476 empathy_import_mc4_accounts (EmpathyConnectionManagers *managers)
479 GError *error = NULL;
480 GSList *dir, *dirs = NULL;
481 gboolean imported_mc4_accounts;
482 gboolean imported = FALSE;
484 g_return_val_if_fail (empathy_connection_managers_is_ready (managers),
487 client = gconf_client_get_default ();
489 imported_mc4_accounts = gconf_client_get_bool (client,
490 IMPORTED_MC4_ACCOUNTS, &error);
494 DEBUG ("Failed to get import_mc4_accounts key: %s", error->message);
495 g_error_free (error);
499 if (imported_mc4_accounts)
501 DEBUG ("Mc4 accounts previously imported");
505 DEBUG ("MC 4 accounts are going to be imported");
507 dirs = gconf_client_all_dirs (client, MC_ACCOUNTS_GCONF_BASE, &error);
511 DEBUG ("Failed to get MC4 account dirs: %s",
513 g_clear_error (&error);
514 g_object_unref (client);
518 for (dir = dirs; NULL != dir; dir = dir->next)
520 if (import_one_account ((gchar *) dir->data, managers, client))
526 gconf_client_set_bool (client, IMPORTED_MC4_ACCOUNTS, TRUE, NULL);
529 g_object_unref (client);