Coverage Report

Created: 2025-12-31 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pidgin/libpurple/connection.c
Line
Count
Source
1
/**
2
 * @file connection.c Connection API
3
 * @ingroup core
4
 */
5
6
/* purple
7
 *
8
 * Purple is the legal property of its developers, whose names are too numerous
9
 * to list here.  Please refer to the COPYRIGHT file distributed with this
10
 * source distribution.
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
25
 */
26
#define _PURPLE_CONNECTION_C_
27
28
#include "internal.h"
29
#include "account.h"
30
#include "blist.h"
31
#include "connection.h"
32
#include "dbus-maybe.h"
33
#include "debug.h"
34
#include "log.h"
35
#include "notify.h"
36
#include "prefs.h"
37
#include "proxy.h"
38
#include "request.h"
39
#include "server.h"
40
#include "signals.h"
41
#include "util.h"
42
43
0
#define KEEPALIVE_INTERVAL 30
44
45
static GList *connections = NULL;
46
static GList *connections_connecting = NULL;
47
static PurpleConnectionUiOps *connection_ui_ops = NULL;
48
49
static int connections_handle;
50
51
static gboolean
52
send_keepalive(gpointer data)
53
0
{
54
0
  PurpleConnection *gc = data;
55
0
  PurplePluginProtocolInfo *prpl_info;
56
57
  /* Only send keep-alives if we haven't heard from the
58
   * server in a while.
59
   */
60
0
  if ((time(NULL) - gc->last_received) < KEEPALIVE_INTERVAL)
61
0
    return TRUE;
62
63
0
  prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
64
0
  if (prpl_info->keepalive)
65
0
    prpl_info->keepalive(gc);
66
67
0
  return TRUE;
68
0
}
69
70
static void
71
update_keepalive(PurpleConnection *gc, gboolean on)
72
0
{
73
0
  PurplePluginProtocolInfo *prpl_info = NULL;
74
75
0
  if (gc != NULL && gc->prpl != NULL)
76
0
    prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
77
78
0
  if (!prpl_info || !prpl_info->keepalive)
79
0
    return;
80
81
0
  if (on && !gc->keepalive)
82
0
  {
83
0
    purple_debug_info("connection", "Activating keepalive.\n");
84
0
    gc->keepalive = purple_timeout_add_seconds(KEEPALIVE_INTERVAL, send_keepalive, gc);
85
0
  }
86
0
  else if (!on && gc->keepalive > 0)
87
0
  {
88
0
    purple_debug_info("connection", "Deactivating keepalive.\n");
89
0
    purple_timeout_remove(gc->keepalive);
90
0
    gc->keepalive = 0;
91
0
  }
92
0
}
93
94
void
95
purple_connection_new(PurpleAccount *account, gboolean regist, const char *password)
96
0
{
97
0
  _purple_connection_new(account, regist, password);
98
0
}
99
100
void
101
_purple_connection_new(PurpleAccount *account, gboolean regist, const char *password)
102
0
{
103
0
  PurpleConnection *gc;
104
0
  PurplePlugin *prpl;
105
0
  PurplePluginProtocolInfo *prpl_info;
106
107
0
  g_return_if_fail(account != NULL);
108
109
0
  if (!purple_account_is_disconnected(account))
110
0
    return;
111
112
0
  prpl = purple_find_prpl(purple_account_get_protocol_id(account));
113
114
0
  if (prpl != NULL)
115
0
    prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
116
0
  else {
117
0
    gchar *message;
118
119
0
    message = g_strdup_printf(_("Missing protocol plugin for %s"),
120
0
      purple_account_get_username(account));
121
0
    purple_notify_error(NULL, regist ? _("Registration Error") :
122
0
              _("Connection Error"), message, NULL);
123
0
    g_free(message);
124
0
    return;
125
0
  }
126
127
0
  if (regist)
128
0
  {
129
0
    if (prpl_info->register_user == NULL)
130
0
      return;
131
0
  }
132
0
  else
133
0
  {
134
0
    if (((password == NULL) || (*password == '\0')) &&
135
0
      !(prpl_info->options & OPT_PROTO_NO_PASSWORD) &&
136
0
      !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL))
137
0
    {
138
0
      purple_debug_error("connection", "Cannot connect to account %s without "
139
0
               "a password.\n", purple_account_get_username(account));
140
0
      return;
141
0
    }
142
0
  }
