~bcurtiswx/ubuntu/precise/empathy/3.4.2.1-0ubuntu1

« back to all changes in this revision

Viewing changes to src/empathy-import-mc4-accounts.c

Tags: upstream-2.31.4
ImportĀ upstreamĀ versionĀ 2.31.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2009 Collabora Ltd.
3
 
 *
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.
8
 
 *
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.
13
 
 *
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
18
 
 *
19
 
 * Authors: Arnaud Maillet <arnaud.maillet@collabora.co.uk>
20
 
 */
21
 
 
22
 
#include <config.h>
23
 
 
24
 
#include <stdio.h>
25
 
#include <string.h>
26
 
#include <glib.h>
27
 
#include <glib/gi18n-lib.h>
28
 
#include <gconf/gconf-client.h>
29
 
#include <telepathy-glib/account-manager.h>
30
 
#include <telepathy-glib/util.h>
31
 
#include <telepathy-glib/defs.h>
32
 
#include <dbus/dbus-protocol.h>
33
 
#include <gnome-keyring.h>
34
 
#include <libempathy/empathy-account-settings.h>
35
 
#include <libempathy/empathy-connection-managers.h>
36
 
 
37
 
#include "empathy-import-mc4-accounts.h"
38
 
 
39
 
#define DEBUG_FLAG EMPATHY_DEBUG_IMPORT_MC4_ACCOUNTS
40
 
#include <libempathy/empathy-debug.h>
41
 
 
42
 
#define MC_ACCOUNTS_GCONF_BASE "/apps/telepathy/mc/accounts"
43
 
#define IMPORTED_MC4_ACCOUNTS "/apps/empathy/accounts/imported_mc4_accounts"
44
 
 
45
 
typedef struct
46
 
{
47
 
  gchar *profile;
48
 
  gchar *protocol;
49
 
} ProfileProtocolMapItem;
50
 
 
51
 
static ProfileProtocolMapItem profile_protocol_map[] =
52
 
{
53
 
  { "ekiga", "sip" },
54
 
  { "fwd", "sip" },
55
 
  { "gtalk", "jabber" },
56
 
  { "msn-haze", "msn" },
57
 
  { "salut", "local-xmpp" },
58
 
  { "sipphone", "sip" },
59
 
  { "sofiasip", "sip" },
60
 
};
61
 
 
62
 
typedef struct {
63
 
  gchar *account_name;
64
 
  gboolean enable;
65
 
} Misc;
66
 
 
67
 
static gchar *
68
 
_account_name_from_key (const gchar *key)
69
 
{
70
 
  guint base_len = strlen (MC_ACCOUNTS_GCONF_BASE);
71
 
  const gchar *base, *slash;
72
 
 
73
 
  g_assert (g_str_has_prefix (key, MC_ACCOUNTS_GCONF_BASE));
74
 
  g_assert (strlen (key) > base_len + 1);
75
 
 
76
 
  base = key + base_len + 1;
77
 
  slash = strchr (base, '/');
78
 
 
79
 
  if (slash == NULL)
80
 
    return g_strdup (base);
81
 
  else
82
 
    return g_strndup (base, slash - base);
83
 
}
84
 
 
85
 
static gchar *
86
 
_param_name_from_key (const gchar *key)
87
 
{
88
 
 const gchar *base, *slash;
89
 
 gchar *account_name;
90
 
 gchar *ret;
91
 
 
92
 
 account_name = _account_name_from_key (key);
93
 
 base = strstr (key, account_name);
94
 
 slash = strchr (base, '/');
95
 
 
96
 
 ret = g_strdup (slash+1);
97
 
 g_free (account_name);
98
 
 
99
 
 return ret;
100
 
}
101
 
 
102
 
static gchar *
103
 
_create_default_display_name (const gchar *protocol)
104
 
{
105
 
  if (!tp_strdiff (protocol, "local-xmpp"))
106
 
    return g_strdup (_("People Nearby"));
107
 
 
108
 
  return g_strdup_printf (_("%s account"), protocol);
109
 
}
110
 
 
111
 
