comparison libgaim/account.c @ 14192:60b1bc8dbf37

[gaim-migrate @ 16863] Renamed 'core' to 'libgaim' committer: Tailor Script <tailor@pidgin.im>
author Evan Schoenberg <evan.s@dreskin.net>
date Sat, 19 Aug 2006 01:50:10 +0000
parents
children f23506e8f812
comparison
equal deleted inserted replaced
14191:009db0b357b5 14192:60b1bc8dbf37
1 /**
2 * @file account.c Account API
3 * @ingroup core
4 *
5 * gaim
6 *
7 * Gaim is the legal property of its developers, whose names are too numerous
8 * to list here. Please refer to the COPYRIGHT file distributed with this
9 * source distribution.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25 #include "internal.h"
26 #include "account.h"
27 #include "core.h"
28 #include "dbus-maybe.h"
29 #include "debug.h"
30 #include "notify.h"
31 #include "pounce.h"
32 #include "prefs.h"
33 #include "privacy.h"
34 #include "prpl.h"
35 #include "request.h"
36 #include "server.h"
37 #include "signals.h"
38 #include "status.h"
39 #include "util.h"
40 #include "xmlnode.h"
41
42 /* TODO: Should use GaimValue instead of this? What about "ui"? */
43 typedef struct
44 {
45 GaimPrefType type;
46
47 char *ui;
48
49 union
50 {
51 int integer;
52 char *string;
53 gboolean bool;
54
55 } value;
56
57 } GaimAccountSetting;
58
59
60 static GaimAccountUiOps *account_ui_ops = NULL;
61
62 static GList *accounts = NULL;
63 static guint save_timer = 0;
64 static gboolean accounts_loaded = FALSE;
65
66
67 /*********************************************************************
68 * Writing to disk *
69 *********************************************************************/
70
71 static void
72 setting_to_xmlnode(gpointer key, gpointer value, gpointer user_data)
73 {
74 const char *name;
75 GaimAccountSetting *setting;
76 xmlnode *node, *child;
77 char buf[20];
78
79 name = (const char *)key;
80 setting = (GaimAccountSetting *)value;
81 node = (xmlnode *)user_data;
82
83 child = xmlnode_new_child(node, "setting");
84 xmlnode_set_attrib(child, "name", name);
85
86 if (setting->type == GAIM_PREF_INT) {
87 xmlnode_set_attrib(child, "type", "int");
88 snprintf(buf, sizeof(buf), "%d", setting->value.integer);
89 xmlnode_insert_data(child, buf, -1);
90 }
91 else if (setting->type == GAIM_PREF_STRING && setting->value.string != NULL) {
92 xmlnode_set_attrib(child, "type", "string");
93 xmlnode_insert_data(child, setting->value.string, -1);
94 }
95 else if (setting->type == GAIM_PREF_BOOLEAN) {
96 xmlnode_set_attrib(child, "type", "bool");
97 snprintf(buf, sizeof(buf), "%d", setting->value.bool);
98 xmlnode_insert_data(child, buf, -1);
99 }
100 }
101
102 static void
103 ui_setting_to_xmlnode(gpointer key, gpointer value, gpointer user_data)
104 {
105 const char *ui;
106 GHashTable *table;
107 xmlnode *node, *child;
108
109 ui = (const char *)key;
110 table = (GHashTable *)value;
111 node = (xmlnode *)user_data;
112
113 if (g_hash_table_size(table) > 0)
114 {
115 child = xmlnode_new_child(node, "settings");
116 xmlnode_set_attrib(child, "ui", ui);
117 g_hash_table_foreach(table, setting_to_xmlnode, child);
118 }
119 }
120
121 static xmlnode *
122 status_attr_to_xmlnode(const GaimStatus *status, const GaimStatusType *type, const GaimStatusAttr *attr)
123 {
124 xmlnode *node;
125 const char *id;
126 char *value = NULL;
127 GaimStatusAttr *default_attr;
128 GaimValue *default_value;
129 GaimType attr_type;
130 GaimValue *attr_value;
131
132 id = gaim_status_attr_get_id(attr);
133 g_return_val_if_fail(id, NULL);
134
135 attr_value = gaim_status_get_attr_value(status, id);
136 g_return_val_if_fail(attr_value, NULL);
137 attr_type = gaim_value_get_type(attr_value);
138
139 /*
140 * If attr_value is a different type than it should be
141 * then don't write it to the file.
142 */
143 default_attr = gaim_status_type_get_attr(type, id);
144 default_value = gaim_status_attr_get_value(default_attr);
145 if (attr_type != gaim_value_get_type(default_value))
146 return NULL;
147
148 /*
149 * If attr_value is the same as the default for this status
150 * then there is no need to write it to the file.
151 */
152 if (attr_type == GAIM_TYPE_STRING)
153 {
154 const char *string_value = gaim_value_get_string(attr_value);
155 const char *default_string_value = gaim_value_get_string(default_value);
156 if (((string_value == NULL) && (default_string_value == NULL)) ||
157 ((string_value != NULL) && (default_string_value != NULL) &&
158 !strcmp(string_value, default_string_value)))
159 return NULL;
160 value = g_strdup(gaim_value_get_string(attr_value));
161 }
162 else if (attr_type == GAIM_TYPE_INT)
163 {
164 int int_value = gaim_value_get_int(attr_value);
165 if (int_value == gaim_value_get_int(default_value))
166 return NULL;
167 value = g_strdup_printf("%d", int_value);
168 }
169 else if (attr_type == GAIM_TYPE_BOOLEAN)
170 {
171 gboolean boolean_value = gaim_value_get_boolean(attr_value);
172 if (boolean_value == gaim_value_get_boolean(default_value))
173 return NULL;
174 value = g_strdup(boolean_value ?
175 "true" : "false");
176 }
177 else
178 {
179 return NULL;
180 }
181
182 g_return_val_if_fail(value, NULL);
183
184 node = xmlnode_new("attribute");
185
186 xmlnode_set_attrib(node, "id", id);
187 xmlnode_set_attrib(node, "value", value);
188
189 g_free(value);
190
191 return node;
192 }
193
194 static xmlnode *
195 status_attrs_to_xmlnode(const GaimStatus *status)
196 {
197 GaimStatusType *type = gaim_status_get_type(status);
198 xmlnode *node, *child;
199 const GList *attrs, *attr;
200
201 node = xmlnode_new("attributes");
202
203 attrs = gaim_status_type_get_attrs(type);
204 for (attr = attrs; attr != NULL; attr = attr->next)
205 {
206 child = status_attr_to_xmlnode(status, type, (const GaimStatusAttr *)attr->data);
207 if (child)
208 xmlnode_insert_child(node, child);
209 }
210
211 return node;
212 }
213
214 static xmlnode *
215 status_to_xmlnode(const GaimStatus *status)
216 {
217 xmlnode *node, *child;
218
219 node = xmlnode_new("status");
220 xmlnode_set_attrib(node, "type", gaim_status_get_id(status));
221 if (gaim_status_get_name(status) != NULL)
222 xmlnode_set_attrib(node, "name", gaim_status_get_name(status));
223 xmlnode_set_attrib(node, "active", gaim_status_is_active(status) ? "true" : "false");
224
225 child = status_attrs_to_xmlnode(status);
226 xmlnode_insert_child(node, child);
227
228 return node;
229 }
230
231 static xmlnode *
232 statuses_to_xmlnode(const GaimPresence *presence)
233 {
234 xmlnode *node, *child;
235 const GList *statuses, *status;
236
237 node = xmlnode_new("statuses");
238
239 statuses = gaim_presence_get_statuses(presence);
240 for (status = statuses; status != NULL; status = status->next)
241 {
242 child = status_to_xmlnode((GaimStatus *)status->data);
243 xmlnode_insert_child(node, child);
244 }
245
246 return node;
247 }
248
249 static xmlnode *
250 proxy_settings_to_xmlnode(GaimProxyInfo *proxy_info)
251 {
252 xmlnode *node, *child;
253 GaimProxyType proxy_type;
254 const char *value;
255 int int_value;
256 char buf[20];
257
258 proxy_type = gaim_proxy_info_get_type(proxy_info);
259
260 node = xmlnode_new("proxy");
261
262 child = xmlnode_new_child(node, "type");
263 xmlnode_insert_data(child,
264 (proxy_type == GAIM_PROXY_USE_GLOBAL ? "global" :
265 proxy_type == GAIM_PROXY_NONE ? "none" :
266 proxy_type == GAIM_PROXY_HTTP ? "http" :
267 proxy_type == GAIM_PROXY_SOCKS4 ? "socks4" :
268 proxy_type == GAIM_PROXY_SOCKS5 ? "socks5" :
269 proxy_type == GAIM_PROXY_USE_ENVVAR ? "envvar" : "unknown"), -1);
270
271 if (proxy_type != GAIM_PROXY_USE_GLOBAL &&
272 proxy_type != GAIM_PROXY_NONE &&
273 proxy_type != GAIM_PROXY_USE_ENVVAR)
274 {
275 if ((value = gaim_proxy_info_get_host(proxy_info)) != NULL)
276 {
277 child = xmlnode_new_child(node, "host");
278 xmlnode_insert_data(child, value, -1);
279 }
280
281 if ((int_value = gaim_proxy_info_get_port(proxy_info)) != 0)
282 {
283 snprintf(buf, sizeof(buf), "%d", int_value);
284 child = xmlnode_new_child(node, "port");
285 xmlnode_insert_data(child, buf, -1);
286 }
287
288 if ((value = gaim_proxy_info_get_username(proxy_info)) != NULL)
289 {
290 child = xmlnode_new_child(node, "username");
291 xmlnode_insert_data(child, value, -1);
292 }
293
294 if ((value = gaim_proxy_info_get_password(proxy_info)) != NULL)
295 {
296 child = xmlnode_new_child(node, "password");
297 xmlnode_insert_data(child, value, -1);
298 }
299 }
300
301 return node;
302 }
303
304 static xmlnode *
305 account_to_xmlnode(GaimAccount *account)
306 {
307 xmlnode *node, *child;
308 const char *tmp;
309 GaimPresence *presence;
310 GaimProxyInfo *proxy_info;
311
312 node = xmlnode_new("account");
313
314 child = xmlnode_new_child(node, "protocol");
315 xmlnode_insert_data(child, gaim_account_get_protocol_id(account), -1);
316
317 child = xmlnode_new_child(node, "name");
318 xmlnode_insert_data(child, gaim_account_get_username(account), -1);
319
320 if (gaim_account_get_remember_password(account) &&
321 ((tmp = gaim_account_get_password(account)) != NULL))
322 {
323 child = xmlnode_new_child(node, "password");
324 xmlnode_insert_data(child, tmp, -1);
325 }
326
327 if ((tmp = gaim_account_get_alias(account)) != NULL)
328 {
329 child = xmlnode_new_child(node, "alias");
330 xmlnode_insert_data(child, tmp, -1);
331 }
332
333 if ((presence = gaim_account_get_presence(account)) != NULL)
334 {
335 child = statuses_to_xmlnode(presence);
336 xmlnode_insert_child(node, child);
337 }
338
339 if ((tmp = gaim_account_get_user_info(account)) != NULL)
340 {
341 /* TODO: Do we need to call gaim_str_strip_char(tmp, '\r') here? */
342 child = xmlnode_new_child(node, "userinfo");
343 xmlnode_insert_data(child, tmp, -1);
344 }
345
346 if ((tmp = gaim_account_get_buddy_icon(account)) != NULL)
347 {
348 child = xmlnode_new_child(node, "buddyicon");
349 xmlnode_insert_data(child, tmp, -1);
350 }
351
352 if (g_hash_table_size(account->settings) > 0)
353 {
354 child = xmlnode_new_child(node, "settings");
355 g_hash_table_foreach(account->settings, setting_to_xmlnode, child);
356 }
357
358 if (g_hash_table_size(account->ui_settings) > 0)
359 {
360 g_hash_table_foreach(account->ui_settings, ui_setting_to_xmlnode, node);
361 }
362
363 if ((proxy_info = gaim_account_get_proxy_info(account)) != NULL)
364 {
365 child = proxy_settings_to_xmlnode(proxy_info);
366 xmlnode_insert_child(node, child);
367 }
368
369 return node;
370 }
371
372 static xmlnode *
373 accounts_to_xmlnode(void)
374 {
375 xmlnode *node, *child;
376 GList *cur;
377
378 node = xmlnode_new("account");
379 xmlnode_set_attrib(node, "version", "1.0");
380
381 for (cur = gaim_accounts_get_all(); cur != NULL; cur = cur->next)
382 {
383 child = account_to_xmlnode(cur->data);
384 xmlnode_insert_child(node, child);
385 }
386
387 return node;
388 }
389
390 static void
391 sync_accounts(void)
392 {
393 xmlnode *node;
394 char *data;
395
396 if (!accounts_loaded)
397 {
398 gaim_debug_error("account", "Attempted to save accounts before "
399 "they were read!\n");
400 return;
401 }
402
403 node = accounts_to_xmlnode();
404 data = xmlnode_to_formatted_str(node, NULL);
405 gaim_util_write_data_to_file("accounts.xml", data, -1);
406 g_free(data);
407 xmlnode_free(node);
408 }
409
410 static gboolean
411 save_cb(gpointer data)
412 {
413 sync_accounts();
414 save_timer = 0;
415 return FALSE;
416 }
417
418 static void
419 schedule_accounts_save()
420 {
421 if (save_timer == 0)
422 save_timer = gaim_timeout_add(5000, save_cb, NULL);
423 }
424
425
426 /*********************************************************************
427 * Reading from disk *
428 *********************************************************************/
429
430 static void
431 parse_settings(xmlnode *node, GaimAccount *account)
432 {
433 const char *ui;
434 xmlnode *child;
435
436 /* Get the UI string, if these are UI settings */
437 ui = xmlnode_get_attrib(node, "ui");
438
439 /* Read settings, one by one */
440 for (child = xmlnode_get_child(node, "setting"); child != NULL;
441 child = xmlnode_get_next_twin(child))
442 {
443 const char *name, *str_type;
444 GaimPrefType type;
445 char *data;
446
447 name = xmlnode_get_attrib(child, "name");
448 if (name == NULL)
449 /* Ignore this setting */
450 continue;
451
452 str_type = xmlnode_get_attrib(child, "type");
453 if (str_type == NULL)
454 /* Ignore this setting */
455 continue;
456
457 if (!strcmp(str_type, "string"))
458 type = GAIM_PREF_STRING;
459 else if (!strcmp(str_type, "int"))
460 type = GAIM_PREF_INT;
461 else if (!strcmp(str_type, "bool"))
462 type = GAIM_PREF_BOOLEAN;
463 else
464 /* Ignore this setting */
465 continue;
466
467 data = xmlnode_get_data(child);
468 if (data == NULL)
469 /* Ignore this setting */
470 continue;
471
472 if (ui == NULL)
473 {
474 if (type == GAIM_PREF_STRING)
475 gaim_account_set_string(account, name, data);
476 else if (type == GAIM_PREF_INT)
477 gaim_account_set_int(account, name, atoi(data));
478 else if (type == GAIM_PREF_BOOLEAN)
479 gaim_account_set_bool(account, name,
480 (*data == '0' ? FALSE : TRUE));
481 } else {
482 if (type == GAIM_PREF_STRING)
483 gaim_account_set_ui_string(account, ui, name, data);
484 else if (type == GAIM_PREF_INT)
485 gaim_account_set_ui_int(account, ui, name, atoi(data));
486 else if (type == GAIM_PREF_BOOLEAN)
487 gaim_account_set_ui_bool(account, ui, name,
488 (*data == '0' ? FALSE : TRUE));
489 }
490
491 g_free(data);
492 }
493 }
494
495 static GList *
496 parse_status_attrs(xmlnode *node, GaimStatus *status)
497 {
498 GList *list = NULL;
499 xmlnode *child;
500 GaimValue *attr_value;
501
502 for (child = xmlnode_get_child(node, "attribute"); child != NULL;
503 child = xmlnode_get_next_twin(child))
504 {
505 const char *id = xmlnode_get_attrib(child, "id");
506 const char *value = xmlnode_get_attrib(child, "value");
507
508 if (!id || !*id || !value || !*value)
509 continue;
510
511 attr_value = gaim_status_get_attr_value(status, id);
512 if (!attr_value)
513 continue;
514
515 list = g_list_append(list, (char *)id);
516
517 switch (gaim_value_get_type(attr_value))
518 {
519 case GAIM_TYPE_STRING:
520 list = g_list_append(list, (char *)value);
521 break;
522 case GAIM_TYPE_INT:
523 case GAIM_TYPE_BOOLEAN:
524 {
525 int v;
526 if (sscanf(value, "%d", &v) == 1)
527 list = g_list_append(list, GINT_TO_POINTER(v));
528 else
529 list = g_list_remove(list, id);
530 break;
531 }
532 default:
533 break;
534 }
535 }
536
537 return list;
538 }
539
540 static void
541 parse_status(xmlnode *node, GaimAccount *account)
542 {
543 gboolean active = FALSE;
544 const char *data;
545 const char *type;
546 xmlnode *child;
547 GList *attrs = NULL;
548
549 /* Get the active/inactive state */
550 data = xmlnode_get_attrib(node, "active");
551 if (data == NULL)
552 return;
553 if (strcasecmp(data, "true") == 0)
554 active = TRUE;
555 else if (strcasecmp(data, "false") == 0)
556 active = FALSE;
557 else
558 return;
559
560 /* Get the type of the status */
561 type = xmlnode_get_attrib(node, "type");
562 if (type == NULL)
563 return;
564
565 /* Read attributes into a GList */
566 child = xmlnode_get_child(node, "attributes");
567 if (child != NULL)
568 {
569 attrs = parse_status_attrs(child,
570 gaim_account_get_status(account, type));
571 }
572
573 gaim_account_set_status_list(account, type, active, attrs);
574
575 g_list_free(attrs);
576 }
577
578 static void
579 parse_statuses(xmlnode *node, GaimAccount *account)
580 {
581 xmlnode *child;
582
583 for (child = xmlnode_get_child(node, "status"); child != NULL;
584 child = xmlnode_get_next_twin(child))
585 {
586 parse_status(child, account);
587 }
588 }
589
590 static void
591 parse_proxy_info(xmlnode *node, GaimAccount *account)
592 {
593 GaimProxyInfo *proxy_info;
594 xmlnode *child;
595 char *data;
596
597 proxy_info = gaim_proxy_info_new();
598
599 /* Use the global proxy settings, by default */
600 gaim_proxy_info_set_type(proxy_info, GAIM_PROXY_USE_GLOBAL);
601
602 /* Read proxy type */
603 child = xmlnode_get_child(node, "type");
604 if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
605 {
606 if (!strcmp(data, "global"))
607 gaim_proxy_info_set_type(proxy_info, GAIM_PROXY_USE_GLOBAL);
608 else if (!strcmp(data, "none"))
609 gaim_proxy_info_set_type(proxy_info, GAIM_PROXY_NONE);
610 else if (!strcmp(data, "http"))
611 gaim_proxy_info_set_type(proxy_info, GAIM_PROXY_HTTP);
612 else if (!strcmp(data, "socks4"))
613 gaim_proxy_info_set_type(proxy_info, GAIM_PROXY_SOCKS4);
614 else if (!strcmp(data, "socks5"))
615 gaim_proxy_info_set_type(proxy_info, GAIM_PROXY_SOCKS5);
616 else if (!strcmp(data, "envvar"))
617 gaim_proxy_info_set_type(proxy_info, GAIM_PROXY_USE_ENVVAR);
618 else
619 {
620 gaim_debug_error("account", "Invalid proxy type found when "
621 "loading account information for %s\n",
622 gaim_account_get_username(account));
623 }
624 g_free(data);
625 }
626
627 /* Read proxy host */
628 child = xmlnode_get_child(node, "host");
629 if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
630 {
631 gaim_proxy_info_set_host(proxy_info, data);
632 g_free(data);
633 }
634
635 /* Read proxy port */
636 child = xmlnode_get_child(node, "port");
637 if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
638 {
639 gaim_proxy_info_set_port(proxy_info, atoi(data));
640 g_free(data);
641 }
642
643 /* Read proxy username */
644 child = xmlnode_get_child(node, "username");
645 if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
646 {
647 gaim_proxy_info_set_username(proxy_info, data);
648 g_free(data);
649 }
650
651 /* Read proxy password */
652 child = xmlnode_get_child(node, "password");
653 if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
654 {
655 gaim_proxy_info_set_password(proxy_info, data);
656 g_free(data);
657 }
658
659 /* If there are no values set then proxy_infourn NULL */
660 if ((gaim_proxy_info_get_type(proxy_info) == GAIM_PROXY_USE_GLOBAL) &&
661 (gaim_proxy_info_get_host(proxy_info) == NULL) &&
662 (gaim_proxy_info_get_port(proxy_info) == 0) &&
663 (gaim_proxy_info_get_username(proxy_info) == NULL) &&
664 (gaim_proxy_info_get_password(proxy_info) == NULL))
665 {
666 gaim_proxy_info_destroy(proxy_info);
667 return;
668 }
669
670 gaim_account_set_proxy_info(account, proxy_info);
671 }
672
673 static GaimAccount *
674 parse_account(xmlnode *node)
675 {
676 GaimAccount *ret;
677 xmlnode *child;
678 char *protocol_id = NULL;
679 char *name = NULL;
680 char *data;
681
682 child = xmlnode_get_child(node, "protocol");
683 if (child != NULL)
684 protocol_id = xmlnode_get_data(child);
685
686 child = xmlnode_get_child(node, "name");
687 if (child != NULL)
688 name = xmlnode_get_data(child);
689 if (name == NULL)
690 {
691 /* Do we really need to do this? */
692 child = xmlnode_get_child(node, "username");
693 if (child != NULL)
694 name = xmlnode_get_data(child);
695 }
696
697 if ((protocol_id == NULL) || (name == NULL))
698 {
699 g_free(protocol_id);
700 g_free(name);
701 return NULL;
702 }
703
704 ret = gaim_account_new(name, protocol_id);
705 g_free(name);
706 g_free(protocol_id);
707
708 /* Read the password */
709 child = xmlnode_get_child(node, "password");
710 if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
711 {
712 gaim_account_set_remember_password(ret, TRUE);
713 gaim_account_set_password(ret, data);
714 g_free(data);
715 }
716
717 /* Read the alias */
718 child = xmlnode_get_child(node, "alias");
719 if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
720 {
721 if (*data != '\0')
722 gaim_account_set_alias(ret, data);
723 g_free(data);
724 }
725
726 /* Read the statuses */
727 child = xmlnode_get_child(node, "statuses");
728 if (child != NULL)
729 {
730 parse_statuses(child, ret);
731 }
732
733 /* Read the userinfo */
734 child = xmlnode_get_child(node, "userinfo");
735 if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
736 {
737 gaim_account_set_user_info(ret, data);
738 g_free(data);
739 }
740
741 /* Read the buddyicon */
742 child = xmlnode_get_child(node, "buddyicon");
743 if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL))
744 {
745 gaim_account_set_buddy_icon(ret, data);
746 g_free(data);
747 }
748
749 /* Read settings (both core and UI) */
750 for (child = xmlnode_get_child(node, "settings"); child != NULL;
751 child = xmlnode_get_next_twin(child))
752 {
753 parse_settings(child, ret);
754 }
755
756 /* Read proxy */
757 child = xmlnode_get_child(node, "proxy");
758 if (child != NULL)
759 {
760 parse_proxy_info(child, ret);
761 }
762
763 return ret;
764 }
765
766 static void
767 load_accounts(void)
768 {
769 xmlnode *node, *child;
770
771 accounts_loaded = TRUE;
772
773 node = gaim_util_read_xml_from_file("accounts.xml", _("accounts"));
774
775 if (node == NULL)
776 return;
777
778 for (child = xmlnode_get_child(node, "account"); child != NULL;
779 child = xmlnode_get_next_twin(child))
780 {
781 GaimAccount *new_acct;
782 new_acct = parse_account(child);
783 gaim_accounts_add(new_acct);
784 }
785
786 xmlnode_free(node);
787 }
788
789
790 static void
791 delete_setting(void *data)
792 {
793 GaimAccountSetting *setting = (GaimAccountSetting *)data;
794
795 g_free(setting->ui);
796
797 if (setting->type == GAIM_PREF_STRING)
798 g_free(setting->value.string);
799
800 g_free(setting);
801 }
802
803 GaimAccount *
804 gaim_account_new(const char *username, const char *protocol_id)
805 {
806 GaimAccount *account = NULL;
807 GaimPlugin *prpl = NULL;
808 GaimPluginProtocolInfo *prpl_info = NULL;
809 GaimStatusType *status_type;
810
811 g_return_val_if_fail(username != NULL, NULL);
812 g_return_val_if_fail(protocol_id != NULL, NULL);
813
814 account = gaim_accounts_find(username, protocol_id);
815
816 if (account != NULL)
817 return account;
818
819 account = g_new0(GaimAccount, 1);
820 GAIM_DBUS_REGISTER_POINTER(account, GaimAccount);
821
822 gaim_account_set_username(account, username);
823
824 gaim_account_set_protocol_id(account, protocol_id);
825
826 account->settings = g_hash_table_new_full(g_str_hash, g_str_equal,
827 g_free, delete_setting);
828 account->ui_settings = g_hash_table_new_full(g_str_hash, g_str_equal,
829 g_free, (GDestroyNotify)g_hash_table_destroy);
830 account->system_log = NULL;
831 /* 0 is not a valid privacy setting */
832 account->perm_deny = GAIM_PRIVACY_ALLOW_ALL;
833
834 account->presence = gaim_presence_new_for_account(account);
835
836 prpl = gaim_find_prpl(protocol_id);
837
838 if (prpl == NULL)
839 return account;
840
841 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl);
842 if (prpl_info != NULL && prpl_info->status_types != NULL)
843 gaim_account_set_status_types(account, prpl_info->status_types(account));
844
845 status_type = gaim_account_get_status_type_with_primitive(account, GAIM_STATUS_AVAILABLE);
846 if (status_type != NULL)
847 gaim_presence_set_status_active(account->presence,
848 gaim_status_type_get_id(status_type),
849 TRUE);
850 else
851 gaim_presence_set_status_active(account->presence,
852 "offline",
853 TRUE);
854
855 return account;
856 }
857
858 void
859 gaim_account_destroy(GaimAccount *account)
860 {
861 GList *l;
862
863 g_return_if_fail(account != NULL);
864
865 gaim_debug_info("account", "Destroying account %p\n", account);
866
867 for (l = gaim_get_conversations(); l != NULL; l = l->next)
868 {
869 GaimConversation *conv = (GaimConversation *)l->data;
870
871 if (gaim_conversation_get_account(conv) == account)
872 gaim_conversation_set_account(conv, NULL);
873 }
874
875 g_free(account->username);
876 g_free(account->alias);
877 g_free(account->password);
878 g_free(account->user_info);
879 g_free(account->protocol_id);
880
881 g_hash_table_destroy(account->settings);
882 g_hash_table_destroy(account->ui_settings);
883
884 gaim_account_set_status_types(account, NULL);
885
886 gaim_presence_destroy(account->presence);
887
888 if(account->system_log)
889 gaim_log_free(account->system_log);
890
891 GAIM_DBUS_UNREGISTER_POINTER(account);
892 g_free(account);
893 }
894
895 void
896 gaim_account_register(GaimAccount *account)
897 {
898 g_return_if_fail(account != NULL);
899
900 gaim_debug_info("account", "Registering account %s\n",
901 gaim_account_get_username(account));
902
903 gaim_connection_new(account, TRUE, NULL);
904 }
905
906 static void
907 request_password_ok_cb(GaimAccount *account, GaimRequestFields *fields)
908 {
909 const char *entry;
910 gboolean remember;
911
912 entry = gaim_request_fields_get_string(fields, "password");
913 remember = gaim_request_fields_get_bool(fields, "remember");
914
915 if (!entry || !*entry)
916 {
917 gaim_notify_error(account, NULL, _("Password is required to sign on."), NULL);
918 return;
919 }
920
921 if(remember)
922 gaim_account_set_remember_password(account, TRUE);
923
924 gaim_account_set_password(account, entry);
925
926 gaim_connection_new(account, FALSE, entry);
927 }
928
929 static void
930 request_password(GaimAccount *account)
931 {
932 gchar *primary;
933 const gchar *username;
934 GaimRequestFieldGroup *group;
935 GaimRequestField *field;
936 GaimRequestFields *fields;
937
938 /* Close any previous password request windows */
939 gaim_request_close_with_handle(account);
940
941 username = gaim_account_get_username(account);
942 primary = g_strdup_printf(_("Enter password for %s (%s)"), username,
943 gaim_account_get_protocol_name(account));
944
945 fields = gaim_request_fields_new();
946 group = gaim_request_field_group_new(NULL);
947 gaim_request_fields_add_group(fields, group);
948
949 field = gaim_request_field_string_new("password", _("Enter Password"), NULL, FALSE);
950 gaim_request_field_string_set_masked(field, TRUE);
951 gaim_request_field_set_required(field, TRUE);
952 gaim_request_field_group_add_field(group, field);
953
954 field = gaim_request_field_bool_new("remember", _("Save password"), FALSE);
955 gaim_request_field_group_add_field(group, field);
956
957 gaim_request_fields(account,
958 NULL,
959 primary,
960 NULL,
961 fields,
962 _("OK"), G_CALLBACK(request_password_ok_cb),
963 _("Cancel"), NULL,
964 account);
965 g_free(primary);
966 }
967
968 void
969 gaim_account_connect(GaimAccount *account)
970 {
971 GaimPlugin *prpl;
972 GaimPluginProtocolInfo *prpl_info;
973 const char *password;
974
975 g_return_if_fail(account != NULL);
976
977 gaim_debug_info("account", "Connecting to account %s\n",
978 gaim_account_get_username(account));
979
980 if (!gaim_account_get_enabled(account, gaim_core_get_ui()))
981 return;
982
983 prpl = gaim_find_prpl(gaim_account_get_protocol_id(account));
984 if (prpl == NULL)
985 {
986 gchar *message;
987
988 message = g_strdup_printf(_("Missing protocol plugin for %s"),
989 gaim_account_get_username(account));
990 gaim_notify_error(account, _("Connection Error"), message, NULL);
991 g_free(message);
992 return;
993 }
994
995 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl);
996 password = gaim_account_get_password(account);
997 if ((password == NULL) &&
998 !(prpl_info->options & OPT_PROTO_NO_PASSWORD) &&
999 !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL))
1000 request_password(account);
1001 else
1002 gaim_connection_new(account, FALSE, password);
1003 }
1004
1005 void
1006 gaim_account_disconnect(GaimAccount *account)
1007 {
1008 GaimConnection *gc;
1009
1010 g_return_if_fail(account != NULL);
1011 g_return_if_fail(!gaim_account_is_disconnected(account));
1012
1013 gaim_debug_info("account", "Disconnecting account %p\n", account);
1014
1015 account->disconnecting = TRUE;
1016
1017 gc = gaim_account_get_connection(account);
1018 gaim_connection_destroy(gc);
1019 if (!gaim_account_get_remember_password(account))
1020 gaim_account_set_password(account, NULL);
1021 gaim_account_set_connection(account, NULL);
1022
1023 account->disconnecting = FALSE;
1024 }
1025
1026 void
1027 gaim_account_notify_added(GaimAccount *account, const char *remote_user,
1028 const char *id, const char *alias,
1029 const char *message)
1030 {
1031 GaimAccountUiOps *ui_ops;
1032
1033 g_return_if_fail(account != NULL);
1034 g_return_if_fail(remote_user != NULL);
1035
1036 ui_ops = gaim_accounts_get_ui_ops();
1037
1038 if (ui_ops != NULL && ui_ops->notify_added != NULL)
1039 ui_ops->notify_added(account, remote_user, id, alias, message);
1040 }
1041
1042 void
1043 gaim_account_request_add(GaimAccount *account, const char *remote_user,
1044 const char *id, const char *alias,
1045 const char *message)
1046 {
1047 GaimAccountUiOps *ui_ops;
1048
1049 g_return_if_fail(account != NULL);
1050 g_return_if_fail(remote_user != NULL);
1051
1052 ui_ops = gaim_accounts_get_ui_ops();
1053
1054 if (ui_ops != NULL && ui_ops->request_add != NULL)
1055 ui_ops->request_add(account, remote_user, id, alias, message);
1056 }
1057
1058 static void
1059 change_password_cb(GaimAccount *account, GaimRequestFields *fields)
1060 {
1061 const char *orig_pass, *new_pass_1, *new_pass_2;
1062
1063 orig_pass = gaim_request_fields_get_string(fields, "password");
1064 new_pass_1 = gaim_request_fields_get_string(fields, "new_password_1");
1065 new_pass_2 = gaim_request_fields_get_string(fields, "new_password_2");
1066
1067 if (g_utf8_collate(new_pass_1, new_pass_2))
1068 {
1069 gaim_notify_error(account, NULL,
1070 _("New passwords do not match."), NULL);
1071
1072 return;
1073 }
1074
1075 if (orig_pass == NULL || new_pass_1 == NULL || new_pass_2 == NULL ||
1076 *orig_pass == '\0' || *new_pass_1 == '\0' || *new_pass_2 == '\0')
1077 {
1078 gaim_notify_error(account, NULL,
1079 _("Fill out all fields completely."), NULL);
1080 return;
1081 }
1082
1083 gaim_account_change_password(account, orig_pass, new_pass_1);
1084 }
1085
1086 void
1087 gaim_account_request_change_password(GaimAccount *account)
1088 {
1089 GaimRequestFields *fields;
1090 GaimRequestFieldGroup *group;
1091 GaimRequestField *field;
1092 char primary[256];
1093
1094 g_return_if_fail(account != NULL);
1095 g_return_if_fail(gaim_account_is_connected(account));
1096
1097 fields = gaim_request_fields_new();
1098
1099 group = gaim_request_field_group_new(NULL);
1100 gaim_request_fields_add_group(fields, group);
1101
1102 field = gaim_request_field_string_new("password", _("Original password"),
1103 NULL, FALSE);
1104 gaim_request_field_string_set_masked(field, TRUE);
1105 gaim_request_field_set_required(field, TRUE);
1106 gaim_request_field_group_add_field(group, field);
1107
1108 field = gaim_request_field_string_new("new_password_1",
1109 _("New password"),
1110 NULL, FALSE);
1111 gaim_request_field_string_set_masked(field, TRUE);
1112 gaim_request_field_set_required(field, TRUE);
1113 gaim_request_field_group_add_field(group, field);
1114
1115 field = gaim_request_field_string_new("new_password_2",
1116 _("New password (again)"),
1117 NULL, FALSE);
1118 gaim_request_field_string_set_masked(field, TRUE);
1119 gaim_request_field_set_required(field, TRUE);
1120 gaim_request_field_group_add_field(group, field);
1121
1122 g_snprintf(primary, sizeof(primary), _("Change password for %s"),
1123 gaim_account_get_username(account));
1124
1125 /* I'm sticking this somewhere in the code: bologna */
1126
1127 gaim_request_fields(gaim_account_get_connection(account),
1128 NULL,
1129 primary,
1130 _("Please enter your current password and your "
1131 "new password."),
1132 fields,
1133 _("OK"), G_CALLBACK(change_password_cb),
1134 _("Cancel"), NULL,
1135 account);
1136 }
1137
1138 static void
1139 set_user_info_cb(GaimAccount *account, const char *user_info)
1140 {
1141 GaimConnection *gc;
1142
1143 gaim_account_set_user_info(account, user_info);
1144
1145 gc = gaim_account_get_connection(account);
1146
1147 if (gc != NULL)
1148 serv_set_info(gc, user_info);
1149 }
1150
1151 void
1152 gaim_account_request_change_user_info(GaimAccount *account)
1153 {
1154 GaimConnection *gc;
1155 char primary[256];
1156
1157 g_return_if_fail(account != NULL);
1158 g_return_if_fail(gaim_account_is_connected(account));
1159
1160 gc = gaim_account_get_connection(account);
1161
1162 g_snprintf(primary, sizeof(primary),
1163 _("Change user information for %s"),
1164 gaim_account_get_username(account));
1165
1166 gaim_request_input(gc, _("Set User Info"), primary, NULL,
1167 gaim_account_get_user_info(account),
1168 TRUE, FALSE, ((gc != NULL) &&
1169 (gc->flags & GAIM_CONNECTION_HTML) ? "html" : NULL),
1170 _("Save"), G_CALLBACK(set_user_info_cb),
1171 _("Cancel"), NULL, account);
1172 }
1173
1174 void
1175 gaim_account_set_username(GaimAccount *account, const char *username)
1176 {
1177 g_return_if_fail(account != NULL);
1178
1179 g_free(account->username);
1180 account->username = g_strdup(username);
1181
1182 schedule_accounts_save();
1183 }
1184
1185 void
1186 gaim_account_set_password(GaimAccount *account, const char *password)
1187 {
1188 g_return_if_fail(account != NULL);
1189
1190 g_free(account->password);
1191 account->password = g_strdup(password);
1192
1193 schedule_accounts_save();
1194 }
1195
1196 void
1197 gaim_account_set_alias(GaimAccount *account, const char *alias)
1198 {
1199 g_return_if_fail(account != NULL);
1200
1201 /*
1202 * Do nothing if alias and account->alias are both NULL. Or if
1203 * they're the exact same string.
1204 */
1205 if (alias == account->alias)
1206 return;
1207
1208 if ((!alias && account->alias) || (alias && !account->alias) ||
1209 g_utf8_collate(account->alias, alias))
1210 {
1211 char *old = account->alias;
1212
1213 account->alias = g_strdup(alias);
1214 gaim_signal_emit(gaim_accounts_get_handle(), "account-alias-changed",
1215 account, old);
1216 g_free(old);
1217
1218 schedule_accounts_save();
1219 }
1220 }
1221
1222 void
1223 gaim_account_set_user_info(GaimAccount *account, const char *user_info)
1224 {
1225 g_return_if_fail(account != NULL);
1226
1227 g_free(account->user_info);
1228 account->user_info = g_strdup(user_info);
1229
1230 schedule_accounts_save();
1231 }
1232
1233 void
1234 gaim_account_set_buddy_icon(GaimAccount *account, const char *icon)
1235 {
1236 g_return_if_fail(account != NULL);
1237
1238 /* Delete an existing icon from the cache. */
1239 if (account->buddy_icon != NULL && (icon == NULL || strcmp(account->buddy_icon, icon)))
1240 {
1241 const char *dirname = gaim_buddy_icons_get_cache_dir();
1242 struct stat st;
1243
1244 if (g_stat(account->buddy_icon, &st) == 0)
1245 {
1246 /* The file exists. This is a full path. */
1247
1248 /* XXX: This is a hack so we only delete the file if it's
1249 * in the cache dir. Otherwise, people who upgrade (who
1250 * may have buddy icon filenames set outside of the cache
1251 * dir) could lose files. */
1252 if (!strncmp(dirname, account->buddy_icon, strlen(dirname)))
1253 g_unlink(account->buddy_icon);
1254 }
1255 else
1256 {
1257 char *filename = g_build_filename(dirname, account->buddy_icon, NULL);
1258 g_unlink(filename);
1259 g_free(filename);
1260 }
1261 }
1262
1263 g_free(account->buddy_icon);
1264 account->buddy_icon = g_strdup(icon);
1265 if (gaim_account_is_connected(account))
1266 {
1267 char *filename = gaim_buddy_icons_get_full_path(icon);
1268 serv_set_buddyicon(gaim_account_get_connection(account), filename);
1269 g_free(filename);
1270 }
1271
1272 schedule_accounts_save();
1273 }
1274
1275 void
1276 gaim_account_set_protocol_id(GaimAccount *account, const char *protocol_id)
1277 {
1278 g_return_if_fail(account != NULL);
1279 g_return_if_fail(protocol_id != NULL);
1280
1281 g_free(account->protocol_id);
1282 account->protocol_id = g_strdup(protocol_id);
1283
1284 schedule_accounts_save();
1285 }
1286
1287 void
1288 gaim_account_set_connection(GaimAccount *account, GaimConnection *gc)
1289 {
1290 g_return_if_fail(account != NULL);
1291
1292 account->gc = gc;
1293 }
1294
1295 void
1296 gaim_account_set_remember_password(GaimAccount *account, gboolean value)
1297 {
1298 g_return_if_fail(account != NULL);
1299
1300 account->remember_pass = value;
1301
1302 schedule_accounts_save();
1303 }
1304
1305 void
1306 gaim_account_set_check_mail(GaimAccount *account, gboolean value)
1307 {
1308 g_return_if_fail(account != NULL);
1309
1310 gaim_account_set_bool(account, "check-mail", value);
1311 }
1312
1313 void
1314 gaim_account_set_enabled(GaimAccount *account, const char *ui,
1315 gboolean value)
1316 {
1317 GaimConnection *gc;
1318 gboolean was_enabled = FALSE;
1319
1320 g_return_if_fail(account != NULL);
1321 g_return_if_fail(ui != NULL);
1322
1323 was_enabled = gaim_account_get_enabled(account, ui);
1324
1325 gaim_account_set_ui_bool(account, ui, "auto-login", value);
1326 gc = gaim_account_get_connection(account);
1327
1328 if(was_enabled && !value)
1329 gaim_signal_emit(gaim_accounts_get_handle(), "account-disabled", account);
1330 else if(!was_enabled && value)
1331 gaim_signal_emit(gaim_accounts_get_handle(), "account-enabled", account);
1332
1333 if ((gc != NULL) && (gc->wants_to_die == TRUE))
1334 return;
1335
1336 if (value && gaim_presence_is_online(account->presence))
1337 gaim_account_connect(account);
1338 else if (!value && !gaim_account_is_disconnected(account))
1339 gaim_account_disconnect(account);
1340 }
1341
1342 void
1343 gaim_account_set_proxy_info(GaimAccount *account, GaimProxyInfo *info)
1344 {
1345 g_return_if_fail(account != NULL);
1346
1347 if (account->proxy_info != NULL)
1348 gaim_proxy_info_destroy(account->proxy_info);
1349
1350 account->proxy_info = info;
1351
1352 schedule_accounts_save();
1353 }
1354
1355 void
1356 gaim_account_set_status_types(GaimAccount *account, GList *status_types)
1357 {
1358 g_return_if_fail(account != NULL);
1359
1360 /* Old with the old... */
1361 if (account->status_types != NULL)
1362 {
1363 g_list_foreach(account->status_types, (GFunc)gaim_status_type_destroy, NULL);
1364 g_list_free(account->status_types);
1365 }
1366
1367 /* In with the new... */
1368 account->status_types = status_types;
1369 }
1370
1371 void
1372 gaim_account_set_status(GaimAccount *account, const char *status_id,
1373 gboolean active, ...)
1374 {
1375 va_list args;
1376
1377 va_start(args, active);
1378 gaim_account_set_status_vargs(account, status_id, active, args);
1379 va_end(args);
1380 }
1381
1382 void
1383 gaim_account_set_status_vargs(GaimAccount *account, const char *status_id,
1384 gboolean active, va_list args)
1385 {
1386 GList *attrs = NULL;
1387 const gchar *id;
1388 gpointer data;
1389
1390 if (args != NULL)
1391 {
1392 while ((id = va_arg(args, const char *)) != NULL)
1393 {
1394 attrs = g_list_append(attrs, (char *)id);
1395 data = va_arg(args, void *);
1396 attrs = g_list_append(attrs, data);
1397 }
1398 }
1399 gaim_account_set_status_list(account, status_id, active, attrs);
1400 g_list_free(attrs);
1401 }
1402
1403 void
1404 gaim_account_set_status_list(GaimAccount *account, const char *status_id,
1405 gboolean active, GList *attrs)
1406 {
1407 GaimStatus *status;
1408
1409 g_return_if_fail(account != NULL);
1410 g_return_if_fail(status_id != NULL);
1411
1412 status = gaim_account_get_status(account, status_id);
1413 if (status == NULL)
1414 {
1415 gaim_debug_error("account",
1416 "Invalid status ID %s for account %s (%s)\n",
1417 status_id, gaim_account_get_username(account),
1418 gaim_account_get_protocol_id(account));
1419 return;
1420 }
1421
1422 if (active || gaim_status_is_independent(status))
1423 gaim_status_set_active_with_attrs_list(status, active, attrs);
1424
1425 /*
1426 * Our current statuses are saved to accounts.xml (so that when we
1427 * reconnect, we go back to the previous status).
1428 */
1429 schedule_accounts_save();
1430 }
1431
1432 void
1433 gaim_account_clear_settings(GaimAccount *account)
1434 {
1435 g_return_if_fail(account != NULL);
1436
1437 g_hash_table_destroy(account->settings);
1438
1439 account->settings = g_hash_table_new_full(g_str_hash, g_str_equal,
1440 g_free, delete_setting);
1441 }
1442
1443 void
1444 gaim_account_set_int(GaimAccount *account, const char *name, int value)
1445 {
1446 GaimAccountSetting *setting;
1447
1448 g_return_if_fail(account != NULL);
1449 g_return_if_fail(name != NULL);
1450
1451 setting = g_new0(GaimAccountSetting, 1);
1452
1453 setting->type = GAIM_PREF_INT;
1454 setting->value.integer = value;
1455
1456 g_hash_table_insert(account->settings, g_strdup(name), setting);
1457
1458 schedule_accounts_save();
1459 }
1460
1461 void
1462 gaim_account_set_string(GaimAccount *account, const char *name,
1463 const char *value)
1464 {
1465 GaimAccountSetting *setting;
1466
1467 g_return_if_fail(account != NULL);
1468 g_return_if_fail(name != NULL);
1469
1470 setting = g_new0(GaimAccountSetting, 1);
1471
1472 setting->type = GAIM_PREF_STRING;
1473 setting->value.string = g_strdup(value);
1474
1475 g_hash_table_insert(account->settings, g_strdup(name), setting);
1476
1477 schedule_accounts_save();
1478 }
1479
1480 void
1481 gaim_account_set_bool(GaimAccount *account, const char *name, gboolean value)
1482 {
1483 GaimAccountSetting *setting;
1484
1485 g_return_if_fail(account != NULL);
1486 g_return_if_fail(name != NULL);
1487
1488 setting = g_new0(GaimAccountSetting, 1);
1489
1490 setting->type = GAIM_PREF_BOOLEAN;
1491 setting->value.bool = value;
1492
1493 g_hash_table_insert(account->settings, g_strdup(name), setting);
1494
1495 schedule_accounts_save();
1496 }
1497
1498 static GHashTable *
1499 get_ui_settings_table(GaimAccount *account, const char *ui)
1500 {
1501 GHashTable *table;
1502
1503 table = g_hash_table_lookup(account->ui_settings, ui);
1504
1505 if (table == NULL) {
1506 table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
1507 delete_setting);
1508 g_hash_table_insert(account->ui_settings, g_strdup(ui), table);
1509 }
1510
1511 return table;
1512 }
1513
1514 void
1515 gaim_account_set_ui_int(GaimAccount *account, const char *ui,
1516 const char *name, int value)
1517 {
1518 GaimAccountSetting *setting;
1519 GHashTable *table;
1520
1521 g_return_if_fail(account != NULL);
1522 g_return_if_fail(ui != NULL);
1523 g_return_if_fail(name != NULL);
1524
1525 setting = g_new0(GaimAccountSetting, 1);
1526
1527 setting->type = GAIM_PREF_INT;
1528 setting->ui = g_strdup(ui);
1529 setting->value.integer = value;
1530
1531 table = get_ui_settings_table(account, ui);
1532
1533 g_hash_table_insert(table, g_strdup(name), setting);
1534
1535 schedule_accounts_save();
1536 }
1537
1538 void
1539 gaim_account_set_ui_string(GaimAccount *account, const char *ui,
1540 const char *name, const char *value)
1541 {
1542 GaimAccountSetting *setting;
1543 GHashTable *table;
1544
1545 g_return_if_fail(account != NULL);
1546 g_return_if_fail(ui != NULL);
1547 g_return_if_fail(name != NULL);
1548
1549 setting = g_new0(GaimAccountSetting, 1);
1550
1551 setting->type = GAIM_PREF_STRING;
1552 setting->ui = g_strdup(ui);
1553 setting->value.string = g_strdup(value);
1554
1555 table = get_ui_settings_table(account, ui);
1556
1557 g_hash_table_insert(table, g_strdup(name), setting);
1558
1559 schedule_accounts_save();
1560 }
1561
1562 void
1563 gaim_account_set_ui_bool(GaimAccount *account, const char *ui,
1564 const char *name, gboolean value)
1565 {
1566 GaimAccountSetting *setting;
1567 GHashTable *table;
1568
1569 g_return_if_fail(account != NULL);
1570 g_return_if_fail(ui != NULL);
1571 g_return_if_fail(name != NULL);
1572
1573 setting = g_new0(GaimAccountSetting, 1);
1574
1575 setting->type = GAIM_PREF_BOOLEAN;
1576 setting->ui = g_strdup(ui);
1577 setting->value.bool = value;
1578
1579 table = get_ui_settings_table(account, ui);
1580
1581 g_hash_table_insert(table, g_strdup(name), setting);
1582
1583 schedule_accounts_save();
1584 }
1585
1586 static GaimConnectionState
1587 gaim_account_get_state(const GaimAccount *account)
1588 {
1589 GaimConnection *gc;
1590
1591 g_return_val_if_fail(account != NULL, GAIM_DISCONNECTED);
1592
1593 gc = gaim_account_get_connection(account);
1594 if (!gc)
1595 return GAIM_DISCONNECTED;
1596
1597 return gaim_connection_get_state(gc);
1598 }
1599
1600 gboolean
1601 gaim_account_is_connected(const GaimAccount *account)
1602 {
1603 return (gaim_account_get_state(account) == GAIM_CONNECTED);
1604 }
1605
1606 gboolean
1607 gaim_account_is_connecting(const GaimAccount *account)
1608 {
1609 return (gaim_account_get_state(account) == GAIM_CONNECTING);
1610 }
1611
1612 gboolean
1613 gaim_account_is_disconnected(const GaimAccount *account)
1614 {
1615 return (gaim_account_get_state(account) == GAIM_DISCONNECTED);
1616 }
1617
1618 const char *
1619 gaim_account_get_username(const GaimAccount *account)
1620 {
1621 g_return_val_if_fail(account != NULL, NULL);
1622
1623 return account->username;
1624 }
1625
1626 const char *
1627 gaim_account_get_password(const GaimAccount *account)
1628 {
1629 g_return_val_if_fail(account != NULL, NULL);
1630
1631 return account->password;
1632 }
1633
1634 const char *
1635 gaim_account_get_alias(const GaimAccount *account)
1636 {
1637 g_return_val_if_fail(account != NULL, NULL);
1638
1639 return account->alias;
1640 }
1641
1642 const char *
1643 gaim_account_get_user_info(const GaimAccount *account)
1644 {
1645 g_return_val_if_fail(account != NULL, NULL);
1646
1647 return account->user_info;
1648 }
1649
1650 const char *
1651 gaim_account_get_buddy_icon(const GaimAccount *account)
1652 {
1653 g_return_val_if_fail(account != NULL, NULL);
1654
1655 return account->buddy_icon;
1656 }
1657
1658 const char *
1659 gaim_account_get_protocol_id(const GaimAccount *account)
1660 {
1661 g_return_val_if_fail(account != NULL, NULL);
1662
1663 return account->protocol_id;
1664 }
1665
1666 const char *
1667 gaim_account_get_protocol_name(const GaimAccount *account)
1668 {
1669 GaimPlugin *p;
1670
1671 g_return_val_if_fail(account != NULL, NULL);
1672
1673 p = gaim_find_prpl(gaim_account_get_protocol_id(account));
1674
1675 return ((p && p->info->name) ? _(p->info->name) : _("Unknown"));
1676 }
1677
1678 GaimConnection *
1679 gaim_account_get_connection(const GaimAccount *account)
1680 {
1681 g_return_val_if_fail(account != NULL, NULL);
1682
1683 return account->gc;
1684 }
1685
1686 gboolean
1687 gaim_account_get_remember_password(const GaimAccount *account)
1688 {
1689 g_return_val_if_fail(account != NULL, FALSE);
1690
1691 return account->remember_pass;
1692 }
1693
1694 gboolean
1695 gaim_account_get_check_mail(const GaimAccount *account)
1696 {
1697 g_return_val_if_fail(account != NULL, FALSE);
1698
1699 return gaim_account_get_bool(account, "check-mail", FALSE);
1700 }
1701
1702 gboolean
1703 gaim_account_get_enabled(const GaimAccount *account, const char *ui)
1704 {
1705 g_return_val_if_fail(account != NULL, FALSE);
1706 g_return_val_if_fail(ui != NULL, FALSE);
1707
1708 return gaim_account_get_ui_bool(account, ui, "auto-login", FALSE);
1709 }
1710
1711 GaimProxyInfo *
1712 gaim_account_get_proxy_info(const GaimAccount *account)
1713 {
1714 g_return_val_if_fail(account != NULL, NULL);
1715
1716 return account->proxy_info;
1717 }
1718
1719 GaimStatus *
1720 gaim_account_get_active_status(const GaimAccount *account)
1721 {
1722 g_return_val_if_fail(account != NULL, NULL);
1723
1724 return gaim_presence_get_active_status(account->presence);
1725 }
1726
1727 GaimStatus *
1728 gaim_account_get_status(const GaimAccount *account, const char *status_id)
1729 {
1730 g_return_val_if_fail(account != NULL, NULL);
1731 g_return_val_if_fail(status_id != NULL, NULL);
1732
1733 return gaim_presence_get_status(account->presence, status_id);
1734 }
1735
1736 GaimStatusType *
1737 gaim_account_get_status_type(const GaimAccount *account, const char *id)
1738 {
1739 const GList *l;
1740
1741 g_return_val_if_fail(account != NULL, NULL);
1742 g_return_val_if_fail(id != NULL, NULL);
1743
1744 for (l = gaim_account_get_status_types(account); l != NULL; l = l->next)
1745 {
1746 GaimStatusType *status_type = (GaimStatusType *)l->data;
1747
1748 if (!strcmp(gaim_status_type_get_id(status_type), id))
1749 return status_type;
1750 }
1751
1752 return NULL;
1753 }
1754
1755 GaimStatusType *
1756 gaim_account_get_status_type_with_primitive(const GaimAccount *account, GaimStatusPrimitive primitive)
1757 {
1758 const GList *l;
1759
1760 g_return_val_if_fail(account != NULL, NULL);
1761
1762 for (l = gaim_account_get_status_types(account); l != NULL; l = l->next)
1763 {
1764 GaimStatusType *status_type = (GaimStatusType *)l->data;
1765
1766 if (gaim_status_type_get_primitive(status_type) == primitive)
1767 return status_type;
1768 }
1769
1770 return NULL;
1771 }
1772
1773 GaimPresence *
1774 gaim_account_get_presence(const GaimAccount *account)
1775 {
1776 g_return_val_if_fail(account != NULL, NULL);
1777
1778 return account->presence;
1779 }
1780
1781 gboolean
1782 gaim_account_is_status_active(const GaimAccount *account,
1783 const char *status_id)
1784 {
1785 g_return_val_if_fail(account != NULL, FALSE);
1786 g_return_val_if_fail(status_id != NULL, FALSE);
1787
1788 return gaim_presence_is_status_active(account->presence, status_id);
1789 }
1790
1791 const GList *
1792 gaim_account_get_status_types(const GaimAccount *account)
1793 {
1794 g_return_val_if_fail(account != NULL, NULL);
1795
1796 return account->status_types;
1797 }
1798
1799 int
1800 gaim_account_get_int(const GaimAccount *account, const char *name,
1801 int default_value)
1802 {
1803 GaimAccountSetting *setting;
1804
1805 g_return_val_if_fail(account != NULL, default_value);
1806 g_return_val_if_fail(name != NULL, default_value);
1807
1808 setting = g_hash_table_lookup(account->settings, name);
1809
1810 if (setting == NULL)
1811 return default_value;
1812
1813 g_return_val_if_fail(setting->type == GAIM_PREF_INT, default_value);
1814
1815 return setting->value.integer;
1816 }
1817
1818 const char *
1819 gaim_account_get_string(const GaimAccount *account, const char *name,
1820 const char *default_value)
1821 {
1822 GaimAccountSetting *setting;
1823
1824 g_return_val_if_fail(account != NULL, default_value);
1825 g_return_val_if_fail(name != NULL, default_value);
1826
1827 setting = g_hash_table_lookup(account->settings, name);
1828
1829 if (setting == NULL)
1830 return default_value;
1831
1832 g_return_val_if_fail(setting->type == GAIM_PREF_STRING, default_value);
1833
1834 return setting->value.string;
1835 }
1836
1837 gboolean
1838 gaim_account_get_bool(const GaimAccount *account, const char *name,
1839 gboolean default_value)
1840 {
1841 GaimAccountSetting *setting;
1842
1843 g_return_val_if_fail(account != NULL, default_value);
1844 g_return_val_if_fail(name != NULL, default_value);
1845
1846 setting = g_hash_table_lookup(account->settings, name);
1847
1848 if (setting == NULL)
1849 return default_value;
1850
1851 g_return_val_if_fail(setting->type == GAIM_PREF_BOOLEAN, default_value);
1852
1853 return setting->value.bool;
1854 }
1855
1856 int
1857 gaim_account_get_ui_int(const GaimAccount *account, const char *ui,
1858 const char *name, int default_value)
1859 {
1860 GaimAccountSetting *setting;
1861 GHashTable *table;
1862
1863 g_return_val_if_fail(account != NULL, default_value);
1864 g_return_val_if_fail(ui != NULL, default_value);
1865 g_return_val_if_fail(name != NULL, default_value);
1866
1867 if ((table = g_hash_table_lookup(account->ui_settings, ui)) == NULL)
1868 return default_value;
1869
1870 if ((setting = g_hash_table_lookup(table, name)) == NULL)
1871 return default_value;
1872
1873 g_return_val_if_fail(setting->type == GAIM_PREF_INT, default_value);
1874
1875 return setting->value.integer;
1876 }
1877
1878 const char *
1879 gaim_account_get_ui_string(const GaimAccount *account, const char *ui,
1880 const char *name, const char *default_value)
1881 {
1882 GaimAccountSetting *setting;
1883 GHashTable *table;
1884
1885 g_return_val_if_fail(account != NULL, default_value);
1886 g_return_val_if_fail(ui != NULL, default_value);
1887 g_return_val_if_fail(name != NULL, default_value);
1888
1889 if ((table = g_hash_table_lookup(account->ui_settings, ui)) == NULL)
1890 return default_value;
1891
1892 if ((setting = g_hash_table_lookup(table, name)) == NULL)
1893 return default_value;
1894
1895 g_return_val_if_fail(setting->type == GAIM_PREF_STRING, default_value);
1896
1897 return setting->value.string;
1898 }
1899
1900 gboolean
1901 gaim_account_get_ui_bool(const GaimAccount *account, const char *ui,
1902 const char *name, gboolean default_value)
1903 {
1904 GaimAccountSetting *setting;
1905 GHashTable *table;
1906
1907 g_return_val_if_fail(account != NULL, default_value);
1908 g_return_val_if_fail(ui != NULL, default_value);
1909 g_return_val_if_fail(name != NULL, default_value);
1910
1911 if ((table = g_hash_table_lookup(account->ui_settings, ui)) == NULL)
1912 return default_value;
1913
1914 if ((setting = g_hash_table_lookup(table, name)) == NULL)
1915 return default_value;
1916
1917 g_return_val_if_fail(setting->type == GAIM_PREF_BOOLEAN, default_value);
1918
1919 return setting->value.bool;
1920 }
1921
1922 GaimLog *
1923 gaim_account_get_log(GaimAccount *account, gboolean create)
1924 {
1925 g_return_val_if_fail(account != NULL, NULL);
1926
1927 if(!account->system_log && create){
1928 GaimPresence *presence;
1929 int login_time;
1930
1931 presence = gaim_account_get_presence(account);
1932 login_time = gaim_presence_get_login_time(presence);
1933
1934 account->system_log = gaim_log_new(GAIM_LOG_SYSTEM,
1935 gaim_account_get_username(account), account, NULL,
1936 (login_time != 0) ? login_time : time(NULL), NULL);
1937 }
1938
1939 return account->system_log;
1940 }
1941
1942 void
1943 gaim_account_destroy_log(GaimAccount *account)
1944 {
1945 g_return_if_fail(account != NULL);
1946
1947 if(account->system_log){
1948 gaim_log_free(account->system_log);
1949 account->system_log = NULL;
1950 }
1951 }
1952
1953 void
1954 gaim_account_add_buddy(GaimAccount *account, GaimBuddy *buddy)
1955 {
1956 GaimPluginProtocolInfo *prpl_info = NULL;
1957 GaimConnection *gc = gaim_account_get_connection(account);
1958
1959 if (gc != NULL && gc->prpl != NULL)
1960 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl);
1961
1962 if (prpl_info != NULL && g_list_find(gaim_connections_get_all(), gc) &&
1963 prpl_info->add_buddy != NULL)
1964 prpl_info->add_buddy(gc, buddy, gaim_buddy_get_group(buddy));
1965 }
1966
1967 void
1968 gaim_account_add_buddies(GaimAccount *account, GList *buddies)
1969 {
1970 GaimPluginProtocolInfo *prpl_info = NULL;
1971 GaimConnection *gc = gaim_account_get_connection(account);
1972
1973 if (gc != NULL && gc->prpl != NULL)
1974 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl);
1975
1976 if (prpl_info && g_list_find(gaim_connections_get_all(), gc)) {
1977 GList *cur, *groups = NULL;
1978
1979 /* Make a list of what group each buddy is in */
1980 for (cur = buddies; cur != NULL; cur = cur->next) {
1981 GaimBlistNode *node = cur->data;
1982 groups = g_list_append(groups, node->parent->parent);
1983 }
1984
1985 if (prpl_info->add_buddies != NULL)
1986 prpl_info->add_buddies(gc, buddies, groups);
1987 else if (prpl_info->add_buddy != NULL) {
1988 GList *curb = buddies, *curg = groups;
1989
1990 while ((curb != NULL) && (curg != NULL)) {
1991 prpl_info->add_buddy(gc, curb->data, curg->data);
1992 curb = curb->next;
1993 curg = curg->next;
1994 }
1995 }
1996
1997 g_list_free(groups);
1998 }
1999 }
2000
2001 void
2002 gaim_account_remove_buddy(GaimAccount *account, GaimBuddy *buddy,
2003 GaimGroup *group)
2004 {
2005 GaimPluginProtocolInfo *prpl_info = NULL;
2006 GaimConnection *gc = gaim_account_get_connection(account);
2007
2008 if (gc != NULL && gc->prpl != NULL)
2009 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl);
2010
2011 if (prpl_info && g_list_find(gaim_connections_get_all(), gc) && prpl_info->remove_buddy)
2012 prpl_info->remove_buddy(gc, buddy, group);
2013 }
2014
2015 void
2016 gaim_account_remove_buddies(GaimAccount *account, GList *buddies, GList *groups)
2017 {
2018 GaimPluginProtocolInfo *prpl_info = NULL;
2019 GaimConnection *gc = gaim_account_get_connection(account);
2020
2021 if (!g_list_find(gaim_connections_get_all(), gc))
2022 return;
2023
2024 if (gc != NULL && gc->prpl != NULL)
2025 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl);
2026
2027 if (prpl_info && g_list_find(gaim_connections_get_all(), gc)) {
2028 if (prpl_info->remove_buddies)
2029 prpl_info->remove_buddies(gc, buddies, groups);
2030 else {
2031 GList *curb = buddies;
2032 GList *curg = groups;
2033 while ((curb != NULL) && (curg != NULL)) {
2034 gaim_account_remove_buddy(account, curb->data, curg->data);
2035 curb = curb->next;
2036 curg = curg->next;
2037 }
2038 }
2039 }
2040 }
2041
2042 void
2043 gaim_account_remove_group(GaimAccount *account, GaimGroup *group)
2044 {
2045 GaimPluginProtocolInfo *prpl_info = NULL;
2046 GaimConnection *gc = gaim_account_get_connection(account);
2047
2048 if (gc != NULL && gc->prpl != NULL)
2049 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl);
2050
2051 if (prpl_info && g_list_find(gaim_connections_get_all(), gc) && prpl_info->remove_group)
2052 prpl_info->remove_group(gc, group);
2053 }
2054
2055 void
2056 gaim_account_change_password(GaimAccount *account, const char *orig_pw,
2057 const char *new_pw)
2058 {
2059 GaimPluginProtocolInfo *prpl_info = NULL;
2060 GaimConnection *gc = gaim_account_get_connection(account);
2061
2062 gaim_account_set_password(account, new_pw);
2063
2064 if (gc != NULL && gc->prpl != NULL)
2065 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl);
2066
2067 if (prpl_info && g_list_find(gaim_connections_get_all(), gc) && prpl_info->change_passwd)
2068 prpl_info->change_passwd(gc, orig_pw, new_pw);
2069 }
2070
2071 gboolean gaim_account_supports_offline_message(GaimAccount *account, GaimBuddy *buddy)
2072 {
2073 GaimConnection *gc;
2074 GaimPluginProtocolInfo *prpl_info;
2075
2076 g_return_val_if_fail(account, FALSE);
2077 g_return_val_if_fail(buddy, FALSE);
2078
2079 gc = gaim_account_get_connection(account);
2080 if (gc == NULL)
2081 return FALSE;
2082
2083 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl);
2084
2085 if (!prpl_info || !prpl_info->offline_message)
2086 return FALSE;
2087 return prpl_info->offline_message(buddy);
2088 }
2089
2090 void
2091 gaim_accounts_add(GaimAccount *account)
2092 {
2093 g_return_if_fail(account != NULL);
2094
2095 if (g_list_find(accounts, account) != NULL)
2096 return;
2097
2098 accounts = g_list_append(accounts, account);
2099
2100 schedule_accounts_save();
2101
2102 gaim_signal_emit(gaim_accounts_get_handle(), "account-added", account);
2103 }
2104
2105 void
2106 gaim_accounts_remove(GaimAccount *account)
2107 {
2108 g_return_if_fail(account != NULL);
2109
2110 accounts = g_list_remove(accounts, account);
2111
2112 schedule_accounts_save();
2113
2114 gaim_signal_emit(gaim_accounts_get_handle(), "account-removed", account);
2115 }
2116
2117 void
2118 gaim_accounts_delete(GaimAccount *account)
2119 {
2120 GaimBlistNode *gnode, *cnode, *bnode;
2121
2122 g_return_if_fail(account != NULL);
2123
2124 if (gaim_account_is_connected(account))
2125 gaim_account_disconnect(account);
2126
2127 gaim_notify_close_with_handle(account);
2128 gaim_request_close_with_handle(account);
2129
2130 gaim_accounts_remove(account);
2131
2132 /* Remove this account's buddies */
2133 for (gnode = gaim_get_blist()->root; gnode != NULL; gnode = gnode->next) {
2134 if (!GAIM_BLIST_NODE_IS_GROUP(gnode))
2135 continue;
2136
2137 cnode = gnode->child;
2138 while (cnode) {
2139 GaimBlistNode *cnode_next = cnode->next;
2140
2141 if(GAIM_BLIST_NODE_IS_CONTACT(cnode)) {
2142 bnode = cnode->child;
2143 while (bnode) {
2144 GaimBlistNode *bnode_next = bnode->next;
2145
2146 if (GAIM_BLIST_NODE_IS_BUDDY(bnode)) {
2147 GaimBuddy *b = (GaimBuddy *)bnode;
2148
2149 if (b->account == account)
2150 gaim_blist_remove_buddy(b);
2151 }
2152 bnode = bnode_next;
2153 }
2154 } else if (GAIM_BLIST_NODE_IS_CHAT(cnode)) {
2155 GaimChat *c = (GaimChat *)cnode;
2156
2157 if (c->account == account)
2158 gaim_blist_remove_chat(c);
2159 }
2160 cnode = cnode_next;
2161 }
2162 }
2163
2164 /* Remove this account's pounces */
2165 gaim_pounce_destroy_all_by_account(account);
2166
2167 /* This will cause the deletion of an old buddy icon. */
2168 gaim_account_set_buddy_icon(account, NULL);
2169
2170 gaim_account_destroy(account);
2171 }
2172
2173 void
2174 gaim_accounts_reorder(GaimAccount *account, gint new_index)
2175 {
2176 gint index;
2177 GList *l;
2178
2179 g_return_if_fail(account != NULL);
2180 g_return_if_fail(new_index <= g_list_length(accounts));
2181
2182 index = g_list_index(accounts, account);
2183
2184 if (index == -1) {
2185 gaim_debug_error("account",
2186 "Unregistered account (%s) discovered during reorder!\n",
2187 gaim_account_get_username(account));
2188 return;
2189 }
2190
2191 l = g_list_nth(accounts, index);
2192
2193 if (new_index > index)
2194 new_index--;
2195
2196 /* Remove the old one. */
2197 accounts = g_list_delete_link(accounts, l);
2198
2199 /* Insert it where it should go. */
2200 accounts = g_list_insert(accounts, account, new_index);
2201
2202 schedule_accounts_save();
2203 }
2204
2205 GList *
2206 gaim_accounts_get_all(void)
2207 {
2208 return accounts;
2209 }
2210
2211 GList *
2212 gaim_accounts_get_all_active(void)
2213 {
2214 GList *list = NULL;
2215 GList *all = gaim_accounts_get_all();
2216
2217 while (all != NULL) {
2218 GaimAccount *account = all->data;
2219
2220 if (gaim_account_get_enabled(account, gaim_core_get_ui()))
2221 list = g_list_append(list, account);
2222
2223 all = all->next;
2224 }
2225
2226 return list;
2227 }
2228
2229 GaimAccount *
2230 gaim_accounts_find(const char *name, const char *protocol_id)
2231 {
2232 GaimAccount *account = NULL;
2233 GList *l;
2234 char *who;
2235
2236 g_return_val_if_fail(name != NULL, NULL);
2237
2238 who = g_strdup(gaim_normalize(NULL, name));
2239
2240 for (l = gaim_accounts_get_all(); l != NULL; l = l->next) {
2241 account = (GaimAccount *)l->data;
2242
2243 if (!strcmp(gaim_normalize(NULL, gaim_account_get_username(account)), who) &&
2244 (!protocol_id || !strcmp(account->protocol_id, protocol_id))) {
2245
2246 break;
2247 }
2248
2249 account = NULL;
2250 }
2251
2252 g_free(who);
2253
2254 return account;
2255 }
2256
2257 void
2258 gaim_accounts_restore_current_statuses()
2259 {
2260 GList *l;
2261 GaimAccount *account;
2262
2263 for (l = gaim_accounts_get_all(); l != NULL; l = l->next)
2264 {
2265 account = (GaimAccount *)l->data;
2266 if (gaim_account_get_enabled(account, gaim_core_get_ui()) &&
2267 (gaim_presence_is_online(account->presence)))
2268 {
2269 gaim_account_connect(account);
2270 }
2271 }
2272 }
2273
2274 void
2275 gaim_accounts_set_ui_ops(GaimAccountUiOps *ops)
2276 {
2277 account_ui_ops = ops;
2278 }
2279
2280 GaimAccountUiOps *
2281 gaim_accounts_get_ui_ops(void)
2282 {
2283 return account_ui_ops;
2284 }
2285
2286 void *
2287 gaim_accounts_get_handle(void)
2288 {
2289 static int handle;
2290
2291 return &handle;
2292 }
2293
2294 void
2295 gaim_accounts_init(void)
2296 {
2297 void *handle = gaim_accounts_get_handle();
2298
2299 gaim_signal_register(handle, "account-connecting",
2300 gaim_marshal_VOID__POINTER, NULL, 1,
2301 gaim_value_new(GAIM_TYPE_SUBTYPE,
2302 GAIM_SUBTYPE_ACCOUNT));
2303
2304 gaim_signal_register(handle, "account-disabled",
2305 gaim_marshal_VOID__POINTER, NULL, 1,
2306 gaim_value_new(GAIM_TYPE_SUBTYPE,
2307 GAIM_SUBTYPE_ACCOUNT));
2308
2309 gaim_signal_register(handle, "account-enabled",
2310 gaim_marshal_VOID__POINTER, NULL, 1,
2311 gaim_value_new(GAIM_TYPE_SUBTYPE,
2312 GAIM_SUBTYPE_ACCOUNT));
2313
2314 gaim_signal_register(handle, "account-setting-info",
2315 gaim_marshal_VOID__POINTER_POINTER, NULL, 2,
2316 gaim_value_new(GAIM_TYPE_SUBTYPE,
2317 GAIM_SUBTYPE_ACCOUNT),
2318 gaim_value_new(GAIM_TYPE_STRING));
2319
2320 gaim_signal_register(handle, "account-set-info",
2321 gaim_marshal_VOID__POINTER_POINTER, NULL, 2,
2322 gaim_value_new(GAIM_TYPE_SUBTYPE,
2323 GAIM_SUBTYPE_ACCOUNT),
2324 gaim_value_new(GAIM_TYPE_STRING));
2325
2326 gaim_signal_register(handle, "account-added",
2327 gaim_marshal_VOID__POINTER, NULL, 1,
2328 gaim_value_new(GAIM_TYPE_SUBTYPE, GAIM_SUBTYPE_ACCOUNT));
2329
2330 gaim_signal_register(handle, "account-removed",
2331 gaim_marshal_VOID__POINTER, NULL, 1,
2332 gaim_value_new(GAIM_TYPE_SUBTYPE, GAIM_SUBTYPE_ACCOUNT));
2333
2334 gaim_signal_register(handle, "account-status-changed",
2335 gaim_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3,
2336 gaim_value_new(GAIM_TYPE_SUBTYPE,
2337 GAIM_SUBTYPE_ACCOUNT),
2338 gaim_value_new(GAIM_TYPE_SUBTYPE,
2339 GAIM_SUBTYPE_STATUS),
2340 gaim_value_new(GAIM_TYPE_SUBTYPE,
2341 GAIM_SUBTYPE_STATUS));
2342
2343 gaim_signal_register(handle, "account-alias-changed",
2344 gaim_marshal_VOID__POINTER_POINTER, NULL, 2,
2345 gaim_value_new(GAIM_TYPE_SUBTYPE,
2346 GAIM_SUBTYPE_ACCOUNT),
2347 gaim_value_new(GAIM_TYPE_STRING));
2348
2349 load_accounts();
2350
2351 }
2352
2353 void
2354 gaim_accounts_uninit(void)
2355 {
2356 if (save_timer != 0)
2357 {
2358 gaim_timeout_remove(save_timer);
2359 save_timer = 0;
2360 sync_accounts();
2361 }
2362
2363 gaim_signals_unregister_by_instance(gaim_accounts_get_handle());
2364 }