143
144
0
  gc = g_new0(PurpleConnection, 1);
145
0
  PURPLE_DBUS_REGISTER_POINTER(gc, PurpleConnection);
146
147
0
  gc->prpl = prpl;
148
0
  if ((password != NULL) && (*password != '\0'))
149
0
    gc->password = g_strdup(password);
150
0
  purple_connection_set_account(gc, account);
151
0
  purple_connection_set_state(gc, PURPLE_CONNECTING);
152
0
  connections = g_list_append(connections, gc);
153
0
  purple_account_set_connection(account, gc);
154
155
0
  purple_signal_emit(purple_connections_get_handle(), "signing-on", gc);
156
157
0
  if (regist)
158
0
  {
159
0
    purple_debug_info("connection", "Registering.  gc = %p\n", gc);
160
161
    /* set this so we don't auto-reconnect after registering */
162
0
    gc->wants_to_die = TRUE;
163
164
0
    prpl_info->register_user(account);
165
0
  }
166
0
  else
167
0
  {
168
0
    purple_debug_info("connection", "Connecting. gc = %p\n", gc);
169
170
0
    purple_signal_emit(purple_accounts_get_handle(), "account-connecting", account);
171
0
    prpl_info->login(account);
172
0
  }
173
0
}
174
void
175
purple_connection_new_unregister(PurpleAccount *account, const char *password, PurpleAccountUnregistrationCb cb, void *user_data)
176
0
{
177
0
  _purple_connection_new_unregister(account, password, cb, user_data);
178
0
}
179
180
void
181
_purple_connection_new_unregister(PurpleAccount *account, const char *password, PurpleAccountUnregistrationCb cb, void *user_data)
182
0
{
183
  /* Lots of copy/pasted code to avoid API changes. You might want to integrate that into the previous function when posssible. */
184
0
  PurpleConnection *gc;
185
0
  PurplePlugin *prpl;
186
0
  PurplePluginProtocolInfo *prpl_info;
187
188
0
  g_return_if_fail(account != NULL);
189
190
0
  prpl = purple_find_prpl(purple_account_get_protocol_id(account));
191
192
0
  if (prpl != NULL)
193
0
    prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
194
0
  else {
195
0
    gchar *message;
196
197
0
    message = g_strdup_printf(_("Missing protocol plugin for %s"),
198
0
                  purple_account_get_username(account));
199
0
    purple_notify_error(NULL, _("Unregistration Error"), message, NULL);
200
0
    g_free(message);
201
0
    return;
202
0
  }
203
204
0
  if (!purple_account_is_disconnected(account)) {
205
0
    prpl_info->unregister_user(account, cb, user_data);
206
0
    return;
207
0
  }
208
209
0
  if (((password == NULL) || (*password == '\0')) &&
210
0
    !(prpl_info->options & OPT_PROTO_NO_PASSWORD) &&
211
0
    !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL))
212
0
  {
213
0
    purple_debug_error("connection", "Cannot connect to account %s without "
214
0
               "a password.\n", purple_account_get_username(account));
215
0
    return;
216
0
  }
217
218
0
  gc = g_new0(PurpleConnection, 1);
219
0
  PURPLE_DBUS_REGISTER_POINTER(gc, PurpleConnection);
220
221
0
  gc->prpl = prpl;
222
0
  if ((password != NULL) && (*password != '\0'))
223
0
    gc->password = g_strdup(password);
224
0
  purple_connection_set_account(gc, account);
