2 * @file account.c Account API
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.
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.
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.
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
29 #include "dbus-maybe.h"
46 PurpleConnectionErrorInfo
*current_error
;
47 } PurpleAccountPrivate
;
49 #define PURPLE_ACCOUNT_GET_PRIVATE(account) \
50 ((PurpleAccountPrivate *) (account->priv))
52 /* TODO: Should use PurpleValue instead of this? What about "ui"? */
67 } PurpleAccountSetting
;
71 PurpleAccountRequestType type
;
72 PurpleAccount
*account
;
76 PurpleAccountRequestAuthorizationCb auth_cb
;
77 PurpleAccountRequestAuthorizationCb deny_cb
;
79 } PurpleAccountRequestInfo
;
81 static PurpleAccountUiOps
*account_ui_ops
= NULL
;
83 static GList
*accounts
= NULL
;
84 static guint save_timer
= 0;
85 static gboolean accounts_loaded
= FALSE
;
87 static GList
*handles
= NULL
;
89 static void set_current_error(PurpleAccount
*account
,
90 PurpleConnectionErrorInfo
*new_err
);
92 /*********************************************************************
94 *********************************************************************/
97 setting_to_xmlnode(gpointer key
, gpointer value
, gpointer user_data
)
100 PurpleAccountSetting
*setting
;
101 xmlnode
*node
, *child
;
104 name
= (const char *)key
;
105 setting
= (PurpleAccountSetting
*)value
;
106 node
= (xmlnode
*)user_data
;
108 child
= xmlnode_new_child(node
, "setting");
109 xmlnode_set_attrib(child
, "name", name
);
111 if (setting
->type
== PURPLE_PREF_INT
) {
112 xmlnode_set_attrib(child
, "type", "int");
113 g_snprintf(buf
, sizeof(buf
), "%d", setting
->value
.integer
);
114 xmlnode_insert_data(child
, buf
, -1);
116 else if (setting
->type
== PURPLE_PREF_STRING
&& setting
->value
.string
!= NULL
) {
117 xmlnode_set_attrib(child
, "type", "string");
118 xmlnode_insert_data(child
, setting
->value
.string
, -1);
120 else if (setting
->type
== PURPLE_PREF_BOOLEAN
) {
121 xmlnode_set_attrib(child
, "type", "bool");
122 g_snprintf(buf
, sizeof(buf
), "%d", setting
->value
.boolean
);
123 xmlnode_insert_data(child
, buf
, -1);
128 ui_setting_to_xmlnode(gpointer key
, gpointer value
, gpointer user_data
)
132 xmlnode
*node
, *child
;
134 ui
= (const char *)key
;
135 table
= (GHashTable
*)value
;
136 node
= (xmlnode
*)user_data
;
138 if (g_hash_table_size(table
) > 0)
140 child
= xmlnode_new_child(node
, "settings");
141 xmlnode_set_attrib(child
, "ui", ui
);
142 g_hash_table_foreach(table
, setting_to_xmlnode
, child
);
147 status_attr_to_xmlnode(const PurpleStatus
*status
, const PurpleStatusType
*type
, const PurpleStatusAttr
*attr
)
152 PurpleStatusAttr
*default_attr
;
153 PurpleValue
*default_value
;
154 PurpleType attr_type
;
155 PurpleValue
*attr_value
;
157 id
= purple_status_attr_get_id(attr
);
158 g_return_val_if_fail(id
, NULL
);
160 attr_value
= purple_status_get_attr_value(status
, id
);
161 g_return_val_if_fail(attr_value
, NULL
);
162 attr_type
= purple_value_get_type(attr_value
);
165 * If attr_value is a different type than it should be
166 * then don't write it to the file.
168 default_attr
= purple_status_type_get_attr(type
, id
);
169 default_value
= purple_status_attr_get_value(default_attr
);
170 if (attr_type
!= purple_value_get_type(default_value
))
174 * If attr_value is the same as the default for this status
175 * then there is no need to write it to the file.
177 if (attr_type
== PURPLE_TYPE_STRING
)
179 const char *string_value
= purple_value_get_string(attr_value
);
180 const char *default_string_value
= purple_value_get_string(default_value
);
181 if (purple_strequal(string_value
, default_string_value
))
183 value
= g_strdup(purple_value_get_string(attr_value
));
185 else if (attr_type
== PURPLE_TYPE_INT
)
187 int int_value
= purple_value_get_int(attr_value
);
188 if (int_value
== purple_value_get_int(default_value
))
190 value
= g_strdup_printf("%d", int_value
);
192 else if (attr_type
== PURPLE_TYPE_BOOLEAN
)
194 gboolean boolean_value
= purple_value_get_boolean(attr_value
);
195 if (boolean_value
== purple_value_get_boolean(default_value
))
197 value
= g_strdup(boolean_value
?
205 g_return_val_if_fail(value
, NULL
);
207 node
= xmlnode_new("attribute");
209 xmlnode_set_attrib(node
, "id", id
);
210 xmlnode_set_attrib(node
, "value", value
);
218 status_attrs_to_xmlnode(const PurpleStatus
*status
)
220 PurpleStatusType
*type
= purple_status_get_type(status
);
221 xmlnode
*node
, *child
;
224 node
= xmlnode_new("attributes");
226 attrs
= purple_status_type_get_attrs(type
);
227 for (attr
= attrs
; attr
!= NULL
; attr
= attr
->next
)
229 child
= status_attr_to_xmlnode(status
, type
, (const PurpleStatusAttr
*)attr
->data
);
231 xmlnode_insert_child(node
, child
);
238 status_to_xmlnode(const PurpleStatus
*status
)
240 xmlnode
*node
, *child
;
242 node
= xmlnode_new("status");
243 xmlnode_set_attrib(node
, "type", purple_status_get_id(status
));
244 if (purple_status_get_name(status
) != NULL
)
245 xmlnode_set_attrib(node
, "name", purple_status_get_name(status
));
246 xmlnode_set_attrib(node
, "active", purple_status_is_active(status
) ? "true" : "false");
248 child
= status_attrs_to_xmlnode(status
);
249 xmlnode_insert_child(node
, child
);
255 statuses_to_xmlnode(const PurplePresence
*presence
)
257 xmlnode
*node
, *child
;
259 PurpleStatus
*status
;
261 node
= xmlnode_new("statuses");
263 statuses
= purple_presence_get_statuses(presence
);
264 for (; statuses
!= NULL
; statuses
= statuses
->next
)
266 status
= statuses
->data
;
267 if (purple_status_type_is_saveable(purple_status_get_type(status
)))
269 child
= status_to_xmlnode(status
);
270 xmlnode_insert_child(node
, child
);
278 proxy_settings_to_xmlnode(PurpleProxyInfo
*proxy_info
)
280 xmlnode
*node
, *child
;
281 PurpleProxyType proxy_type
;
286 proxy_type
= purple_proxy_info_get_type(proxy_info
);
288 node
= xmlnode_new("proxy");
290 child
= xmlnode_new_child(node
, "type");
291 xmlnode_insert_data(child
,
292 (proxy_type
== PURPLE_PROXY_USE_GLOBAL
? "global" :
293 proxy_type
== PURPLE_PROXY_NONE
? "none" :
294 proxy_type
== PURPLE_PROXY_HTTP
? "http" :
295 proxy_type
== PURPLE_PROXY_SOCKS4
? "socks4" :
296 proxy_type
== PURPLE_PROXY_SOCKS5
? "socks5" :
297 proxy_type
== PURPLE_PROXY_TOR
? "tor" :
298 proxy_type
== PURPLE_PROXY_USE_ENVVAR
? "envvar" : "unknown"), -1);
300 if ((value
= purple_proxy_info_get_host(proxy_info
)) != NULL
)
302 child
= xmlnode_new_child(node
, "host");
303 xmlnode_insert_data(child
, value
, -1);
306 if ((int_value
= purple_proxy_info_get_port(proxy_info
)) != 0)
308 g_snprintf(buf
, sizeof(buf
), "%d", int_value
);
309 child
= xmlnode_new_child(node
, "port");
310 xmlnode_insert_data(child
, buf
, -1);
313 if ((value
= purple_proxy_info_get_username(proxy_info
)) != NULL
)
315 child
= xmlnode_new_child(node
, "username");
316 xmlnode_insert_data(child
, value
, -1);
319 if ((value
= purple_proxy_info_get_password(proxy_info
)) != NULL
)
321 child
= xmlnode_new_child(node
, "password");
322 xmlnode_insert_data(child
, value
, -1);
329 current_error_to_xmlnode(PurpleConnectionErrorInfo
*err
)
331 xmlnode
*node
, *child
;
334 node
= xmlnode_new("current_error");
339 /* It doesn't make sense to have transient errors persist across a
342 if(!purple_connection_error_is_fatal (err
->type
))
345 child
= xmlnode_new_child(node
, "type");
346 g_snprintf(type_str
, sizeof(type_str
), "%u", err
->type
);
347 xmlnode_insert_data(child
, type_str
, -1);
349 child
= xmlnode_new_child(node
, "description");
350 if(err
->description
) {
351 char *utf8ized
= purple_utf8_try_convert(err
->description
);
353 utf8ized
= purple_utf8_salvage(err
->description
);
354 xmlnode_insert_data(child
, utf8ized
, -1);
362 account_to_xmlnode(PurpleAccount
*account
)
364 PurpleAccountPrivate
*priv
= PURPLE_ACCOUNT_GET_PRIVATE(account
);
366 xmlnode
*node
, *child
;
368 PurplePresence
*presence
;
369 PurpleProxyInfo
*proxy_info
;
371 node
= xmlnode_new("account");
373 child
= xmlnode_new_child(node
, "protocol");
374 xmlnode_insert_data(child
, purple_account_get_protocol_id(account
), -1);
376 child
= xmlnode_new_child(node
, "name");
377 xmlnode_insert_data(child
, purple_account_get_username(account
), -1);
379 if (purple_account_get_remember_password(account
) &&
380 ((tmp
= purple_account_get_password(account
)) != NULL
))
382 child
= xmlnode_new_child(node
, "password");
383 xmlnode_insert_data(child
, tmp
, -1);
386 if ((tmp
= purple_account_get_alias(account
)) != NULL
)
388 child
= xmlnode_new_child(node
, "alias");
389 xmlnode_insert_data(child
, tmp
, -1);
392 if ((presence
= purple_account_get_presence(account
)) != NULL
)
394 child
= statuses_to_xmlnode(presence
);
395 xmlnode_insert_child(node
, child
);
398 if ((tmp
= purple_account_get_user_info(account
)) != NULL
)
400 /* TODO: Do we need to call purple_str_strip_char(tmp, '\r') here? */
401 child
= xmlnode_new_child(node
, "userinfo");
402 xmlnode_insert_data(child
, tmp
, -1);
405 if (g_hash_table_size(account
->settings
) > 0)
407 child
= xmlnode_new_child(node
, "settings");
408 g_hash_table_foreach(account
->settings
, setting_to_xmlnode
, child
);
411 if (g_hash_table_size(account
->ui_settings
) > 0)
413 g_hash_table_foreach(account
->ui_settings
, ui_setting_to_xmlnode
, node
);
416 if ((proxy_info
= purple_account_get_proxy_info(account
)) != NULL
)
418 child
= proxy_settings_to_xmlnode(proxy_info
);
419 xmlnode_insert_child(node
, child
);
422 child
= current_error_to_xmlnode(priv
->current_error
);
423 xmlnode_insert_child(node
, child
);
429 accounts_to_xmlnode(void)
431 xmlnode
*node
, *child
;
434 node
= xmlnode_new("account");
435 xmlnode_set_attrib(node
, "version", "1.0");
437 for (cur
= purple_accounts_get_all(); cur
!= NULL
; cur
= cur
->next
)
439 child
= account_to_xmlnode(cur
->data
);
440 xmlnode_insert_child(node
, child
);
452 if (!accounts_loaded
)
454 purple_debug_error("account", "Attempted to save accounts before "
455 "they were read!\n");
459 node
= accounts_to_xmlnode();
460 data
= xmlnode_to_formatted_str(node
, NULL
);
461 purple_util_write_data_to_file("accounts.xml", data
, -1);
467 save_cb(gpointer data
)
475 schedule_accounts_save(void)
478 save_timer
= purple_timeout_add_seconds(5, save_cb
, NULL
);
482 /*********************************************************************
483 * Reading from disk *
484 *********************************************************************/
486 migrate_yahoo_japan(PurpleAccount
*account
)
488 /* detect a Yahoo! JAPAN account that existed prior to 2.6.0 and convert it
489 * to use the new prpl-yahoojp. Also remove the account-specific settings
490 * we no longer need */
492 if(purple_strequal(purple_account_get_protocol_id(account
), "prpl-yahoo")) {
493 if(purple_account_get_bool(account
, "yahoojp", FALSE
)) {
494 const char *serverjp
= purple_account_get_string(account
, "serverjp", NULL
);
495 const char *xferjp_host
= purple_account_get_string(account
, "xferjp_host", NULL
);
497 g_return_if_fail(serverjp
!= NULL
);
498 g_return_if_fail(xferjp_host
!= NULL
);
500 purple_account_set_string(account
, "server", serverjp
);
501 purple_account_set_string(account
, "xfer_host", xferjp_host
);
503 purple_account_set_protocol_id(account
, "prpl-yahoojp");
506 /* these should always be nuked */
507 purple_account_remove_setting(account
, "yahoojp");
508 purple_account_remove_setting(account
, "serverjp");
509 purple_account_remove_setting(account
, "xferjp_host");
515 migrate_icq_server(PurpleAccount
*account
)
517 /* Migrate the login server setting for ICQ accounts. See
518 * 'mtn log --last 1 --no-graph --from b6d7712e90b68610df3bd2d8cbaf46d94c8b3794'
519 * for details on the change. */
521 if(purple_strequal(purple_account_get_protocol_id(account
), "prpl-icq")) {
522 const char *tmp
= purple_account_get_string(account
, "server", NULL
);
524 /* Non-secure server */
525 if(purple_strequal(tmp
, "login.messaging.aol.com") ||
526 purple_strequal(tmp
, "login.oscar.aol.com"))
527 purple_account_set_string(account
, "server", "login.icq.com");
530 if(purple_strequal(tmp
, "slogin.oscar.aol.com"))
531 purple_account_set_string(account
, "server", "slogin.icq.com");
536 migrate_xmpp_encryption(PurpleAccount
*account
)
538 /* When this is removed, nuke the "old_ssl" and "require_tls" settings */
539 if (g_str_equal(purple_account_get_protocol_id(account
), "prpl-jabber")) {
540 const char *sec
= purple_account_get_string(account
, "connection_security", "");
542 if (g_str_equal("", sec
)) {
543 const char *val
= "require_tls";
544 if (purple_account_get_bool(account
, "old_ssl", FALSE
))
546 else if (!purple_account_get_bool(account
, "require_tls", TRUE
))
547 val
= "opportunistic_tls";
549 purple_account_set_string(account
, "connection_security", val
);
555 parse_settings(xmlnode
*node
, PurpleAccount
*account
)
560 /* Get the UI string, if these are UI settings */
561 ui
= xmlnode_get_attrib(node
, "ui");
563 /* Read settings, one by one */
564 for (child
= xmlnode_get_child(node
, "setting"); child
!= NULL
;
565 child
= xmlnode_get_next_twin(child
))
567 const char *name
, *str_type
;
571 name
= xmlnode_get_attrib(child
, "name");
573 /* Ignore this setting */
576 str_type
= xmlnode_get_attrib(child
, "type");
577 if (str_type
== NULL
)
578 /* Ignore this setting */
581 if (purple_strequal(str_type
, "string"))
582 type
= PURPLE_PREF_STRING
;
583 else if (purple_strequal(str_type
, "int"))
584 type
= PURPLE_PREF_INT
;
585 else if (purple_strequal(str_type
, "bool"))
586 type
= PURPLE_PREF_BOOLEAN
;
588 /* Ignore this setting */
591 data
= xmlnode_get_data(child
);
593 /* Ignore this setting */
598 if (type
== PURPLE_PREF_STRING
)
599 purple_account_set_string(account
, name
, data
);
600 else if (type
== PURPLE_PREF_INT
)
601 purple_account_set_int(account
, name
, atoi(data
));
602 else if (type
== PURPLE_PREF_BOOLEAN
)
603 purple_account_set_bool(account
, name
,
604 (*data
== '0' ? FALSE
: TRUE
));
606 if (type
== PURPLE_PREF_STRING
)
607 purple_account_set_ui_string(account
, ui
, name
, data
);
608 else if (type
== PURPLE_PREF_INT
)
609 purple_account_set_ui_int(account
, ui
, name
, atoi(data
));
610 else if (type
== PURPLE_PREF_BOOLEAN
)
611 purple_account_set_ui_bool(account
, ui
, name
,
612 (*data
== '0' ? FALSE
: TRUE
));
618 /* we do this here because we need access to account settings to determine
619 * if we can/should migrate an old Yahoo! JAPAN account */
620 migrate_yahoo_japan(account
);
621 /* we do this here because we need access to account settings to determine
622 * if we can/should migrate an ICQ account's server setting */
623 migrate_icq_server(account
);
624 /* we do this here because we need to do it before the user views the
625 * Edit Account dialog. */
626 migrate_xmpp_encryption(account
);
630 parse_status_attrs(xmlnode
*node
, PurpleStatus
*status
)
634 PurpleValue
*attr_value
;
636 for (child
= xmlnode_get_child(node
, "attribute"); child
!= NULL
;
637 child
= xmlnode_get_next_twin(child
))
639 const char *id
= xmlnode_get_attrib(child
, "id");
640 const char *value
= xmlnode_get_attrib(child
, "value");
642 if (!id
|| !*id
|| !value
|| !*value
)
645 attr_value
= purple_status_get_attr_value(status
, id
);
649 list
= g_list_append(list
, (char *)id
);
651 switch (purple_value_get_type(attr_value
))
653 case PURPLE_TYPE_STRING
:
654 list
= g_list_append(list
, (char *)value
);
656 case PURPLE_TYPE_INT
:
657 case PURPLE_TYPE_BOOLEAN
:
660 if (sscanf(value
, "%d", &v
) == 1)
661 list
= g_list_append(list
, GINT_TO_POINTER(v
));
663 list
= g_list_remove(list
, id
);
675 parse_status(xmlnode
*node
, PurpleAccount
*account
)
677 gboolean active
= FALSE
;
683 /* Get the active/inactive state */
684 data
= xmlnode_get_attrib(node
, "active");
687 if (g_ascii_strcasecmp(data
, "true") == 0)
689 else if (g_ascii_strcasecmp(data
, "false") == 0)
694 /* Get the type of the status */
695 type
= xmlnode_get_attrib(node
, "type");
699 /* Read attributes into a GList */
700 child
= xmlnode_get_child(node
, "attributes");
703 attrs
= parse_status_attrs(child
,
704 purple_account_get_status(account
, type
));
707 purple_account_set_status_list(account
, type
, active
, attrs
);
713 parse_statuses(xmlnode
*node
, PurpleAccount
*account
)
717 for (child
= xmlnode_get_child(node
, "status"); child
!= NULL
;
718 child
= xmlnode_get_next_twin(child
))
720 parse_status(child
, account
);
725 parse_proxy_info(xmlnode
*node
, PurpleAccount
*account
)
727 PurpleProxyInfo
*proxy_info
;
731 proxy_info
= purple_proxy_info_new();
733 /* Use the global proxy settings, by default */
734 purple_proxy_info_set_type(proxy_info
, PURPLE_PROXY_USE_GLOBAL
);
736 /* Read proxy type */
737 child
= xmlnode_get_child(node
, "type");
738 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
740 if (purple_strequal(data
, "global"))
741 purple_proxy_info_set_type(proxy_info
, PURPLE_PROXY_USE_GLOBAL
);
742 else if (purple_strequal(data
, "none"))
743 purple_proxy_info_set_type(proxy_info
, PURPLE_PROXY_NONE
);
744 else if (purple_strequal(data
, "http"))
745 purple_proxy_info_set_type(proxy_info
, PURPLE_PROXY_HTTP
);
746 else if (purple_strequal(data
, "socks4"))
747 purple_proxy_info_set_type(proxy_info
, PURPLE_PROXY_SOCKS4
);
748 else if (purple_strequal(data
, "socks5"))
749 purple_proxy_info_set_type(proxy_info
, PURPLE_PROXY_SOCKS5
);
750 else if (purple_strequal(data
, "tor"))
751 purple_proxy_info_set_type(proxy_info
, PURPLE_PROXY_TOR
);
752 else if (purple_strequal(data
, "envvar"))
753 purple_proxy_info_set_type(proxy_info
, PURPLE_PROXY_USE_ENVVAR
);
756 purple_debug_error("account", "Invalid proxy type found when "
757 "loading account information for %s\n",
758 purple_account_get_username(account
));
763 /* Read proxy host */
764 child
= xmlnode_get_child(node
, "host");
765 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
767 purple_proxy_info_set_host(proxy_info
, data
);
771 /* Read proxy port */
772 child
= xmlnode_get_child(node
, "port");
773 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
775 purple_proxy_info_set_port(proxy_info
, atoi(data
));
779 /* Read proxy username */
780 child
= xmlnode_get_child(node
, "username");
781 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
783 purple_proxy_info_set_username(proxy_info
, data
);
787 /* Read proxy password */
788 child
= xmlnode_get_child(node
, "password");
789 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
791 purple_proxy_info_set_password(proxy_info
, data
);
795 /* If there are no values set then proxy_info NULL */
796 if ((purple_proxy_info_get_type(proxy_info
) == PURPLE_PROXY_USE_GLOBAL
) &&
797 (purple_proxy_info_get_host(proxy_info
) == NULL
) &&
798 (purple_proxy_info_get_port(proxy_info
) == 0) &&
799 (purple_proxy_info_get_username(proxy_info
) == NULL
) &&
800 (purple_proxy_info_get_password(proxy_info
) == NULL
))
802 purple_proxy_info_destroy(proxy_info
);
806 purple_account_set_proxy_info(account
, proxy_info
);
810 parse_current_error(xmlnode
*node
, PurpleAccount
*account
)
813 char *type_str
= NULL
, *description
= NULL
;
815 PurpleConnectionErrorInfo
*current_error
= NULL
;
817 child
= xmlnode_get_child(node
, "type");
818 if (child
== NULL
|| (type_str
= xmlnode_get_data(child
)) == NULL
)
820 type
= atoi(type_str
);
823 if (type
> PURPLE_CONNECTION_ERROR_OTHER_ERROR
)
825 purple_debug_error("account",
826 "Invalid PurpleConnectionError value %d found when "
827 "loading account information for %s\n",
828 type
, purple_account_get_username(account
));
829 type
= PURPLE_CONNECTION_ERROR_OTHER_ERROR
;
832 child
= xmlnode_get_child(node
, "description");
834 description
= xmlnode_get_data(child
);
835 if (description
== NULL
)
836 description
= g_strdup("");
838 current_error
= g_new0(PurpleConnectionErrorInfo
, 1);
839 PURPLE_DBUS_REGISTER_POINTER(current_error
, PurpleConnectionErrorInfo
);
840 current_error
->type
= type
;
841 current_error
->description
= description
;
843 set_current_error(account
, current_error
);
846 static PurpleAccount
*
847 parse_account(xmlnode
*node
)
851 char *protocol_id
= NULL
;
855 child
= xmlnode_get_child(node
, "protocol");
857 protocol_id
= xmlnode_get_data(child
);
859 child
= xmlnode_get_child(node
, "name");
861 name
= xmlnode_get_data(child
);
864 /* Do we really need to do this? */
865 child
= xmlnode_get_child(node
, "username");
867 name
= xmlnode_get_data(child
);
870 if ((protocol_id
== NULL
) || (name
== NULL
))
877 ret
= purple_account_new(name
, _purple_oscar_convert(name
, protocol_id
)); /* XXX: */
881 /* Read the password */
882 child
= xmlnode_get_child(node
, "password");
883 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
885 purple_account_set_remember_password(ret
, TRUE
);
886 purple_account_set_password(ret
, data
);
891 child
= xmlnode_get_child(node
, "alias");
892 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
895 purple_account_set_alias(ret
, data
);
899 /* Read the statuses */
900 child
= xmlnode_get_child(node
, "statuses");
903 parse_statuses(child
, ret
);
906 /* Read the userinfo */
907 child
= xmlnode_get_child(node
, "userinfo");
908 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
910 purple_account_set_user_info(ret
, data
);
914 /* Read an old buddyicon */
915 child
= xmlnode_get_child(node
, "buddyicon");
916 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
918 const char *dirname
= purple_buddy_icons_get_cache_dir();
919 char *filename
= g_build_filename(dirname
, data
, NULL
);
923 if (g_file_get_contents(filename
, &contents
, &len
, NULL
))
925 purple_buddy_icons_set_account_icon(ret
, (guchar
*)contents
, len
);
929 /* Try to see if the icon got left behind in the old cache. */
931 filename
= g_build_filename(g_get_home_dir(), ".gaim", "icons", data
, NULL
);
932 if (g_file_get_contents(filename
, &contents
, &len
, NULL
)) {
933 purple_buddy_icons_set_account_icon(ret
, (guchar
*)contents
, len
);
941 /* Read settings (both core and UI) */
942 for (child
= xmlnode_get_child(node
, "settings"); child
!= NULL
;
943 child
= xmlnode_get_next_twin(child
))
945 parse_settings(child
, ret
);
949 child
= xmlnode_get_child(node
, "proxy");
952 parse_proxy_info(child
, ret
);
955 /* Read current error */
956 child
= xmlnode_get_child(node
, "current_error");
959 parse_current_error(child
, ret
);
968 xmlnode
*node
, *child
;
970 accounts_loaded
= TRUE
;
972 node
= purple_util_read_xml_from_file("accounts.xml", _("accounts"));
977 for (child
= xmlnode_get_child(node
, "account"); child
!= NULL
;
978 child
= xmlnode_get_next_twin(child
))
980 PurpleAccount
*new_acct
;
981 new_acct
= parse_account(child
);
982 purple_accounts_add(new_acct
);
987 _purple_buddy_icons_account_loaded_cb();
992 delete_setting(void *data
)
994 PurpleAccountSetting
*setting
= (PurpleAccountSetting
*)data
;
998 if (setting
->type
== PURPLE_PREF_STRING
)
999 g_free(setting
->value
.string
);
1005 purple_account_new(const char *username
, const char *protocol_id
)
1007 PurpleAccount
*account
= NULL
;
1008 PurpleAccountPrivate
*priv
= NULL
;
1009 PurplePlugin
*prpl
= NULL
;
1010 PurplePluginProtocolInfo
*prpl_info
= NULL
;
1011 PurpleStatusType
*status_type
;
1013 g_return_val_if_fail(username
!= NULL
, NULL
);
1014 g_return_val_if_fail(protocol_id
!= NULL
, NULL
);
1016 account
= purple_accounts_find(username
, protocol_id
);
1018 if (account
!= NULL
)
1021 account
= g_new0(PurpleAccount
, 1);
1022 PURPLE_DBUS_REGISTER_POINTER(account
, PurpleAccount
);
1023 priv
= g_new0(PurpleAccountPrivate
, 1);
1024 account
->priv
= priv
;
1026 purple_account_set_username(account
, username
);
1028 purple_account_set_protocol_id(account
, protocol_id
);
1030 account
->settings
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
1031 g_free
, delete_setting
);
1032 account
->ui_settings
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
1033 g_free
, (GDestroyNotify
)g_hash_table_destroy
);
1034 account
->system_log
= NULL
;
1035 /* 0 is not a valid privacy setting */
1036 account
->perm_deny
= PURPLE_PRIVACY_ALLOW_ALL
;
1038 purple_signal_emit(purple_accounts_get_handle(), "account-created", account
);
1040 prpl
= purple_find_prpl(protocol_id
);
1045 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
1046 if (prpl_info
!= NULL
&& prpl_info
->status_types
!= NULL
)
1047 purple_account_set_status_types(account
, prpl_info
->status_types(account
));
1049 account
->presence
= purple_presence_new_for_account(account
);
1051 status_type
= purple_account_get_status_type_with_primitive(account
, PURPLE_STATUS_AVAILABLE
);
1052 if (status_type
!= NULL
)
1053 purple_presence_set_status_active(account
->presence
,
1054 purple_status_type_get_id(status_type
),
1057 purple_presence_set_status_active(account
->presence
,
1065 purple_account_destroy(PurpleAccount
*account
)
1067 PurpleAccountPrivate
*priv
= NULL
;
1070 g_return_if_fail(account
!= NULL
);
1072 purple_debug_info("account", "Destroying account %p\n", account
);
1073 purple_signal_emit(purple_accounts_get_handle(), "account-destroying", account
);
1075 for (l
= purple_get_conversations(); l
!= NULL
; l
= l
->next
)
1077 PurpleConversation
*conv
= (PurpleConversation
*)l
->data
;
1079 if (purple_conversation_get_account(conv
) == account
)
1080 purple_conversation_set_account(conv
, NULL
);
1083 g_free(account
->username
);
1084 g_free(account
->alias
);
1085 g_free(account
->password
);
1086 g_free(account
->user_info
);
1087 g_free(account
->buddy_icon_path
);
1088 g_free(account
->protocol_id
);
1090 g_hash_table_destroy(account
->settings
);
1091 g_hash_table_destroy(account
->ui_settings
);
1093 if (account
->proxy_info
)
1094 purple_proxy_info_destroy(account
->proxy_info
);
1096 purple_account_set_status_types(account
, NULL
);
1098 purple_presence_destroy(account
->presence
);
1100 if(account
->system_log
)
1101 purple_log_free(account
->system_log
);
1103 while (account
->deny
) {
1104 g_free(account
->deny
->data
);
1105 account
->deny
= g_slist_delete_link(account
->deny
, account
->deny
);
1108 while (account
->permit
) {
1109 g_free(account
->permit
->data
);
1110 account
->permit
= g_slist_delete_link(account
->permit
, account
->permit
);
1113 priv
= PURPLE_ACCOUNT_GET_PRIVATE(account
);
1114 PURPLE_DBUS_UNREGISTER_POINTER(priv
->current_error
);
1115 if (priv
->current_error
) {
1116 g_free(priv
->current_error
->description
);
1117 g_free(priv
->current_error
);
1121 PURPLE_DBUS_UNREGISTER_POINTER(account
);
1126 purple_account_set_register_callback(PurpleAccount
*account
, PurpleAccountRegistrationCb cb
, void *user_data
)
1128 g_return_if_fail(account
!= NULL
);
1130 account
->registration_cb
= cb
;
1131 account
->registration_cb_user_data
= user_data
;
1135 purple_account_register(PurpleAccount
*account
)
1137 g_return_if_fail(account
!= NULL
);
1139 purple_debug_info("account", "Registering account %s\n",
1140 purple_account_get_username(account
));
1142 _purple_connection_new(account
, TRUE
, purple_account_get_password(account
));
1146 purple_account_unregister(PurpleAccount
*account
, PurpleAccountUnregistrationCb cb
, void *user_data
)
1148 g_return_if_fail(account
!= NULL
);
1150 purple_debug_info("account", "Unregistering account %s\n",
1151 purple_account_get_username(account
));
1153 _purple_connection_new_unregister(account
, purple_account_get_password(account
), cb
, user_data
);
1157 request_password_ok_cb(PurpleAccount
*account
, PurpleRequestFields
*fields
)
1162 entry
= purple_request_fields_get_string(fields
, "password");
1163 remember
= purple_request_fields_get_bool(fields
, "remember");
1165 if (!entry
|| !*entry
)
1167 purple_notify_error(account
, NULL
, _("Password is required to sign on."), NULL
);
1172 purple_account_set_remember_password(account
, TRUE
);
1174 purple_account_set_password(account
, entry
);
1176 _purple_connection_new(account
, FALSE
, entry
);
1180 request_password_cancel_cb(PurpleAccount
*account
, PurpleRequestFields
*fields
)
1182 /* Disable the account as the user has cancelled connecting */
1183 purple_account_set_enabled(account
, purple_core_get_ui(), FALSE
);
1188 purple_account_request_password(PurpleAccount
*account
, GCallback ok_cb
,
1189 GCallback cancel_cb
, void *user_data
)
1192 const gchar
*username
;
1193 PurpleRequestFieldGroup
*group
;
1194 PurpleRequestField
*field
;
1195 PurpleRequestFields
*fields
;
1197 /* Close any previous password request windows */
1198 purple_request_close_with_handle(account
);
1200 username
= purple_account_get_username(account
);
1201 primary
= g_strdup_printf(_("Enter password for %s (%s)"), username
,
1202 purple_account_get_protocol_name(account
));
1204 fields
= purple_request_fields_new();
1205 group
= purple_request_field_group_new(NULL
);
1206 purple_request_fields_add_group(fields
, group
);
1208 field
= purple_request_field_string_new("password", _("Enter Password"), NULL
, FALSE
);
1209 purple_request_field_string_set_masked(field
, TRUE
);
1210 purple_request_field_set_required(field
, TRUE
);
1211 purple_request_field_group_add_field(group
, field
);
1213 field
= purple_request_field_bool_new("remember", _("Save password"), FALSE
);
1214 purple_request_field_group_add_field(group
, field
);
1216 purple_request_fields(account
,
1222 _("Cancel"), cancel_cb
,
1223 account
, NULL
, NULL
,
1229 purple_account_connect(PurpleAccount
*account
)
1232 const char *password
, *username
;
1233 PurplePluginProtocolInfo
*prpl_info
;
1235 g_return_if_fail(account
!= NULL
);
1237 username
= purple_account_get_username(account
);
1239 if (!purple_account_get_enabled(account
, purple_core_get_ui())) {
1240 purple_debug_info("account",
1241 "Account %s not enabled, not connecting.\n",
1246 prpl
= purple_find_prpl(purple_account_get_protocol_id(account
));
1250 message
= g_strdup_printf(_("Missing protocol plugin for %s"), username
);
1251 purple_notify_error(account
, _("Connection Error"), message
, NULL
);
1256 purple_debug_info("account", "Connecting to account %s.\n", username
);
1258 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
1259 password
= purple_account_get_password(account
);
1260 if ((password
== NULL
) &&
1261 !(prpl_info
->options
& OPT_PROTO_NO_PASSWORD
) &&
1262 !(prpl_info
->options
& OPT_PROTO_PASSWORD_OPTIONAL
))
1263 purple_account_request_password(account
, G_CALLBACK(request_password_ok_cb
), G_CALLBACK(request_password_cancel_cb
), account
);
1265 _purple_connection_new(account
, FALSE
, password
);
1269 purple_account_disconnect(PurpleAccount
*account
)
1271 PurpleConnection
*gc
;
1272 const char *username
;
1274 g_return_if_fail(account
!= NULL
);
1275 g_return_if_fail(!purple_account_is_disconnected(account
));
1277 username
= purple_account_get_username(account
);
1278 purple_debug_info("account", "Disconnecting account %s (%p)\n",
1279 username
? username
: "(null)", account
);
1281 account
->disconnecting
= TRUE
;
1283 gc
= purple_account_get_connection(account
);
1284 _purple_connection_destroy(gc
);
1285 if (!purple_account_get_remember_password(account
))
1286 purple_account_set_password(account
, NULL
);
1287 purple_account_set_connection(account
, NULL
);
1289 account
->disconnecting
= FALSE
;
1293 purple_account_notify_added(PurpleAccount
*account
, const char *remote_user
,
1294 const char *id
, const char *alias
,
1295 const char *message
)
1297 PurpleAccountUiOps
*ui_ops
;
1299 g_return_if_fail(account
!= NULL
);
1300 g_return_if_fail(remote_user
!= NULL
);
1302 ui_ops
= purple_accounts_get_ui_ops();
1304 if (ui_ops
!= NULL
&& ui_ops
->notify_added
!= NULL
)
1305 ui_ops
->notify_added(account
, remote_user
, id
, alias
, message
);
1309 purple_account_request_add(PurpleAccount
*account
, const char *remote_user
,
1310 const char *id
, const char *alias
,
1311 const char *message
)
1313 PurpleAccountUiOps
*ui_ops
;
1315 g_return_if_fail(account
!= NULL
);
1316 g_return_if_fail(remote_user
!= NULL
);
1318 ui_ops
= purple_accounts_get_ui_ops();
1320 if (ui_ops
!= NULL
&& ui_ops
->request_add
!= NULL
)
1321 ui_ops
->request_add(account
, remote_user
, id
, alias
, message
);
1324 static PurpleAccountRequestInfo
*
1325 purple_account_request_info_unref(PurpleAccountRequestInfo
*info
)
1330 /* TODO: This will leak info->user_data, but there is no callback to just clean that up */
1337 purple_account_request_close_info(PurpleAccountRequestInfo
*info
)
1339 PurpleAccountUiOps
*ops
;
1341 ops
= purple_accounts_get_ui_ops();
1343 if (ops
!= NULL
&& ops
->close_account_request
!= NULL
)
1344 ops
->close_account_request(info
->ui_handle
);
1346 purple_account_request_info_unref(info
);
1350 purple_account_request_close_with_account(PurpleAccount
*account
)
1354 g_return_if_fail(account
!= NULL
);
1356 for (l
= handles
; l
!= NULL
; l
= l_next
) {
1357 PurpleAccountRequestInfo
*info
= l
->data
;
1361 if (info
->account
== account
) {
1362 handles
= g_list_remove(handles
, info
);
1363 purple_account_request_close_info(info
);
1369 purple_account_request_close(void *ui_handle
)
1373 g_return_if_fail(ui_handle
!= NULL
);
1375 for (l
= handles
; l
!= NULL
; l
= l_next
) {
1376 PurpleAccountRequestInfo
*info
= l
->data
;
1380 if (info
->ui_handle
== ui_handle
) {
1381 handles
= g_list_remove(handles
, info
);
1382 purple_account_request_close_info(info
);
1388 request_auth_cb(void *data
)
1390 PurpleAccountRequestInfo
*info
= data
;
1392 handles
= g_list_remove(handles
, info
);
1394 if (info
->auth_cb
!= NULL
)
1395 info
->auth_cb(info
->userdata
);
1397 purple_signal_emit(purple_accounts_get_handle(),
1398 "account-authorization-granted", info
->account
, info
->user
);
1400 purple_account_request_info_unref(info
);
1404 request_deny_cb(void *data
)
1406 PurpleAccountRequestInfo
*info
= data
;
1408 handles
= g_list_remove(handles
, info
);
1410 if (info
->deny_cb
!= NULL
)
1411 info
->deny_cb(info
->userdata
);
1413 purple_signal_emit(purple_accounts_get_handle(),
1414 "account-authorization-denied", info
->account
, info
->user
);
1416 purple_account_request_info_unref(info
);
1420 purple_account_request_authorization(PurpleAccount
*account
, const char *remote_user
,
1421 const char *id
, const char *alias
, const char *message
, gboolean on_list
,
1422 PurpleAccountRequestAuthorizationCb auth_cb
, PurpleAccountRequestAuthorizationCb deny_cb
, void *user_data
)
1424 PurpleAccountUiOps
*ui_ops
;
1425 PurpleAccountRequestInfo
*info
;
1428 g_return_val_if_fail(account
!= NULL
, NULL
);
1429 g_return_val_if_fail(remote_user
!= NULL
, NULL
);
1431 ui_ops
= purple_accounts_get_ui_ops();
1433 plugin_return
= GPOINTER_TO_INT(
1434 purple_signal_emit_return_1(purple_accounts_get_handle(),
1435 "account-authorization-requested", account
, remote_user
));
1437 if (plugin_return
> 0) {
1438 if (auth_cb
!= NULL
)
1441 } else if (plugin_return
< 0) {
1442 if (deny_cb
!= NULL
)
1447 plugin_return
= GPOINTER_TO_INT(
1448 purple_signal_emit_return_1(
1449 purple_accounts_get_handle(),
1450 "account-authorization-requested-with-message",
1451 account
, remote_user
, message
1454 switch (plugin_return
)
1456 case PURPLE_ACCOUNT_RESPONSE_IGNORE
:
1458 case PURPLE_ACCOUNT_RESPONSE_ACCEPT
:
1459 if (auth_cb
!= NULL
)
1462 case PURPLE_ACCOUNT_RESPONSE_DENY
:
1463 if (deny_cb
!= NULL
)
1468 if (ui_ops
!= NULL
&& ui_ops
->request_authorize
!= NULL
) {
1469 info
= g_new0(PurpleAccountRequestInfo
, 1);
1470 info
->type
= PURPLE_ACCOUNT_REQUEST_AUTHORIZATION
;
1471 info
->account
= account
;
1472 info
->auth_cb
= auth_cb
;
1473 info
->deny_cb
= deny_cb
;
1474 info
->userdata
= user_data
;
1475 info
->user
= g_strdup(remote_user
);
1476 info
->ref
= 2; /* We hold an extra ref to make sure info remains valid
1477 if any of the callbacks are called synchronously. We
1478 unref it after the function call */
1480 info
->ui_handle
= ui_ops
->request_authorize(account
, remote_user
, id
, alias
, message
,
1481 on_list
, request_auth_cb
, request_deny_cb
, info
);
1483 info
= purple_account_request_info_unref(info
);
1485 handles
= g_list_append(handles
, info
);
1486 return info
->ui_handle
;
1494 change_password_cb(PurpleAccount
*account
, PurpleRequestFields
*fields
)
1496 const char *orig_pass
, *new_pass_1
, *new_pass_2
;
1498 orig_pass
= purple_request_fields_get_string(fields
, "password");
1499 new_pass_1
= purple_request_fields_get_string(fields
, "new_password_1");
1500 new_pass_2
= purple_request_fields_get_string(fields
, "new_password_2");
1502 if (g_utf8_collate(new_pass_1
, new_pass_2
))
1504 purple_notify_error(account
, NULL
,
1505 _("New passwords do not match."), NULL
);
1510 if ((purple_request_fields_is_field_required(fields
, "password") &&
1511 (orig_pass
== NULL
|| *orig_pass
== '\0')) ||
1512 (purple_request_fields_is_field_required(fields
, "new_password_1") &&
1513 (new_pass_1
== NULL
|| *new_pass_1
== '\0')) ||
1514 (purple_request_fields_is_field_required(fields
, "new_password_2") &&
1515 (new_pass_2
== NULL
|| *new_pass_2
== '\0')))
1517 purple_notify_error(account
, NULL
,
1518 _("Fill out all fields completely."), NULL
);
1522 purple_account_change_password(account
, orig_pass
, new_pass_1
);
1526 purple_account_request_change_password(PurpleAccount
*account
)
1528 PurpleRequestFields
*fields
;
1529 PurpleRequestFieldGroup
*group
;
1530 PurpleRequestField
*field
;
1531 PurpleConnection
*gc
;
1532 PurplePlugin
*prpl
= NULL
;
1533 PurplePluginProtocolInfo
*prpl_info
= NULL
;
1536 g_return_if_fail(account
!= NULL
);
1537 g_return_if_fail(purple_account_is_connected(account
));
1539 gc
= purple_account_get_connection(account
);
1541 prpl
= purple_connection_get_prpl(gc
);
1543 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
1545 fields
= purple_request_fields_new();
1547 group
= purple_request_field_group_new(NULL
);
1548 purple_request_fields_add_group(fields
, group
);
1550 field
= purple_request_field_string_new("password", _("Original password"),
1552 purple_request_field_string_set_masked(field
, TRUE
);
1553 if (!(prpl_info
&& (prpl_info
->options
| OPT_PROTO_PASSWORD_OPTIONAL
)))
1554 purple_request_field_set_required(field
, TRUE
);
1555 purple_request_field_group_add_field(group
, field
);
1557 field
= purple_request_field_string_new("new_password_1",
1560 purple_request_field_string_set_masked(field
, TRUE
);
1561 if (!(prpl_info
&& (prpl_info
->options
| OPT_PROTO_PASSWORD_OPTIONAL
)))
1562 purple_request_field_set_required(field
, TRUE
);
1563 purple_request_field_group_add_field(group
, field
);
1565 field
= purple_request_field_string_new("new_password_2",
1566 _("New password (again)"),
1568 purple_request_field_string_set_masked(field
, TRUE
);
1569 if (!(prpl_info
&& (prpl_info
->options
| OPT_PROTO_PASSWORD_OPTIONAL
)))
1570 purple_request_field_set_required(field
, TRUE
);
1571 purple_request_field_group_add_field(group
, field
);
1573 g_snprintf(primary
, sizeof(primary
), _("Change password for %s"),
1574 purple_account_get_username(account
));
1576 /* I'm sticking this somewhere in the code: bologna */
1578 purple_request_fields(purple_account_get_connection(account
),
1581 _("Please enter your current password and your "
1584 _("OK"), G_CALLBACK(change_password_cb
),
1586 account
, NULL
, NULL
,
1591 set_user_info_cb(PurpleAccount
*account
, const char *user_info
)
1593 PurpleConnection
*gc
;
1595 purple_account_set_user_info(account
, user_info
);
1596 gc
= purple_account_get_connection(account
);
1597 serv_set_info(gc
, user_info
);
1601 purple_account_request_change_user_info(PurpleAccount
*account
)
1603 PurpleConnection
*gc
;
1606 g_return_if_fail(account
!= NULL
);
1607 g_return_if_fail(purple_account_is_connected(account
));
1609 gc
= purple_account_get_connection(account
);
1611 g_snprintf(primary
, sizeof(primary
),
1612 _("Change user information for %s"),
1613 purple_account_get_username(account
));
1615 purple_request_input(gc
, _("Set User Info"), primary
, NULL
,
1616 purple_account_get_user_info(account
),
1617 TRUE
, FALSE
, ((gc
!= NULL
) &&
1618 (gc
->flags
& PURPLE_CONNECTION_HTML
) ? "html" : NULL
),
1619 _("Save"), G_CALLBACK(set_user_info_cb
),
1621 account
, NULL
, NULL
,
1626 purple_account_set_username(PurpleAccount
*account
, const char *username
)
1628 PurpleBlistUiOps
*blist_ops
;
1630 g_return_if_fail(account
!= NULL
);
1632 g_free(account
->username
);
1633 account
->username
= g_strdup(username
);
1635 schedule_accounts_save();
1637 /* if the name changes, we should re-write the buddy list
1638 * to disk with the new name */
1639 blist_ops
= purple_blist_get_ui_ops();
1640 if (blist_ops
!= NULL
&& blist_ops
->save_account
!= NULL
)
1641 blist_ops
->save_account(account
);
1645 purple_account_set_password(PurpleAccount
*account
, const char *password
)
1647 g_return_if_fail(account
!= NULL
);
1649 g_free(account
->password
);
1650 account
->password
= g_strdup(password
);
1652 schedule_accounts_save();
1656 purple_account_set_alias(PurpleAccount
*account
, const char *alias
)
1658 g_return_if_fail(account
!= NULL
);
1661 * Do nothing if alias and account->alias are both NULL. Or if
1662 * they're the exact same string.
1664 if (alias
== account
->alias
)
1667 if ((!alias
&& account
->alias
) || (alias
&& !account
->alias
) ||
1668 g_utf8_collate(account
->alias
, alias
))
1670 char *old
= account
->alias
;
1672 account
->alias
= g_strdup(alias
);
1673 purple_signal_emit(purple_accounts_get_handle(), "account-alias-changed",
1677 schedule_accounts_save();
1682 purple_account_set_user_info(PurpleAccount
*account
, const char *user_info
)
1684 g_return_if_fail(account
!= NULL
);
1686 g_free(account
->user_info
);
1687 account
->user_info
= g_strdup(user_info
);
1689 schedule_accounts_save();
1692 void purple_account_set_buddy_icon_path(PurpleAccount
*account
, const char *path
)
1694 g_return_if_fail(account
!= NULL
);
1696 g_free(account
->buddy_icon_path
);
1697 account
->buddy_icon_path
= g_strdup(path
);
1699 schedule_accounts_save();
1703 purple_account_set_protocol_id(PurpleAccount
*account
, const char *protocol_id
)
1705 g_return_if_fail(account
!= NULL
);
1706 g_return_if_fail(protocol_id
!= NULL
);
1708 g_free(account
->protocol_id
);
1709 account
->protocol_id
= g_strdup(protocol_id
);
1711 schedule_accounts_save();
1715 purple_account_set_connection(PurpleAccount
*account
, PurpleConnection
*gc
)
1717 g_return_if_fail(account
!= NULL
);
1723 purple_account_set_remember_password(PurpleAccount
*account
, gboolean value
)
1725 g_return_if_fail(account
!= NULL
);
1727 account
->remember_pass
= value
;
1729 schedule_accounts_save();
1733 purple_account_set_check_mail(PurpleAccount
*account
, gboolean value
)
1735 g_return_if_fail(account
!= NULL
);
1737 purple_account_set_bool(account
, "check-mail", value
);
1741 purple_account_set_enabled(PurpleAccount
*account
, const char *ui
,
1744 PurpleConnection
*gc
;
1745 gboolean was_enabled
= FALSE
;
1747 g_return_if_fail(account
!= NULL
);
1748 g_return_if_fail(ui
!= NULL
);
1750 was_enabled
= purple_account_get_enabled(account
, ui
);
1752 purple_account_set_ui_bool(account
, ui
, "auto-login", value
);
1753 gc
= purple_account_get_connection(account
);
1755 if(was_enabled
&& !value
)
1756 purple_signal_emit(purple_accounts_get_handle(), "account-disabled", account
);
1757 else if(!was_enabled
&& value
)
1758 purple_signal_emit(purple_accounts_get_handle(), "account-enabled", account
);
1760 if ((gc
!= NULL
) && (gc
->wants_to_die
== TRUE
))
1763 if (value
&& purple_presence_is_online(account
->presence
))
1764 purple_account_connect(account
);
1765 else if (!value
&& !purple_account_is_disconnected(account
))
1766 purple_account_disconnect(account
);
1770 purple_account_set_proxy_info(PurpleAccount
*account
, PurpleProxyInfo
*info
)
1772 g_return_if_fail(account
!= NULL
);
1774 if (account
->proxy_info
!= NULL
)
1775 purple_proxy_info_destroy(account
->proxy_info
);
1777 account
->proxy_info
= info
;
1779 schedule_accounts_save();
1783 purple_account_set_privacy_type(PurpleAccount
*account
, PurplePrivacyType privacy_type
)
1785 g_return_if_fail(account
!= NULL
);
1787 account
->perm_deny
= privacy_type
;
1791 purple_account_set_status_types(PurpleAccount
*account
, GList
*status_types
)
1793 g_return_if_fail(account
!= NULL
);
1795 /* Out with the old... */
1796 if (account
->status_types
!= NULL
)
1798 g_list_foreach(account
->status_types
, (GFunc
)purple_status_type_destroy
, NULL
);
1799 g_list_free(account
->status_types
);
1802 /* In with the new... */
1803 account
->status_types
= status_types
;
1807 purple_account_set_status(PurpleAccount
*account
, const char *status_id
,
1808 gboolean active
, ...)
1810 GList
*attrs
= NULL
;
1815 va_start(args
, active
);
1816 while ((id
= va_arg(args
, const char *)) != NULL
)
1818 attrs
= g_list_append(attrs
, (char *)id
);
1819 data
= va_arg(args
, void *);
1820 attrs
= g_list_append(attrs
, data
);
1822 purple_account_set_status_list(account
, status_id
, active
, attrs
);
1828 purple_account_set_status_list(PurpleAccount
*account
, const char *status_id
,
1829 gboolean active
, GList
*attrs
)
1831 PurpleStatus
*status
;
1833 g_return_if_fail(account
!= NULL
);
1834 g_return_if_fail(status_id
!= NULL
);
1836 status
= purple_account_get_status(account
, status_id
);
1839 purple_debug_error("account",
1840 "Invalid status ID '%s' for account %s (%s)\n",
1841 status_id
, purple_account_get_username(account
),
1842 purple_account_get_protocol_id(account
));
1846 if (active
|| purple_status_is_independent(status
))
1847 purple_status_set_active_with_attrs_list(status
, active
, attrs
);
1850 * Our current statuses are saved to accounts.xml (so that when we
1851 * reconnect, we go back to the previous status).
1853 schedule_accounts_save();
1856 struct public_alias_closure
1858 PurpleAccount
*account
;
1859 gpointer failure_cb
;
1863 set_public_alias_unsupported(gpointer data
)
1865 struct public_alias_closure
*closure
= data
;
1866 PurpleSetPublicAliasFailureCallback failure_cb
= closure
->failure_cb
;
1868 failure_cb(closure
->account
,
1869 _("This protocol does not support setting a public alias."));
1876 purple_account_set_public_alias(PurpleAccount
*account
,
1877 const char *alias
, PurpleSetPublicAliasSuccessCallback success_cb
,
1878 PurpleSetPublicAliasFailureCallback failure_cb
)
1880 PurpleConnection
*gc
;
1881 PurplePlugin
*prpl
= NULL
;
1882 PurplePluginProtocolInfo
*prpl_info
= NULL
;
1884 g_return_if_fail(account
!= NULL
);
1885 g_return_if_fail(purple_account_is_connected(account
));
1887 gc
= purple_account_get_connection(account
);
1888 prpl
= purple_connection_get_prpl(gc
);
1889 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
1891 if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, set_public_alias
))
1892 prpl_info
->set_public_alias(gc
, alias
, success_cb
, failure_cb
);
1893 else if (failure_cb
) {
1894 struct public_alias_closure
*closure
=
1895 g_new0(struct public_alias_closure
, 1);
1896 closure
->account
= account
;
1897 closure
->failure_cb
= failure_cb
;
1898 purple_timeout_add(0, set_public_alias_unsupported
, closure
);
1903 get_public_alias_unsupported(gpointer data
)
1905 struct public_alias_closure
*closure
= data
;
1906 PurpleGetPublicAliasFailureCallback failure_cb
= closure
->failure_cb
;
1908 failure_cb(closure
->account
,
1909 _("This protocol does not support fetching the public alias."));
1916 purple_account_get_public_alias(PurpleAccount
*account
,
1917 PurpleGetPublicAliasSuccessCallback success_cb
,
1918 PurpleGetPublicAliasFailureCallback failure_cb
)
1920 PurpleConnection
*gc
;
1921 PurplePlugin
*prpl
= NULL
;
1922 PurplePluginProtocolInfo
*prpl_info
= NULL
;
1924 g_return_if_fail(account
!= NULL
);
1925 g_return_if_fail(purple_account_is_connected(account
));
1927 gc
= purple_account_get_connection(account
);
1928 prpl
= purple_connection_get_prpl(gc
);
1929 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
1931 if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, get_public_alias
))
1932 prpl_info
->get_public_alias(gc
, success_cb
, failure_cb
);
1933 else if (failure_cb
) {
1934 struct public_alias_closure
*closure
=
1935 g_new0(struct public_alias_closure
, 1);
1936 closure
->account
= account
;
1937 closure
->failure_cb
= failure_cb
;
1938 purple_timeout_add(0, get_public_alias_unsupported
, closure
);
1943 purple_account_get_silence_suppression(const PurpleAccount
*account
)
1945 return purple_account_get_bool(account
, "silence-suppression", FALSE
);
1949 purple_account_set_silence_suppression(PurpleAccount
*account
, gboolean value
)
1951 g_return_if_fail(account
!= NULL
);
1953 purple_account_set_bool(account
, "silence-suppression", value
);
1957 purple_account_clear_settings(PurpleAccount
*account
)
1959 g_return_if_fail(account
!= NULL
);
1961 g_hash_table_destroy(account
->settings
);
1963 account
->settings
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
1964 g_free
, delete_setting
);
1968 purple_account_remove_setting(PurpleAccount
*account
, const char *setting
)
1970 g_return_if_fail(account
!= NULL
);
1971 g_return_if_fail(setting
!= NULL
);
1973 g_hash_table_remove(account
->settings
, setting
);
1977 purple_account_set_int(PurpleAccount
*account
, const char *name
, int value
)
1979 PurpleAccountSetting
*setting
;
1981 g_return_if_fail(account
!= NULL
);
1982 g_return_if_fail(name
!= NULL
);
1984 setting
= g_new0(PurpleAccountSetting
, 1);
1986 setting
->type
= PURPLE_PREF_INT
;
1987 setting
->value
.integer
= value
;
1989 g_hash_table_insert(account
->settings
, g_strdup(name
), setting
);
1991 schedule_accounts_save();
1995 purple_account_set_string(PurpleAccount
*account
, const char *name
,
1998 PurpleAccountSetting
*setting
;
2000 g_return_if_fail(account
!= NULL
);
2001 g_return_if_fail(name
!= NULL
);
2003 setting
= g_new0(PurpleAccountSetting
, 1);
2005 setting
->type
= PURPLE_PREF_STRING
;
2006 setting
->value
.string
= g_strdup(value
);
2008 g_hash_table_insert(account
->settings
, g_strdup(name
), setting
);
2010 schedule_accounts_save();
2014 purple_account_set_bool(PurpleAccount
*account
, const char *name
, gboolean value
)
2016 PurpleAccountSetting
*setting
;
2018 g_return_if_fail(account
!= NULL
);
2019 g_return_if_fail(name
!= NULL
);
2021 setting
= g_new0(PurpleAccountSetting
, 1);
2023 setting
->type
= PURPLE_PREF_BOOLEAN
;
2024 setting
->value
.boolean
= value
;
2026 g_hash_table_insert(account
->settings
, g_strdup(name
), setting
);
2028 schedule_accounts_save();
2032 get_ui_settings_table(PurpleAccount
*account
, const char *ui
)
2036 table
= g_hash_table_lookup(account
->ui_settings
, ui
);
2038 if (table
== NULL
) {
2039 table
= g_hash_table_new_full(g_str_hash
, g_str_equal
, g_free
,
2041 g_hash_table_insert(account
->ui_settings
, g_strdup(ui
), table
);
2048 purple_account_set_ui_int(PurpleAccount
*account
, const char *ui
,
2049 const char *name
, int value
)
2051 PurpleAccountSetting
*setting
;
2054 g_return_if_fail(account
!= NULL
);
2055 g_return_if_fail(ui
!= NULL
);
2056 g_return_if_fail(name
!= NULL
);
2058 setting
= g_new0(PurpleAccountSetting
, 1);
2060 setting
->type
= PURPLE_PREF_INT
;
2061 setting
->ui
= g_strdup(ui
);
2062 setting
->value
.integer
= value
;
2064 table
= get_ui_settings_table(account
, ui
);
2066 g_hash_table_insert(table
, g_strdup(name
), setting
);
2068 schedule_accounts_save();
2072 purple_account_set_ui_string(PurpleAccount
*account
, const char *ui
,
2073 const char *name
, const char *value
)
2075 PurpleAccountSetting
*setting
;
2078 g_return_if_fail(account
!= NULL
);
2079 g_return_if_fail(ui
!= NULL
);
2080 g_return_if_fail(name
!= NULL
);
2082 setting
= g_new0(PurpleAccountSetting
, 1);
2084 setting
->type
= PURPLE_PREF_STRING
;
2085 setting
->ui
= g_strdup(ui
);
2086 setting
->value
.string
= g_strdup(value
);
2088 table
= get_ui_settings_table(account
, ui
);
2090 g_hash_table_insert(table
, g_strdup(name
), setting
);
2092 schedule_accounts_save();
2096 purple_account_set_ui_bool(PurpleAccount
*account
, const char *ui
,
2097 const char *name
, gboolean value
)
2099 PurpleAccountSetting
*setting
;
2102 g_return_if_fail(account
!= NULL
);
2103 g_return_if_fail(ui
!= NULL
);
2104 g_return_if_fail(name
!= NULL
);
2106 setting
= g_new0(PurpleAccountSetting
, 1);
2108 setting
->type
= PURPLE_PREF_BOOLEAN
;
2109 setting
->ui
= g_strdup(ui
);
2110 setting
->value
.boolean
= value
;
2112 table
= get_ui_settings_table(account
, ui
);
2114 g_hash_table_insert(table
, g_strdup(name
), setting
);
2116 schedule_accounts_save();
2119 static PurpleConnectionState
2120 purple_account_get_state(const PurpleAccount
*account
)
2122 PurpleConnection
*gc
;
2124 g_return_val_if_fail(account
!= NULL
, PURPLE_DISCONNECTED
);
2126 gc
= purple_account_get_connection(account
);
2128 return PURPLE_DISCONNECTED
;
2130 return purple_connection_get_state(gc
);
2134 purple_account_is_connected(const PurpleAccount
*account
)
2136 return (purple_account_get_state(account
) == PURPLE_CONNECTED
);
2140 purple_account_is_connecting(const PurpleAccount
*account
)
2142 return (purple_account_get_state(account
) == PURPLE_CONNECTING
);
2146 purple_account_is_disconnected(const PurpleAccount
*account
)
2148 return (purple_account_get_state(account
) == PURPLE_DISCONNECTED
);
2152 purple_account_get_username(const PurpleAccount
*account
)
2154 g_return_val_if_fail(account
!= NULL
, NULL
);
2156 return account
->username
;
2160 purple_account_get_password(const PurpleAccount
*account
)
2162 g_return_val_if_fail(account
!= NULL
, NULL
);
2164 return account
->password
;
2168 purple_account_get_alias(const PurpleAccount
*account
)
2170 g_return_val_if_fail(account
!= NULL
, NULL
);
2172 return account
->alias
;
2176 purple_account_get_user_info(const PurpleAccount
*account
)
2178 g_return_val_if_fail(account
!= NULL
, NULL
);
2180 return account
->user_info
;
2184 purple_account_get_buddy_icon_path(const PurpleAccount
*account
)
2186 g_return_val_if_fail(account
!= NULL
, NULL
);
2188 return account
->buddy_icon_path
;
2192 purple_account_get_protocol_id(const PurpleAccount
*account
)
2194 g_return_val_if_fail(account
!= NULL
, NULL
);
2195 return account
->protocol_id
;
2199 purple_account_get_protocol_name(const PurpleAccount
*account
)
2203 g_return_val_if_fail(account
!= NULL
, NULL
);
2205 p
= purple_find_prpl(purple_account_get_protocol_id(account
));
2207 return ((p
&& p
->info
->name
) ? _(p
->info
->name
) : _("Unknown"));
2211 purple_account_get_connection(const PurpleAccount
*account
)
2213 g_return_val_if_fail(account
!= NULL
, NULL
);
2219 purple_account_get_name_for_display(const PurpleAccount
*account
)
2221 PurpleBuddy
*self
= NULL
;
2222 PurpleConnection
*gc
= NULL
;
2223 const gchar
*name
= NULL
, *username
= NULL
, *displayname
= NULL
;
2225 name
= purple_account_get_alias(account
);
2231 username
= purple_account_get_username(account
);
2232 self
= purple_find_buddy((PurpleAccount
*)account
, username
);
2235 const gchar
*calias
= purple_buddy_get_contact_alias(self
);
2237 /* We don't want to return the buddy name if the buddy/contact
2238 * doesn't have an alias set. */
2239 if (!purple_strequal(username
, calias
)) {
2244 gc
= purple_account_get_connection(account
);
2245 displayname
= purple_connection_get_display_name(gc
);
2255 purple_account_get_remember_password(const PurpleAccount
*account
)
2257 g_return_val_if_fail(account
!= NULL
, FALSE
);
2259 return account
->remember_pass
;
2263 purple_account_get_check_mail(const PurpleAccount
*account
)
2265 g_return_val_if_fail(account
!= NULL
, FALSE
);
2267 return purple_account_get_bool(account
, "check-mail", FALSE
);
2271 purple_account_get_enabled(const PurpleAccount
*account
, const char *ui
)
2273 g_return_val_if_fail(account
!= NULL
, FALSE
);
2274 g_return_val_if_fail(ui
!= NULL
, FALSE
);
2276 return purple_account_get_ui_bool(account
, ui
, "auto-login", FALSE
);
2280 purple_account_get_proxy_info(const PurpleAccount
*account
)
2282 g_return_val_if_fail(account
!= NULL
, NULL
);
2284 return account
->proxy_info
;
2288 purple_account_get_privacy_type(const PurpleAccount
*account
)
2290 g_return_val_if_fail(account
!= NULL
, PURPLE_PRIVACY_ALLOW_ALL
);
2292 return account
->perm_deny
;
2296 purple_account_get_active_status(const PurpleAccount
*account
)
2298 g_return_val_if_fail(account
!= NULL
, NULL
);
2300 return purple_presence_get_active_status(account
->presence
);
2304 purple_account_get_status(const PurpleAccount
*account
, const char *status_id
)
2306 g_return_val_if_fail(account
!= NULL
, NULL
);
2307 g_return_val_if_fail(status_id
!= NULL
, NULL
);
2309 return purple_presence_get_status(account
->presence
, status_id
);
2313 purple_account_get_status_type(const PurpleAccount
*account
, const char *id
)
2317 g_return_val_if_fail(account
!= NULL
, NULL
);
2318 g_return_val_if_fail(id
!= NULL
, NULL
);
2320 for (l
= purple_account_get_status_types(account
); l
!= NULL
; l
= l
->next
)
2322 PurpleStatusType
*status_type
= (PurpleStatusType
*)l
->data
;
2324 if (purple_strequal(purple_status_type_get_id(status_type
), id
))
2332 purple_account_get_status_type_with_primitive(const PurpleAccount
*account
, PurpleStatusPrimitive primitive
)
2336 g_return_val_if_fail(account
!= NULL
, NULL
);
2338 for (l
= purple_account_get_status_types(account
); l
!= NULL
; l
= l
->next
)
2340 PurpleStatusType
*status_type
= (PurpleStatusType
*)l
->data
;
2342 if (purple_status_type_get_primitive(status_type
) == primitive
)
2350 purple_account_get_presence(const PurpleAccount
*account
)
2352 g_return_val_if_fail(account
!= NULL
, NULL
);
2354 return account
->presence
;
2358 purple_account_is_status_active(const PurpleAccount
*account
,
2359 const char *status_id
)
2361 g_return_val_if_fail(account
!= NULL
, FALSE
);
2362 g_return_val_if_fail(status_id
!= NULL
, FALSE
);
2364 return purple_presence_is_status_active(account
->presence
, status_id
);
2368 purple_account_get_status_types(const PurpleAccount
*account
)
2370 g_return_val_if_fail(account
!= NULL
, NULL
);
2372 return account
->status_types
;
2376 purple_account_get_int(const PurpleAccount
*account
, const char *name
,
2379 PurpleAccountSetting
*setting
;
2381 g_return_val_if_fail(account
!= NULL
, default_value
);
2382 g_return_val_if_fail(name
!= NULL
, default_value
);
2384 setting
= g_hash_table_lookup(account
->settings
, name
);
2386 if (setting
== NULL
)
2387 return default_value
;
2389 g_return_val_if_fail(setting
->type
== PURPLE_PREF_INT
, default_value
);
2391 return setting
->value
.integer
;
2395 purple_account_get_string(const PurpleAccount
*account
, const char *name
,
2396 const char *default_value
)
2398 PurpleAccountSetting
*setting
;
2400 g_return_val_if_fail(account
!= NULL
, default_value
);
2401 g_return_val_if_fail(name
!= NULL
, default_value
);
2403 setting
= g_hash_table_lookup(account
->settings
, name
);
2405 if (setting
== NULL
)
2406 return default_value
;
2408 g_return_val_if_fail(setting
->type
== PURPLE_PREF_STRING
, default_value
);
2410 return setting
->value
.string
;
2414 purple_account_get_bool(const PurpleAccount
*account
, const char *name
,
2415 gboolean default_value
)
2417 PurpleAccountSetting
*setting
;
2419 g_return_val_if_fail(account
!= NULL
, default_value
);
2420 g_return_val_if_fail(name
!= NULL
, default_value
);
2422 setting
= g_hash_table_lookup(account
->settings
, name
);
2424 if (setting
== NULL
)
2425 return default_value
;
2427 g_return_val_if_fail(setting
->type
== PURPLE_PREF_BOOLEAN
, default_value
);
2429 return setting
->value
.boolean
;
2433 purple_account_get_ui_int(const PurpleAccount
*account
, const char *ui
,
2434 const char *name
, int default_value
)
2436 PurpleAccountSetting
*setting
;
2439 g_return_val_if_fail(account
!= NULL
, default_value
);
2440 g_return_val_if_fail(ui
!= NULL
, default_value
);
2441 g_return_val_if_fail(name
!= NULL
, default_value
);
2443 if ((table
= g_hash_table_lookup(account
->ui_settings
, ui
)) == NULL
)
2444 return default_value
;
2446 if ((setting
= g_hash_table_lookup(table
, name
)) == NULL
)
2447 return default_value
;
2449 g_return_val_if_fail(setting
->type
== PURPLE_PREF_INT
, default_value
);
2451 return setting
->value
.integer
;
2455 purple_account_get_ui_string(const PurpleAccount
*account
, const char *ui
,
2456 const char *name
, const char *default_value
)
2458 PurpleAccountSetting
*setting
;
2461 g_return_val_if_fail(account
!= NULL
, default_value
);
2462 g_return_val_if_fail(ui
!= NULL
, default_value
);
2463 g_return_val_if_fail(name
!= NULL
, default_value
);
2465 if ((table
= g_hash_table_lookup(account
->ui_settings
, ui
)) == NULL
)
2466 return default_value
;
2468 if ((setting
= g_hash_table_lookup(table
, name
)) == NULL
)
2469 return default_value
;
2471 g_return_val_if_fail(setting
->type
== PURPLE_PREF_STRING
, default_value
);
2473 return setting
->value
.string
;
2477 purple_account_get_ui_bool(const PurpleAccount
*account
, const char *ui
,
2478 const char *name
, gboolean default_value
)
2480 PurpleAccountSetting
*setting
;
2483 g_return_val_if_fail(account
!= NULL
, default_value
);
2484 g_return_val_if_fail(ui
!= NULL
, default_value
);
2485 g_return_val_if_fail(name
!= NULL
, default_value
);
2487 if ((table
= g_hash_table_lookup(account
->ui_settings
, ui
)) == NULL
)
2488 return default_value
;
2490 if ((setting
= g_hash_table_lookup(table
, name
)) == NULL
)
2491 return default_value
;
2493 g_return_val_if_fail(setting
->type
== PURPLE_PREF_BOOLEAN
, default_value
);
2495 return setting
->value
.boolean
;
2499 purple_account_get_log(PurpleAccount
*account
, gboolean create
)
2501 g_return_val_if_fail(account
!= NULL
, NULL
);
2503 if(!account
->system_log
&& create
){
2504 PurplePresence
*presence
;
2507 presence
= purple_account_get_presence(account
);
2508 login_time
= purple_presence_get_login_time(presence
);
2510 account
->system_log
= purple_log_new(PURPLE_LOG_SYSTEM
,
2511 purple_account_get_username(account
), account
, NULL
,
2512 (login_time
!= 0) ? login_time
: time(NULL
), NULL
);
2515 return account
->system_log
;
2519 purple_account_destroy_log(PurpleAccount
*account
)
2521 g_return_if_fail(account
!= NULL
);
2523 if(account
->system_log
){
2524 purple_log_free(account
->system_log
);
2525 account
->system_log
= NULL
;
2530 purple_account_add_buddy(PurpleAccount
*account
, PurpleBuddy
*buddy
)
2532 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2533 PurpleConnection
*gc
;
2534 PurplePlugin
*prpl
= NULL
;
2536 g_return_if_fail(account
!= NULL
);
2537 g_return_if_fail(buddy
!= NULL
);
2539 gc
= purple_account_get_connection(account
);
2541 prpl
= purple_connection_get_prpl(gc
);
2544 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2546 if (prpl_info
!= NULL
) {
2547 if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, add_buddy_with_invite
))
2548 prpl_info
->add_buddy_with_invite(gc
, buddy
, purple_buddy_get_group(buddy
), NULL
);
2549 else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, add_buddy
))
2550 prpl_info
->add_buddy(gc
, buddy
, purple_buddy_get_group(buddy
));
2555 purple_account_add_buddy_with_invite(PurpleAccount
*account
, PurpleBuddy
*buddy
, const char *message
)
2557 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2558 PurpleConnection
*gc
;
2559 PurplePlugin
*prpl
= NULL
;
2561 g_return_if_fail(account
!= NULL
);
2562 g_return_if_fail(buddy
!= NULL
);
2564 gc
= purple_account_get_connection(account
);
2566 prpl
= purple_connection_get_prpl(gc
);
2569 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2571 if (prpl_info
!= NULL
) {
2572 if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, add_buddy_with_invite
))
2573 prpl_info
->add_buddy_with_invite(gc
, buddy
, purple_buddy_get_group(buddy
), message
);
2574 else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, add_buddy
))
2575 prpl_info
->add_buddy(gc
, buddy
, purple_buddy_get_group(buddy
));
2580 purple_account_add_buddies(PurpleAccount
*account
, GList
*buddies
)
2582 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2583 PurpleConnection
*gc
= purple_account_get_connection(account
);
2584 PurplePlugin
*prpl
= NULL
;
2587 prpl
= purple_connection_get_prpl(gc
);
2590 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2593 GList
*cur
, *groups
= NULL
;
2595 /* Make a list of what group each buddy is in */
2596 for (cur
= buddies
; cur
!= NULL
; cur
= cur
->next
) {
2597 PurpleBuddy
*buddy
= cur
->data
;
2598 groups
= g_list_append(groups
, purple_buddy_get_group(buddy
));
2601 if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, add_buddies_with_invite
))
2602 prpl_info
->add_buddies_with_invite(gc
, buddies
, groups
, NULL
);
2603 else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, add_buddies
))
2604 prpl_info
->add_buddies(gc
, buddies
, groups
);
2605 else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, add_buddy_with_invite
)) {
2606 GList
*curb
= buddies
, *curg
= groups
;
2608 while ((curb
!= NULL
) && (curg
!= NULL
)) {
2609 prpl_info
->add_buddy_with_invite(gc
, curb
->data
, curg
->data
, NULL
);
2614 else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, add_buddy
)) {
2615 GList
*curb
= buddies
, *curg
= groups
;
2617 while ((curb
!= NULL
) && (curg
!= NULL
)) {
2618 prpl_info
->add_buddy(gc
, curb
->data
, curg
->data
);
2624 g_list_free(groups
);
2629 purple_account_add_buddies_with_invite(PurpleAccount
*account
, GList
*buddies
, const char *message
)
2631 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2632 PurpleConnection
*gc
= purple_account_get_connection(account
);
2633 PurplePlugin
*prpl
= NULL
;
2636 prpl
= purple_connection_get_prpl(gc
);
2639 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2642 GList
*cur
, *groups
= NULL
;
2644 /* Make a list of what group each buddy is in */
2645 for (cur
= buddies
; cur
!= NULL
; cur
= cur
->next
) {
2646 PurpleBuddy
*buddy
= cur
->data
;
2647 groups
= g_list_append(groups
, purple_buddy_get_group(buddy
));
2650 if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, add_buddies_with_invite
))
2651 prpl_info
->add_buddies_with_invite(gc
, buddies
, groups
, message
);
2652 else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, add_buddy_with_invite
)) {
2653 GList
*curb
= buddies
, *curg
= groups
;
2655 while ((curb
!= NULL
) && (curg
!= NULL
)) {
2656 prpl_info
->add_buddy_with_invite(gc
, curb
->data
, curg
->data
, message
);
2661 else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, add_buddies
))
2662 prpl_info
->add_buddies(gc
, buddies
, groups
);
2663 else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, add_buddy
)) {
2664 GList
*curb
= buddies
, *curg
= groups
;
2666 while ((curb
!= NULL
) && (curg
!= NULL
)) {
2667 prpl_info
->add_buddy(gc
, curb
->data
, curg
->data
);
2673 g_list_free(groups
);
2678 purple_account_remove_buddy(PurpleAccount
*account
, PurpleBuddy
*buddy
,
2681 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2682 PurpleConnection
*gc
= purple_account_get_connection(account
);
2683 PurplePlugin
*prpl
= NULL
;
2686 prpl
= purple_connection_get_prpl(gc
);
2689 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2691 if (prpl_info
&& prpl_info
->remove_buddy
)
2692 prpl_info
->remove_buddy(gc
, buddy
, group
);
2696 purple_account_remove_buddies(PurpleAccount
*account
, GList
*buddies
, GList
*groups
)
2698 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2699 PurpleConnection
*gc
= purple_account_get_connection(account
);
2700 PurplePlugin
*prpl
= NULL
;
2703 prpl
= purple_connection_get_prpl(gc
);
2706 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2709 if (prpl_info
->remove_buddies
)
2710 prpl_info
->remove_buddies(gc
, buddies
, groups
);
2712 GList
*curb
= buddies
;
2713 GList
*curg
= groups
;
2714 while ((curb
!= NULL
) && (curg
!= NULL
)) {
2715 purple_account_remove_buddy(account
, curb
->data
, curg
->data
);
2724 purple_account_remove_group(PurpleAccount
*account
, PurpleGroup
*group
)
2726 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2727 PurpleConnection
*gc
= purple_account_get_connection(account
);
2728 PurplePlugin
*prpl
= NULL
;
2731 prpl
= purple_connection_get_prpl(gc
);
2734 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2736 if (prpl_info
&& prpl_info
->remove_group
)
2737 prpl_info
->remove_group(gc
, group
);
2741 purple_account_change_password(PurpleAccount
*account
, const char *orig_pw
,
2744 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2745 PurpleConnection
*gc
= purple_account_get_connection(account
);
2746 PurplePlugin
*prpl
= NULL
;
2748 purple_account_set_password(account
, new_pw
);
2751 prpl
= purple_connection_get_prpl(gc
);
2754 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2756 if (prpl_info
&& prpl_info
->change_passwd
)
2757 prpl_info
->change_passwd(gc
, orig_pw
, new_pw
);
2760 gboolean
purple_account_supports_offline_message(PurpleAccount
*account
, PurpleBuddy
*buddy
)
2762 PurpleConnection
*gc
;
2763 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2764 PurplePlugin
*prpl
= NULL
;
2766 g_return_val_if_fail(account
, FALSE
);
2767 g_return_val_if_fail(buddy
, FALSE
);
2769 gc
= purple_account_get_connection(account
);
2773 prpl
= purple_connection_get_prpl(gc
);
2776 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2778 if (!prpl_info
|| !prpl_info
->offline_message
)
2780 return prpl_info
->offline_message(buddy
);
2784 signed_on_cb(PurpleConnection
*gc
,
2787 PurpleAccount
*account
= purple_connection_get_account(gc
);
2788 purple_account_clear_current_error(account
);
2790 purple_signal_emit(purple_accounts_get_handle(), "account-signed-on",
2795 signed_off_cb(PurpleConnection
*gc
,
2798 PurpleAccount
*account
= purple_connection_get_account(gc
);
2800 purple_signal_emit(purple_accounts_get_handle(), "account-signed-off",
2805 set_current_error(PurpleAccount
*account
, PurpleConnectionErrorInfo
*new_err
)
2807 PurpleAccountPrivate
*priv
;
2808 PurpleConnectionErrorInfo
*old_err
;
2810 g_return_if_fail(account
!= NULL
);
2812 priv
= PURPLE_ACCOUNT_GET_PRIVATE(account
);
2813 old_err
= priv
->current_error
;
2815 if(new_err
== old_err
)
2818 priv
->current_error
= new_err
;
2820 purple_signal_emit(purple_accounts_get_handle(),
2821 "account-error-changed",
2822 account
, old_err
, new_err
);
2823 schedule_accounts_save();
2826 g_free(old_err
->description
);
2828 PURPLE_DBUS_UNREGISTER_POINTER(old_err
);
2833 connection_error_cb(PurpleConnection
*gc
,
2834 PurpleConnectionError type
,
2835 const gchar
*description
,
2838 PurpleAccount
*account
;
2839 PurpleConnectionErrorInfo
*err
;
2841 account
= purple_connection_get_account(gc
);
2843 g_return_if_fail(account
!= NULL
);
2845 err
= g_new0(PurpleConnectionErrorInfo
, 1);
2846 PURPLE_DBUS_REGISTER_POINTER(err
, PurpleConnectionErrorInfo
);
2849 err
->description
= g_strdup(description
);
2851 set_current_error(account
, err
);
2853 purple_signal_emit(purple_accounts_get_handle(), "account-connection-error",
2854 account
, type
, description
);
2857 const PurpleConnectionErrorInfo
*
2858 purple_account_get_current_error(PurpleAccount
*account
)
2860 PurpleAccountPrivate
*priv
= PURPLE_ACCOUNT_GET_PRIVATE(account
);
2861 return priv
->current_error
;
2865 purple_account_clear_current_error(PurpleAccount
*account
)
2867 set_current_error(account
, NULL
);
2871 purple_accounts_add(PurpleAccount
*account
)
2873 g_return_if_fail(account
!= NULL
);
2875 if (g_list_find(accounts
, account
) != NULL
)
2878 accounts
= g_list_append(accounts
, account
);
2880 schedule_accounts_save();
2882 purple_signal_emit(purple_accounts_get_handle(), "account-added", account
);
2886 purple_accounts_remove(PurpleAccount
*account
)
2888 g_return_if_fail(account
!= NULL
);
2890 accounts
= g_list_remove(accounts
, account
);
2892 schedule_accounts_save();
2894 /* Clearing the error ensures that account-error-changed is emitted,
2895 * which is the end of the guarantee that the the error's pointer is
2898 purple_account_clear_current_error(account
);
2899 purple_signal_emit(purple_accounts_get_handle(), "account-removed", account
);
2903 purple_accounts_delete(PurpleAccount
*account
)
2905 PurpleBlistNode
*gnode
, *cnode
, *bnode
;
2908 g_return_if_fail(account
!= NULL
);
2911 * Disable the account before blowing it out of the water.
2912 * Conceptually it probably makes more sense to disable the
2913 * account for all UIs rather than the just the current UI,
2914 * but it doesn't really matter.
2916 purple_account_set_enabled(account
, purple_core_get_ui(), FALSE
);
2918 purple_notify_close_with_handle(account
);
2919 purple_request_close_with_handle(account
);
2921 purple_accounts_remove(account
);
2923 /* Remove this account's buddies */
2924 for (gnode
= purple_blist_get_root();
2926 gnode
= purple_blist_node_get_sibling_next(gnode
))
2928 if (!PURPLE_BLIST_NODE_IS_GROUP(gnode
))
2931 cnode
= purple_blist_node_get_first_child(gnode
);
2933 PurpleBlistNode
*cnode_next
= purple_blist_node_get_sibling_next(cnode
);
2935 if(PURPLE_BLIST_NODE_IS_CONTACT(cnode
)) {
2936 bnode
= purple_blist_node_get_first_child(cnode
);
2938 PurpleBlistNode
*bnode_next
= purple_blist_node_get_sibling_next(bnode
);
2940 if (PURPLE_BLIST_NODE_IS_BUDDY(bnode
)) {
2941 PurpleBuddy
*b
= (PurpleBuddy
*)bnode
;
2943 if (purple_buddy_get_account(b
) == account
)
2944 purple_blist_remove_buddy(b
);
2948 } else if (PURPLE_BLIST_NODE_IS_CHAT(cnode
)) {
2949 PurpleChat
*c
= (PurpleChat
*)cnode
;
2951 if (purple_chat_get_account(c
) == account
)
2952 purple_blist_remove_chat(c
);
2958 /* Remove any open conversation for this account */
2959 for (iter
= purple_get_conversations(); iter
; ) {
2960 PurpleConversation
*conv
= iter
->data
;
2962 if (purple_conversation_get_account(conv
) == account
)
2963 purple_conversation_destroy(conv
);
2966 /* Remove this account's pounces */
2967 purple_pounce_destroy_all_by_account(account
);
2969 /* This will cause the deletion of an old buddy icon. */
2970 purple_buddy_icons_set_account_icon(account
, NULL
, 0);
2972 purple_account_destroy(account
);
2976 purple_accounts_reorder(PurpleAccount
*account
, gint new_index
)
2981 g_return_if_fail(account
!= NULL
);
2982 g_return_if_fail(new_index
<= g_list_length(accounts
));
2984 index
= g_list_index(accounts
, account
);
2987 purple_debug_error("account",
2988 "Unregistered account (%s) discovered during reorder!\n",
2989 purple_account_get_username(account
));
2993 l
= g_list_nth(accounts
, index
);
2995 if (new_index
> index
)
2998 /* Remove the old one. */
2999 accounts
= g_list_delete_link(accounts
, l
);
3001 /* Insert it where it should go. */
3002 accounts
= g_list_insert(accounts
, account
, new_index
);
3004 schedule_accounts_save();
3008 purple_accounts_get_all(void)
3014 purple_accounts_get_all_active(void)
3017 GList
*all
= purple_accounts_get_all();
3019 while (all
!= NULL
) {
3020 PurpleAccount
*account
= all
->data
;
3022 if (purple_account_get_enabled(account
, purple_core_get_ui()))
3023 list
= g_list_append(list
, account
);
3032 purple_accounts_find(const char *name
, const char *protocol_id
)
3034 PurpleAccount
*account
= NULL
;
3038 g_return_val_if_fail(name
!= NULL
, NULL
);
3039 g_return_val_if_fail(protocol_id
!= NULL
, NULL
);
3041 for (l
= purple_accounts_get_all(); l
!= NULL
; l
= l
->next
) {
3042 account
= (PurpleAccount
*)l
->data
;
3043 if (!purple_strequal(account
->protocol_id
, protocol_id
))
3046 who
= g_strdup(purple_normalize(account
, name
));
3047 if (purple_strequal(purple_normalize(account
, purple_account_get_username(account
)), who
)) {
3058 purple_accounts_restore_current_statuses()
3061 PurpleAccount
*account
;
3063 /* If we're not connected to the Internet right now, we bail on this */
3064 if (!purple_network_is_available())
3066 purple_debug_warning("account", "Network not connected; skipping reconnect\n");
3070 for (l
= purple_accounts_get_all(); l
!= NULL
; l
= l
->next
)
3072 account
= (PurpleAccount
*)l
->data
;
3073 if (purple_account_get_enabled(account
, purple_core_get_ui()) &&
3074 (purple_presence_is_online(account
->presence
)))
3076 purple_account_connect(account
);
3082 purple_accounts_set_ui_ops(PurpleAccountUiOps
*ops
)
3084 account_ui_ops
= ops
;
3087 PurpleAccountUiOps
*
3088 purple_accounts_get_ui_ops(void)
3090 return account_ui_ops
;
3094 purple_accounts_get_handle(void)
3102 purple_accounts_init(void)
3104 void *handle
= purple_accounts_get_handle();
3105 void *conn_handle
= purple_connections_get_handle();
3107 purple_signal_register(handle
, "account-connecting",
3108 purple_marshal_VOID__POINTER
, NULL
, 1,
3109 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3110 PURPLE_SUBTYPE_ACCOUNT
));
3112 purple_signal_register(handle
, "account-disabled",
3113 purple_marshal_VOID__POINTER
, NULL
, 1,
3114 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3115 PURPLE_SUBTYPE_ACCOUNT
));
3117 purple_signal_register(handle
, "account-enabled",
3118 purple_marshal_VOID__POINTER
, NULL
, 1,
3119 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3120 PURPLE_SUBTYPE_ACCOUNT
));
3122 purple_signal_register(handle
, "account-setting-info",
3123 purple_marshal_VOID__POINTER_POINTER
, NULL
, 2,
3124 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3125 PURPLE_SUBTYPE_ACCOUNT
),
3126 purple_value_new(PURPLE_TYPE_STRING
));
3128 purple_signal_register(handle
, "account-set-info",
3129 purple_marshal_VOID__POINTER_POINTER
, NULL
, 2,
3130 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3131 PURPLE_SUBTYPE_ACCOUNT
),
3132 purple_value_new(PURPLE_TYPE_STRING
));
3134 purple_signal_register(handle
, "account-created",
3135 purple_marshal_VOID__POINTER
, NULL
, 1,
3136 purple_value_new(PURPLE_TYPE_SUBTYPE
, PURPLE_SUBTYPE_ACCOUNT
));
3138 purple_signal_register(handle
, "account-destroying",
3139 purple_marshal_VOID__POINTER
, NULL
, 1,
3140 purple_value_new(PURPLE_TYPE_SUBTYPE
, PURPLE_SUBTYPE_ACCOUNT
));
3142 purple_signal_register(handle
, "account-added",
3143 purple_marshal_VOID__POINTER
, NULL
, 1,
3144 purple_value_new(PURPLE_TYPE_SUBTYPE
, PURPLE_SUBTYPE_ACCOUNT
));
3146 purple_signal_register(handle
, "account-removed",
3147 purple_marshal_VOID__POINTER
, NULL
, 1,
3148 purple_value_new(PURPLE_TYPE_SUBTYPE
, PURPLE_SUBTYPE_ACCOUNT
));
3150 purple_signal_register(handle
, "account-status-changed",
3151 purple_marshal_VOID__POINTER_POINTER_POINTER
, NULL
, 3,
3152 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3153 PURPLE_SUBTYPE_ACCOUNT
),
3154 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3155 PURPLE_SUBTYPE_STATUS
),
3156 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3157 PURPLE_SUBTYPE_STATUS
));
3159 purple_signal_register(handle
, "account-actions-changed",
3160 purple_marshal_VOID__POINTER
, NULL
, 1,
3161 purple_value_new(PURPLE_TYPE_SUBTYPE
, PURPLE_SUBTYPE_ACCOUNT
));
3163 purple_signal_register(handle
, "account-alias-changed",
3164 purple_marshal_VOID__POINTER_POINTER
, NULL
, 2,
3165 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3166 PURPLE_SUBTYPE_ACCOUNT
),
3167 purple_value_new(PURPLE_TYPE_STRING
));
3169 purple_signal_register(handle
, "account-authorization-requested",
3170 purple_marshal_INT__POINTER_POINTER
,
3171 purple_value_new(PURPLE_TYPE_INT
), 2,
3172 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3173 PURPLE_SUBTYPE_ACCOUNT
),
3174 purple_value_new(PURPLE_TYPE_STRING
));
3176 purple_signal_register(handle
, "account-authorization-requested-with-message",
3177 purple_marshal_INT__POINTER_POINTER_POINTER
,
3178 purple_value_new(PURPLE_TYPE_INT
), 3,
3179 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3180 PURPLE_SUBTYPE_ACCOUNT
),
3181 purple_value_new(PURPLE_TYPE_STRING
),
3182 purple_value_new(PURPLE_TYPE_STRING
));
3183 purple_signal_register(handle
, "account-authorization-denied",
3184 purple_marshal_VOID__POINTER_POINTER
, NULL
, 2,
3185 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3186 PURPLE_SUBTYPE_ACCOUNT
),
3187 purple_value_new(PURPLE_TYPE_STRING
));
3189 purple_signal_register(handle
, "account-authorization-granted",
3190 purple_marshal_VOID__POINTER_POINTER
, NULL
, 2,
3191 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3192 PURPLE_SUBTYPE_ACCOUNT
),
3193 purple_value_new(PURPLE_TYPE_STRING
));
3195 purple_signal_register(handle
, "account-error-changed",
3196 purple_marshal_VOID__POINTER_POINTER_POINTER
,
3198 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3199 PURPLE_SUBTYPE_ACCOUNT
),
3200 purple_value_new(PURPLE_TYPE_POINTER
),
3201 purple_value_new(PURPLE_TYPE_POINTER
));
3203 purple_signal_register(handle
, "account-signed-on",
3204 purple_marshal_VOID__POINTER
, NULL
, 1,
3205 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3206 PURPLE_SUBTYPE_ACCOUNT
));
3208 purple_signal_register(handle
, "account-signed-off",
3209 purple_marshal_VOID__POINTER
, NULL
, 1,
3210 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3211 PURPLE_SUBTYPE_ACCOUNT
));
3213 purple_signal_register(handle
, "account-connection-error",
3214 purple_marshal_VOID__POINTER_INT_POINTER
, NULL
, 3,
3215 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3216 PURPLE_SUBTYPE_ACCOUNT
),
3217 purple_value_new(PURPLE_TYPE_ENUM
),
3218 purple_value_new(PURPLE_TYPE_STRING
));
3220 purple_signal_connect(conn_handle
, "signed-on", handle
,
3221 PURPLE_CALLBACK(signed_on_cb
), NULL
);
3222 purple_signal_connect(conn_handle
, "signed-off", handle
,
3223 PURPLE_CALLBACK(signed_off_cb
), NULL
);
3224 purple_signal_connect(conn_handle
, "connection-error", handle
,
3225 PURPLE_CALLBACK(connection_error_cb
), NULL
);
3232 purple_accounts_uninit(void)
3234 gpointer handle
= purple_accounts_get_handle();
3235 if (save_timer
!= 0)
3237 purple_timeout_remove(save_timer
);
3242 for (; accounts
; accounts
= g_list_delete_link(accounts
, accounts
))
3243 purple_account_destroy(accounts
->data
);
3245 purple_signals_disconnect_by_handle(handle
);
3246 purple_signals_unregister_by_instance(handle
);