static const gchar *
112
 
_get_manager_for_protocol (EmpathyConnectionManagers *managers,
113
 
    const gchar *protocol)
114
 
{
115
 
  GList *cms = empathy_connection_managers_get_cms (managers);
116
 
  GList *l;
117
 
  TpConnectionManager *haze = NULL;
118
 
  TpConnectionManager *cm = NULL;
119
 
 
120
 
  for (l = cms; l; l = l->next)
121
 
    {
122
 
      TpConnectionManager *tp_cm = l->data;
123
 
 
124
 
      /* Only use haze if no other cm provides this protocol */
125
 
      if (!tp_strdiff (tp_connection_manager_get_name (tp_cm), "haze"))
126
 
        {
127
 
          haze = tp_cm;
128
 
          continue;
129
 
        }
130
 
 
131
 
      if (tp_connection_manager_has_protocol (tp_cm, protocol))
132
 
        {
133
 
          cm = tp_cm;
134
 
          goto out;
135
 
        }
136
 
    }
137
 
 
138
 
  if (haze != NULL && tp_connection_manager_has_protocol (haze, protocol))
139
 
    return tp_connection_manager_get_name (haze);
140
 
 
141
 
out:
142
 
  return cm != NULL ? tp_connection_manager_get_name (cm) : NULL;
143
 
}
144
 
 
145
 
static void
146
 
_move_contents (const gchar *old, const gchar *new)
147
 
{
148
 
  GDir *source;
149
 
  const gchar *f;
150
 
  int ret;
151
 
 
152
 
  ret = g_mkdir_with_parents (new, 0777);
153
 
  if (ret == -1)
154
 
    return;
155
 
 
156
 
  source = g_dir_open (old, 0, NULL);
157
 
  if (source == NULL)
158
 
    return;
159
 
 
160
 
  while ((f = g_dir_read_name (source)) != NULL)
161
 
    {
162
 
      gchar *old_path;
163
 
      gchar *new_path;
164
 
 
165
 
      old_path = g_build_path (G_DIR_SEPARATOR_S, old, f, NULL);
166
 
      new_path = g_build_path (G_DIR_SEPARATOR_S, new, f, NULL);
167
 
 
168
 
      if (g_file_test (old_path, G_FILE_TEST_IS_DIR))
169
 
        {
170
 
          _move_contents (old_path, new_path);
171
 
        }
172
 
      else
173
 
        {
174
 
          GFile *f_old, *f_new;
175
 
 
176
 
          f_old = g_file_new_for_path (old_path);
177
 
          f_new = g_file_new_for_path (new_path);
178
 
 
179
 
          g_file_move (f_old, f_new, G_FILE_COPY_NONE,
180
 
            NULL, NULL, NULL, NULL);
181
 
 
182
 
          g_object_unref (f_old);
183
 
          g_object_unref (f_new);
184
 
        }
185
 
 
186
 
      g_free (old_path);
187
 
      g_free (new_path);
188
 
    }
189
 
 
190
 
  g_dir_close (source);
191
 
}
192
 
 
193
 
static void
194
 
_move_logs (TpAccount *account, const gchar *account_name)
195
 
{
196
 
  gchar *old_path, *new_path, *escaped;
197
 
  const gchar *name;
198
 
 
199
 
  name = tp_proxy_get_object_path (account);
200
 
  if (g_str_has_prefix (name, TP_ACCOUNT_OBJECT_PATH_BASE))
201
 
    name += strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
202
 
 
203
 
  escaped = g_strdelimit (g_strdup (name), "/", '_');
204
 
  new_path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (),
205
 
    PACKAGE_NAME, "logs", escaped, NULL);
206
 
  g_free (escaped);
207
 
 
208
 
  old_path = g_build_path (G_DIR_SEPARATOR_S,
209
 
    g_get_home_dir (),
210
 
    ".gnome2", PACKAGE_NAME, "logs", account_name, NULL);
211
 
 
212
 
  _move_contents (old_path, new_path);