225
0
  purple_connection_set_state(gc, PURPLE_CONNECTING);
226
0
  connections = g_list_append(connections, gc);
227
0
  purple_account_set_connection(account, gc);
228
229
0
  purple_signal_emit(purple_connections_get_handle(), "signing-on", gc);
230
231
0
  purple_debug_info("connection", "Unregistering.  gc = %p\n", gc);
232
233
0
  prpl_info->unregister_user(account, cb, user_data);
234
0
}
235
236
void
237
purple_connection_destroy(PurpleConnection *gc)
238
0
{
239
0
  _purple_connection_destroy(gc);
240
0
}
241
242
void
243
_purple_connection_destroy(PurpleConnection *gc)
244
0
{
245
0
  PurpleAccount *account;
246
0
  GSList *buddies;
247
0
  PurplePluginProtocolInfo *prpl_info = NULL;
248
0
  gboolean remove = FALSE;
249
250
0
  g_return_if_fail(gc != NULL);
251
252
0
  account = purple_connection_get_account(gc);
253
254
0
  purple_debug_info("connection", "Disconnecting connection %p\n", gc);
255
256
0
  if (purple_connection_get_state(gc) != PURPLE_CONNECTING)
257
0
    remove = TRUE;
258
259
0
  purple_signal_emit(purple_connections_get_handle(), "signing-off", gc);
260
261
0
  while (gc->buddy_chats)
262
0
  {
263
0
    PurpleConversation *b = gc->buddy_chats->data;
264
265
0
    gc->buddy_chats = g_slist_remove(gc->buddy_chats, b);
266
0
    purple_conv_chat_left(PURPLE_CONV_CHAT(b));
267
0
  }
268
269
0
  update_keepalive(gc, FALSE);
270
271
0
  purple_proxy_connect_cancel_with_handle(gc);
272
273
0
  prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
274
0
  if (prpl_info->close)
275
0
    (prpl_info->close)(gc);
276
277
  /* Clear out the proto data that was freed in the prpl close method*/
278
0
  buddies = purple_find_buddies(account, NULL);
279
0
  while (buddies != NULL) {
280
0
    PurpleBuddy *buddy = buddies->data;
281
0
    purple_buddy_set_protocol_data(buddy, NULL);
282
0
    buddies = g_slist_delete_link(buddies, buddies);
283
0
  }
284
285
0
  connections = g_list_remove(connections, gc);
286
287
0
  purple_connection_set_state(gc, PURPLE_DISCONNECTED);
288
289
0
  if (remove)
290
0
    purple_blist_remove_account(account);
291
292
0
  purple_signal_emit(purple_connections_get_handle(), "signed-off", gc);
293
294
0
  purple_account_request_close_with_account(account);
295
0
  purple_request_close_with_handle(gc);
296
0
  purple_notify_close_with_handle(gc);
297
298
0
  purple_debug_info("connection", "Destroying connection %p\n", gc);
299
300
0
  purple_account_set_connection(account, NULL);
301
302
0
  g_free(gc->password);
303
0
  g_free(gc->display_name);
304
305
0
  if (gc->disconnect_timeout > 0)
306
0
    purple_timeout_remove(gc->disconnect_timeout);
307
308
0
  PURPLE_DBUS_UNREGISTER_POINTER(gc);
309
0
  g_free(gc);
310
0
}
311
312
/*
313
 * d:)->-<
314
 *
315
 * d:O-\-<
316
 *
317
 * d:D-/-<
318
 *
319
 * d8D->-< DANCE!
320
 */
