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_USE_ENVVAR
? "envvar" : "unknown"), -1);
299 if ((value
= purple_proxy_info_get_host(proxy_info
)) != NULL
)
301 child
= xmlnode_new_child(node
, "host");
302 xmlnode_insert_data(child
, value
, -1);
305 if ((int_value
= purple_proxy_info_get_port(proxy_info
)) != 0)
307 g_snprintf(buf
, sizeof(buf
), "%d", int_value
);
308 child
= xmlnode_new_child(node
, "port");
309 xmlnode_insert_data(child
, buf
, -1);
312 if ((value
= purple_proxy_info_get_username(proxy_info
)) != NULL
)
314 child
= xmlnode_new_child(node
, "username");
315 xmlnode_insert_data(child
, value
, -1);
318 if ((value
= purple_proxy_info_get_password(proxy_info
)) != NULL
)
320 child
= xmlnode_new_child(node
, "password");
321 xmlnode_insert_data(child
, value
, -1);
328 current_error_to_xmlnode(PurpleConnectionErrorInfo
*err
)
330 xmlnode
*node
, *child
;
333 node
= xmlnode_new("current_error");
338 /* It doesn't make sense to have transient errors persist across a
341 if(!purple_connection_error_is_fatal (err
->type
))
344 child
= xmlnode_new_child(node
, "type");
345 g_snprintf(type_str
, sizeof(type_str
), "%u", err
->type
);
346 xmlnode_insert_data(child
, type_str
, -1);
348 child
= xmlnode_new_child(node
, "description");
349 if(err
->description
) {
350 char *utf8ized
= purple_utf8_try_convert(err
->description
);
352 utf8ized
= purple_utf8_salvage(err
->description
);
353 xmlnode_insert_data(child
, utf8ized
, -1);
361 account_to_xmlnode(PurpleAccount
*account
)
363 PurpleAccountPrivate
*priv
= PURPLE_ACCOUNT_GET_PRIVATE(account
);
365 xmlnode
*node
, *child
;
367 PurplePresence
*presence
;
368 PurpleProxyInfo
*proxy_info
;
370 node
= xmlnode_new("account");
372 child
= xmlnode_new_child(node
, "protocol");
373 xmlnode_insert_data(child
, purple_account_get_protocol_id(account
), -1);
375 child
= xmlnode_new_child(node
, "name");
376 xmlnode_insert_data(child
, purple_account_get_username(account
), -1);
378 if (purple_account_get_remember_password(account
) &&
379 ((tmp
= purple_account_get_password(account
)) != NULL
))
381 child
= xmlnode_new_child(node
, "password");
382 xmlnode_insert_data(child
, tmp
, -1);
385 if ((tmp
= purple_account_get_alias(account
)) != NULL
)
387 child
= xmlnode_new_child(node
, "alias");
388 xmlnode_insert_data(child
, tmp
, -1);
391 if ((presence
= purple_account_get_presence(account
)) != NULL
)
393 child
= statuses_to_xmlnode(presence
);
394 xmlnode_insert_child(node
, child
);
397 if ((tmp
= purple_account_get_user_info(account
)) != NULL
)
399 /* TODO: Do we need to call purple_str_strip_char(tmp, '\r') here? */
400 child
= xmlnode_new_child(node
, "userinfo");
401 xmlnode_insert_data(child
, tmp
, -1);
404 if (g_hash_table_size(account
->settings
) > 0)
406 child
= xmlnode_new_child(node
, "settings");
407 g_hash_table_foreach(account
->settings
, setting_to_xmlnode
, child
);
410 if (g_hash_table_size(account
->ui_settings
) > 0)
412 g_hash_table_foreach(account
->ui_settings
, ui_setting_to_xmlnode
, node
);
415 if ((proxy_info
= purple_account_get_proxy_info(account
)) != NULL
)
417 child
= proxy_settings_to_xmlnode(proxy_info
);
418 xmlnode_insert_child(node
, child
);
421 child
= current_error_to_xmlnode(priv
->current_error
);
422 xmlnode_insert_child(node
, child
);
428 accounts_to_xmlnode(void)
430 xmlnode
*node
, *child
;
433 node
= xmlnode_new("account");
434 xmlnode_set_attrib(node
, "version", "1.0");
436 for (cur
= purple_accounts_get_all(); cur
!= NULL
; cur
= cur
->next
)
438 child
= account_to_xmlnode(cur
->data
);
439 xmlnode_insert_child(node
, child
);
451 if (!accounts_loaded
)
453 purple_debug_error("account", "Attempted to save accounts before "
454 "they were read!\n");
458 node
= accounts_to_xmlnode();
459 data
= xmlnode_to_formatted_str(node
, NULL
);
460 purple_util_write_data_to_file("accounts.xml", data
, -1);
466 save_cb(gpointer data
)
474 schedule_accounts_save(void)
477 save_timer
= purple_timeout_add_seconds(5, save_cb
, NULL
);
481 /*********************************************************************
482 * Reading from disk *
483 *********************************************************************/
485 migrate_yahoo_japan(PurpleAccount
*account
)
487 /* detect a Yahoo! JAPAN account that existed prior to 2.6.0 and convert it
488 * to use the new prpl-yahoojp. Also remove the account-specific settings
489 * we no longer need */
491 if(purple_strequal(purple_account_get_protocol_id(account
), "prpl-yahoo")) {
492 if(purple_account_get_bool(account
, "yahoojp", FALSE
)) {
493 const char *serverjp
= purple_account_get_string(account
, "serverjp", NULL
);
494 const char *xferjp_host
= purple_account_get_string(account
, "xferjp_host", NULL
);
496 g_return_if_fail(serverjp
!= NULL
);
497 g_return_if_fail(xferjp_host
!= NULL
);
499 purple_account_set_string(account
, "server", serverjp
);
500 purple_account_set_string(account
, "xfer_host", xferjp_host
);
502 purple_account_set_protocol_id(account
, "prpl-yahoojp");
505 /* these should always be nuked */
506 purple_account_remove_setting(account
, "yahoojp");
507 purple_account_remove_setting(account
, "serverjp");
508 purple_account_remove_setting(account
, "xferjp_host");
516 parse_settings(xmlnode
*node
, PurpleAccount
*account
)
521 /* Get the UI string, if these are UI settings */
522 ui
= xmlnode_get_attrib(node
, "ui");
524 /* Read settings, one by one */
525 for (child
= xmlnode_get_child(node
, "setting"); child
!= NULL
;
526 child
= xmlnode_get_next_twin(child
))
528 const char *name
, *str_type
;
532 name
= xmlnode_get_attrib(child
, "name");
534 /* Ignore this setting */
537 str_type
= xmlnode_get_attrib(child
, "type");
538 if (str_type
== NULL
)
539 /* Ignore this setting */
542 if (purple_strequal(str_type
, "string"))
543 type
= PURPLE_PREF_STRING
;
544 else if (purple_strequal(str_type
, "int"))
545 type
= PURPLE_PREF_INT
;
546 else if (purple_strequal(str_type
, "bool"))
547 type
= PURPLE_PREF_BOOLEAN
;
549 /* Ignore this setting */
552 data
= xmlnode_get_data(child
);
554 /* Ignore this setting */
559 if (type
== PURPLE_PREF_STRING
)
560 purple_account_set_string(account
, name
, data
);
561 else if (type
== PURPLE_PREF_INT
)
562 purple_account_set_int(account
, name
, atoi(data
));
563 else if (type
== PURPLE_PREF_BOOLEAN
)
564 purple_account_set_bool(account
, name
,
565 (*data
== '0' ? FALSE
: TRUE
));
567 if (type
== PURPLE_PREF_STRING
)
568 purple_account_set_ui_string(account
, ui
, name
, data
);
569 else if (type
== PURPLE_PREF_INT
)
570 purple_account_set_ui_int(account
, ui
, name
, atoi(data
));
571 else if (type
== PURPLE_PREF_BOOLEAN
)
572 purple_account_set_ui_bool(account
, ui
, name
,
573 (*data
== '0' ? FALSE
: TRUE
));
579 /* we do this here because we need access to account settings to determine
580 * if we can/should migrate an old Yahoo! JAPAN account */
581 migrate_yahoo_japan(account
);
585 parse_status_attrs(xmlnode
*node
, PurpleStatus
*status
)
589 PurpleValue
*attr_value
;
591 for (child
= xmlnode_get_child(node
, "attribute"); child
!= NULL
;
592 child
= xmlnode_get_next_twin(child
))
594 const char *id
= xmlnode_get_attrib(child
, "id");
595 const char *value
= xmlnode_get_attrib(child
, "value");
597 if (!id
|| !*id
|| !value
|| !*value
)
600 attr_value
= purple_status_get_attr_value(status
, id
);
604 list
= g_list_append(list
, (char *)id
);
606 switch (purple_value_get_type(attr_value
))
608 case PURPLE_TYPE_STRING
:
609 list
= g_list_append(list
, (char *)value
);
611 case PURPLE_TYPE_INT
:
612 case PURPLE_TYPE_BOOLEAN
:
615 if (sscanf(value
, "%d", &v
) == 1)
616 list
= g_list_append(list
, GINT_TO_POINTER(v
));
618 list
= g_list_remove(list
, id
);
630 parse_status(xmlnode
*node
, PurpleAccount
*account
)
632 gboolean active
= FALSE
;
638 /* Get the active/inactive state */
639 data
= xmlnode_get_attrib(node
, "active");
642 if (g_ascii_strcasecmp(data
, "true") == 0)
644 else if (g_ascii_strcasecmp(data
, "false") == 0)
649 /* Get the type of the status */
650 type
= xmlnode_get_attrib(node
, "type");
654 /* Read attributes into a GList */
655 child
= xmlnode_get_child(node
, "attributes");
658 attrs
= parse_status_attrs(child
,
659 purple_account_get_status(account
, type
));
662 purple_account_set_status_list(account
, type
, active
, attrs
);
668 parse_statuses(xmlnode
*node
, PurpleAccount
*account
)
672 for (child
= xmlnode_get_child(node
, "status"); child
!= NULL
;
673 child
= xmlnode_get_next_twin(child
))
675 parse_status(child
, account
);
680 parse_proxy_info(xmlnode
*node
, PurpleAccount
*account
)
682 PurpleProxyInfo
*proxy_info
;
686 proxy_info
= purple_proxy_info_new();
688 /* Use the global proxy settings, by default */
689 purple_proxy_info_set_type(proxy_info
, PURPLE_PROXY_USE_GLOBAL
);
691 /* Read proxy type */
692 child
= xmlnode_get_child(node
, "type");
693 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
695 if (purple_strequal(data
, "global"))
696 purple_proxy_info_set_type(proxy_info
, PURPLE_PROXY_USE_GLOBAL
);
697 else if (purple_strequal(data
, "none"))
698 purple_proxy_info_set_type(proxy_info
, PURPLE_PROXY_NONE
);
699 else if (purple_strequal(data
, "http"))
700 purple_proxy_info_set_type(proxy_info
, PURPLE_PROXY_HTTP
);
701 else if (purple_strequal(data
, "socks4"))
702 purple_proxy_info_set_type(proxy_info
, PURPLE_PROXY_SOCKS4
);
703 else if (purple_strequal(data
, "socks5"))
704 purple_proxy_info_set_type(proxy_info
, PURPLE_PROXY_SOCKS5
);
705 else if (purple_strequal(data
, "envvar"))
706 purple_proxy_info_set_type(proxy_info
, PURPLE_PROXY_USE_ENVVAR
);
709 purple_debug_error("account", "Invalid proxy type found when "
710 "loading account information for %s\n",
711 purple_account_get_username(account
));
716 /* Read proxy host */
717 child
= xmlnode_get_child(node
, "host");
718 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
720 purple_proxy_info_set_host(proxy_info
, data
);
724 /* Read proxy port */
725 child
= xmlnode_get_child(node
, "port");
726 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
728 purple_proxy_info_set_port(proxy_info
, atoi(data
));
732 /* Read proxy username */
733 child
= xmlnode_get_child(node
, "username");
734 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
736 purple_proxy_info_set_username(proxy_info
, data
);
740 /* Read proxy password */
741 child
= xmlnode_get_child(node
, "password");
742 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
744 purple_proxy_info_set_password(proxy_info
, data
);
748 /* If there are no values set then proxy_info NULL */
749 if ((purple_proxy_info_get_type(proxy_info
) == PURPLE_PROXY_USE_GLOBAL
) &&
750 (purple_proxy_info_get_host(proxy_info
) == NULL
) &&
751 (purple_proxy_info_get_port(proxy_info
) == 0) &&
752 (purple_proxy_info_get_username(proxy_info
) == NULL
) &&
753 (purple_proxy_info_get_password(proxy_info
) == NULL
))
755 purple_proxy_info_destroy(proxy_info
);
759 purple_account_set_proxy_info(account
, proxy_info
);
763 parse_current_error(xmlnode
*node
, PurpleAccount
*account
)
766 char *type_str
= NULL
, *description
= NULL
;
768 PurpleConnectionErrorInfo
*current_error
= NULL
;
770 child
= xmlnode_get_child(node
, "type");
771 if (child
== NULL
|| (type_str
= xmlnode_get_data(child
)) == NULL
)
773 type
= atoi(type_str
);
776 if (type
> PURPLE_CONNECTION_ERROR_OTHER_ERROR
)
778 purple_debug_error("account",
779 "Invalid PurpleConnectionError value %d found when "
780 "loading account information for %s\n",
781 type
, purple_account_get_username(account
));
782 type
= PURPLE_CONNECTION_ERROR_OTHER_ERROR
;
785 child
= xmlnode_get_child(node
, "description");
787 description
= xmlnode_get_data(child
);
788 if (description
== NULL
)
789 description
= g_strdup("");
791 current_error
= g_new0(PurpleConnectionErrorInfo
, 1);
792 PURPLE_DBUS_REGISTER_POINTER(current_error
, PurpleConnectionErrorInfo
);
793 current_error
->type
= type
;
794 current_error
->description
= description
;
796 set_current_error(account
, current_error
);
799 static PurpleAccount
*
800 parse_account(xmlnode
*node
)
804 char *protocol_id
= NULL
;
808 child
= xmlnode_get_child(node
, "protocol");
810 protocol_id
= xmlnode_get_data(child
);
812 child
= xmlnode_get_child(node
, "name");
814 name
= xmlnode_get_data(child
);
817 /* Do we really need to do this? */
818 child
= xmlnode_get_child(node
, "username");
820 name
= xmlnode_get_data(child
);
823 if ((protocol_id
== NULL
) || (name
== NULL
))
830 ret
= purple_account_new(name
, _purple_oscar_convert(name
, protocol_id
)); /* XXX: */
834 /* Read the password */
835 child
= xmlnode_get_child(node
, "password");
836 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
838 purple_account_set_remember_password(ret
, TRUE
);
839 purple_account_set_password(ret
, data
);
844 child
= xmlnode_get_child(node
, "alias");
845 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
848 purple_account_set_alias(ret
, data
);
852 /* Read the statuses */
853 child
= xmlnode_get_child(node
, "statuses");
856 parse_statuses(child
, ret
);
859 /* Read the userinfo */
860 child
= xmlnode_get_child(node
, "userinfo");
861 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
863 purple_account_set_user_info(ret
, data
);
867 /* Read an old buddyicon */
868 child
= xmlnode_get_child(node
, "buddyicon");
869 if ((child
!= NULL
) && ((data
= xmlnode_get_data(child
)) != NULL
))
871 const char *dirname
= purple_buddy_icons_get_cache_dir();
872 char *filename
= g_build_filename(dirname
, data
, NULL
);
876 if (g_file_get_contents(filename
, &contents
, &len
, NULL
))
878 purple_buddy_icons_set_account_icon(ret
, (guchar
*)contents
, len
);
882 /* Try to see if the icon got left behind in the old cache. */
884 filename
= g_build_filename(g_get_home_dir(), ".gaim", "icons", data
, NULL
);
885 if (g_file_get_contents(filename
, &contents
, &len
, NULL
)) {
886 purple_buddy_icons_set_account_icon(ret
, (guchar
*)contents
, len
);
894 /* Read settings (both core and UI) */
895 for (child
= xmlnode_get_child(node
, "settings"); child
!= NULL
;
896 child
= xmlnode_get_next_twin(child
))
898 parse_settings(child
, ret
);
902 child
= xmlnode_get_child(node
, "proxy");
905 parse_proxy_info(child
, ret
);
908 /* Read current error */
909 child
= xmlnode_get_child(node
, "current_error");
912 parse_current_error(child
, ret
);
921 xmlnode
*node
, *child
;
923 accounts_loaded
= TRUE
;
925 node
= purple_util_read_xml_from_file("accounts.xml", _("accounts"));
930 for (child
= xmlnode_get_child(node
, "account"); child
!= NULL
;
931 child
= xmlnode_get_next_twin(child
))
933 PurpleAccount
*new_acct
;
934 new_acct
= parse_account(child
);
935 purple_accounts_add(new_acct
);
940 _purple_buddy_icons_account_loaded_cb();
945 delete_setting(void *data
)
947 PurpleAccountSetting
*setting
= (PurpleAccountSetting
*)data
;
951 if (setting
->type
== PURPLE_PREF_STRING
)
952 g_free(setting
->value
.string
);
958 purple_account_new(const char *username
, const char *protocol_id
)
960 PurpleAccount
*account
= NULL
;
961 PurpleAccountPrivate
*priv
= NULL
;
962 PurplePlugin
*prpl
= NULL
;
963 PurplePluginProtocolInfo
*prpl_info
= NULL
;
964 PurpleStatusType
*status_type
;
966 g_return_val_if_fail(username
!= NULL
, NULL
);
967 g_return_val_if_fail(protocol_id
!= NULL
, NULL
);
969 account
= purple_accounts_find(username
, protocol_id
);
974 account
= g_new0(PurpleAccount
, 1);
975 PURPLE_DBUS_REGISTER_POINTER(account
, PurpleAccount
);
976 priv
= g_new0(PurpleAccountPrivate
, 1);
977 account
->priv
= priv
;
979 purple_account_set_username(account
, username
);
981 purple_account_set_protocol_id(account
, protocol_id
);
983 account
->settings
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
984 g_free
, delete_setting
);
985 account
->ui_settings
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
986 g_free
, (GDestroyNotify
)g_hash_table_destroy
);
987 account
->system_log
= NULL
;
988 /* 0 is not a valid privacy setting */
989 account
->perm_deny
= PURPLE_PRIVACY_ALLOW_ALL
;
991 purple_signal_emit(purple_accounts_get_handle(), "account-created", account
);
993 prpl
= purple_find_prpl(protocol_id
);
998 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
999 if (prpl_info
!= NULL
&& prpl_info
->status_types
!= NULL
)
1000 purple_account_set_status_types(account
, prpl_info
->status_types(account
));
1002 account
->presence
= purple_presence_new_for_account(account
);
1004 status_type
= purple_account_get_status_type_with_primitive(account
, PURPLE_STATUS_AVAILABLE
);
1005 if (status_type
!= NULL
)
1006 purple_presence_set_status_active(account
->presence
,
1007 purple_status_type_get_id(status_type
),
1010 purple_presence_set_status_active(account
->presence
,
1018 purple_account_destroy(PurpleAccount
*account
)
1020 PurpleAccountPrivate
*priv
= NULL
;
1023 g_return_if_fail(account
!= NULL
);
1025 purple_debug_info("account", "Destroying account %p\n", account
);
1026 purple_signal_emit(purple_accounts_get_handle(), "account-destroying", account
);
1028 for (l
= purple_get_conversations(); l
!= NULL
; l
= l
->next
)
1030 PurpleConversation
*conv
= (PurpleConversation
*)l
->data
;
1032 if (purple_conversation_get_account(conv
) == account
)
1033 purple_conversation_set_account(conv
, NULL
);
1036 g_free(account
->username
);
1037 g_free(account
->alias
);
1038 g_free(account
->password
);
1039 g_free(account
->user_info
);
1040 g_free(account
->buddy_icon_path
);
1041 g_free(account
->protocol_id
);
1043 g_hash_table_destroy(account
->settings
);
1044 g_hash_table_destroy(account
->ui_settings
);
1046 purple_account_set_status_types(account
, NULL
);
1048 purple_presence_destroy(account
->presence
);
1050 if(account
->system_log
)
1051 purple_log_free(account
->system_log
);
1053 while (account
->deny
) {
1054 g_free(account
->deny
->data
);
1055 account
->deny
= g_slist_delete_link(account
->deny
, account
->deny
);
1058 while (account
->permit
) {
1059 g_free(account
->permit
->data
);
1060 account
->permit
= g_slist_delete_link(account
->permit
, account
->permit
);
1063 priv
= PURPLE_ACCOUNT_GET_PRIVATE(account
);
1064 PURPLE_DBUS_UNREGISTER_POINTER(priv
->current_error
);
1065 if (priv
->current_error
) {
1066 g_free(priv
->current_error
->description
);
1067 g_free(priv
->current_error
);
1071 PURPLE_DBUS_UNREGISTER_POINTER(account
);
1076 purple_account_set_register_callback(PurpleAccount
*account
, PurpleAccountRegistrationCb cb
, void *user_data
)
1078 g_return_if_fail(account
!= NULL
);
1080 account
->registration_cb
= cb
;
1081 account
->registration_cb_user_data
= user_data
;
1085 purple_account_register(PurpleAccount
*account
)
1087 g_return_if_fail(account
!= NULL
);
1089 purple_debug_info("account", "Registering account %s\n",
1090 purple_account_get_username(account
));
1092 _purple_connection_new(account
, TRUE
, purple_account_get_password(account
));
1096 purple_account_unregister(PurpleAccount
*account
, PurpleAccountUnregistrationCb cb
, void *user_data
)
1098 g_return_if_fail(account
!= NULL
);
1100 purple_debug_info("account", "Unregistering account %s\n",
1101 purple_account_get_username(account
));
1103 _purple_connection_new_unregister(account
, purple_account_get_password(account
), cb
, user_data
);
1107 request_password_ok_cb(PurpleAccount
*account
, PurpleRequestFields
*fields
)
1112 entry
= purple_request_fields_get_string(fields
, "password");
1113 remember
= purple_request_fields_get_bool(fields
, "remember");
1115 if (!entry
|| !*entry
)
1117 purple_notify_error(account
, NULL
, _("Password is required to sign on."), NULL
);
1122 purple_account_set_remember_password(account
, TRUE
);
1124 purple_account_set_password(account
, entry
);
1126 _purple_connection_new(account
, FALSE
, entry
);
1130 request_password_cancel_cb(PurpleAccount
*account
, PurpleRequestFields
*fields
)
1132 /* Disable the account as the user has canceled connecting */
1133 purple_account_set_enabled(account
, purple_core_get_ui(), FALSE
);
1138 purple_account_request_password(PurpleAccount
*account
, GCallback ok_cb
,
1139 GCallback cancel_cb
, void *user_data
)
1142 const gchar
*username
;
1143 PurpleRequestFieldGroup
*group
;
1144 PurpleRequestField
*field
;
1145 PurpleRequestFields
*fields
;
1147 /* Close any previous password request windows */
1148 purple_request_close_with_handle(account
);
1150 username
= purple_account_get_username(account
);
1151 primary
= g_strdup_printf(_("Enter password for %s (%s)"), username
,
1152 purple_account_get_protocol_name(account
));
1154 fields
= purple_request_fields_new();
1155 group
= purple_request_field_group_new(NULL
);
1156 purple_request_fields_add_group(fields
, group
);
1158 field
= purple_request_field_string_new("password", _("Enter Password"), NULL
, FALSE
);
1159 purple_request_field_string_set_masked(field
, TRUE
);
1160 purple_request_field_set_required(field
, TRUE
);
1161 purple_request_field_group_add_field(group
, field
);
1163 field
= purple_request_field_bool_new("remember", _("Save password"), FALSE
);
1164 purple_request_field_group_add_field(group
, field
);
1166 purple_request_fields(account
,
1172 _("Cancel"), cancel_cb
,
1173 account
, NULL
, NULL
,
1179 purple_account_connect(PurpleAccount
*account
)
1182 const char *password
, *username
;
1183 PurplePluginProtocolInfo
*prpl_info
;
1185 g_return_if_fail(account
!= NULL
);
1187 username
= purple_account_get_username(account
);
1189 if (!purple_account_get_enabled(account
, purple_core_get_ui())) {
1190 purple_debug_info("account",
1191 "Account %s not enabled, not connecting.\n",
1196 prpl
= purple_find_prpl(purple_account_get_protocol_id(account
));
1200 message
= g_strdup_printf(_("Missing protocol plugin for %s"), username
);
1201 purple_notify_error(account
, _("Connection Error"), message
, NULL
);
1206 purple_debug_info("account", "Connecting to account %s.\n", username
);
1208 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
1209 password
= purple_account_get_password(account
);
1210 if ((password
== NULL
) &&
1211 !(prpl_info
->options
& OPT_PROTO_NO_PASSWORD
) &&
1212 !(prpl_info
->options
& OPT_PROTO_PASSWORD_OPTIONAL
))
1213 purple_account_request_password(account
, G_CALLBACK(request_password_ok_cb
), G_CALLBACK(request_password_cancel_cb
), account
);
1215 _purple_connection_new(account
, FALSE
, password
);
1219 purple_account_disconnect(PurpleAccount
*account
)
1221 PurpleConnection
*gc
;
1222 const char *username
;
1224 g_return_if_fail(account
!= NULL
);
1225 g_return_if_fail(!purple_account_is_disconnected(account
));
1227 username
= purple_account_get_username(account
);
1228 purple_debug_info("account", "Disconnecting account %s (%p)\n",
1229 username
? username
: "(null)", account
);
1231 account
->disconnecting
= TRUE
;
1233 gc
= purple_account_get_connection(account
);
1234 _purple_connection_destroy(gc
);
1235 if (!purple_account_get_remember_password(account
))
1236 purple_account_set_password(account
, NULL
);
1237 purple_account_set_connection(account
, NULL
);
1239 account
->disconnecting
= FALSE
;
1243 purple_account_notify_added(PurpleAccount
*account
, const char *remote_user
,
1244 const char *id
, const char *alias
,
1245 const char *message
)
1247 PurpleAccountUiOps
*ui_ops
;
1249 g_return_if_fail(account
!= NULL
);
1250 g_return_if_fail(remote_user
!= NULL
);
1252 ui_ops
= purple_accounts_get_ui_ops();
1254 if (ui_ops
!= NULL
&& ui_ops
->notify_added
!= NULL
)
1255 ui_ops
->notify_added(account
, remote_user
, id
, alias
, message
);
1259 purple_account_request_add(PurpleAccount
*account
, const char *remote_user
,
1260 const char *id
, const char *alias
,
1261 const char *message
)
1263 PurpleAccountUiOps
*ui_ops
;
1265 g_return_if_fail(account
!= NULL
);
1266 g_return_if_fail(remote_user
!= NULL
);
1268 ui_ops
= purple_accounts_get_ui_ops();
1270 if (ui_ops
!= NULL
&& ui_ops
->request_add
!= NULL
)
1271 ui_ops
->request_add(account
, remote_user
, id
, alias
, message
);
1274 static PurpleAccountRequestInfo
*
1275 purple_account_request_info_unref(PurpleAccountRequestInfo
*info
)
1280 /* TODO: This will leak info->user_data, but there is no callback to just clean that up */
1287 purple_account_request_close_info(PurpleAccountRequestInfo
*info
)
1289 PurpleAccountUiOps
*ops
;
1291 ops
= purple_accounts_get_ui_ops();
1293 if (ops
!= NULL
&& ops
->close_account_request
!= NULL
)
1294 ops
->close_account_request(info
->ui_handle
);
1296 purple_account_request_info_unref(info
);
1300 purple_account_request_close_with_account(PurpleAccount
*account
)
1304 g_return_if_fail(account
!= NULL
);
1306 for (l
= handles
; l
!= NULL
; l
= l_next
) {
1307 PurpleAccountRequestInfo
*info
= l
->data
;
1311 if (info
->account
== account
) {
1312 handles
= g_list_remove(handles
, info
);
1313 purple_account_request_close_info(info
);
1319 purple_account_request_close(void *ui_handle
)
1323 g_return_if_fail(ui_handle
!= NULL
);
1325 for (l
= handles
; l
!= NULL
; l
= l_next
) {
1326 PurpleAccountRequestInfo
*info
= l
->data
;
1330 if (info
->ui_handle
== ui_handle
) {
1331 handles
= g_list_remove(handles
, info
);
1332 purple_account_request_close_info(info
);
1338 request_auth_cb(void *data
)
1340 PurpleAccountRequestInfo
*info
= data
;
1342 handles
= g_list_remove(handles
, info
);
1344 if (info
->auth_cb
!= NULL
)
1345 info
->auth_cb(info
->userdata
);
1347 purple_signal_emit(purple_accounts_get_handle(),
1348 "account-authorization-granted", info
->account
, info
->user
);
1350 purple_account_request_info_unref(info
);
1354 request_deny_cb(void *data
)
1356 PurpleAccountRequestInfo
*info
= data
;
1358 handles
= g_list_remove(handles
, info
);
1360 if (info
->deny_cb
!= NULL
)
1361 info
->deny_cb(info
->userdata
);
1363 purple_signal_emit(purple_accounts_get_handle(),
1364 "account-authorization-denied", info
->account
, info
->user
);
1366 purple_account_request_info_unref(info
);
1370 purple_account_request_authorization(PurpleAccount
*account
, const char *remote_user
,
1371 const char *id
, const char *alias
, const char *message
, gboolean on_list
,
1372 PurpleAccountRequestAuthorizationCb auth_cb
, PurpleAccountRequestAuthorizationCb deny_cb
, void *user_data
)
1374 PurpleAccountUiOps
*ui_ops
;
1375 PurpleAccountRequestInfo
*info
;
1378 g_return_val_if_fail(account
!= NULL
, NULL
);
1379 g_return_val_if_fail(remote_user
!= NULL
, NULL
);
1381 ui_ops
= purple_accounts_get_ui_ops();
1383 plugin_return
= GPOINTER_TO_INT(
1384 purple_signal_emit_return_1(purple_accounts_get_handle(),
1385 "account-authorization-requested", account
, remote_user
));
1387 if (plugin_return
> 0) {
1388 if (auth_cb
!= NULL
)
1391 } else if (plugin_return
< 0) {
1392 if (deny_cb
!= NULL
)
1397 if (ui_ops
!= NULL
&& ui_ops
->request_authorize
!= NULL
) {
1398 info
= g_new0(PurpleAccountRequestInfo
, 1);
1399 info
->type
= PURPLE_ACCOUNT_REQUEST_AUTHORIZATION
;
1400 info
->account
= account
;
1401 info
->auth_cb
= auth_cb
;
1402 info
->deny_cb
= deny_cb
;
1403 info
->userdata
= user_data
;
1404 info
->user
= g_strdup(remote_user
);
1405 info
->ref
= 2; /* We hold an extra ref to make sure info remains valid
1406 if any of the callbacks are called synchronously. We
1407 unref it after the function call */
1409 info
->ui_handle
= ui_ops
->request_authorize(account
, remote_user
, id
, alias
, message
,
1410 on_list
, request_auth_cb
, request_deny_cb
, info
);
1412 info
= purple_account_request_info_unref(info
);
1414 handles
= g_list_append(handles
, info
);
1415 return info
->ui_handle
;
1423 change_password_cb(PurpleAccount
*account
, PurpleRequestFields
*fields
)
1425 const char *orig_pass
, *new_pass_1
, *new_pass_2
;
1427 orig_pass
= purple_request_fields_get_string(fields
, "password");
1428 new_pass_1
= purple_request_fields_get_string(fields
, "new_password_1");
1429 new_pass_2
= purple_request_fields_get_string(fields
, "new_password_2");
1431 if (g_utf8_collate(new_pass_1
, new_pass_2
))
1433 purple_notify_error(account
, NULL
,
1434 _("New passwords do not match."), NULL
);
1439 if ((purple_request_fields_is_field_required(fields
, "password") &&
1440 (orig_pass
== NULL
|| *orig_pass
== '\0')) ||
1441 (purple_request_fields_is_field_required(fields
, "new_password_1") &&
1442 (new_pass_1
== NULL
|| *new_pass_1
== '\0')) ||
1443 (purple_request_fields_is_field_required(fields
, "new_password_2") &&
1444 (new_pass_2
== NULL
|| *new_pass_2
== '\0')))
1446 purple_notify_error(account
, NULL
,
1447 _("Fill out all fields completely."), NULL
);
1451 purple_account_change_password(account
, orig_pass
, new_pass_1
);
1455 purple_account_request_change_password(PurpleAccount
*account
)
1457 PurpleRequestFields
*fields
;
1458 PurpleRequestFieldGroup
*group
;
1459 PurpleRequestField
*field
;
1460 PurpleConnection
*gc
;
1461 PurplePlugin
*prpl
= NULL
;
1462 PurplePluginProtocolInfo
*prpl_info
= NULL
;
1465 g_return_if_fail(account
!= NULL
);
1466 g_return_if_fail(purple_account_is_connected(account
));
1468 gc
= purple_account_get_connection(account
);
1470 prpl
= purple_connection_get_prpl(gc
);
1472 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
1474 fields
= purple_request_fields_new();
1476 group
= purple_request_field_group_new(NULL
);
1477 purple_request_fields_add_group(fields
, group
);
1479 field
= purple_request_field_string_new("password", _("Original password"),
1481 purple_request_field_string_set_masked(field
, TRUE
);
1482 if (!(prpl_info
&& (prpl_info
->options
| OPT_PROTO_PASSWORD_OPTIONAL
)))
1483 purple_request_field_set_required(field
, TRUE
);
1484 purple_request_field_group_add_field(group
, field
);
1486 field
= purple_request_field_string_new("new_password_1",
1489 purple_request_field_string_set_masked(field
, TRUE
);
1490 if (!(prpl_info
&& (prpl_info
->options
| OPT_PROTO_PASSWORD_OPTIONAL
)))
1491 purple_request_field_set_required(field
, TRUE
);
1492 purple_request_field_group_add_field(group
, field
);
1494 field
= purple_request_field_string_new("new_password_2",
1495 _("New password (again)"),
1497 purple_request_field_string_set_masked(field
, TRUE
);
1498 if (!(prpl_info
&& (prpl_info
->options
| OPT_PROTO_PASSWORD_OPTIONAL
)))
1499 purple_request_field_set_required(field
, TRUE
);
1500 purple_request_field_group_add_field(group
, field
);
1502 g_snprintf(primary
, sizeof(primary
), _("Change password for %s"),
1503 purple_account_get_username(account
));
1505 /* I'm sticking this somewhere in the code: bologna */
1507 purple_request_fields(purple_account_get_connection(account
),
1510 _("Please enter your current password and your "
1513 _("OK"), G_CALLBACK(change_password_cb
),
1515 account
, NULL
, NULL
,
1520 set_user_info_cb(PurpleAccount
*account
, const char *user_info
)
1522 PurpleConnection
*gc
;
1524 purple_account_set_user_info(account
, user_info
);
1525 gc
= purple_account_get_connection(account
);
1526 serv_set_info(gc
, user_info
);
1530 purple_account_request_change_user_info(PurpleAccount
*account
)
1532 PurpleConnection
*gc
;
1535 g_return_if_fail(account
!= NULL
);
1536 g_return_if_fail(purple_account_is_connected(account
));
1538 gc
= purple_account_get_connection(account
);
1540 g_snprintf(primary
, sizeof(primary
),
1541 _("Change user information for %s"),
1542 purple_account_get_username(account
));
1544 purple_request_input(gc
, _("Set User Info"), primary
, NULL
,
1545 purple_account_get_user_info(account
),
1546 TRUE
, FALSE
, ((gc
!= NULL
) &&
1547 (gc
->flags
& PURPLE_CONNECTION_HTML
) ? "html" : NULL
),
1548 _("Save"), G_CALLBACK(set_user_info_cb
),
1550 account
, NULL
, NULL
,
1555 purple_account_set_username(PurpleAccount
*account
, const char *username
)
1557 PurpleBlistUiOps
*blist_ops
;
1559 g_return_if_fail(account
!= NULL
);
1561 g_free(account
->username
);
1562 account
->username
= g_strdup(username
);
1564 schedule_accounts_save();
1566 /* if the name changes, we should re-write the buddy list
1567 * to disk with the new name */
1568 blist_ops
= purple_blist_get_ui_ops();
1569 if (blist_ops
!= NULL
&& blist_ops
->save_account
!= NULL
)
1570 blist_ops
->save_account(account
);
1574 purple_account_set_password(PurpleAccount
*account
, const char *password
)
1576 g_return_if_fail(account
!= NULL
);
1578 g_free(account
->password
);
1579 account
->password
= g_strdup(password
);
1581 schedule_accounts_save();
1585 purple_account_set_alias(PurpleAccount
*account
, const char *alias
)
1587 g_return_if_fail(account
!= NULL
);
1590 * Do nothing if alias and account->alias are both NULL. Or if
1591 * they're the exact same string.
1593 if (alias
== account
->alias
)
1596 if ((!alias
&& account
->alias
) || (alias
&& !account
->alias
) ||
1597 g_utf8_collate(account
->alias
, alias
))
1599 char *old
= account
->alias
;
1601 account
->alias
= g_strdup(alias
);
1602 purple_signal_emit(purple_accounts_get_handle(), "account-alias-changed",
1606 schedule_accounts_save();
1611 purple_account_set_user_info(PurpleAccount
*account
, const char *user_info
)
1613 g_return_if_fail(account
!= NULL
);
1615 g_free(account
->user_info
);
1616 account
->user_info
= g_strdup(user_info
);
1618 schedule_accounts_save();
1621 void purple_account_set_buddy_icon_path(PurpleAccount
*account
, const char *path
)
1623 g_return_if_fail(account
!= NULL
);
1625 g_free(account
->buddy_icon_path
);
1626 account
->buddy_icon_path
= g_strdup(path
);
1628 schedule_accounts_save();
1632 purple_account_set_protocol_id(PurpleAccount
*account
, const char *protocol_id
)
1634 g_return_if_fail(account
!= NULL
);
1635 g_return_if_fail(protocol_id
!= NULL
);
1637 g_free(account
->protocol_id
);
1638 account
->protocol_id
= g_strdup(protocol_id
);
1640 schedule_accounts_save();
1644 purple_account_set_connection(PurpleAccount
*account
, PurpleConnection
*gc
)
1646 g_return_if_fail(account
!= NULL
);
1652 purple_account_set_remember_password(PurpleAccount
*account
, gboolean value
)
1654 g_return_if_fail(account
!= NULL
);
1656 account
->remember_pass
= value
;
1658 schedule_accounts_save();
1662 purple_account_set_check_mail(PurpleAccount
*account
, gboolean value
)
1664 g_return_if_fail(account
!= NULL
);
1666 purple_account_set_bool(account
, "check-mail", value
);
1670 purple_account_set_enabled(PurpleAccount
*account
, const char *ui
,
1673 PurpleConnection
*gc
;
1674 gboolean was_enabled
= FALSE
;
1676 g_return_if_fail(account
!= NULL
);
1677 g_return_if_fail(ui
!= NULL
);
1679 was_enabled
= purple_account_get_enabled(account
, ui
);
1681 purple_account_set_ui_bool(account
, ui
, "auto-login", value
);
1682 gc
= purple_account_get_connection(account
);
1684 if(was_enabled
&& !value
)
1685 purple_signal_emit(purple_accounts_get_handle(), "account-disabled", account
);
1686 else if(!was_enabled
&& value
)
1687 purple_signal_emit(purple_accounts_get_handle(), "account-enabled", account
);
1689 if ((gc
!= NULL
) && (gc
->wants_to_die
== TRUE
))
1692 if (value
&& purple_presence_is_online(account
->presence
))
1693 purple_account_connect(account
);
1694 else if (!value
&& !purple_account_is_disconnected(account
))
1695 purple_account_disconnect(account
);
1699 purple_account_set_proxy_info(PurpleAccount
*account
, PurpleProxyInfo
*info
)
1701 g_return_if_fail(account
!= NULL
);
1703 if (account
->proxy_info
!= NULL
)
1704 purple_proxy_info_destroy(account
->proxy_info
);
1706 account
->proxy_info
= info
;
1708 schedule_accounts_save();
1712 purple_account_set_privacy_type(PurpleAccount
*account
, PurplePrivacyType privacy_type
)
1714 g_return_if_fail(account
!= NULL
);
1716 account
->perm_deny
= privacy_type
;
1720 purple_account_set_status_types(PurpleAccount
*account
, GList
*status_types
)
1722 g_return_if_fail(account
!= NULL
);
1724 /* Out with the old... */
1725 if (account
->status_types
!= NULL
)
1727 g_list_foreach(account
->status_types
, (GFunc
)purple_status_type_destroy
, NULL
);
1728 g_list_free(account
->status_types
);
1731 /* In with the new... */
1732 account
->status_types
= status_types
;
1736 purple_account_set_status(PurpleAccount
*account
, const char *status_id
,
1737 gboolean active
, ...)
1739 GList
*attrs
= NULL
;
1744 va_start(args
, active
);
1745 while ((id
= va_arg(args
, const char *)) != NULL
)
1747 attrs
= g_list_append(attrs
, (char *)id
);
1748 data
= va_arg(args
, void *);
1749 attrs
= g_list_append(attrs
, data
);
1751 purple_account_set_status_list(account
, status_id
, active
, attrs
);
1757 purple_account_set_status_list(PurpleAccount
*account
, const char *status_id
,
1758 gboolean active
, GList
*attrs
)
1760 PurpleStatus
*status
;
1762 g_return_if_fail(account
!= NULL
);
1763 g_return_if_fail(status_id
!= NULL
);
1765 status
= purple_account_get_status(account
, status_id
);
1768 purple_debug_error("account",
1769 "Invalid status ID '%s' for account %s (%s)\n",
1770 status_id
, purple_account_get_username(account
),
1771 purple_account_get_protocol_id(account
));
1775 if (active
|| purple_status_is_independent(status
))
1776 purple_status_set_active_with_attrs_list(status
, active
, attrs
);
1779 * Our current statuses are saved to accounts.xml (so that when we
1780 * reconnect, we go back to the previous status).
1782 schedule_accounts_save();
1785 struct public_alias_closure
1787 PurpleAccount
*account
;
1788 gpointer failure_cb
;
1792 set_public_alias_unsupported(gpointer data
)
1794 struct public_alias_closure
*closure
= data
;
1795 PurpleSetPublicAliasFailureCallback failure_cb
= closure
->failure_cb
;
1797 failure_cb(closure
->account
,
1798 _("This protocol does not support setting a public alias."));
1805 purple_account_set_public_alias(PurpleAccount
*account
,
1806 const char *alias
, PurpleSetPublicAliasSuccessCallback success_cb
,
1807 PurpleSetPublicAliasFailureCallback failure_cb
)
1809 PurpleConnection
*gc
;
1810 PurplePlugin
*prpl
= NULL
;
1811 PurplePluginProtocolInfo
*prpl_info
= NULL
;
1813 g_return_if_fail(account
!= NULL
);
1814 g_return_if_fail(purple_account_is_connected(account
));
1816 gc
= purple_account_get_connection(account
);
1817 prpl
= purple_connection_get_prpl(gc
);
1818 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
1820 if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, set_public_alias
))
1821 prpl_info
->set_public_alias(gc
, alias
, success_cb
, failure_cb
);
1822 else if (failure_cb
) {
1823 struct public_alias_closure
*closure
=
1824 g_new0(struct public_alias_closure
, 1);
1825 closure
->account
= account
;
1826 closure
->failure_cb
= failure_cb
;
1827 purple_timeout_add(0, set_public_alias_unsupported
, closure
);
1832 get_public_alias_unsupported(gpointer data
)
1834 struct public_alias_closure
*closure
= data
;
1835 PurpleGetPublicAliasFailureCallback failure_cb
= closure
->failure_cb
;
1837 failure_cb(closure
->account
,
1838 _("This protocol does not support fetching the public alias."));
1845 purple_account_get_public_alias(PurpleAccount
*account
,
1846 PurpleGetPublicAliasSuccessCallback success_cb
,
1847 PurpleGetPublicAliasFailureCallback failure_cb
)
1849 PurpleConnection
*gc
;
1850 PurplePlugin
*prpl
= NULL
;
1851 PurplePluginProtocolInfo
*prpl_info
= NULL
;
1853 g_return_if_fail(account
!= NULL
);
1854 g_return_if_fail(purple_account_is_connected(account
));
1856 gc
= purple_account_get_connection(account
);
1857 prpl
= purple_connection_get_prpl(gc
);
1858 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
1860 if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info
, get_public_alias
))
1861 prpl_info
->get_public_alias(gc
, success_cb
, failure_cb
);
1862 else if (failure_cb
) {
1863 struct public_alias_closure
*closure
=
1864 g_new0(struct public_alias_closure
, 1);
1865 closure
->account
= account
;
1866 closure
->failure_cb
= failure_cb
;
1867 purple_timeout_add(0, get_public_alias_unsupported
, closure
);
1872 purple_account_clear_settings(PurpleAccount
*account
)
1874 g_return_if_fail(account
!= NULL
);
1876 g_hash_table_destroy(account
->settings
);
1878 account
->settings
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
1879 g_free
, delete_setting
);
1883 purple_account_remove_setting(PurpleAccount
*account
, const char *setting
)
1885 g_return_if_fail(account
!= NULL
);
1886 g_return_if_fail(setting
!= NULL
);
1888 g_hash_table_remove(account
->settings
, setting
);
1892 purple_account_set_int(PurpleAccount
*account
, const char *name
, int value
)
1894 PurpleAccountSetting
*setting
;
1896 g_return_if_fail(account
!= NULL
);
1897 g_return_if_fail(name
!= NULL
);
1899 setting
= g_new0(PurpleAccountSetting
, 1);
1901 setting
->type
= PURPLE_PREF_INT
;
1902 setting
->value
.integer
= value
;
1904 g_hash_table_insert(account
->settings
, g_strdup(name
), setting
);
1906 schedule_accounts_save();
1910 purple_account_set_string(PurpleAccount
*account
, const char *name
,
1913 PurpleAccountSetting
*setting
;
1915 g_return_if_fail(account
!= NULL
);
1916 g_return_if_fail(name
!= NULL
);
1918 setting
= g_new0(PurpleAccountSetting
, 1);
1920 setting
->type
= PURPLE_PREF_STRING
;
1921 setting
->value
.string
= g_strdup(value
);
1923 g_hash_table_insert(account
->settings
, g_strdup(name
), setting
);
1925 schedule_accounts_save();
1929 purple_account_set_bool(PurpleAccount
*account
, const char *name
, gboolean value
)
1931 PurpleAccountSetting
*setting
;
1933 g_return_if_fail(account
!= NULL
);
1934 g_return_if_fail(name
!= NULL
);
1936 setting
= g_new0(PurpleAccountSetting
, 1);
1938 setting
->type
= PURPLE_PREF_BOOLEAN
;
1939 setting
->value
.boolean
= value
;
1941 g_hash_table_insert(account
->settings
, g_strdup(name
), setting
);
1943 schedule_accounts_save();
1947 get_ui_settings_table(PurpleAccount
*account
, const char *ui
)
1951 table
= g_hash_table_lookup(account
->ui_settings
, ui
);
1953 if (table
== NULL
) {
1954 table
= g_hash_table_new_full(g_str_hash
, g_str_equal
, g_free
,
1956 g_hash_table_insert(account
->ui_settings
, g_strdup(ui
), table
);
1963 purple_account_set_ui_int(PurpleAccount
*account
, const char *ui
,
1964 const char *name
, int value
)
1966 PurpleAccountSetting
*setting
;
1969 g_return_if_fail(account
!= NULL
);
1970 g_return_if_fail(ui
!= NULL
);
1971 g_return_if_fail(name
!= NULL
);
1973 setting
= g_new0(PurpleAccountSetting
, 1);
1975 setting
->type
= PURPLE_PREF_INT
;
1976 setting
->ui
= g_strdup(ui
);
1977 setting
->value
.integer
= value
;
1979 table
= get_ui_settings_table(account
, ui
);
1981 g_hash_table_insert(table
, g_strdup(name
), setting
);
1983 schedule_accounts_save();
1987 purple_account_set_ui_string(PurpleAccount
*account
, const char *ui
,
1988 const char *name
, const char *value
)
1990 PurpleAccountSetting
*setting
;
1993 g_return_if_fail(account
!= NULL
);
1994 g_return_if_fail(ui
!= NULL
);
1995 g_return_if_fail(name
!= NULL
);
1997 setting
= g_new0(PurpleAccountSetting
, 1);
1999 setting
->type
= PURPLE_PREF_STRING
;
2000 setting
->ui
= g_strdup(ui
);
2001 setting
->value
.string
= g_strdup(value
);
2003 table
= get_ui_settings_table(account
, ui
);
2005 g_hash_table_insert(table
, g_strdup(name
), setting
);
2007 schedule_accounts_save();
2011 purple_account_set_ui_bool(PurpleAccount
*account
, const char *ui
,
2012 const char *name
, gboolean value
)
2014 PurpleAccountSetting
*setting
;
2017 g_return_if_fail(account
!= NULL
);
2018 g_return_if_fail(ui
!= NULL
);
2019 g_return_if_fail(name
!= NULL
);
2021 setting
= g_new0(PurpleAccountSetting
, 1);
2023 setting
->type
= PURPLE_PREF_BOOLEAN
;
2024 setting
->ui
= g_strdup(ui
);
2025 setting
->value
.boolean
= value
;
2027 table
= get_ui_settings_table(account
, ui
);
2029 g_hash_table_insert(table
, g_strdup(name
), setting
);
2031 schedule_accounts_save();
2034 static PurpleConnectionState
2035 purple_account_get_state(const PurpleAccount
*account
)
2037 PurpleConnection
*gc
;
2039 g_return_val_if_fail(account
!= NULL
, PURPLE_DISCONNECTED
);
2041 gc
= purple_account_get_connection(account
);
2043 return PURPLE_DISCONNECTED
;
2045 return purple_connection_get_state(gc
);
2049 purple_account_is_connected(const PurpleAccount
*account
)
2051 return (purple_account_get_state(account
) == PURPLE_CONNECTED
);
2055 purple_account_is_connecting(const PurpleAccount
*account
)
2057 return (purple_account_get_state(account
) == PURPLE_CONNECTING
);
2061 purple_account_is_disconnected(const PurpleAccount
*account
)
2063 return (purple_account_get_state(account
) == PURPLE_DISCONNECTED
);
2067 purple_account_get_username(const PurpleAccount
*account
)
2069 g_return_val_if_fail(account
!= NULL
, NULL
);
2071 return account
->username
;
2075 purple_account_get_password(const PurpleAccount
*account
)
2077 g_return_val_if_fail(account
!= NULL
, NULL
);
2079 return account
->password
;
2083 purple_account_get_alias(const PurpleAccount
*account
)
2085 g_return_val_if_fail(account
!= NULL
, NULL
);
2087 return account
->alias
;
2091 purple_account_get_user_info(const PurpleAccount
*account
)
2093 g_return_val_if_fail(account
!= NULL
, NULL
);
2095 return account
->user_info
;
2099 purple_account_get_buddy_icon_path(const PurpleAccount
*account
)
2101 g_return_val_if_fail(account
!= NULL
, NULL
);
2103 return account
->buddy_icon_path
;
2107 purple_account_get_protocol_id(const PurpleAccount
*account
)
2109 g_return_val_if_fail(account
!= NULL
, NULL
);
2110 return account
->protocol_id
;
2114 purple_account_get_protocol_name(const PurpleAccount
*account
)
2118 g_return_val_if_fail(account
!= NULL
, NULL
);
2120 p
= purple_find_prpl(purple_account_get_protocol_id(account
));
2122 return ((p
&& p
->info
->name
) ? _(p
->info
->name
) : _("Unknown"));
2126 purple_account_get_connection(const PurpleAccount
*account
)
2128 g_return_val_if_fail(account
!= NULL
, NULL
);
2134 purple_account_get_name_for_display(const PurpleAccount
*account
)
2136 PurpleBuddy
*self
= NULL
;
2137 PurpleConnection
*gc
= NULL
;
2138 const gchar
*name
= NULL
, *username
= NULL
, *displayname
= NULL
;
2140 name
= purple_account_get_alias(account
);
2146 username
= purple_account_get_username(account
);
2147 self
= purple_find_buddy((PurpleAccount
*)account
, username
);
2150 const gchar
*calias
= purple_buddy_get_contact_alias(self
);
2152 /* We don't want to return the buddy name if the buddy/contact
2153 * doesn't have an alias set. */
2154 if (!purple_strequal(username
, calias
)) {
2159 gc
= purple_account_get_connection(account
);
2160 displayname
= purple_connection_get_display_name(gc
);
2170 purple_account_get_remember_password(const PurpleAccount
*account
)
2172 g_return_val_if_fail(account
!= NULL
, FALSE
);
2174 return account
->remember_pass
;
2178 purple_account_get_check_mail(const PurpleAccount
*account
)
2180 g_return_val_if_fail(account
!= NULL
, FALSE
);
2182 return purple_account_get_bool(account
, "check-mail", FALSE
);
2186 purple_account_get_enabled(const PurpleAccount
*account
, const char *ui
)
2188 g_return_val_if_fail(account
!= NULL
, FALSE
);
2189 g_return_val_if_fail(ui
!= NULL
, FALSE
);
2191 return purple_account_get_ui_bool(account
, ui
, "auto-login", FALSE
);
2195 purple_account_get_proxy_info(const PurpleAccount
*account
)
2197 g_return_val_if_fail(account
!= NULL
, NULL
);
2199 return account
->proxy_info
;
2203 purple_account_get_privacy_type(const PurpleAccount
*account
)
2205 g_return_val_if_fail(account
!= NULL
, PURPLE_PRIVACY_ALLOW_ALL
);
2207 return account
->perm_deny
;
2211 purple_account_get_active_status(const PurpleAccount
*account
)
2213 g_return_val_if_fail(account
!= NULL
, NULL
);
2215 return purple_presence_get_active_status(account
->presence
);
2219 purple_account_get_status(const PurpleAccount
*account
, const char *status_id
)
2221 g_return_val_if_fail(account
!= NULL
, NULL
);
2222 g_return_val_if_fail(status_id
!= NULL
, NULL
);
2224 return purple_presence_get_status(account
->presence
, status_id
);
2228 purple_account_get_status_type(const PurpleAccount
*account
, const char *id
)
2232 g_return_val_if_fail(account
!= NULL
, NULL
);
2233 g_return_val_if_fail(id
!= NULL
, NULL
);
2235 for (l
= purple_account_get_status_types(account
); l
!= NULL
; l
= l
->next
)
2237 PurpleStatusType
*status_type
= (PurpleStatusType
*)l
->data
;
2239 if (purple_strequal(purple_status_type_get_id(status_type
), id
))
2247 purple_account_get_status_type_with_primitive(const PurpleAccount
*account
, PurpleStatusPrimitive primitive
)
2251 g_return_val_if_fail(account
!= NULL
, NULL
);
2253 for (l
= purple_account_get_status_types(account
); l
!= NULL
; l
= l
->next
)
2255 PurpleStatusType
*status_type
= (PurpleStatusType
*)l
->data
;
2257 if (purple_status_type_get_primitive(status_type
) == primitive
)
2265 purple_account_get_presence(const PurpleAccount
*account
)
2267 g_return_val_if_fail(account
!= NULL
, NULL
);
2269 return account
->presence
;
2273 purple_account_is_status_active(const PurpleAccount
*account
,
2274 const char *status_id
)
2276 g_return_val_if_fail(account
!= NULL
, FALSE
);
2277 g_return_val_if_fail(status_id
!= NULL
, FALSE
);
2279 return purple_presence_is_status_active(account
->presence
, status_id
);
2283 purple_account_get_status_types(const PurpleAccount
*account
)
2285 g_return_val_if_fail(account
!= NULL
, NULL
);
2287 return account
->status_types
;
2291 purple_account_get_int(const PurpleAccount
*account
, const char *name
,
2294 PurpleAccountSetting
*setting
;
2296 g_return_val_if_fail(account
!= NULL
, default_value
);
2297 g_return_val_if_fail(name
!= NULL
, default_value
);
2299 setting
= g_hash_table_lookup(account
->settings
, name
);
2301 if (setting
== NULL
)
2302 return default_value
;
2304 g_return_val_if_fail(setting
->type
== PURPLE_PREF_INT
, default_value
);
2306 return setting
->value
.integer
;
2310 purple_account_get_string(const PurpleAccount
*account
, const char *name
,
2311 const char *default_value
)
2313 PurpleAccountSetting
*setting
;
2315 g_return_val_if_fail(account
!= NULL
, default_value
);
2316 g_return_val_if_fail(name
!= NULL
, default_value
);
2318 setting
= g_hash_table_lookup(account
->settings
, name
);
2320 if (setting
== NULL
)
2321 return default_value
;
2323 g_return_val_if_fail(setting
->type
== PURPLE_PREF_STRING
, default_value
);
2325 return setting
->value
.string
;
2329 purple_account_get_bool(const PurpleAccount
*account
, const char *name
,
2330 gboolean default_value
)
2332 PurpleAccountSetting
*setting
;
2334 g_return_val_if_fail(account
!= NULL
, default_value
);
2335 g_return_val_if_fail(name
!= NULL
, default_value
);
2337 setting
= g_hash_table_lookup(account
->settings
, name
);
2339 if (setting
== NULL
)
2340 return default_value
;
2342 g_return_val_if_fail(setting
->type
== PURPLE_PREF_BOOLEAN
, default_value
);
2344 return setting
->value
.boolean
;
2348 purple_account_get_ui_int(const PurpleAccount
*account
, const char *ui
,
2349 const char *name
, int default_value
)
2351 PurpleAccountSetting
*setting
;
2354 g_return_val_if_fail(account
!= NULL
, default_value
);
2355 g_return_val_if_fail(ui
!= NULL
, default_value
);
2356 g_return_val_if_fail(name
!= NULL
, default_value
);
2358 if ((table
= g_hash_table_lookup(account
->ui_settings
, ui
)) == NULL
)
2359 return default_value
;
2361 if ((setting
= g_hash_table_lookup(table
, name
)) == NULL
)
2362 return default_value
;
2364 g_return_val_if_fail(setting
->type
== PURPLE_PREF_INT
, default_value
);
2366 return setting
->value
.integer
;
2370 purple_account_get_ui_string(const PurpleAccount
*account
, const char *ui
,
2371 const char *name
, const char *default_value
)
2373 PurpleAccountSetting
*setting
;
2376 g_return_val_if_fail(account
!= NULL
, default_value
);
2377 g_return_val_if_fail(ui
!= NULL
, default_value
);
2378 g_return_val_if_fail(name
!= NULL
, default_value
);
2380 if ((table
= g_hash_table_lookup(account
->ui_settings
, ui
)) == NULL
)
2381 return default_value
;
2383 if ((setting
= g_hash_table_lookup(table
, name
)) == NULL
)
2384 return default_value
;
2386 g_return_val_if_fail(setting
->type
== PURPLE_PREF_STRING
, default_value
);
2388 return setting
->value
.string
;
2392 purple_account_get_ui_bool(const PurpleAccount
*account
, const char *ui
,
2393 const char *name
, gboolean default_value
)
2395 PurpleAccountSetting
*setting
;
2398 g_return_val_if_fail(account
!= NULL
, default_value
);
2399 g_return_val_if_fail(ui
!= NULL
, default_value
);
2400 g_return_val_if_fail(name
!= NULL
, default_value
);
2402 if ((table
= g_hash_table_lookup(account
->ui_settings
, ui
)) == NULL
)
2403 return default_value
;
2405 if ((setting
= g_hash_table_lookup(table
, name
)) == NULL
)
2406 return default_value
;
2408 g_return_val_if_fail(setting
->type
== PURPLE_PREF_BOOLEAN
, default_value
);
2410 return setting
->value
.boolean
;
2414 purple_account_get_log(PurpleAccount
*account
, gboolean create
)
2416 g_return_val_if_fail(account
!= NULL
, NULL
);
2418 if(!account
->system_log
&& create
){
2419 PurplePresence
*presence
;
2422 presence
= purple_account_get_presence(account
);
2423 login_time
= purple_presence_get_login_time(presence
);
2425 account
->system_log
= purple_log_new(PURPLE_LOG_SYSTEM
,
2426 purple_account_get_username(account
), account
, NULL
,
2427 (login_time
!= 0) ? login_time
: time(NULL
), NULL
);
2430 return account
->system_log
;
2434 purple_account_destroy_log(PurpleAccount
*account
)
2436 g_return_if_fail(account
!= NULL
);
2438 if(account
->system_log
){
2439 purple_log_free(account
->system_log
);
2440 account
->system_log
= NULL
;
2445 purple_account_add_buddy(PurpleAccount
*account
, PurpleBuddy
*buddy
)
2447 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2448 PurpleConnection
*gc
;
2449 PurplePlugin
*prpl
= NULL
;
2451 g_return_if_fail(account
!= NULL
);
2452 g_return_if_fail(buddy
!= NULL
);
2454 gc
= purple_account_get_connection(account
);
2456 prpl
= purple_connection_get_prpl(gc
);
2459 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2461 if (prpl_info
!= NULL
&& prpl_info
->add_buddy
!= NULL
)
2462 prpl_info
->add_buddy(gc
, buddy
, purple_buddy_get_group(buddy
));
2466 purple_account_add_buddies(PurpleAccount
*account
, GList
*buddies
)
2468 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2469 PurpleConnection
*gc
= purple_account_get_connection(account
);
2470 PurplePlugin
*prpl
= NULL
;
2473 prpl
= purple_connection_get_prpl(gc
);
2476 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2479 GList
*cur
, *groups
= NULL
;
2481 /* Make a list of what group each buddy is in */
2482 for (cur
= buddies
; cur
!= NULL
; cur
= cur
->next
) {
2483 PurpleBuddy
*buddy
= cur
->data
;
2484 groups
= g_list_append(groups
, purple_buddy_get_group(buddy
));
2487 if (prpl_info
->add_buddies
!= NULL
)
2488 prpl_info
->add_buddies(gc
, buddies
, groups
);
2489 else if (prpl_info
->add_buddy
!= NULL
) {
2490 GList
*curb
= buddies
, *curg
= groups
;
2492 while ((curb
!= NULL
) && (curg
!= NULL
)) {
2493 prpl_info
->add_buddy(gc
, curb
->data
, curg
->data
);
2499 g_list_free(groups
);
2504 purple_account_remove_buddy(PurpleAccount
*account
, PurpleBuddy
*buddy
,
2507 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2508 PurpleConnection
*gc
= purple_account_get_connection(account
);
2509 PurplePlugin
*prpl
= NULL
;
2512 prpl
= purple_connection_get_prpl(gc
);
2515 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2517 if (prpl_info
&& prpl_info
->remove_buddy
)
2518 prpl_info
->remove_buddy(gc
, buddy
, group
);
2522 purple_account_remove_buddies(PurpleAccount
*account
, GList
*buddies
, GList
*groups
)
2524 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2525 PurpleConnection
*gc
= purple_account_get_connection(account
);
2526 PurplePlugin
*prpl
= NULL
;
2529 prpl
= purple_connection_get_prpl(gc
);
2532 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2535 if (prpl_info
->remove_buddies
)
2536 prpl_info
->remove_buddies(gc
, buddies
, groups
);
2538 GList
*curb
= buddies
;
2539 GList
*curg
= groups
;
2540 while ((curb
!= NULL
) && (curg
!= NULL
)) {
2541 purple_account_remove_buddy(account
, curb
->data
, curg
->data
);
2550 purple_account_remove_group(PurpleAccount
*account
, PurpleGroup
*group
)
2552 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2553 PurpleConnection
*gc
= purple_account_get_connection(account
);
2554 PurplePlugin
*prpl
= NULL
;
2557 prpl
= purple_connection_get_prpl(gc
);
2560 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2562 if (prpl_info
&& prpl_info
->remove_group
)
2563 prpl_info
->remove_group(gc
, group
);
2567 purple_account_change_password(PurpleAccount
*account
, const char *orig_pw
,
2570 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2571 PurpleConnection
*gc
= purple_account_get_connection(account
);
2572 PurplePlugin
*prpl
= NULL
;
2574 purple_account_set_password(account
, new_pw
);
2577 prpl
= purple_connection_get_prpl(gc
);
2580 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2582 if (prpl_info
&& prpl_info
->change_passwd
)
2583 prpl_info
->change_passwd(gc
, orig_pw
, new_pw
);
2586 gboolean
purple_account_supports_offline_message(PurpleAccount
*account
, PurpleBuddy
*buddy
)
2588 PurpleConnection
*gc
;
2589 PurplePluginProtocolInfo
*prpl_info
= NULL
;
2590 PurplePlugin
*prpl
= NULL
;
2592 g_return_val_if_fail(account
, FALSE
);
2593 g_return_val_if_fail(buddy
, FALSE
);
2595 gc
= purple_account_get_connection(account
);
2599 prpl
= purple_connection_get_prpl(gc
);
2602 prpl_info
= PURPLE_PLUGIN_PROTOCOL_INFO(prpl
);
2604 if (!prpl_info
|| !prpl_info
->offline_message
)
2606 return prpl_info
->offline_message(buddy
);
2610 signed_on_cb(PurpleConnection
*gc
,
2613 PurpleAccount
*account
= purple_connection_get_account(gc
);
2614 purple_account_clear_current_error(account
);
2616 purple_signal_emit(purple_accounts_get_handle(), "account-signed-on",
2621 signed_off_cb(PurpleConnection
*gc
,
2624 PurpleAccount
*account
= purple_connection_get_account(gc
);
2626 purple_signal_emit(purple_accounts_get_handle(), "account-signed-off",
2631 set_current_error(PurpleAccount
*account
, PurpleConnectionErrorInfo
*new_err
)
2633 PurpleAccountPrivate
*priv
;
2634 PurpleConnectionErrorInfo
*old_err
;
2636 g_return_if_fail(account
!= NULL
);
2638 priv
= PURPLE_ACCOUNT_GET_PRIVATE(account
);
2639 old_err
= priv
->current_error
;
2641 if(new_err
== old_err
)
2644 priv
->current_error
= new_err
;
2646 purple_signal_emit(purple_accounts_get_handle(),
2647 "account-error-changed",
2648 account
, old_err
, new_err
);
2649 schedule_accounts_save();
2652 g_free(old_err
->description
);
2654 PURPLE_DBUS_UNREGISTER_POINTER(old_err
);
2659 connection_error_cb(PurpleConnection
*gc
,
2660 PurpleConnectionError type
,
2661 const gchar
*description
,
2664 PurpleAccount
*account
;
2665 PurpleConnectionErrorInfo
*err
;
2667 account
= purple_connection_get_account(gc
);
2669 g_return_if_fail(account
!= NULL
);
2671 err
= g_new0(PurpleConnectionErrorInfo
, 1);
2672 PURPLE_DBUS_REGISTER_POINTER(err
, PurpleConnectionErrorInfo
);
2675 err
->description
= g_strdup(description
);
2677 set_current_error(account
, err
);
2679 purple_signal_emit(purple_accounts_get_handle(), "account-connection-error",
2680 account
, type
, description
);
2683 const PurpleConnectionErrorInfo
*
2684 purple_account_get_current_error(PurpleAccount
*account
)
2686 PurpleAccountPrivate
*priv
= PURPLE_ACCOUNT_GET_PRIVATE(account
);
2687 return priv
->current_error
;
2691 purple_account_clear_current_error(PurpleAccount
*account
)
2693 set_current_error(account
, NULL
);
2697 purple_accounts_add(PurpleAccount
*account
)
2699 g_return_if_fail(account
!= NULL
);
2701 if (g_list_find(accounts
, account
) != NULL
)
2704 accounts
= g_list_append(accounts
, account
);
2706 schedule_accounts_save();
2708 purple_signal_emit(purple_accounts_get_handle(), "account-added", account
);
2712 purple_accounts_remove(PurpleAccount
*account
)
2714 g_return_if_fail(account
!= NULL
);
2716 accounts
= g_list_remove(accounts
, account
);
2718 schedule_accounts_save();
2720 /* Clearing the error ensures that account-error-changed is emitted,
2721 * which is the end of the guarantee that the the error's pointer is
2724 purple_account_clear_current_error(account
);
2725 purple_signal_emit(purple_accounts_get_handle(), "account-removed", account
);
2729 purple_accounts_delete(PurpleAccount
*account
)
2731 PurpleBlistNode
*gnode
, *cnode
, *bnode
;
2734 g_return_if_fail(account
!= NULL
);
2737 * Disable the account before blowing it out of the water.
2738 * Conceptually it probably makes more sense to disable the
2739 * account for all UIs rather than the just the current UI,
2740 * but it doesn't really matter.
2742 purple_account_set_enabled(account
, purple_core_get_ui(), FALSE
);
2744 purple_notify_close_with_handle(account
);
2745 purple_request_close_with_handle(account
);
2747 purple_accounts_remove(account
);
2749 /* Remove this account's buddies */
2750 for (gnode
= purple_blist_get_root();
2752 gnode
= purple_blist_node_get_sibling_next(gnode
))
2754 if (!PURPLE_BLIST_NODE_IS_GROUP(gnode
))
2757 cnode
= purple_blist_node_get_first_child(gnode
);
2759 PurpleBlistNode
*cnode_next
= purple_blist_node_get_sibling_next(cnode
);
2761 if(PURPLE_BLIST_NODE_IS_CONTACT(cnode
)) {
2762 bnode
= purple_blist_node_get_first_child(cnode
);
2764 PurpleBlistNode
*bnode_next
= purple_blist_node_get_sibling_next(bnode
);
2766 if (PURPLE_BLIST_NODE_IS_BUDDY(bnode
)) {
2767 PurpleBuddy
*b
= (PurpleBuddy
*)bnode
;
2769 if (purple_buddy_get_account(b
) == account
)
2770 purple_blist_remove_buddy(b
);
2774 } else if (PURPLE_BLIST_NODE_IS_CHAT(cnode
)) {
2775 PurpleChat
*c
= (PurpleChat
*)cnode
;
2777 if (purple_chat_get_account(c
) == account
)
2778 purple_blist_remove_chat(c
);
2784 /* Remove any open conversation for this account */
2785 for (iter
= purple_get_conversations(); iter
; ) {
2786 PurpleConversation
*conv
= iter
->data
;
2788 if (purple_conversation_get_account(conv
) == account
)
2789 purple_conversation_destroy(conv
);
2792 /* Remove this account's pounces */
2793 purple_pounce_destroy_all_by_account(account
);
2795 /* This will cause the deletion of an old buddy icon. */
2796 purple_buddy_icons_set_account_icon(account
, NULL
, 0);
2798 purple_account_destroy(account
);
2802 purple_accounts_reorder(PurpleAccount
*account
, gint new_index
)
2807 g_return_if_fail(account
!= NULL
);
2808 g_return_if_fail(new_index
<= g_list_length(accounts
));
2810 index
= g_list_index(accounts
, account
);
2813 purple_debug_error("account",
2814 "Unregistered account (%s) discovered during reorder!\n",
2815 purple_account_get_username(account
));
2819 l
= g_list_nth(accounts
, index
);
2821 if (new_index
> index
)
2824 /* Remove the old one. */
2825 accounts
= g_list_delete_link(accounts
, l
);
2827 /* Insert it where it should go. */
2828 accounts
= g_list_insert(accounts
, account
, new_index
);
2830 schedule_accounts_save();
2834 purple_accounts_get_all(void)
2840 purple_accounts_get_all_active(void)
2843 GList
*all
= purple_accounts_get_all();
2845 while (all
!= NULL
) {
2846 PurpleAccount
*account
= all
->data
;
2848 if (purple_account_get_enabled(account
, purple_core_get_ui()))
2849 list
= g_list_append(list
, account
);
2858 purple_accounts_find(const char *name
, const char *protocol_id
)
2860 PurpleAccount
*account
= NULL
;
2864 g_return_val_if_fail(name
!= NULL
, NULL
);
2865 g_return_val_if_fail(protocol_id
!= NULL
, NULL
);
2867 for (l
= purple_accounts_get_all(); l
!= NULL
; l
= l
->next
) {
2868 account
= (PurpleAccount
*)l
->data
;
2869 if (!purple_strequal(account
->protocol_id
, protocol_id
))
2872 who
= g_strdup(purple_normalize(account
, name
));
2873 if (purple_strequal(purple_normalize(account
, purple_account_get_username(account
)), who
)) {
2884 purple_accounts_restore_current_statuses()
2887 PurpleAccount
*account
;
2889 /* If we're not connected to the Internet right now, we bail on this */
2890 if (!purple_network_is_available())
2892 purple_debug_warning("account", "Network not connected; skipping reconnect\n");
2896 for (l
= purple_accounts_get_all(); l
!= NULL
; l
= l
->next
)
2898 account
= (PurpleAccount
*)l
->data
;
2899 if (purple_account_get_enabled(account
, purple_core_get_ui()) &&
2900 (purple_presence_is_online(account
->presence
)))
2902 purple_account_connect(account
);
2908 purple_accounts_set_ui_ops(PurpleAccountUiOps
*ops
)
2910 account_ui_ops
= ops
;
2913 PurpleAccountUiOps
*
2914 purple_accounts_get_ui_ops(void)
2916 return account_ui_ops
;
2920 purple_accounts_get_handle(void)
2928 purple_accounts_init(void)
2930 void *handle
= purple_accounts_get_handle();
2931 void *conn_handle
= purple_connections_get_handle();
2933 purple_signal_register(handle
, "account-connecting",
2934 purple_marshal_VOID__POINTER
, NULL
, 1,
2935 purple_value_new(PURPLE_TYPE_SUBTYPE
,
2936 PURPLE_SUBTYPE_ACCOUNT
));
2938 purple_signal_register(handle
, "account-disabled",
2939 purple_marshal_VOID__POINTER
, NULL
, 1,
2940 purple_value_new(PURPLE_TYPE_SUBTYPE
,
2941 PURPLE_SUBTYPE_ACCOUNT
));
2943 purple_signal_register(handle
, "account-enabled",
2944 purple_marshal_VOID__POINTER
, NULL
, 1,
2945 purple_value_new(PURPLE_TYPE_SUBTYPE
,
2946 PURPLE_SUBTYPE_ACCOUNT
));
2948 purple_signal_register(handle
, "account-setting-info",
2949 purple_marshal_VOID__POINTER_POINTER
, NULL
, 2,
2950 purple_value_new(PURPLE_TYPE_SUBTYPE
,
2951 PURPLE_SUBTYPE_ACCOUNT
),
2952 purple_value_new(PURPLE_TYPE_STRING
));
2954 purple_signal_register(handle
, "account-set-info",
2955 purple_marshal_VOID__POINTER_POINTER
, NULL
, 2,
2956 purple_value_new(PURPLE_TYPE_SUBTYPE
,
2957 PURPLE_SUBTYPE_ACCOUNT
),
2958 purple_value_new(PURPLE_TYPE_STRING
));
2960 purple_signal_register(handle
, "account-created",
2961 purple_marshal_VOID__POINTER
, NULL
, 1,
2962 purple_value_new(PURPLE_TYPE_SUBTYPE
, PURPLE_SUBTYPE_ACCOUNT
));
2964 purple_signal_register(handle
, "account-destroying",
2965 purple_marshal_VOID__POINTER
, NULL
, 1,
2966 purple_value_new(PURPLE_TYPE_SUBTYPE
, PURPLE_SUBTYPE_ACCOUNT
));
2968 purple_signal_register(handle
, "account-added",
2969 purple_marshal_VOID__POINTER
, NULL
, 1,
2970 purple_value_new(PURPLE_TYPE_SUBTYPE
, PURPLE_SUBTYPE_ACCOUNT
));
2972 purple_signal_register(handle
, "account-removed",
2973 purple_marshal_VOID__POINTER
, NULL
, 1,
2974 purple_value_new(PURPLE_TYPE_SUBTYPE
, PURPLE_SUBTYPE_ACCOUNT
));
2976 purple_signal_register(handle
, "account-status-changed",
2977 purple_marshal_VOID__POINTER_POINTER_POINTER
, NULL
, 3,
2978 purple_value_new(PURPLE_TYPE_SUBTYPE
,
2979 PURPLE_SUBTYPE_ACCOUNT
),
2980 purple_value_new(PURPLE_TYPE_SUBTYPE
,
2981 PURPLE_SUBTYPE_STATUS
),
2982 purple_value_new(PURPLE_TYPE_SUBTYPE
,
2983 PURPLE_SUBTYPE_STATUS
));
2985 purple_signal_register(handle
, "account-actions-changed",
2986 purple_marshal_VOID__POINTER
, NULL
, 1,
2987 purple_value_new(PURPLE_TYPE_SUBTYPE
, PURPLE_SUBTYPE_ACCOUNT
));
2989 purple_signal_register(handle
, "account-alias-changed",
2990 purple_marshal_VOID__POINTER_POINTER
, NULL
, 2,
2991 purple_value_new(PURPLE_TYPE_SUBTYPE
,
2992 PURPLE_SUBTYPE_ACCOUNT
),
2993 purple_value_new(PURPLE_TYPE_STRING
));
2995 purple_signal_register(handle
, "account-authorization-requested",
2996 purple_marshal_INT__POINTER_POINTER
,
2997 purple_value_new(PURPLE_TYPE_INT
), 2,
2998 purple_value_new(PURPLE_TYPE_SUBTYPE
,
2999 PURPLE_SUBTYPE_ACCOUNT
),
3000 purple_value_new(PURPLE_TYPE_STRING
));
3002 purple_signal_register(handle
, "account-authorization-denied",
3003 purple_marshal_VOID__POINTER_POINTER
, NULL
, 2,
3004 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3005 PURPLE_SUBTYPE_ACCOUNT
),
3006 purple_value_new(PURPLE_TYPE_STRING
));
3008 purple_signal_register(handle
, "account-authorization-granted",
3009 purple_marshal_VOID__POINTER_POINTER
, NULL
, 2,
3010 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3011 PURPLE_SUBTYPE_ACCOUNT
),
3012 purple_value_new(PURPLE_TYPE_STRING
));
3014 purple_signal_register(handle
, "account-error-changed",
3015 purple_marshal_VOID__POINTER_POINTER_POINTER
,
3017 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3018 PURPLE_SUBTYPE_ACCOUNT
),
3019 purple_value_new(PURPLE_TYPE_POINTER
),
3020 purple_value_new(PURPLE_TYPE_POINTER
));
3022 purple_signal_register(handle
, "account-signed-on",
3023 purple_marshal_VOID__POINTER
, NULL
, 1,
3024 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3025 PURPLE_SUBTYPE_ACCOUNT
));
3027 purple_signal_register(handle
, "account-signed-off",
3028 purple_marshal_VOID__POINTER
, NULL
, 1,
3029 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3030 PURPLE_SUBTYPE_ACCOUNT
));
3032 purple_signal_register(handle
, "account-connection-error",
3033 purple_marshal_VOID__POINTER_INT_POINTER
, NULL
, 3,
3034 purple_value_new(PURPLE_TYPE_SUBTYPE
,
3035 PURPLE_SUBTYPE_ACCOUNT
),
3036 purple_value_new(PURPLE_TYPE_ENUM
),
3037 purple_value_new(PURPLE_TYPE_STRING
));
3039 purple_signal_connect(conn_handle
, "signed-on", handle
,
3040 PURPLE_CALLBACK(signed_on_cb
), NULL
);
3041 purple_signal_connect(conn_handle
, "signed-off", handle
,
3042 PURPLE_CALLBACK(signed_off_cb
), NULL
);
3043 purple_signal_connect(conn_handle
, "connection-error", handle
,
3044 PURPLE_CALLBACK(connection_error_cb
), NULL
);
3051 purple_accounts_uninit(void)
3053 gpointer handle
= purple_accounts_get_handle();
3054 if (save_timer
!= 0)
3056 purple_timeout_remove(save_timer
);
3061 for (; accounts
; accounts
= g_list_delete_link(accounts
, accounts
))
3062 purple_account_destroy(accounts
->data
);
3064 purple_signals_disconnect_by_handle(handle
);
3065 purple_signals_unregister_by_instance(handle
);