2 * Copyright (C) 2008 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/util.h>
28 #include <dbus/dbus-protocol.h>
29 #include <gnome-keyring.h>
30 #include <libempathy/empathy-account-manager.h>
31 #include <libempathy/empathy-account-settings.h>
32 #include <libempathy/empathy-connection-managers.h>
34 #include "empathy-import-mc4-accounts.h"
36 #define DEBUG_FLAG EMPATHY_DEBUG_IMPORT_MC4_ACCOUNTS
37 #include <libempathy/empathy-debug.h>
39 #define MC_ACCOUNTS_GCONF_BASE "/apps/telepathy/mc/accounts"
40 #define IMPORTED_MC4_ACCOUNTS "/apps/empathy/accounts/imported_mc4_accounts"
46 } ProfileProtocolMapItem;
48 static ProfileProtocolMapItem profile_protocol_map[] =
52 { "gtalk", "jabber" },
53 { "msn-haze", "msn" },
54 { "salut", "local-xmpp" },
55 { "sipphone", "sip" },
56 { "sofiasip", "sip" },
60 _account_name_from_key (const gchar *key)
62 guint base_len = strlen (MC_ACCOUNTS_GCONF_BASE);
63 const gchar *base, *slash;
65 g_assert (g_str_has_prefix (key, MC_ACCOUNTS_GCONF_BASE));
66 g_assert (strlen (key) > base_len + 1);
68 base = key + base_len + 1;
69 slash = strchr (base, '/');
72 return g_strdup (base);
74 return g_strndup (base, slash - base);
78 _param_name_from_key (const gchar *key)
80 const gchar *base, *slash;
83 account_name = _account_name_from_key (key);
84 base = strstr (key, account_name);
85 slash = strchr (base, '/');
86 g_free (account_name);
88 return g_strdup (slash+1);
92 _create_default_display_name (const gchar *protocol)
94 if (!tp_strdiff (protocol, "local-xmpp"))
95 return g_strdup (_("People Nearby"));
97 return g_strdup_printf ("%s account", protocol);
101 _get_manager_for_protocol (EmpathyConnectionManagers *managers,
102 const gchar *protocol)
104 GList *cms = empathy_connection_managers_get_cms (managers);
106 TpConnectionManager *haze = NULL;
107 TpConnectionManager *cm = NULL;
109 for (l = cms; l; l = l->next)
111 TpConnectionManager *tp_cm = l->data;
113 /* Only use haze if no other cm provides this account */
114 if (!tp_strdiff (tp_connection_manager_get_name (tp_cm), "haze"))
120 if (tp_connection_manager_has_protocol (tp_cm, protocol))
127 if (haze != NULL && tp_connection_manager_has_protocol (haze, protocol))
128 return tp_connection_manager_get_name (haze);
131 return cm != NULL ? tp_connection_manager_get_name (cm) : NULL;
135 _create_account_cb (GObject *source,
136 GAsyncResult *result,
139 EmpathyAccount *account;
140 GError *error = NULL;
142 if (!empathy_account_settings_apply_finish (
143 EMPATHY_ACCOUNT_SETTINGS (source), result, &error))
145 DEBUG ("Failed to create account: %s",
146 error ? error->message : "No error given");
147 g_error_free (error);
151 DEBUG ("account created\n");
152 account = empathy_account_settings_get_account (
153 EMPATHY_ACCOUNT_SETTINGS (source));
154 empathy_account_set_enabled_async (account,
155 GPOINTER_TO_INT (user_data), NULL, NULL);
158 g_object_unref (source);
162 _get_protocol_from_profile (const gchar *profile)
166 DEBUG ("profile: %s\n", profile);
168 for (i = 0; i < G_N_ELEMENTS (profile_protocol_map); i++)
169 if (!tp_strdiff (profile, profile_protocol_map[i].profile))
170 return g_strdup (profile_protocol_map[i].protocol);
172 return g_strdup (profile);
176 _set_password_from_keyring (EmpathyAccountSettings *settings,
177 const gchar *account_name, const gchar *key)
179 GnomeKeyringResult res;
181 GnomeKeyringPasswordSchema keyring_schema = {
182 GNOME_KEYRING_ITEM_GENERIC_SECRET,
184 { "account", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
185 { "param", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
190 res = gnome_keyring_find_password_sync (&keyring_schema,
192 "account", account_name,
196 if (res == GNOME_KEYRING_RESULT_OK)
198 empathy_account_settings_set_string (settings, key, password);
199 gnome_keyring_free_password (password);
204 _handle_entry (EmpathyAccountSettings *settings, const gchar *account_name,
208 const gchar *signature;
210 signature = empathy_account_settings_get_dbus_signature (settings, key);
211 if (signature == NULL)
213 DEBUG ("Parameter %s is unknown", signature);
217 switch ((int)*signature)
219 case DBUS_TYPE_INT16:
220 case DBUS_TYPE_INT32:
222 gint v = gconf_value_get_int (gconf_entry_get_value (entry));
223 empathy_account_settings_set_int32 (settings, key, v);
226 case DBUS_TYPE_UINT16:
227 case DBUS_TYPE_UINT32:
229 gint v = gconf_value_get_int (gconf_entry_get_value (entry));
230 empathy_account_settings_set_uint32 (settings, key, v);
233 case DBUS_TYPE_STRING:
235 const gchar *v = gconf_value_get_string (
236 gconf_entry_get_value (entry));
238 /* MC 4 would put password in the keyring and leave the password in
241 if (!tp_strdiff (key, "password") && !tp_strdiff (v, "keyring"))
242 _set_password_from_keyring (settings, account_name, key);
244 empathy_account_settings_set_string (settings, key, v);
247 case DBUS_TYPE_BOOLEAN:
249 gboolean v = gconf_value_get_bool (
250 gconf_entry_get_value (entry));
252 empathy_account_settings_set_boolean (settings, key, v);
256 DEBUG ("Unsupported type in signature: %s", signature);
261 _recurse_account (GSList *entries, EmpathyAccountSettings *settings,
262 const gchar *account_name)
266 for (tmp = entries; tmp != NULL; tmp = tmp->next)
272 entry = (GConfEntry*) tmp->data;
273 param = _param_name_from_key (gconf_entry_get_key (entry));
275 if (g_str_has_prefix (param, "param-"))
277 _handle_entry (settings, account_name, param + strlen ("param-"),
282 gconf_entry_unref (entry);
287 import_one_account (const char *path,
288 EmpathyConnectionManagers *managers,
291 gchar *account_name = _account_name_from_key (path);
292 EmpathyAccountSettings *settings;
293 GError *error = NULL;
294 GSList *entries = NULL;
295 gchar *profile = NULL;
296 gchar *protocol = NULL;
297 const gchar *manager;
300 gboolean enabled = FALSE;
301 gboolean ret = FALSE;
303 DEBUG ("Starting import of %s (%s)", path, account_name);
305 key = g_strdup_printf ("%s/profile", path);
306 profile = gconf_client_get_string (client, key, NULL);
311 DEBUG ("Account is missing a profile entry\n");
315 protocol = _get_protocol_from_profile (profile);
316 manager = _get_manager_for_protocol (managers, protocol);
319 DEBUG ("No manager available for this protocol %s", protocol);
323 key = g_strdup_printf ("%s/display_name", path);
324 display_name = gconf_client_get_string (client, key, NULL);
327 if (display_name == NULL)
328 display_name = _create_default_display_name (protocol);
330 settings = empathy_account_settings_new (manager, protocol, display_name);
331 g_free (display_name);
333 /* Bit of a hack, as we know EmpathyConnectionManagers is ready the
334 * EmpathyAccountSettings should be ready right away as well */
335 g_assert (empathy_account_settings_is_ready (settings));
337 entries = gconf_client_all_entries (client, path, &error);
342 DEBUG ("Failed to get all entries: %s\n", error->message);
343 g_error_free (error);
347 _recurse_account (entries, settings, account_name);
349 key = g_strdup_printf ("%s/enabled", path);
350 enabled = gconf_client_get_bool (client, key, NULL);
352 empathy_account_settings_apply_async (settings,
353 _create_account_cb, GINT_TO_POINTER (enabled));
359 g_slist_free (entries);
360 g_free (account_name);
365 DEBUG ("Failed to import %s", path);
366 if (settings != NULL)
367 g_object_unref (settings);
372 empathy_import_mc4_has_imported (void)
377 client = gconf_client_get_default ();
379 ret = gconf_client_get_bool (client, IMPORTED_MC4_ACCOUNTS, NULL);
380 g_object_unref (client);
386 empathy_import_mc4_accounts (EmpathyConnectionManagers *managers)
389 GError *error = NULL;
390 GSList *dir, *dirs = NULL;
391 gboolean imported_mc4_accounts;
392 gboolean imported = FALSE;
394 g_return_val_if_fail (empathy_connection_managers_is_ready (managers),
397 client = gconf_client_get_default ();
399 imported_mc4_accounts = gconf_client_get_bool (client,
400 IMPORTED_MC4_ACCOUNTS, &error);
404 DEBUG ("Failed to get import_mc4_accounts key: %s\n", error->message);
405 g_clear_error (&error);
406 g_object_unref (client);
410 if (imported_mc4_accounts)
412 DEBUG ("Mc4 accounts already imported");
416 DEBUG ("MC 4 accounts are going to be imported\n");
418 dirs = gconf_client_all_dirs (client, MC_ACCOUNTS_GCONF_BASE, &error);
422 DEBUG ("Failed to get mc_accounts_gconf_base dirs: %s\n",
424 g_clear_error (&error);
425 g_object_unref (client);
429 for (dir = dirs; NULL != dir; dir = dir->next)
431 if (import_one_account ((gchar *)dir->data, managers, client))
436 gconf_client_set_bool (client,
437 IMPORTED_MC4_ACCOUNTS, TRUE, &error);
441 DEBUG ("Failed to set import_mc4_accounts key: %s\n", error->message);
442 g_clear_error (&error);
447 g_object_unref (client);