~ubuntu-branches/ubuntu/hardy/pidgin/hardy

« back to all changes in this revision

Viewing changes to libpurple/protocols/silc/silc.c

  • Committer: Bazaar Package Importer
  • Author(s): Pedro Fragoso
  • Date: 2007-12-21 02:48:06 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20071221024806-pd44a5k9tiyh12mp
Tags: 1:2.3.1-2ubuntu1
* Sync with Debian, remaining Ubuntu changes; (LP: #177811)
  - Set Maintainer to Ubuntu Core Developers.
  - Add build-deps on liblaunchpad-integration-dev, intltool,
    libnm-glib-dev (for --enable-nm) (Ubuntu #112720).
  - Drop build-deps on libsilc-1.1-2-dev | libsilc-dev (>= 1.1.1) as 
    this library is in universe.
  - Drop the libpurple0 recommends on libpurple-bin.
  - Add a gaim transitionnal package for upgrades.
  - Ship compatibility symlinks via debian/gaim.links.
  - Pass --enable-nm to configure to enable NetworkManager support.
  - Pass --disable-silc to configure to disable silc support even if 
    it's installed in the build environment.
  - Add X-Ubuntu-Gettext-Domain to the desktop file and update the
    translation templates in common-install-impl::.
   - Update debian/prefs.xml to set the notify plugin prefs
    /plugins/gtk/X11/notify/* and set /pidgin/plugins/loaded to load 
    the notify plugin; Ubuntu: #13389.
  - Add LPI integration patch, 02_lpi.
  - Add patch 04_let_crasher_for_apport to stop catching the SIGSEGV signal
    and let apport handle it.
  - Add patch 05_default_to_irc_ubuntu_com to set the default IRC 
    server to irc.ubuntu.com.
  - Add autoconf patch, 70_autoconf.

Show diffs side-by-side

added added

removed removed

Lines of Context:
128
128
                         NULL, 0);
129
129
}
130
130
 
 
131
#if __SILC_TOOLKIT_VERSION < SILC_VERSION(1,1,1)
131
132
static gboolean
132
133
silcpurple_scheduler(gpointer *context)
133
134
{
135
136
        silc_client_run_one(client);
136
137
        return TRUE;
137
138
}
 
139
#else
 
140
typedef struct {
 
141
  SilcPurple sg;
 
142
  SilcUInt32 fd;
 
143
  guint tag;
 
144
} *SilcPurpleTask;
 
145
 
 
146
/* A timeout occurred.  Call SILC scheduler. */
 
147
 
 
148
static gboolean
 
149
silcpurple_scheduler_timeout(gpointer context)
 
150
{
 
151
        SilcPurpleTask task = (SilcPurpleTask)context;
 
152
        silc_client_run_one(task->sg->client);
 
153
        silc_dlist_del(task->sg->tasks, task);
 
154
        silc_free(task);
 
155
        return FALSE;
 
156
}
 
157
 
 
158
/* An fd task event occurred.  Call SILC scheduler. */
 
159
 
 
160
static void
 
161
silcpurple_scheduler_fd(gpointer data, gint fd, PurpleInputCondition cond)
 
162
{
 
163
        SilcClient client = (SilcClient)data;
 
164
        silc_client_run_one(client);
 
165
}
 
166
 
 
167
/* SILC Scheduler notify callback.  This is called whenever task is added to
 
168
   or deleted from SILC scheduler.  It's also called when fd task events
 
169
   change.  Here we add same tasks to glib's main loop. */
 
170
 
 
171
static void
 
172
silcpurple_scheduler(SilcSchedule schedule,
 
173
                     SilcBool added, SilcTask task,
 
174
                     SilcBool fd_task, SilcUInt32 fd,
 
175
                     SilcTaskEvent event,
 
176
                     long seconds, long useconds,
 
177
                     void *context)
 
178
{
 
179
        SilcClient client = (SilcClient)context;
 
180
        PurpleConnection *gc = client->application;
 
181
        SilcPurple sg = gc->proto_data;
 
182
        SilcPurpleTask ptask = NULL;
 
183
 
 
184
        if (added) {
 
185
          if (fd_task) {
 
186
            /* Add fd or change fd events */
 
187
            PurpleInputCondition e = 0;
 
188
 
 
189
            silc_dlist_start(sg->tasks);
 
190
            while ((ptask = silc_dlist_get(sg->tasks)))
 
191
              if (ptask->fd == fd) {
 
192
                purple_input_remove(ptask->tag);
 
193
                break;
 
194
              }
 
195
 
 
196
            if (event & SILC_TASK_READ)
 
197
              e |= PURPLE_INPUT_READ;
 
198
            if (event & SILC_TASK_WRITE)
 
199
              e |= PURPLE_INPUT_WRITE;
 
200
 
 
201
            if (e) {
 
202
              if (!ptask) {
 
203
                ptask = silc_calloc(1, sizeof(*ptask));
 
204
                ptask->fd = fd;
 
205
                silc_dlist_add(sg->tasks, ptask);
 
206
              }
 
207
              ptask->tag = purple_input_add(fd, e, silcpurple_scheduler_fd,
 
208
                                            client);
 
209
            } else if (ptask) {
 
210
              silc_dlist_del(sg->tasks, ptask);
 
211
              silc_free(ptask);
 
212
            }
 
213
          } else {
 
214
            /* Add timeout */
 
215
            ptask = silc_calloc(1, sizeof(*ptask));
 
216
            ptask->sg = sg;
 
217
            ptask->tag = purple_timeout_add((seconds * 1000) +
 
218
                                            (useconds / 1000),
 
219
                                            silcpurple_scheduler_timeout,
 
220
                                            ptask);
 
221
            silc_dlist_add(sg->tasks, ptask);
 
222
          }
 
223
        } else {
 
224
          if (fd_task) {
 
225
            /* Remove fd */
 
226
            silc_dlist_start(sg->tasks);
 
227
            while ((ptask = silc_dlist_get(sg->tasks)))
 
228
              if (ptask->fd == fd) {
 
229
                purple_input_remove(ptask->tag);
 
230
                silc_dlist_del(sg->tasks, ptask);
 
231
                silc_free(ptask);
 
232
                break;
 
233
              }
 
234
          }
 
235
        }
 
236
}
 
237
#endif /* __SILC_TOOLKIT_VERSION */
138
238
 
139
239
static void
140
240
silcpurple_connect_cb(SilcClient client, SilcClientConnection conn,
214
314
 
215
315
                /* Close the connection */
216
316
                if (!sg->detaching)
217
 
                  purple_connection_error(gc, _("Disconnected by server"));
 
317
                  purple_connection_error_reason(gc,
 
318
                                                 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 
319
                                                 _("Disconnected by server"));
218
320
                else
219
321
                  /* TODO: Does this work correctly? Maybe we need to set wants_to_die? */
220
322
                  purple_account_disconnect(purple_connection_get_account(gc));
221
323
                break;
222
324
 
223
325
        case SILC_CLIENT_CONN_ERROR:
224
 
                purple_connection_error(gc, _("Error during connecting to SILC Server"));
 
326
                purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 
327
                                             _("Error during connecting to SILC Server"));
225
328
                g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
226
329
                break;
227
330
 
228
331
        case SILC_CLIENT_CONN_ERROR_KE:
229
 
                purple_connection_error(gc, _("Key Exchange failed"));
 
332
                purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
 
333
                                             _("Key Exchange failed"));
230
334
                break;
231
335
 
232
336
        case SILC_CLIENT_CONN_ERROR_AUTH:
233
 
                purple_connection_error(gc, _("Authentication failed"));
 
337
                purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
 
338
                                             _("Authentication failed"));