213
 
}
214
 
 
215
 
static void
216
 
_create_account_cb (GObject *source,
217
 
  GAsyncResult *result,
218
 
  gpointer user_data)
219
 
{
220
 
  TpAccount *account;
221
 
  GError *error = NULL;
222
 
  Misc *misc = (Misc *) user_data;
223
 
 
224
 
  if (!empathy_account_settings_apply_finish (
225
 
      EMPATHY_ACCOUNT_SETTINGS (source), result, &error))
226
 
    {
227
 
      DEBUG ("Failed to create account: %s", error->message);
228
 
      g_error_free (error);
229
 
      goto out;
230
 
    }
231
 
 
232
 
  DEBUG ("account created");
233
 
  account = empathy_account_settings_get_account (
234
 
    EMPATHY_ACCOUNT_SETTINGS (source));
235
 
 
236
 
  _move_logs (account, misc->account_name);
237
 
 
238
 
  tp_account_set_enabled_async (account,
239
 
      misc->enable, NULL, NULL);
240
 
 
241
 
  g_free (misc->account_name);
242
 
  g_slice_free (Misc, misc);
243
 
 
244
 
out:
245
 
  g_object_unref (source);
246
 
}
247
 
 
248
 
static gchar *
249
 
_get_protocol_from_profile (const gchar *profile)
250
 
{
251
 
  guint i;
252
 
 
253
 
  DEBUG ("profile: %s", profile);
254
 
 
255
 
  for (i = 0; i < G_N_ELEMENTS (profile_protocol_map); i++)
256
 
    if (!tp_strdiff (profile, profile_protocol_map[i].profile))
257
 
      return g_strdup (profile_protocol_map[i].protocol);
258
 
 
259
 
  return g_strdup (profile);
260
 
}
261
 
 
262
 
static void
263
 
_set_password_from_keyring (EmpathyAccountSettings *settings,
264
 
    const gchar *account_name, const gchar *key)
265
 