321
322
void
323
purple_connection_set_state(PurpleConnection *gc, PurpleConnectionState state)
324
0
{
325
0
  PurpleConnectionUiOps *ops;
326
327
0
  g_return_if_fail(gc != NULL);
328
329
0
  if (gc->state == state)
330
0
    return;
331
332
0
  gc->state = state;
333
334
0
  ops = purple_connections_get_ui_ops();
335
336
0
  if (gc->state == PURPLE_CONNECTING) {
337
0
    connections_connecting = g_list_append(connections_connecting, gc);
338
0
  }
339
0
  else {
340
0
    connections_connecting = g_list_remove(connections_connecting, gc);
341
0
  }
342
343
0
  if (gc->state == PURPLE_CONNECTED) {
344
0
    PurpleAccount *account;
345
0
    PurplePresence *presence;
346
347
0
    account = purple_connection_get_account(gc);
348
0
    presence = purple_account_get_presence(account);
349
350
    /* Set the time the account came online */
351
0
    purple_presence_set_login_time(presence, time(NULL));
352
353
0
    if (purple_prefs_get_bool("/purple/logging/log_system"))
354
0
    {
355
0
      PurpleLog *log = purple_account_get_log(account, TRUE);
356
357
0
      if (log != NULL)
358
0
      {
359
0
        char *msg = g_strdup_printf(_("+++ %s signed on"),
360
0
                      purple_account_get_username(account));
361
0
        purple_log_write(log, PURPLE_MESSAGE_SYSTEM,
362
0
                 purple_account_get_username(account),
363
0
                 purple_presence_get_login_time(presence),
364
0
                 msg);
365
0
        g_free(msg);
366
0
      }
367
0
    }
368
369
0
    if (ops != NULL && ops->connected != NULL)
370
0
      ops->connected(gc);
371
372
0
    purple_blist_add_account(account);
373
374
0
    purple_signal_emit(purple_connections_get_handle(), "signed-on", gc);
375
0
    purple_signal_emit_return_1(purple_connections_get_handle(), "autojoin", gc);
376
377
0
    serv_set_permit_deny(gc);
378
379
0
    update_keepalive(gc, TRUE);
380
0
  }
381
0
  else if (gc->state == PURPLE_DISCONNECTED) {
382
0
    PurpleAccount *account = purple_connection_get_account(gc);
383
384
0
    if (purple_prefs_get_bool("/purple/logging/log_system"))
385
0
    {
386
0
      PurpleLog *log = purple_account_get_log(account, FALSE);
387
388
0
      if (log != NULL)
389
0
      {
390
0
        char *msg = g_strdup_printf(_("+++ %s signed off"),
391
0
                      purple_account_get_username(account));
392
0
        purple_log_write(log, PURPLE_MESSAGE_SYSTEM,
393
0
                 purple_account_get_username(account), time(NULL),
394
0
                 msg);
395
0
        g_free(msg);
396
0
      }
397
0
    }
398
399
0
    purple_account_destroy_log(account);
400
401
0
    if (ops != NULL && ops->disconnected != NULL)
402
0
      ops->disconnected(gc);
403
0
  }
404
0
}
405
406
void
407
purple_connection_set_account(PurpleConnection *gc, PurpleAccount *account)
408
0
{
409
0
  g_return_if_fail(gc != NULL);
410
0
  g_return_if_fail(account != NULL);
411
412
0
  gc->account = account;
413
0
}
414
415
void
416
purple_connection_set_display_name(PurpleConnection *gc, const char *name)
417
0
{
418
0
  g_return_if_fail(gc != NULL);
419
420
0
  g_free(gc->display_name);
421
0
  gc->display_name = g_strdup(name);
422
0
}
423
424
void
425
0
purple_connection_set_protocol_data(PurpleConnection *connection, void *proto_data) {
426
0
  g_return_if_fail(connection != NULL);
427
428
0
  connection->proto_data = proto_data;
429
0
}
430
431
PurpleConnectionState
432
purple_connection_get_state(const PurpleConnection *gc)
433
0
{
434
0
  g_return_val_if_fail(gc != NULL, PURPLE_DISCONNECTED);
435
436
0
  return gc->state;
437
0
}
438
439
PurpleAccount *
440
purple_connection_get_account(const PurpleConnection *gc)
441
0
{
442
0
  g_return_val_if_fail(gc != NULL, NULL);
443
444
0
  return gc->account;
445
0
}
446
447
PurplePlugin *
448
purple_connection_get_prpl(const PurpleConnection *gc)
449
0
{
450
0
  g_return_val_if_fail(gc != NULL, NULL);
451
452
0
  return gc->prpl;
453
0
}
454
455
const char *
456
purple_connection_get_password(const PurpleConnection *gc)
457
0
{
458
0
  g_return_val_if_fail(gc != NULL, NULL);
459
460
0
  return gc->password ? gc->password : gc->account->password;
461
0
}
462
463
const char *
464
purple_connection_get_display_name(const PurpleConnection *gc)
465
0
{
466
0
  g_return_val_if_fail(gc != NULL, NULL);
467
468
0
  return gc->display_name;
469
0
}
470
471
void *
472
0
purple_connection_get_protocol_data(const PurpleConnection *connection) {
473
0
  g_return_val_if_fail(connection != NULL, NULL);
474
475
0
  return connection->proto_data;
476
0
}
477
478
void
479
purple_connection_update_progress(PurpleConnection *gc, const char *text,
480
                size_t step, size_t count)