234
339
                break;
235
340
 
236
341
        case SILC_CLIENT_CONN_ERROR_RESUME:
237
 
                purple_connection_error(gc,
238
 
                                      _("Resuming detached session failed. "
239
 
                                        "Press Reconnect to create new connection."));
 
342
                purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 
343
                                             _("Resuming detached session failed. "
 
344
                                               "Press Reconnect to create new connection."));
240
345
                g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
241
346
                break;
242
347
 
243
348
        case SILC_CLIENT_CONN_ERROR_TIMEOUT:
244
 
                purple_connection_error(gc, _("Connection Timeout"));
 
349
                purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 
350
                                             _("Connection Timeout"));
245
351
                break;
246
352
        }
247
353
 
262
368
        sg = gc->proto_data;
263
369
 
264
370
        if (status != SILC_SOCKET_OK) {
265
 
                purple_connection_error(gc, _("Connection failed"));
 
371
                purple_connection_error_reason(gc,
 
372
                        PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 
373
                        _("Connection failed"));
266
374
                silc_pkcs_public_key_free(sg->public_key);
267
375
                silc_pkcs_private_key_free(sg->private_key);
268
376
                silc_free(sg);
308
416
        sg = gc->proto_data;
309
417
 
310
418
        if (source < 0) {
311
 
                purple_connection_error(gc, _("Connection failed"));
 
419
                purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 
420
                                             _("Connection failed"));
312
421
                silc_pkcs_public_key_free(sg->public_key);
313
422
                silc_pkcs_private_key_free(sg->private_key);
314
423
                silc_free(sg);
316
425
                return;
317
426
        }
