3 * Purple is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
29 static PurpleAccountUiOps
*account_ui_ops
= NULL
;
31 static GList
*accounts
= NULL
;
32 static guint save_timer
= 0;
33 static gboolean accounts_loaded
= FALSE
;
35 /*********************************************************************
37 *********************************************************************/
38 static PurpleXmlNode
*
39 accounts_to_xmlnode(void)
41 PurpleXmlNode
*node
, *child
;
44 node
= purple_xmlnode_new("account");
45 purple_xmlnode_set_attrib(node
, "version", "1.0");
47 for (cur
= purple_accounts_get_all(); cur
!= NULL
; cur
= cur
->next
)
49 child
= _purple_account_to_xmlnode(cur
->data
);
50 purple_xmlnode_insert_child(node
, child
);
64 purple_debug_error("accounts", "Attempted to save accounts before "
69 node
= accounts_to_xmlnode();
70 data
= purple_xmlnode_to_formatted_str(node
, NULL
);
71 purple_util_write_data_to_config_file("accounts.xml", data
, -1);
73 purple_xmlnode_free(node
);
77 save_cb(gpointer data
)
85 purple_accounts_schedule_save(void)
88 save_timer
= g_timeout_add_seconds(5, save_cb
, NULL
);
92 migrate_icq_server(PurpleAccount
*account
)
94 /* Migrate the login server setting for ICQ accounts. See
95 * 'mtn log --last 1 --no-graph --from b6d7712e90b68610df3bd2d8cbaf46d94c8b3794'
96 * for details on the change. */
98 if(purple_strequal(purple_account_get_protocol_id(account
), "prpl-icq")) {
99 const char *tmp
= purple_account_get_string(account
, "server", NULL
);
101 /* Non-secure server */
102 if(purple_strequal(tmp
, "login.messaging.aol.com") ||
103 purple_strequal(tmp
, "login.oscar.aol.com"))
104 purple_account_set_string(account
, "server", "login.icq.com");
107 if(purple_strequal(tmp
, "slogin.oscar.aol.com"))
108 purple_account_set_string(account
, "server", "slogin.icq.com");
113 migrate_xmpp_encryption(PurpleAccount
*account
)
115 /* When this is removed, nuke the "old_ssl" and "require_tls" settings */
116 if (g_str_equal(purple_account_get_protocol_id(account
), "prpl-jabber")) {
117 const char *sec
= purple_account_get_string(account
, "connection_security", "");
119 if (g_str_equal("", sec
)) {
120 const char *val
= "require_tls";
121 if (purple_account_get_bool(account
, "old_ssl", FALSE
))
123 else if (!purple_account_get_bool(account
, "require_tls", TRUE
))
124 val
= "opportunistic_tls";
126 purple_account_set_string(account
, "connection_security", val
);
132 parse_settings(PurpleXmlNode
*node
, PurpleAccount
*account
)
135 PurpleXmlNode
*child
;
137 /* Get the UI string, if these are UI settings */
138 ui
= purple_xmlnode_get_attrib(node
, "ui");
140 /* Read settings, one by one */
141 for (child
= purple_xmlnode_get_child(node
, "setting"); child
!= NULL
;
142 child
= purple_xmlnode_get_next_twin(child
))
144 const char *name
, *str_type
;
148 name
= purple_xmlnode_get_attrib(child
, "name");
150 /* Ignore this setting */
153 str_type
= purple_xmlnode_get_attrib(child
, "type");
154 if (str_type
== NULL
)
155 /* Ignore this setting */
158 if (purple_strequal(str_type
, "string"))
159 type
= PURPLE_PREF_STRING
;
160 else if (purple_strequal(str_type
, "int"))
161 type
= PURPLE_PREF_INT
;
162 else if (purple_strequal(str_type
, "bool"))
163 type
= PURPLE_PREF_BOOLEAN
;
165 /* Ignore this setting */
168 data
= purple_xmlnode_get_data(child
);
170 /* Ignore this setting */
175 if (type
== PURPLE_PREF_STRING
)
176 purple_account_set_string(account
, name
, data
);
177 else if (type
== PURPLE_PREF_INT
)
178 purple_account_set_int(account
, name
, atoi(data
));
179 else if (type
== PURPLE_PREF_BOOLEAN
)
180 purple_account_set_bool(account
, name
,
181 (*data
== '0' ? FALSE
: TRUE
));
183 if (type
== PURPLE_PREF_STRING
)
184 purple_account_set_ui_string(account
, ui
, name
, data
);
185 else if (type
== PURPLE_PREF_INT
)
186 purple_account_set_ui_int(account
, ui
, name
, atoi(data
));
187 else if (type
== PURPLE_PREF_BOOLEAN
)
188 purple_account_set_ui_bool(account
, ui
, name
,
189 (*data
== '0' ? FALSE
: TRUE
));
195 /* we do this here because we need access to account settings to determine
196 * if we can/should migrate an ICQ account's server setting */
197 migrate_icq_server(account
);
198 /* we do this here because we need to do it before the user views the
199 * Edit Account dialog. */
200 migrate_xmpp_encryption(account
);
204 parse_status_attrs(PurpleXmlNode
*node
, PurpleStatus
*status
)
207 PurpleXmlNode
*child
;
210 for (child
= purple_xmlnode_get_child(node
, "attribute"); child
!= NULL
;
211 child
= purple_xmlnode_get_next_twin(child
))
213 const char *id
= purple_xmlnode_get_attrib(child
, "id");
214 const char *value
= purple_xmlnode_get_attrib(child
, "value");
216 if (!id
|| !*id
|| !value
|| !*value
)
219 attr_value
= purple_status_get_attr_value(status
, id
);
223 list
= g_list_append(list
, (char *)id
);
225 switch (G_VALUE_TYPE(attr_value
))
228 list
= g_list_append(list
, (char *)value
);
234 if (sscanf(value
, "%d", &v
) == 1)
235 list
= g_list_append(list
, GINT_TO_POINTER(v
));
237 list
= g_list_remove(list
, id
);
249 parse_status(PurpleXmlNode
*node
, PurpleAccount
*account
)
251 gboolean active
= FALSE
;
254 PurpleXmlNode
*child
;
257 /* Get the active/inactive state */
258 data
= purple_xmlnode_get_attrib(node
, "active");
261 if (g_ascii_strcasecmp(data
, "true") == 0)
263 else if (g_ascii_strcasecmp(data
, "false") == 0)
268 /* Get the type of the status */
269 type
= purple_xmlnode_get_attrib(node
, "type");
273 /* Read attributes into a GList */
274 child
= purple_xmlnode_get_child(node
, "attributes");
277 attrs
= parse_status_attrs(child
,
278 purple_account_get_status(account
, type
));
281 purple_account_set_status_list(account
, type
, active
, attrs
);
287 parse_statuses(PurpleXmlNode
*node
, PurpleAccount
*account
)
289 PurpleXmlNode
*child
;
291 for (child
= purple_xmlnode_get_child(node
, "status"); child
!= NULL
;
292 child
= purple_xmlnode_get_next_twin(child
))
294 parse_status(child
, account
);
299 parse_proxy_info(PurpleXmlNode
*node
, PurpleAccount
*account
)
301 PurpleProxyInfo
*proxy_info
;
302 PurpleXmlNode
*child
;
305 proxy_info
= purple_proxy_info_new();
307 /* Use the global proxy settings, by default */
308 purple_proxy_info_set_proxy_type(proxy_info
, PURPLE_PROXY_USE_GLOBAL
);
310 /* Read proxy type */
311 child
= purple_xmlnode_get_child(node
, "type");
312 if ((child
!= NULL
) && ((data
= purple_xmlnode_get_data(child
)) != NULL
))
314 if (purple_strequal(data
, "global"))
315 purple_proxy_info_set_proxy_type(proxy_info
, PURPLE_PROXY_USE_GLOBAL
);
316 else if (purple_strequal(data
, "none"))
317 purple_proxy_info_set_proxy_type(proxy_info
, PURPLE_PROXY_NONE
);
318 else if (purple_strequal(data
, "http"))
319 purple_proxy_info_set_proxy_type(proxy_info
, PURPLE_PROXY_HTTP
);
320 else if (purple_strequal(data
, "socks4"))
321 purple_proxy_info_set_proxy_type(proxy_info
, PURPLE_PROXY_SOCKS4
);
322 else if (purple_strequal(data
, "socks5"))
323 purple_proxy_info_set_proxy_type(proxy_info
, PURPLE_PROXY_SOCKS5
);
324 else if (purple_strequal(data
, "tor"))
325 purple_proxy_info_set_proxy_type(proxy_info
, PURPLE_PROXY_TOR
);
326 else if (purple_strequal(data
, "envvar"))
327 purple_proxy_info_set_proxy_type(proxy_info
, PURPLE_PROXY_USE_ENVVAR
);
330 purple_debug_error("accounts", "Invalid proxy type found when "
331 "loading account information for %s\n",
332 purple_account_get_username(account
));
337 /* Read proxy host */
338 child
= purple_xmlnode_get_child(node
, "host");
339 if ((child
!= NULL
) && ((data
= purple_xmlnode_get_data(child
)) != NULL
))
341 purple_proxy_info_set_host(proxy_info
, data
);
345 /* Read proxy port */
346 child
= purple_xmlnode_get_child(node
, "port");
347 if ((child
!= NULL
) && ((data
= purple_xmlnode_get_data(child
)) != NULL
))
349 purple_proxy_info_set_port(proxy_info
, atoi(data
));
353 /* Read proxy username */
354 child
= purple_xmlnode_get_child(node
, "username");
355 if ((child
!= NULL
) && ((data
= purple_xmlnode_get_data(child
)) != NULL
))
357 purple_proxy_info_set_username(proxy_info
, data
);
361 /* Read proxy password */
362 child
= purple_xmlnode_get_child(node
, "password");
363 if ((child
!= NULL
) && ((data
= purple_xmlnode_get_data(child
)) != NULL
))
365 purple_proxy_info_set_password(proxy_info
, data
);
369 /* If there are no values set then proxy_info NULL */
370 if ((purple_proxy_info_get_proxy_type(proxy_info
) == PURPLE_PROXY_USE_GLOBAL
) &&
371 (purple_proxy_info_get_host(proxy_info
) == NULL
) &&
372 (purple_proxy_info_get_port(proxy_info
) == 0) &&
373 (purple_proxy_info_get_username(proxy_info
) == NULL
) &&
374 (purple_proxy_info_get_password(proxy_info
) == NULL
))
376 purple_proxy_info_destroy(proxy_info
);
380 purple_account_set_proxy_info(account
, proxy_info
);
384 parse_current_error(PurpleXmlNode
*node
, PurpleAccount
*account
)
387 char *type_str
= NULL
, *description
= NULL
;
388 PurpleXmlNode
*child
;
389 PurpleConnectionErrorInfo
*current_error
= NULL
;
391 child
= purple_xmlnode_get_child(node
, "type");
392 if (child
== NULL
|| (type_str
= purple_xmlnode_get_data(child
)) == NULL
)
394 type
= atoi(type_str
);
397 if (type
> PURPLE_CONNECTION_ERROR_OTHER_ERROR
)
399 purple_debug_error("accounts",
400 "Invalid PurpleConnectionError value %d found when "
401 "loading account information for %s\n",
402 type
, purple_account_get_username(account
));
403 type
= PURPLE_CONNECTION_ERROR_OTHER_ERROR
;
406 child
= purple_xmlnode_get_child(node
, "description");
408 description
= purple_xmlnode_get_data(child
);
409 if (description
== NULL
)
410 description
= g_strdup("");
412 current_error
= g_new0(PurpleConnectionErrorInfo
, 1);
413 current_error
->type
= type
;
414 current_error
->description
= description
;
416 _purple_account_set_current_error(account
, current_error
);
419 static PurpleAccount
*
420 parse_account(PurpleXmlNode
*node
)
423 PurpleXmlNode
*child
;
424 char *protocol_id
= NULL
;
428 child
= purple_xmlnode_get_child(node
, "protocol");
430 protocol_id
= purple_xmlnode_get_data(child
);
432 child
= purple_xmlnode_get_child(node
, "name");
434 name
= purple_xmlnode_get_data(child
);
437 /* Do we really need to do this? */
438 child
= purple_xmlnode_get_child(node
, "username");
440 name
= purple_xmlnode_get_data(child
);
443 if ((protocol_id
== NULL
) || (name
== NULL
))
450 ret
= purple_account_new(name
, protocol_id
);
455 child
= purple_xmlnode_get_child(node
, "alias");
456 if ((child
!= NULL
) && ((data
= purple_xmlnode_get_data(child
)) != NULL
))
459 purple_account_set_private_alias(ret
, data
);
463 /* Read the statuses */
464 child
= purple_xmlnode_get_child(node
, "statuses");
467 parse_statuses(child
, ret
);
470 /* Read the userinfo */
471 child
= purple_xmlnode_get_child(node
, "userinfo");
472 if ((child
!= NULL
) && ((data
= purple_xmlnode_get_data(child
)) != NULL
))
474 purple_account_set_user_info(ret
, data
);
478 /* Read an old buddyicon */
479 child
= purple_xmlnode_get_child(node
, "buddyicon");
480 if ((child
!= NULL
) && ((data
= purple_xmlnode_get_data(child
)) != NULL
))
482 const char *dirname
= purple_buddy_icons_get_cache_dir();
483 char *filename
= g_build_filename(dirname
, data
, NULL
);
487 if (g_file_get_contents(filename
, &contents
, &len
, NULL
))
489 purple_buddy_icons_set_account_icon(ret
, (guchar
*)contents
, len
);
496 /* Read settings (both core and UI) */
497 for (child
= purple_xmlnode_get_child(node
, "settings"); child
!= NULL
;
498 child
= purple_xmlnode_get_next_twin(child
))
500 parse_settings(child
, ret
);
504 child
= purple_xmlnode_get_child(node
, "proxy");
507 parse_proxy_info(child
, ret
);
510 /* Read current error */
511 child
= purple_xmlnode_get_child(node
, "current_error");
514 parse_current_error(child
, ret
);
517 /* Read the password */
518 child
= purple_xmlnode_get_child(node
, "password");
521 const char *keyring_id
= purple_xmlnode_get_attrib(child
, "keyring_id");
522 const char *mode
= purple_xmlnode_get_attrib(child
, "mode");
525 data
= purple_xmlnode_get_data(child
);
526 result
= purple_keyring_import_password(ret
, keyring_id
, mode
, data
, NULL
);
528 if (result
== TRUE
|| purple_keyring_get_inuse() == NULL
) {
529 purple_account_set_remember_password(ret
, TRUE
);
531 purple_debug_error("accounts", "Failed to import password.\n");
533 purple_str_wipe(data
);
542 PurpleXmlNode
*node
, *child
;
544 accounts_loaded
= TRUE
;
546 node
= purple_util_read_xml_from_config_file("accounts.xml", _("accounts"));
551 for (child
= purple_xmlnode_get_child(node
, "account"); child
!= NULL
;
552 child
= purple_xmlnode_get_next_twin(child
))
554 PurpleAccount
*new_acct
;
555 new_acct
= parse_account(child
);
556 purple_accounts_add(new_acct
);
559 purple_xmlnode_free(node
);
561 _purple_buddy_icons_account_loaded_cb();
565 purple_accounts_add(PurpleAccount
*account
)
567 g_return_if_fail(account
!= NULL
);
569 if (g_list_find(accounts
, account
) != NULL
)
572 accounts
= g_list_append(accounts
, account
);
574 purple_accounts_schedule_save();
576 purple_signal_emit(purple_accounts_get_handle(), "account-added", account
);
580 purple_accounts_remove(PurpleAccount
*account
)
582 g_return_if_fail(account
!= NULL
);
584 accounts
= g_list_remove(accounts
, account
);
586 purple_accounts_schedule_save();
588 /* Clearing the error ensures that account-error-changed is emitted,
589 * which is the end of the guarantee that the the error's pointer is
592 purple_account_clear_current_error(account
);
593 purple_signal_emit(purple_accounts_get_handle(), "account-removed", account
);
597 purple_accounts_delete_set(PurpleAccount
*account
, GError
*error
, gpointer data
)
599 g_object_unref(G_OBJECT(account
));
603 purple_accounts_delete(PurpleAccount
*account
)
605 PurpleBlistNode
*gnode
, *cnode
, *bnode
;
608 g_return_if_fail(account
!= NULL
);
611 * Disable the account before blowing it out of the water.
612 * Conceptually it probably makes more sense to disable the
613 * account for all UIs rather than the just the current UI,
614 * but it doesn't really matter.
616 purple_account_set_enabled(account
, purple_core_get_ui(), FALSE
);
618 purple_notify_close_with_handle(account
);
619 purple_request_close_with_handle(account
);
621 purple_accounts_remove(account
);
623 /* Remove this account's buddies */
624 for (gnode
= purple_blist_get_root();
626 gnode
= purple_blist_node_get_sibling_next(gnode
))
628 if (!PURPLE_IS_GROUP(gnode
))
631 cnode
= purple_blist_node_get_first_child(gnode
);
633 PurpleBlistNode
*cnode_next
= purple_blist_node_get_sibling_next(cnode
);
635 if(PURPLE_IS_CONTACT(cnode
)) {
636 bnode
= purple_blist_node_get_first_child(cnode
);
638 PurpleBlistNode
*bnode_next
= purple_blist_node_get_sibling_next(bnode
);
640 if (PURPLE_IS_BUDDY(bnode
)) {
641 PurpleBuddy
*b
= (PurpleBuddy
*)bnode
;
643 if (purple_buddy_get_account(b
) == account
)
644 purple_blist_remove_buddy(b
);
648 } else if (PURPLE_IS_CHAT(cnode
)) {
649 PurpleChat
*c
= (PurpleChat
*)cnode
;
651 if (purple_chat_get_account(c
) == account
)
652 purple_blist_remove_chat(c
);
658 /* Remove any open conversation for this account */
659 for (iter
= purple_conversations_get_all(); iter
; ) {
660 PurpleConversation
*conv
= iter
->data
;
662 if (purple_conversation_get_account(conv
) == account
)
663 g_object_unref(conv
);
666 /* Remove this account's pounces */
667 purple_pounce_destroy_all_by_account(account
);
669 /* This will cause the deletion of an old buddy icon. */
670 purple_buddy_icons_set_account_icon(account
, NULL
, 0);
672 /* This is async because we do not want the
673 * account being overwritten before we are done.
675 purple_keyring_set_password(account
, NULL
,
676 purple_accounts_delete_set
, NULL
);
680 purple_accounts_reorder(PurpleAccount
*account
, guint new_index
)
685 g_return_if_fail(account
!= NULL
);
686 g_return_if_fail(new_index
<= g_list_length(accounts
));
688 index
= g_list_index(accounts
, account
);
691 purple_debug_error("accounts",
692 "Unregistered account (%s) discovered during reorder!\n",
693 purple_account_get_username(account
));
697 l
= g_list_nth(accounts
, index
);
699 if (new_index
> (guint
)index
)
702 /* Remove the old one. */
703 accounts
= g_list_delete_link(accounts
, l
);
705 /* Insert it where it should go. */
706 accounts
= g_list_insert(accounts
, account
, new_index
);
708 purple_accounts_schedule_save();
712 purple_accounts_get_all(void)
718 purple_accounts_get_all_active(void)
721 GList
*all
= purple_accounts_get_all();
723 while (all
!= NULL
) {
724 PurpleAccount
*account
= all
->data
;
726 if (purple_account_get_enabled(account
, purple_core_get_ui()))
727 list
= g_list_append(list
, account
);
736 purple_accounts_find(const char *name
, const char *protocol_id
)
738 PurpleAccount
*account
= NULL
;
742 g_return_val_if_fail(name
!= NULL
, NULL
);
743 g_return_val_if_fail(protocol_id
!= NULL
, NULL
);
745 for (l
= purple_accounts_get_all(); l
!= NULL
; l
= l
->next
) {
746 account
= (PurpleAccount
*)l
->data
;
748 if (!purple_strequal(purple_account_get_protocol_id(account
), protocol_id
))
751 who
= g_strdup(purple_normalize(account
, name
));
752 if (purple_strequal(purple_normalize(account
, purple_account_get_username(account
)), who
)) {
763 purple_accounts_restore_current_statuses()
766 PurpleAccount
*account
;
768 /* If we're not connected to the Internet right now, we bail on this */
769 if (!purple_network_is_available())
771 purple_debug_warning("accounts", "Network not connected; skipping reconnect\n");
775 for (l
= purple_accounts_get_all(); l
!= NULL
; l
= l
->next
)
777 account
= (PurpleAccount
*)l
->data
;
779 if (purple_account_get_enabled(account
, purple_core_get_ui()) &&
780 (purple_presence_is_online(purple_account_get_presence(account
))))
782 purple_account_connect(account
);
787 static PurpleAccountUiOps
*
788 purple_account_ui_ops_copy(PurpleAccountUiOps
*ops
)
790 PurpleAccountUiOps
*ops_new
;
792 g_return_val_if_fail(ops
!= NULL
, NULL
);
794 ops_new
= g_new(PurpleAccountUiOps
, 1);
801 purple_account_ui_ops_get_type(void)
803 static GType type
= 0;
806 type
= g_boxed_type_register_static("PurpleAccountUiOps",
807 (GBoxedCopyFunc
)purple_account_ui_ops_copy
,
808 (GBoxedFreeFunc
)g_free
);
815 purple_accounts_set_ui_ops(PurpleAccountUiOps
*ops
)
817 account_ui_ops
= ops
;
821 purple_accounts_get_ui_ops(void)
823 return account_ui_ops
;
827 purple_accounts_get_handle(void)
835 signed_on_cb(PurpleConnection
*gc
,
838 PurpleAccount
*account
= purple_connection_get_account(gc
);
839 purple_account_clear_current_error(account
);
841 purple_signal_emit(purple_accounts_get_handle(), "account-signed-on",
846 signed_off_cb(PurpleConnection
*gc
,
849 PurpleAccount
*account
= purple_connection_get_account(gc
);
851 purple_signal_emit(purple_accounts_get_handle(), "account-signed-off",
856 connection_error_cb(PurpleConnection
*gc
,
857 PurpleConnectionError type
,
858 const gchar
*description
,
861 PurpleAccount
*account
;
862 PurpleConnectionErrorInfo
*err
;
864 account
= purple_connection_get_account(gc
);
866 g_return_if_fail(account
!= NULL
);
868 err
= g_new0(PurpleConnectionErrorInfo
, 1);
871 err
->description
= g_strdup(description
);
873 _purple_account_set_current_error(account
, err
);
875 purple_signal_emit(purple_accounts_get_handle(), "account-connection-error",
876 account
, type
, description
);
880 password_migration_cb(PurpleAccount
*account
)
882 /* account may be NULL (means: all) */
884 purple_accounts_schedule_save();
888 purple_accounts_init(void)
890 void *handle
= purple_accounts_get_handle();
891 void *conn_handle
= purple_connections_get_handle();
893 purple_signal_register(handle
, "account-connecting",
894 purple_marshal_VOID__POINTER
, G_TYPE_NONE
, 1,
895 PURPLE_TYPE_ACCOUNT
);
897 purple_signal_register(handle
, "account-disabled",
898 purple_marshal_VOID__POINTER
, G_TYPE_NONE
, 1,
899 PURPLE_TYPE_ACCOUNT
);
901 purple_signal_register(handle
, "account-enabled",
902 purple_marshal_VOID__POINTER
, G_TYPE_NONE
, 1,
903 PURPLE_TYPE_ACCOUNT
);
905 purple_signal_register(handle
, "account-setting-info",
906 purple_marshal_VOID__POINTER_POINTER
, G_TYPE_NONE
, 2,
907 PURPLE_TYPE_ACCOUNT
, G_TYPE_STRING
);
909 purple_signal_register(handle
, "account-set-info",
910 purple_marshal_VOID__POINTER_POINTER
, G_TYPE_NONE
, 2,
911 PURPLE_TYPE_ACCOUNT
, G_TYPE_STRING
);
913 purple_signal_register(handle
, "account-created",
914 purple_marshal_VOID__POINTER
, G_TYPE_NONE
, 1,
915 PURPLE_TYPE_ACCOUNT
);
917 purple_signal_register(handle
, "account-destroying",
918 purple_marshal_VOID__POINTER
, G_TYPE_NONE
, 1,
919 PURPLE_TYPE_ACCOUNT
);
921 purple_signal_register(handle
, "account-added",
922 purple_marshal_VOID__POINTER
, G_TYPE_NONE
, 1,
923 PURPLE_TYPE_ACCOUNT
);
925 purple_signal_register(handle
, "account-removed",
926 purple_marshal_VOID__POINTER
, G_TYPE_NONE
, 1,
927 PURPLE_TYPE_ACCOUNT
);
929 purple_signal_register(handle
, "account-status-changing",
930 purple_marshal_VOID__POINTER_POINTER_POINTER
,
931 G_TYPE_NONE
, 3, PURPLE_TYPE_ACCOUNT
,
932 PURPLE_TYPE_STATUS
, PURPLE_TYPE_STATUS
);
934 purple_signal_register(handle
, "account-status-changed",
935 purple_marshal_VOID__POINTER_POINTER_POINTER
,
936 G_TYPE_NONE
, 3, PURPLE_TYPE_ACCOUNT
,
937 PURPLE_TYPE_STATUS
, PURPLE_TYPE_STATUS
);
939 purple_signal_register(handle
, "account-actions-changed",
940 purple_marshal_VOID__POINTER
, G_TYPE_NONE
, 1,
941 PURPLE_TYPE_ACCOUNT
);
943 purple_signal_register(handle
, "account-alias-changed",
944 purple_marshal_VOID__POINTER_POINTER
, G_TYPE_NONE
, 2,
945 PURPLE_TYPE_ACCOUNT
, G_TYPE_STRING
);
947 purple_signal_register(handle
, "account-authorization-requested",
948 purple_marshal_INT__POINTER_POINTER_POINTER
,
949 G_TYPE_INT
, 4, PURPLE_TYPE_ACCOUNT
, G_TYPE_STRING
,
950 G_TYPE_STRING
, G_TYPE_STRING
);
952 purple_signal_register(handle
, "account-authorization-denied",
953 purple_marshal_VOID__POINTER_POINTER
, G_TYPE_NONE
, 3,
954 PURPLE_TYPE_ACCOUNT
, G_TYPE_STRING
, G_TYPE_STRING
);
956 purple_signal_register(handle
, "account-authorization-granted",
957 purple_marshal_VOID__POINTER_POINTER
, G_TYPE_NONE
, 3,
958 PURPLE_TYPE_ACCOUNT
, G_TYPE_STRING
, G_TYPE_STRING
);
960 purple_signal_register(handle
, "account-error-changed",
961 purple_marshal_VOID__POINTER_POINTER_POINTER
,
962 G_TYPE_NONE
, 3, PURPLE_TYPE_ACCOUNT
,
963 PURPLE_TYPE_CONNECTION_ERROR_INFO
,
964 PURPLE_TYPE_CONNECTION_ERROR_INFO
);
966 purple_signal_register(handle
, "account-signed-on",
967 purple_marshal_VOID__POINTER
, G_TYPE_NONE
, 1,
968 PURPLE_TYPE_ACCOUNT
);
970 purple_signal_register(handle
, "account-signed-off",
971 purple_marshal_VOID__POINTER
, G_TYPE_NONE
, 1,
972 PURPLE_TYPE_ACCOUNT
);
974 purple_signal_register(handle
, "account-connection-error",
975 purple_marshal_VOID__POINTER_INT_POINTER
,
976 G_TYPE_NONE
, 3, PURPLE_TYPE_ACCOUNT
,
977 PURPLE_TYPE_CONNECTION_ERROR
, G_TYPE_STRING
);
979 purple_signal_connect(conn_handle
, "signed-on", handle
,
980 PURPLE_CALLBACK(signed_on_cb
), NULL
);
981 purple_signal_connect(conn_handle
, "signed-off", handle
,
982 PURPLE_CALLBACK(signed_off_cb
), NULL
);
983 purple_signal_connect(conn_handle
, "connection-error", handle
,
984 PURPLE_CALLBACK(connection_error_cb
), NULL
);
985 purple_signal_connect(purple_keyring_get_handle(), "password-migration", handle
,
986 PURPLE_CALLBACK(password_migration_cb
), NULL
);
993 purple_accounts_uninit(void)
995 gpointer handle
= purple_accounts_get_handle();
998 g_source_remove(save_timer
);
1003 for (; accounts
; accounts
= g_list_delete_link(accounts
, accounts
))
1004 g_object_unref(G_OBJECT(accounts
->data
));
1006 purple_signals_disconnect_by_handle(handle
);
1007 purple_signals_unregister_by_instance(handle
);