481
0
{
482
0
  PurpleConnectionUiOps *ops;
483
484
0
  g_return_if_fail(gc   != NULL);
485
0
  g_return_if_fail(text != NULL);
486
0
  g_return_if_fail(step < count);
487
0
  g_return_if_fail(count > 1);
488
489
0
  ops = purple_connections_get_ui_ops();
490
491
0
  if (ops != NULL && ops->connect_progress != NULL)
492
0
    ops->connect_progress(gc, text, step, count);
493
0
}
494
495
void
496
purple_connection_notice(PurpleConnection *gc, const char *text)
497
0
{
498
0
  PurpleConnectionUiOps *ops;
499
500
0
  g_return_if_fail(gc   != NULL);
501
0
  g_return_if_fail(text != NULL);
502
503
0
  ops = purple_connections_get_ui_ops();
504
505
0
  if (ops != NULL && ops->notice != NULL)
506
0
    ops->notice(gc, text);
507
0
}
508
509
static gboolean
510
purple_connection_disconnect_cb(gpointer data)
511
0
{
512
0
  PurpleAccount *account;
513
0
  PurpleConnection *gc;
514
0
  char *password;
515
516
0
  account = data;
517
0
  gc = purple_account_get_connection(account);
518
519
0
  if (gc != NULL)
520
0
    gc->disconnect_timeout = 0;
521
522
0
  password = g_strdup(purple_account_get_password(account));
523
0
  purple_account_disconnect(account);
524
0
  purple_account_set_password(account, password);
525
0
  g_free(password);
526
527
0
  return FALSE;
528
0
}
529
530
void
531
purple_connection_error(PurpleConnection *gc, const char *text)
532
0
{
533
  /* prpls that have not been updated to use disconnection reasons will
534
   * be setting wants_to_die before calling this function, so choose
535
   * PURPLE_CONNECTION_ERROR_OTHER_ERROR (which is fatal) if it's true,
536
   * and PURPLE_CONNECTION_ERROR_NETWORK_ERROR (which isn't) if not.  See
537
   * the documentation in connection.h.
538
   */
539
0
  PurpleConnectionError reason = gc->wants_to_die
540
0
                               ? PURPLE_CONNECTION_ERROR_OTHER_ERROR
541
0
                               : PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
542
0
  purple_connection_error_reason (gc, reason, text);
543
0
}
544
545
void
546
purple_connection_error_reason (PurpleConnection *gc,
547
                                PurpleConnectionError reason,
548
                                const char *description)