{
266
 
  GnomeKeyringResult res;
267
 
  gchar *password;
268
 
  GnomeKeyringPasswordSchema keyring_schema = {
269
 
      GNOME_KEYRING_ITEM_GENERIC_SECRET,
270
 
      {
271
 
        { "account", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
272
 
        { "param", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
273
 
        { NULL, 0 }
274
 
      }
275
 
   };
276
 
 
277
 
  res = gnome_keyring_find_password_sync (&keyring_schema,
278
 
    &password,
279
 
    "account", account_name,
280
 
    "param", key,
281
 
    NULL);
282
 
 
283
 
  if (res == GNOME_KEYRING_RESULT_OK)
284
 
    {
285
 
       empathy_account_settings_set_string (settings, key, password);
286
 
       gnome_keyring_free_password (password);
287
 
    }
288
 
}
289
 
 
290
 
static void
291
 
_handle_entry (EmpathyAccountSettings *settings, const gchar *account_name,
292
 
    const gchar *key,
293
 
    GConfEntry *entry)
294
 
{
295
 
  const gchar *signature;
296
 
 
297
 
  signature = empathy_account_settings_get_dbus_signature (settings, key);
298
 
  if (signature == NULL)
299
 
    {
300
 
      DEBUG ("Parameter %s is unknown", signature);
301
 
      return;
302
 
    }
303
 
 
304
 
  switch ((int)*signature)
305
 
    {
306
 
      case DBUS_TYPE_INT16:
307
 
      case DBUS_TYPE_INT32:
308
 
        {
309
 
          gint v = gconf_value_get_int (gconf_entry_get_value (entry));
310
 
          empathy_account_settings_set_int32 (settings, key, v);
311
 
          break;
312
 
        }
313
 
      case DBUS_TYPE_UINT16:
314
 
      case DBUS_TYPE_UINT32:
315
 
        {
316
 
          gint v = gconf_value_get_int (gconf_entry_get_value (entry));
317
 
          empathy_account_settings_set_uint32 (settings, key, v);
318
 
          break;
319
 
        }
320
 
      case DBUS_TYPE_STRING:
321
 
        {
322
 
          const gchar *v = gconf_value_get_string (
323
 
              gconf_entry_get_value (entry));
324
 
 
325
 
          /* MC 4 would put password in the keyring and leave the password in
326
 
           * gconf keyring */
327
 
 
328
 
          if (!tp_strdiff (key, "password") && !tp_strdiff (v, "keyring"))
329
 
            _set_password_from_keyring (settings, account_name, key);
330
 
          else
331
 
              empathy_account_settings_set_string (settings, key, v);
332
 
          break;
333
 
        }
334
 
      case DBUS_TYPE_BOOLEAN:
335
 
        {
336
 
          gboolean v = gconf_value_get_bool (
337
 
              gconf_entry_get_value (entry));
338
 
 
339
 
          empathy_account_settings_set_boolean (settings, key, v);
340
 
          break;
341
 
        }
342
 
     default:
343
 
       DEBUG ("Unsupported type in signature: %s", signature);
344
 
    }
345
 
}
346
 
 
347
 
static void
348
 
_recurse_account (GSList *entries, EmpathyAccountSettings *settings,
349
 
  const gchar *account_name)
350
 
{
351
 
  GSList *tmp;
352
 
 
353
 
  for (tmp = entries; tmp != NULL; tmp = tmp->next)
354
 
    {
355
 
 
356
 
      GConfEntry *entry;
357
 
      gchar *param;
358
 
 
359
 
      entry = (GConfEntry *) tmp->data;
360
 
      param = _param_name_from_key (gconf_entry_get_key (entry));
361
 
 
362
 
      if (g_str_has_prefix (param, "param-"))
363
 
        {
364
 
          _handle_entry (settings, account_name, param + strlen ("param-"),
365
 
            entry);
366
 
        }
367
 
 
368
 
      g_free (param);
369
 
      gconf_entry_unref (entry);
370
 
    }
371
 
}
372
 
 
373
 
static gboolean
374
 
import_one_account (const char *path,
375
 
  EmpathyConnectionManagers *managers,
376
 
  GConfClient *client)
377
 
{
378
 
  gchar *account_name = _account_name_from_key (path);
379
 
  EmpathyAccountSettings *settings = NULL;
380
 
  GError *error = NULL;
381
 
  GSList *entries = NULL;
382
 
  gchar *profile = NULL;
383
 
  gchar *protocol = NULL;
384
 
  const gchar *manager;
385
 
  gchar *display_name;
386
 
  gchar *key;
387
 
  gboolean enabled = FALSE;
388
 
  gboolean ret = FALSE;
389
 
  Misc *misc;
390
 
 
391
 
  DEBUG ("Starting import of %s (%s)", path, account_name);
392
 
 
393
 
  key = g_strdup_printf ("%s/profile", path);
394
 
  profile = gconf_client_get_string (client, key, NULL);
395
 
  g_free (key);
396
 
 
397
 
  if (profile == NULL)
398
 
    {
399
 
      DEBUG ("Account is missing a profile entry");
400
 
      goto failed;
401
 
    }
402
 
 
403
 
  protocol = _get_protocol_from_profile (profile);
404
 
  manager = _get_manager_for_protocol (managers, protocol);
405
 
  if (manager == NULL)
406
 
    {
407
 
      DEBUG ("No manager available for this protocol %s", protocol);
408
 
      goto failed;
409
 
    }
410
 
 
411
 
  key = g_strdup_printf ("%s/display_name", path);
412
 
  display_name = gconf_client_get_string (client, key, NULL);
413
 
  g_free (key);
414
 
 
415
 
  if (display_name == NULL)
416
 
    display_name = _create_default_display_name (protocol);
417
 
 
418
 
  settings = empathy_account_settings_new (manager, protocol, display_name);
419
 
  g_free (display_name);
420
 
 
421
 
  /* Bit of a hack, as we know EmpathyConnectionManagers is ready the
422
 
   * EmpathyAccountSettings should be ready right away as well */
423
 
  g_assert (empathy_account_settings_is_ready (settings));
424
 
 
425
 
  entries = gconf_client_all_entries (client, path, &error);
426
 
 
427
 
  if (entries == NULL)
428
 
    {
429
 
      DEBUG ("Failed to get all entries: %s", error->message);
430
 
      g_error_free (error);
431
 
      goto failed;
432
 
    }
433
 
 
434
 
  _recurse_account (entries, settings, account_name);
435
 
 
436
 
  key = g_strdup_printf ("%s/enabled", path);
437
 
  enabled = gconf_client_get_bool (client, key, NULL);
438
 
  g_free (key);
439
 
 
440
 
  misc = g_slice_new (Misc);
441
 
  misc->account_name = account_name;
442
 
  misc->enable = enabled;
443
 
 
444
 
  empathy_account_settings_apply_async (settings,
445
 
          _create_account_cb, misc);
446
 
  ret = TRUE;
447
 
 
448
 
out:
449
 
  g_free (protocol);
450
 
  g_free (profile);
451
 
  g_slist_free (entries);
452
 
 
453
 
  return ret;
454
 
 
455
 
failed:
456
 
  DEBUG ("Failed to import %s", path);
457
 
  g_free (account_name);
458
 
  if (settings != NULL)
459
 
    g_object_unref (settings);
460
 
  goto out;
461
 
}
462
 
 
463
 
gboolean
464
 
empathy_import_mc4_has_imported (void)
465
 
{
466
 
  GConfClient *client;
467
 
  gboolean ret;
468
 
 
469
 
  client = gconf_client_get_default ();
470
 
 
471
 
  ret = gconf_client_get_bool (client, IMPORTED_MC4_ACCOUNTS, NULL);
472
 
  g_object_unref (client);
473
 
 
474
 
  return ret;
475
 
}
476
 
 
477
 
gboolean
478
 
empathy_import_mc4_accounts (EmpathyConnectionManagers *managers)
479
 
{
480
 
  GConfClient *client;
481
 
  GError *error = NULL;
482
 
  GSList *dir, *dirs = NULL;
483
 
  gboolean imported_mc4_accounts;
484
 
  gboolean imported = FALSE;
485
 
 
486
 
  g_return_val_if_fail (empathy_connection_managers_is_ready (managers),
487
 
    FALSE);
488
 
 
489
 
  client = gconf_client_get_default ();
490
 
 
491
 
  imported_mc4_accounts = gconf_client_get_bool (client,
492
 
      IMPORTED_MC4_ACCOUNTS, &error);
493
 
 
494
 
  if (error != NULL)
495
 
    {
496
 
      DEBUG ("Failed to get import_mc4_accounts key: %s", error->message);
497
 
      g_error_free (error);
498
 
      goto out;
499
 
    }
500
 
 
501
 
  if (imported_mc4_accounts)
502
 
    {
503
 
      DEBUG ("Mc4 accounts previously imported");
504
 
      goto out;
505
 
    }
506
 
 
507
 
  DEBUG ("MC 4 accounts are going to be imported");
508
 
 
509
 
  dirs = gconf_client_all_dirs (client, MC_ACCOUNTS_GCONF_BASE, &error);
510
 
 
511
 
  if (error != NULL)
512
 
    {
513
 
      DEBUG ("Failed to get MC4 account dirs: %s",
514
 
          error->message);
515
 
      g_clear_error (&error);
516
 
      g_object_unref (client);
517
 
      goto out;
518
 
    }
519
 
 
520
 
  for (dir = dirs; NULL != dir; dir = dir->next)
521
 
    {
522
 
      if (import_one_account ((gchar *) dir->data, managers, client))
523
 
        imported = TRUE;
524
 
      g_free (dir->data);
525
 
    }
526
 
 
527
 
out:
528
 
  gconf_client_set_bool (client, IMPORTED_MC4_ACCOUNTS, TRUE, NULL);
529
 
 
530
 
  g_slist_free (dirs);
531
 
  g_object_unref (client);
532
 
  return imported;
533
 
}