318
427
 
 
428
        silc_hash_alloc((unsigned char *)"sha1", &sg->sha1hash);
 
429
 
319
430
        /* Wrap socket to TCP stream */
320
431
        silc_socket_tcp_stream_create(source, TRUE, FALSE,
321
432
                                      sg->client->schedule,
324
435
 
325
436
static void silcpurple_running(SilcClient client, void *context)
326
437
{
327
 
        PurpleAccount *account = context;
328
 
        PurpleConnection *gc = account->gc;
329
 
        SilcPurple sg;
 
438
        SilcPurple sg = context;
 
439
        PurpleConnection *gc = sg->gc;
 
440
        PurpleAccount *account = purple_connection_get_account(gc);
330
441
        char pkd[256], prd[256];
331
442
 
332
 
        sg = silc_calloc(1, sizeof(*sg));
333
 
        if (!sg)
334
 
                return;
335
 
        memset(sg, 0, sizeof(*sg));
336
 
        sg->client = client;
337
 
        sg->gc = gc;
338
 
        sg->account = account;
339
 
        sg->scheduler = SILC_PTR_TO_32(gc->proto_data);
340
 
        gc->proto_data = sg;
341
443
 
342
444
        /* Progress */
343
445
        purple_connection_update_progress(gc, _("Connecting to SILC Server"), 1, 5);
349
451
                                (char *)purple_account_get_string(account, "private-key", prd),
350
452
                                (gc->password == NULL) ? "" : gc->password,
351
453
                                &sg->public_key, &sg->private_key)) {
352
 
                g_snprintf(pkd, sizeof(pkd), _("Could not load SILC key pair"));
353
 
                purple_connection_error(gc, pkd);
 
454
                purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 
455
                                             _("Could not load SILC key pair"));
354
456
                gc->proto_data = NULL;
355
457
                silc_free(sg);
356
458
                return;
363
465
                                 purple_account_get_int(account, "port", 706),
364
466
                                 silcpurple_login_connected, gc) == NULL)
365
467
        {
366
 
                purple_connection_error(gc, _("Unable to create connection"));
 
468
                purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 
469
                                             _("Unable to create connection"));
367
470
                gc->proto_data = NULL;
368
471
                silc_free(sg);
369
472
                return;
375
478
{
376
479
        SilcClient client;
377
480
        PurpleConnection *gc;
 
481
        SilcPurple sg;
378
482
        SilcClientParams params;
379
483
        const char *cipher, *hmac;
380
484
        char *username, *hostname, *realname, **up;
381
 
        guint scheduler;
382
485
        int i;
383
486
 
384
487
        gc = account->gc;
392
495
        /* Allocate SILC client */
393
496
        client = silc_client_alloc(&ops, &params, gc, NULL);
394
497
        if (!client) {
395
 
                purple_connection_error(gc, _("Out of memory"));
 
498
                purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 
499
                                             _("Out of memory"));
396
500
                return;
397
501
        }
398
502
 
431
535
                        break;
432
536
                }
433
537
 
 
538
        sg = silc_calloc(1, sizeof(*sg));
 
539
        if (!sg)
 
540
                return;
 
541
        sg->client = client;
 
542
        sg->gc = gc;
 
543
        sg->account = account;
 
544
        gc->proto_data = sg;
 
545
 
434
546
        /* Init SILC client */
435
547
        if (!silc_client_init(client, username, hostname, realname,
436
 
                              silcpurple_running, account)) {
437
 
                gc->wants_to_die = TRUE;
438
 
                purple_connection_error(gc, _("Cannot initialize SILC protocol"));
 
548
                              silcpurple_running, sg)) {
 
549
                purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 
550
                                             _("Cannot initialize SILC protocol"));
 
551
                gc->proto_data = NULL;
 
552
                silc_free(sg);
439
553
                return;
440
554
        }
441
555
 
442
556
        /* Check the ~/.silc dir and create it, and new key pair if necessary. */
443
557
        if (!silcpurple_check_silc_dir(gc)) {
444
 
                gc->wants_to_die = TRUE;
445
 
                purple_connection_error(gc, _("Error loading SILC key pair"));
 
558
                purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 
559
                                             _("Error loading SILC key pair"));
 
560
                gc->proto_data = NULL;
 
561
                silc_free(sg);
446
562
                return;
447
563
        }
448
564
 
 
565
#if __SILC_TOOLKIT_VERSION < SILC_VERSION(1,1,1)
449
566
        /* Schedule SILC using Glib's event loop */