549
0
{
550
0
  PurpleConnectionUiOps *ops;
551
552
0
  g_return_if_fail(gc   != NULL);
553
  /* This sanity check relies on PURPLE_CONNECTION_ERROR_OTHER_ERROR
554
   * being the last member of the PurpleConnectionError enum in
555
   * connection.h; if other reasons are added after it, this check should
556
   * be updated.
557
   */
558
0
  if (reason > PURPLE_CONNECTION_ERROR_OTHER_ERROR) {
559
0
    purple_debug_error("connection",
560
0
      "purple_connection_error_reason: reason %u isn't a "
561
0
      "valid reason\n", reason);
562
0
    reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
563
0
  }
564
565
0
  if (description == NULL) {
566
0
    purple_debug_error("connection", "purple_connection_error_reason called with NULL description\n");
567
0
    description = _("Unknown error");
568
0
  }
569
570
  /* If we've already got one error, we don't need any more */
571
0
  if (gc->disconnect_timeout > 0)
572
0
    return;
573
574
0
  gc->wants_to_die = purple_connection_error_is_fatal (reason);
575
576
0
  purple_debug_info("connection", "Connection error on %p (reason: %u description: %s)\n",
577
0
                    gc, reason, description);
578
579
0
  ops = purple_connections_get_ui_ops();
580
581
0
  if (ops != NULL)
582
0
  {
583
0
    if (ops->report_disconnect_reason != NULL)
584
0
      ops->report_disconnect_reason (gc, reason, description);
585
0
    if (ops->report_disconnect != NULL)
586
0
      ops->report_disconnect (gc, description);
587
0
  }
588
589
0
  purple_signal_emit(purple_connections_get_handle(), "connection-error",
590
0
    gc, reason, description);
591
592
0
  gc->disconnect_timeout = purple_timeout_add(0, purple_connection_disconnect_cb,
593
0
      purple_connection_get_account(gc));
594
0
}
595
596
void
597
purple_connection_ssl_error (PurpleConnection *gc,
598
                             PurpleSslErrorType ssl_error)
