3 * Purple is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
22 #include "glibcompat.h"
39 * Structure representing an account.
48 char *username
; /* The username. */
49 char *alias
; /* How you appear to yourself. */
50 char *password
; /* The account password. */
51 char *user_info
; /* User information. */
53 char *buddy_icon_path
; /* The buddy icon's non-cached path. */
55 gboolean remember_pass
; /* Remember the password. */
58 * TODO: After a GObject representing a protocol is ready, use it
59 * here instead of the protocol ID.
61 char *protocol_id
; /* The ID of the protocol. */
63 PurpleConnection
*gc
; /* The connection handle. */
64 gboolean disconnecting
; /* The account is currently disconnecting */
66 GHashTable
*settings
; /* Protocol-specific settings. */
67 GHashTable
*ui_settings
; /* UI-specific settings. */
69 PurpleProxyInfo
*proxy_info
; /* Proxy information. This will be set */
70 /* to NULL when the account inherits */
71 /* proxy settings from global prefs. */
74 * TODO: Instead of linked lists for permit and deny, use a data
75 * structure that allows fast lookups AND decent performance when
76 * iterating through all items. Fast lookups should help performance
77 * for protocols like MSN, where all your buddies exist in your permit
78 * list therefore the permit list is large. Possibly GTree or
81 GSList
*permit
; /* Permit list. */
82 GSList
*deny
; /* Deny list. */
83 PurpleAccountPrivacyType privacy_type
; /* The permit/deny setting. */
85 GList
*status_types
; /* Status types. */
87 PurplePresence
*presence
; /* Presence. */
88 PurpleLog
*system_log
; /* The system log */
90 PurpleAccountRegistrationCb registration_cb
;
91 void *registration_cb_user_data
;
93 PurpleConnectionErrorInfo
*current_error
; /* Errors */
94 } PurpleAccountPrivate
;
101 } PurpleAccountSetting
;
105 PurpleAccountRequestType type
;
106 PurpleAccount
*account
;
110 PurpleAccountRequestAuthorizationCb auth_cb
;
111 PurpleAccountRequestAuthorizationCb deny_cb
;
113 } PurpleAccountRequestInfo
;
119 } PurpleCallbackBundle
;
121 /* GObject Property enums */
131 PROP_BUDDY_ICON_PATH
,
132 PROP_REMEMBER_PASSWORD
,
137 static GParamSpec
*properties
[PROP_LAST
];
138 static GList
*handles
= NULL
;
140 G_DEFINE_TYPE_WITH_PRIVATE(PurpleAccount
, purple_account
, G_TYPE_OBJECT
);
142 /******************************************************************************
144 *****************************************************************************/
146 purple_account_register_got_password_cb(PurpleAccount
*account
,
147 const gchar
*password
, GError
*error
, gpointer data
)
149 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
151 _purple_connection_new(account
, TRUE
, password
);
155 purple_account_register(PurpleAccount
*account
)
157 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
159 purple_debug_info("account", "Registering account %s\n",
160 purple_account_get_username(account
));
162 purple_keyring_get_password(account
,
163 purple_account_register_got_password_cb
, NULL
);
167 purple_account_unregister_got_password_cb(PurpleAccount
*account
,
168 const gchar
*password
, GError
*error
, gpointer data
)
170 PurpleCallbackBundle
*cbb
= data
;
171 PurpleAccountUnregistrationCb cb
;
173 cb
= (PurpleAccountUnregistrationCb
)cbb
->cb
;
174 _purple_connection_new_unregister(account
, password
, cb
, cbb
->data
);
179 struct register_completed_closure
181 PurpleAccount
*account
;
186 purple_account_register_completed_cb(gpointer data
)
188 struct register_completed_closure
*closure
= data
;
189 PurpleAccountPrivate
*priv
;
191 priv
= purple_account_get_instance_private(closure
->account
);
193 if (priv
->registration_cb
)
194 (priv
->registration_cb
)(closure
->account
, closure
->succeeded
,
195 priv
->registration_cb_user_data
);
197 g_object_unref(closure
->account
);
204 request_password_ok_cb(PurpleAccount
*account
, PurpleRequestFields
*fields
)
209 entry
= purple_request_fields_get_string(fields
, "password");
210 remember
= purple_request_fields_get_bool(fields
, "remember");
212 if (!entry
|| !*entry
)
214 purple_notify_error(account
, NULL
,
215 _("Password is required to sign on."), NULL
,
216 purple_request_cpar_from_account(account
));
220 purple_account_set_remember_password(account
, remember
);
222 purple_account_set_password(account
, entry
, NULL
, NULL
);
223 _purple_connection_new(account
, FALSE
, entry
);
227 request_password_cancel_cb(PurpleAccount
*account
, PurpleRequestFields
*fields
)
229 /* Disable the account as the user has cancelled connecting */
230 purple_account_set_enabled(account
, purple_core_get_ui(), FALSE
);
235 purple_account_connect_got_password_cb(PurpleAccount
*account
,
236 const gchar
*password
, GError
*error
, gpointer data
)
238 PurpleProtocol
*protocol
= data
;
240 if ((password
== NULL
|| *password
== '\0') &&
241 !(purple_protocol_get_options(protocol
) & OPT_PROTO_NO_PASSWORD
) &&
242 !(purple_protocol_get_options(protocol
) & OPT_PROTO_PASSWORD_OPTIONAL
))
243 purple_account_request_password(account
,
244 G_CALLBACK(request_password_ok_cb
),
245 G_CALLBACK(request_password_cancel_cb
), account
);
247 _purple_connection_new(account
, FALSE
, password
);
250 static PurpleAccountRequestInfo
*
251 purple_account_request_info_unref(PurpleAccountRequestInfo
*info
)
256 /* TODO: This will leak info->user_data, but there is no callback to just clean that up */
263 purple_account_request_close_info(PurpleAccountRequestInfo
*info
)
265 PurpleAccountUiOps
*ops
;
267 ops
= purple_accounts_get_ui_ops();
269 if (ops
!= NULL
&& ops
->close_account_request
!= NULL
)
270 ops
->close_account_request(info
->ui_handle
);
272 purple_account_request_info_unref(info
);
276 request_auth_cb(const char *message
, void *data
)
278 PurpleAccountRequestInfo
*info
= data
;
280 handles
= g_list_remove(handles
, info
);
282 if (info
->auth_cb
!= NULL
)
283 info
->auth_cb(message
, info
->userdata
);
285 purple_signal_emit(purple_accounts_get_handle(),
286 "account-authorization-granted", info
->account
, info
->user
, message
);
288 purple_account_request_info_unref(info
);
292 request_deny_cb(const char *message
, void *data
)
294 PurpleAccountRequestInfo
*info
= data
;
296 handles
= g_list_remove(handles
, info
);
298 if (info
->deny_cb
!= NULL
)
299 info
->deny_cb(message
, info
->userdata
);
301 purple_signal_emit(purple_accounts_get_handle(),
302 "account-authorization-denied", info
->account
, info
->user
, message
);
304 purple_account_request_info_unref(info
);
308 change_password_cb(PurpleAccount
*account
, PurpleRequestFields
*fields
)
310 const char *orig_pass
, *new_pass_1
, *new_pass_2
;
312 orig_pass
= purple_request_fields_get_string(fields
, "password");
313 new_pass_1
= purple_request_fields_get_string(fields
, "new_password_1");
314 new_pass_2
= purple_request_fields_get_string(fields
, "new_password_2");
316 if (g_utf8_collate(new_pass_1
, new_pass_2
))
318 purple_notify_error(account
, NULL
,
319 _("New passwords do not match."), NULL
,
320 purple_request_cpar_from_account(account
));
325 if ((purple_request_fields_is_field_required(fields
, "password") &&
326 (orig_pass
== NULL
|| *orig_pass
== '\0')) ||
327 (purple_request_fields_is_field_required(fields
, "new_password_1") &&
328 (new_pass_1
== NULL
|| *new_pass_1
== '\0')) ||
329 (purple_request_fields_is_field_required(fields
, "new_password_2") &&
330 (new_pass_2
== NULL
|| *new_pass_2
== '\0')))
332 purple_notify_error(account
, NULL
,
333 _("Fill out all fields completely."), NULL
,
334 purple_request_cpar_from_account(account
));
338 purple_account_change_password(account
, orig_pass
, new_pass_1
);
342 set_user_info_cb(PurpleAccount
*account
, const char *user_info
)
344 PurpleConnection
*gc
;
346 purple_account_set_user_info(account
, user_info
);
347 gc
= purple_account_get_connection(account
);
348 purple_serv_set_info(gc
, user_info
);
351 struct public_alias_closure
353 PurpleAccount
*account
;
358 set_public_alias_unsupported(gpointer data
)
360 struct public_alias_closure
*closure
= data
;
361 PurpleSetPublicAliasFailureCallback failure_cb
= closure
->failure_cb
;
363 failure_cb(closure
->account
,
364 _("This protocol does not support setting a public alias."));
366 g_object_unref(closure
->account
);
373 get_public_alias_unsupported(gpointer data
)
375 struct public_alias_closure
*closure
= data
;
376 PurpleGetPublicAliasFailureCallback failure_cb
= closure
->failure_cb
;
378 failure_cb(closure
->account
,
379 _("This protocol does not support fetching the public alias."));
381 g_object_unref(closure
->account
);
388 delete_setting(void *data
)
390 PurpleAccountSetting
*setting
= (PurpleAccountSetting
*)data
;
393 g_value_unset(&setting
->value
);
399 get_ui_settings_table(PurpleAccount
*account
, const char *ui
)
402 PurpleAccountPrivate
*priv
= purple_account_get_instance_private(account
);
404 table
= g_hash_table_lookup(priv
->ui_settings
, ui
);
407 table
= g_hash_table_new_full(g_str_hash
, g_str_equal
, g_free
,
409 g_hash_table_insert(priv
->ui_settings
, g_strdup(ui
), table
);
415 static PurpleConnectionState
416 purple_account_get_state(PurpleAccount
*account
)
418 PurpleConnection
*gc
;
420 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), PURPLE_CONNECTION_DISCONNECTED
);
422 gc
= purple_account_get_connection(account
);
424 return PURPLE_CONNECTION_DISCONNECTED
;
426 return purple_connection_get_state(gc
);
430 purple_account_get_password_got(PurpleAccount
*account
,
431 const gchar
*password
, GError
*error
, gpointer data
)
433 PurpleCallbackBundle
*cbb
= data
;
434 PurpleKeyringReadCallback cb
;
435 PurpleAccountPrivate
*priv
= purple_account_get_instance_private(account
);
437 purple_debug_info("account",
438 "Read password for account %s from async keyring.\n",
439 purple_account_get_username(account
));
441 purple_str_wipe(priv
->password
);
442 priv
->password
= g_strdup(password
);
444 cb
= (PurpleKeyringReadCallback
)cbb
->cb
;
446 cb(account
, password
, error
, cbb
->data
);
452 * This makes sure your permit list contains all buddies from your
453 * buddy list and ONLY buddies from your buddy list.
456 add_all_buddies_to_permit_list(PurpleAccount
*account
, gboolean local
)
459 PurpleAccountPrivate
*priv
= purple_account_get_instance_private(account
);
461 /* Remove anyone in the permit list who is not in the buddylist */
462 for (list
= priv
->permit
; list
!= NULL
; ) {
463 char *person
= list
->data
;
465 if (!purple_blist_find_buddy(account
, person
))
466 purple_account_privacy_permit_remove(account
, person
, local
);
469 /* Now make sure everyone in the buddylist is in the permit list */
470 list
= purple_blist_find_buddies(account
, NULL
);
473 PurpleBuddy
*buddy
= list
->data
;
474 const gchar
*name
= purple_buddy_get_name(buddy
);
476 if (!g_slist_find_custom(priv
->permit
, name
, (GCompareFunc
)g_utf8_collate
))
477 purple_account_privacy_permit_add(account
, name
, local
);
478 list
= g_slist_delete_link(list
, list
);
483 _purple_account_set_current_error(PurpleAccount
*account
,
484 PurpleConnectionErrorInfo
*new_err
)
486 PurpleConnectionErrorInfo
*old_err
;
487 PurpleAccountPrivate
*priv
;
489 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
490 priv
= purple_account_get_instance_private(account
);
492 old_err
= priv
->current_error
;
494 if(new_err
== old_err
)
497 priv
->current_error
= new_err
;
499 purple_signal_emit(purple_accounts_get_handle(),
500 "account-error-changed",
501 account
, old_err
, new_err
);
502 purple_accounts_schedule_save();
505 g_free(old_err
->description
);
510 /******************************************************************************
512 *****************************************************************************/
513 static PurpleXmlNode
*
514 status_attribute_to_xmlnode(PurpleStatus
*status
, PurpleStatusType
*type
,
515 PurpleStatusAttribute
*attr
)
520 PurpleStatusAttribute
*default_attr
;
521 GValue
*default_value
;
525 id
= purple_status_attribute_get_id(attr
);
526 g_return_val_if_fail(id
, NULL
);
528 attr_value
= purple_status_get_attr_value(status
, id
);
529 g_return_val_if_fail(attr_value
, NULL
);
530 attr_type
= G_VALUE_TYPE(attr_value
);
533 * If attr_value is a different type than it should be
534 * then don't write it to the file.
536 default_attr
= purple_status_type_get_attr(type
, id
);
537 default_value
= purple_status_attribute_get_value(default_attr
);
538 if (attr_type
!= G_VALUE_TYPE(default_value
))
542 * If attr_value is the same as the default for this status
543 * then there is no need to write it to the file.
545 if (attr_type
== G_TYPE_STRING
)
547 const char *string_value
= g_value_get_string(attr_value
);
548 const char *default_string_value
= g_value_get_string(default_value
);
549 if (purple_strequal(string_value
, default_string_value
))
551 value
= g_value_dup_string(attr_value
);
553 else if (attr_type
== G_TYPE_INT
)
555 int int_value
= g_value_get_int(attr_value
);
556 if (int_value
== g_value_get_int(default_value
))
558 value
= g_strdup_printf("%d", int_value
);
560 else if (attr_type
== G_TYPE_BOOLEAN
)
562 gboolean boolean_value
= g_value_get_boolean(attr_value
);
563 if (boolean_value
== g_value_get_boolean(default_value
))
565 value
= g_strdup(boolean_value
?
573 g_return_val_if_fail(value
, NULL
);
575 node
= purple_xmlnode_new("attribute");
577 purple_xmlnode_set_attrib(node
, "id", id
);
578 purple_xmlnode_set_attrib(node
, "value", value
);
585 static PurpleXmlNode
*
586 status_attrs_to_xmlnode(PurpleStatus
*status
)
588 PurpleStatusType
*type
= purple_status_get_status_type(status
);
589 PurpleXmlNode
*node
, *child
;
592 node
= purple_xmlnode_new("attributes");
594 attrs
= purple_status_type_get_attrs(type
);
595 for (attr
= attrs
; attr
!= NULL
; attr
= attr
->next
)
597 child
= status_attribute_to_xmlnode(status
, type
, (PurpleStatusAttribute
*)attr
->data
);
599 purple_xmlnode_insert_child(node
, child
);
605 static PurpleXmlNode
*
606 status_to_xmlnode(PurpleStatus
*status
)
608 PurpleXmlNode
*node
, *child
;
610 node
= purple_xmlnode_new("status");
611 purple_xmlnode_set_attrib(node
, "type", purple_status_get_id(status
));
612 if (purple_status_get_name(status
) != NULL
)
613 purple_xmlnode_set_attrib(node
, "name", purple_status_get_name(status
));
614 purple_xmlnode_set_attrib(node
, "active", purple_status_is_active(status
) ? "true" : "false");
616 child
= status_attrs_to_xmlnode(status
);
617 purple_xmlnode_insert_child(node
, child
);
622 static PurpleXmlNode
*
623 statuses_to_xmlnode(PurplePresence
*presence
)
625 PurpleXmlNode
*node
, *child
;
627 PurpleStatus
*status
;
629 node
= purple_xmlnode_new("statuses");
631 statuses
= purple_presence_get_statuses(presence
);
632 for (; statuses
!= NULL
; statuses
= statuses
->next
)
634 status
= statuses
->data
;
635 if (purple_status_type_is_saveable(purple_status_get_status_type(status
)))
637 child
= status_to_xmlnode(status
);
638 purple_xmlnode_insert_child(node
, child
);
645 static PurpleXmlNode
*
646 proxy_settings_to_xmlnode(const PurpleProxyInfo
*proxy_info
)
648 PurpleXmlNode
*node
, *child
;
649 PurpleProxyType proxy_type
;
654 proxy_type
= purple_proxy_info_get_proxy_type(proxy_info
);
656 node
= purple_xmlnode_new("proxy");
658 child
= purple_xmlnode_new_child(node
, "type");
659 purple_xmlnode_insert_data(child
,
660 (proxy_type
== PURPLE_PROXY_USE_GLOBAL
? "global" :
661 proxy_type
== PURPLE_PROXY_NONE
? "none" :
662 proxy_type
== PURPLE_PROXY_HTTP
? "http" :
663 proxy_type
== PURPLE_PROXY_SOCKS4
? "socks4" :
664 proxy_type
== PURPLE_PROXY_SOCKS5
? "socks5" :
665 proxy_type
== PURPLE_PROXY_TOR
? "tor" :
666 proxy_type
== PURPLE_PROXY_USE_ENVVAR
? "envvar" : "unknown"), -1);
668 if ((value
= purple_proxy_info_get_host(proxy_info
)) != NULL
)
670 child
= purple_xmlnode_new_child(node
, "host");
671 purple_xmlnode_insert_data(child
, value
, -1);
674 if ((int_value
= purple_proxy_info_get_port(proxy_info
)) != 0)
676 g_snprintf(buf
, sizeof(buf
), "%d", int_value
);
677 child
= purple_xmlnode_new_child(node
, "port");
678 purple_xmlnode_insert_data(child
, buf
, -1);
681 if ((value
= purple_proxy_info_get_username(proxy_info
)) != NULL
)
683 child
= purple_xmlnode_new_child(node
, "username");
684 purple_xmlnode_insert_data(child
, value
, -1);
687 if ((value
= purple_proxy_info_get_password(proxy_info
)) != NULL
)
689 child
= purple_xmlnode_new_child(node
, "password");
690 purple_xmlnode_insert_data(child
, value
, -1);
696 static PurpleXmlNode
*
697 current_error_to_xmlnode(PurpleConnectionErrorInfo
*err
)
699 PurpleXmlNode
*node
, *child
;
702 node
= purple_xmlnode_new("current_error");
707 /* It doesn't make sense to have transient errors persist across a
710 if(!purple_connection_error_is_fatal (err
->type
))
713 child
= purple_xmlnode_new_child(node
, "type");
714 g_snprintf(type_str
, sizeof(type_str
), "%u", err
->type
);
715 purple_xmlnode_insert_data(child
, type_str
, -1);
717 child
= purple_xmlnode_new_child(node
, "description");
718 if(err
->description
) {
719 char *utf8ized
= purple_utf8_try_convert(err
->description
);
721 utf8ized
= purple_utf8_salvage(err
->description
);
722 purple_xmlnode_insert_data(child
, utf8ized
, -1);
730 setting_to_xmlnode(gpointer key
, gpointer value
, gpointer user_data
)
733 PurpleAccountSetting
*setting
;
734 PurpleXmlNode
*node
, *child
;
737 name
= (const char *)key
;
738 setting
= (PurpleAccountSetting
*)value
;
739 node
= (PurpleXmlNode
*)user_data
;
741 child
= purple_xmlnode_new_child(node
, "setting");
742 purple_xmlnode_set_attrib(child
, "name", name
);
744 if (G_VALUE_HOLDS_INT(&setting
->value
)) {
745 purple_xmlnode_set_attrib(child
, "type", "int");
746 g_snprintf(buf
, sizeof(buf
), "%d", g_value_get_int(&setting
->value
));
747 purple_xmlnode_insert_data(child
, buf
, -1);
749 else if (G_VALUE_HOLDS_STRING(&setting
->value
) && g_value_get_string(&setting
->value
) != NULL
) {
750 purple_xmlnode_set_attrib(child
, "type", "string");
751 purple_xmlnode_insert_data(child
, g_value_get_string(&setting
->value
), -1);
753 else if (G_VALUE_HOLDS_BOOLEAN(&setting
->value
)) {
754 purple_xmlnode_set_attrib(child
, "type", "bool");
755 g_snprintf(buf
, sizeof(buf
), "%d", g_value_get_boolean(&setting
->value
));
756 purple_xmlnode_insert_data(child
, buf
, -1);
761 ui_setting_to_xmlnode(gpointer key
, gpointer value
, gpointer user_data
)
765 PurpleXmlNode
*node
, *child
;
767 ui
= (const char *)key
;
768 table
= (GHashTable
*)value
;
769 node
= (PurpleXmlNode
*)user_data
;
771 if (g_hash_table_size(table
) > 0)
773 child
= purple_xmlnode_new_child(node
, "settings");
774 purple_xmlnode_set_attrib(child
, "ui", ui
);
775 g_hash_table_foreach(table
, setting_to_xmlnode
, child
);
780 _purple_account_to_xmlnode(PurpleAccount
*account
)
782 PurpleXmlNode
*node
, *child
;
784 PurplePresence
*presence
;
785 const PurpleProxyInfo
*proxy_info
;
786 PurpleAccountPrivate
*priv
= purple_account_get_instance_private(account
);
788 node
= purple_xmlnode_new("account");
790 child
= purple_xmlnode_new_child(node
, "protocol");
791 purple_xmlnode_insert_data(child
, purple_account_get_protocol_id(account
), -1);
793 child
= purple_xmlnode_new_child(node
, "name");
794 purple_xmlnode_insert_data(child
, purple_account_get_username(account
), -1);
796 if (purple_account_get_remember_password(account
))
798 const char *keyring_id
= NULL
;
799 const char *mode
= NULL
;
801 GError
*error
= NULL
;
802 GDestroyNotify destroy
= NULL
;
803 gboolean exported
= purple_keyring_export_password(account
,
804 &keyring_id
, &mode
, &data
, &error
, &destroy
);
807 purple_debug_error("account",
808 "Failed to export password for account %s: %s.\n",
809 purple_account_get_username(account
),
811 } else if (exported
) {
812 child
= purple_xmlnode_new_child(node
, "password");
813 if (keyring_id
!= NULL
)
814 purple_xmlnode_set_attrib(child
, "keyring_id", keyring_id
);
816 purple_xmlnode_set_attrib(child
, "mode", mode
);
818 purple_xmlnode_insert_data(child
, data
, -1);
825 if ((tmp
= purple_account_get_private_alias(account
)) != NULL
)
827 child
= purple_xmlnode_new_child(node
, "alias");
828 purple_xmlnode_insert_data(child
, tmp
, -1);
831 if ((presence
= purple_account_get_presence(account
)) != NULL
)
833 child
= statuses_to_xmlnode(presence
);
834 purple_xmlnode_insert_child(node
, child
);
837 if ((tmp
= purple_account_get_user_info(account
)) != NULL
)
839 /* TODO: Do we need to call purple_str_strip_char(tmp, '\r') here? */
840 child
= purple_xmlnode_new_child(node
, "user-info");
841 purple_xmlnode_insert_data(child
, tmp
, -1);
844 if (g_hash_table_size(priv
->settings
) > 0)
846 child
= purple_xmlnode_new_child(node
, "settings");
847 g_hash_table_foreach(priv
->settings
, setting_to_xmlnode
, child
);
850 if (g_hash_table_size(priv
->ui_settings
) > 0)
852 g_hash_table_foreach(priv
->ui_settings
, ui_setting_to_xmlnode
, node
);
855 if ((proxy_info
= purple_account_get_proxy_info(account
)) != NULL
)
857 child
= proxy_settings_to_xmlnode(proxy_info
);
858 purple_xmlnode_insert_child(node
, child
);
861 child
= current_error_to_xmlnode(priv
->current_error
);
862 purple_xmlnode_insert_child(node
, child
);
867 /******************************************************************************
868 * GObject Implementation
869 *****************************************************************************/
871 purple_account_set_property(GObject
*obj
, guint param_id
, const GValue
*value
,
874 PurpleAccount
*account
= PURPLE_ACCOUNT(obj
);
878 purple_account_set_username(account
, g_value_get_string(value
));
880 case PROP_PRIVATE_ALIAS
:
881 purple_account_set_private_alias(account
, g_value_get_string(value
));
884 purple_account_set_enabled(account
, purple_core_get_ui(),
885 g_value_get_boolean(value
));
887 case PROP_CONNECTION
:
888 purple_account_set_connection(account
, g_value_get_object(value
));
890 case PROP_PROTOCOL_ID
:
891 purple_account_set_protocol_id(account
, g_value_get_string(value
));
894 purple_account_set_user_info(account
, g_value_get_string(value
));
896 case PROP_BUDDY_ICON_PATH
:
897 purple_account_set_buddy_icon_path(account
,
898 g_value_get_string(value
));
900 case PROP_REMEMBER_PASSWORD
:
901 purple_account_set_remember_password(account
,
902 g_value_get_boolean(value
));
904 case PROP_CHECK_MAIL
:
905 purple_account_set_check_mail(account
, g_value_get_boolean(value
));
908 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
914 purple_account_get_property(GObject
*obj
, guint param_id
, GValue
*value
,
917 PurpleAccount
*account
= PURPLE_ACCOUNT(obj
);
921 g_value_set_string(value
, purple_account_get_username(account
));
923 case PROP_PRIVATE_ALIAS
:
924 g_value_set_string(value
, purple_account_get_private_alias(account
));
927 g_value_set_boolean(value
, purple_account_get_enabled(account
,
928 purple_core_get_ui()));
930 case PROP_CONNECTION
:
931 g_value_set_object(value
, purple_account_get_connection(account
));
933 case PROP_PROTOCOL_ID
:
934 g_value_set_string(value
, purple_account_get_protocol_id(account
));
937 g_value_set_string(value
, purple_account_get_user_info(account
));
939 case PROP_BUDDY_ICON_PATH
:
940 g_value_set_string(value
,
941 purple_account_get_buddy_icon_path(account
));
943 case PROP_REMEMBER_PASSWORD
:
944 g_value_set_boolean(value
,
945 purple_account_get_remember_password(account
));
947 case PROP_CHECK_MAIL
:
948 g_value_set_boolean(value
, purple_account_get_check_mail(account
));
951 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
957 purple_account_init(PurpleAccount
*account
)
959 PurpleAccountPrivate
*priv
= purple_account_get_instance_private(account
);
961 priv
->settings
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
962 g_free
, delete_setting
);
963 priv
->ui_settings
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
964 g_free
, (GDestroyNotify
)g_hash_table_destroy
);
965 priv
->system_log
= NULL
;
967 priv
->privacy_type
= PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL
;
971 purple_account_constructed(GObject
*object
)
973 PurpleAccount
*account
= PURPLE_ACCOUNT(object
);
974 PurpleAccountPrivate
*priv
= purple_account_get_instance_private(account
);
975 gchar
*username
, *protocol_id
;
976 PurpleProtocol
*protocol
= NULL
;
977 PurpleStatusType
*status_type
;
979 G_OBJECT_CLASS(purple_account_parent_class
)->constructed(object
);
982 "username", &username
,
983 "protocol-id", &protocol_id
,
986 purple_signal_emit(purple_accounts_get_handle(), "account-created",
989 protocol
= purple_protocols_find(protocol_id
);
990 if (protocol
== NULL
) {
996 purple_account_set_status_types(account
,
997 purple_protocol_class_status_types(protocol
, account
));
999 priv
->presence
= PURPLE_PRESENCE(purple_account_presence_new(account
));
1001 status_type
= purple_account_get_status_type_with_primitive(account
,
1002 PURPLE_STATUS_AVAILABLE
);
1003 if (status_type
!= NULL
)
1004 purple_presence_set_status_active(priv
->presence
,
1005 purple_status_type_get_id(status_type
),
1008 purple_presence_set_status_active(priv
->presence
,
1013 g_free(protocol_id
);
1017 purple_account_dispose(GObject
*object
)
1019 PurpleAccount
*account
= PURPLE_ACCOUNT(object
);
1020 PurpleAccountPrivate
*priv
= purple_account_get_instance_private(account
);
1022 if (!purple_account_is_disconnected(account
))
1023 purple_account_disconnect(account
);
1025 if (priv
->presence
) {
1026 g_object_unref(priv
->presence
);
1027 priv
->presence
= NULL
;
1030 G_OBJECT_CLASS(purple_account_parent_class
)->dispose(object
);
1034 purple_account_finalize(GObject
*object
)
1037 PurpleAccount
*account
= PURPLE_ACCOUNT(object
);
1038 PurpleAccountPrivate
*priv
= purple_account_get_instance_private(account
);
1040 purple_debug_info("account", "Destroying account %p\n", account
);
1041 purple_signal_emit(purple_accounts_get_handle(), "account-destroying",
1044 for (l
= purple_conversations_get_all(); l
!= NULL
; l
= l
->next
)
1046 PurpleConversation
*conv
= (PurpleConversation
*)l
->data
;
1048 if (purple_conversation_get_account(conv
) == account
)
1049 purple_conversation_set_account(conv
, NULL
);
1052 purple_account_set_status_types(account
, NULL
);
1054 if (priv
->proxy_info
)
1055 purple_proxy_info_destroy(priv
->proxy_info
);
1057 if(priv
->system_log
)
1058 purple_log_free(priv
->system_log
);
1060 if (priv
->current_error
) {
1061 g_free(priv
->current_error
->description
);
1062 g_free(priv
->current_error
);
1065 g_free(priv
->username
);
1066 g_free(priv
->alias
);
1067 purple_str_wipe(priv
->password
);
1068 g_free(priv
->user_info
);
1069 g_free(priv
->buddy_icon_path
);
1070 g_free(priv
->protocol_id
);
1072 g_hash_table_destroy(priv
->settings
);
1073 g_hash_table_destroy(priv
->ui_settings
);
1075 while (priv
->deny
) {
1076 g_free(priv
->deny
->data
);
1077 priv
->deny
= g_slist_delete_link(priv
->deny
, priv
->deny
);
1080 while (priv
->permit
) {
1081 g_free(priv
->permit
->data
);
1082 priv
->permit
= g_slist_delete_link(priv
->permit
, priv
->permit
);
1085 G_OBJECT_CLASS(purple_account_parent_class
)->finalize(object
);
1089 purple_account_class_init(PurpleAccountClass
*klass
)
1091 GObjectClass
*obj_class
= G_OBJECT_CLASS(klass
);
1093 obj_class
->dispose
= purple_account_dispose
;
1094 obj_class
->finalize
= purple_account_finalize
;
1095 obj_class
->constructed
= purple_account_constructed
;
1097 /* Setup properties */
1098 obj_class
->get_property
= purple_account_get_property
;
1099 obj_class
->set_property
= purple_account_set_property
;
1101 properties
[PROP_USERNAME
] = g_param_spec_string("username", "Username",
1102 "The username for the account.", NULL
,
1103 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT
| G_PARAM_STATIC_STRINGS
);
1105 properties
[PROP_PRIVATE_ALIAS
] = g_param_spec_string("private-alias",
1107 "The private alias for the account.", NULL
,
1108 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
1110 properties
[PROP_USER_INFO
] = g_param_spec_string("user-info",
1112 "Detailed user information for the account.", NULL
,
1113 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
1115 properties
[PROP_BUDDY_ICON_PATH
] = g_param_spec_string("buddy-icon-path",
1117 "Path to the buddyicon for the account.", NULL
,
1118 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
1120 properties
[PROP_ENABLED
] = g_param_spec_boolean("enabled", "Enabled",
1121 "Whether the account is enabled or not.", FALSE
,
1122 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
1124 properties
[PROP_REMEMBER_PASSWORD
] = g_param_spec_boolean(
1125 "remember-password", "Remember password",
1126 "Whether to remember and store the password for this account.",
1127 FALSE
, G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
1129 properties
[PROP_CHECK_MAIL
] = g_param_spec_boolean("check-mail",
1131 "Whether to check mails for this account.", FALSE
,
1132 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
1134 properties
[PROP_CONNECTION
] = g_param_spec_object("connection",
1136 "The connection for the account.", PURPLE_TYPE_CONNECTION
,
1137 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
1139 properties
[PROP_PROTOCOL_ID
] = g_param_spec_string("protocol-id",
1141 "ID of the protocol that is responsible for the account.", NULL
,
1142 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
|
1143 G_PARAM_STATIC_STRINGS
);
1145 g_object_class_install_properties(obj_class
, PROP_LAST
, properties
);
1148 /******************************************************************************
1150 *****************************************************************************/
1152 purple_account_new(const char *username
, const char *protocol_id
)
1154 PurpleAccount
*account
;
1156 g_return_val_if_fail(username
!= NULL
, NULL
);
1157 g_return_val_if_fail(protocol_id
!= NULL
, NULL
);
1159 account
= purple_accounts_find(username
, protocol_id
);
1161 if (account
!= NULL
)
1164 account
= g_object_new(PURPLE_TYPE_ACCOUNT
,
1165 "username", username
,
1166 "protocol-id", protocol_id
,
1173 purple_account_connect(PurpleAccount
*account
)
1175 const char *username
;
1176 PurpleProtocol
*protocol
;
1177 PurpleAccountPrivate
*priv
;
1179 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1181 username
= purple_account_get_username(account
);
1183 if (!purple_account_get_enabled(account
, purple_core_get_ui())) {
1184 purple_debug_info("account",
1185 "Account %s not enabled, not connecting.\n",
1190 protocol
= purple_protocols_find(purple_account_get_protocol_id(account
));
1191 if (protocol
== NULL
) {
1194 message
= g_strdup_printf(_("Missing protocol for %s"), username
);
1195 purple_notify_error(account
, _("Connection Error"), message
,
1196 NULL
, purple_request_cpar_from_account(account
));
1201 priv
= purple_account_get_instance_private(account
);
1203 purple_debug_info("account", "Connecting to account %s.\n", username
);
1205 if (priv
->password
!= NULL
) {
1206 purple_account_connect_got_password_cb(account
,
1207 priv
->password
, NULL
, protocol
);
1209 purple_keyring_get_password(account
,
1210 purple_account_connect_got_password_cb
, protocol
);
1215 purple_account_set_register_callback(PurpleAccount
*account
, PurpleAccountRegistrationCb cb
, void *user_data
)
1217 PurpleAccountPrivate
*priv
;
1219 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1221 priv
= purple_account_get_instance_private(account
);
1223 priv
->registration_cb
= cb
;
1224 priv
->registration_cb_user_data
= user_data
;
1228 purple_account_register_completed(PurpleAccount
*account
, gboolean succeeded
)
1230 struct register_completed_closure
*closure
;
1232 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1234 closure
= g_new0(struct register_completed_closure
, 1);
1235 closure
->account
= g_object_ref(account
);
1236 closure
->succeeded
= succeeded
;
1238 g_timeout_add(0, purple_account_register_completed_cb
, closure
);
1242 purple_account_unregister(PurpleAccount
*account
, PurpleAccountUnregistrationCb cb
, void *user_data
)
1244 PurpleCallbackBundle
*cbb
;
1246 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1248 purple_debug_info("account", "Unregistering account %s\n",
1249 purple_account_get_username(account
));
1251 cbb
= g_new0(PurpleCallbackBundle
, 1);
1252 cbb
->cb
= PURPLE_CALLBACK(cb
);
1253 cbb
->data
= user_data
;
1255 purple_keyring_get_password(account
,
1256 purple_account_unregister_got_password_cb
, cbb
);
1260 purple_account_disconnect(PurpleAccount
*account
)
1262 PurpleConnection
*gc
;
1263 PurpleAccountPrivate
*priv
;
1264 const char *username
;
1266 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1267 g_return_if_fail(!purple_account_is_disconnecting(account
));
1268 g_return_if_fail(!purple_account_is_disconnected(account
));
1270 priv
= purple_account_get_instance_private(account
);
1272 username
= purple_account_get_username(account
);
1273 purple_debug_info("account", "Disconnecting account %s (%p)\n",
1274 username
? username
: "(null)", account
);
1276 priv
->disconnecting
= TRUE
;
1278 gc
= purple_account_get_connection(account
);
1280 purple_account_set_connection(account
, NULL
);
1282 priv
->disconnecting
= FALSE
;
1286 purple_account_is_disconnecting(PurpleAccount
*account
)
1288 PurpleAccountPrivate
*priv
;
1290 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), TRUE
);
1292 priv
= purple_account_get_instance_private(account
);
1293 return priv
->disconnecting
;
1297 purple_account_notify_added(PurpleAccount
*account
, const char *remote_user
,
1298 const char *id
, const char *alias
,
1299 const char *message
)
1301 PurpleAccountUiOps
*ui_ops
;
1303 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1304 g_return_if_fail(remote_user
!= NULL
);
1306 ui_ops
= purple_accounts_get_ui_ops();
1308 if (ui_ops
!= NULL
&& ui_ops
->notify_added
!= NULL
)
1309 ui_ops
->notify_added(account
, remote_user
, id
, alias
, message
);
1313 purple_account_request_add(PurpleAccount
*account
, const char *remote_user
,
1314 const char *id
, const char *alias
,
1315 const char *message
)
1317 PurpleAccountUiOps
*ui_ops
;
1319 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1320 g_return_if_fail(remote_user
!= NULL
);
1322 ui_ops
= purple_accounts_get_ui_ops();
1324 if (ui_ops
!= NULL
&& ui_ops
->request_add
!= NULL
)
1325 ui_ops
->request_add(account
, remote_user
, id
, alias
, message
);
1329 purple_account_request_authorization(PurpleAccount
*account
, const char *remote_user
,
1330 const char *id
, const char *alias
, const char *message
, gboolean on_list
,
1331 PurpleAccountRequestAuthorizationCb auth_cb
, PurpleAccountRequestAuthorizationCb deny_cb
, void *user_data
)
1333 PurpleAccountUiOps
*ui_ops
;
1334 PurpleAccountRequestInfo
*info
;
1336 char *response
= NULL
;
1338 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
1339 g_return_val_if_fail(remote_user
!= NULL
, NULL
);
1341 ui_ops
= purple_accounts_get_ui_ops();
1343 plugin_return
= GPOINTER_TO_INT(
1344 purple_signal_emit_return_1(
1345 purple_accounts_get_handle(),
1346 "account-authorization-requested",
1347 account
, remote_user
, message
, &response
1350 switch (plugin_return
)
1352 case PURPLE_ACCOUNT_RESPONSE_IGNORE
:
1355 case PURPLE_ACCOUNT_RESPONSE_ACCEPT
:
1356 if (auth_cb
!= NULL
)
1357 auth_cb(response
, user_data
);
1360 case PURPLE_ACCOUNT_RESPONSE_DENY
:
1361 if (deny_cb
!= NULL
)
1362 deny_cb(response
, user_data
);
1369 if (ui_ops
!= NULL
&& ui_ops
->request_authorize
!= NULL
) {
1370 info
= g_new0(PurpleAccountRequestInfo
, 1);
1371 info
->type
= PURPLE_ACCOUNT_REQUEST_AUTHORIZATION
;
1372 info
->account
= account
;
1373 info
->auth_cb
= auth_cb
;
1374 info
->deny_cb
= deny_cb
;
1375 info
->userdata
= user_data
;
1376 info
->user
= g_strdup(remote_user
);
1377 info
->ref
= 2; /* We hold an extra ref to make sure info remains valid
1378 if any of the callbacks are called synchronously. We
1379 unref it after the function call */
1381 info
->ui_handle
= ui_ops
->request_authorize(account
, remote_user
, id
, alias
, message
,
1382 on_list
, request_auth_cb
, request_deny_cb
, info
);
1384 info
= purple_account_request_info_unref(info
);
1386 handles
= g_list_append(handles
, info
);
1387 return info
->ui_handle
;
1395 purple_account_request_close_with_account(PurpleAccount
*account
)
1399 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1401 for (l
= handles
; l
!= NULL
; l
= l_next
) {
1402 PurpleAccountRequestInfo
*info
= l
->data
;
1406 if (info
->account
== account
) {
1407 handles
= g_list_remove(handles
, info
);
1408 purple_account_request_close_info(info
);
1414 purple_account_request_close(void *ui_handle
)
1418 g_return_if_fail(ui_handle
!= NULL
);
1420 for (l
= handles
; l
!= NULL
; l
= l_next
) {
1421 PurpleAccountRequestInfo
*info
= l
->data
;
1425 if (info
->ui_handle
== ui_handle
) {
1426 handles
= g_list_remove(handles
, info
);
1427 purple_account_request_close_info(info
);
1433 purple_account_request_password(PurpleAccount
*account
, GCallback ok_cb
,
1434 GCallback cancel_cb
, void *user_data
)
1437 const gchar
*username
;
1438 PurpleRequestFieldGroup
*group
;
1439 PurpleRequestField
*field
;
1440 PurpleRequestFields
*fields
;
1442 /* Close any previous password request windows */
1443 purple_request_close_with_handle(account
);
1445 username
= purple_account_get_username(account
);
1446 primary
= g_strdup_printf(_("Enter password for %s (%s)"), username
,
1447 purple_account_get_protocol_name(account
));
1449 fields
= purple_request_fields_new();
1450 group
= purple_request_field_group_new(NULL
);
1451 purple_request_fields_add_group(fields
, group
);
1453 field
= purple_request_field_string_new("password", _("Enter Password"), NULL
, FALSE
);
1454 purple_request_field_string_set_masked(field
, TRUE
);
1455 purple_request_field_set_required(field
, TRUE
);
1456 purple_request_field_group_add_field(group
, field
);
1458 field
= purple_request_field_bool_new("remember", _("Save password"), FALSE
);
1459 purple_request_field_group_add_field(group
, field
);
1461 purple_request_fields(account
, NULL
, primary
, NULL
, fields
, _("OK"),
1462 ok_cb
, _("Cancel"), cancel_cb
,
1463 purple_request_cpar_from_account(account
), user_data
);
1468 purple_account_request_change_password(PurpleAccount
*account
)
1470 PurpleRequestFields
*fields
;
1471 PurpleRequestFieldGroup
*group
;
1472 PurpleRequestField
*field
;
1473 PurpleConnection
*gc
;
1474 PurpleProtocol
*protocol
= NULL
;
1477 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1478 g_return_if_fail(purple_account_is_connected(account
));
1480 gc
= purple_account_get_connection(account
);
1482 protocol
= purple_connection_get_protocol(gc
);
1484 fields
= purple_request_fields_new();
1486 group
= purple_request_field_group_new(NULL
);
1487 purple_request_fields_add_group(fields
, group
);
1489 field
= purple_request_field_string_new("password", _("Original password"),
1491 purple_request_field_string_set_masked(field
, TRUE
);
1492 if (!protocol
|| !(purple_protocol_get_options(protocol
) & OPT_PROTO_PASSWORD_OPTIONAL
))
1493 purple_request_field_set_required(field
, TRUE
);
1494 purple_request_field_group_add_field(group
, field
);
1496 field
= purple_request_field_string_new("new_password_1",
1499 purple_request_field_string_set_masked(field
, TRUE
);
1500 if (!protocol
|| !(purple_protocol_get_options(protocol
) & OPT_PROTO_PASSWORD_OPTIONAL
))
1501 purple_request_field_set_required(field
, TRUE
);
1502 purple_request_field_group_add_field(group
, field
);
1504 field
= purple_request_field_string_new("new_password_2",
1505 _("New password (again)"),
1507 purple_request_field_string_set_masked(field
, TRUE
);
1508 if (!protocol
|| !(purple_protocol_get_options(protocol
) & OPT_PROTO_PASSWORD_OPTIONAL
))
1509 purple_request_field_set_required(field
, TRUE
);
1510 purple_request_field_group_add_field(group
, field
);
1512 g_snprintf(primary
, sizeof(primary
), _("Change password for %s"),
1513 purple_account_get_username(account
));
1515 /* I'm sticking this somewhere in the code: bologna */
1517 purple_request_fields(purple_account_get_connection(account
), NULL
,
1518 primary
, _("Please enter your current password and your new "
1519 "password."), fields
, _("OK"), G_CALLBACK(change_password_cb
),
1520 _("Cancel"), NULL
, purple_request_cpar_from_account(account
),
1525 purple_account_request_change_user_info(PurpleAccount
*account
)
1527 PurpleConnection
*gc
;
1530 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1531 g_return_if_fail(purple_account_is_connected(account
));
1533 gc
= purple_account_get_connection(account
);
1535 g_snprintf(primary
, sizeof(primary
),
1536 _("Change user information for %s"),
1537 purple_account_get_username(account
));
1539 purple_request_input(gc
, _("Set User Info"), primary
, NULL
,
1540 purple_account_get_user_info(account
),
1541 TRUE
, FALSE
, ((gc
!= NULL
) &&
1542 (purple_connection_get_flags(gc
) & PURPLE_CONNECTION_FLAG_HTML
) ? "html" : NULL
),
1543 _("Save"), G_CALLBACK(set_user_info_cb
),
1545 purple_request_cpar_from_account(account
),
1550 purple_account_set_username(PurpleAccount
*account
, const char *username
)
1552 PurpleAccountPrivate
*priv
;
1554 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1556 priv
= purple_account_get_instance_private(account
);
1558 g_free(priv
->username
);
1559 priv
->username
= g_strdup(username
);
1561 g_object_notify_by_pspec(G_OBJECT(account
), properties
[PROP_USERNAME
]);
1563 purple_accounts_schedule_save();
1565 /* if the name changes, we should re-write the buddy list
1566 * to disk with the new name */
1567 purple_blist_save_account(purple_blist_get_default(), account
);
1571 purple_account_set_password(PurpleAccount
*account
, const gchar
*password
,
1572 PurpleKeyringSaveCallback cb
, gpointer data
)
1574 PurpleAccountPrivate
*priv
;
1576 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1578 priv
= purple_account_get_instance_private(account
);
1580 purple_str_wipe(priv
->password
);
1581 priv
->password
= g_strdup(password
);
1583 purple_accounts_schedule_save();
1585 if (!purple_account_get_remember_password(account
)) {
1586 purple_debug_info("account",
1587 "Password for %s set, not sent to keyring.\n",
1588 purple_account_get_username(account
));
1591 cb(account
, NULL
, data
);
1593 purple_keyring_set_password(account
, password
, cb
, data
);
1598 purple_account_set_private_alias(PurpleAccount
*account
, const char *alias
)
1600 PurpleAccountPrivate
*priv
;
1602 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1604 priv
= purple_account_get_instance_private(account
);
1607 * Do nothing if alias and priv->alias are both NULL. Or if
1608 * they're the exact same string.
1610 if (alias
== priv
->alias
)
1613 if ((!alias
&& priv
->alias
) || (alias
&& !priv
->alias
) ||
1614 g_utf8_collate(priv
->alias
, alias
))
1616 char *old
= priv
->alias
;
1618 priv
->alias
= g_strdup(alias
);
1619 g_object_notify_by_pspec(G_OBJECT(account
),
1620 properties
[PROP_PRIVATE_ALIAS
]);
1621 purple_signal_emit(purple_accounts_get_handle(), "account-alias-changed",
1625 purple_accounts_schedule_save();
1630 purple_account_set_user_info(PurpleAccount
*account
, const char *user_info
)
1632 PurpleAccountPrivate
*priv
;
1634 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1636 priv
= purple_account_get_instance_private(account
);
1638 g_free(priv
->user_info
);
1639 priv
->user_info
= g_strdup(user_info
);
1641 g_object_notify_by_pspec(G_OBJECT(account
), properties
[PROP_USER_INFO
]);
1643 purple_accounts_schedule_save();
1646 void purple_account_set_buddy_icon_path(PurpleAccount
*account
, const char *path
)
1648 PurpleAccountPrivate
*priv
;
1650 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1652 priv
= purple_account_get_instance_private(account
);
1654 g_free(priv
->buddy_icon_path
);
1655 priv
->buddy_icon_path
= g_strdup(path
);
1657 g_object_notify_by_pspec(G_OBJECT(account
),
1658 properties
[PROP_BUDDY_ICON_PATH
]);
1660 purple_accounts_schedule_save();
1664 purple_account_set_protocol_id(PurpleAccount
*account
, const char *protocol_id
)
1666 PurpleAccountPrivate
*priv
;
1668 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1669 g_return_if_fail(protocol_id
!= NULL
);
1671 priv
= purple_account_get_instance_private(account
);
1673 g_free(priv
->protocol_id
);
1674 priv
->protocol_id
= g_strdup(protocol_id
);
1676 g_object_notify_by_pspec(G_OBJECT(account
), properties
[PROP_PROTOCOL_ID
]);
1678 purple_accounts_schedule_save();
1682 purple_account_set_connection(PurpleAccount
*account
, PurpleConnection
*gc
)
1684 PurpleAccountPrivate
*priv
;
1686 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1688 priv
= purple_account_get_instance_private(account
);
1691 g_object_notify_by_pspec(G_OBJECT(account
), properties
[PROP_CONNECTION
]);
1695 purple_account_set_remember_password(PurpleAccount
*account
, gboolean value
)
1697 PurpleAccountPrivate
*priv
;
1699 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1701 priv
= purple_account_get_instance_private(account
);
1702 priv
->remember_pass
= value
;
1704 g_object_notify_by_pspec(G_OBJECT(account
),
1705 properties
[PROP_REMEMBER_PASSWORD
]);
1707 purple_accounts_schedule_save();
1711 purple_account_set_check_mail(PurpleAccount
*account
, gboolean value
)
1713 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1715 purple_account_set_bool(account
, "check-mail", value
);
1717 g_object_notify_by_pspec(G_OBJECT(account
), properties
[PROP_CHECK_MAIL
]);
1721 purple_account_set_enabled(PurpleAccount
*account
, const char *ui
,
1724 PurpleConnection
*gc
;
1725 PurpleAccountPrivate
*priv
;
1726 gboolean was_enabled
= FALSE
;
1728 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1729 g_return_if_fail(ui
!= NULL
);
1731 was_enabled
= purple_account_get_enabled(account
, ui
);
1733 purple_account_set_ui_bool(account
, ui
, "auto-login", value
);
1734 gc
= purple_account_get_connection(account
);
1736 if(was_enabled
&& !value
)
1737 purple_signal_emit(purple_accounts_get_handle(), "account-disabled", account
);
1738 else if(!was_enabled
&& value
)
1739 purple_signal_emit(purple_accounts_get_handle(), "account-enabled", account
);
1741 g_object_notify_by_pspec(G_OBJECT(account
), properties
[PROP_ENABLED
]);
1743 if ((gc
!= NULL
) && (_purple_connection_wants_to_die(gc
)))
1746 priv
= purple_account_get_instance_private(account
);
1748 if (value
&& purple_presence_is_online(priv
->presence
))
1749 purple_account_connect(account
);
1750 else if (!value
&& !purple_account_is_disconnected(account
))
1751 purple_account_disconnect(account
);
1755 purple_account_set_proxy_info(PurpleAccount
*account
, PurpleProxyInfo
*info
)
1757 PurpleAccountPrivate
*priv
;
1759 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1761 priv
= purple_account_get_instance_private(account
);
1763 if (priv
->proxy_info
!= NULL
)
1764 purple_proxy_info_destroy(priv
->proxy_info
);
1766 priv
->proxy_info
= info
;
1768 purple_accounts_schedule_save();
1772 purple_account_set_privacy_type(PurpleAccount
*account
, PurpleAccountPrivacyType privacy_type
)
1774 PurpleAccountPrivate
*priv
;
1776 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1778 priv
= purple_account_get_instance_private(account
);
1779 priv
->privacy_type
= privacy_type
;
1783 purple_account_set_status_types(PurpleAccount
*account
, GList
*status_types
)
1785 PurpleAccountPrivate
*priv
;
1787 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1789 priv
= purple_account_get_instance_private(account
);
1791 /* Out with the old... */
1792 g_list_free_full(priv
->status_types
,
1793 (GDestroyNotify
)purple_status_type_destroy
);
1795 /* In with the new... */
1796 priv
->status_types
= status_types
;
1800 purple_account_set_status(PurpleAccount
*account
, const char *status_id
,
1801 gboolean active
, ...)
1803 GList
*attrs
= NULL
;
1808 va_start(args
, active
);
1809 while ((id
= va_arg(args
, const char *)) != NULL
)
1811 attrs
= g_list_append(attrs
, (char *)id
);
1812 data
= va_arg(args
, void *);
1813 attrs
= g_list_append(attrs
, data
);
1815 purple_account_set_status_list(account
, status_id
, active
, attrs
);
1821 purple_account_set_status_list(PurpleAccount
*account
, const char *status_id
,
1822 gboolean active
, GList
*attrs
)
1824 PurpleStatus
*status
;
1826 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1827 g_return_if_fail(status_id
!= NULL
);
1829 status
= purple_account_get_status(account
, status_id
);
1832 purple_debug_error("account",
1833 "Invalid status ID '%s' for account %s (%s)\n",
1834 status_id
, purple_account_get_username(account
),
1835 purple_account_get_protocol_id(account
));
1839 if (active
|| purple_status_is_independent(status
))
1840 purple_status_set_active_with_attrs_list(status
, active
, attrs
);
1843 * Our current statuses are saved to accounts.xml (so that when we
1844 * reconnect, we go back to the previous status).
1846 purple_accounts_schedule_save();
1850 purple_account_set_public_alias(PurpleAccount
*account
,
1851 const char *alias
, PurpleSetPublicAliasSuccessCallback success_cb
,
1852 PurpleSetPublicAliasFailureCallback failure_cb
)
1854 PurpleConnection
*gc
;
1855 PurpleProtocol
*protocol
= NULL
;
1857 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1858 g_return_if_fail(purple_account_is_connected(account
));
1860 gc
= purple_account_get_connection(account
);
1861 protocol
= purple_connection_get_protocol(gc
);
1863 if (PURPLE_PROTOCOL_IMPLEMENTS(protocol
, SERVER
, set_public_alias
))
1864 purple_protocol_server_iface_set_public_alias(protocol
, gc
, alias
, success_cb
, failure_cb
);
1865 else if (failure_cb
) {
1866 struct public_alias_closure
*closure
=
1867 g_new0(struct public_alias_closure
, 1);
1868 closure
->account
= g_object_ref(account
);
1869 closure
->failure_cb
= failure_cb
;
1870 g_timeout_add(0, set_public_alias_unsupported
, closure
);
1875 purple_account_get_public_alias(PurpleAccount
*account
,
1876 PurpleGetPublicAliasSuccessCallback success_cb
,
1877 PurpleGetPublicAliasFailureCallback failure_cb
)
1879 PurpleConnection
*gc
;
1880 PurpleProtocol
*protocol
= NULL
;
1882 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1883 g_return_if_fail(purple_account_is_connected(account
));
1885 gc
= purple_account_get_connection(account
);
1886 protocol
= purple_connection_get_protocol(gc
);
1888 if (PURPLE_PROTOCOL_IMPLEMENTS(protocol
, SERVER
, get_public_alias
))
1889 purple_protocol_server_iface_get_public_alias(protocol
, gc
, success_cb
, failure_cb
);
1890 else if (failure_cb
) {
1891 struct public_alias_closure
*closure
=
1892 g_new0(struct public_alias_closure
, 1);
1893 closure
->account
= g_object_ref(account
);
1894 closure
->failure_cb
= failure_cb
;
1895 g_timeout_add(0, get_public_alias_unsupported
, closure
);
1900 purple_account_get_silence_suppression(PurpleAccount
*account
)
1902 return purple_account_get_bool(account
, "silence-suppression", FALSE
);
1906 purple_account_set_silence_suppression(PurpleAccount
*account
, gboolean value
)
1908 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1910 purple_account_set_bool(account
, "silence-suppression", value
);
1914 purple_account_clear_settings(PurpleAccount
*account
)
1916 PurpleAccountPrivate
*priv
;
1918 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1920 priv
= purple_account_get_instance_private(account
);
1921 g_hash_table_destroy(priv
->settings
);
1923 priv
->settings
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
1924 g_free
, delete_setting
);
1928 purple_account_remove_setting(PurpleAccount
*account
, const char *setting
)
1930 PurpleAccountPrivate
*priv
;
1932 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1933 g_return_if_fail(setting
!= NULL
);
1935 priv
= purple_account_get_instance_private(account
);
1937 g_hash_table_remove(priv
->settings
, setting
);
1941 purple_account_set_int(PurpleAccount
*account
, const char *name
, int value
)
1943 PurpleAccountSetting
*setting
;
1944 PurpleAccountPrivate
*priv
;
1946 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1947 g_return_if_fail(name
!= NULL
);
1949 priv
= purple_account_get_instance_private(account
);
1951 setting
= g_new0(PurpleAccountSetting
, 1);
1953 g_value_init(&setting
->value
, G_TYPE_INT
);
1954 g_value_set_int(&setting
->value
, value
);
1956 g_hash_table_insert(priv
->settings
, g_strdup(name
), setting
);
1958 purple_accounts_schedule_save();
1962 purple_account_set_string(PurpleAccount
*account
, const char *name
,
1965 PurpleAccountSetting
*setting
;
1966 PurpleAccountPrivate
*priv
;
1968 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1969 g_return_if_fail(name
!= NULL
);
1971 priv
= purple_account_get_instance_private(account
);
1973 setting
= g_new0(PurpleAccountSetting
, 1);
1975 g_value_init(&setting
->value
, G_TYPE_STRING
);
1976 g_value_set_string(&setting
->value
, value
);
1978 g_hash_table_insert(priv
->settings
, g_strdup(name
), setting
);
1980 purple_accounts_schedule_save();
1984 purple_account_set_bool(PurpleAccount
*account
, const char *name
, gboolean value
)
1986 PurpleAccountSetting
*setting
;
1987 PurpleAccountPrivate
*priv
;
1989 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
1990 g_return_if_fail(name
!= NULL
);
1992 priv
= purple_account_get_instance_private(account
);
1994 setting
= g_new0(PurpleAccountSetting
, 1);
1996 g_value_init(&setting
->value
, G_TYPE_BOOLEAN
);
1997 g_value_set_boolean(&setting
->value
, value
);
1999 g_hash_table_insert(priv
->settings
, g_strdup(name
), setting
);
2001 purple_accounts_schedule_save();
2005 purple_account_set_ui_int(PurpleAccount
*account
, const char *ui
,
2006 const char *name
, int value
)
2008 PurpleAccountSetting
*setting
;
2011 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
2012 g_return_if_fail(ui
!= NULL
);
2013 g_return_if_fail(name
!= NULL
);
2015 setting
= g_new0(PurpleAccountSetting
, 1);
2017 setting
->ui
= g_strdup(ui
);
2018 g_value_init(&setting
->value
, G_TYPE_INT
);
2019 g_value_set_int(&setting
->value
, value
);
2021 table
= get_ui_settings_table(account
, ui
);
2023 g_hash_table_insert(table
, g_strdup(name
), setting
);
2025 purple_accounts_schedule_save();
2029 purple_account_set_ui_string(PurpleAccount
*account
, const char *ui
,
2030 const char *name
, const char *value
)
2032 PurpleAccountSetting
*setting
;
2035 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
2036 g_return_if_fail(ui
!= NULL
);
2037 g_return_if_fail(name
!= NULL
);
2039 setting
= g_new0(PurpleAccountSetting
, 1);
2041 setting
->ui
= g_strdup(ui
);
2042 g_value_init(&setting
->value
, G_TYPE_STRING
);
2043 g_value_set_string(&setting
->value
, value
);
2045 table
= get_ui_settings_table(account
, ui
);
2047 g_hash_table_insert(table
, g_strdup(name
), setting
);
2049 purple_accounts_schedule_save();
2053 purple_account_set_ui_bool(PurpleAccount
*account
, const char *ui
,
2054 const char *name
, gboolean value
)
2056 PurpleAccountSetting
*setting
;
2059 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
2060 g_return_if_fail(ui
!= NULL
);
2061 g_return_if_fail(name
!= NULL
);
2063 setting
= g_new0(PurpleAccountSetting
, 1);
2065 setting
->ui
= g_strdup(ui
);
2066 g_value_init(&setting
->value
, G_TYPE_BOOLEAN
);
2067 g_value_set_boolean(&setting
->value
, value
);
2069 table
= get_ui_settings_table(account
, ui
);
2071 g_hash_table_insert(table
, g_strdup(name
), setting
);
2073 purple_accounts_schedule_save();
2077 purple_account_is_connected(PurpleAccount
*account
)
2079 return (purple_account_get_state(account
) == PURPLE_CONNECTION_CONNECTED
);
2083 purple_account_is_connecting(PurpleAccount
*account
)
2085 return (purple_account_get_state(account
) == PURPLE_CONNECTION_CONNECTING
);
2089 purple_account_is_disconnected(PurpleAccount
*account
)
2091 return (purple_account_get_state(account
) == PURPLE_CONNECTION_DISCONNECTED
);
2095 purple_account_get_username(PurpleAccount
*account
)
2097 PurpleAccountPrivate
*priv
;
2099 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2101 priv
= purple_account_get_instance_private(account
);
2102 return priv
->username
;
2106 purple_account_get_password(PurpleAccount
*account
,
2107 PurpleKeyringReadCallback cb
, gpointer data
)
2109 PurpleAccountPrivate
*priv
;
2111 if (account
== NULL
) {
2112 cb(NULL
, NULL
, NULL
, data
);
2116 priv
= purple_account_get_instance_private(account
);
2118 if (priv
->password
!= NULL
) {
2119 purple_debug_info("account",
2120 "Reading password for account %s from cache.\n",
2121 purple_account_get_username(account
));
2122 cb(account
, priv
->password
, NULL
, data
);
2124 PurpleCallbackBundle
*cbb
= g_new0(PurpleCallbackBundle
, 1);
2125 cbb
->cb
= PURPLE_CALLBACK(cb
);
2128 purple_debug_info("account",
2129 "Reading password for account %s from async keyring.\n",
2130 purple_account_get_username(account
));
2131 purple_keyring_get_password(account
,
2132 purple_account_get_password_got
, cbb
);
2137 purple_account_get_private_alias(PurpleAccount
*account
)
2139 PurpleAccountPrivate
*priv
;
2141 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2143 priv
= purple_account_get_instance_private(account
);
2148 purple_account_get_user_info(PurpleAccount
*account
)
2150 PurpleAccountPrivate
*priv
;
2152 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2154 priv
= purple_account_get_instance_private(account
);
2155 return priv
->user_info
;
2159 purple_account_get_buddy_icon_path(PurpleAccount
*account
)
2161 PurpleAccountPrivate
*priv
;
2163 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2165 priv
= purple_account_get_instance_private(account
);
2166 return priv
->buddy_icon_path
;
2170 purple_account_get_protocol_id(PurpleAccount
*account
)
2172 PurpleAccountPrivate
*priv
;
2174 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2176 priv
= purple_account_get_instance_private(account
);
2177 return priv
->protocol_id
;
2181 purple_account_get_protocol_name(PurpleAccount
*account
)
2185 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2187 p
= purple_protocols_find(purple_account_get_protocol_id(account
));
2189 return (p
&& purple_protocol_get_name(p
) ?
2190 _(purple_protocol_get_name(p
)) : _("Unknown"));
2194 purple_account_get_connection(PurpleAccount
*account
)
2196 PurpleAccountPrivate
*priv
;
2198 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2200 priv
= purple_account_get_instance_private(account
);
2205 purple_account_get_name_for_display(PurpleAccount
*account
)
2207 PurpleBuddy
*self
= NULL
;
2208 PurpleConnection
*gc
= NULL
;
2209 const gchar
*name
= NULL
, *username
= NULL
, *displayname
= NULL
;
2211 name
= purple_account_get_private_alias(account
);
2217 username
= purple_account_get_username(account
);
2218 self
= purple_blist_find_buddy((PurpleAccount
*)account
, username
);
2221 const gchar
*calias
= purple_buddy_get_contact_alias(self
);
2223 /* We don't want to return the buddy name if the buddy/contact
2224 * doesn't have an alias set. */
2225 if (!purple_strequal(username
, calias
)) {
2230 gc
= purple_account_get_connection(account
);
2231 displayname
= purple_connection_get_display_name(gc
);
2241 purple_account_get_remember_password(PurpleAccount
*account
)
2243 PurpleAccountPrivate
*priv
;
2245 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), FALSE
);
2247 priv
= purple_account_get_instance_private(account
);
2248 return priv
->remember_pass
;
2252 purple_account_get_check_mail(PurpleAccount
*account
)
2254 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), FALSE
);
2256 return purple_account_get_bool(account
, "check-mail", FALSE
);
2260 purple_account_get_enabled(PurpleAccount
*account
, const char *ui
)
2262 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), FALSE
);
2263 g_return_val_if_fail(ui
!= NULL
, FALSE
);
2265 return purple_account_get_ui_bool(account
, ui
, "auto-login", FALSE
);
2269 purple_account_get_proxy_info(PurpleAccount
*account
)
2271 PurpleAccountPrivate
*priv
;
2273 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2275 priv
= purple_account_get_instance_private(account
);
2276 return priv
->proxy_info
;
2279 PurpleAccountPrivacyType
2280 purple_account_get_privacy_type(PurpleAccount
*account
)
2282 PurpleAccountPrivate
*priv
;
2284 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL
);
2286 priv
= purple_account_get_instance_private(account
);
2287 return priv
->privacy_type
;
2291 purple_account_privacy_permit_add(PurpleAccount
*account
, const char *who
,
2292 gboolean local_only
)
2297 PurpleAccountPrivate
*priv
;
2298 PurpleAccountUiOps
*ui_ops
= purple_accounts_get_ui_ops();
2300 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), FALSE
);
2301 g_return_val_if_fail(who
!= NULL
, FALSE
);
2303 priv
= purple_account_get_instance_private(account
);
2304 name
= g_strdup(purple_normalize(account
, who
));
2306 for (l
= priv
->permit
; l
!= NULL
; l
= l
->next
) {
2307 if (g_str_equal(name
, l
->data
))
2308 /* This buddy already exists */
2314 /* This buddy already exists, so bail out */
2319 priv
->permit
= g_slist_append(priv
->permit
, name
);
2321 if (!local_only
&& purple_account_is_connected(account
))
2322 purple_serv_add_permit(purple_account_get_connection(account
), who
);
2324 if (ui_ops
!= NULL
&& ui_ops
->permit_added
!= NULL
)
2325 ui_ops
->permit_added(account
, who
);
2327 purple_blist_save_account(purple_blist_get_default(), account
);
2329 /* This lets the UI know a buddy has had its privacy setting changed */
2330 buddy
= purple_blist_find_buddy(account
, name
);
2331 if (buddy
!= NULL
) {
2332 purple_signal_emit(purple_blist_get_handle(),
2333 "buddy-privacy-changed", buddy
);
2339 purple_account_privacy_permit_remove(PurpleAccount
*account
, const char *who
,
2340 gboolean local_only
)
2346 PurpleAccountPrivate
*priv
;
2347 PurpleAccountUiOps
*ui_ops
= purple_accounts_get_ui_ops();
2349 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), FALSE
);
2350 g_return_val_if_fail(who
!= NULL
, FALSE
);
2352 priv
= purple_account_get_instance_private(account
);
2353 name
= purple_normalize(account
, who
);
2355 for (l
= priv
->permit
; l
!= NULL
; l
= l
->next
) {
2356 if (g_str_equal(name
, l
->data
))
2357 /* We found the buddy we were looking for */
2362 /* We didn't find the buddy we were looking for, so bail out */
2365 /* We should not free l->data just yet. There can be occasions where
2366 * l->data == who. In such cases, freeing l->data here can cause crashes
2367 * later when who is used. */
2369 priv
->permit
= g_slist_delete_link(priv
->permit
, l
);
2371 if (!local_only
&& purple_account_is_connected(account
))
2372 purple_serv_rem_permit(purple_account_get_connection(account
), who
);
2374 if (ui_ops
!= NULL
&& ui_ops
->permit_removed
!= NULL
)
2375 ui_ops
->permit_removed(account
, who
);
2377 purple_blist_save_account(purple_blist_get_default(), account
);
2379 buddy
= purple_blist_find_buddy(account
, name
);
2380 if (buddy
!= NULL
) {
2381 purple_signal_emit(purple_blist_get_handle(),
2382 "buddy-privacy-changed", buddy
);
2389 purple_account_privacy_deny_add(PurpleAccount
*account
, const char *who
,
2390 gboolean local_only
)
2395 PurpleAccountPrivate
*priv
;
2396 PurpleAccountUiOps
*ui_ops
= purple_accounts_get_ui_ops();
2398 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), FALSE
);
2399 g_return_val_if_fail(who
!= NULL
, FALSE
);
2401 priv
= purple_account_get_instance_private(account
);
2402 name
= g_strdup(purple_normalize(account
, who
));
2404 for (l
= priv
->deny
; l
!= NULL
; l
= l
->next
) {
2405 if (g_str_equal(name
, l
->data
))
2406 /* This buddy already exists */
2412 /* This buddy already exists, so bail out */
2417 priv
->deny
= g_slist_append(priv
->deny
, name
);
2419 if (!local_only
&& purple_account_is_connected(account
))
2420 purple_serv_add_deny(purple_account_get_connection(account
), who
);
2422 if (ui_ops
!= NULL
&& ui_ops
->deny_added
!= NULL
)
2423 ui_ops
->deny_added(account
, who
);
2425 purple_blist_save_account(purple_blist_get_default(), account
);
2427 buddy
= purple_blist_find_buddy(account
, name
);
2428 if (buddy
!= NULL
) {
2429 purple_signal_emit(purple_blist_get_handle(),
2430 "buddy-privacy-changed", buddy
);
2436 purple_account_privacy_deny_remove(PurpleAccount
*account
, const char *who
,
2437 gboolean local_only
)
2440 const char *normalized
;
2443 PurpleAccountPrivate
*priv
;
2444 PurpleAccountUiOps
*ui_ops
= purple_accounts_get_ui_ops();
2446 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), FALSE
);
2447 g_return_val_if_fail(who
!= NULL
, FALSE
);
2449 priv
= purple_account_get_instance_private(account
);
2450 normalized
= purple_normalize(account
, who
);
2452 for (l
= priv
->deny
; l
!= NULL
; l
= l
->next
) {
2453 if (g_str_equal(normalized
, l
->data
))
2454 /* We found the buddy we were looking for */
2459 /* We didn't find the buddy we were looking for, so bail out */
2462 buddy
= purple_blist_find_buddy(account
, normalized
);
2465 priv
->deny
= g_slist_delete_link(priv
->deny
, l
);
2467 if (!local_only
&& purple_account_is_connected(account
))
2468 purple_serv_rem_deny(purple_account_get_connection(account
), name
);
2470 if (ui_ops
!= NULL
&& ui_ops
->deny_removed
!= NULL
)
2471 ui_ops
->deny_removed(account
, who
);
2473 if (buddy
!= NULL
) {
2474 purple_signal_emit(purple_blist_get_handle(),
2475 "buddy-privacy-changed", buddy
);
2480 purple_blist_save_account(purple_blist_get_default(), account
);
2486 purple_account_privacy_allow(PurpleAccount
*account
, const char *who
)
2489 PurpleAccountPrivacyType type
= purple_account_get_privacy_type(account
);
2490 PurpleAccountPrivate
*priv
= purple_account_get_instance_private(account
);
2493 case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL
:
2495 case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
:
2496 purple_account_privacy_permit_add(account
, who
, FALSE
);
2498 case PURPLE_ACCOUNT_PRIVACY_DENY_USERS
:
2499 purple_account_privacy_deny_remove(account
, who
, FALSE
);
2501 case PURPLE_ACCOUNT_PRIVACY_DENY_ALL
:
2503 /* Empty the allow-list. */
2504 const char *norm
= purple_normalize(account
, who
);
2505 for (list
= priv
->permit
; list
!= NULL
;) {
2506 char *person
= list
->data
;
2508 if (!purple_strequal(norm
, person
))
2509 purple_account_privacy_permit_remove(account
, person
, FALSE
);
2511 purple_account_privacy_permit_add(account
, who
, FALSE
);
2512 purple_account_set_privacy_type(account
, PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
);
2515 case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST
:
2516 if (!purple_blist_find_buddy(account
, who
)) {
2517 add_all_buddies_to_permit_list(account
, FALSE
);
2518 purple_account_privacy_permit_add(account
, who
, FALSE
);
2519 purple_account_set_privacy_type(account
, PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
);
2523 g_return_if_reached();
2526 /* Notify the server if the privacy setting was changed */
2527 if (type
!= purple_account_get_privacy_type(account
) && purple_account_is_connected(account
))
2528 purple_serv_set_permit_deny(purple_account_get_connection(account
));
2532 purple_account_privacy_deny(PurpleAccount
*account
, const char *who
)
2535 PurpleAccountPrivacyType type
= purple_account_get_privacy_type(account
);
2536 PurpleAccountPrivate
*priv
= purple_account_get_instance_private(account
);
2539 case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL
:
2541 /* Empty the deny-list. */
2542 const char *norm
= purple_normalize(account
, who
);
2543 for (list
= priv
->deny
; list
!= NULL
; ) {
2544 char *person
= list
->data
;
2546 if (!purple_strequal(norm
, person
))
2547 purple_account_privacy_deny_remove(account
, person
, FALSE
);
2549 purple_account_privacy_deny_add(account
, who
, FALSE
);
2550 purple_account_set_privacy_type(account
, PURPLE_ACCOUNT_PRIVACY_DENY_USERS
);
2553 case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
:
2554 purple_account_privacy_permit_remove(account
, who
, FALSE
);
2556 case PURPLE_ACCOUNT_PRIVACY_DENY_USERS
:
2557 purple_account_privacy_deny_add(account
, who
, FALSE
);
2559 case PURPLE_ACCOUNT_PRIVACY_DENY_ALL
:
2561 case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST
:
2562 if (purple_blist_find_buddy(account
, who
)) {
2563 add_all_buddies_to_permit_list(account
, FALSE
);
2564 purple_account_privacy_permit_remove(account
, who
, FALSE
);
2565 purple_account_set_privacy_type(account
, PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
);
2569 g_return_if_reached();
2572 /* Notify the server if the privacy setting was changed */
2573 if (type
!= purple_account_get_privacy_type(account
) && purple_account_is_connected(account
))
2574 purple_serv_set_permit_deny(purple_account_get_connection(account
));
2578 purple_account_privacy_get_permitted(PurpleAccount
*account
)
2580 PurpleAccountPrivate
*priv
= NULL
;
2582 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2584 priv
= purple_account_get_instance_private(account
);
2585 return priv
->permit
;
2589 purple_account_privacy_get_denied(PurpleAccount
*account
)
2591 PurpleAccountPrivate
*priv
= NULL
;
2593 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2595 priv
= purple_account_get_instance_private(account
);
2600 purple_account_privacy_check(PurpleAccount
*account
, const char *who
)
2603 PurpleAccountPrivate
*priv
= purple_account_get_instance_private(account
);
2605 switch (purple_account_get_privacy_type(account
)) {
2606 case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL
:
2609 case PURPLE_ACCOUNT_PRIVACY_DENY_ALL
:
2612 case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
:
2613 who
= purple_normalize(account
, who
);
2614 for (list
=priv
->permit
; list
!=NULL
; list
=list
->next
) {
2615 if (g_str_equal(who
, list
->data
))
2620 case PURPLE_ACCOUNT_PRIVACY_DENY_USERS
:
2621 who
= purple_normalize(account
, who
);
2622 for (list
=priv
->deny
; list
!=NULL
; list
=list
->next
) {
2623 if (g_str_equal(who
, list
->data
))
2628 case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST
:
2629 return (purple_blist_find_buddy(account
, who
) != NULL
);
2632 g_return_val_if_reached(TRUE
);
2637 purple_account_get_active_status(PurpleAccount
*account
)
2639 PurpleAccountPrivate
*priv
;
2641 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2643 priv
= purple_account_get_instance_private(account
);
2644 return purple_presence_get_active_status(priv
->presence
);
2648 purple_account_get_status(PurpleAccount
*account
, const char *status_id
)
2650 PurpleAccountPrivate
*priv
;
2652 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2653 g_return_val_if_fail(status_id
!= NULL
, NULL
);
2655 priv
= purple_account_get_instance_private(account
);
2657 return purple_presence_get_status(priv
->presence
, status_id
);
2661 purple_account_get_status_type(PurpleAccount
*account
, const char *id
)
2665 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2666 g_return_val_if_fail(id
!= NULL
, NULL
);
2668 for (l
= purple_account_get_status_types(account
); l
!= NULL
; l
= l
->next
)
2670 PurpleStatusType
*status_type
= (PurpleStatusType
*)l
->data
;
2672 if (purple_strequal(purple_status_type_get_id(status_type
), id
))
2680 purple_account_get_status_type_with_primitive(PurpleAccount
*account
, PurpleStatusPrimitive primitive
)
2684 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2686 for (l
= purple_account_get_status_types(account
); l
!= NULL
; l
= l
->next
)
2688 PurpleStatusType
*status_type
= (PurpleStatusType
*)l
->data
;
2690 if (purple_status_type_get_primitive(status_type
) == primitive
)
2698 purple_account_get_presence(PurpleAccount
*account
)
2700 PurpleAccountPrivate
*priv
;
2702 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2704 priv
= purple_account_get_instance_private(account
);
2705 return priv
->presence
;
2709 purple_account_is_status_active(PurpleAccount
*account
,
2710 const char *status_id
)
2712 PurpleAccountPrivate
*priv
;
2714 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), FALSE
);
2715 g_return_val_if_fail(status_id
!= NULL
, FALSE
);
2717 priv
= purple_account_get_instance_private(account
);
2719 return purple_presence_is_status_active(priv
->presence
, status_id
);
2723 purple_account_get_status_types(PurpleAccount
*account
)
2725 PurpleAccountPrivate
*priv
;
2727 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2729 priv
= purple_account_get_instance_private(account
);
2730 return priv
->status_types
;
2734 purple_account_get_int(PurpleAccount
*account
, const char *name
,
2737 PurpleAccountSetting
*setting
;
2738 PurpleAccountPrivate
*priv
;
2740 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), default_value
);
2741 g_return_val_if_fail(name
!= NULL
, default_value
);
2743 priv
= purple_account_get_instance_private(account
);
2745 setting
= g_hash_table_lookup(priv
->settings
, name
);
2747 if (setting
== NULL
)
2748 return default_value
;
2750 g_return_val_if_fail(G_VALUE_HOLDS_INT(&setting
->value
), default_value
);
2752 return g_value_get_int(&setting
->value
);
2756 purple_account_get_string(PurpleAccount
*account
, const char *name
,
2757 const char *default_value
)
2759 PurpleAccountSetting
*setting
;
2760 PurpleAccountPrivate
*priv
;
2762 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), default_value
);
2763 g_return_val_if_fail(name
!= NULL
, default_value
);
2765 priv
= purple_account_get_instance_private(account
);
2767 setting
= g_hash_table_lookup(priv
->settings
, name
);
2769 if (setting
== NULL
)
2770 return default_value
;
2772 g_return_val_if_fail(G_VALUE_HOLDS_STRING(&setting
->value
), default_value
);
2774 return g_value_get_string(&setting
->value
);
2778 purple_account_get_bool(PurpleAccount
*account
, const char *name
,
2779 gboolean default_value
)
2781 PurpleAccountSetting
*setting
;
2782 PurpleAccountPrivate
*priv
;
2784 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), default_value
);
2785 g_return_val_if_fail(name
!= NULL
, default_value
);
2787 priv
= purple_account_get_instance_private(account
);
2789 setting
= g_hash_table_lookup(priv
->settings
, name
);
2791 if (setting
== NULL
)
2792 return default_value
;
2794 g_return_val_if_fail(G_VALUE_HOLDS_BOOLEAN(&setting
->value
), default_value
);
2796 return g_value_get_boolean(&setting
->value
);
2800 purple_account_get_ui_int(PurpleAccount
*account
, const char *ui
,
2801 const char *name
, int default_value
)
2803 PurpleAccountSetting
*setting
;
2804 PurpleAccountPrivate
*priv
;
2807 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), default_value
);
2808 g_return_val_if_fail(ui
!= NULL
, default_value
);
2809 g_return_val_if_fail(name
!= NULL
, default_value
);
2811 priv
= purple_account_get_instance_private(account
);
2813 if ((table
= g_hash_table_lookup(priv
->ui_settings
, ui
)) == NULL
)
2814 return default_value
;
2816 if ((setting
= g_hash_table_lookup(table
, name
)) == NULL
)
2817 return default_value
;
2819 g_return_val_if_fail(G_VALUE_HOLDS_INT(&setting
->value
), default_value
);
2821 return g_value_get_int(&setting
->value
);
2825 purple_account_get_ui_string(PurpleAccount
*account
, const char *ui
,
2826 const char *name
, const char *default_value
)
2828 PurpleAccountSetting
*setting
;
2829 PurpleAccountPrivate
*priv
;
2832 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), default_value
);
2833 g_return_val_if_fail(ui
!= NULL
, default_value
);
2834 g_return_val_if_fail(name
!= NULL
, default_value
);
2836 priv
= purple_account_get_instance_private(account
);
2838 if ((table
= g_hash_table_lookup(priv
->ui_settings
, ui
)) == NULL
)
2839 return default_value
;
2841 if ((setting
= g_hash_table_lookup(table
, name
)) == NULL
)
2842 return default_value
;
2844 g_return_val_if_fail(G_VALUE_HOLDS_STRING(&setting
->value
), default_value
);
2846 return g_value_get_string(&setting
->value
);
2850 purple_account_get_ui_bool(PurpleAccount
*account
, const char *ui
,
2851 const char *name
, gboolean default_value
)
2853 PurpleAccountSetting
*setting
;
2854 PurpleAccountPrivate
*priv
;
2857 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), default_value
);
2858 g_return_val_if_fail(ui
!= NULL
, default_value
);
2859 g_return_val_if_fail(name
!= NULL
, default_value
);
2861 priv
= purple_account_get_instance_private(account
);
2863 if ((table
= g_hash_table_lookup(priv
->ui_settings
, ui
)) == NULL
)
2864 return default_value
;
2866 if ((setting
= g_hash_table_lookup(table
, name
)) == NULL
)
2867 return default_value
;
2869 g_return_val_if_fail(G_VALUE_HOLDS_BOOLEAN(&setting
->value
), default_value
);
2871 return g_value_get_boolean(&setting
->value
);
2875 purple_account_get_log(PurpleAccount
*account
, gboolean create
)
2877 PurpleAccountPrivate
*priv
;
2879 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), NULL
);
2881 priv
= purple_account_get_instance_private(account
);
2883 if(!priv
->system_log
&& create
){
2884 PurplePresence
*presence
;
2888 presence
= purple_account_get_presence(account
);
2889 login_time
= purple_presence_get_login_time(presence
);
2890 if (login_time
!= 0) {
2891 dt
= g_date_time_new_from_unix_local(login_time
);
2893 dt
= g_date_time_new_now_local();
2896 priv
->system_log
= purple_log_new(PURPLE_LOG_SYSTEM
,
2897 purple_account_get_username(account
),
2899 g_date_time_unref(dt
);
2902 return priv
->system_log
;
2906 purple_account_destroy_log(PurpleAccount
*account
)
2908 PurpleAccountPrivate
*priv
;
2910 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
2912 priv
= purple_account_get_instance_private(account
);
2914 if(priv
->system_log
){
2915 purple_log_free(priv
->system_log
);
2916 priv
->system_log
= NULL
;
2921 purple_account_add_buddy(PurpleAccount
*account
, PurpleBuddy
*buddy
, const char *message
)
2923 PurpleProtocol
*protocol
= NULL
;
2924 PurpleConnection
*gc
;
2926 g_return_if_fail(PURPLE_IS_ACCOUNT(account
));
2927 g_return_if_fail(PURPLE_IS_BUDDY(buddy
));
2929 gc
= purple_account_get_connection(account
);
2931 protocol
= purple_connection_get_protocol(gc
);
2933 if (protocol
!= NULL
)
2934 purple_protocol_server_iface_add_buddy(protocol
, gc
, buddy
,
2935 purple_buddy_get_group(buddy
), message
);
2939 purple_account_add_buddies(PurpleAccount
*account
, GList
*buddies
, const char *message
)
2941 PurpleProtocol
*protocol
= NULL
;
2942 PurpleConnection
*gc
= purple_account_get_connection(account
);
2945 protocol
= purple_connection_get_protocol(gc
);
2948 GList
*cur
, *groups
= NULL
;
2950 /* Make a list of what group each buddy is in */
2951 for (cur
= buddies
; cur
!= NULL
; cur
= cur
->next
) {
2952 PurpleBuddy
*buddy
= cur
->data
;
2953 groups
= g_list_append(groups
, purple_buddy_get_group(buddy
));
2956 if (PURPLE_PROTOCOL_IMPLEMENTS(protocol
, SERVER
, add_buddies
))
2957 purple_protocol_server_iface_add_buddies(protocol
, gc
, buddies
, groups
, message
);
2958 else if (PURPLE_PROTOCOL_IMPLEMENTS(protocol
, SERVER
, add_buddy
)) {
2959 GList
*curb
= buddies
, *curg
= groups
;
2961 while ((curb
!= NULL
) && (curg
!= NULL
)) {
2962 purple_protocol_server_iface_add_buddy(protocol
, gc
, curb
->data
, curg
->data
, message
);
2968 g_list_free(groups
);
2973 purple_account_remove_buddy(PurpleAccount
*account
, PurpleBuddy
*buddy
,
2976 PurpleProtocol
*protocol
= NULL
;
2977 PurpleConnection
*gc
= purple_account_get_connection(account
);
2980 protocol
= purple_connection_get_protocol(gc
);
2983 purple_protocol_server_iface_remove_buddy(protocol
, gc
, buddy
, group
);
2987 purple_account_remove_buddies(PurpleAccount
*account
, GList
*buddies
, GList
*groups
)
2989 PurpleProtocol
*protocol
= NULL
;
2990 PurpleConnection
*gc
= purple_account_get_connection(account
);
2993 protocol
= purple_connection_get_protocol(gc
);
2996 if (PURPLE_PROTOCOL_IMPLEMENTS(protocol
, SERVER
, remove_buddies
))
2997 purple_protocol_server_iface_remove_buddies(protocol
, gc
, buddies
, groups
);
2999 GList
*curb
= buddies
;
3000 GList
*curg
= groups
;
3001 while ((curb
!= NULL
) && (curg
!= NULL
)) {
3002 purple_account_remove_buddy(account
, curb
->data
, curg
->data
);
3011 purple_account_remove_group(PurpleAccount
*account
, PurpleGroup
*group
)
3013 PurpleProtocol
*protocol
= NULL
;
3014 PurpleConnection
*gc
= purple_account_get_connection(account
);
3017 protocol
= purple_connection_get_protocol(gc
);
3020 purple_protocol_server_iface_remove_group(protocol
, gc
, group
);
3024 purple_account_change_password(PurpleAccount
*account
, const char *orig_pw
,
3027 PurpleProtocol
*protocol
= NULL
;
3028 PurpleConnection
*gc
= purple_account_get_connection(account
);
3030 purple_account_set_password(account
, new_pw
, NULL
, NULL
);
3033 protocol
= purple_connection_get_protocol(gc
);
3036 purple_protocol_server_iface_change_passwd(protocol
, gc
, orig_pw
, new_pw
);
3039 gboolean
purple_account_supports_offline_message(PurpleAccount
*account
, PurpleBuddy
*buddy
)
3041 PurpleConnection
*gc
;
3042 PurpleProtocol
*protocol
= NULL
;
3044 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), FALSE
);
3045 g_return_val_if_fail(PURPLE_IS_BUDDY(buddy
), FALSE
);
3047 gc
= purple_account_get_connection(account
);
3051 protocol
= purple_connection_get_protocol(gc
);
3055 return purple_protocol_client_iface_offline_message(protocol
, buddy
);
3058 const PurpleConnectionErrorInfo
*
3059 purple_account_get_current_error(PurpleAccount
*account
)
3061 PurpleAccountPrivate
*priv
= purple_account_get_instance_private(account
);
3063 return priv
->current_error
;
3067 purple_account_clear_current_error(PurpleAccount
*account
)
3069 _purple_account_set_current_error(account
, NULL
);