450
 
        scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, client);
451
 
        gc->proto_data = SILC_32_TO_PTR(scheduler);
 
567
        sg->scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, client);
 
568
#else
 
569
        /* Run SILC scheduler */
 
570
        sg->tasks = silc_dlist_init();
 
571
        silc_schedule_set_notify(client->schedule, silcpurple_scheduler,
 
572
                                 client);
 
573
        silc_client_run_one(client);
 
574
#endif /* __SILC_TOOLKIT_VERSION */
452
575
}
453
576
 
454
577
static int
455
578
silcpurple_close_final(gpointer *context)
456
579
{
457
580
        SilcPurple sg = (SilcPurple)context;
 
581
 
458
582
        silc_client_stop(sg->client, NULL, NULL);
459
583
        silc_client_free(sg->client);
 
584
        if (sg->sha1hash)
 
585
                silc_hash_free(sg->sha1hash);
460
586
        if (sg->mimeass)
461
587
                silc_mime_assembler_free(sg->mimeass);
462
588
        silc_free(sg);
467
593
silcpurple_close(PurpleConnection *gc)
468
594
{
469
595
        SilcPurple sg = gc->proto_data;
 
596
#if __SILC_TOOLKIT_VERSION >= SILC_VERSION(1,1,1)
 
597
        SilcPurpleTask task;
 
598
#endif /* __SILC_TOOLKIT_VERSION */
470
599
 
471
600
        g_return_if_fail(sg != NULL);
472
601
 
473
602
        /* Send QUIT */
474
603
        silc_client_command_call(sg->client, sg->conn, NULL,
475
 
                                 "QUIT", "Download Pidgin: " PURPLE_WEBSITE, NULL);
 
604
                                 "QUIT", "Download Pidgin: " PURPLE_WEBSITE,
 
605
                                 NULL);
476
606
 
477
607
        if (sg->conn)
478
608
                silc_client_close_connection(sg->client, sg->conn);
479
609
 
 
610
#if __SILC_TOOLKIT_VERSION >= SILC_VERSION(1,1,1)
 
611
        if (sg->conn)
 
612
          silc_client_run_one(sg->client);
 
613
        silc_schedule_set_notify(sg->client->schedule, NULL, NULL);
 
614
 
 
615
        silc_dlist_start(sg->tasks);
 
616
        while ((task = silc_dlist_get(sg->tasks))) {
 
617
          purple_input_remove(task->tag);
 
618
          silc_free(task);
 
619
        }
 
620
        silc_dlist_uninit(sg->tasks);
 
621
#endif /* __SILC_TOOLKIT_VERSION */
 
622
 
480
623
        purple_timeout_remove(sg->scheduler);
481
624
        purple_timeout_add(1, (GSourceFunc)silcpurple_close_final, sg);
482
625
}
1155
1298
                        silc_dlist_start(list);
1156
1299
                        while ((buf = silc_dlist_get(list)) != SILC_LIST_END)
1157
1300
                                silc_client_send_private_message(client, conn,
1158
 
                                                                 client_entry, im->flags, NULL,
 
1301
                                                                 client_entry, im->flags, sg->sha1hash,
1159
1302
                                                                 buf->data,
1160
1303
                                                                 silc_buffer_len(buf));
1161
1304
                        silc_mime_partial_free(list);
1167
1310
 
1168
1311
        /* Send the message */
1169
1312
        silc_client_send_private_message(client, conn, client_entry, im->flags,
1170
 
                                         NULL, (unsigned char *)im->message, im->message_len);
 
1313
                                         sg->sha1hash, (unsigned char *)im->message, im->message_len);
1171
1314
        purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname,
1172
1315
                             im->message, 0, time(NULL));
1173
1316
        goto out;
1259
1402
                        while ((buf = silc_dlist_get(list)) != SILC_LIST_END)
1260
1403
                                ret =
1261
1404
                                silc_client_send_private_message(client, conn,
1262
 
                                                                 client_entry, mflags, NULL,
 
1405
                                                                 client_entry, mflags, sg->sha1hash,
1263
1406
                                                                 buf->data,
1264
1407
                                                                 silc_buffer_len(buf));
1265
1408
                        silc_mime_partial_free(list);
1271
1414
 
1272
1415
        /* Send private message directly */
1273
1416
        ret = silc_client_send_private_message(client, conn, client_entry,
1274
 
                                               mflags, NULL,
 
1417
                                               mflags, sg->sha1hash,
1275
1418
                                               (unsigned char *)msg,
1276
1419
                                               strlen(msg));
1277
1420