599
0
{
600
0
  PurpleConnectionError reason;
601
602
0
  switch (ssl_error) {
603
0
    case PURPLE_SSL_HANDSHAKE_FAILED:
604
0
      reason = PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR;
605
0
      break;
606
0
    case PURPLE_SSL_CONNECT_FAILED:
607
0
      reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
608
0
      break;
609
0
    case PURPLE_SSL_CERTIFICATE_INVALID:
610
      /* TODO: maybe PURPLE_SSL_* should be more specific? */
611
0
      reason = PURPLE_CONNECTION_ERROR_CERT_OTHER_ERROR;
612
0
      break;
613
0
    default:
614
0
      g_assert_not_reached ();
615
0
      reason = PURPLE_CONNECTION_ERROR_CERT_OTHER_ERROR;
616
0
  }
617
618
0
  purple_connection_error_reason (gc, reason,
619
0
    purple_ssl_strerror(ssl_error));
620
0
}
621
622
gboolean
623
purple_connection_error_is_fatal (PurpleConnectionError reason)
624
0
{
625
0
  switch (reason)
626
0
  {
627
0
    case PURPLE_CONNECTION_ERROR_NETWORK_ERROR:
628
0
    case PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR:
629
0
      return FALSE;
630
0
    case PURPLE_CONNECTION_ERROR_INVALID_USERNAME:
631
0
    case PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED:
632
0
    case PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE:
633
0
    case PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT:
634
0
    case PURPLE_CONNECTION_ERROR_NAME_IN_USE:
635
0
    case PURPLE_CONNECTION_ERROR_INVALID_SETTINGS:
636
0
    case PURPLE_CONNECTION_ERROR_OTHER_ERROR:
637
0
    case PURPLE_CONNECTION_ERROR_CERT_NOT_PROVIDED:
638
0
    case PURPLE_CONNECTION_ERROR_CERT_UNTRUSTED:
639
0
    case PURPLE_CONNECTION_ERROR_CERT_EXPIRED:
640
0
    case PURPLE_CONNECTION_ERROR_CERT_NOT_ACTIVATED:
641
0
    case PURPLE_CONNECTION_ERROR_CERT_HOSTNAME_MISMATCH:
642
0
    case PURPLE_CONNECTION_ERROR_CERT_FINGERPRINT_MISMATCH:
643
0
    case PURPLE_CONNECTION_ERROR_CERT_SELF_SIGNED:
644
0
    case PURPLE_CONNECTION_ERROR_CERT_OTHER_ERROR:
645
0
      return TRUE;
646
0
    default:
647
0
      g_return_val_if_reached(TRUE);
648
0
  }
649
0
}
650
651
void
652
purple_connections_disconnect_all(void)
653
0
{
654
0
  GList *l;
655
0
  PurpleConnection *gc;
656
657
0
  while ((l = purple_connections_get_all()) != NULL) {
658
0
    gc = l->data;
659
0
    gc->wants_to_die = TRUE;
660
0
    purple_account_disconnect(gc->account);
661
0
  }
662
0
}
663
664
GList *
665
purple_connections_get_all(void)
666
0
{
667
0
  return connections;
668
0
}
669
670
GList *
671
purple_connections_get_connecting(void)
672
0
{
673
0
  return connections_connecting;
674
0
}
675
676
void
677
purple_connections_set_ui_ops(PurpleConnectionUiOps *ops)
678
0
{
679
0
  connection_ui_ops = ops;
680
0
}
681
682
PurpleConnectionUiOps *
683
purple_connections_get_ui_ops(void)
684
0
{
685
0
  return connection_ui_ops;
686
0
}
687
688
void
689
purple_connections_init(void)
690
0
{
691
0
  void *handle = purple_connections_get_handle();
692
693
0
  purple_signal_register(handle, "signing-on",
694
0
             purple_marshal_VOID__POINTER, NULL, 1,
695
0
             purple_value_new(PURPLE_TYPE_SUBTYPE,
696
0
                    PURPLE_SUBTYPE_CONNECTION));
697
698
0
  purple_signal_register(handle, "signed-on",
699
0
             purple_marshal_VOID__POINTER, NULL, 1,
700
0
             purple_value_new(PURPLE_TYPE_SUBTYPE,
701
0
                    PURPLE_SUBTYPE_CONNECTION));
702
703
0
  purple_signal_register(handle, "signing-off",
704
0
             purple_marshal_VOID__POINTER, NULL, 1,
705
0
             purple_value_new(PURPLE_TYPE_SUBTYPE,
706
0
                    PURPLE_SUBTYPE_CONNECTION));
707
708
0
  purple_signal_register(handle, "signed-off",
709
0
             purple_marshal_VOID__POINTER, NULL, 1,
710
0
             purple_value_new(PURPLE_TYPE_SUBTYPE,
711
0
                    PURPLE_SUBTYPE_CONNECTION));
712
713
0
  purple_signal_register(handle, "connection-error",
714
0
                         purple_marshal_VOID__POINTER_INT_POINTER, NULL, 3,
715
0
                         purple_value_new(PURPLE_TYPE_SUBTYPE,
716
0
                                          PURPLE_SUBTYPE_CONNECTION),
717
0
                         purple_value_new(PURPLE_TYPE_ENUM),
718
0
                         purple_value_new(PURPLE_TYPE_STRING));
719
720
0
  purple_signal_register(handle, "autojoin",
721
0
                         purple_marshal_BOOLEAN__POINTER, NULL, 1,
722
0
                         purple_value_new(PURPLE_TYPE_SUBTYPE,
723
0
                                          PURPLE_SUBTYPE_CONNECTION));
724
725
0
}
726
727
void
728
purple_connections_uninit(void)
729
0
{
730
0
  purple_signals_unregister_by_instance(purple_connections_get_handle());
731
0
}
732
733
void *
734
purple_connections_get_handle(void)
735
0
{
736
0
  return &connections_handle;
737
0
}