Merged default into xdg-dirs
[pidgin-git.git] / libpurple / account.c
blobbcbaa5a74d6242665602a9faf78a9954cec5468c
1 /* purple
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
5 * source distribution.
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
21 #include "internal.h"
22 #include "glibcompat.h"
24 #include "accounts.h"
25 #include "core.h"
26 #include "dbus-maybe.h"
27 #include "debug.h"
28 #include "network.h"
29 #include "notify.h"
30 #include "pounce.h"
31 #include "prefs.h"
32 #include "request.h"
33 #include "server.h"
34 #include "signals.h"
35 #include "util.h"
37 #define PURPLE_ACCOUNT_GET_PRIVATE(obj) \
38 (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_ACCOUNT, PurpleAccountPrivate))
40 typedef struct
42 char *username; /* The username. */
43 char *alias; /* How you appear to yourself. */
44 char *password; /* The account password. */
45 char *user_info; /* User information. */
47 char *buddy_icon_path; /* The buddy icon's non-cached path. */
49 gboolean remember_pass; /* Remember the password. */
52 * TODO: After a GObject representing a protocol is ready, use it
53 * here instead of the protocol ID.
55 char *protocol_id; /* The ID of the protocol. */
57 PurpleConnection *gc; /* The connection handle. */
58 gboolean disconnecting; /* The account is currently disconnecting */
60 GHashTable *settings; /* Protocol-specific settings. */
61 GHashTable *ui_settings; /* UI-specific settings. */
63 PurpleProxyInfo *proxy_info; /* Proxy information. This will be set */
64 /* to NULL when the account inherits */
65 /* proxy settings from global prefs. */
68 * TODO: Instead of linked lists for permit and deny, use a data
69 * structure that allows fast lookups AND decent performance when
70 * iterating through all items. Fast lookups should help performance
71 * for protocols like MSN, where all your buddies exist in your permit
72 * list therefore the permit list is large. Possibly GTree or
73 * GHashTable.
75 GSList *permit; /* Permit list. */
76 GSList *deny; /* Deny list. */
77 PurpleAccountPrivacyType privacy_type; /* The permit/deny setting. */
79 GList *status_types; /* Status types. */
81 PurplePresence *presence; /* Presence. */
82 PurpleLog *system_log; /* The system log */
84 PurpleAccountRegistrationCb registration_cb;
85 void *registration_cb_user_data;
87 PurpleConnectionErrorInfo *current_error; /* Errors */
88 } PurpleAccountPrivate;
90 typedef struct
92 char *ui;
93 GValue value;
95 } PurpleAccountSetting;
97 typedef struct
99 PurpleAccountRequestType type;
100 PurpleAccount *account;
101 void *ui_handle;
102 char *user;
103 gpointer userdata;
104 PurpleAccountRequestAuthorizationCb auth_cb;
105 PurpleAccountRequestAuthorizationCb deny_cb;
106 guint ref;
107 } PurpleAccountRequestInfo;
109 typedef struct
111 PurpleCallback cb;
112 gpointer data;
113 } PurpleCallbackBundle;
115 /* GObject Property enums */
116 enum
118 PROP_0,
119 PROP_USERNAME,
120 PROP_PRIVATE_ALIAS,
121 PROP_ENABLED,
122 PROP_CONNECTION,
123 PROP_PROTOCOL_ID,
124 PROP_USER_INFO,
125 PROP_BUDDY_ICON_PATH,
126 PROP_REMEMBER_PASSWORD,
127 PROP_CHECK_MAIL,
128 PROP_LAST
131 static GObjectClass *parent_class = NULL;
132 static GParamSpec *properties[PROP_LAST];
133 static GList *handles = NULL;
135 /***************
136 * Account API *
137 ***************/
138 void
139 purple_account_set_register_callback(PurpleAccount *account, PurpleAccountRegistrationCb cb, void *user_data)
141 PurpleAccountPrivate *priv;
143 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
145 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
147 priv->registration_cb = cb;
148 priv->registration_cb_user_data = user_data;
151 static void
152 purple_account_register_got_password_cb(PurpleAccount *account,
153 const gchar *password, GError *error, gpointer data)
155 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
157 _purple_connection_new(account, TRUE, password);
160 void
161 purple_account_register(PurpleAccount *account)
163 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
165 purple_debug_info("account", "Registering account %s\n",
166 purple_account_get_username(account));
168 purple_keyring_get_password(account,
169 purple_account_register_got_password_cb, NULL);
172 static void
173 purple_account_unregister_got_password_cb(PurpleAccount *account,
174 const gchar *password, GError *error, gpointer data)
176 PurpleCallbackBundle *cbb = data;
177 PurpleAccountUnregistrationCb cb;
179 cb = (PurpleAccountUnregistrationCb)cbb->cb;
180 _purple_connection_new_unregister(account, password, cb, cbb->data);
182 g_free(cbb);
185 struct register_completed_closure
187 PurpleAccount *account;
188 gboolean succeeded;
191 static gboolean
192 purple_account_register_completed_cb(gpointer data)
194 struct register_completed_closure *closure = data;
195 PurpleAccountPrivate *priv;
197 priv = PURPLE_ACCOUNT_GET_PRIVATE(closure->account);
199 if (priv->registration_cb)
200 (priv->registration_cb)(closure->account, closure->succeeded,
201 priv->registration_cb_user_data);
203 g_object_unref(closure->account);
204 g_free(closure);
206 return FALSE;
209 void
210 purple_account_register_completed(PurpleAccount *account, gboolean succeeded)
212 struct register_completed_closure *closure;
214 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
216 closure = g_new0(struct register_completed_closure, 1);
217 closure->account = g_object_ref(account);
218 closure->succeeded = succeeded;
220 g_timeout_add(0, purple_account_register_completed_cb, closure);
223 void
224 purple_account_unregister(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data)
226 PurpleCallbackBundle *cbb;
228 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
230 purple_debug_info("account", "Unregistering account %s\n",
231 purple_account_get_username(account));
233 cbb = g_new0(PurpleCallbackBundle, 1);
234 cbb->cb = PURPLE_CALLBACK(cb);
235 cbb->data = user_data;
237 purple_keyring_get_password(account,
238 purple_account_unregister_got_password_cb, cbb);
241 static void
242 request_password_ok_cb(PurpleAccount *account, PurpleRequestFields *fields)
244 const char *entry;
245 gboolean remember;
247 entry = purple_request_fields_get_string(fields, "password");
248 remember = purple_request_fields_get_bool(fields, "remember");
250 if (!entry || !*entry)
252 purple_notify_error(account, NULL,
253 _("Password is required to sign on."), NULL,
254 purple_request_cpar_from_account(account));
255 return;
258 purple_account_set_remember_password(account, remember);
260 purple_account_set_password(account, entry, NULL, NULL);
261 _purple_connection_new(account, FALSE, entry);
264 static void
265 request_password_cancel_cb(PurpleAccount *account, PurpleRequestFields *fields)
267 /* Disable the account as the user has cancelled connecting */
268 purple_account_set_enabled(account, purple_core_get_ui(), FALSE);
272 void
273 purple_account_request_password(PurpleAccount *account, GCallback ok_cb,
274 GCallback cancel_cb, void *user_data)
276 gchar *primary;
277 const gchar *username;
278 PurpleRequestFieldGroup *group;
279 PurpleRequestField *field;
280 PurpleRequestFields *fields;
282 /* Close any previous password request windows */
283 purple_request_close_with_handle(account);
285 username = purple_account_get_username(account);
286 primary = g_strdup_printf(_("Enter password for %s (%s)"), username,
287 purple_account_get_protocol_name(account));
289 fields = purple_request_fields_new();
290 group = purple_request_field_group_new(NULL);
291 purple_request_fields_add_group(fields, group);
293 field = purple_request_field_string_new("password", _("Enter Password"), NULL, FALSE);
294 purple_request_field_string_set_masked(field, TRUE);
295 purple_request_field_set_required(field, TRUE);
296 purple_request_field_group_add_field(group, field);
298 field = purple_request_field_bool_new("remember", _("Save password"), FALSE);
299 purple_request_field_group_add_field(group, field);
301 purple_request_fields(account, NULL, primary, NULL, fields, _("OK"),
302 ok_cb, _("Cancel"), cancel_cb,
303 purple_request_cpar_from_account(account), user_data);
304 g_free(primary);
307 static void
308 purple_account_connect_got_password_cb(PurpleAccount *account,
309 const gchar *password, GError *error, gpointer data)
311 PurpleProtocol *protocol = data;
313 if ((password == NULL || *password == '\0') &&
314 !(purple_protocol_get_options(protocol) & OPT_PROTO_NO_PASSWORD) &&
315 !(purple_protocol_get_options(protocol) & OPT_PROTO_PASSWORD_OPTIONAL))
316 purple_account_request_password(account,
317 G_CALLBACK(request_password_ok_cb),
318 G_CALLBACK(request_password_cancel_cb), account);
319 else
320 _purple_connection_new(account, FALSE, password);
323 void
324 purple_account_connect(PurpleAccount *account)
326 const char *username;
327 PurpleProtocol *protocol;
328 PurpleAccountPrivate *priv;
330 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
332 username = purple_account_get_username(account);
334 if (!purple_account_get_enabled(account, purple_core_get_ui())) {
335 purple_debug_info("account",
336 "Account %s not enabled, not connecting.\n",
337 username);
338 return;
341 protocol = purple_protocols_find(purple_account_get_protocol_id(account));
342 if (protocol == NULL) {
343 gchar *message;
345 message = g_strdup_printf(_("Missing protocol for %s"), username);
346 purple_notify_error(account, _("Connection Error"), message,
347 NULL, purple_request_cpar_from_account(account));
348 g_free(message);
349 return;
352 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
354 purple_debug_info("account", "Connecting to account %s.\n", username);
356 if (priv->password != NULL) {
357 purple_account_connect_got_password_cb(account,
358 priv->password, NULL, protocol);
359 } else {
360 purple_keyring_get_password(account,
361 purple_account_connect_got_password_cb, protocol);
365 void
366 purple_account_disconnect(PurpleAccount *account)
368 PurpleConnection *gc;
369 PurpleAccountPrivate *priv;
370 const char *username;
372 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
373 g_return_if_fail(!purple_account_is_disconnecting(account));
374 g_return_if_fail(!purple_account_is_disconnected(account));
376 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
378 username = purple_account_get_username(account);
379 purple_debug_info("account", "Disconnecting account %s (%p)\n",
380 username ? username : "(null)", account);
382 priv->disconnecting = TRUE;
384 gc = purple_account_get_connection(account);
385 g_object_unref(gc);
386 purple_account_set_connection(account, NULL);
388 priv->disconnecting = FALSE;
391 gboolean
392 purple_account_is_disconnecting(const PurpleAccount *account)
394 PurpleAccountPrivate *priv;
396 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), TRUE);
398 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
399 return priv->disconnecting;
402 void
403 purple_account_notify_added(PurpleAccount *account, const char *remote_user,
404 const char *id, const char *alias,
405 const char *message)
407 PurpleAccountUiOps *ui_ops;
409 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
410 g_return_if_fail(remote_user != NULL);
412 ui_ops = purple_accounts_get_ui_ops();
414 if (ui_ops != NULL && ui_ops->notify_added != NULL)
415 ui_ops->notify_added(account, remote_user, id, alias, message);
418 void
419 purple_account_request_add(PurpleAccount *account, const char *remote_user,
420 const char *id, const char *alias,
421 const char *message)
423 PurpleAccountUiOps *ui_ops;
425 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
426 g_return_if_fail(remote_user != NULL);
428 ui_ops = purple_accounts_get_ui_ops();
430 if (ui_ops != NULL && ui_ops->request_add != NULL)
431 ui_ops->request_add(account, remote_user, id, alias, message);
434 static PurpleAccountRequestInfo *
435 purple_account_request_info_unref(PurpleAccountRequestInfo *info)
437 if (--info->ref)
438 return info;
440 /* TODO: This will leak info->user_data, but there is no callback to just clean that up */
441 g_free(info->user);
442 g_free(info);
443 return NULL;
446 static void
447 purple_account_request_close_info(PurpleAccountRequestInfo *info)
449 PurpleAccountUiOps *ops;
451 ops = purple_accounts_get_ui_ops();
453 if (ops != NULL && ops->close_account_request != NULL)
454 ops->close_account_request(info->ui_handle);
456 purple_account_request_info_unref(info);
459 void
460 purple_account_request_close_with_account(PurpleAccount *account)
462 GList *l, *l_next;
464 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
466 for (l = handles; l != NULL; l = l_next) {
467 PurpleAccountRequestInfo *info = l->data;
469 l_next = l->next;
471 if (info->account == account) {
472 handles = g_list_remove(handles, info);
473 purple_account_request_close_info(info);
478 void
479 purple_account_request_close(void *ui_handle)
481 GList *l, *l_next;
483 g_return_if_fail(ui_handle != NULL);
485 for (l = handles; l != NULL; l = l_next) {
486 PurpleAccountRequestInfo *info = l->data;
488 l_next = l->next;
490 if (info->ui_handle == ui_handle) {
491 handles = g_list_remove(handles, info);
492 purple_account_request_close_info(info);
497 static void
498 request_auth_cb(const char *message, void *data)
500 PurpleAccountRequestInfo *info = data;
502 handles = g_list_remove(handles, info);
504 if (info->auth_cb != NULL)
505 info->auth_cb(message, info->userdata);
507 purple_signal_emit(purple_accounts_get_handle(),
508 "account-authorization-granted", info->account, info->user, message);
510 purple_account_request_info_unref(info);
513 static void
514 request_deny_cb(const char *message, void *data)
516 PurpleAccountRequestInfo *info = data;
518 handles = g_list_remove(handles, info);
520 if (info->deny_cb != NULL)
521 info->deny_cb(message, info->userdata);
523 purple_signal_emit(purple_accounts_get_handle(),
524 "account-authorization-denied", info->account, info->user, message);
526 purple_account_request_info_unref(info);
529 void *
530 purple_account_request_authorization(PurpleAccount *account, const char *remote_user,
531 const char *id, const char *alias, const char *message, gboolean on_list,
532 PurpleAccountRequestAuthorizationCb auth_cb, PurpleAccountRequestAuthorizationCb deny_cb, void *user_data)
534 PurpleAccountUiOps *ui_ops;
535 PurpleAccountRequestInfo *info;
536 int plugin_return;
537 char *response = NULL;
539 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
540 g_return_val_if_fail(remote_user != NULL, NULL);
542 ui_ops = purple_accounts_get_ui_ops();
544 plugin_return = GPOINTER_TO_INT(
545 purple_signal_emit_return_1(
546 purple_accounts_get_handle(),
547 "account-authorization-requested",
548 account, remote_user, message, &response
551 switch (plugin_return)
553 case PURPLE_ACCOUNT_RESPONSE_IGNORE:
554 g_free(response);
555 return NULL;
556 case PURPLE_ACCOUNT_RESPONSE_ACCEPT:
557 if (auth_cb != NULL)
558 auth_cb(response, user_data);
559 g_free(response);
560 return NULL;
561 case PURPLE_ACCOUNT_RESPONSE_DENY:
562 if (deny_cb != NULL)
563 deny_cb(response, user_data);
564 g_free(response);
565 return NULL;
568 g_free(response);
570 if (ui_ops != NULL && ui_ops->request_authorize != NULL) {
571 info = g_new0(PurpleAccountRequestInfo, 1);
572 info->type = PURPLE_ACCOUNT_REQUEST_AUTHORIZATION;
573 info->account = account;
574 info->auth_cb = auth_cb;
575 info->deny_cb = deny_cb;
576 info->userdata = user_data;
577 info->user = g_strdup(remote_user);
578 info->ref = 2; /* We hold an extra ref to make sure info remains valid
579 if any of the callbacks are called synchronously. We
580 unref it after the function call */
582 info->ui_handle = ui_ops->request_authorize(account, remote_user, id, alias, message,
583 on_list, request_auth_cb, request_deny_cb, info);
585 info = purple_account_request_info_unref(info);
586 if (info) {
587 handles = g_list_append(handles, info);
588 return info->ui_handle;
592 return NULL;
595 static void
596 change_password_cb(PurpleAccount *account, PurpleRequestFields *fields)
598 const char *orig_pass, *new_pass_1, *new_pass_2;
600 orig_pass = purple_request_fields_get_string(fields, "password");
601 new_pass_1 = purple_request_fields_get_string(fields, "new_password_1");
602 new_pass_2 = purple_request_fields_get_string(fields, "new_password_2");
604 if (g_utf8_collate(new_pass_1, new_pass_2))
606 purple_notify_error(account, NULL,
607 _("New passwords do not match."), NULL,
608 purple_request_cpar_from_account(account));
610 return;
613 if ((purple_request_fields_is_field_required(fields, "password") &&
614 (orig_pass == NULL || *orig_pass == '\0')) ||
615 (purple_request_fields_is_field_required(fields, "new_password_1") &&
616 (new_pass_1 == NULL || *new_pass_1 == '\0')) ||
617 (purple_request_fields_is_field_required(fields, "new_password_2") &&
618 (new_pass_2 == NULL || *new_pass_2 == '\0')))
620 purple_notify_error(account, NULL,
621 _("Fill out all fields completely."), NULL,
622 purple_request_cpar_from_account(account));
623 return;
626 purple_account_change_password(account, orig_pass, new_pass_1);
629 void
630 purple_account_request_change_password(PurpleAccount *account)
632 PurpleRequestFields *fields;
633 PurpleRequestFieldGroup *group;
634 PurpleRequestField *field;
635 PurpleConnection *gc;
636 PurpleProtocol *protocol = NULL;
637 char primary[256];
639 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
640 g_return_if_fail(purple_account_is_connected(account));
642 gc = purple_account_get_connection(account);
643 if (gc != NULL)
644 protocol = purple_connection_get_protocol(gc);
646 fields = purple_request_fields_new();
648 group = purple_request_field_group_new(NULL);
649 purple_request_fields_add_group(fields, group);
651 field = purple_request_field_string_new("password", _("Original password"),
652 NULL, FALSE);
653 purple_request_field_string_set_masked(field, TRUE);
654 if (!protocol || !(purple_protocol_get_options(protocol) & OPT_PROTO_PASSWORD_OPTIONAL))
655 purple_request_field_set_required(field, TRUE);
656 purple_request_field_group_add_field(group, field);
658 field = purple_request_field_string_new("new_password_1",
659 _("New password"),
660 NULL, FALSE);
661 purple_request_field_string_set_masked(field, TRUE);
662 if (!protocol || !(purple_protocol_get_options(protocol) & OPT_PROTO_PASSWORD_OPTIONAL))
663 purple_request_field_set_required(field, TRUE);
664 purple_request_field_group_add_field(group, field);
666 field = purple_request_field_string_new("new_password_2",
667 _("New password (again)"),
668 NULL, FALSE);
669 purple_request_field_string_set_masked(field, TRUE);
670 if (!protocol || !(purple_protocol_get_options(protocol) & OPT_PROTO_PASSWORD_OPTIONAL))
671 purple_request_field_set_required(field, TRUE);
672 purple_request_field_group_add_field(group, field);
674 g_snprintf(primary, sizeof(primary), _("Change password for %s"),
675 purple_account_get_username(account));
677 /* I'm sticking this somewhere in the code: bologna */
679 purple_request_fields(purple_account_get_connection(account), NULL,
680 primary, _("Please enter your current password and your new "
681 "password."), fields, _("OK"), G_CALLBACK(change_password_cb),
682 _("Cancel"), NULL, purple_request_cpar_from_account(account),
683 account);
686 static void
687 set_user_info_cb(PurpleAccount *account, const char *user_info)
689 PurpleConnection *gc;
691 purple_account_set_user_info(account, user_info);
692 gc = purple_account_get_connection(account);
693 purple_serv_set_info(gc, user_info);
696 void
697 purple_account_request_change_user_info(PurpleAccount *account)
699 PurpleConnection *gc;
700 char primary[256];
702 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
703 g_return_if_fail(purple_account_is_connected(account));
705 gc = purple_account_get_connection(account);
707 g_snprintf(primary, sizeof(primary),
708 _("Change user information for %s"),
709 purple_account_get_username(account));
711 purple_request_input(gc, _("Set User Info"), primary, NULL,
712 purple_account_get_user_info(account),
713 TRUE, FALSE, ((gc != NULL) &&
714 (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_HTML) ? "html" : NULL),
715 _("Save"), G_CALLBACK(set_user_info_cb),
716 _("Cancel"), NULL,
717 purple_request_cpar_from_account(account),
718 account);
721 void
722 purple_account_set_username(PurpleAccount *account, const char *username)
724 PurpleBlistUiOps *blist_ops;
725 PurpleAccountPrivate *priv;
727 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
729 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
731 g_free(priv->username);
732 priv->username = g_strdup(username);
734 g_object_notify_by_pspec(G_OBJECT(account), properties[PROP_USERNAME]);
736 purple_accounts_schedule_save();
738 /* if the name changes, we should re-write the buddy list
739 * to disk with the new name */
740 blist_ops = purple_blist_get_ui_ops();
741 if (blist_ops != NULL && blist_ops->save_account != NULL)
742 blist_ops->save_account(account);
745 void
746 purple_account_set_password(PurpleAccount *account, const gchar *password,
747 PurpleKeyringSaveCallback cb, gpointer data)
749 PurpleAccountPrivate *priv;
751 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
753 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
755 purple_str_wipe(priv->password);
756 priv->password = g_strdup(password);
758 purple_accounts_schedule_save();
760 if (!purple_account_get_remember_password(account)) {
761 purple_debug_info("account",
762 "Password for %s set, not sent to keyring.\n",
763 purple_account_get_username(account));
765 if (cb != NULL)
766 cb(account, NULL, data);
767 } else {
768 purple_keyring_set_password(account, password, cb, data);
772 void
773 purple_account_set_private_alias(PurpleAccount *account, const char *alias)
775 PurpleAccountPrivate *priv;
777 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
779 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
782 * Do nothing if alias and priv->alias are both NULL. Or if
783 * they're the exact same string.
785 if (alias == priv->alias)
786 return;
788 if ((!alias && priv->alias) || (alias && !priv->alias) ||
789 g_utf8_collate(priv->alias, alias))
791 char *old = priv->alias;
793 priv->alias = g_strdup(alias);
794 g_object_notify_by_pspec(G_OBJECT(account),
795 properties[PROP_PRIVATE_ALIAS]);
796 purple_signal_emit(purple_accounts_get_handle(), "account-alias-changed",
797 account, old);
798 g_free(old);
800 purple_accounts_schedule_save();
804 void
805 purple_account_set_user_info(PurpleAccount *account, const char *user_info)
807 PurpleAccountPrivate *priv;
809 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
811 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
813 g_free(priv->user_info);
814 priv->user_info = g_strdup(user_info);
816 g_object_notify_by_pspec(G_OBJECT(account), properties[PROP_USER_INFO]);
818 purple_accounts_schedule_save();
821 void purple_account_set_buddy_icon_path(PurpleAccount *account, const char *path)
823 PurpleAccountPrivate *priv;
825 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
827 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
829 g_free(priv->buddy_icon_path);
830 priv->buddy_icon_path = g_strdup(path);
832 g_object_notify_by_pspec(G_OBJECT(account),
833 properties[PROP_BUDDY_ICON_PATH]);
835 purple_accounts_schedule_save();
838 void
839 purple_account_set_protocol_id(PurpleAccount *account, const char *protocol_id)
841 PurpleAccountPrivate *priv;
843 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
844 g_return_if_fail(protocol_id != NULL);
846 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
848 g_free(priv->protocol_id);
849 priv->protocol_id = g_strdup(protocol_id);
851 g_object_notify_by_pspec(G_OBJECT(account), properties[PROP_PROTOCOL_ID]);
853 purple_accounts_schedule_save();
856 void
857 purple_account_set_connection(PurpleAccount *account, PurpleConnection *gc)
859 PurpleAccountPrivate *priv;
861 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
863 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
864 priv->gc = gc;
866 g_object_notify_by_pspec(G_OBJECT(account), properties[PROP_CONNECTION]);
869 void
870 purple_account_set_remember_password(PurpleAccount *account, gboolean value)
872 PurpleAccountPrivate *priv;
874 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
876 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
877 priv->remember_pass = value;
879 g_object_notify_by_pspec(G_OBJECT(account),
880 properties[PROP_REMEMBER_PASSWORD]);
882 purple_accounts_schedule_save();
885 void
886 purple_account_set_check_mail(PurpleAccount *account, gboolean value)
888 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
890 purple_account_set_bool(account, "check-mail", value);
892 g_object_notify_by_pspec(G_OBJECT(account), properties[PROP_CHECK_MAIL]);
895 void
896 purple_account_set_enabled(PurpleAccount *account, const char *ui,
897 gboolean value)
899 PurpleConnection *gc;
900 PurpleAccountPrivate *priv;
901 gboolean was_enabled = FALSE;
903 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
904 g_return_if_fail(ui != NULL);
906 was_enabled = purple_account_get_enabled(account, ui);
908 purple_account_set_ui_bool(account, ui, "auto-login", value);
909 gc = purple_account_get_connection(account);
911 if(was_enabled && !value)
912 purple_signal_emit(purple_accounts_get_handle(), "account-disabled", account);
913 else if(!was_enabled && value)
914 purple_signal_emit(purple_accounts_get_handle(), "account-enabled", account);
916 g_object_notify_by_pspec(G_OBJECT(account), properties[PROP_ENABLED]);
918 if ((gc != NULL) && (_purple_connection_wants_to_die(gc)))
919 return;
921 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
923 if (value && purple_presence_is_online(priv->presence))
924 purple_account_connect(account);
925 else if (!value && !purple_account_is_disconnected(account))
926 purple_account_disconnect(account);
929 void
930 purple_account_set_proxy_info(PurpleAccount *account, PurpleProxyInfo *info)
932 PurpleAccountPrivate *priv;
934 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
936 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
938 if (priv->proxy_info != NULL)
939 purple_proxy_info_destroy(priv->proxy_info);
941 priv->proxy_info = info;
943 purple_accounts_schedule_save();
946 void
947 purple_account_set_privacy_type(PurpleAccount *account, PurpleAccountPrivacyType privacy_type)
949 PurpleAccountPrivate *priv;
951 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
953 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
954 priv->privacy_type = privacy_type;
957 void
958 purple_account_set_status_types(PurpleAccount *account, GList *status_types)
960 PurpleAccountPrivate *priv;
962 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
964 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
966 /* Out with the old... */
967 if (priv->status_types != NULL)
969 g_list_foreach(priv->status_types, (GFunc)purple_status_type_destroy, NULL);
970 g_list_free(priv->status_types);
973 /* In with the new... */
974 priv->status_types = status_types;
977 void
978 purple_account_set_status(PurpleAccount *account, const char *status_id,
979 gboolean active, ...)
981 GList *attrs = NULL;
982 const gchar *id;
983 gpointer data;
984 va_list args;
986 va_start(args, active);
987 while ((id = va_arg(args, const char *)) != NULL)
989 attrs = g_list_append(attrs, (char *)id);
990 data = va_arg(args, void *);
991 attrs = g_list_append(attrs, data);
993 purple_account_set_status_list(account, status_id, active, attrs);
994 g_list_free(attrs);
995 va_end(args);
998 void
999 purple_account_set_status_list(PurpleAccount *account, const char *status_id,
1000 gboolean active, GList *attrs)
1002 PurpleStatus *status;
1004 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
1005 g_return_if_fail(status_id != NULL);
1007 status = purple_account_get_status(account, status_id);
1008 if (status == NULL)
1010 purple_debug_error("account",
1011 "Invalid status ID '%s' for account %s (%s)\n",
1012 status_id, purple_account_get_username(account),
1013 purple_account_get_protocol_id(account));
1014 return;
1017 if (active || purple_status_is_independent(status))
1018 purple_status_set_active_with_attrs_list(status, active, attrs);
1021 * Our current statuses are saved to accounts.xml (so that when we
1022 * reconnect, we go back to the previous status).
1024 purple_accounts_schedule_save();
1027 struct public_alias_closure
1029 PurpleAccount *account;
1030 gpointer failure_cb;
1033 static gboolean
1034 set_public_alias_unsupported(gpointer data)
1036 struct public_alias_closure *closure = data;
1037 PurpleSetPublicAliasFailureCallback failure_cb = closure->failure_cb;
1039 failure_cb(closure->account,
1040 _("This protocol does not support setting a public alias."));
1042 g_object_unref(closure->account);
1043 g_free(closure);
1045 return FALSE;
1048 void
1049 purple_account_set_public_alias(PurpleAccount *account,
1050 const char *alias, PurpleSetPublicAliasSuccessCallback success_cb,
1051 PurpleSetPublicAliasFailureCallback failure_cb)
1053 PurpleConnection *gc;
1054 PurpleProtocol *protocol = NULL;
1056 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
1057 g_return_if_fail(purple_account_is_connected(account));
1059 gc = purple_account_get_connection(account);
1060 protocol = purple_connection_get_protocol(gc);
1062 if (PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER_IFACE, set_public_alias))
1063 purple_protocol_server_iface_set_public_alias(protocol, gc, alias, success_cb, failure_cb);
1064 else if (failure_cb) {
1065 struct public_alias_closure *closure =
1066 g_new0(struct public_alias_closure, 1);
1067 closure->account = g_object_ref(account);
1068 closure->failure_cb = failure_cb;
1069 g_timeout_add(0, set_public_alias_unsupported, closure);
1073 static gboolean
1074 get_public_alias_unsupported(gpointer data)
1076 struct public_alias_closure *closure = data;
1077 PurpleGetPublicAliasFailureCallback failure_cb = closure->failure_cb;
1079 failure_cb(closure->account,
1080 _("This protocol does not support fetching the public alias."));
1082 g_object_unref(closure->account);
1083 g_free(closure);
1085 return FALSE;
1088 void
1089 purple_account_get_public_alias(PurpleAccount *account,
1090 PurpleGetPublicAliasSuccessCallback success_cb,
1091 PurpleGetPublicAliasFailureCallback failure_cb)
1093 PurpleConnection *gc;
1094 PurpleProtocol *protocol = NULL;
1096 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
1097 g_return_if_fail(purple_account_is_connected(account));
1099 gc = purple_account_get_connection(account);
1100 protocol = purple_connection_get_protocol(gc);
1102 if (PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER_IFACE, get_public_alias))
1103 purple_protocol_server_iface_get_public_alias(protocol, gc, success_cb, failure_cb);
1104 else if (failure_cb) {
1105 struct public_alias_closure *closure =
1106 g_new0(struct public_alias_closure, 1);
1107 closure->account = g_object_ref(account);
1108 closure->failure_cb = failure_cb;
1109 g_timeout_add(0, get_public_alias_unsupported, closure);
1113 gboolean
1114 purple_account_get_silence_suppression(const PurpleAccount *account)
1116 return purple_account_get_bool(account, "silence-suppression", FALSE);
1119 void
1120 purple_account_set_silence_suppression(PurpleAccount *account, gboolean value)
1122 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
1124 purple_account_set_bool(account, "silence-suppression", value);
1127 static void
1128 delete_setting(void *data)
1130 PurpleAccountSetting *setting = (PurpleAccountSetting *)data;
1132 g_free(setting->ui);
1133 g_value_unset(&setting->value);
1135 g_free(setting);
1138 void
1139 purple_account_clear_settings(PurpleAccount *account)
1141 PurpleAccountPrivate *priv;
1143 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
1145 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1146 g_hash_table_destroy(priv->settings);
1148 priv->settings = g_hash_table_new_full(g_str_hash, g_str_equal,
1149 g_free, delete_setting);
1152 void
1153 purple_account_remove_setting(PurpleAccount *account, const char *setting)
1155 PurpleAccountPrivate *priv;
1157 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
1158 g_return_if_fail(setting != NULL);
1160 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1162 g_hash_table_remove(priv->settings, setting);
1165 void
1166 purple_account_set_int(PurpleAccount *account, const char *name, int value)
1168 PurpleAccountSetting *setting;
1169 PurpleAccountPrivate *priv;
1171 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
1172 g_return_if_fail(name != NULL);
1174 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1176 setting = g_new0(PurpleAccountSetting, 1);
1178 g_value_init(&setting->value, G_TYPE_INT);
1179 g_value_set_int(&setting->value, value);
1181 g_hash_table_insert(priv->settings, g_strdup(name), setting);
1183 purple_accounts_schedule_save();
1186 void
1187 purple_account_set_string(PurpleAccount *account, const char *name,
1188 const char *value)
1190 PurpleAccountSetting *setting;
1191 PurpleAccountPrivate *priv;
1193 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
1194 g_return_if_fail(name != NULL);
1196 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1198 setting = g_new0(PurpleAccountSetting, 1);
1200 g_value_init(&setting->value, G_TYPE_STRING);
1201 g_value_set_string(&setting->value, value);
1203 g_hash_table_insert(priv->settings, g_strdup(name), setting);
1205 purple_accounts_schedule_save();
1208 void
1209 purple_account_set_bool(PurpleAccount *account, const char *name, gboolean value)
1211 PurpleAccountSetting *setting;
1212 PurpleAccountPrivate *priv;
1214 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
1215 g_return_if_fail(name != NULL);
1217 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1219 setting = g_new0(PurpleAccountSetting, 1);
1221 g_value_init(&setting->value, G_TYPE_BOOLEAN);
1222 g_value_set_boolean(&setting->value, value);
1224 g_hash_table_insert(priv->settings, g_strdup(name), setting);
1226 purple_accounts_schedule_save();
1229 static GHashTable *
1230 get_ui_settings_table(PurpleAccount *account, const char *ui)
1232 GHashTable *table;
1233 PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1235 table = g_hash_table_lookup(priv->ui_settings, ui);
1237 if (table == NULL) {
1238 table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
1239 delete_setting);
1240 g_hash_table_insert(priv->ui_settings, g_strdup(ui), table);
1243 return table;
1246 void
1247 purple_account_set_ui_int(PurpleAccount *account, const char *ui,
1248 const char *name, int value)
1250 PurpleAccountSetting *setting;
1251 GHashTable *table;
1253 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
1254 g_return_if_fail(ui != NULL);
1255 g_return_if_fail(name != NULL);
1257 setting = g_new0(PurpleAccountSetting, 1);
1259 setting->ui = g_strdup(ui);
1260 g_value_init(&setting->value, G_TYPE_INT);
1261 g_value_set_int(&setting->value, value);
1263 table = get_ui_settings_table(account, ui);
1265 g_hash_table_insert(table, g_strdup(name), setting);
1267 purple_accounts_schedule_save();
1270 void
1271 purple_account_set_ui_string(PurpleAccount *account, const char *ui,
1272 const char *name, const char *value)
1274 PurpleAccountSetting *setting;
1275 GHashTable *table;
1277 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
1278 g_return_if_fail(ui != NULL);
1279 g_return_if_fail(name != NULL);
1281 setting = g_new0(PurpleAccountSetting, 1);
1283 setting->ui = g_strdup(ui);
1284 g_value_init(&setting->value, G_TYPE_STRING);
1285 g_value_set_string(&setting->value, value);
1287 table = get_ui_settings_table(account, ui);
1289 g_hash_table_insert(table, g_strdup(name), setting);
1291 purple_accounts_schedule_save();
1294 void
1295 purple_account_set_ui_bool(PurpleAccount *account, const char *ui,
1296 const char *name, gboolean value)
1298 PurpleAccountSetting *setting;
1299 GHashTable *table;
1301 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
1302 g_return_if_fail(ui != NULL);
1303 g_return_if_fail(name != NULL);
1305 setting = g_new0(PurpleAccountSetting, 1);
1307 setting->ui = g_strdup(ui);
1308 g_value_init(&setting->value, G_TYPE_BOOLEAN);
1309 g_value_set_boolean(&setting->value, value);
1311 table = get_ui_settings_table(account, ui);
1313 g_hash_table_insert(table, g_strdup(name), setting);
1315 purple_accounts_schedule_save();
1318 static PurpleConnectionState
1319 purple_account_get_state(const PurpleAccount *account)
1321 PurpleConnection *gc;
1323 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), PURPLE_CONNECTION_DISCONNECTED);
1325 gc = purple_account_get_connection(account);
1326 if (!gc)
1327 return PURPLE_CONNECTION_DISCONNECTED;
1329 return purple_connection_get_state(gc);
1332 gboolean
1333 purple_account_is_connected(const PurpleAccount *account)
1335 return (purple_account_get_state(account) == PURPLE_CONNECTION_CONNECTED);
1338 gboolean
1339 purple_account_is_connecting(const PurpleAccount *account)
1341 return (purple_account_get_state(account) == PURPLE_CONNECTION_CONNECTING);
1344 gboolean
1345 purple_account_is_disconnected(const PurpleAccount *account)
1347 return (purple_account_get_state(account) == PURPLE_CONNECTION_DISCONNECTED);
1350 const char *
1351 purple_account_get_username(const PurpleAccount *account)
1353 PurpleAccountPrivate *priv;
1355 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
1357 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1358 return priv->username;
1361 static void
1362 purple_account_get_password_got(PurpleAccount *account,
1363 const gchar *password, GError *error, gpointer data)
1365 PurpleCallbackBundle *cbb = data;
1366 PurpleKeyringReadCallback cb;
1367 PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1369 purple_debug_info("account",
1370 "Read password for account %s from async keyring.\n",
1371 purple_account_get_username(account));
1373 purple_str_wipe(priv->password);
1374 priv->password = g_strdup(password);
1376 cb = (PurpleKeyringReadCallback)cbb->cb;
1377 if (cb != NULL)
1378 cb(account, password, error, cbb->data);
1380 g_free(cbb);
1383 void
1384 purple_account_get_password(PurpleAccount *account,
1385 PurpleKeyringReadCallback cb, gpointer data)
1387 PurpleAccountPrivate *priv;
1389 if (account == NULL) {
1390 cb(NULL, NULL, NULL, data);
1391 return;
1394 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1396 if (priv->password != NULL) {
1397 purple_debug_info("account",
1398 "Reading password for account %s from cache.\n",
1399 purple_account_get_username(account));
1400 cb(account, priv->password, NULL, data);
1401 } else {
1402 PurpleCallbackBundle *cbb = g_new0(PurpleCallbackBundle, 1);
1403 cbb->cb = PURPLE_CALLBACK(cb);
1404 cbb->data = data;
1406 purple_debug_info("account",
1407 "Reading password for account %s from async keyring.\n",
1408 purple_account_get_username(account));
1409 purple_keyring_get_password(account,
1410 purple_account_get_password_got, cbb);
1414 const char *
1415 purple_account_get_private_alias(const PurpleAccount *account)
1417 PurpleAccountPrivate *priv;
1419 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
1421 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1422 return priv->alias;
1425 const char *
1426 purple_account_get_user_info(const PurpleAccount *account)
1428 PurpleAccountPrivate *priv;
1430 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
1432 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1433 return priv->user_info;
1436 const char *
1437 purple_account_get_buddy_icon_path(const PurpleAccount *account)
1439 PurpleAccountPrivate *priv;
1441 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
1443 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1444 return priv->buddy_icon_path;
1447 const char *
1448 purple_account_get_protocol_id(const PurpleAccount *account)
1450 PurpleAccountPrivate *priv;
1452 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
1454 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1455 return priv->protocol_id;
1458 const char *
1459 purple_account_get_protocol_name(const PurpleAccount *account)
1461 PurpleProtocol *p;
1463 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
1465 p = purple_protocols_find(purple_account_get_protocol_id(account));
1467 return (p && purple_protocol_get_name(p) ?
1468 _(purple_protocol_get_name(p)) : _("Unknown"));
1471 PurpleConnection *
1472 purple_account_get_connection(const PurpleAccount *account)
1474 PurpleAccountPrivate *priv;
1476 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
1478 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1479 return priv->gc;
1482 const gchar *
1483 purple_account_get_name_for_display(const PurpleAccount *account)
1485 PurpleBuddy *self = NULL;
1486 PurpleConnection *gc = NULL;
1487 const gchar *name = NULL, *username = NULL, *displayname = NULL;
1489 name = purple_account_get_private_alias(account);
1491 if (name) {
1492 return name;
1495 username = purple_account_get_username(account);
1496 self = purple_blist_find_buddy((PurpleAccount *)account, username);
1498 if (self) {
1499 const gchar *calias= purple_buddy_get_contact_alias(self);
1501 /* We don't want to return the buddy name if the buddy/contact
1502 * doesn't have an alias set. */
1503 if (!purple_strequal(username, calias)) {
1504 return calias;
1508 gc = purple_account_get_connection(account);
1509 displayname = purple_connection_get_display_name(gc);
1511 if (displayname) {
1512 return displayname;
1515 return username;
1518 gboolean
1519 purple_account_get_remember_password(const PurpleAccount *account)
1521 PurpleAccountPrivate *priv;
1523 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE);
1525 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1526 return priv->remember_pass;
1529 gboolean
1530 purple_account_get_check_mail(const PurpleAccount *account)
1532 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE);
1534 return purple_account_get_bool(account, "check-mail", FALSE);
1537 gboolean
1538 purple_account_get_enabled(const PurpleAccount *account, const char *ui)
1540 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE);
1541 g_return_val_if_fail(ui != NULL, FALSE);
1543 return purple_account_get_ui_bool(account, ui, "auto-login", FALSE);
1546 PurpleProxyInfo *
1547 purple_account_get_proxy_info(const PurpleAccount *account)
1549 PurpleAccountPrivate *priv;
1551 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
1553 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1554 return priv->proxy_info;
1557 PurpleAccountPrivacyType
1558 purple_account_get_privacy_type(const PurpleAccount *account)
1560 PurpleAccountPrivate *priv;
1562 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL);
1564 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1565 return priv->privacy_type;
1568 gboolean
1569 purple_account_privacy_permit_add(PurpleAccount *account, const char *who,
1570 gboolean local_only)
1572 GSList *l;
1573 char *name;
1574 PurpleBuddy *buddy;
1575 PurpleBlistUiOps *blist_ops;
1576 PurpleAccountPrivate *priv;
1577 PurpleAccountUiOps *ui_ops = purple_accounts_get_ui_ops();
1579 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE);
1580 g_return_val_if_fail(who != NULL, FALSE);
1582 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1583 name = g_strdup(purple_normalize(account, who));
1585 for (l = priv->permit; l != NULL; l = l->next) {
1586 if (g_str_equal(name, l->data))
1587 /* This buddy already exists */
1588 break;
1591 if (l != NULL)
1593 /* This buddy already exists, so bail out */
1594 g_free(name);
1595 return FALSE;
1598 priv->permit = g_slist_append(priv->permit, name);
1600 if (!local_only && purple_account_is_connected(account))
1601 purple_serv_add_permit(purple_account_get_connection(account), who);
1603 if (ui_ops != NULL && ui_ops->permit_added != NULL)
1604 ui_ops->permit_added(account, who);
1606 blist_ops = purple_blist_get_ui_ops();
1607 if (blist_ops != NULL && blist_ops->save_account != NULL)
1608 blist_ops->save_account(account);
1610 /* This lets the UI know a buddy has had its privacy setting changed */
1611 buddy = purple_blist_find_buddy(account, name);
1612 if (buddy != NULL) {
1613 purple_signal_emit(purple_blist_get_handle(),
1614 "buddy-privacy-changed", buddy);
1616 return TRUE;
1619 gboolean
1620 purple_account_privacy_permit_remove(PurpleAccount *account, const char *who,
1621 gboolean local_only)
1623 GSList *l;
1624 const char *name;
1625 PurpleBuddy *buddy;
1626 char *del;
1627 PurpleBlistUiOps *blist_ops;
1628 PurpleAccountPrivate *priv;
1629 PurpleAccountUiOps *ui_ops = purple_accounts_get_ui_ops();
1631 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE);
1632 g_return_val_if_fail(who != NULL, FALSE);
1634 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1635 name = purple_normalize(account, who);
1637 for (l = priv->permit; l != NULL; l = l->next) {
1638 if (g_str_equal(name, l->data))
1639 /* We found the buddy we were looking for */
1640 break;
1643 if (l == NULL)
1644 /* We didn't find the buddy we were looking for, so bail out */
1645 return FALSE;
1647 /* We should not free l->data just yet. There can be occasions where
1648 * l->data == who. In such cases, freeing l->data here can cause crashes
1649 * later when who is used. */
1650 del = l->data;
1651 priv->permit = g_slist_delete_link(priv->permit, l);
1653 if (!local_only && purple_account_is_connected(account))
1654 purple_serv_rem_permit(purple_account_get_connection(account), who);
1656 if (ui_ops != NULL && ui_ops->permit_removed != NULL)
1657 ui_ops->permit_removed(account, who);
1659 blist_ops = purple_blist_get_ui_ops();
1660 if (blist_ops != NULL && blist_ops->save_account != NULL)
1661 blist_ops->save_account(account);
1663 buddy = purple_blist_find_buddy(account, name);
1664 if (buddy != NULL) {
1665 purple_signal_emit(purple_blist_get_handle(),
1666 "buddy-privacy-changed", buddy);
1668 g_free(del);
1669 return TRUE;
1672 gboolean
1673 purple_account_privacy_deny_add(PurpleAccount *account, const char *who,
1674 gboolean local_only)
1676 GSList *l;
1677 char *name;
1678 PurpleBuddy *buddy;
1679 PurpleBlistUiOps *blist_ops;
1680 PurpleAccountPrivate *priv;
1681 PurpleAccountUiOps *ui_ops = purple_accounts_get_ui_ops();
1683 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE);
1684 g_return_val_if_fail(who != NULL, FALSE);
1686 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1687 name = g_strdup(purple_normalize(account, who));
1689 for (l = priv->deny; l != NULL; l = l->next) {
1690 if (g_str_equal(name, l->data))
1691 /* This buddy already exists */
1692 break;
1695 if (l != NULL)
1697 /* This buddy already exists, so bail out */
1698 g_free(name);
1699 return FALSE;
1702 priv->deny = g_slist_append(priv->deny, name);
1704 if (!local_only && purple_account_is_connected(account))
1705 purple_serv_add_deny(purple_account_get_connection(account), who);
1707 if (ui_ops != NULL && ui_ops->deny_added != NULL)
1708 ui_ops->deny_added(account, who);
1710 blist_ops = purple_blist_get_ui_ops();
1711 if (blist_ops != NULL && blist_ops->save_account != NULL)
1712 blist_ops->save_account(account);
1714 buddy = purple_blist_find_buddy(account, name);
1715 if (buddy != NULL) {
1716 purple_signal_emit(purple_blist_get_handle(),
1717 "buddy-privacy-changed", buddy);
1719 return TRUE;
1722 gboolean
1723 purple_account_privacy_deny_remove(PurpleAccount *account, const char *who,
1724 gboolean local_only)
1726 GSList *l;
1727 const char *normalized;
1728 char *name;
1729 PurpleBuddy *buddy;
1730 PurpleBlistUiOps *blist_ops;
1731 PurpleAccountPrivate *priv;
1732 PurpleAccountUiOps *ui_ops = purple_accounts_get_ui_ops();
1734 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE);
1735 g_return_val_if_fail(who != NULL, FALSE);
1737 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1738 normalized = purple_normalize(account, who);
1740 for (l = priv->deny; l != NULL; l = l->next) {
1741 if (g_str_equal(normalized, l->data))
1742 /* We found the buddy we were looking for */
1743 break;
1746 if (l == NULL)
1747 /* We didn't find the buddy we were looking for, so bail out */
1748 return FALSE;
1750 buddy = purple_blist_find_buddy(account, normalized);
1752 name = l->data;
1753 priv->deny = g_slist_delete_link(priv->deny, l);
1755 if (!local_only && purple_account_is_connected(account))
1756 purple_serv_rem_deny(purple_account_get_connection(account), name);
1758 if (ui_ops != NULL && ui_ops->deny_removed != NULL)
1759 ui_ops->deny_removed(account, who);
1761 if (buddy != NULL) {
1762 purple_signal_emit(purple_blist_get_handle(),
1763 "buddy-privacy-changed", buddy);
1766 g_free(name);
1768 blist_ops = purple_blist_get_ui_ops();
1769 if (blist_ops != NULL && blist_ops->save_account != NULL)
1770 blist_ops->save_account(account);
1772 return TRUE;
1776 * This makes sure your permit list contains all buddies from your
1777 * buddy list and ONLY buddies from your buddy list.
1779 static void
1780 add_all_buddies_to_permit_list(PurpleAccount *account, gboolean local)
1782 GSList *list;
1783 PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1785 /* Remove anyone in the permit list who is not in the buddylist */
1786 for (list = priv->permit; list != NULL; ) {
1787 char *person = list->data;
1788 list = list->next;
1789 if (!purple_blist_find_buddy(account, person))
1790 purple_account_privacy_permit_remove(account, person, local);
1793 /* Now make sure everyone in the buddylist is in the permit list */
1794 list = purple_blist_find_buddies(account, NULL);
1795 while (list != NULL)
1797 PurpleBuddy *buddy = list->data;
1798 const gchar *name = purple_buddy_get_name(buddy);
1800 if (!g_slist_find_custom(priv->permit, name, (GCompareFunc)g_utf8_collate))
1801 purple_account_privacy_permit_add(account, name, local);
1802 list = g_slist_delete_link(list, list);
1806 void
1807 purple_account_privacy_allow(PurpleAccount *account, const char *who)
1809 GSList *list;
1810 PurpleAccountPrivacyType type = purple_account_get_privacy_type(account);
1811 PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1813 switch (type) {
1814 case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL:
1815 return;
1816 case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS:
1817 purple_account_privacy_permit_add(account, who, FALSE);
1818 break;
1819 case PURPLE_ACCOUNT_PRIVACY_DENY_USERS:
1820 purple_account_privacy_deny_remove(account, who, FALSE);
1821 break;
1822 case PURPLE_ACCOUNT_PRIVACY_DENY_ALL:
1824 /* Empty the allow-list. */
1825 const char *norm = purple_normalize(account, who);
1826 for (list = priv->permit; list != NULL;) {
1827 char *person = list->data;
1828 list = list->next;
1829 if (!purple_strequal(norm, person))
1830 purple_account_privacy_permit_remove(account, person, FALSE);
1832 purple_account_privacy_permit_add(account, who, FALSE);
1833 purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS);
1835 break;
1836 case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST:
1837 if (!purple_blist_find_buddy(account, who)) {
1838 add_all_buddies_to_permit_list(account, FALSE);
1839 purple_account_privacy_permit_add(account, who, FALSE);
1840 purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS);
1842 break;
1843 default:
1844 g_return_if_reached();
1847 /* Notify the server if the privacy setting was changed */
1848 if (type != purple_account_get_privacy_type(account) && purple_account_is_connected(account))
1849 purple_serv_set_permit_deny(purple_account_get_connection(account));
1852 void
1853 purple_account_privacy_deny(PurpleAccount *account, const char *who)
1855 GSList *list;
1856 PurpleAccountPrivacyType type = purple_account_get_privacy_type(account);
1857 PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1859 switch (type) {
1860 case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL:
1862 /* Empty the deny-list. */
1863 const char *norm = purple_normalize(account, who);
1864 for (list = priv->deny; list != NULL; ) {
1865 char *person = list->data;
1866 list = list->next;
1867 if (!purple_strequal(norm, person))
1868 purple_account_privacy_deny_remove(account, person, FALSE);
1870 purple_account_privacy_deny_add(account, who, FALSE);
1871 purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_DENY_USERS);
1873 break;
1874 case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS:
1875 purple_account_privacy_permit_remove(account, who, FALSE);
1876 break;
1877 case PURPLE_ACCOUNT_PRIVACY_DENY_USERS:
1878 purple_account_privacy_deny_add(account, who, FALSE);
1879 break;
1880 case PURPLE_ACCOUNT_PRIVACY_DENY_ALL:
1881 break;
1882 case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST:
1883 if (purple_blist_find_buddy(account, who)) {
1884 add_all_buddies_to_permit_list(account, FALSE);
1885 purple_account_privacy_permit_remove(account, who, FALSE);
1886 purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS);
1888 break;
1889 default:
1890 g_return_if_reached();
1893 /* Notify the server if the privacy setting was changed */
1894 if (type != purple_account_get_privacy_type(account) && purple_account_is_connected(account))
1895 purple_serv_set_permit_deny(purple_account_get_connection(account));
1898 GSList *
1899 purple_account_privacy_get_permitted(PurpleAccount *account)
1901 PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1903 g_return_val_if_fail(priv != NULL, NULL);
1905 return priv->permit;
1908 GSList *
1909 purple_account_privacy_get_denied(PurpleAccount *account)
1911 PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1913 g_return_val_if_fail(priv != NULL, NULL);
1915 return priv->deny;
1918 gboolean
1919 purple_account_privacy_check(PurpleAccount *account, const char *who)
1921 GSList *list;
1922 PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1924 switch (purple_account_get_privacy_type(account)) {
1925 case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL:
1926 return TRUE;
1928 case PURPLE_ACCOUNT_PRIVACY_DENY_ALL:
1929 return FALSE;
1931 case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS:
1932 who = purple_normalize(account, who);
1933 for (list=priv->permit; list!=NULL; list=list->next) {
1934 if (g_str_equal(who, list->data))
1935 return TRUE;
1937 return FALSE;
1939 case PURPLE_ACCOUNT_PRIVACY_DENY_USERS:
1940 who = purple_normalize(account, who);
1941 for (list=priv->deny; list!=NULL; list=list->next) {
1942 if (g_str_equal(who, list->data))
1943 return FALSE;
1945 return TRUE;
1947 case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST:
1948 return (purple_blist_find_buddy(account, who) != NULL);
1950 default:
1951 g_return_val_if_reached(TRUE);
1955 PurpleStatus *
1956 purple_account_get_active_status(const PurpleAccount *account)
1958 PurpleAccountPrivate *priv;
1960 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
1962 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1963 return purple_presence_get_active_status(priv->presence);
1966 PurpleStatus *
1967 purple_account_get_status(const PurpleAccount *account, const char *status_id)
1969 PurpleAccountPrivate *priv;
1971 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
1972 g_return_val_if_fail(status_id != NULL, NULL);
1974 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
1976 return purple_presence_get_status(priv->presence, status_id);
1979 PurpleStatusType *
1980 purple_account_get_status_type(const PurpleAccount *account, const char *id)
1982 GList *l;
1984 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
1985 g_return_val_if_fail(id != NULL, NULL);
1987 for (l = purple_account_get_status_types(account); l != NULL; l = l->next)
1989 PurpleStatusType *status_type = (PurpleStatusType *)l->data;
1991 if (purple_strequal(purple_status_type_get_id(status_type), id))
1992 return status_type;
1995 return NULL;
1998 PurpleStatusType *
1999 purple_account_get_status_type_with_primitive(const PurpleAccount *account, PurpleStatusPrimitive primitive)
2001 GList *l;
2003 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
2005 for (l = purple_account_get_status_types(account); l != NULL; l = l->next)
2007 PurpleStatusType *status_type = (PurpleStatusType *)l->data;
2009 if (purple_status_type_get_primitive(status_type) == primitive)
2010 return status_type;
2013 return NULL;
2016 PurplePresence *
2017 purple_account_get_presence(const PurpleAccount *account)
2019 PurpleAccountPrivate *priv;
2021 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
2023 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2024 return priv->presence;
2027 gboolean
2028 purple_account_is_status_active(const PurpleAccount *account,
2029 const char *status_id)
2031 PurpleAccountPrivate *priv;
2033 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE);
2034 g_return_val_if_fail(status_id != NULL, FALSE);
2036 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2038 return purple_presence_is_status_active(priv->presence, status_id);
2041 GList *
2042 purple_account_get_status_types(const PurpleAccount *account)
2044 PurpleAccountPrivate *priv;
2046 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
2048 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2049 return priv->status_types;
2053 purple_account_get_int(const PurpleAccount *account, const char *name,
2054 int default_value)
2056 PurpleAccountSetting *setting;
2057 PurpleAccountPrivate *priv;
2059 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), default_value);
2060 g_return_val_if_fail(name != NULL, default_value);
2062 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2064 setting = g_hash_table_lookup(priv->settings, name);
2066 if (setting == NULL)
2067 return default_value;
2069 g_return_val_if_fail(G_VALUE_HOLDS_INT(&setting->value), default_value);
2071 return g_value_get_int(&setting->value);
2074 const char *
2075 purple_account_get_string(const PurpleAccount *account, const char *name,
2076 const char *default_value)
2078 PurpleAccountSetting *setting;
2079 PurpleAccountPrivate *priv;
2081 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), default_value);
2082 g_return_val_if_fail(name != NULL, default_value);
2084 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2086 setting = g_hash_table_lookup(priv->settings, name);
2088 if (setting == NULL)
2089 return default_value;
2091 g_return_val_if_fail(G_VALUE_HOLDS_STRING(&setting->value), default_value);
2093 return g_value_get_string(&setting->value);
2096 gboolean
2097 purple_account_get_bool(const PurpleAccount *account, const char *name,
2098 gboolean default_value)
2100 PurpleAccountSetting *setting;
2101 PurpleAccountPrivate *priv;
2103 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), default_value);
2104 g_return_val_if_fail(name != NULL, default_value);
2106 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2108 setting = g_hash_table_lookup(priv->settings, name);
2110 if (setting == NULL)
2111 return default_value;
2113 g_return_val_if_fail(G_VALUE_HOLDS_BOOLEAN(&setting->value), default_value);
2115 return g_value_get_boolean(&setting->value);
2119 purple_account_get_ui_int(const PurpleAccount *account, const char *ui,
2120 const char *name, int default_value)
2122 PurpleAccountSetting *setting;
2123 PurpleAccountPrivate *priv;
2124 GHashTable *table;
2126 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), default_value);
2127 g_return_val_if_fail(ui != NULL, default_value);
2128 g_return_val_if_fail(name != NULL, default_value);
2130 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2132 if ((table = g_hash_table_lookup(priv->ui_settings, ui)) == NULL)
2133 return default_value;
2135 if ((setting = g_hash_table_lookup(table, name)) == NULL)
2136 return default_value;
2138 g_return_val_if_fail(G_VALUE_HOLDS_INT(&setting->value), default_value);
2140 return g_value_get_int(&setting->value);
2143 const char *
2144 purple_account_get_ui_string(const PurpleAccount *account, const char *ui,
2145 const char *name, const char *default_value)
2147 PurpleAccountSetting *setting;
2148 PurpleAccountPrivate *priv;
2149 GHashTable *table;
2151 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), default_value);
2152 g_return_val_if_fail(ui != NULL, default_value);
2153 g_return_val_if_fail(name != NULL, default_value);
2155 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2157 if ((table = g_hash_table_lookup(priv->ui_settings, ui)) == NULL)
2158 return default_value;
2160 if ((setting = g_hash_table_lookup(table, name)) == NULL)
2161 return default_value;
2163 g_return_val_if_fail(G_VALUE_HOLDS_STRING(&setting->value), default_value);
2165 return g_value_get_string(&setting->value);
2168 gboolean
2169 purple_account_get_ui_bool(const PurpleAccount *account, const char *ui,
2170 const char *name, gboolean default_value)
2172 PurpleAccountSetting *setting;
2173 PurpleAccountPrivate *priv;
2174 GHashTable *table;
2176 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), default_value);
2177 g_return_val_if_fail(ui != NULL, default_value);
2178 g_return_val_if_fail(name != NULL, default_value);
2180 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2182 if ((table = g_hash_table_lookup(priv->ui_settings, ui)) == NULL)
2183 return default_value;
2185 if ((setting = g_hash_table_lookup(table, name)) == NULL)
2186 return default_value;
2188 g_return_val_if_fail(G_VALUE_HOLDS_BOOLEAN(&setting->value), default_value);
2190 return g_value_get_boolean(&setting->value);
2193 gpointer
2194 purple_account_get_ui_data(const PurpleAccount *account)
2196 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
2198 return account->ui_data;
2201 void
2202 purple_account_set_ui_data(PurpleAccount *account, gpointer ui_data)
2204 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
2206 account->ui_data = ui_data;
2209 PurpleLog *
2210 purple_account_get_log(PurpleAccount *account, gboolean create)
2212 PurpleAccountPrivate *priv;
2214 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
2216 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2218 if(!priv->system_log && create){
2219 PurplePresence *presence;
2220 int login_time;
2221 GDateTime *dt;
2223 presence = purple_account_get_presence(account);
2224 login_time = purple_presence_get_login_time(presence);
2225 if (login_time != 0) {
2226 dt = g_date_time_new_from_unix_local(login_time);
2227 } else {
2228 dt = g_date_time_new_now_local();
2231 priv->system_log = purple_log_new(PURPLE_LOG_SYSTEM,
2232 purple_account_get_username(account),
2233 account, NULL, dt);
2234 g_date_time_unref(dt);
2237 return priv->system_log;
2240 void
2241 purple_account_destroy_log(PurpleAccount *account)
2243 PurpleAccountPrivate *priv;
2245 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
2247 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2249 if(priv->system_log){
2250 purple_log_free(priv->system_log);
2251 priv->system_log = NULL;
2255 void
2256 purple_account_add_buddy(PurpleAccount *account, PurpleBuddy *buddy, const char *message)
2258 PurpleProtocol *protocol = NULL;
2259 PurpleConnection *gc;
2261 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
2262 g_return_if_fail(PURPLE_IS_BUDDY(buddy));
2264 gc = purple_account_get_connection(account);
2265 if (gc != NULL)
2266 protocol = purple_connection_get_protocol(gc);
2268 if (protocol != NULL)
2269 purple_protocol_server_iface_add_buddy(protocol, gc, buddy,
2270 purple_buddy_get_group(buddy), message);
2273 void
2274 purple_account_add_buddies(PurpleAccount *account, GList *buddies, const char *message)
2276 PurpleProtocol *protocol = NULL;
2277 PurpleConnection *gc = purple_account_get_connection(account);
2279 if (gc != NULL)
2280 protocol = purple_connection_get_protocol(gc);
2282 if (protocol) {
2283 GList *cur, *groups = NULL;
2285 /* Make a list of what group each buddy is in */
2286 for (cur = buddies; cur != NULL; cur = cur->next) {
2287 PurpleBuddy *buddy = cur->data;
2288 groups = g_list_append(groups, purple_buddy_get_group(buddy));
2291 if (PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER_IFACE, add_buddies))
2292 purple_protocol_server_iface_add_buddies(protocol, gc, buddies, groups, message);
2293 else if (PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER_IFACE, add_buddy)) {
2294 GList *curb = buddies, *curg = groups;
2296 while ((curb != NULL) && (curg != NULL)) {
2297 purple_protocol_server_iface_add_buddy(protocol, gc, curb->data, curg->data, message);
2298 curb = curb->next;
2299 curg = curg->next;
2303 g_list_free(groups);
2307 void
2308 purple_account_remove_buddy(PurpleAccount *account, PurpleBuddy *buddy,
2309 PurpleGroup *group)
2311 PurpleProtocol *protocol = NULL;
2312 PurpleConnection *gc = purple_account_get_connection(account);
2314 if (gc != NULL)
2315 protocol = purple_connection_get_protocol(gc);
2317 if (protocol)
2318 purple_protocol_server_iface_remove_buddy(protocol, gc, buddy, group);
2321 void
2322 purple_account_remove_buddies(PurpleAccount *account, GList *buddies, GList *groups)
2324 PurpleProtocol *protocol = NULL;
2325 PurpleConnection *gc = purple_account_get_connection(account);
2327 if (gc != NULL)
2328 protocol = purple_connection_get_protocol(gc);
2330 if (protocol) {
2331 if (PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER_IFACE, remove_buddies))
2332 purple_protocol_server_iface_remove_buddies(protocol, gc, buddies, groups);
2333 else {
2334 GList *curb = buddies;
2335 GList *curg = groups;
2336 while ((curb != NULL) && (curg != NULL)) {
2337 purple_account_remove_buddy(account, curb->data, curg->data);
2338 curb = curb->next;
2339 curg = curg->next;
2345 void
2346 purple_account_remove_group(PurpleAccount *account, PurpleGroup *group)
2348 PurpleProtocol *protocol = NULL;
2349 PurpleConnection *gc = purple_account_get_connection(account);
2351 if (gc != NULL)
2352 protocol = purple_connection_get_protocol(gc);
2354 if (protocol)
2355 purple_protocol_server_iface_remove_group(protocol, gc, group);
2358 void
2359 purple_account_change_password(PurpleAccount *account, const char *orig_pw,
2360 const char *new_pw)
2362 PurpleProtocol *protocol = NULL;
2363 PurpleConnection *gc = purple_account_get_connection(account);
2365 purple_account_set_password(account, new_pw, NULL, NULL);
2367 if (gc != NULL)
2368 protocol = purple_connection_get_protocol(gc);
2370 if (protocol)
2371 purple_protocol_server_iface_change_passwd(protocol, gc, orig_pw, new_pw);
2374 gboolean purple_account_supports_offline_message(PurpleAccount *account, PurpleBuddy *buddy)
2376 PurpleConnection *gc;
2377 PurpleProtocol *protocol = NULL;
2379 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE);
2380 g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), FALSE);
2382 gc = purple_account_get_connection(account);
2383 if (gc == NULL)
2384 return FALSE;
2386 protocol = purple_connection_get_protocol(gc);
2388 if (!protocol)
2389 return FALSE;
2390 return purple_protocol_client_iface_offline_message(protocol, buddy);
2393 void
2394 _purple_account_set_current_error(PurpleAccount *account,
2395 PurpleConnectionErrorInfo *new_err)
2397 PurpleConnectionErrorInfo *old_err;
2398 PurpleAccountPrivate *priv;
2400 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
2401 priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2403 old_err = priv->current_error;
2405 if(new_err == old_err)
2406 return;
2408 priv->current_error = new_err;
2410 purple_signal_emit(purple_accounts_get_handle(),
2411 "account-error-changed",
2412 account, old_err, new_err);
2413 purple_accounts_schedule_save();
2415 if(old_err)
2416 g_free(old_err->description);
2418 PURPLE_DBUS_UNREGISTER_POINTER(old_err);
2419 g_free(old_err);
2422 const PurpleConnectionErrorInfo *
2423 purple_account_get_current_error(PurpleAccount *account)
2425 PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2427 return priv->current_error;
2430 void
2431 purple_account_clear_current_error(PurpleAccount *account)
2433 _purple_account_set_current_error(account, NULL);
2436 static PurpleXmlNode *
2437 status_attribute_to_xmlnode(const PurpleStatus *status, const PurpleStatusType *type,
2438 const PurpleStatusAttribute *attr)
2440 PurpleXmlNode *node;
2441 const char *id;
2442 char *value = NULL;
2443 PurpleStatusAttribute *default_attr;
2444 GValue *default_value;
2445 GType attr_type;
2446 GValue *attr_value;
2448 id = purple_status_attribute_get_id(attr);
2449 g_return_val_if_fail(id, NULL);
2451 attr_value = purple_status_get_attr_value(status, id);
2452 g_return_val_if_fail(attr_value, NULL);
2453 attr_type = G_VALUE_TYPE(attr_value);
2456 * If attr_value is a different type than it should be
2457 * then don't write it to the file.
2459 default_attr = purple_status_type_get_attr(type, id);
2460 default_value = purple_status_attribute_get_value(default_attr);
2461 if (attr_type != G_VALUE_TYPE(default_value))
2462 return NULL;
2465 * If attr_value is the same as the default for this status
2466 * then there is no need to write it to the file.
2468 if (attr_type == G_TYPE_STRING)
2470 const char *string_value = g_value_get_string(attr_value);
2471 const char *default_string_value = g_value_get_string(default_value);
2472 if (purple_strequal(string_value, default_string_value))
2473 return NULL;
2474 value = g_strdup(g_value_get_string(attr_value));
2476 else if (attr_type == G_TYPE_INT)
2478 int int_value = g_value_get_int(attr_value);
2479 if (int_value == g_value_get_int(default_value))
2480 return NULL;
2481 value = g_strdup_printf("%d", int_value);
2483 else if (attr_type == G_TYPE_BOOLEAN)
2485 gboolean boolean_value = g_value_get_boolean(attr_value);
2486 if (boolean_value == g_value_get_boolean(default_value))
2487 return NULL;
2488 value = g_strdup(boolean_value ?
2489 "true" : "false");
2491 else
2493 return NULL;
2496 g_return_val_if_fail(value, NULL);
2498 node = purple_xmlnode_new("attribute");
2500 purple_xmlnode_set_attrib(node, "id", id);
2501 purple_xmlnode_set_attrib(node, "value", value);
2503 g_free(value);
2505 return node;
2508 static PurpleXmlNode *
2509 status_attrs_to_xmlnode(const PurpleStatus *status)
2511 PurpleStatusType *type = purple_status_get_status_type(status);
2512 PurpleXmlNode *node, *child;
2513 GList *attrs, *attr;
2515 node = purple_xmlnode_new("attributes");
2517 attrs = purple_status_type_get_attrs(type);
2518 for (attr = attrs; attr != NULL; attr = attr->next)
2520 child = status_attribute_to_xmlnode(status, type, (const PurpleStatusAttribute *)attr->data);
2521 if (child)
2522 purple_xmlnode_insert_child(node, child);
2525 return node;
2528 static PurpleXmlNode *
2529 status_to_xmlnode(const PurpleStatus *status)
2531 PurpleXmlNode *node, *child;
2533 node = purple_xmlnode_new("status");
2534 purple_xmlnode_set_attrib(node, "type", purple_status_get_id(status));
2535 if (purple_status_get_name(status) != NULL)
2536 purple_xmlnode_set_attrib(node, "name", purple_status_get_name(status));
2537 purple_xmlnode_set_attrib(node, "active", purple_status_is_active(status) ? "true" : "false");
2539 child = status_attrs_to_xmlnode(status);
2540 purple_xmlnode_insert_child(node, child);
2542 return node;
2545 static PurpleXmlNode *
2546 statuses_to_xmlnode(const PurplePresence *presence)
2548 PurpleXmlNode *node, *child;
2549 GList *statuses;
2550 PurpleStatus *status;
2552 node = purple_xmlnode_new("statuses");
2554 statuses = purple_presence_get_statuses(presence);
2555 for (; statuses != NULL; statuses = statuses->next)
2557 status = statuses->data;
2558 if (purple_status_type_is_saveable(purple_status_get_status_type(status)))
2560 child = status_to_xmlnode(status);
2561 purple_xmlnode_insert_child(node, child);
2565 return node;
2568 static PurpleXmlNode *
2569 proxy_settings_to_xmlnode(PurpleProxyInfo *proxy_info)
2571 PurpleXmlNode *node, *child;
2572 PurpleProxyType proxy_type;
2573 const char *value;
2574 int int_value;
2575 char buf[21];
2577 proxy_type = purple_proxy_info_get_proxy_type(proxy_info);
2579 node = purple_xmlnode_new("proxy");
2581 child = purple_xmlnode_new_child(node, "type");
2582 purple_xmlnode_insert_data(child,
2583 (proxy_type == PURPLE_PROXY_USE_GLOBAL ? "global" :
2584 proxy_type == PURPLE_PROXY_NONE ? "none" :
2585 proxy_type == PURPLE_PROXY_HTTP ? "http" :
2586 proxy_type == PURPLE_PROXY_SOCKS4 ? "socks4" :
2587 proxy_type == PURPLE_PROXY_SOCKS5 ? "socks5" :
2588 proxy_type == PURPLE_PROXY_TOR ? "tor" :
2589 proxy_type == PURPLE_PROXY_USE_ENVVAR ? "envvar" : "unknown"), -1);
2591 if ((value = purple_proxy_info_get_host(proxy_info)) != NULL)
2593 child = purple_xmlnode_new_child(node, "host");
2594 purple_xmlnode_insert_data(child, value, -1);
2597 if ((int_value = purple_proxy_info_get_port(proxy_info)) != 0)
2599 g_snprintf(buf, sizeof(buf), "%d", int_value);
2600 child = purple_xmlnode_new_child(node, "port");
2601 purple_xmlnode_insert_data(child, buf, -1);
2604 if ((value = purple_proxy_info_get_username(proxy_info)) != NULL)
2606 child = purple_xmlnode_new_child(node, "username");
2607 purple_xmlnode_insert_data(child, value, -1);
2610 if ((value = purple_proxy_info_get_password(proxy_info)) != NULL)
2612 child = purple_xmlnode_new_child(node, "password");
2613 purple_xmlnode_insert_data(child, value, -1);
2616 return node;
2619 static PurpleXmlNode *
2620 current_error_to_xmlnode(PurpleConnectionErrorInfo *err)
2622 PurpleXmlNode *node, *child;
2623 char type_str[3];
2625 node = purple_xmlnode_new("current_error");
2627 if(err == NULL)
2628 return node;
2630 /* It doesn't make sense to have transient errors persist across a
2631 * restart.
2633 if(!purple_connection_error_is_fatal (err->type))
2634 return node;
2636 child = purple_xmlnode_new_child(node, "type");
2637 g_snprintf(type_str, sizeof(type_str), "%u", err->type);
2638 purple_xmlnode_insert_data(child, type_str, -1);
2640 child = purple_xmlnode_new_child(node, "description");
2641 if(err->description) {
2642 char *utf8ized = purple_utf8_try_convert(err->description);
2643 if(utf8ized == NULL)
2644 utf8ized = purple_utf8_salvage(err->description);
2645 purple_xmlnode_insert_data(child, utf8ized, -1);
2646 g_free(utf8ized);
2649 return node;
2652 static void
2653 setting_to_xmlnode(gpointer key, gpointer value, gpointer user_data)
2655 const char *name;
2656 PurpleAccountSetting *setting;
2657 PurpleXmlNode *node, *child;
2658 char buf[21];
2660 name = (const char *)key;
2661 setting = (PurpleAccountSetting *)value;
2662 node = (PurpleXmlNode *)user_data;
2664 child = purple_xmlnode_new_child(node, "setting");
2665 purple_xmlnode_set_attrib(child, "name", name);
2667 if (G_VALUE_HOLDS_INT(&setting->value)) {
2668 purple_xmlnode_set_attrib(child, "type", "int");
2669 g_snprintf(buf, sizeof(buf), "%d", g_value_get_int(&setting->value));
2670 purple_xmlnode_insert_data(child, buf, -1);
2672 else if (G_VALUE_HOLDS_STRING(&setting->value) && g_value_get_string(&setting->value) != NULL) {
2673 purple_xmlnode_set_attrib(child, "type", "string");
2674 purple_xmlnode_insert_data(child, g_value_get_string(&setting->value), -1);
2676 else if (G_VALUE_HOLDS_BOOLEAN(&setting->value)) {
2677 purple_xmlnode_set_attrib(child, "type", "bool");
2678 g_snprintf(buf, sizeof(buf), "%d", g_value_get_boolean(&setting->value));
2679 purple_xmlnode_insert_data(child, buf, -1);
2683 static void
2684 ui_setting_to_xmlnode(gpointer key, gpointer value, gpointer user_data)
2686 const char *ui;
2687 GHashTable *table;
2688 PurpleXmlNode *node, *child;
2690 ui = (const char *)key;
2691 table = (GHashTable *)value;
2692 node = (PurpleXmlNode *)user_data;
2694 if (g_hash_table_size(table) > 0)
2696 child = purple_xmlnode_new_child(node, "settings");
2697 purple_xmlnode_set_attrib(child, "ui", ui);
2698 g_hash_table_foreach(table, setting_to_xmlnode, child);
2702 PurpleXmlNode *
2703 _purple_account_to_xmlnode(PurpleAccount *account)
2705 PurpleXmlNode *node, *child;
2706 const char *tmp;
2707 PurplePresence *presence;
2708 PurpleProxyInfo *proxy_info;
2709 PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2711 node = purple_xmlnode_new("account");
2713 child = purple_xmlnode_new_child(node, "protocol");
2714 purple_xmlnode_insert_data(child, purple_account_get_protocol_id(account), -1);
2716 child = purple_xmlnode_new_child(node, "name");
2717 purple_xmlnode_insert_data(child, purple_account_get_username(account), -1);
2719 if (purple_account_get_remember_password(account))
2721 const char *keyring_id = NULL;
2722 const char *mode = NULL;
2723 char *data = NULL;
2724 GError *error = NULL;
2725 GDestroyNotify destroy = NULL;
2726 gboolean exported = purple_keyring_export_password(account,
2727 &keyring_id, &mode, &data, &error, &destroy);
2729 if (error != NULL) {
2730 purple_debug_error("account",
2731 "Failed to export password for account %s: %s.\n",
2732 purple_account_get_username(account),
2733 error->message);
2734 } else if (exported) {
2735 child = purple_xmlnode_new_child(node, "password");
2736 if (keyring_id != NULL)
2737 purple_xmlnode_set_attrib(child, "keyring_id", keyring_id);
2738 if (mode != NULL)
2739 purple_xmlnode_set_attrib(child, "mode", mode);
2740 if (data != NULL)
2741 purple_xmlnode_insert_data(child, data, -1);
2743 if (destroy != NULL)
2744 destroy(data);
2748 if ((tmp = purple_account_get_private_alias(account)) != NULL)
2750 child = purple_xmlnode_new_child(node, "alias");
2751 purple_xmlnode_insert_data(child, tmp, -1);
2754 if ((presence = purple_account_get_presence(account)) != NULL)
2756 child = statuses_to_xmlnode(presence);
2757 purple_xmlnode_insert_child(node, child);
2760 if ((tmp = purple_account_get_user_info(account)) != NULL)
2762 /* TODO: Do we need to call purple_str_strip_char(tmp, '\r') here? */
2763 child = purple_xmlnode_new_child(node, "user-info");
2764 purple_xmlnode_insert_data(child, tmp, -1);
2767 if (g_hash_table_size(priv->settings) > 0)
2769 child = purple_xmlnode_new_child(node, "settings");
2770 g_hash_table_foreach(priv->settings, setting_to_xmlnode, child);
2773 if (g_hash_table_size(priv->ui_settings) > 0)
2775 g_hash_table_foreach(priv->ui_settings, ui_setting_to_xmlnode, node);
2778 if ((proxy_info = purple_account_get_proxy_info(account)) != NULL)
2780 child = proxy_settings_to_xmlnode(proxy_info);
2781 purple_xmlnode_insert_child(node, child);
2784 child = current_error_to_xmlnode(priv->current_error);
2785 purple_xmlnode_insert_child(node, child);
2787 return node;
2790 /****************
2791 * GObject Code *
2792 ****************/
2794 /* Set method for GObject properties */
2795 static void
2796 purple_account_set_property(GObject *obj, guint param_id, const GValue *value,
2797 GParamSpec *pspec)
2799 PurpleAccount *account = PURPLE_ACCOUNT(obj);
2801 switch (param_id) {
2802 case PROP_USERNAME:
2803 purple_account_set_username(account, g_value_get_string(value));
2804 break;
2805 case PROP_PRIVATE_ALIAS:
2806 purple_account_set_private_alias(account, g_value_get_string(value));
2807 break;
2808 case PROP_ENABLED:
2809 purple_account_set_enabled(account, purple_core_get_ui(),
2810 g_value_get_boolean(value));
2811 break;
2812 case PROP_CONNECTION:
2813 purple_account_set_connection(account, g_value_get_object(value));
2814 break;
2815 case PROP_PROTOCOL_ID:
2816 purple_account_set_protocol_id(account, g_value_get_string(value));
2817 break;
2818 case PROP_USER_INFO:
2819 purple_account_set_user_info(account, g_value_get_string(value));
2820 break;
2821 case PROP_BUDDY_ICON_PATH:
2822 purple_account_set_buddy_icon_path(account,
2823 g_value_get_string(value));
2824 break;
2825 case PROP_REMEMBER_PASSWORD:
2826 purple_account_set_remember_password(account,
2827 g_value_get_boolean(value));
2828 break;
2829 case PROP_CHECK_MAIL:
2830 purple_account_set_check_mail(account, g_value_get_boolean(value));
2831 break;
2832 default:
2833 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
2834 break;
2838 /* Get method for GObject properties */
2839 static void
2840 purple_account_get_property(GObject *obj, guint param_id, GValue *value,
2841 GParamSpec *pspec)
2843 PurpleAccount *account = PURPLE_ACCOUNT(obj);
2845 switch (param_id) {
2846 case PROP_USERNAME:
2847 g_value_set_string(value, purple_account_get_username(account));
2848 break;
2849 case PROP_PRIVATE_ALIAS:
2850 g_value_set_string(value, purple_account_get_private_alias(account));
2851 break;
2852 case PROP_ENABLED:
2853 g_value_set_boolean(value, purple_account_get_enabled(account,
2854 purple_core_get_ui()));
2855 break;
2856 case PROP_CONNECTION:
2857 g_value_set_object(value, purple_account_get_connection(account));
2858 break;
2859 case PROP_PROTOCOL_ID:
2860 g_value_set_string(value, purple_account_get_protocol_id(account));
2861 break;
2862 case PROP_USER_INFO:
2863 g_value_set_string(value, purple_account_get_user_info(account));
2864 break;
2865 case PROP_BUDDY_ICON_PATH:
2866 g_value_set_string(value,
2867 purple_account_get_buddy_icon_path(account));
2868 break;
2869 case PROP_REMEMBER_PASSWORD:
2870 g_value_set_boolean(value,
2871 purple_account_get_remember_password(account));
2872 break;
2873 case PROP_CHECK_MAIL:
2874 g_value_set_boolean(value, purple_account_get_check_mail(account));
2875 break;
2876 default:
2877 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
2878 break;
2882 /* GObject initialization function */
2883 static void purple_account_init(GTypeInstance *instance, gpointer klass)
2885 PurpleAccount *account = PURPLE_ACCOUNT(instance);
2886 PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2888 priv->settings = g_hash_table_new_full(g_str_hash, g_str_equal,
2889 g_free, delete_setting);
2890 priv->ui_settings = g_hash_table_new_full(g_str_hash, g_str_equal,
2891 g_free, (GDestroyNotify)g_hash_table_destroy);
2892 priv->system_log = NULL;
2894 priv->privacy_type = PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL;
2896 PURPLE_DBUS_REGISTER_POINTER(account, PurpleAccount);
2899 /* Called when done constructing */
2900 static void
2901 purple_account_constructed(GObject *object)
2903 PurpleAccount *account = PURPLE_ACCOUNT(object);
2904 PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2905 gchar *username, *protocol_id;
2906 PurpleProtocol *protocol = NULL;
2907 PurpleStatusType *status_type;
2909 parent_class->constructed(object);
2911 g_object_get(object,
2912 "username", &username,
2913 "protocol-id", &protocol_id,
2914 NULL);
2916 purple_signal_emit(purple_accounts_get_handle(), "account-created",
2917 account);
2919 protocol = purple_protocols_find(protocol_id);
2920 if (protocol == NULL) {
2921 g_free(username);
2922 g_free(protocol_id);
2923 return;
2926 purple_account_set_status_types(account,
2927 purple_protocol_class_status_types(protocol, account));
2929 priv->presence = PURPLE_PRESENCE(purple_account_presence_new(account));
2931 status_type = purple_account_get_status_type_with_primitive(account,
2932 PURPLE_STATUS_AVAILABLE);
2933 if (status_type != NULL)
2934 purple_presence_set_status_active(priv->presence,
2935 purple_status_type_get_id(status_type),
2936 TRUE);
2937 else
2938 purple_presence_set_status_active(priv->presence,
2939 "offline",
2940 TRUE);
2942 g_free(username);
2943 g_free(protocol_id);
2946 /* GObject dispose function */
2947 static void
2948 purple_account_dispose(GObject *object)
2950 PurpleAccount *account = PURPLE_ACCOUNT(object);
2951 PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2953 if (!purple_account_is_disconnected(account))
2954 purple_account_disconnect(account);
2956 if (priv->presence) {
2957 g_object_unref(priv->presence);
2958 priv->presence = NULL;
2961 parent_class->dispose(object);
2964 /* GObject finalize function */
2965 static void
2966 purple_account_finalize(GObject *object)
2968 GList *l;
2969 PurpleAccount *account = PURPLE_ACCOUNT(object);
2970 PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
2972 purple_debug_info("account", "Destroying account %p\n", account);
2973 purple_signal_emit(purple_accounts_get_handle(), "account-destroying",
2974 account);
2976 for (l = purple_conversations_get_all(); l != NULL; l = l->next)
2978 PurpleConversation *conv = (PurpleConversation *)l->data;
2980 if (purple_conversation_get_account(conv) == account)
2981 purple_conversation_set_account(conv, NULL);
2984 purple_account_set_status_types(account, NULL);
2986 if (priv->proxy_info)
2987 purple_proxy_info_destroy(priv->proxy_info);
2989 if(priv->system_log)
2990 purple_log_free(priv->system_log);
2992 PURPLE_DBUS_UNREGISTER_POINTER(priv->current_error);
2993 if (priv->current_error) {
2994 g_free(priv->current_error->description);
2995 g_free(priv->current_error);
2998 g_free(priv->username);
2999 g_free(priv->alias);
3000 purple_str_wipe(priv->password);
3001 g_free(priv->user_info);
3002 g_free(priv->buddy_icon_path);
3003 g_free(priv->protocol_id);
3005 g_hash_table_destroy(priv->settings);
3006 g_hash_table_destroy(priv->ui_settings);
3008 while (priv->deny) {
3009 g_free(priv->deny->data);
3010 priv->deny = g_slist_delete_link(priv->deny, priv->deny);
3013 while (priv->permit) {
3014 g_free(priv->permit->data);
3015 priv->permit = g_slist_delete_link(priv->permit, priv->permit);
3018 PURPLE_DBUS_UNREGISTER_POINTER(account);
3020 parent_class->finalize(object);
3023 /* Class initializer function */
3024 static void
3025 purple_account_class_init(PurpleAccountClass *klass)
3027 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
3029 parent_class = g_type_class_peek_parent(klass);
3031 obj_class->dispose = purple_account_dispose;
3032 obj_class->finalize = purple_account_finalize;
3033 obj_class->constructed = purple_account_constructed;
3035 /* Setup properties */
3036 obj_class->get_property = purple_account_get_property;
3037 obj_class->set_property = purple_account_set_property;
3039 g_type_class_add_private(klass, sizeof(PurpleAccountPrivate));
3041 properties[PROP_USERNAME] = g_param_spec_string("username", "Username",
3042 "The username for the account.", NULL,
3043 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
3045 properties[PROP_PRIVATE_ALIAS] = g_param_spec_string("private-alias",
3046 "Private Alias",
3047 "The private alias for the account.", NULL,
3048 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
3050 properties[PROP_USER_INFO] = g_param_spec_string("user-info",
3051 "User information",
3052 "Detailed user information for the account.", NULL,
3053 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
3055 properties[PROP_BUDDY_ICON_PATH] = g_param_spec_string("buddy-icon-path",
3056 "Buddy icon path",
3057 "Path to the buddyicon for the account.", NULL,
3058 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
3060 properties[PROP_ENABLED] = g_param_spec_boolean("enabled", "Enabled",
3061 "Whether the account is enabled or not.", FALSE,
3062 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
3064 properties[PROP_REMEMBER_PASSWORD] = g_param_spec_boolean(
3065 "remember-password", "Remember password",
3066 "Whether to remember and store the password for this account.",
3067 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
3069 properties[PROP_CHECK_MAIL] = g_param_spec_boolean("check-mail",
3070 "Check mail",
3071 "Whether to check mails for this account.", FALSE,
3072 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
3074 properties[PROP_CONNECTION] = g_param_spec_object("connection",
3075 "Connection",
3076 "The connection for the account.", PURPLE_TYPE_CONNECTION,
3077 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
3079 properties[PROP_PROTOCOL_ID] = g_param_spec_string("protocol-id",
3080 "Protocol ID",
3081 "ID of the protocol that is responsible for the account.", NULL,
3082 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
3083 G_PARAM_STATIC_STRINGS);
3085 g_object_class_install_properties(obj_class, PROP_LAST, properties);
3088 GType
3089 purple_account_get_type(void)
3091 static GType type = 0;
3093 if(type == 0) {
3094 static const GTypeInfo info = {
3095 sizeof(PurpleAccountClass),
3096 NULL,
3097 NULL,
3098 (GClassInitFunc)purple_account_class_init,
3099 NULL,
3100 NULL,
3101 sizeof(PurpleAccount),
3103 (GInstanceInitFunc)purple_account_init,
3104 NULL,
3107 type = g_type_register_static(G_TYPE_OBJECT,
3108 "PurpleAccount",
3109 &info, 0);
3112 return type;
3115 PurpleAccount *
3116 purple_account_new(const char *username, const char *protocol_id)
3118 PurpleAccount *account;
3120 g_return_val_if_fail(username != NULL, NULL);
3121 g_return_val_if_fail(protocol_id != NULL, NULL);
3123 account = purple_accounts_find(username, protocol_id);
3125 if (account != NULL)
3126 return account;
3128 account = g_object_new(PURPLE_TYPE_ACCOUNT,
3129 "username", username,
3130 "protocol-id", protocol_id,
3131 NULL);
3133 return account;