diff options
author | Ankit Vani <a@nevitus.org> | 2013-08-22 01:35:32 +0530 |
---|---|---|
committer | Ankit Vani <a@nevitus.org> | 2013-08-22 01:35:32 +0530 |
commit | f30f5667daa327c86ae481816fc516d6833f86e7 (patch) | |
tree | c95a3d4675c8ebe44fdd2ef71bc7cdd8eaade097 | |
parent | 836575deafeb881a6c984146be7ccb62e40561c0 (diff) | |
parent | 24eb25e1d7eeba87abf49e997674459b43c994e6 (diff) | |
download | pidgin-f30f5667daa327c86ae481816fc516d6833f86e7.tar.gz |
Merged default branch
354 files changed, 27664 insertions, 22080 deletions
@@ -59,6 +59,7 @@ libpurple/dbus-bindings.c libpurple/dbus-signals.c libpurple/dbus-types.c libpurple/dbus-types.h +libpurple/enums.[ch] libpurple/example/nullclient libpurple/gconf/purple.schemas$ libpurple/marshallers.[ch] diff --git a/configure.ac b/configure.ac index 01ace1d191..ee3ea2850f 100644 --- a/configure.ac +++ b/configure.ac @@ -353,6 +353,9 @@ AC_SUBST(GLIB_LIBS) GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0` AC_SUBST(GLIB_GENMARSHAL) +GLIB_MKENUMS=`pkg-config --variable=glib_mkenums glib-2.0` +AC_SUBST(GLIB_MKENUMS) + AC_ARG_WITH([extraversion], AS_HELP_STRING([--with-extraversion=STRING], [extra version number to be displayed in Help->About and --help (for packagers)]), diff --git a/doc/SIGNAL-HOWTO.dox b/doc/SIGNAL-HOWTO.dox index 3007415ca2..a123cbc0a8 100644 --- a/doc/SIGNAL-HOWTO.dox +++ b/doc/SIGNAL-HOWTO.dox @@ -78,8 +78,6 @@ @todo Describe this more. - @see value.h - @section connect Connecting to the signal Once the signal is registered, you can connect callbacks to it. First, you must define a callback function, such as this one from gtkplugin.c : diff --git a/doc/conversation-signals.dox b/doc/conversation-signals.dox index b9746990ac..6ac019bc2e 100644 --- a/doc/conversation-signals.dox +++ b/doc/conversation-signals.dox @@ -19,11 +19,11 @@ @signal deleting-conversation @signal buddy-typing @signal buddy-typing-stopped - @signal chat-buddy-joining - @signal chat-buddy-joined - @signal chat-buddy-flags - @signal chat-buddy-leaving - @signal chat-buddy-left + @signal chat-user-joining + @signal chat-user-joined + @signal chat-user-flags + @signal chat-user-leaving + @signal chat-user-left @signal chat-inviting-user @signal chat-invited-user @signal chat-invited @@ -294,7 +294,7 @@ void (*buddy_typing_stopped)(PurpleAccount *account, const char *name); @param name The name of the user which stopped typing. @endsignaldef - @signaldef chat-buddy-joining + @signaldef chat-user-joining @signalproto gboolean (*chat_buddy_joining)(PurpleConversation *conv, const char *name, PurpleConvChatBuddyFlags flags); @@ -308,7 +308,7 @@ gboolean (*chat_buddy_joining)(PurpleConversation *conv, const char *name, @param flags The flags of the user that is joining the conversation. @endsignaldef - @signaldef chat-buddy-joined + @signaldef chat-user-joined @signalproto void (*chat_buddy_joined)(PurpleConversation *conv, const char *name, PurpleConvChatBuddyFlags flags, @@ -334,21 +334,20 @@ void (*chat_join_failed)(PurpleConnection *gc, GHashTable *components); function should be g_str_equal(). @endsignaldef - @signaldef chat-buddy-flags + @signaldef chat-user-flags @signalproto -void (*chat_buddy_flags)(PurpleConversation *conv, const char *name, +void (*chat_buddy_flags)(PurpleChatUser *chatuser, PurpleConvChatBuddyFlags oldflags, PurpleConvChatBuddyFlags newflags); @endsignalproto @signaldesc Emitted when a user in a chat changes flags. - @param conv The chat conversation. - @param name The name of the user. + @param chatuser The chat user whose flags changed. @param oldflags The old flags. @param newflags The new flags. @endsignaldef - @signaldef chat-buddy-leaving + @signaldef chat-user-leaving @signalproto gboolean (*chat_buddy_leaving)(PurpleConversation *conv, const char *name, const char *reason); @@ -362,7 +361,7 @@ gboolean (*chat_buddy_leaving)(PurpleConversation *conv, const char *name, @param reason The optional reason why the user is leaving. @endsignaldef - @signaldef chat-buddy-left + @signaldef chat-user-left @signalproto void (*chat_buddy_left)(PurpleConversation *conv, const char *name, const char *reason); diff --git a/finch/gntaccount.c b/finch/gntaccount.c index a08f7ffffb..5f612b8aab 100644 --- a/finch/gntaccount.c +++ b/finch/gntaccount.c @@ -188,7 +188,7 @@ save_account_cb(AccountEditDialog *dialog) /* Alias */ value = gnt_entry_get_text(GNT_ENTRY(dialog->alias)); - purple_account_set_alias(account, value); + purple_account_set_private_alias(account, value); /* Remember password and password */ purple_account_set_remember_password(account, @@ -628,7 +628,7 @@ edit_account_continue(PurpleAccount *account, gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Alias:"))); gnt_box_add_widget(GNT_BOX(hbox), entry); if (account) - gnt_entry_set_text(GNT_ENTRY(entry), purple_account_get_alias(account)); + gnt_entry_set_text(GNT_ENTRY(entry), purple_account_get_private_alias(account)); /* User options */ update_user_options(dialog); @@ -1158,7 +1158,8 @@ static PurpleAccountUiOps ui_ops = NULL, NULL, NULL, - NULL + NULL, + NULL, NULL, NULL, NULL }; PurpleAccountUiOps *finch_accounts_get_ui_ops() diff --git a/finch/gntblist.c b/finch/gntblist.c index 4bf1148c38..8d68a55f0c 100644 --- a/finch/gntblist.c +++ b/finch/gntblist.c @@ -27,10 +27,9 @@ #include "finch.h" #include <account.h> -#include <blist.h> +#include <buddylist.h> #include <log.h> #include <notify.h> -#include <privacy.h> #include <request.h> #include <savedstatuses.h> #include <server.h> @@ -73,15 +72,15 @@ typedef struct GntWidget *tree; GntWidget *tooltip; - PurpleBlistNode *tnode; /* Who is the tooltip being displayed for? */ - GList *tagged; /* A list of tagged blistnodes */ + PurpleBlistNode *tnode; /* Who is the tooltip being displayed for? */ + GList *tagged; /* A list of tagged blistnodes */ GntWidget *context; PurpleBlistNode *cnode; /* XXX: I am KISSing */ - GntWidget *status; /* Dropdown with the statuses */ - GntWidget *statustext; /* Status message */ + GntWidget *status; /* Dropdown with the statuses */ + GntWidget *statustext; /* Status message */ int typing; GntWidget *menu; @@ -102,8 +101,8 @@ typedef struct typedef struct { - gpointer row; /* the row in the GntTree */ - guint signed_timer; /* used when 'recently' signed on/off */ + gpointer row; /* the row in the GntTree */ + guint signed_timer; /* used when 'recently' signed on/off */ } FinchBlistNode; typedef enum @@ -168,7 +167,7 @@ static gboolean default_can_add_node(PurpleBlistNode *node) { gboolean offline = purple_prefs_get_bool(PREF_ROOT "/showoffline"); - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (PURPLE_IS_BUDDY(node)) { PurpleBuddy *buddy = (PurpleBuddy*)node; FinchBlistNode *fnode = purple_blist_node_get_ui_data(node); if (!purple_buddy_get_contact(buddy)) @@ -183,18 +182,18 @@ static gboolean default_can_add_node(PurpleBlistNode *node) return TRUE; /* Show if the buddy just signed off */ if (purple_blist_node_get_bool(node, "show_offline")) return TRUE; - } else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + } else if (PURPLE_IS_CONTACT(node)) { PurpleBlistNode *nd; for (nd = purple_blist_node_get_first_child(node); nd; nd = purple_blist_node_get_sibling_next(nd)) { if (default_can_add_node(nd)) return TRUE; } - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { PurpleChat *chat = (PurpleChat*)node; if (purple_account_is_connected(purple_chat_get_account(chat))) return TRUE; /* Show whenever the account is online */ - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { PurpleBlistNode *nd; gboolean empty = purple_prefs_get_bool(PREF_ROOT "/emptygroups"); if (empty) @@ -216,17 +215,13 @@ static gboolean default_can_add_node(PurpleBlistNode *node) static gpointer default_find_parent(PurpleBlistNode *node) { gpointer ret = NULL; - switch (purple_blist_node_get_type(node)) { - case PURPLE_BLIST_BUDDY_NODE: - case PURPLE_BLIST_CONTACT_NODE: - case PURPLE_BLIST_CHAT_NODE: - ret = purple_blist_node_get_parent(node); - break; - default: - break; - } + + if (PURPLE_IS_BUDDY(node) || PURPLE_IS_CONTACT(node) || PURPLE_IS_CHAT(node)) + ret = purple_blist_node_get_parent(node); + if (ret) add_node(ret, ggblist); + return ret; } @@ -237,13 +232,13 @@ static gboolean default_create_tooltip(gpointer selected_row, GString **body, ch int lastseen = 0; char *title; - if (!node || - purple_blist_node_get_type(node) == PURPLE_BLIST_OTHER_NODE) + if (!node || !(PURPLE_IS_BUDDY(node) || PURPLE_IS_CONTACT(node) || + PURPLE_IS_GROUP(node) || PURPLE_IS_CHAT(node))) return FALSE; str = g_string_new(""); - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if (PURPLE_IS_CONTACT(node)) { PurpleBuddy *pr = purple_contact_get_priority_buddy((PurpleContact*)node); gboolean offline = !PURPLE_BUDDY_IS_ONLINE(pr); gboolean showoffline = purple_prefs_get_bool(PREF_ROOT "/showoffline"); @@ -267,21 +262,21 @@ static gboolean default_create_tooltip(gpointer selected_row, GString **body, ch str = g_string_append(str, "\n----------\n"); tooltip_for_buddy(buddy, str, FALSE); } - } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + } else if (PURPLE_IS_BUDDY(node)) { PurpleBuddy *buddy = (PurpleBuddy *)node; tooltip_for_buddy(buddy, str, TRUE); title = g_strdup(purple_buddy_get_name(buddy)); if (!PURPLE_BUDDY_IS_ONLINE((PurpleBuddy*)node)) lastseen = purple_blist_node_get_int(node, "last_seen"); - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { PurpleGroup *group = (PurpleGroup *)node; g_string_append_printf(str, _("Online: %d\nTotal: %d"), - purple_blist_get_group_online_count(group), - purple_blist_get_group_size(group, FALSE)); + purple_counting_node_get_online_count(PURPLE_COUNTING_NODE(group)), + purple_counting_node_get_current_size(PURPLE_COUNTING_NODE(group))); title = g_strdup(purple_group_get_name(group)); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { PurpleChat *chat = (PurpleChat *)node; PurpleAccount *account = purple_chat_get_account(chat); @@ -358,9 +353,9 @@ get_display_color(PurpleBlistNode *node) PurpleBuddy *buddy; int color = 0; - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + if (PURPLE_IS_CONTACT(node)) node = PURPLE_BLIST_NODE(purple_contact_get_priority_buddy(PURPLE_CONTACT(node))); - if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (!PURPLE_IS_BUDDY(node)) return 0; buddy = (PurpleBuddy*)node; @@ -389,12 +384,12 @@ get_blist_node_flag(PurpleBlistNode *node) if (fnode && fnode->signed_timer) flag |= GNT_TEXT_FLAG_BLINK; - else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + else if (PURPLE_IS_CONTACT(node)) { node = PURPLE_BLIST_NODE(purple_contact_get_priority_buddy(PURPLE_CONTACT(node))); fnode = purple_blist_node_get_ui_data(node); if (fnode && fnode->signed_timer) flag |= GNT_TEXT_FLAG_BLINK; - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { /* If the node is collapsed, then check to see if any of the priority buddies of * any of the contacts within this group recently signed on/off, and set the blink * flag appropriately. */ @@ -448,7 +443,7 @@ is_group_online(PurpleGroup *group) PurpleBlistNode *node; for (node = purple_blist_node_get_first_child(((PurpleBlistNode*)group)); node; node = purple_blist_node_get_sibling_next(node)) { - if (PURPLE_BLIST_NODE_IS_CHAT(node) && + if (PURPLE_IS_CHAT(node) && purple_account_is_connected(((PurpleChat *)node)->account)) return TRUE; else if (is_contact_online((PurpleContact*)node)) @@ -472,13 +467,13 @@ add_node(PurpleBlistNode *node, FinchBlist *ggblist) if (!ggblist->manager->can_add_node(node)) return; - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (PURPLE_IS_BUDDY(node)) add_buddy((PurpleBuddy*)node, ggblist); - else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + else if (PURPLE_IS_CONTACT(node)) add_contact((PurpleContact*)node, ggblist); - else if (PURPLE_BLIST_NODE_IS_GROUP(node)) + else if (PURPLE_IS_GROUP(node)) add_group((PurpleGroup*)node, ggblist); - else if (PURPLE_BLIST_NODE_IS_CHAT(node)) + else if (PURPLE_IS_CHAT(node)) add_chat((PurpleChat *)node, ggblist); draw_tooltip(ggblist); @@ -506,7 +501,7 @@ node_remove(PurpleBuddyList *list, PurpleBlistNode *node) if (ggblist == NULL || purple_blist_node_get_ui_data(node) == NULL) return; - if (PURPLE_BLIST_NODE_IS_GROUP(node) && ggblist->new_group) { + if (PURPLE_IS_GROUP(node) && ggblist->new_group) { ggblist->new_group = g_list_remove(ggblist->new_group, node); } @@ -554,19 +549,19 @@ node_update(PurpleBuddyList *list, PurpleBlistNode *node) node_remove(list, node); } - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (PURPLE_IS_BUDDY(node)) { PurpleBuddy *buddy = (PurpleBuddy*)node; add_node((PurpleBlistNode*)buddy, FINCH_GET_DATA(list)); node_update(list, purple_blist_node_get_parent(node)); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { add_node(node, FINCH_GET_DATA(list)); - } else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + } else if (PURPLE_IS_CONTACT(node)) { if (purple_blist_node_get_ui_data(node)== NULL) { /* The core seems to expect the UI to add the buddies. */ for (node = purple_blist_node_get_first_child(node); node; node = purple_blist_node_get_sibling_next(node)) add_node(node, FINCH_GET_DATA(list)); } - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { if (!ggblist->manager->can_add_node(node)) node_remove(list, node); else @@ -608,7 +603,7 @@ remove_new_empty_group(gpointer data) if (!ggblist) return FALSE; - list = purple_get_blist(); + list = purple_blist_get_buddy_list(); g_return_val_if_fail(list, FALSE); ggblist->new_group_timeout = 0; @@ -649,7 +644,7 @@ add_buddy_cb(void *data, PurpleRequestFields *allfields) return; } - grp = purple_find_group(group); + grp = purple_blist_find_group(group); if (!grp) { grp = purple_group_new(group); @@ -658,7 +653,7 @@ add_buddy_cb(void *data, PurpleRequestFields *allfields) /* XXX: Ask to merge if there's already a buddy with the same alias in the same group (#4553) */ - if ((buddy = purple_find_buddy_in_group(account, username, grp)) == NULL) + if ((buddy = purple_blist_find_buddy_in_group(account, username, grp)) == NULL) { buddy = purple_buddy_new(account, username, alias); purple_blist_add_buddy(buddy, NULL, grp, NULL); @@ -708,24 +703,16 @@ join_chat(PurpleChat *chat) { PurpleAccount *account = purple_chat_get_account(chat); const char *name; - PurpleConversation *conv; - const char *alias; - - /* This hack here is to work around the fact that there's no good way of - * getting the actual name of a chat. I don't understand why we return - * the alias for a chat when all we want is the name. */ - alias = chat->alias; - chat->alias = NULL; - name = purple_chat_get_name(chat); - conv = purple_find_conversation_with_account( - PURPLE_CONV_TYPE_CHAT, name, account); - chat->alias = (char *)alias; - - if (!conv || purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) { + PurpleChatConversation *conv; + + name = purple_chat_get_name_only(chat); + conv = purple_conversations_find_chat_with_account(name, account); + + if (!conv || purple_chat_conversation_has_left(conv)) { serv_join_chat(purple_account_get_connection(account), purple_chat_get_components(chat)); } else if (conv) { - purple_conversation_present(conv); + purple_conversation_present(PURPLE_CONVERSATION(conv)); } } @@ -761,12 +748,12 @@ add_chat_cb(void *data, PurpleRequestFields *allfields) chat = purple_chat_new(account, name, hash); if (chat != NULL) { - if ((grp = purple_find_group(group)) == NULL) { + if ((grp = purple_blist_find_group(group)) == NULL) { grp = purple_group_new(group); purple_blist_add_group(grp, NULL); } purple_blist_add_chat(chat, grp, NULL); - purple_blist_alias_chat(chat, alias); + purple_chat_set_alias(chat, alias); purple_blist_node_set_bool((PurpleBlistNode*)chat, "gnt-autojoin", autojoin); if (autojoin) { join_chat(chat); @@ -820,7 +807,7 @@ add_group_cb(gpointer null, const char *group) return; } - grp = purple_find_group(group); + grp = purple_blist_find_group(group); if (!grp) { grp = purple_group_new(group); purple_blist_add_group(grp, NULL); @@ -905,13 +892,13 @@ get_display_name(PurpleBlistNode *node) char status[8] = " "; const char *name = NULL; - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + if (PURPLE_IS_CONTACT(node)) node = PURPLE_BLIST_NODE(purple_contact_get_priority_buddy(PURPLE_CONTACT(node))); /* XXX: this can return NULL?! */ if (node == NULL) return NULL; - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (PURPLE_IS_BUDDY(node)) { PurpleBuddy *buddy = (PurpleBuddy *)node; PurpleStatusPrimitive prim; @@ -925,7 +912,7 @@ get_display_name(PurpleBlistNode *node) else { now = purple_presence_get_active_status(presence); - prim = purple_status_type_get_primitive(purple_status_get_type(now)); + prim = purple_status_type_get_primitive(purple_status_get_status_type(now)); switch(prim) { case PURPLE_STATUS_OFFLINE: @@ -941,14 +928,14 @@ get_display_name(PurpleBlistNode *node) } name = purple_buddy_get_alias(buddy); } - else if (PURPLE_BLIST_NODE_IS_CHAT(node)) + else if (PURPLE_IS_CHAT(node)) { PurpleChat *chat = (PurpleChat*)node; name = purple_chat_get_name(chat); strncpy(status, "~", sizeof(status) - 1); } - else if (PURPLE_BLIST_NODE_IS_GROUP(node)) + else if (PURPLE_IS_GROUP(node)) return purple_group_get_name((PurpleGroup*)node); g_snprintf(text, sizeof(text) - 1, "%s %s", status, name); @@ -1028,7 +1015,7 @@ buddy_signed_on(PurpleBuddy *buddy, FinchBlist *ggblist) static void buddy_signed_off(PurpleBuddy *buddy, FinchBlist *ggblist) { - node_remove(purple_get_blist(), (PurpleBlistNode*)buddy); + node_remove(purple_blist_get_buddy_list(), (PurpleBlistNode*)buddy); } #endif @@ -1046,27 +1033,25 @@ selection_activate(GntWidget *widget, FinchBlist *ggblist) if (!node) return; - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + if (PURPLE_IS_CONTACT(node)) node = PURPLE_BLIST_NODE(purple_contact_get_priority_buddy(PURPLE_CONTACT(node))); - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (PURPLE_IS_BUDDY(node)) { PurpleBuddy *buddy = (PurpleBuddy *)node; - PurpleConversation *conv; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - purple_buddy_get_name(buddy), + PurpleIMConversation *im; + im = purple_conversations_find_im_with_account(purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); - if (!conv) { - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, - purple_buddy_get_account(buddy), + if (!im) { + im = purple_im_conversation_new(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy)); } else { - FinchConv *ggconv = FINCH_CONV(conv); + FinchConv *ggconv = FINCH_CONV(PURPLE_CONVERSATION(im)); gnt_window_present(ggconv->window); } - finch_conversation_set_active(conv); + finch_conversation_set_active(PURPLE_CONVERSATION(im)); } - else if (PURPLE_BLIST_NODE_IS_CHAT(node)) + else if (PURPLE_IS_CHAT(node)) { join_chat((PurpleChat*)node); } @@ -1253,7 +1238,7 @@ static void finch_blist_pounce_node_cb(PurpleBlistNode *selected, PurpleBlistNode *node) { PurpleBuddy *b; - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + if (PURPLE_IS_CONTACT(node)) b = purple_contact_get_priority_buddy((PurpleContact *)node); else b = (PurpleBuddy *)node; @@ -1267,8 +1252,8 @@ toggle_block_buddy(GntMenuItem *item, gpointer buddy) PurpleAccount *account = purple_buddy_get_account(buddy); const char *name = purple_buddy_get_name(buddy); - block ? purple_privacy_deny(account, name, FALSE, FALSE) : - purple_privacy_allow(account, name, FALSE, FALSE); + block ? purple_account_privacy_deny(account, name) : + purple_account_privacy_allow(account, name); } static void @@ -1277,9 +1262,9 @@ toggle_show_offline(GntMenuItem *item, gpointer buddy) purple_blist_node_set_bool(buddy, "show_offline", !purple_blist_node_get_bool(buddy, "show_offline")); if (!ggblist->manager->can_add_node(buddy)) - node_remove(purple_get_blist(), buddy); + node_remove(purple_blist_get_buddy_list(), buddy); else - node_update(purple_get_blist(), buddy); + node_update(purple_blist_get_buddy_list(), buddy); } static void @@ -1310,7 +1295,7 @@ create_buddy_menu(GntMenu *menu, PurpleBuddy *buddy) } account = purple_buddy_get_account(buddy); - permitted = purple_privacy_check(account, purple_buddy_get_name(buddy)); + permitted = purple_account_privacy_check(account, purple_buddy_get_name(buddy)); item = gnt_menuitem_check_new(_("Blocked")); gnt_menuitem_check_set_checked(GNT_MENU_ITEM_CHECK(item), !permitted); @@ -1365,19 +1350,19 @@ rename_blist_node(PurpleBlistNode *node, const char *newname) if (name && !*name) name = NULL; - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if (PURPLE_IS_CONTACT(node)) { PurpleContact *contact = (PurpleContact*)node; PurpleBuddy *buddy = purple_contact_get_priority_buddy(contact); - purple_blist_alias_contact(contact, name); - purple_blist_alias_buddy(buddy, name); + purple_contact_set_alias(contact, name); + purple_buddy_set_local_alias(buddy, name); serv_alias_buddy(buddy); - } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { - purple_blist_alias_buddy((PurpleBuddy*)node, name); + } else if (PURPLE_IS_BUDDY(node)) { + purple_buddy_set_local_alias((PurpleBuddy*)node, name); serv_alias_buddy((PurpleBuddy*)node); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) - purple_blist_alias_chat((PurpleChat*)node, name); - else if (PURPLE_BLIST_NODE_IS_GROUP(node) && (name != NULL)) - purple_blist_rename_group((PurpleGroup*)node, name); + } else if (PURPLE_IS_CHAT(node)) + purple_chat_set_alias((PurpleChat*)node, name); + else if (PURPLE_IS_GROUP(node) && (name != NULL)) + purple_group_set_name((PurpleGroup*)node, name); else g_return_if_reached(); } @@ -1389,20 +1374,20 @@ finch_blist_rename_node_cb(PurpleBlistNode *selected, PurpleBlistNode *node) char *prompt; const char *text; - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + if (PURPLE_IS_CONTACT(node)) name = purple_contact_get_alias((PurpleContact*)node); - else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + else if (PURPLE_IS_BUDDY(node)) name = purple_buddy_get_contact_alias((PurpleBuddy*)node); - else if (PURPLE_BLIST_NODE_IS_CHAT(node)) + else if (PURPLE_IS_CHAT(node)) name = purple_chat_get_name((PurpleChat*)node); - else if (PURPLE_BLIST_NODE_IS_GROUP(node)) + else if (PURPLE_IS_GROUP(node)) name = purple_group_get_name((PurpleGroup*)node); else g_return_if_reached(); prompt = g_strdup_printf(_("Please enter the new name for %s"), name); - text = PURPLE_BLIST_NODE_IS_GROUP(node) ? _("Rename") : _("Set Alias"); + text = PURPLE_IS_GROUP(node) ? _("Rename") : _("Set Alias"); purple_request_input(node, text, prompt, _("Enter empty string to reset the name."), name, FALSE, FALSE, NULL, text, G_CALLBACK(rename_blist_node), _("Cancel"), NULL, @@ -1419,12 +1404,12 @@ static void showlog_cb(PurpleBlistNode *sel, PurpleBlistNode *node) PurpleAccount *account; char *name = NULL; - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (PURPLE_IS_BUDDY(node)) { PurpleBuddy *b = (PurpleBuddy*) node; type = PURPLE_LOG_IM; name = g_strdup(purple_buddy_get_name(b)); account = purple_buddy_get_account(b); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { PurpleChat *c = (PurpleChat*) node; PurplePluginProtocolInfo *prpl_info = NULL; type = PURPLE_LOG_CHAT; @@ -1433,7 +1418,7 @@ static void showlog_cb(PurpleBlistNode *sel, PurpleBlistNode *node) if (prpl_info && prpl_info->get_chat_name) { name = prpl_info->get_chat_name(purple_chat_get_components(c)); } - } else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + } else if (PURPLE_IS_CONTACT(node)) { finch_log_show_contact((PurpleContact *)node); return; } else { @@ -1458,12 +1443,12 @@ remove_group(PurpleGroup *group) cnode = purple_blist_node_get_first_child(((PurpleBlistNode*)group)); while (cnode) { - if (PURPLE_BLIST_NODE_IS_CONTACT(cnode)) { + if (PURPLE_IS_CONTACT(cnode)) { bnode = purple_blist_node_get_first_child(cnode); cnode = purple_blist_node_get_sibling_next(cnode); while (bnode) { PurpleBuddy *buddy; - if (PURPLE_BLIST_NODE_IS_BUDDY(bnode)) { + if (PURPLE_IS_BUDDY(bnode)) { PurpleAccount *account; buddy = (PurpleBuddy*)bnode; bnode = purple_blist_node_get_sibling_next(bnode); @@ -1476,7 +1461,7 @@ remove_group(PurpleGroup *group) bnode = purple_blist_node_get_sibling_next(bnode); } } - } else if (PURPLE_BLIST_NODE_IS_CHAT(cnode)) { + } else if (PURPLE_IS_CHAT(cnode)) { PurpleChat *chat = (PurpleChat *)cnode; cnode = purple_blist_node_get_sibling_next(cnode); if (purple_account_is_connected(purple_chat_get_account(chat))) @@ -1492,16 +1477,16 @@ remove_group(PurpleGroup *group) static void finch_blist_remove_node(PurpleBlistNode *node) { - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if (PURPLE_IS_CONTACT(node)) { remove_contact((PurpleContact*)node); - } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + } else if (PURPLE_IS_BUDDY(node)) { PurpleBuddy *buddy = (PurpleBuddy*)node; PurpleGroup *group = purple_buddy_get_group(buddy); purple_account_remove_buddy(purple_buddy_get_account(buddy), buddy, group); purple_blist_remove_buddy(buddy); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { purple_blist_remove_chat((PurpleChat*)node); - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { remove_group((PurpleGroup*)node); } } @@ -1513,17 +1498,17 @@ finch_blist_remove_node_cb(PurpleBlistNode *selected, PurpleBlistNode *node) char *primary; const char *name, *sec = NULL; - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if (PURPLE_IS_CONTACT(node)) { PurpleContact *c = (PurpleContact*)node; name = purple_contact_get_alias(c); - if (purple_contact_get_contact_size(c, TRUE) > 1) + if (purple_counting_node_get_total_size(PURPLE_COUNTING_NODE(c)) > 1) sec = _("Removing this contact will also remove all the buddies in the contact"); - } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + } else if (PURPLE_IS_BUDDY(node)) { name = purple_buddy_get_name((PurpleBuddy*)node); account = purple_buddy_get_account((PurpleBuddy*)node); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { name = purple_chat_get_name((PurpleChat*)node); - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { name = purple_group_get_name((PurpleGroup*)node); sec = _("Removing this group will also remove all the buddies in the group"); } @@ -1554,9 +1539,9 @@ finch_blist_toggle_tag_buddy(PurpleBlistNode *node) } else { ggblist->tagged = g_list_prepend(ggblist->tagged, node); } - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + if (PURPLE_IS_CONTACT(node)) update_buddy_display(purple_contact_get_priority_buddy(PURPLE_CONTACT(node)), ggblist); - else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + else if (PURPLE_IS_BUDDY(node)) update_buddy_display((PurpleBuddy*)node, ggblist); else update_node_display(node, ggblist); @@ -1568,17 +1553,17 @@ finch_blist_place_tagged(PurpleBlistNode *target) PurpleGroup *tg = NULL; PurpleContact *tc = NULL; - if (target == NULL || - purple_blist_node_get_type(target) == PURPLE_BLIST_OTHER_NODE) + if (target == NULL || !(PURPLE_IS_BUDDY(target) || PURPLE_IS_CONTACT(target) || + PURPLE_IS_GROUP(target) || PURPLE_IS_CHAT(target))) return; - if (PURPLE_BLIST_NODE_IS_GROUP(target)) + if (PURPLE_IS_GROUP(target)) tg = (PurpleGroup*)target; - else if (PURPLE_BLIST_NODE_IS_BUDDY(target)) { + else if (PURPLE_IS_BUDDY(target)) { tc = (PurpleContact*)purple_blist_node_get_parent(target); tg = (PurpleGroup*)purple_blist_node_get_parent((PurpleBlistNode*)tc); } else { - if (PURPLE_BLIST_NODE_IS_CONTACT(target)) + if (PURPLE_IS_CONTACT(target)) tc = (PurpleContact*)target; tg = (PurpleGroup*)purple_blist_node_get_parent(target); } @@ -1590,38 +1575,38 @@ finch_blist_place_tagged(PurpleBlistNode *target) PurpleBlistNode *node = list->data; list = g_list_delete_link(list, list); - if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + if (PURPLE_IS_GROUP(node)) { update_node_display(node, ggblist); /* Add the group after the current group */ purple_blist_add_group((PurpleGroup*)node, (PurpleBlistNode*)tg); - } else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + } else if (PURPLE_IS_CONTACT(node)) { update_buddy_display(purple_contact_get_priority_buddy((PurpleContact*)node), ggblist); if (PURPLE_BLIST_NODE(tg) == target) { /* The target is a group, just add the contact to the group. */ purple_blist_add_contact((PurpleContact*)node, tg, NULL); } else if (tc) { /* The target is either a buddy, or a contact. Merge with that contact. */ - purple_blist_merge_contact((PurpleContact*)node, (PurpleBlistNode*)tc); + purple_contact_merge((PurpleContact*)node, (PurpleBlistNode*)tc); } else { /* The target is a chat. Add the contact to the group after this chat. */ purple_blist_add_contact((PurpleContact*)node, NULL, target); } - } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + } else if (PURPLE_IS_BUDDY(node)) { update_buddy_display((PurpleBuddy*)node, ggblist); if (PURPLE_BLIST_NODE(tg) == target) { /* The target is a group. Add this buddy in a new contact under this group. */ purple_blist_add_buddy((PurpleBuddy*)node, NULL, tg, NULL); - } else if (PURPLE_BLIST_NODE_IS_CONTACT(target)) { + } else if (PURPLE_IS_CONTACT(target)) { /* Add to the contact. */ purple_blist_add_buddy((PurpleBuddy*)node, tc, NULL, NULL); - } else if (PURPLE_BLIST_NODE_IS_BUDDY(target)) { + } else if (PURPLE_IS_BUDDY(target)) { /* Add to the contact after the selected buddy. */ purple_blist_add_buddy((PurpleBuddy*)node, NULL, NULL, target); - } else if (PURPLE_BLIST_NODE_IS_CHAT(target)) { + } else if (PURPLE_IS_CHAT(target)) { /* Add to the selected chat's group. */ purple_blist_add_buddy((PurpleBuddy*)node, NULL, tg, NULL); } - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { update_node_display(node, ggblist); if (PURPLE_BLIST_NODE(tg) == target) purple_blist_add_chat((PurpleChat*)node, tg, NULL); @@ -1653,7 +1638,8 @@ draw_context_menu(FinchBlist *ggblist) tree = GNT_TREE(ggblist->tree); node = gnt_tree_get_selection_data(tree); - if (node && purple_blist_node_get_type(node) == PURPLE_BLIST_OTHER_NODE) + if (node && !(PURPLE_IS_BUDDY(node) || PURPLE_IS_CONTACT(node) || + PURPLE_IS_GROUP(node) || PURPLE_IS_CHAT(node))) return; if (ggblist->tooltip) @@ -1668,19 +1654,19 @@ draw_context_menu(FinchBlist *ggblist) if (!node) { create_group_menu(GNT_MENU(context), NULL); title = g_strdup(_("Buddy List")); - } else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + } else if (PURPLE_IS_CONTACT(node)) { ggblist->cnode = PURPLE_BLIST_NODE(purple_contact_get_priority_buddy(PURPLE_CONTACT(node))); create_buddy_menu(GNT_MENU(context), (PurpleBuddy*)ggblist->cnode); title = g_strdup(purple_contact_get_alias((PurpleContact*)node)); - } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + } else if (PURPLE_IS_BUDDY(node)) { PurpleBuddy *buddy = (PurpleBuddy *)node; create_buddy_menu(GNT_MENU(context), buddy); title = g_strdup(purple_buddy_get_name(buddy)); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { PurpleChat *chat = (PurpleChat*)node; create_chat_menu(GNT_MENU(context), chat); title = g_strdup(purple_chat_get_name(chat)); - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { PurpleGroup *group = (PurpleGroup *)node; create_group_menu(GNT_MENU(context), group); title = g_strdup(purple_group_get_name(group)); @@ -1691,22 +1677,22 @@ draw_context_menu(FinchBlist *ggblist) /* These are common for everything */ if (node) { add_custom_action(GNT_MENU(context), - PURPLE_BLIST_NODE_IS_GROUP(node) ? _("Rename") : _("Alias"), + PURPLE_IS_GROUP(node) ? _("Rename") : _("Alias"), PURPLE_CALLBACK(finch_blist_rename_node_cb), node); add_custom_action(GNT_MENU(context), _("Remove"), PURPLE_CALLBACK(finch_blist_remove_node_cb), node); - if (ggblist->tagged && (PURPLE_BLIST_NODE_IS_CONTACT(node) - || PURPLE_BLIST_NODE_IS_GROUP(node))) { + if (ggblist->tagged && (PURPLE_IS_CONTACT(node) + || PURPLE_IS_GROUP(node))) { add_custom_action(GNT_MENU(context), _("Place tagged"), PURPLE_CALLBACK(finch_blist_place_tagged), node); } - if (PURPLE_BLIST_NODE_IS_BUDDY(node) || PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if (PURPLE_IS_BUDDY(node) || PURPLE_IS_CONTACT(node)) { add_custom_action(GNT_MENU(context), _("Toggle Tag"), PURPLE_CALLBACK(finch_blist_toggle_tag_buddy), node); } - if (!PURPLE_BLIST_NODE_IS_GROUP(node)) { + if (!PURPLE_IS_GROUP(node)) { add_custom_action(GNT_MENU(context), _("View Log"), PURPLE_CALLBACK(showlog_cb), node); } @@ -1902,7 +1888,7 @@ key_pressed(GntWidget *widget, const char *text, FinchBlist *ggblist) } else if (strcmp(text, GNT_KEY_INS) == 0) { PurpleBlistNode *node = gnt_tree_get_selection_data(GNT_TREE(ggblist->tree)); purple_blist_request_add_buddy(NULL, NULL, - node && PURPLE_BLIST_NODE_IS_GROUP(node) ? purple_group_get_name(PURPLE_GROUP(node)) : NULL, + node && PURPLE_IS_GROUP(node) ? purple_group_get_name(PURPLE_GROUP(node)) : NULL, NULL); } else if (!gnt_tree_is_searching(GNT_TREE(ggblist->tree))) { if (strcmp(text, "t") == 0) { @@ -1985,7 +1971,7 @@ reset_blist_window(GntWidget *window, gpointer null) { PurpleBlistNode *node; purple_signals_disconnect_by_handle(finch_blist_get_handle()); - FINCH_SET_DATA(purple_get_blist(), NULL); + FINCH_SET_DATA(purple_blist_get_buddy_list(), NULL); node = purple_blist_get_root(); while (node) { @@ -2028,7 +2014,7 @@ populate_buddylist(void) (GCompareFunc)blist_node_compare_log); } - list = purple_get_blist(); + list = purple_blist_get_buddy_list(); node = purple_blist_get_root(); while (node) { @@ -2359,25 +2345,21 @@ blist_node_compare_text(PurpleBlistNode *n1, PurpleBlistNode *n2) char *us1, *us2; int ret; - if (purple_blist_node_get_type(n1) != purple_blist_node_get_type(n2)) + if (G_OBJECT_TYPE(n1) != G_OBJECT_TYPE(n2)) return blist_node_compare_position(n1, n2); - switch (purple_blist_node_get_type(n1)) - { - case PURPLE_BLIST_CHAT_NODE: - s1 = purple_chat_get_name((PurpleChat*)n1); - s2 = purple_chat_get_name((PurpleChat*)n2); - break; - case PURPLE_BLIST_BUDDY_NODE: - return purple_presence_compare(purple_buddy_get_presence((PurpleBuddy*)n1), - purple_buddy_get_presence((PurpleBuddy*)n2)); - break; - case PURPLE_BLIST_CONTACT_NODE: - s1 = purple_contact_get_alias((PurpleContact*)n1); - s2 = purple_contact_get_alias((PurpleContact*)n2); - break; - default: - return blist_node_compare_position(n1, n2); + if (PURPLE_IS_CHAT(n1)) { + s1 = purple_chat_get_name((PurpleChat*)n1); + s2 = purple_chat_get_name((PurpleChat*)n2); + } else if (PURPLE_IS_BUDDY(n1)) { + return purple_buddy_presence_compare( + PURPLE_BUDDY_PRESENCE(purple_buddy_get_presence(PURPLE_BUDDY(n1))), + PURPLE_BUDDY_PRESENCE(purple_buddy_get_presence(PURPLE_BUDDY(n2)))); + } else if (PURPLE_IS_CONTACT(n1)) { + s1 = purple_contact_get_alias((PurpleContact*)n1); + s2 = purple_contact_get_alias((PurpleContact*)n2); + } else { + return blist_node_compare_position(n1, n2); } us1 = g_utf8_strup(s1, -1); @@ -2394,23 +2376,22 @@ blist_node_compare_status(PurpleBlistNode *n1, PurpleBlistNode *n2) { int ret; - if (purple_blist_node_get_type(n1) != purple_blist_node_get_type(n2)) + if (G_OBJECT_TYPE(n1) != G_OBJECT_TYPE(n2)) return blist_node_compare_position(n1, n2); - switch (purple_blist_node_get_type(n1)) { - case PURPLE_BLIST_CONTACT_NODE: - n1 = PURPLE_BLIST_NODE(purple_contact_get_priority_buddy(PURPLE_CONTACT(n1))); - n2 = PURPLE_BLIST_NODE(purple_contact_get_priority_buddy(PURPLE_CONTACT(n2))); - /* now compare the presence of the priority buddies */ - case PURPLE_BLIST_BUDDY_NODE: - ret = purple_presence_compare(purple_buddy_get_presence((PurpleBuddy*)n1), - purple_buddy_get_presence((PurpleBuddy*)n2)); - if (ret != 0) - return ret; - break; - default: - return blist_node_compare_position(n1, n2); - break; + if (PURPLE_IS_CONTACT(n1) || PURPLE_IS_BUDDY(n1)) { + n1 = PURPLE_BLIST_NODE(purple_contact_get_priority_buddy(PURPLE_CONTACT(n1))); + n2 = PURPLE_BLIST_NODE(purple_contact_get_priority_buddy(PURPLE_CONTACT(n2))); + } + + if (PURPLE_IS_BUDDY(n1)) { + ret = purple_buddy_presence_compare( + PURPLE_BUDDY_PRESENCE(purple_buddy_get_presence(PURPLE_BUDDY(n1))), + PURPLE_BUDDY_PRESENCE(purple_buddy_get_presence(PURPLE_BUDDY(n2)))); + if (ret != 0) + return ret; + } else { + return blist_node_compare_position(n1, n2); } /* Sort alphabetically if presence is not comparable */ @@ -2440,26 +2421,24 @@ blist_node_compare_log(PurpleBlistNode *n1, PurpleBlistNode *n2) int ret; PurpleBuddy *b1, *b2; - if (purple_blist_node_get_type(n1) != purple_blist_node_get_type(n2)) + if (G_OBJECT_TYPE(n1) != G_OBJECT_TYPE(n2)) return blist_node_compare_position(n1, n2); - switch (purple_blist_node_get_type(n1)) { - case PURPLE_BLIST_BUDDY_NODE: - b1 = (PurpleBuddy*)n1; - b2 = (PurpleBuddy*)n2; - ret = purple_log_get_total_size(PURPLE_LOG_IM, purple_buddy_get_name(b2), purple_buddy_get_account(b2)) - - purple_log_get_total_size(PURPLE_LOG_IM, purple_buddy_get_name(b1), purple_buddy_get_account(b1)); - if (ret != 0) - return ret; - break; - case PURPLE_BLIST_CONTACT_NODE: - ret = get_contact_log_size(n2) - get_contact_log_size(n1); - if (ret != 0) - return ret; - break; - default: - return blist_node_compare_position(n1, n2); + if (PURPLE_IS_BUDDY(n1)) { + b1 = (PurpleBuddy*)n1; + b2 = (PurpleBuddy*)n2; + ret = purple_log_get_total_size(PURPLE_LOG_IM, purple_buddy_get_name(b2), purple_buddy_get_account(b2)) - + purple_log_get_total_size(PURPLE_LOG_IM, purple_buddy_get_name(b1), purple_buddy_get_account(b1)); + if (ret != 0) + return ret; + } else if (PURPLE_IS_CONTACT(n1)) { + ret = get_contact_log_size(n2) - get_contact_log_size(n1); + if (ret != 0) + return ret; + } else { + return blist_node_compare_position(n1, n2); } + ret = blist_node_compare_text(n1, n2); return ret; } @@ -2506,13 +2485,14 @@ buddy_recent_signed_on_off(gpointer data) fnode->signed_timer = 0; if (!ggblist->manager->can_add_node(node)) { - node_remove(purple_get_blist(), node); + node_remove(purple_blist_get_buddy_list(), node); } else { update_node_display(node, ggblist); - if (purple_blist_node_get_parent(node) && PURPLE_BLIST_NODE_IS_CONTACT(purple_blist_node_get_parent(node))) + if (purple_blist_node_get_parent(node) && PURPLE_IS_CONTACT(purple_blist_node_get_parent(node))) update_node_display(purple_blist_node_get_parent(node), ggblist); } + g_object_unref(node); return FALSE; } @@ -2526,9 +2506,11 @@ buddy_signed_on_off_cb(gpointer data) if (fnode->signed_timer) purple_timeout_remove(fnode->signed_timer); + + g_object_ref(node); fnode->signed_timer = purple_timeout_add_seconds(6, (GSourceFunc)buddy_recent_signed_on_off, data); update_node_display(node, ggblist); - if (purple_blist_node_get_parent(node) && PURPLE_BLIST_NODE_IS_CONTACT(purple_blist_node_get_parent(node))) + if (purple_blist_node_get_parent(node) && PURPLE_IS_CONTACT(purple_blist_node_get_parent(node))) update_node_display(purple_blist_node_get_parent(node), ggblist); return FALSE; } @@ -2639,7 +2621,7 @@ auto_join_chats(gpointer data) for (node = purple_blist_get_root(); node; node = purple_blist_node_next(node, FALSE)) { - if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + if (PURPLE_IS_CHAT(node)) { PurpleChat *chat = (PurpleChat*)node; if (purple_chat_get_account(chat) == account && purple_blist_node_get_bool(node, "gnt-autojoin")) @@ -2673,9 +2655,9 @@ block_select_cb(gpointer data, PurpleRequestFields *fields) const char *name = purple_request_fields_get_string(fields, "screenname"); if (account && name && *name != '\0') { if (purple_request_fields_get_choice(fields, "block") == 1) { - purple_privacy_deny(account, name, FALSE, FALSE); + purple_account_privacy_deny(account, name); } else { - purple_privacy_allow(account, name, FALSE, FALSE); + purple_account_privacy_allow(account, name); } } } @@ -2710,7 +2692,7 @@ block_select(GntMenuItem *item, gpointer n) purple_request_field_choice_add(field, _("Unblock")); purple_request_field_group_add_field(group, field); - purple_request_fields(purple_get_blist(), _("Block/Unblock"), + purple_request_fields(purple_blist_get_buddy_list(), _("Block/Unblock"), NULL, _("Please enter the username or alias of the person " "you would like to Block/Unblock."), @@ -2727,13 +2709,13 @@ send_im_select_cb(gpointer data, PurpleRequestFields *fields) { PurpleAccount *account; const char *username; - PurpleConversation *conv; + PurpleIMConversation *im; account = purple_request_fields_get_account(fields, "account"); username = purple_request_fields_get_string(fields, "screenname"); - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, username); - purple_conversation_present(conv); + im = purple_im_conversation_new(account, username); + purple_conversation_present(PURPLE_CONVERSATION(im)); } static void @@ -2761,7 +2743,7 @@ send_im_select(GntMenuItem *item, gpointer n) purple_request_field_set_required(field, TRUE); purple_request_field_group_add_field(group, field); - purple_request_fields(purple_get_blist(), _("New Instant Message"), + purple_request_fields(purple_blist_get_buddy_list(), _("New Instant Message"), NULL, _("Please enter the username or alias of the person " "you would like to IM."), @@ -2780,7 +2762,7 @@ join_chat_select_cb(gpointer data, PurpleRequestFields *fields) PurpleConnection *gc; PurpleChat *chat; GHashTable *hash = NULL; - PurpleConversation *conv; + PurpleChatConversation *conv; account = purple_request_fields_get_account(fields, "account"); name = purple_request_fields_get_string(fields, "chat"); @@ -2792,11 +2774,11 @@ join_chat_select_cb(gpointer data, PurpleRequestFields *fields) /* Create a new conversation now. This will give focus to the new window. * But it's necessary to pretend that we left the chat, because otherwise * a new conversation window will pop up when we finally join the chat. */ - if (!(conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, name, account))) { - conv = purple_conversation_new(PURPLE_CONV_TYPE_CHAT, account, name); - purple_conv_chat_left(PURPLE_CONV_CHAT(conv)); + if (!(conv = purple_conversations_find_chat_with_account(name, account))) { + conv = purple_chat_conversation_new(account, name); + purple_chat_conversation_leave(conv); } else { - purple_conversation_present(conv); + purple_conversation_present(PURPLE_CONVERSATION(conv)); } chat = purple_blist_find_chat(account, name); @@ -2836,7 +2818,7 @@ join_chat_select(GntMenuItem *item, gpointer n) purple_request_field_set_required(field, TRUE); purple_request_field_group_add_field(group, field); - purple_request_fields(purple_get_blist(), _("Join a Chat"), + purple_request_fields(purple_blist_get_buddy_list(), _("Join a Chat"), NULL, _("Please enter the name of the chat you want to join."), fields, @@ -2857,7 +2839,7 @@ view_log_select_cb(gpointer data, PurpleRequestFields *fields) account = purple_request_fields_get_account(fields, "account"); name = purple_request_fields_get_string(fields, "screenname"); - buddy = purple_find_buddy(account, name); + buddy = purple_blist_find_buddy(account, name); if (buddy) { contact = purple_buddy_get_contact(buddy); } else { @@ -2897,7 +2879,7 @@ view_log_cb(GntMenuItem *item, gpointer n) purple_request_field_group_add_field(group, field); purple_request_field_account_set_show_all(field, TRUE); - purple_request_fields(purple_get_blist(), _("View Log"), + purple_request_fields(purple_blist_get_buddy_list(), _("View Log"), NULL, _("Please enter the username or alias of the person " "whose log you would like to view."), @@ -3057,13 +3039,13 @@ create_menu(void) void finch_blist_show() { - blist_show(purple_get_blist()); + blist_show(purple_blist_get_buddy_list()); } static void group_collapsed(GntWidget *widget, PurpleBlistNode *node, gboolean collapsed, gpointer null) { - if (PURPLE_BLIST_NODE_IS_GROUP(node)) + if (PURPLE_IS_GROUP(node)) purple_blist_node_set_bool(node, "collapsed", collapsed); } diff --git a/finch/gntblist.h b/finch/gntblist.h index 5b67691970..5c3dadfcc3 100644 --- a/finch/gntblist.h +++ b/finch/gntblist.h @@ -26,7 +26,7 @@ #ifndef _GNT_BLIST_H #define _GNT_BLIST_H -#include "blist.h" +#include "buddylist.h" #include "gnttree.h" /********************************************************************** diff --git a/finch/gntconv.c b/finch/gntconv.c index ca8d826a6a..1f189387e6 100644 --- a/finch/gntconv.c +++ b/finch/gntconv.c @@ -78,7 +78,7 @@ static int color_timestamp; static PurpleBuddy * find_buddy_for_conversation(PurpleConversation *conv) { - return purple_find_buddy(purple_conversation_get_account(conv), + return purple_blist_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); } @@ -94,17 +94,13 @@ get_conversation_blist_node(PurpleConversation *conv) { PurpleBlistNode *node = NULL; - switch (purple_conversation_get_type(conv)) { - case PURPLE_CONV_TYPE_IM: - node = (PurpleBlistNode*)find_buddy_for_conversation(conv); - node = node ? purple_blist_node_get_parent(node) : NULL; - break; - case PURPLE_CONV_TYPE_CHAT: - node = (PurpleBlistNode*)find_chat_for_conversation(conv); - break; - default: - break; + if (PURPLE_IS_IM_CONVERSATION(conv)) { + node = (PurpleBlistNode*)find_buddy_for_conversation(conv); + node = node ? purple_blist_node_get_parent(node) : NULL; + } else { + node = (PurpleBlistNode*)find_chat_for_conversation(conv); } + return node; } @@ -115,26 +111,26 @@ send_typing_notification(GntWidget *w, FinchConv *ggconv) gboolean empty = (!text || !*text || (*text == '/')); if (purple_prefs_get_bool("/finch/conversations/notify_typing")) { PurpleConversation *conv = ggconv->active_conv; - PurpleConvIm *im = PURPLE_CONV_IM(conv); + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(conv); if (!empty) { - gboolean send = (purple_conv_im_get_send_typed_timeout(im) == 0); + gboolean send = (purple_im_conversation_get_send_typed_timeout(im) == 0); - purple_conv_im_stop_send_typed_timeout(im); - purple_conv_im_start_send_typed_timeout(im); - if (send || (purple_conv_im_get_type_again(im) != 0 && - time(NULL) > purple_conv_im_get_type_again(im))) { + purple_im_conversation_stop_send_typed_timeout(im); + purple_im_conversation_start_send_typed_timeout(im); + if (send || (purple_im_conversation_get_type_again(im) != 0 && + time(NULL) > purple_im_conversation_get_type_again(im))) { unsigned int timeout; timeout = serv_send_typing(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), - PURPLE_TYPING); - purple_conv_im_set_type_again(im, timeout); + PURPLE_IM_TYPING); + purple_im_conversation_set_type_again(im, timeout); } } else { - purple_conv_im_stop_send_typed_timeout(im); + purple_im_conversation_stop_send_typed_timeout(im); serv_send_typing(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), - PURPLE_NOT_TYPING); + PURPLE_IM_NOT_TYPING); } } } @@ -172,7 +168,7 @@ entry_key_pressed(GntWidget *w, FinchConv *ggconv) PURPLE_MESSAGE_NO_LOG, time(NULL)); break; case PURPLE_CMD_STATUS_WRONG_TYPE: - if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) + if(PURPLE_IS_IM_CONVERSATION(conv)) purple_conversation_write(conv, "", _("That command only works in chats, not IMs."), PURPLE_MESSAGE_NO_LOG, time(NULL)); else @@ -194,18 +190,7 @@ entry_key_pressed(GntWidget *w, FinchConv *ggconv) else { char *escape = purple_markup_escape_text((*text == '/' ? text + 1 : text), -1); - switch (purple_conversation_get_type(ggconv->active_conv)) - { - case PURPLE_CONV_TYPE_IM: - purple_conv_im_send_with_flags(PURPLE_CONV_IM(ggconv->active_conv), escape, PURPLE_MESSAGE_SEND); - break; - case PURPLE_CONV_TYPE_CHAT: - purple_conv_chat_send(PURPLE_CONV_CHAT(ggconv->active_conv), escape); - break; - default: - g_free(escape); - g_return_if_reached(); - } + purple_conversation_send(ggconv->active_conv, escape); g_free(escape); purple_idle_touch(); } @@ -221,7 +206,7 @@ closing_window(GntWidget *window, FinchConv *ggconv) while (list) { PurpleConversation *conv = list->data; list = list->next; - purple_conversation_destroy(conv); + g_object_unref(conv); } } @@ -241,12 +226,12 @@ save_position_cb(GntWidget *w, int x, int y) purple_prefs_set_int(PREF_ROOT "/position/y", y); } -static PurpleConversation * -find_conv_with_contact(PurpleAccount *account, const char *name) +static PurpleIMConversation * +find_im_with_contact(PurpleAccount *account, const char *name) { PurpleBlistNode *node; - PurpleBuddy *buddy = purple_find_buddy(account, name); - PurpleConversation *ret = NULL; + PurpleBuddy *buddy = purple_blist_find_buddy(account, name); + PurpleIMConversation *im = NULL; if (!buddy) return NULL; @@ -255,11 +240,11 @@ find_conv_with_contact(PurpleAccount *account, const char *name) node; node = purple_blist_node_get_sibling_next(node)) { if (node == (PurpleBlistNode*)buddy) continue; - if ((ret = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, + if ((im = purple_conversations_find_im_with_account( purple_buddy_get_name((PurpleBuddy*)node), purple_buddy_get_account((PurpleBuddy*)node))) != NULL) break; } - return ret; + return im; } static char * @@ -272,20 +257,20 @@ get_conversation_title(PurpleConversation *conv, PurpleAccount *account) static void update_buddy_typing(PurpleAccount *account, const char *who, gpointer null) { - PurpleConversation *conv; FinchConv *ggc; - PurpleConvIm *im = NULL; + PurpleIMConversation *im; + PurpleConversation *conv; char *title, *str; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account); + im = purple_conversations_find_im_with_account(who, account); - if (!conv) + if (!im) return; - im = PURPLE_CONV_IM(conv); + conv = PURPLE_CONVERSATION(im); ggc = FINCH_CONV(conv); - if (purple_conv_im_get_typing_state(im) == PURPLE_TYPING) { + if (purple_im_conversation_get_typing_state(im) == PURPLE_IM_TYPING) { int scroll; str = get_conversation_title(conv, account); title = g_strdup_printf(_("%s [%s]"), str, @@ -319,29 +304,29 @@ chat_left_cb(PurpleConversation *conv, gpointer null) static void buddy_signed_on_off(PurpleBuddy *buddy, gpointer null) { - PurpleConversation *conv = find_conv_with_contact(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy)); - if (conv == NULL) + PurpleIMConversation *im = find_im_with_contact(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy)); + if (im == NULL) return; - generate_send_to_menu(FINCH_CONV(conv)); + generate_send_to_menu(FINCH_CONV(PURPLE_CONVERSATION(im))); } static void account_signed_on_off(PurpleConnection *gc, gpointer null) { - GList *list = purple_get_ims(); + GList *list = purple_conversations_get_ims(); while (list) { PurpleConversation *conv = list->data; - PurpleConversation *cc = find_conv_with_contact( + PurpleIMConversation *cc = find_im_with_contact( purple_conversation_get_account(conv), purple_conversation_get_name(conv)); if (cc) - generate_send_to_menu(FINCH_CONV(cc)); + generate_send_to_menu(FINCH_CONV(PURPLE_CONVERSATION(cc))); list = list->next; } if (PURPLE_CONNECTION_IS_CONNECTED(gc)) { /* We just signed on. Let's see if there's any chat that we have open, * and hadn't left before the disconnect. */ - list = purple_get_chats(); + list = purple_conversations_get_chats(); while (list) { PurpleConversation *conv = list->data; PurpleChat *chat; @@ -349,7 +334,7 @@ account_signed_on_off(PurpleConnection *gc, gpointer null) list = list->next; if (purple_conversation_get_account(conv) != purple_connection_get_account(gc) || - !purple_conversation_get_data(conv, "want-to-rejoin")) + !g_object_get_data(G_OBJECT(conv), "want-to-rejoin")) continue; chat = find_chat_for_conversation(conv); @@ -370,16 +355,16 @@ account_signed_on_off(PurpleConnection *gc, gpointer null) static void account_signing_off(PurpleConnection *gc) { - GList *list = purple_get_chats(); + GList *list = purple_conversations_get_chats(); PurpleAccount *account = purple_connection_get_account(gc); /* We are about to sign off. See which chats we are currently in, and mark * them for rejoin on reconnect. */ while (list) { PurpleConversation *conv = list->data; - if (!purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)) && + if (!purple_chat_conversation_has_left(PURPLE_CHAT_CONVERSATION(conv)) && purple_conversation_get_account(conv) == account) { - purple_conversation_set_data(conv, "want-to-rejoin", GINT_TO_POINTER(TRUE)); + g_object_set_data(G_OBJECT(conv), "want-to-rejoin", GINT_TO_POINTER(TRUE)); purple_conversation_write(conv, NULL, _("The account has disconnected and you are no " "longer in this chat. You will be automatically rejoined in the chat when " "the account reconnects."), @@ -421,9 +406,9 @@ gg_extended_menu(FinchConv *ggc) } static void -conv_updated(PurpleConversation *conv, PurpleConvUpdateType type) +conv_updated(PurpleConversation *conv, PurpleConversationUpdateType type) { - if (type == PURPLE_CONV_UPDATE_FEATURES) { + if (type == PURPLE_CONVERSATION_UPDATE_FEATURES) { gg_extended_menu(purple_conversation_get_ui_data(conv)); } } @@ -518,8 +503,8 @@ send_to_cb(GntMenuItem *m, gpointer n) { PurpleAccount *account = g_object_get_data(G_OBJECT(m), "purple_account"); gchar *buddy = g_object_get_data(G_OBJECT(m), "purple_buddy_name"); - PurpleConversation *conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, buddy); - finch_conversation_set_active(conv); + PurpleIMConversation *im = purple_im_conversation_new(account, buddy); + finch_conversation_set_active(PURPLE_CONVERSATION(im)); } static void @@ -536,17 +521,15 @@ view_log_cb(GntMenuItem *n, gpointer ggc) fc = ggc; conv = fc->active_conv; - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) + if (PURPLE_IS_IM_CONVERSATION(conv)) type = PURPLE_LOG_IM; - else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) - type = PURPLE_LOG_CHAT; else - return; + type = PURPLE_LOG_CHAT; name = purple_conversation_get_name(conv); account = purple_conversation_get_account(conv); - buddies = purple_find_buddies(account, name); + buddies = purple_blist_find_buddies(account, name); for (cur = buddies; cur != NULL; cur = cur->next) { PurpleBlistNode *node = cur->data; if ((node != NULL) && @@ -569,7 +552,7 @@ generate_send_to_menu(FinchConv *ggc) GSList *buds; GList *list = NULL; - buds = purple_find_buddies(purple_conversation_get_account(ggc->active_conv), + buds = purple_blist_find_buddies(purple_conversation_get_account(ggc->active_conv), purple_conversation_get_name(ggc->active_conv)); if (!buds) return; @@ -598,7 +581,7 @@ generate_send_to_menu(FinchConv *ggc) } for (list = g_list_reverse(list); list != NULL; list = g_list_delete_link(list, list)) { PurplePresence *pre = list->data; - PurpleBuddy *buddy = purple_presence_get_buddy(pre); + PurpleBuddy *buddy = purple_buddy_presence_get_buddy(PURPLE_BUDDY_PRESENCE(pre)); PurpleAccount *account = purple_buddy_get_account(buddy); gchar *name = g_strdup(purple_buddy_get_name(buddy)); gchar *text = g_strdup_printf("%s (%s)", purple_buddy_get_name(buddy), purple_account_get_username(account)); @@ -615,8 +598,8 @@ static void invite_cb(GntMenuItem *item, gpointer ggconv) { FinchConv *fc = ggconv; - PurpleConversation *conv = fc->active_conv; - purple_conv_chat_invite_user(PURPLE_CONV_CHAT(conv), NULL, NULL, TRUE); + PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(fc->active_conv); + purple_chat_conversation_invite_user(chat, NULL, NULL, TRUE); } static void @@ -650,7 +633,7 @@ gg_create_menu(FinchConv *ggc) gnt_menu_add_item(GNT_MENU(sub), item); gnt_menuitem_set_callback(item, toggle_timestamps_cb, ggc); - if (purple_conversation_get_type(ggc->active_conv) == PURPLE_CONV_TYPE_IM) { + if (PURPLE_IS_IM_CONVERSATION(ggc->active_conv)) { PurpleAccount *account = purple_conversation_get_account(ggc->active_conv); PurpleConnection *gc = purple_account_get_connection(account); PurplePluginProtocolInfo *pinfo = @@ -675,7 +658,7 @@ gg_create_menu(FinchConv *ggc) } generate_send_to_menu(ggc); - } else if (purple_conversation_get_type(ggc->active_conv) == PURPLE_CONV_TYPE_CHAT) { + } else { item = gnt_menuitem_new(_("Invite...")); gnt_menu_add_item(GNT_MENU(sub), item); gnt_menuitem_set_callback(item, invite_cb, ggc); @@ -722,10 +705,11 @@ create_conv_from_userlist(GntWidget *widget, FinchConv *fc) prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_cb_real_name)) - realname = prpl_info->get_cb_real_name(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(fc->active_conv)), name); + realname = prpl_info->get_cb_real_name(gc, purple_chat_conversation_get_id( + PURPLE_CHAT_CONVERSATION(fc->active_conv)), name); else realname = NULL; - purple_conversation_new(PURPLE_CONV_TYPE_IM, account, realname ? realname : name); + purple_im_conversation_new(account, realname ? realname : name); g_free(realname); } @@ -734,8 +718,8 @@ gained_focus_cb(GntWindow *window, FinchConv *fc) { GList *iter; for (iter = fc->list; iter; iter = iter->next) { - purple_conversation_set_data(iter->data, "unseen-count", 0); - purple_conversation_update(iter->data, PURPLE_CONV_UPDATE_UNSEEN); + g_object_set_data(G_OBJECT(iter->data), "unseen-count", 0); + purple_conversation_update(iter->data, PURPLE_CONVERSATION_UPDATE_UNSEEN); } } @@ -788,7 +772,6 @@ finch_create_conversation(PurpleConversation *conv) { FinchConv *ggc = FINCH_CONV(conv); char *title; - PurpleConversationType type; PurpleConversation *cc; PurpleAccount *account; PurpleBlistNode *convnode = NULL; @@ -799,7 +782,7 @@ finch_create_conversation(PurpleConversation *conv) } account = purple_conversation_get_account(conv); - cc = find_conv_with_contact(account, purple_conversation_get_name(conv)); + cc = PURPLE_CONVERSATION(find_im_with_contact(account, purple_conversation_get_name(conv))); if (cc && FINCH_CONV(cc)) ggc = FINCH_CONV(cc); else @@ -820,7 +803,6 @@ finch_create_conversation(PurpleConversation *conv) return; } - type = purple_conversation_get_type(conv); title = get_conversation_title(conv, account); ggc->window = gnt_vwindow_new(FALSE); @@ -828,30 +810,15 @@ finch_create_conversation(PurpleConversation *conv) gnt_box_set_toplevel(GNT_BOX(ggc->window), TRUE); gnt_box_set_pad(GNT_BOX(ggc->window), 0); - switch (purple_conversation_get_type(conv)) { - case PURPLE_CONV_TYPE_UNKNOWN: - gnt_widget_set_name(ggc->window, "conversation-window-unknown" ); - break; - case PURPLE_CONV_TYPE_IM: - gnt_widget_set_name(ggc->window, "conversation-window-im" ); - break; - case PURPLE_CONV_TYPE_CHAT: - gnt_widget_set_name(ggc->window, "conversation-window-chat" ); - break; - case PURPLE_CONV_TYPE_MISC: - gnt_widget_set_name(ggc->window, "conversation-window-misc" ); - break; - case PURPLE_CONV_TYPE_ANY: - gnt_widget_set_name(ggc->window, "conversation-window-any" ); - break; - } + gnt_widget_set_name(ggc->window, + PURPLE_IS_IM_CONVERSATION(conv) ? "conversation-window-im" : "conversation-window-chat"); ggc->tv = gnt_text_view_new(); gnt_widget_set_name(ggc->tv, "conversation-window-textview"); gnt_widget_set_size(ggc->tv, purple_prefs_get_int(PREF_ROOT "/size/width"), purple_prefs_get_int(PREF_ROOT "/size/height")); - if (type == PURPLE_CONV_TYPE_CHAT) { + if (PURPLE_IS_CHAT_CONVERSATION(conv)) { GntWidget *hbox, *tree; FinchConvChat *fc = ggc->u.chat = g_new0(FinchConvChat, 1); hbox = gnt_hbox_new(FALSE); @@ -896,9 +863,8 @@ finch_create_conversation(PurpleConversation *conv) g_signal_connect(G_OBJECT(ggc->tv), "size_changed", G_CALLBACK(size_changed_cb), NULL); g_signal_connect(G_OBJECT(ggc->window), "position_set", G_CALLBACK(save_position_cb), NULL); - if (type == PURPLE_CONV_TYPE_IM) { + if (PURPLE_IS_IM_CONVERSATION(conv)) g_signal_connect(G_OBJECT(ggc->entry), "text_changed", G_CALLBACK(send_typing_notification), ggc); - } convnode = get_conversation_blist_node(conv); if ((convnode && purple_blist_node_get_bool(convnode, "gnt-mute-sound")) || @@ -1027,8 +993,8 @@ finch_write_common(PurpleConversation *conv, const char *who, const char *messag g_free(newline); g_free(strip); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM && - purple_conv_im_get_typing_state(PURPLE_CONV_IM(conv)) == PURPLE_TYPING) { + if (PURPLE_IS_IM_CONVERSATION(conv) && purple_im_conversation_get_typing_state( + PURPLE_IM_CONVERSATION(conv)) == PURPLE_IM_TYPING) { strip = g_strdup_printf(_("\n%s is typing..."), purple_conversation_get_title(conv)); gnt_text_view_append_text_with_tag(GNT_TEXT_VIEW(ggconv->tv), strip, GNT_TEXT_FLAG_DIM, "typing"); @@ -1041,29 +1007,30 @@ finch_write_common(PurpleConversation *conv, const char *who, const char *messag if (flags & (PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_NICK | PURPLE_MESSAGE_ERROR)) gnt_widget_set_urgent(ggconv->tv); if (flags & PURPLE_MESSAGE_RECV && !gnt_widget_has_focus(ggconv->window)) { - int count = GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count")); - purple_conversation_set_data(conv, "unseen-count", GINT_TO_POINTER(count + 1)); - purple_conversation_update(conv, PURPLE_CONV_UPDATE_UNSEEN); + int count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "unseen-count")); + g_object_set_data(G_OBJECT(conv), "unseen-count", GINT_TO_POINTER(count + 1)); + purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_UNSEEN); } } static void -finch_write_chat(PurpleConversation *conv, const char *who, const char *message, +finch_write_chat(PurpleChatConversation *chat, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime) { - purple_conversation_write(conv, who, message, flags, mtime); + purple_conversation_write(PURPLE_CONVERSATION(chat), who, message, flags, mtime); } static void -finch_write_im(PurpleConversation *conv, const char *who, const char *message, +finch_write_im(PurpleIMConversation *im, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime) { + PurpleConversation *conv = PURPLE_CONVERSATION(im); PurpleAccount *account = purple_conversation_get_account(conv); if (flags & PURPLE_MESSAGE_SEND) { who = purple_connection_get_display_name(purple_account_get_connection(account)); if (!who) - who = purple_account_get_alias(account); + who = purple_account_get_private_alias(account); if (!who) who = purple_account_get_username(account); } @@ -1071,7 +1038,7 @@ finch_write_im(PurpleConversation *conv, const char *who, const char *message, { PurpleBuddy *buddy; who = purple_conversation_get_name(conv); - buddy = purple_find_buddy(account, who); + buddy = purple_blist_find_buddy(account, who); if (buddy) who = purple_buddy_get_contact_alias(buddy); } @@ -1095,22 +1062,23 @@ finch_write_conv(PurpleConversation *conv, const char *who, const char *alias, } static const char * -chat_flag_text(PurpleConvChatBuddyFlags flags) +chat_flag_text(PurpleChatUserFlags flags) { - if (flags & PURPLE_CBFLAGS_FOUNDER) + if (flags & PURPLE_CHAT_USER_FOUNDER) return "~"; - if (flags & PURPLE_CBFLAGS_OP) + if (flags & PURPLE_CHAT_USER_OP) return "@"; - if (flags & PURPLE_CBFLAGS_HALFOP) + if (flags & PURPLE_CHAT_USER_HALFOP) return "%"; - if (flags & PURPLE_CBFLAGS_VOICE) + if (flags & PURPLE_CHAT_USER_VOICE) return "+"; return " "; } static void -finch_chat_add_users(PurpleConversation *conv, GList *users, gboolean new_arrivals) +finch_chat_add_users(PurpleChatConversation *chat, GList *users, gboolean new_arrivals) { + PurpleConversation *conv = PURPLE_CONVERSATION(chat); FinchConv *ggc = FINCH_CONV(conv); GntEntry *entry = GNT_ENTRY(ggc->entry); @@ -1125,11 +1093,11 @@ finch_chat_add_users(PurpleConversation *conv, GList *users, gboolean new_arriva ngettext("List of %d user:\n", "List of %d users:\n", count), count); for (iter = users; iter; iter = iter->next) { - PurpleConvChatBuddy *cbuddy = iter->data; + PurpleChatUser *chatuser = iter->data; const char *str; - if ((str = purple_conv_chat_cb_get_alias(cbuddy)) == NULL) - str = purple_conv_chat_cb_get_name(cbuddy); + if ((str = purple_chat_user_get_alias(chatuser)) == NULL) + str = purple_chat_user_get_name(chatuser); g_string_append_printf(string, "[ %s ]", str); } @@ -1140,23 +1108,23 @@ finch_chat_add_users(PurpleConversation *conv, GList *users, gboolean new_arriva for (; users; users = users->next) { - PurpleConvChatBuddy *cbuddy = users->data; + PurpleChatUser *chatuser = users->data; GntTree *tree = GNT_TREE(ggc->u.chat->userlist); - gnt_entry_add_suggest(entry, purple_conv_chat_cb_get_name(cbuddy)); - gnt_entry_add_suggest(entry, purple_conv_chat_cb_get_alias(cbuddy)); - gnt_tree_add_row_after(tree, g_strdup(purple_conv_chat_cb_get_name(cbuddy)), - gnt_tree_create_row(tree, chat_flag_text(purple_conv_chat_cb_get_flags(cbuddy)), purple_conv_chat_cb_get_alias(cbuddy)), NULL, NULL); + gnt_entry_add_suggest(entry, purple_chat_user_get_name(chatuser)); + gnt_entry_add_suggest(entry, purple_chat_user_get_alias(chatuser)); + gnt_tree_add_row_after(tree, g_strdup(purple_chat_user_get_name(chatuser)), + gnt_tree_create_row(tree, chat_flag_text(purple_chat_user_get_flags(chatuser)), purple_chat_user_get_alias(chatuser)), NULL, NULL); } } static void -finch_chat_rename_user(PurpleConversation *conv, const char *old, const char *new_n, const char *new_a) +finch_chat_rename_user(PurpleChatConversation *chat, const char *old, const char *new_n, const char *new_a) { /* Update the name for string completion */ - FinchConv *ggc = FINCH_CONV(conv); + FinchConv *ggc = FINCH_CONV(PURPLE_CONVERSATION(chat)); GntEntry *entry = GNT_ENTRY(ggc->entry); GntTree *tree = GNT_TREE(ggc->u.chat->userlist); - PurpleConvChatBuddy *cb = purple_conv_chat_cb_find(PURPLE_CONV_CHAT(conv), new_n); + PurpleChatUser *cb = purple_chat_conversation_find_user(chat, new_n); gnt_entry_remove_suggest(entry, old); gnt_tree_remove(tree, (gpointer)old); @@ -1164,14 +1132,14 @@ finch_chat_rename_user(PurpleConversation *conv, const char *old, const char *ne gnt_entry_add_suggest(entry, new_n); gnt_entry_add_suggest(entry, new_a); gnt_tree_add_row_after(tree, g_strdup(new_n), - gnt_tree_create_row(tree, chat_flag_text(purple_conv_chat_cb_get_flags(cb)), new_a), NULL, NULL); + gnt_tree_create_row(tree, chat_flag_text(purple_chat_user_get_flags(cb)), new_a), NULL, NULL); } static void -finch_chat_remove_users(PurpleConversation *conv, GList *list) +finch_chat_remove_users(PurpleChatConversation *chat, GList *list) { /* Remove the name from string completion */ - FinchConv *ggc = FINCH_CONV(conv); + FinchConv *ggc = FINCH_CONV(PURPLE_CONVERSATION(chat)); GntEntry *entry = GNT_ENTRY(ggc->entry); for (; list; list = list->next) { GntTree *tree = GNT_TREE(ggc->u.chat->userlist); @@ -1181,11 +1149,18 @@ finch_chat_remove_users(PurpleConversation *conv, GList *list) } static void -finch_chat_update_user(PurpleConversation *conv, const char *user) +finch_chat_update_user(PurpleChatUser *cb) { - PurpleConvChatBuddy *cb = purple_conv_chat_cb_find(PURPLE_CONV_CHAT(conv), user); - FinchConv *ggc = FINCH_CONV(conv); - gnt_tree_change_text(GNT_TREE(ggc->u.chat->userlist), (gpointer)user, 0, chat_flag_text(purple_conv_chat_cb_get_flags(cb))); + PurpleChatConversation *chat; + FinchConv *ggc; + if (!cb) + return; + + chat = purple_chat_user_get_chat(cb); + ggc = FINCH_CONV(PURPLE_CONVERSATION(chat)); + gnt_tree_change_text(GNT_TREE(ggc->u.chat->userlist), + (gpointer)purple_chat_user_get_name(cb), 0, + chat_flag_text(purple_chat_user_get_flags(cb))); } static void @@ -1238,10 +1213,7 @@ static PurpleCmdRet say_command_cb(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) - purple_conv_im_send(PURPLE_CONV_IM(conv), args[0]); - else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) - purple_conv_chat_send(PURPLE_CONV_CHAT(conv), args[0]); + purple_conversation_send(conv, args[0]); return PURPLE_CMD_RET_OK; } @@ -1254,11 +1226,7 @@ me_command_cb(PurpleConversation *conv, char *tmp; tmp = g_strdup_printf("/me %s", args[0]); - - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) - purple_conv_im_send(PURPLE_CONV_IM(conv), tmp); - else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) - purple_conv_chat_send(PURPLE_CONV_CHAT(conv), tmp); + purple_conversation_send(conv, tmp); g_free(tmp); return PURPLE_CMD_RET_OK; @@ -1299,10 +1267,7 @@ debug_command_cb(PurpleConversation *conv, } markup = g_markup_escape_text(tmp, -1); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) - purple_conv_im_send(PURPLE_CONV_IM(conv), markup); - else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) - purple_conv_chat_send(PURPLE_CONV_CHAT(conv), markup); + purple_conversation_send(conv, markup); g_free(tmp); g_free(markup); diff --git a/finch/gntlog.c b/finch/gntlog.c index c946c285c6..6d5a924299 100644 --- a/finch/gntlog.c +++ b/finch/gntlog.c @@ -407,7 +407,7 @@ void finch_log_show(PurpleLogType type, const char *username, PurpleAccount *acc PurpleBuddy *buddy; if (username) { - buddy = purple_find_buddy(account, username); + buddy = purple_blist_find_buddy(account, username); if (buddy != NULL) name = purple_buddy_get_contact_alias(buddy); title = g_strdup_printf(_("Conversations with %s"), name); @@ -461,7 +461,7 @@ void finch_log_show_contact(PurpleContact *contact) child = purple_blist_node_get_sibling_next(child)) { const char *name; PurpleAccount *account; - if (!PURPLE_BLIST_NODE_IS_BUDDY(child)) + if (!PURPLE_IS_BUDDY(child)) continue; name = purple_buddy_get_name((PurpleBuddy *)child); @@ -481,7 +481,7 @@ void finch_log_show_contact(PurpleContact *contact) * There is probably a better way to deal with this. */ if (name == NULL) { child = purple_blist_node_get_first_child((PurpleBlistNode*)contact); - if (child != NULL && PURPLE_BLIST_NODE_IS_BUDDY(child)) + if (child != NULL && PURPLE_IS_BUDDY(child)) name = purple_buddy_get_contact_alias((PurpleBuddy *)child); if (name == NULL) name = ""; @@ -533,11 +533,9 @@ void finch_log_init(void) purple_signal_register(handle, "log-displaying", purple_marshal_VOID__POINTER_POINTER, - NULL, 2, - purple_value_new(PURPLE_TYPE_BOXED, - "FinchLogViewer *"), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_LOG)); + G_TYPE_NONE, 2, + G_TYPE_POINTER, /* (FinchLogViewer *) */ + PURPLE_TYPE_LOG); } void diff --git a/finch/gntmedia.c b/finch/gntmedia.c index 9c524d7eff..b88169fec2 100644 --- a/finch/gntmedia.c +++ b/finch/gntmedia.c @@ -262,7 +262,7 @@ finch_media_state_changed_cb(PurpleMedia *media, PurpleMediaState state, gchar *message = NULL; account = purple_media_get_account(gntmedia->priv->media); - buddy = purple_find_buddy(account, name); + buddy = purple_blist_find_buddy(account, name); alias = buddy ? purple_buddy_get_contact_alias(buddy) : name; if (type & PURPLE_MEDIA_AUDIO) { @@ -378,8 +378,8 @@ finch_media_new(PurpleMedia *media) static void gntmedia_message_cb(FinchMedia *gntmedia, const char *msg, PurpleConversation *conv) { - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - purple_conv_im_write(PURPLE_CONV_IM(conv), NULL, msg, PURPLE_MESSAGE_SYSTEM, time(NULL)); + if (PURPLE_IS_IM_CONVERSATION(conv)) { + purple_conversation_write_message(conv, NULL, msg, PURPLE_MESSAGE_SYSTEM, time(NULL)); } } @@ -390,7 +390,7 @@ finch_new_media(PurpleMediaManager *manager, PurpleMedia *media, GntWidget *gntmedia; PurpleConversation *conv; - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name); + conv = PURPLE_CONVERSATION(purple_im_conversation_new(account, name)); gntmedia = finch_media_new(media); g_signal_connect(G_OBJECT(gntmedia), "message", G_CALLBACK(gntmedia_message_cb), conv); diff --git a/finch/gntpounce.c b/finch/gntpounce.c index c5fc691a54..66c5adb6ef 100644 --- a/finch/gntpounce.c +++ b/finch/gntpounce.c @@ -173,7 +173,7 @@ setup_buddy_list_suggestion(GntEntry *entry, gboolean offline) { PurpleBlistNode *node = purple_blist_get_root(); for (; node; node = purple_blist_node_next(node, offline)) { - if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (!PURPLE_IS_BUDDY(node)) continue; gnt_entry_add_suggest(entry, purple_buddy_get_name((PurpleBuddy*)node)); } @@ -558,7 +558,7 @@ finch_pounce_editor_show(PurpleAccount *account, const char *name, PurpleBuddy *buddy = NULL; if (name != NULL) - buddy = purple_find_buddy(account, name); + buddy = purple_blist_find_buddy(account, name); /* Set some defaults */ if (buddy == NULL) { @@ -780,7 +780,7 @@ finch_pounces_manager_hide(void) static void pounce_cb(PurplePounce *pounce, PurplePounceEvent events, void *data) { - PurpleConversation *conv; + PurpleIMConversation *im; PurpleAccount *account; PurpleBuddy *buddy; const char *pouncee; @@ -789,7 +789,7 @@ pounce_cb(PurplePounce *pounce, PurplePounceEvent events, void *data) pouncee = purple_pounce_get_pouncee(pounce); account = purple_pounce_get_pouncer(pounce); - buddy = purple_find_buddy(account, pouncee); + buddy = purple_blist_find_buddy(account, pouncee); if (buddy != NULL) { alias = purple_buddy_get_alias(buddy); @@ -801,8 +801,8 @@ pounce_cb(PurplePounce *pounce, PurplePounceEvent events, void *data) if (purple_pounce_action_is_enabled(pounce, "open-window")) { - if (!purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, pouncee, account)) - purple_conversation_new(PURPLE_CONV_TYPE_IM, account, pouncee); + if (!purple_conversations_find_im_with_account(pouncee, account)) + purple_im_conversation_new(account, pouncee); } if (purple_pounce_action_is_enabled(pounce, "popup-notify")) @@ -849,7 +849,7 @@ pounce_cb(PurplePounce *pounce, PurplePounceEvent events, void *data) * NULL to the account alias if we have it or the account * name if that's all we have */ - if ((name_shown = purple_account_get_alias(account)) == NULL) + if ((name_shown = purple_account_get_private_alias(account)) == NULL) name_shown = purple_account_get_username(account); if (reason == NULL) @@ -874,12 +874,12 @@ pounce_cb(PurplePounce *pounce, PurplePounceEvent events, void *data) if (message != NULL) { - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, pouncee, account); + im = purple_conversations_find_im_with_account(pouncee, account); - if (conv == NULL) - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, pouncee); + if (im == NULL) + im = purple_im_conversation_new(account, pouncee); - purple_conversation_write(conv, NULL, message, + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, message, PURPLE_MESSAGE_SEND, time(NULL)); serv_send_im(purple_account_get_connection(account), (char *)pouncee, (char *)message, 0); diff --git a/finch/gntrequest.c b/finch/gntrequest.c index 3f4413504e..838c339b3e 100644 --- a/finch/gntrequest.c +++ b/finch/gntrequest.c @@ -412,7 +412,7 @@ update_selected_account(GntEntry *username, const char *start, const char *end, GList *accounts = gnt_tree_get_rows(GNT_TREE(accountlist->dropdown)); const char *name = gnt_entry_get_text(username); while (accounts) { - if (purple_find_buddy(accounts->data, name)) { + if (purple_blist_find_buddy(accounts->data, name)) { gnt_combo_box_set_selected(accountlist, accounts->data); gnt_widget_draw(GNT_WIDGET(accountlist)); break; @@ -443,7 +443,7 @@ create_string_field(PurpleRequestField *field, GntWidget **username) PurpleBlistNode *node = purple_blist_get_root(); gboolean offline = purple_str_has_suffix(hint, "all"); for (; node; node = purple_blist_node_next(node, offline)) { - if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (!PURPLE_IS_BUDDY(node)) continue; gnt_entry_add_suggest(GNT_ENTRY(entry), purple_buddy_get_name((PurpleBuddy*)node)); } @@ -454,7 +454,7 @@ create_string_field(PurpleRequestField *field, GntWidget **username) PurpleBlistNode *node; for (node = purple_blist_get_root(); node; node = purple_blist_node_get_sibling_next(node)) { - if (PURPLE_BLIST_NODE_IS_GROUP(node)) + if (PURPLE_IS_GROUP(node)) gnt_entry_add_suggest(GNT_ENTRY(entry), purple_group_get_name((PurpleGroup *)node)); } } diff --git a/finch/gntsound.c b/finch/gntsound.c index fee724b0e7..4eace710d5 100644 --- a/finch/gntsound.c +++ b/finch/gntsound.c @@ -137,20 +137,18 @@ unmute_login_sounds_cb(gpointer data) } static gboolean -chat_nick_matches_name(PurpleConversation *conv, const char *aname) +chat_nick_matches_name(PurpleChatConversation *chat, const char *aname) { - PurpleConvChat *chat = NULL; char *nick = NULL; char *name = NULL; gboolean ret = FALSE; PurpleAccount *account; - chat = purple_conversation_get_chat_data(conv); if (chat == NULL) return ret; - account = purple_conversation_get_account(conv); - nick = g_strdup(purple_normalize(account, purple_conv_chat_get_nick(chat))); + account = purple_conversation_get_account(PURPLE_CONVERSATION(chat)); + nick = g_strdup(purple_normalize(account, purple_chat_conversation_get_nick(chat))); name = g_strdup(purple_normalize(account, aname)); if (g_utf8_collate(nick, name) == 0) @@ -214,26 +212,26 @@ static void im_msg_sent_cb(PurpleAccount *account, const char *receiver, const char *message, PurpleSoundEventID event) { - PurpleConversation *conv = purple_find_conversation_with_account( - PURPLE_CONV_TYPE_IM, receiver, account); - play_conv_event(conv, event); + PurpleIMConversation *im = purple_conversations_find_im_with_account( + receiver, account); + play_conv_event(PURPLE_CONVERSATION(im), event); } static void -chat_buddy_join_cb(PurpleConversation *conv, const char *name, - PurpleConvChatBuddyFlags flags, gboolean new_arrival, +chat_user_join_cb(PurpleChatConversation *chat, const char *name, + PurpleChatUserFlags flags, gboolean new_arrival, PurpleSoundEventID event) { - if (new_arrival && !chat_nick_matches_name(conv, name)) - play_conv_event(conv, event); + if (new_arrival && !chat_nick_matches_name(chat, name)) + play_conv_event(PURPLE_CONVERSATION(chat), event); } static void -chat_buddy_left_cb(PurpleConversation *conv, const char *name, +chat_user_left_cb(PurpleChatConversation *chat, const char *name, const char *reason, PurpleSoundEventID event) { - if (!chat_nick_matches_name(conv, name)) - play_conv_event(conv, event); + if (!chat_nick_matches_name(chat, name)) + play_conv_event(PURPLE_CONVERSATION(chat), event); } static void @@ -241,37 +239,34 @@ chat_msg_sent_cb(PurpleAccount *account, const char *message, int id, PurpleSoundEventID event) { PurpleConnection *conn = purple_account_get_connection(account); - PurpleConversation *conv = NULL; + PurpleChatConversation *chat = NULL; if (conn!=NULL) - conv = purple_find_chat(conn, id); + chat = purple_conversations_find_chat(conn, id); - play_conv_event(conv, event); + play_conv_event(PURPLE_CONVERSATION(chat), event); } static void chat_msg_received_cb(PurpleAccount *account, char *sender, - char *message, PurpleConversation *conv, + char *message, PurpleChatConversation *chat, PurpleMessageFlags flags, PurpleSoundEventID event) { - PurpleConvChat *chat; - if (flags & PURPLE_MESSAGE_DELAYED) return; - chat = purple_conversation_get_chat_data(conv); g_return_if_fail(chat != NULL); - if (purple_conv_chat_is_user_ignored(chat, sender)) + if (purple_chat_conversation_is_ignored_user(chat, sender)) return; - if (chat_nick_matches_name(conv, sender)) + if (chat_nick_matches_name(chat, sender)) return; - if (flags & PURPLE_MESSAGE_NICK || purple_utf8_has_word(message, purple_conv_chat_get_nick(chat))) - play_conv_event(conv, PURPLE_SOUND_CHAT_NICK); + if (flags & PURPLE_MESSAGE_NICK || purple_utf8_has_word(message, purple_chat_conversation_get_nick(chat))) + play_conv_event(PURPLE_CONVERSATION(chat), PURPLE_SOUND_CHAT_NICK); else - play_conv_event(conv, event); + play_conv_event(PURPLE_CONVERSATION(chat), event); } static void @@ -403,11 +398,11 @@ finch_sound_init(void) purple_signal_connect(conv_handle, "sent-im-msg", gnt_sound_handle, PURPLE_CALLBACK(im_msg_sent_cb), GINT_TO_POINTER(PURPLE_SOUND_SEND)); - purple_signal_connect(conv_handle, "chat-buddy-joined", - gnt_sound_handle, PURPLE_CALLBACK(chat_buddy_join_cb), + purple_signal_connect(conv_handle, "chat-user-joined", + gnt_sound_handle, PURPLE_CALLBACK(chat_user_join_cb), GINT_TO_POINTER(PURPLE_SOUND_CHAT_JOIN)); - purple_signal_connect(conv_handle, "chat-buddy-left", - gnt_sound_handle, PURPLE_CALLBACK(chat_buddy_left_cb), + purple_signal_connect(conv_handle, "chat-user-left", + gnt_sound_handle, PURPLE_CALLBACK(chat_user_left_cb), GINT_TO_POINTER(PURPLE_SOUND_CHAT_LEAVE)); purple_signal_connect(conv_handle, "sent-chat-msg", gnt_sound_handle, PURPLE_CALLBACK(chat_msg_sent_cb), diff --git a/finch/libgnt/wms/s.c b/finch/libgnt/wms/s.c index a326815bab..e7d5343788 100644 --- a/finch/libgnt/wms/s.c +++ b/finch/libgnt/wms/s.c @@ -11,7 +11,7 @@ #include "gntwindow.h" #include "gntlabel.h" -#include "blist.h" +#include "buddylist.h" #define TYPE_S (s_get_gtype()) diff --git a/finch/plugins/gntgf.c b/finch/plugins/gntgf.c index 925c24834d..cfb47884ca 100644 --- a/finch/plugins/gntgf.c +++ b/finch/plugins/gntgf.c @@ -44,7 +44,7 @@ #include <plugin.h> #include <version.h> -#include <blist.h> +#include <buddylist.h> #include <conversation.h> #include <debug.h> #include <eventloop.h> @@ -241,22 +241,23 @@ buddy_signed_off(PurpleBuddy *buddy, gpointer null) static void received_im_msg(PurpleAccount *account, const char *sender, const char *msg, - PurpleConversation *conv, PurpleMessageFlags flags, gpointer null) + PurpleIMConversation *im, PurpleMessageFlags flags, gpointer null) { if (purple_prefs_get_bool(PREFS_EVENT_IM_MSG)) - notify(conv, _("%s sent you a message"), sender); + notify(PURPLE_CONVERSATION(im), _("%s sent you a message"), sender); } static void received_chat_msg(PurpleAccount *account, const char *sender, const char *msg, - PurpleConversation *conv, PurpleMessageFlags flags, gpointer null) + PurpleChatConversation *chat, PurpleMessageFlags flags, gpointer null) { const char *nick; + PurpleConversation *conv = PURPLE_CONVERSATION(chat); if (flags & PURPLE_MESSAGE_WHISPER) return; - nick = purple_conv_chat_get_nick(PURPLE_CONV_CHAT(conv)); + nick = purple_chat_conversation_get_nick(chat); if (g_utf8_collate(sender, nick) == 0) return; diff --git a/finch/plugins/gnthistory.c b/finch/plugins/gnthistory.c index b5514f0b26..9706bd7197 100644 --- a/finch/plugins/gnthistory.c +++ b/finch/plugins/gnthistory.c @@ -43,7 +43,6 @@ static void historize(PurpleConversation *c) { PurpleAccount *account = purple_conversation_get_account(c); const char *name = purple_conversation_get_name(c); - PurpleConversationType convtype; GList *logs = NULL; const char *alias = name; PurpleLogReadFlags flags; @@ -51,8 +50,7 @@ static void historize(PurpleConversation *c) char *header; PurpleMessageFlags mflag; - convtype = purple_conversation_get_type(c); - if (convtype == PURPLE_CONV_TYPE_IM) { + if (PURPLE_IS_IM_CONVERSATION(c)) { GSList *buddies; GSList *cur; FinchConv *fc = FINCH_CONV(c); @@ -65,11 +63,11 @@ static void historize(PurpleConversation *c) return; /* Find buddies for this conversation. */ - buddies = purple_find_buddies(account, name); + buddies = purple_blist_find_buddies(account, name); /* If we found at least one buddy, save the first buddy's alias. */ if (buddies != NULL) - alias = purple_buddy_get_contact_alias((PurpleBuddy *)buddies->data); + alias = purple_buddy_get_contact_alias(PURPLE_BUDDY(buddies->data)); for (cur = buddies; cur != NULL; cur = cur->next) { PurpleBlistNode *node = cur->data; @@ -78,7 +76,7 @@ static void historize(PurpleConversation *c) (purple_blist_node_get_sibling_next(node) != NULL))) { PurpleBlistNode *node2; - alias = purple_buddy_get_contact_alias((PurpleBuddy *)node); + alias = purple_buddy_get_contact_alias(PURPLE_BUDDY(node)); /* We've found a buddy that matches this conversation. It's part of a * PurpleContact with more than one PurpleBuddy. Loop through the PurpleBuddies @@ -87,8 +85,8 @@ static void historize(PurpleConversation *c) node2 != NULL ; node2 = purple_blist_node_get_sibling_next(node2)) { logs = g_list_concat( purple_log_get_logs(PURPLE_LOG_IM, - purple_buddy_get_name((PurpleBuddy *)node2), - purple_buddy_get_account((PurpleBuddy *)node2)), + purple_buddy_get_name(PURPLE_BUDDY(node2)), + purple_buddy_get_account(PURPLE_BUDDY(node2))), logs); } break; @@ -100,7 +98,7 @@ static void historize(PurpleConversation *c) logs = purple_log_get_logs(PURPLE_LOG_IM, name, account); else logs = g_list_sort(logs, purple_log_compare); - } else if (convtype == PURPLE_CONV_TYPE_CHAT) { + } else if (PURPLE_IS_CHAT_CONVERSATION(c)) { /* If we're not logging, don't show anything. * Otherwise, we might show a very old log. */ if (!purple_prefs_get_bool("/purple/logging/log_chats")) diff --git a/finch/plugins/gnttinyurl.c b/finch/plugins/gnttinyurl.c index 6428279337..2c817bf71a 100644 --- a/finch/plugins/gnttinyurl.c +++ b/finch/plugins/gnttinyurl.c @@ -210,7 +210,7 @@ static void url_fetched(PurpleHttpConnection *http_conn, { CbInfo *data = (CbInfo *)_data; PurpleConversation *conv = data->conv; - GList *convs = purple_get_conversations(); + GList *convs = purple_conversations_get_all(); const gchar *url; if (purple_http_response_is_successful(response)) @@ -251,7 +251,7 @@ static gboolean writing_msg(PurpleAccount *account, char *sender, char **message if ((flags & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_INVISIBLE))) return FALSE; - urls = purple_conversation_get_data(conv, "TinyURLs"); + urls = g_object_get_data(G_OBJECT(conv), "TinyURLs"); if (urls != NULL) /* message was cancelled somewhere? Reset. */ g_list_foreach(urls, free_urls, NULL); g_list_free(urls); @@ -287,8 +287,8 @@ static gboolean writing_msg(PurpleAccount *account, char *sender, char **message *message = t->str; g_string_free(t, FALSE); if (conv == NULL) - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender); - purple_conversation_set_data(conv, "TinyURLs", urls); + conv = PURPLE_CONVERSATION(purple_im_conversation_new(account, sender)); + g_object_set_data(G_OBJECT(conv), "TinyURLs", urls); return FALSE; } @@ -297,12 +297,12 @@ static void wrote_msg(PurpleAccount *account, char *sender, char *message, { GList *urls; - urls = purple_conversation_get_data(conv, "TinyURLs"); + urls = g_object_get_data(G_OBJECT(conv), "TinyURLs"); if ((flags & PURPLE_MESSAGE_SEND) || urls == NULL) return; process_urls(conv, urls); - purple_conversation_set_data(conv, "TinyURLs", NULL); + g_object_set_data(G_OBJECT(conv), "TinyURLs", NULL); } /* Frees 'urls' */ @@ -345,7 +345,7 @@ process_urls(PurpleConversation *conv, GList *urls) static void free_conv_urls(PurpleConversation *conv) { - GList *urls = purple_conversation_get_data(conv, "TinyURLs"); + GList *urls = g_object_get_data(G_OBJECT(conv), "TinyURLs"); if (urls) g_list_foreach(urls, free_urls, NULL); g_list_free(urls); diff --git a/finch/plugins/grouping.c b/finch/plugins/grouping.c index 18ebd4cbe0..b54584eea4 100644 --- a/finch/plugins/grouping.c +++ b/finch/plugins/grouping.c @@ -28,78 +28,104 @@ #include "gnttree.h" +#define FINCH_TYPE_GROUPING_NODE (finch_grouping_node_get_type()) +#define FINCH_GROUPING_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), FINCH_TYPE_GROUPING_NODE, FinchGroupingNode)) +#define FINCH_IS_GROUPING_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), FINCH_TYPE_GROUPING_NODE)) + +typedef struct { + PurpleBlistNode node; +} FinchGroupingNode; + +typedef struct { + PurpleBlistNodeClass node_class; +} FinchGroupingNodeClass; + static FinchBlistManager *default_manager; /** + * GObject code + */ +static GType +finch_grouping_node_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(FinchGroupingNodeClass), + NULL, + NULL, + NULL, + NULL, + NULL, + sizeof(FinchGroupingNode), + 0, + NULL, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_BLIST_NODE, + "FinchGroupingNode", + &info, 0); + } + + return type; +} + +/** * Online/Offline */ -static PurpleBlistNode online = {.type = PURPLE_BLIST_OTHER_NODE}, - offline = {.type = PURPLE_BLIST_OTHER_NODE}; +static FinchGroupingNode *online, *offline; static gboolean on_offline_init() { GntTree *tree = finch_blist_get_tree(); - gnt_tree_add_row_after(tree, &online, + gnt_tree_add_row_after(tree, online, gnt_tree_create_row(tree, _("Online")), NULL, NULL); - gnt_tree_add_row_after(tree, &offline, - gnt_tree_create_row(tree, _("Offline")), NULL, &online); + gnt_tree_add_row_after(tree, offline, + gnt_tree_create_row(tree, _("Offline")), NULL, online); return TRUE; } static gboolean on_offline_can_add_node(PurpleBlistNode *node) { - switch (purple_blist_node_get_type(node)) { - case PURPLE_BLIST_CONTACT_NODE: - { - PurpleContact *contact = (PurpleContact*)node; - if (purple_contact_get_contact_size(contact, FALSE) > 0) - return TRUE; - return FALSE; - } - break; - case PURPLE_BLIST_BUDDY_NODE: - { - PurpleBuddy *buddy = (PurpleBuddy*)node; - if (PURPLE_BUDDY_IS_ONLINE(buddy)) - return TRUE; - if (purple_prefs_get_bool("/finch/blist/showoffline") && - purple_account_is_connected(purple_buddy_get_account(buddy))) - return TRUE; - return FALSE; - } - break; - case PURPLE_BLIST_CHAT_NODE: - { - PurpleChat *chat = (PurpleChat*)node; - return purple_account_is_connected(purple_chat_get_account(chat)); - } - break; - default: - return FALSE; + if (PURPLE_IS_CONTACT(node)) { + PurpleContact *contact = PURPLE_CONTACT(node); + if (purple_counting_node_get_current_size(PURPLE_COUNTING_NODE(contact)) > 0) + return TRUE; + return FALSE; + } else if (PURPLE_IS_BUDDY(node)) { + PurpleBuddy *buddy = PURPLE_BUDDY(node); + if (PURPLE_BUDDY_IS_ONLINE(buddy)) + return TRUE; + if (purple_prefs_get_bool("/finch/blist/showoffline") && + purple_account_is_connected(purple_buddy_get_account(buddy))) + return TRUE; + return FALSE; + } else if (PURPLE_IS_CHAT(node)) { + PurpleChat *chat = PURPLE_CHAT(node); + return purple_account_is_connected(purple_chat_get_account(chat)); } + + return FALSE; } static gpointer on_offline_find_parent(PurpleBlistNode *node) { gpointer ret = NULL; - switch (purple_blist_node_get_type(node)) { - case PURPLE_BLIST_CONTACT_NODE: - node = PURPLE_BLIST_NODE(purple_contact_get_priority_buddy(PURPLE_CONTACT(node))); - ret = PURPLE_BUDDY_IS_ONLINE((PurpleBuddy*)node) ? &online : &offline; - break; - case PURPLE_BLIST_BUDDY_NODE: - ret = purple_blist_node_get_parent(node); - finch_blist_manager_add_node(ret); - break; - case PURPLE_BLIST_CHAT_NODE: - ret = &online; - break; - default: - break; + if (PURPLE_IS_CONTACT(node)) { + node = PURPLE_BLIST_NODE(purple_contact_get_priority_buddy(PURPLE_CONTACT(node))); + ret = PURPLE_BUDDY_IS_ONLINE(PURPLE_BUDDY(node)) ? online : offline; + } else if (PURPLE_IS_BUDDY(node)) { + ret = purple_blist_node_get_parent(node); + finch_blist_manager_add_node(ret); + } else if (PURPLE_IS_CHAT(node)) { + ret = online; } + return ret; } @@ -107,12 +133,13 @@ static gboolean on_offline_create_tooltip(gpointer selected_row, GString **body, { PurpleBlistNode *node = selected_row; - if (purple_blist_node_get_type(node) == PURPLE_BLIST_OTHER_NODE) { + if (FINCH_IS_GROUPING_NODE(node)) { /* There should be some easy way of getting the total online count, * or total number of chats. Doing a loop here will probably be pretty * expensive. */ if (body) - *body = g_string_new(node == &online ? _("Online Buddies") : _("Offline Buddies")); + *body = g_string_new(FINCH_GROUPING_NODE(node) == online ? + _("Online Buddies") : _("Offline Buddies")); return TRUE; } else { return default_manager ? default_manager->create_tooltip(selected_row, body, tool_title) : FALSE; @@ -134,7 +161,7 @@ static FinchBlistManager on_offline = /** * Meebo-like Grouping. */ -static PurpleBlistNode meebo = {.type = PURPLE_BLIST_OTHER_NODE}; +static FinchGroupingNode meebo; static gboolean meebo_init() { GntTree *tree = finch_blist_get_tree(); @@ -147,8 +174,8 @@ static gboolean meebo_init() static gpointer meebo_find_parent(PurpleBlistNode *node) { - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { - PurpleBuddy *buddy = purple_contact_get_priority_buddy((PurpleContact*)node); + if (PURPLE_IS_CONTACT(node)) { + PurpleBuddy *buddy = purple_contact_get_priority_buddy(PURPLE_CONTACT(node)); if (buddy && !PURPLE_BUDDY_IS_ONLINE(buddy)) { return &meebo; } @@ -194,14 +221,11 @@ static gpointer no_group_find_parent(PurpleBlistNode *node) { gpointer ret = NULL; - switch (purple_blist_node_get_type(node)) { - case PURPLE_BLIST_BUDDY_NODE: - ret = purple_blist_node_get_parent(node); - finch_blist_manager_add_node(ret); - break; - default: - break; + if (PURPLE_IS_BUDDY(node)) { + ret = purple_blist_node_get_parent(node); + finch_blist_manager_add_node(ret); } + return ret; } @@ -247,10 +271,10 @@ nested_group_find_parent(PurpleBlistNode *node) PurpleBlistNode *ret, *parent; GntTree *tree; - if (!PURPLE_BLIST_NODE_IS_GROUP(node)) + if (!PURPLE_IS_GROUP(node)) return default_manager->find_parent(node); - group = (PurpleGroup *)node; + group = PURPLE_GROUP(node); name = g_strdup(purple_group_get_name(group)); if (!(sep = strchr(name, '/'))) { g_free(name); @@ -262,13 +286,12 @@ nested_group_find_parent(PurpleBlistNode *node) while (sep) { *sep = 0; - if (*(sep + 1) && (ret = (PurpleBlistNode *)purple_find_group(name))) { + if (*(sep + 1) && (ret = PURPLE_BLIST_NODE(purple_blist_find_group(name)))) { finch_blist_manager_add_node(ret); parent = ret; } else if (!(ret = g_hash_table_lookup(groups, name))) { - ret = g_new0(PurpleBlistNode, 1); + ret = g_object_new(FINCH_TYPE_GROUPING_NODE, NULL); g_hash_table_insert(groups, g_strdup(name), ret); - ret->type = PURPLE_BLIST_OTHER_NODE; gnt_tree_add_row_last(tree, ret, gnt_tree_create_row(tree, name), parent); parent = ret; @@ -285,8 +308,7 @@ static gboolean nested_group_create_tooltip(gpointer selected_row, GString **body, char **title) { PurpleBlistNode *node = selected_row; - if (!node || - purple_blist_node_get_type(node) != PURPLE_BLIST_OTHER_NODE) + if (!node || !FINCH_IS_GROUPING_NODE(node)) return default_manager->create_tooltip(selected_row, body, title); if (body) *body = g_string_new(_("Nested Subgroup")); /* Perhaps list the child groups/subgroups? */ @@ -299,19 +321,19 @@ nested_group_can_add_node(PurpleBlistNode *node) PurpleBlistNode *group; int len; - if (!PURPLE_BLIST_NODE_IS_GROUP(node)) + if (!PURPLE_IS_GROUP(node)) return default_manager->can_add_node(node); if (default_manager->can_add_node(node)) return TRUE; - len = strlen(purple_group_get_name((PurpleGroup*)node)); + len = strlen(purple_group_get_name(PURPLE_GROUP(node))); group = purple_blist_get_root(); for (; group; group = purple_blist_node_get_sibling_next(group)) { if (group == node) continue; - if (strncmp(purple_group_get_name((PurpleGroup *)node), - purple_group_get_name((PurpleGroup *)group), len) == 0 && + if (strncmp(purple_group_get_name(PURPLE_GROUP(node)), + purple_group_get_name(PURPLE_GROUP(group)), len) == 0 && default_manager->can_add_node(group)) return TRUE; } @@ -381,6 +403,8 @@ static PurplePluginInfo info = static void init_plugin(PurplePlugin *plugin) { + online = g_object_new(FINCH_TYPE_GROUPING_NODE, NULL); + offline = g_object_new(FINCH_TYPE_GROUPING_NODE, NULL); } PURPLE_INIT_PLUGIN(grouping, init_plugin, info) diff --git a/libpurple/Makefile.am b/libpurple/Makefile.am index 433aa088cd..37842f6ec5 100644 --- a/libpurple/Makefile.am +++ b/libpurple/Makefile.am @@ -38,20 +38,26 @@ SUBDIRS = $(GCONF_DIR) plugins protocols ciphers . tests example purple_coresources = \ account.c \ + accounts.c \ accountopt.c \ - blist.c \ + blistnode.c \ + blistnodetypes.c \ + buddylist.c \ buddyicon.c \ certificate.c \ cipher.c \ - circbuffer.c \ + circularbuffer.c \ cmds.c \ connection.c \ conversation.c \ + conversationtypes.c \ + conversations.c \ core.c \ debug.c \ desktopitem.c \ eventloop.c \ ft.c \ + hash.c \ http.c \ idle.c \ imgstore.c \ @@ -73,7 +79,7 @@ purple_coresources = \ pluginpref.c \ pounce.c \ prefs.c \ - privacy.c \ + presence.c \ proxy.c \ prpl.c \ request.c \ @@ -96,31 +102,37 @@ purple_coresources = \ theme-manager.c \ upnp.c \ util.c \ - value.c \ version.c \ xmlnode.c \ whiteboard.c purple_builtsources = \ + enums.c \ marshallers.c purple_coreheaders = \ account.h \ + accounts.h \ accountopt.h \ - blist.h \ + blistnode.h \ + blistnodetypes.h \ + buddylist.h \ buddyicon.h \ certificate.h \ cipher.h \ - circbuffer.h \ + circularbuffer.h \ cmds.h \ connection.h \ conversation.h \ + conversationtypes.h \ + conversations.h \ core.h \ dbus-maybe.h \ debug.h \ desktopitem.h \ eventloop.h \ ft.h \ + hash.h \ http.h \ idle.h \ imgstore.h \ @@ -138,7 +150,7 @@ purple_coreheaders = \ pluginpref.h \ pounce.h \ prefs.h \ - privacy.h \ + presence.h \ proxy.h \ prpl.h \ request.h \ @@ -161,7 +173,6 @@ purple_coreheaders = \ theme-manager.h \ upnp.h \ util.h \ - value.h \ xmlnode.h \ whiteboard.h @@ -171,7 +182,15 @@ purple_mediaheaders = \ codec.h \ enum-types.h -purple_builtheaders = purple.h version.h marshallers.h +purple_builtheaders = purple.h version.h enums.h marshallers.h + +purple_enumheaders = \ + account.h \ + cipher.h \ + connection.h \ + conversation.h \ + conversationtypes.h \ + status.h marshallers.h: marshallers.list $(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=purple_smarshal $(srcdir)/marshallers.list --header > marshallers.h @@ -180,6 +199,12 @@ marshallers.c: marshallers.list marshallers.h $(AM_V_GEN)echo "#include \"marshallers.h\"" > marshallers.c $(AM_V_at)$(GLIB_GENMARSHAL) --prefix=purple_smarshal $(srcdir)/marshallers.list --body >> marshallers.c +enums.h: enums.h.template $(purple_enumheaders) + $(AM_V_GEN)$(GLIB_MKENUMS) --template enums.h.template $(purple_enumheaders) > $@ + +enums.c: enums.c.template $(purple_enumheaders) + $(AM_V_GEN)$(GLIB_MKENUMS) --template enums.c.template $(purple_enumheaders) > $@ + if ENABLE_DBUS CLEANFILES = \ @@ -189,6 +214,8 @@ CLEANFILES = \ dbus-signals.c \ dbus-types.c \ dbus-types.h \ + enums.c \ + enums.h \ marshallers.c \ marshallers.h \ purple-client-bindings.c \ @@ -200,9 +227,11 @@ CLEANFILES = \ dbus_sources = dbus-server.c dbus-useful.c dbus_headers = dbus-bindings.h dbus-purple.h dbus-server.h dbus-useful.h dbus-define-api.h dbus-types.h -dbus_exported = dbus-useful.h dbus-define-api.h account.h blist.h buddyicon.h \ - connection.h conversation.h core.h ft.h log.h notify.h prefs.h roomlist.h \ - savedstatuses.h smiley.h status.h server.h util.h xmlnode.h prpl.h +dbus_exported = dbus-useful.h dbus-define-api.h account.h accounts.h blistnode.h \ + blistnodetypes.h buddylist.h buddyicon.h connection.h conversation.h \ + conversationtypes.h conversations.h core.h ft.h log.h notify.h \ + prefs.h presence.h roomlist.h savedstatuses.h smiley.h status.h \ + server.h util.h xmlnode.h prpl.h purple_build_coreheaders = $(addprefix $(srcdir)/, $(purple_coreheaders)) \ $(addprefix $(srcdir)/media/, $(purple_mediaheaders)) \ @@ -302,7 +331,10 @@ mediaincludedir=$(includedir)/libpurple/media mediainclude_HEADERS = \ $(addprefix $(srcdir)/media/, $(purple_mediaheaders)) -libpurple_la_DEPENDENCIES = $(STATIC_LINK_LIBS) +libpurple_la_DEPENDENCIES = \ + $(STATIC_LINK_LIBS) \ + ciphers/libpurple-ciphers.la + libpurple_la_LDFLAGS = -export-dynamic -version-info $(PURPLE_LT_VERSION_INFO) -no-undefined libpurple_la_LIBADD = \ $(STATIC_LINK_LIBS) \ diff --git a/libpurple/Makefile.mingw b/libpurple/Makefile.mingw index 88164b8f31..d1eb3bbfc6 100644 --- a/libpurple/Makefile.mingw +++ b/libpurple/Makefile.mingw @@ -61,22 +61,27 @@ endif C_SRC = \ account.c \ + accounts.c \ accountopt.c \ blist.c \ buddyicon.c \ certificate.c \ cipher.c \ - ciphers/aes.c \ - ciphers/des.c \ - ciphers/gchecksum.c \ - ciphers/hmac.c \ - ciphers/md4.c \ - ciphers/pbkdf2.c \ - ciphers/rc4.c \ - circbuffer.c \ + ciphers/aescipher.c \ + ciphers/des3cipher.c \ + ciphers/descipher.c \ + ciphers/hmaccipher.c \ + ciphers/md4hash.c \ + ciphers/md5hash.c \ + ciphers/pbkdf2cipher.c \ + ciphers/rc4cipher.c \ + ciphers/sha1hash.c \ + ciphers/sha256hash.c \ + circularbuffer.c \ cmds.c \ connection.c \ conversation.c \ + conversations.c \ core.c \ debug.c \ dnsquery.c \ @@ -122,7 +127,6 @@ C_SRC = \ theme.c \ upnp.c \ util.c \ - value.c \ version.c \ whiteboard.c \ xmlnode.c \ diff --git a/libpurple/account.c b/libpurple/account.c index 526cd7bb34..2e2d537c20 100644 --- a/libpurple/account.c +++ b/libpurple/account.c @@ -24,38 +24,77 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ #include "internal.h" -#include "account.h" +#include "accounts.h" #include "core.h" #include "dbus-maybe.h" #include "debug.h" -#include "keyring.h" #include "network.h" #include "notify.h" #include "pounce.h" #include "prefs.h" -#include "privacy.h" -#include "prpl.h" #include "request.h" #include "server.h" #include "signals.h" -#include "status.h" #include "util.h" -#include "xmlnode.h" -/* TODO: Should use PurpleValue instead of this? What about "ui"? */ +#define PURPLE_ACCOUNT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_ACCOUNT, PurpleAccountPrivate)) + typedef struct { - PurplePrefType type; + char *username; /**< The username. */ + char *alias; /**< How you appear to yourself. */ + char *password; /**< The account password. */ + char *user_info; /**< User information. */ - char *ui; + char *buddy_icon_path; /**< The buddy icon's non-cached path. */ - union - { - int integer; - char *string; - gboolean boolean; + gboolean remember_pass; /**< Remember the password. */ + + /* + * TODO: After a GObject representing a protocol is ready, use it + * here instead of the protocol ID. + */ + char *protocol_id; /**< The ID of the protocol. */ + + PurpleConnection *gc; /**< The connection handle. */ + gboolean disconnecting; /**< The account is currently disconnecting */ + + GHashTable *settings; /**< Protocol-specific settings. */ + GHashTable *ui_settings; /**< UI-specific settings. */ + + PurpleProxyInfo *proxy_info; /**< Proxy information. This will be set */ + /* to NULL when the account inherits */ + /* proxy settings from global prefs. */ + + /* + * TODO: Supplementing the next two linked lists with hash tables + * should help performance a lot when these lists are long. This + * matters quite a bit for protocols like MSN, where all your + * buddies are added to your permit list. Currently we have to + * iterate through the entire list if we want to check if someone + * is permitted or denied. We should do this for 3.0.0. + * Or maybe use a GTree. + */ + GSList *permit; /**< Permit list. */ + GSList *deny; /**< Deny list. */ + PurpleAccountPrivacyType privacy_type; /**< The permit/deny setting. */ + + GList *status_types; /**< Status types. */ + + PurplePresence *presence; /**< Presence. */ + PurpleLog *system_log; /**< The system log */ + + PurpleAccountRegistrationCb registration_cb; + void *registration_cb_user_data; - } value; + PurpleConnectionErrorInfo *current_error; /**< Errors */ +} PurpleAccountPrivate; + +typedef struct +{ + char *ui; + GValue value; } PurpleAccountSetting; @@ -77,1073 +116,42 @@ typedef struct gpointer data; } PurpleCallbackBundle; -static PurpleAccountUiOps *account_ui_ops = NULL; - -static GList *accounts = NULL; -static guint save_timer = 0; -static gboolean accounts_loaded = FALSE; - -static GList *handles = NULL; - -static void set_current_error(PurpleAccount *account, - PurpleConnectionErrorInfo *new_err); - -/********************************************************************* - * Writing to disk * - *********************************************************************/ - -static void -setting_to_xmlnode(gpointer key, gpointer value, gpointer user_data) -{ - const char *name; - PurpleAccountSetting *setting; - xmlnode *node, *child; - char buf[21]; - - name = (const char *)key; - setting = (PurpleAccountSetting *)value; - node = (xmlnode *)user_data; - - child = xmlnode_new_child(node, "setting"); - xmlnode_set_attrib(child, "name", name); - - if (setting->type == PURPLE_PREF_INT) { - xmlnode_set_attrib(child, "type", "int"); - g_snprintf(buf, sizeof(buf), "%d", setting->value.integer); - xmlnode_insert_data(child, buf, -1); - } - else if (setting->type == PURPLE_PREF_STRING && setting->value.string != NULL) { - xmlnode_set_attrib(child, "type", "string"); - xmlnode_insert_data(child, setting->value.string, -1); - } - else if (setting->type == PURPLE_PREF_BOOLEAN) { - xmlnode_set_attrib(child, "type", "bool"); - g_snprintf(buf, sizeof(buf), "%d", setting->value.boolean); - xmlnode_insert_data(child, buf, -1); - } -} - -static void -ui_setting_to_xmlnode(gpointer key, gpointer value, gpointer user_data) -{ - const char *ui; - GHashTable *table; - xmlnode *node, *child; - - ui = (const char *)key; - table = (GHashTable *)value; - node = (xmlnode *)user_data; - - if (g_hash_table_size(table) > 0) - { - child = xmlnode_new_child(node, "settings"); - xmlnode_set_attrib(child, "ui", ui); - g_hash_table_foreach(table, setting_to_xmlnode, child); - } -} - -static xmlnode * -status_attr_to_xmlnode(const PurpleStatus *status, const PurpleStatusType *type, const PurpleStatusAttr *attr) -{ - xmlnode *node; - const char *id; - char *value = NULL; - PurpleStatusAttr *default_attr; - PurpleValue *default_value; - PurpleType attr_type; - PurpleValue *attr_value; - - id = purple_status_attr_get_id(attr); - g_return_val_if_fail(id, NULL); - - attr_value = purple_status_get_attr_value(status, id); - g_return_val_if_fail(attr_value, NULL); - attr_type = purple_value_get_type(attr_value); - - /* - * If attr_value is a different type than it should be - * then don't write it to the file. - */ - default_attr = purple_status_type_get_attr(type, id); - default_value = purple_status_attr_get_value(default_attr); - if (attr_type != purple_value_get_type(default_value)) - return NULL; - - /* - * If attr_value is the same as the default for this status - * then there is no need to write it to the file. - */ - if (attr_type == PURPLE_TYPE_STRING) - { - const char *string_value = purple_value_get_string(attr_value); - const char *default_string_value = purple_value_get_string(default_value); - if (purple_strequal(string_value, default_string_value)) - return NULL; - value = g_strdup(purple_value_get_string(attr_value)); - } - else if (attr_type == PURPLE_TYPE_INT) - { - int int_value = purple_value_get_int(attr_value); - if (int_value == purple_value_get_int(default_value)) - return NULL; - value = g_strdup_printf("%d", int_value); - } - else if (attr_type == PURPLE_TYPE_BOOLEAN) - { - gboolean boolean_value = purple_value_get_boolean(attr_value); - if (boolean_value == purple_value_get_boolean(default_value)) - return NULL; - value = g_strdup(boolean_value ? - "true" : "false"); - } - else - { - return NULL; - } - - g_return_val_if_fail(value, NULL); - - node = xmlnode_new("attribute"); - - xmlnode_set_attrib(node, "id", id); - xmlnode_set_attrib(node, "value", value); - - g_free(value); - - return node; -} - -static xmlnode * -status_attrs_to_xmlnode(const PurpleStatus *status) -{ - PurpleStatusType *type = purple_status_get_type(status); - xmlnode *node, *child; - GList *attrs, *attr; - - node = xmlnode_new("attributes"); - - attrs = purple_status_type_get_attrs(type); - for (attr = attrs; attr != NULL; attr = attr->next) - { - child = status_attr_to_xmlnode(status, type, (const PurpleStatusAttr *)attr->data); - if (child) - xmlnode_insert_child(node, child); - } - - return node; -} - -static xmlnode * -status_to_xmlnode(const PurpleStatus *status) -{ - xmlnode *node, *child; - - node = xmlnode_new("status"); - xmlnode_set_attrib(node, "type", purple_status_get_id(status)); - if (purple_status_get_name(status) != NULL) - xmlnode_set_attrib(node, "name", purple_status_get_name(status)); - xmlnode_set_attrib(node, "active", purple_status_is_active(status) ? "true" : "false"); - - child = status_attrs_to_xmlnode(status); - xmlnode_insert_child(node, child); - - return node; -} - -static xmlnode * -statuses_to_xmlnode(const PurplePresence *presence) -{ - xmlnode *node, *child; - GList *statuses; - PurpleStatus *status; - - node = xmlnode_new("statuses"); - - statuses = purple_presence_get_statuses(presence); - for (; statuses != NULL; statuses = statuses->next) - { - status = statuses->data; - if (purple_status_type_is_saveable(purple_status_get_type(status))) - { - child = status_to_xmlnode(status); - xmlnode_insert_child(node, child); - } - } - - return node; -} - -static xmlnode * -proxy_settings_to_xmlnode(PurpleProxyInfo *proxy_info) -{ - xmlnode *node, *child; - PurpleProxyType proxy_type; - const char *value; - int int_value; - char buf[21]; - - proxy_type = purple_proxy_info_get_type(proxy_info); - - node = xmlnode_new("proxy"); - - child = xmlnode_new_child(node, "type"); - xmlnode_insert_data(child, - (proxy_type == PURPLE_PROXY_USE_GLOBAL ? "global" : - proxy_type == PURPLE_PROXY_NONE ? "none" : - proxy_type == PURPLE_PROXY_HTTP ? "http" : - proxy_type == PURPLE_PROXY_SOCKS4 ? "socks4" : - proxy_type == PURPLE_PROXY_SOCKS5 ? "socks5" : - proxy_type == PURPLE_PROXY_TOR ? "tor" : - proxy_type == PURPLE_PROXY_USE_ENVVAR ? "envvar" : "unknown"), -1); - - if ((value = purple_proxy_info_get_host(proxy_info)) != NULL) - { - child = xmlnode_new_child(node, "host"); - xmlnode_insert_data(child, value, -1); - } - - if ((int_value = purple_proxy_info_get_port(proxy_info)) != 0) - { - g_snprintf(buf, sizeof(buf), "%d", int_value); - child = xmlnode_new_child(node, "port"); - xmlnode_insert_data(child, buf, -1); - } - - if ((value = purple_proxy_info_get_username(proxy_info)) != NULL) - { - child = xmlnode_new_child(node, "username"); - xmlnode_insert_data(child, value, -1); - } - - if ((value = purple_proxy_info_get_password(proxy_info)) != NULL) - { - child = xmlnode_new_child(node, "password"); - xmlnode_insert_data(child, value, -1); - } - - return node; -} - -static xmlnode * -current_error_to_xmlnode(PurpleConnectionErrorInfo *err) -{ - xmlnode *node, *child; - char type_str[3]; - - node = xmlnode_new("current_error"); - - if(err == NULL) - return node; - - /* It doesn't make sense to have transient errors persist across a - * restart. - */ - if(!purple_connection_error_is_fatal (err->type)) - return node; - - child = xmlnode_new_child(node, "type"); - g_snprintf(type_str, sizeof(type_str), "%u", err->type); - xmlnode_insert_data(child, type_str, -1); - - child = xmlnode_new_child(node, "description"); - if(err->description) { - char *utf8ized = purple_utf8_try_convert(err->description); - if(utf8ized == NULL) - utf8ized = purple_utf8_salvage(err->description); - xmlnode_insert_data(child, utf8ized, -1); - g_free(utf8ized); - } - - return node; -} - -static xmlnode * -account_to_xmlnode(PurpleAccount *account) -{ - xmlnode *node, *child; - const char *tmp; - PurplePresence *presence; - PurpleProxyInfo *proxy_info; - - node = xmlnode_new("account"); - - child = xmlnode_new_child(node, "protocol"); - xmlnode_insert_data(child, purple_account_get_protocol_id(account), -1); - - child = xmlnode_new_child(node, "name"); - xmlnode_insert_data(child, purple_account_get_username(account), -1); - - if (purple_account_get_remember_password(account)) - { - const char *keyring_id = NULL; - const char *mode = NULL; - char *data = NULL; - GError *error = NULL; - GDestroyNotify destroy = NULL; - gboolean exported = purple_keyring_export_password(account, - &keyring_id, &mode, &data, &error, &destroy); - - if (error != NULL) { - purple_debug_error("account", - "Failed to export password for account %s: %s.\n", - purple_account_get_username(account), - error->message); - } else if (exported) { - child = xmlnode_new_child(node, "password"); - if (keyring_id != NULL) - xmlnode_set_attrib(child, "keyring_id", keyring_id); - if (mode != NULL) - xmlnode_set_attrib(child, "mode", mode); - if (data != NULL) - xmlnode_insert_data(child, data, -1); - - if (destroy != NULL) - destroy(data); - } - } - - if ((tmp = purple_account_get_alias(account)) != NULL) - { - child = xmlnode_new_child(node, "alias"); - xmlnode_insert_data(child, tmp, -1); - } - - if ((presence = purple_account_get_presence(account)) != NULL) - { - child = statuses_to_xmlnode(presence); - xmlnode_insert_child(node, child); - } - - if ((tmp = purple_account_get_user_info(account)) != NULL) - { - /* TODO: Do we need to call purple_str_strip_char(tmp, '\r') here? */ - child = xmlnode_new_child(node, "userinfo"); - xmlnode_insert_data(child, tmp, -1); - } - - if (g_hash_table_size(account->settings) > 0) - { - child = xmlnode_new_child(node, "settings"); - g_hash_table_foreach(account->settings, setting_to_xmlnode, child); - } - - if (g_hash_table_size(account->ui_settings) > 0) - { - g_hash_table_foreach(account->ui_settings, ui_setting_to_xmlnode, node); - } - - if ((proxy_info = purple_account_get_proxy_info(account)) != NULL) - { - child = proxy_settings_to_xmlnode(proxy_info); - xmlnode_insert_child(node, child); - } - - child = current_error_to_xmlnode(account->current_error); - xmlnode_insert_child(node, child); - - return node; -} - -static xmlnode * -accounts_to_xmlnode(void) -{ - xmlnode *node, *child; - GList *cur; - - node = xmlnode_new("account"); - xmlnode_set_attrib(node, "version", "1.0"); - - for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next) - { - child = account_to_xmlnode(cur->data); - xmlnode_insert_child(node, child); - } - - return node; -} - -static void -sync_accounts(void) -{ - xmlnode *node; - char *data; - - if (!accounts_loaded) - { - purple_debug_error("account", "Attempted to save accounts before " - "they were read!\n"); - return; - } - - node = accounts_to_xmlnode(); - data = xmlnode_to_formatted_str(node, NULL); - purple_util_write_data_to_file("accounts.xml", data, -1); - g_free(data); - xmlnode_free(node); -} - -static gboolean -save_cb(gpointer data) -{ - sync_accounts(); - save_timer = 0; - return FALSE; -} - -static void -schedule_accounts_save(void) -{ - if (save_timer == 0) - save_timer = purple_timeout_add_seconds(5, save_cb, NULL); -} - - -/********************************************************************* - * Reading from disk * - *********************************************************************/ -static void -migrate_yahoo_japan(PurpleAccount *account) -{ - /* detect a Yahoo! JAPAN account that existed prior to 2.6.0 and convert it - * to use the new prpl-yahoojp. Also remove the account-specific settings - * we no longer need */ - - if(purple_strequal(purple_account_get_protocol_id(account), "prpl-yahoo")) { - if(purple_account_get_bool(account, "yahoojp", FALSE)) { - const char *serverjp = purple_account_get_string(account, "serverjp", NULL); - const char *xferjp_host = purple_account_get_string(account, "xferjp_host", NULL); - - g_return_if_fail(serverjp != NULL); - g_return_if_fail(xferjp_host != NULL); - - purple_account_set_string(account, "server", serverjp); - purple_account_set_string(account, "xfer_host", xferjp_host); - - purple_account_set_protocol_id(account, "prpl-yahoojp"); - } - - /* these should always be nuked */ - purple_account_remove_setting(account, "yahoojp"); - purple_account_remove_setting(account, "serverjp"); - purple_account_remove_setting(account, "xferjp_host"); - - } -} - -static void -migrate_icq_server(PurpleAccount *account) -{ - /* Migrate the login server setting for ICQ accounts. See - * 'mtn log --last 1 --no-graph --from b6d7712e90b68610df3bd2d8cbaf46d94c8b3794' - * for details on the change. */ - - if(purple_strequal(purple_account_get_protocol_id(account), "prpl-icq")) { - const char *tmp = purple_account_get_string(account, "server", NULL); - - /* Non-secure server */ - if(purple_strequal(tmp, "login.messaging.aol.com") || - purple_strequal(tmp, "login.oscar.aol.com")) - purple_account_set_string(account, "server", "login.icq.com"); - - /* Secure server */ - if(purple_strequal(tmp, "slogin.oscar.aol.com")) - purple_account_set_string(account, "server", "slogin.icq.com"); - } -} - -static void -migrate_xmpp_encryption(PurpleAccount *account) -{ - /* When this is removed, nuke the "old_ssl" and "require_tls" settings */ - if (g_str_equal(purple_account_get_protocol_id(account), "prpl-jabber")) { - const char *sec = purple_account_get_string(account, "connection_security", ""); - - if (g_str_equal("", sec)) { - const char *val = "require_tls"; - if (purple_account_get_bool(account, "old_ssl", FALSE)) - val = "old_ssl"; - else if (!purple_account_get_bool(account, "require_tls", TRUE)) - val = "opportunistic_tls"; - - purple_account_set_string(account, "connection_security", val); - } - } -} - -static void -parse_settings(xmlnode *node, PurpleAccount *account) -{ - const char *ui; - xmlnode *child; - - /* Get the UI string, if these are UI settings */ - ui = xmlnode_get_attrib(node, "ui"); - - /* Read settings, one by one */ - for (child = xmlnode_get_child(node, "setting"); child != NULL; - child = xmlnode_get_next_twin(child)) - { - const char *name, *str_type; - PurplePrefType type; - char *data; - - name = xmlnode_get_attrib(child, "name"); - if (name == NULL) - /* Ignore this setting */ - continue; - - str_type = xmlnode_get_attrib(child, "type"); - if (str_type == NULL) - /* Ignore this setting */ - continue; - - if (purple_strequal(str_type, "string")) - type = PURPLE_PREF_STRING; - else if (purple_strequal(str_type, "int")) - type = PURPLE_PREF_INT; - else if (purple_strequal(str_type, "bool")) - type = PURPLE_PREF_BOOLEAN; - else - /* Ignore this setting */ - continue; - - data = xmlnode_get_data(child); - if (data == NULL) - /* Ignore this setting */ - continue; - - if (ui == NULL) - { - if (type == PURPLE_PREF_STRING) - purple_account_set_string(account, name, data); - else if (type == PURPLE_PREF_INT) - purple_account_set_int(account, name, atoi(data)); - else if (type == PURPLE_PREF_BOOLEAN) - purple_account_set_bool(account, name, - (*data == '0' ? FALSE : TRUE)); - } else { - if (type == PURPLE_PREF_STRING) - purple_account_set_ui_string(account, ui, name, data); - else if (type == PURPLE_PREF_INT) - purple_account_set_ui_int(account, ui, name, atoi(data)); - else if (type == PURPLE_PREF_BOOLEAN) - purple_account_set_ui_bool(account, ui, name, - (*data == '0' ? FALSE : TRUE)); - } - - g_free(data); - } - - /* we do this here because we need access to account settings to determine - * if we can/should migrate an old Yahoo! JAPAN account */ - migrate_yahoo_japan(account); - /* we do this here because we need access to account settings to determine - * if we can/should migrate an ICQ account's server setting */ - migrate_icq_server(account); - /* we do this here because we need to do it before the user views the - * Edit Account dialog. */ - migrate_xmpp_encryption(account); -} - -static GList * -parse_status_attrs(xmlnode *node, PurpleStatus *status) -{ - GList *list = NULL; - xmlnode *child; - PurpleValue *attr_value; - - for (child = xmlnode_get_child(node, "attribute"); child != NULL; - child = xmlnode_get_next_twin(child)) - { - const char *id = xmlnode_get_attrib(child, "id"); - const char *value = xmlnode_get_attrib(child, "value"); - - if (!id || !*id || !value || !*value) - continue; - - attr_value = purple_status_get_attr_value(status, id); - if (!attr_value) - continue; - - list = g_list_append(list, (char *)id); - - switch (purple_value_get_type(attr_value)) - { - case PURPLE_TYPE_STRING: - list = g_list_append(list, (char *)value); - break; - case PURPLE_TYPE_INT: - case PURPLE_TYPE_BOOLEAN: - { - int v; - if (sscanf(value, "%d", &v) == 1) - list = g_list_append(list, GINT_TO_POINTER(v)); - else - list = g_list_remove(list, id); - break; - } - default: - break; - } - } - - return list; -} - -static void -parse_status(xmlnode *node, PurpleAccount *account) -{ - gboolean active = FALSE; - const char *data; - const char *type; - xmlnode *child; - GList *attrs = NULL; - - /* Get the active/inactive state */ - data = xmlnode_get_attrib(node, "active"); - if (data == NULL) - return; - if (g_ascii_strcasecmp(data, "true") == 0) - active = TRUE; - else if (g_ascii_strcasecmp(data, "false") == 0) - active = FALSE; - else - return; - - /* Get the type of the status */ - type = xmlnode_get_attrib(node, "type"); - if (type == NULL) - return; - - /* Read attributes into a GList */ - child = xmlnode_get_child(node, "attributes"); - if (child != NULL) - { - attrs = parse_status_attrs(child, - purple_account_get_status(account, type)); - } - - purple_account_set_status_list(account, type, active, attrs); - - g_list_free(attrs); -} - -static void -parse_statuses(xmlnode *node, PurpleAccount *account) -{ - xmlnode *child; - - for (child = xmlnode_get_child(node, "status"); child != NULL; - child = xmlnode_get_next_twin(child)) - { - parse_status(child, account); - } -} - -static void -parse_proxy_info(xmlnode *node, PurpleAccount *account) -{ - PurpleProxyInfo *proxy_info; - xmlnode *child; - char *data; - - proxy_info = purple_proxy_info_new(); - - /* Use the global proxy settings, by default */ - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_USE_GLOBAL); - - /* Read proxy type */ - child = xmlnode_get_child(node, "type"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - if (purple_strequal(data, "global")) - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_USE_GLOBAL); - else if (purple_strequal(data, "none")) - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_NONE); - else if (purple_strequal(data, "http")) - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_HTTP); - else if (purple_strequal(data, "socks4")) - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_SOCKS4); - else if (purple_strequal(data, "socks5")) - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_SOCKS5); - else if (purple_strequal(data, "tor")) - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_TOR); - else if (purple_strequal(data, "envvar")) - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_USE_ENVVAR); - else - { - purple_debug_error("account", "Invalid proxy type found when " - "loading account information for %s\n", - purple_account_get_username(account)); - } - g_free(data); - } - - /* Read proxy host */ - child = xmlnode_get_child(node, "host"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - purple_proxy_info_set_host(proxy_info, data); - g_free(data); - } - - /* Read proxy port */ - child = xmlnode_get_child(node, "port"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - purple_proxy_info_set_port(proxy_info, atoi(data)); - g_free(data); - } - - /* Read proxy username */ - child = xmlnode_get_child(node, "username"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - purple_proxy_info_set_username(proxy_info, data); - g_free(data); - } - - /* Read proxy password */ - child = xmlnode_get_child(node, "password"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - purple_proxy_info_set_password(proxy_info, data); - g_free(data); - } - - /* If there are no values set then proxy_info NULL */ - if ((purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_USE_GLOBAL) && - (purple_proxy_info_get_host(proxy_info) == NULL) && - (purple_proxy_info_get_port(proxy_info) == 0) && - (purple_proxy_info_get_username(proxy_info) == NULL) && - (purple_proxy_info_get_password(proxy_info) == NULL)) - { - purple_proxy_info_destroy(proxy_info); - return; - } - - purple_account_set_proxy_info(account, proxy_info); -} - -static void -parse_current_error(xmlnode *node, PurpleAccount *account) -{ - guint type; - char *type_str = NULL, *description = NULL; - xmlnode *child; - PurpleConnectionErrorInfo *current_error = NULL; - - child = xmlnode_get_child(node, "type"); - if (child == NULL || (type_str = xmlnode_get_data(child)) == NULL) - return; - type = atoi(type_str); - g_free(type_str); - - if (type > PURPLE_CONNECTION_ERROR_OTHER_ERROR) - { - purple_debug_error("account", - "Invalid PurpleConnectionError value %d found when " - "loading account information for %s\n", - type, purple_account_get_username(account)); - type = PURPLE_CONNECTION_ERROR_OTHER_ERROR; - } - - child = xmlnode_get_child(node, "description"); - if (child) - description = xmlnode_get_data(child); - if (description == NULL) - description = g_strdup(""); - - current_error = g_new0(PurpleConnectionErrorInfo, 1); - PURPLE_DBUS_REGISTER_POINTER(current_error, PurpleConnectionErrorInfo); - current_error->type = type; - current_error->description = description; - - set_current_error(account, current_error); -} - -static PurpleAccount * -parse_account(xmlnode *node) -{ - PurpleAccount *ret; - xmlnode *child; - char *protocol_id = NULL; - char *name = NULL; - char *data; - - child = xmlnode_get_child(node, "protocol"); - if (child != NULL) - protocol_id = xmlnode_get_data(child); - - child = xmlnode_get_child(node, "name"); - if (child != NULL) - name = xmlnode_get_data(child); - if (name == NULL) - { - /* Do we really need to do this? */ - child = xmlnode_get_child(node, "username"); - if (child != NULL) - name = xmlnode_get_data(child); - } - - if ((protocol_id == NULL) || (name == NULL)) - { - g_free(protocol_id); - g_free(name); - return NULL; - } - - ret = purple_account_new(name, protocol_id); - g_free(name); - g_free(protocol_id); - - /* Read the alias */ - child = xmlnode_get_child(node, "alias"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - if (*data != '\0') - purple_account_set_alias(ret, data); - g_free(data); - } - - /* Read the statuses */ - child = xmlnode_get_child(node, "statuses"); - if (child != NULL) - { - parse_statuses(child, ret); - } - - /* Read the userinfo */ - child = xmlnode_get_child(node, "userinfo"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - purple_account_set_user_info(ret, data); - g_free(data); - } - - /* Read an old buddyicon */ - child = xmlnode_get_child(node, "buddyicon"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - const char *dirname = purple_buddy_icons_get_cache_dir(); - char *filename = g_build_filename(dirname, data, NULL); - gchar *contents; - gsize len; - - if (g_file_get_contents(filename, &contents, &len, NULL)) - { - purple_buddy_icons_set_account_icon(ret, (guchar *)contents, len); - } - - g_free(filename); - g_free(data); - } - - /* Read settings (both core and UI) */ - for (child = xmlnode_get_child(node, "settings"); child != NULL; - child = xmlnode_get_next_twin(child)) - { - parse_settings(child, ret); - } - - /* Read proxy */ - child = xmlnode_get_child(node, "proxy"); - if (child != NULL) - { - parse_proxy_info(child, ret); - } - - /* Read current error */ - child = xmlnode_get_child(node, "current_error"); - if (child != NULL) - { - parse_current_error(child, ret); - } - - /* Read the password */ - child = xmlnode_get_child(node, "password"); - if (child != NULL) - { - const char *keyring_id = xmlnode_get_attrib(child, "keyring_id"); - const char *mode = xmlnode_get_attrib(child, "mode"); - gboolean result; - - data = xmlnode_get_data(child); - result = purple_keyring_import_password(ret, keyring_id, mode, data, NULL); - - if (result == TRUE || purple_keyring_get_inuse() == NULL) { - purple_account_set_remember_password(ret, TRUE); - } else { - purple_debug_error("account", "Failed to import password.\n"); - } - purple_str_wipe(data); - } - - return ret; -} - -static void -load_accounts(void) -{ - xmlnode *node, *child; - - accounts_loaded = TRUE; - - node = purple_util_read_xml_from_file("accounts.xml", _("accounts")); - - if (node == NULL) - return; - - for (child = xmlnode_get_child(node, "account"); child != NULL; - child = xmlnode_get_next_twin(child)) - { - PurpleAccount *new_acct; - new_acct = parse_account(child); - purple_accounts_add(new_acct); - } - - xmlnode_free(node); - - _purple_buddy_icons_account_loaded_cb(); -} - - -static void -delete_setting(void *data) -{ - PurpleAccountSetting *setting = (PurpleAccountSetting *)data; - - g_free(setting->ui); - - if (setting->type == PURPLE_PREF_STRING) - g_free(setting->value.string); - - g_free(setting); -} - -PurpleAccount * -purple_account_new(const char *username, const char *protocol_id) -{ - PurpleAccount *account = NULL; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; - PurpleStatusType *status_type; - - g_return_val_if_fail(username != NULL, NULL); - g_return_val_if_fail(protocol_id != NULL, NULL); - - account = purple_accounts_find(username, protocol_id); - - if (account != NULL) - return account; - - account = g_new0(PurpleAccount, 1); - PURPLE_DBUS_REGISTER_POINTER(account, PurpleAccount); - - purple_account_set_username(account, username); - - purple_account_set_protocol_id(account, protocol_id); - - account->settings = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, delete_setting); - account->ui_settings = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, (GDestroyNotify)g_hash_table_destroy); - account->system_log = NULL; - /* 0 is not a valid privacy setting */ - account->perm_deny = PURPLE_PRIVACY_ALLOW_ALL; - - purple_signal_emit(purple_accounts_get_handle(), "account-created", account); - - prpl = purple_find_prpl(protocol_id); - - if (prpl == NULL) - return account; - - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info != NULL && prpl_info->status_types != NULL) - purple_account_set_status_types(account, prpl_info->status_types(account)); - - account->presence = purple_presence_new_for_account(account); +/* GObject Property enums */ +enum +{ + PROP_0, + PROP_USERNAME, + PROP_PRIVATE_ALIAS, + PROP_ENABLED, + PROP_CONNECTION, + PROP_PROTOCOL_ID, + PROP_USER_INFO, + PROP_BUDDY_ICON_PATH, + PROP_REMEMBER_PASSWORD, + PROP_CHECK_MAIL, + PROP_LAST +}; - status_type = purple_account_get_status_type_with_primitive(account, PURPLE_STATUS_AVAILABLE); - if (status_type != NULL) - purple_presence_set_status_active(account->presence, - purple_status_type_get_id(status_type), - TRUE); - else - purple_presence_set_status_active(account->presence, - "offline", - TRUE); +static GObjectClass *parent_class = NULL; +static GList *handles = NULL; - return account; -} +void _purple_account_set_current_error(PurpleAccount *account, + PurpleConnectionErrorInfo *new_err); +/*************** + * Account API * + ***************/ void -purple_account_destroy(PurpleAccount *account) +purple_account_set_register_callback(PurpleAccount *account, PurpleAccountRegistrationCb cb, void *user_data) { - GList *l; + PurpleAccountPrivate *priv; g_return_if_fail(account != NULL); - purple_debug_info("account", "Destroying account %p\n", account); - purple_signal_emit(purple_accounts_get_handle(), "account-destroying", account); - - for (l = purple_get_conversations(); l != NULL; l = l->next) - { - PurpleConversation *conv = (PurpleConversation *)l->data; - - if (purple_conversation_get_account(conv) == account) - purple_conversation_set_account(conv, NULL); - } - - g_free(account->username); - g_free(account->alias); - purple_str_wipe(account->password); - g_free(account->user_info); - g_free(account->buddy_icon_path); - g_free(account->protocol_id); - - g_hash_table_destroy(account->settings); - g_hash_table_destroy(account->ui_settings); - - if (account->proxy_info) - purple_proxy_info_destroy(account->proxy_info); - - purple_account_set_status_types(account, NULL); - - if (account->presence) - purple_presence_destroy(account->presence); - - if(account->system_log) - purple_log_free(account->system_log); - - while (account->deny) { - g_free(account->deny->data); - account->deny = g_slist_delete_link(account->deny, account->deny); - } - - while (account->permit) { - g_free(account->permit->data); - account->permit = g_slist_delete_link(account->permit, account->permit); - } - - PURPLE_DBUS_UNREGISTER_POINTER(account->current_error); - if (account->current_error) { - g_free(account->current_error->description); - g_free(account->current_error); - } - - PURPLE_DBUS_UNREGISTER_POINTER(account); - g_free(account); -} - -void -purple_account_set_register_callback(PurpleAccount *account, PurpleAccountRegistrationCb cb, void *user_data) -{ - g_return_if_fail(account != NULL); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); - account->registration_cb = cb; - account->registration_cb_user_data = user_data; + priv->registration_cb = cb; + priv->registration_cb_user_data = user_data; } static void @@ -1183,10 +191,14 @@ purple_account_unregister_got_password_cb(PurpleAccount *account, void purple_account_register_completed(PurpleAccount *account, gboolean succeeded) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - if (account->registration_cb) - (account->registration_cb)(account, succeeded, account->registration_cb_user_data); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if (priv->registration_cb) + (priv->registration_cb)(account, succeeded, priv->registration_cb_user_data); } void @@ -1299,6 +311,7 @@ purple_account_connect(PurpleAccount *account) PurplePlugin *prpl; const char *username; PurplePluginProtocolInfo *prpl_info; + PurpleAccountPrivate *priv; g_return_if_fail(account != NULL); @@ -1321,12 +334,14 @@ purple_account_connect(PurpleAccount *account) return; } + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + purple_debug_info("account", "Connecting to account %s.\n", username); prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (account->password != NULL) { + if (priv->password != NULL) { purple_account_connect_got_password_cb(account, - account->password, NULL, prpl_info); + priv->password, NULL, prpl_info); } else { purple_keyring_get_password(account, purple_account_connect_got_password_cb, prpl_info); @@ -1337,30 +352,36 @@ void purple_account_disconnect(PurpleAccount *account) { PurpleConnection *gc; + PurpleAccountPrivate *priv; const char *username; g_return_if_fail(account != NULL); g_return_if_fail(!purple_account_is_disconnected(account)); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + username = purple_account_get_username(account); purple_debug_info("account", "Disconnecting account %s (%p)\n", username ? username : "(null)", account); - account->disconnecting = TRUE; + priv->disconnecting = TRUE; gc = purple_account_get_connection(account); - _purple_connection_destroy(gc); + g_object_unref(gc); purple_account_set_connection(account, NULL); - account->disconnecting = FALSE; + priv->disconnecting = FALSE; } gboolean purple_account_is_disconnecting(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, TRUE); - - return account->disconnecting; + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->disconnecting; } void @@ -1681,7 +702,7 @@ purple_account_request_change_user_info(PurpleAccount *account) purple_request_input(gc, _("Set User Info"), primary, NULL, purple_account_get_user_info(account), TRUE, FALSE, ((gc != NULL) && - (purple_connection_get_flags(gc) & PURPLE_CONNECTION_HTML) ? "html" : NULL), + (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_HTML) ? "html" : NULL), _("Save"), G_CALLBACK(set_user_info_cb), _("Cancel"), NULL, account, NULL, NULL, @@ -1692,13 +713,16 @@ void purple_account_set_username(PurpleAccount *account, const char *username) { PurpleBlistUiOps *blist_ops; + PurpleAccountPrivate *priv; g_return_if_fail(account != NULL); - g_free(account->username); - account->username = g_strdup(username); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + g_free(priv->username); + priv->username = g_strdup(username); - schedule_accounts_save(); + purple_accounts_schedule_save(); /* if the name changes, we should re-write the buddy list * to disk with the new name */ @@ -1711,12 +735,16 @@ void purple_account_set_password(PurpleAccount *account, const gchar *password, PurpleKeyringSaveCallback cb, gpointer data) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - purple_str_wipe(account->password); - account->password = g_strdup(password); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + purple_str_wipe(priv->password); + priv->password = g_strdup(password); - schedule_accounts_save(); + purple_accounts_schedule_save(); if (!purple_account_get_remember_password(account)) { purple_debug_info("account", @@ -1731,80 +759,102 @@ purple_account_set_password(PurpleAccount *account, const gchar *password, } void -purple_account_set_alias(PurpleAccount *account, const char *alias) +purple_account_set_private_alias(PurpleAccount *account, const char *alias) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + /* - * Do nothing if alias and account->alias are both NULL. Or if + * Do nothing if alias and priv->alias are both NULL. Or if * they're the exact same string. */ - if (alias == account->alias) + if (alias == priv->alias) return; - if ((!alias && account->alias) || (alias && !account->alias) || - g_utf8_collate(account->alias, alias)) + if ((!alias && priv->alias) || (alias && !priv->alias) || + g_utf8_collate(priv->alias, alias)) { - char *old = account->alias; + char *old = priv->alias; - account->alias = g_strdup(alias); + priv->alias = g_strdup(alias); purple_signal_emit(purple_accounts_get_handle(), "account-alias-changed", account, old); g_free(old); - schedule_accounts_save(); + purple_accounts_schedule_save(); } } void purple_account_set_user_info(PurpleAccount *account, const char *user_info) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - g_free(account->user_info); - account->user_info = g_strdup(user_info); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); - schedule_accounts_save(); + g_free(priv->user_info); + priv->user_info = g_strdup(user_info); + + purple_accounts_schedule_save(); } void purple_account_set_buddy_icon_path(PurpleAccount *account, const char *path) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - g_free(account->buddy_icon_path); - account->buddy_icon_path = g_strdup(path); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); - schedule_accounts_save(); + g_free(priv->buddy_icon_path); + priv->buddy_icon_path = g_strdup(path); + + purple_accounts_schedule_save(); } void purple_account_set_protocol_id(PurpleAccount *account, const char *protocol_id) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); g_return_if_fail(protocol_id != NULL); - g_free(account->protocol_id); - account->protocol_id = g_strdup(protocol_id); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + g_free(priv->protocol_id); + priv->protocol_id = g_strdup(protocol_id); - schedule_accounts_save(); + purple_accounts_schedule_save(); } void purple_account_set_connection(PurpleAccount *account, PurpleConnection *gc) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - account->gc = gc; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + priv->gc = gc; } void purple_account_set_remember_password(PurpleAccount *account, gboolean value) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - account->remember_pass = value; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + priv->remember_pass = value; - schedule_accounts_save(); + purple_accounts_schedule_save(); } void @@ -1820,6 +870,7 @@ purple_account_set_enabled(PurpleAccount *account, const char *ui, gboolean value) { PurpleConnection *gc; + PurpleAccountPrivate *priv; gboolean was_enabled = FALSE; g_return_if_fail(account != NULL); @@ -1835,10 +886,12 @@ purple_account_set_enabled(PurpleAccount *account, const char *ui, else if(!was_enabled && value) purple_signal_emit(purple_accounts_get_handle(), "account-enabled", account); - if ((gc != NULL) && (gc->wants_to_die == TRUE)) + if ((gc != NULL) && (_purple_connection_wants_to_die(gc))) return; - if (value && purple_presence_is_online(account->presence)) + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if (value && purple_presence_is_online(priv->presence)) purple_account_connect(account); else if (!value && !purple_account_is_disconnected(account)) purple_account_disconnect(account); @@ -1847,38 +900,49 @@ purple_account_set_enabled(PurpleAccount *account, const char *ui, void purple_account_set_proxy_info(PurpleAccount *account, PurpleProxyInfo *info) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - if (account->proxy_info != NULL) - purple_proxy_info_destroy(account->proxy_info); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if (priv->proxy_info != NULL) + purple_proxy_info_destroy(priv->proxy_info); - account->proxy_info = info; + priv->proxy_info = info; - schedule_accounts_save(); + purple_accounts_schedule_save(); } void -purple_account_set_privacy_type(PurpleAccount *account, PurplePrivacyType privacy_type) +purple_account_set_privacy_type(PurpleAccount *account, PurpleAccountPrivacyType privacy_type) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - account->perm_deny = privacy_type; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + priv->privacy_type = privacy_type; } void purple_account_set_status_types(PurpleAccount *account, GList *status_types) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + /* Out with the old... */ - if (account->status_types != NULL) + if (priv->status_types != NULL) { - g_list_foreach(account->status_types, (GFunc)purple_status_type_destroy, NULL); - g_list_free(account->status_types); + g_list_foreach(priv->status_types, (GFunc)purple_status_type_destroy, NULL); + g_list_free(priv->status_types); } /* In with the new... */ - account->status_types = status_types; + priv->status_types = status_types; } void @@ -1928,7 +992,7 @@ purple_account_set_status_list(PurpleAccount *account, const char *status_id, * Our current statuses are saved to accounts.xml (so that when we * reconnect, we go back to the previous status). */ - schedule_accounts_save(); + purple_accounts_schedule_save(); } struct public_alias_closure @@ -2031,42 +1095,63 @@ purple_account_set_silence_suppression(PurpleAccount *account, gboolean value) purple_account_set_bool(account, "silence-suppression", value); } +static void +delete_setting(void *data) +{ + PurpleAccountSetting *setting = (PurpleAccountSetting *)data; + + g_free(setting->ui); + g_value_unset(&setting->value); + + g_free(setting); +} + void purple_account_clear_settings(PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - g_hash_table_destroy(account->settings); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + g_hash_table_destroy(priv->settings); - account->settings = g_hash_table_new_full(g_str_hash, g_str_equal, + priv->settings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, delete_setting); } void purple_account_remove_setting(PurpleAccount *account, const char *setting) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); g_return_if_fail(setting != NULL); - g_hash_table_remove(account->settings, setting); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + g_hash_table_remove(priv->settings, setting); } void purple_account_set_int(PurpleAccount *account, const char *name, int value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; g_return_if_fail(account != NULL); g_return_if_fail(name != NULL); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + setting = g_new0(PurpleAccountSetting, 1); - setting->type = PURPLE_PREF_INT; - setting->value.integer = value; + g_value_init(&setting->value, G_TYPE_INT); + g_value_set_int(&setting->value, value); - g_hash_table_insert(account->settings, g_strdup(name), setting); + g_hash_table_insert(priv->settings, g_strdup(name), setting); - schedule_accounts_save(); + purple_accounts_schedule_save(); } void @@ -2074,49 +1159,56 @@ purple_account_set_string(PurpleAccount *account, const char *name, const char *value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; g_return_if_fail(account != NULL); g_return_if_fail(name != NULL); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + setting = g_new0(PurpleAccountSetting, 1); - setting->type = PURPLE_PREF_STRING; - setting->value.string = g_strdup(value); + g_value_init(&setting->value, G_TYPE_STRING); + g_value_set_string(&setting->value, value); - g_hash_table_insert(account->settings, g_strdup(name), setting); + g_hash_table_insert(priv->settings, g_strdup(name), setting); - schedule_accounts_save(); + purple_accounts_schedule_save(); } void purple_account_set_bool(PurpleAccount *account, const char *name, gboolean value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; g_return_if_fail(account != NULL); g_return_if_fail(name != NULL); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + setting = g_new0(PurpleAccountSetting, 1); - setting->type = PURPLE_PREF_BOOLEAN; - setting->value.boolean = value; + g_value_init(&setting->value, G_TYPE_BOOLEAN); + g_value_set_boolean(&setting->value, value); - g_hash_table_insert(account->settings, g_strdup(name), setting); + g_hash_table_insert(priv->settings, g_strdup(name), setting); - schedule_accounts_save(); + purple_accounts_schedule_save(); } static GHashTable * get_ui_settings_table(PurpleAccount *account, const char *ui) { GHashTable *table; + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); - table = g_hash_table_lookup(account->ui_settings, ui); + table = g_hash_table_lookup(priv->ui_settings, ui); if (table == NULL) { table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, delete_setting); - g_hash_table_insert(account->ui_settings, g_strdup(ui), table); + g_hash_table_insert(priv->ui_settings, g_strdup(ui), table); } return table; @@ -2135,15 +1227,15 @@ purple_account_set_ui_int(PurpleAccount *account, const char *ui, setting = g_new0(PurpleAccountSetting, 1); - setting->type = PURPLE_PREF_INT; setting->ui = g_strdup(ui); - setting->value.integer = value; + g_value_init(&setting->value, G_TYPE_INT); + g_value_set_int(&setting->value, value); table = get_ui_settings_table(account, ui); g_hash_table_insert(table, g_strdup(name), setting); - schedule_accounts_save(); + purple_accounts_schedule_save(); } void @@ -2159,15 +1251,15 @@ purple_account_set_ui_string(PurpleAccount *account, const char *ui, setting = g_new0(PurpleAccountSetting, 1); - setting->type = PURPLE_PREF_STRING; setting->ui = g_strdup(ui); - setting->value.string = g_strdup(value); + g_value_init(&setting->value, G_TYPE_STRING); + g_value_set_string(&setting->value, value); table = get_ui_settings_table(account, ui); g_hash_table_insert(table, g_strdup(name), setting); - schedule_accounts_save(); + purple_accounts_schedule_save(); } void @@ -2183,15 +1275,15 @@ purple_account_set_ui_bool(PurpleAccount *account, const char *ui, setting = g_new0(PurpleAccountSetting, 1); - setting->type = PURPLE_PREF_BOOLEAN; setting->ui = g_strdup(ui); - setting->value.boolean = value; + g_value_init(&setting->value, G_TYPE_BOOLEAN); + g_value_set_boolean(&setting->value, value); table = get_ui_settings_table(account, ui); g_hash_table_insert(table, g_strdup(name), setting); - schedule_accounts_save(); + purple_accounts_schedule_save(); } static PurpleConnectionState @@ -2199,11 +1291,11 @@ purple_account_get_state(const PurpleAccount *account) { PurpleConnection *gc; - g_return_val_if_fail(account != NULL, PURPLE_DISCONNECTED); + g_return_val_if_fail(account != NULL, PURPLE_CONNECTION_DISCONNECTED); gc = purple_account_get_connection(account); if (!gc) - return PURPLE_DISCONNECTED; + return PURPLE_CONNECTION_DISCONNECTED; return purple_connection_get_state(gc); } @@ -2211,27 +1303,30 @@ purple_account_get_state(const PurpleAccount *account) gboolean purple_account_is_connected(const PurpleAccount *account) { - return (purple_account_get_state(account) == PURPLE_CONNECTED); + return (purple_account_get_state(account) == PURPLE_CONNECTION_CONNECTED); } gboolean purple_account_is_connecting(const PurpleAccount *account) { - return (purple_account_get_state(account) == PURPLE_CONNECTING); + return (purple_account_get_state(account) == PURPLE_CONNECTION_CONNECTING); } gboolean purple_account_is_disconnected(const PurpleAccount *account) { - return (purple_account_get_state(account) == PURPLE_DISCONNECTED); + return (purple_account_get_state(account) == PURPLE_CONNECTION_DISCONNECTED); } const char * purple_account_get_username(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->username; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->username; } static void @@ -2240,13 +1335,14 @@ purple_account_get_password_got(PurpleAccount *account, { PurpleCallbackBundle *cbb = data; PurpleKeyringReadCallback cb; + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); purple_debug_info("account", "Read password for account %s from async keyring.\n", purple_account_get_username(account)); - purple_str_wipe(account->password); - account->password = g_strdup(password); + purple_str_wipe(priv->password); + priv->password = g_strdup(password); cb = (PurpleKeyringReadCallback)cbb->cb; if (cb != NULL) @@ -2259,16 +1355,20 @@ void purple_account_get_password(PurpleAccount *account, PurpleKeyringReadCallback cb, gpointer data) { + PurpleAccountPrivate *priv; + if (account == NULL) { cb(NULL, NULL, NULL, data); return; } - if (account->password != NULL) { + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if (priv->password != NULL) { purple_debug_info("account", "Reading password for account %s from cache.\n", purple_account_get_username(account)); - cb(account, account->password, NULL, data); + cb(account, priv->password, NULL, data); } else { PurpleCallbackBundle *cbb = g_new0(PurpleCallbackBundle, 1); cbb->cb = PURPLE_CALLBACK(cb); @@ -2283,34 +1383,47 @@ purple_account_get_password(PurpleAccount *account, } const char * -purple_account_get_alias(const PurpleAccount *account) +purple_account_get_private_alias(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->alias; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->alias; } const char * purple_account_get_user_info(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->user_info; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->user_info; } const char * purple_account_get_buddy_icon_path(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->buddy_icon_path; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->buddy_icon_path; } const char * purple_account_get_protocol_id(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->protocol_id; + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->protocol_id; } const char * @@ -2328,9 +1441,12 @@ purple_account_get_protocol_name(const PurpleAccount *account) PurpleConnection * purple_account_get_connection(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->gc; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->gc; } const gchar * @@ -2340,14 +1456,14 @@ purple_account_get_name_for_display(const PurpleAccount *account) PurpleConnection *gc = NULL; const gchar *name = NULL, *username = NULL, *displayname = NULL; - name = purple_account_get_alias(account); + name = purple_account_get_private_alias(account); if (name) { return name; } username = purple_account_get_username(account); - self = purple_find_buddy((PurpleAccount *)account, username); + self = purple_blist_find_buddy((PurpleAccount *)account, username); if (self) { const gchar *calias= purple_buddy_get_contact_alias(self); @@ -2372,9 +1488,12 @@ purple_account_get_name_for_display(const PurpleAccount *account) gboolean purple_account_get_remember_password(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, FALSE); - return account->remember_pass; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->remember_pass; } gboolean @@ -2397,34 +1516,434 @@ purple_account_get_enabled(const PurpleAccount *account, const char *ui) PurpleProxyInfo * purple_account_get_proxy_info(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->proxy_info; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->proxy_info; } -PurplePrivacyType +PurpleAccountPrivacyType purple_account_get_privacy_type(const PurpleAccount *account) { - g_return_val_if_fail(account != NULL, PURPLE_PRIVACY_ALLOW_ALL); + PurpleAccountPrivate *priv; + + g_return_val_if_fail(account != NULL, PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL); + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->privacy_type; +} + +gboolean +purple_account_privacy_permit_add(PurpleAccount *account, const char *who, + gboolean local_only) +{ + GSList *l; + char *name; + PurpleBuddy *buddy; + PurpleBlistUiOps *blist_ops; + PurpleAccountPrivate *priv; + PurpleAccountUiOps *ui_ops = purple_accounts_get_ui_ops(); + + g_return_val_if_fail(account != NULL, FALSE); + g_return_val_if_fail(who != NULL, FALSE); + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + name = g_strdup(purple_normalize(account, who)); + + for (l = priv->permit; l != NULL; l = l->next) { + if (g_str_equal(name, l->data)) + /* This buddy already exists */ + break; + } + + if (l != NULL) + { + /* This buddy already exists, so bail out */ + g_free(name); + return FALSE; + } + + priv->permit = g_slist_append(priv->permit, name); + + if (!local_only && purple_account_is_connected(account)) + serv_add_permit(purple_account_get_connection(account), who); + + if (ui_ops != NULL && ui_ops->permit_added != NULL) + ui_ops->permit_added(account, who); + + blist_ops = purple_blist_get_ui_ops(); + if (blist_ops != NULL && blist_ops->save_account != NULL) + blist_ops->save_account(account); + + /* This lets the UI know a buddy has had its privacy setting changed */ + buddy = purple_blist_find_buddy(account, name); + if (buddy != NULL) { + purple_signal_emit(purple_blist_get_handle(), + "buddy-privacy-changed", buddy); + } + return TRUE; +} + +gboolean +purple_account_privacy_permit_remove(PurpleAccount *account, const char *who, + gboolean local_only) +{ + GSList *l; + const char *name; + PurpleBuddy *buddy; + char *del; + PurpleBlistUiOps *blist_ops; + PurpleAccountPrivate *priv; + PurpleAccountUiOps *ui_ops = purple_accounts_get_ui_ops(); + + g_return_val_if_fail(account != NULL, FALSE); + g_return_val_if_fail(who != NULL, FALSE); + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + name = purple_normalize(account, who); + + for (l = priv->permit; l != NULL; l = l->next) { + if (g_str_equal(name, l->data)) + /* We found the buddy we were looking for */ + break; + } + + if (l == NULL) + /* We didn't find the buddy we were looking for, so bail out */ + return FALSE; + + /* We should not free l->data just yet. There can be occasions where + * l->data == who. In such cases, freeing l->data here can cause crashes + * later when who is used. */ + del = l->data; + priv->permit = g_slist_delete_link(priv->permit, l); + + if (!local_only && purple_account_is_connected(account)) + serv_rem_permit(purple_account_get_connection(account), who); + + if (ui_ops != NULL && ui_ops->permit_removed != NULL) + ui_ops->permit_removed(account, who); + + blist_ops = purple_blist_get_ui_ops(); + if (blist_ops != NULL && blist_ops->save_account != NULL) + blist_ops->save_account(account); + + buddy = purple_blist_find_buddy(account, name); + if (buddy != NULL) { + purple_signal_emit(purple_blist_get_handle(), + "buddy-privacy-changed", buddy); + } + g_free(del); + return TRUE; +} + +gboolean +purple_account_privacy_deny_add(PurpleAccount *account, const char *who, + gboolean local_only) +{ + GSList *l; + char *name; + PurpleBuddy *buddy; + PurpleBlistUiOps *blist_ops; + PurpleAccountPrivate *priv; + PurpleAccountUiOps *ui_ops = purple_accounts_get_ui_ops(); + + g_return_val_if_fail(account != NULL, FALSE); + g_return_val_if_fail(who != NULL, FALSE); + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + name = g_strdup(purple_normalize(account, who)); + + for (l = priv->deny; l != NULL; l = l->next) { + if (g_str_equal(name, l->data)) + /* This buddy already exists */ + break; + } + + if (l != NULL) + { + /* This buddy already exists, so bail out */ + g_free(name); + return FALSE; + } + + priv->deny = g_slist_append(priv->deny, name); + + if (!local_only && purple_account_is_connected(account)) + serv_add_deny(purple_account_get_connection(account), who); + + if (ui_ops != NULL && ui_ops->deny_added != NULL) + ui_ops->deny_added(account, who); + + blist_ops = purple_blist_get_ui_ops(); + if (blist_ops != NULL && blist_ops->save_account != NULL) + blist_ops->save_account(account); + + buddy = purple_blist_find_buddy(account, name); + if (buddy != NULL) { + purple_signal_emit(purple_blist_get_handle(), + "buddy-privacy-changed", buddy); + } + return TRUE; +} + +gboolean +purple_account_privacy_deny_remove(PurpleAccount *account, const char *who, + gboolean local_only) +{ + GSList *l; + const char *normalized; + char *name; + PurpleBuddy *buddy; + PurpleBlistUiOps *blist_ops; + PurpleAccountPrivate *priv; + PurpleAccountUiOps *ui_ops = purple_accounts_get_ui_ops(); + + g_return_val_if_fail(account != NULL, FALSE); + g_return_val_if_fail(who != NULL, FALSE); + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + normalized = purple_normalize(account, who); + + for (l = priv->deny; l != NULL; l = l->next) { + if (g_str_equal(normalized, l->data)) + /* We found the buddy we were looking for */ + break; + } + + if (l == NULL) + /* We didn't find the buddy we were looking for, so bail out */ + return FALSE; + + buddy = purple_blist_find_buddy(account, normalized); + + name = l->data; + priv->deny = g_slist_delete_link(priv->deny, l); + + if (!local_only && purple_account_is_connected(account)) + serv_rem_deny(purple_account_get_connection(account), name); + + if (ui_ops != NULL && ui_ops->deny_removed != NULL) + ui_ops->deny_removed(account, who); + + if (buddy != NULL) { + purple_signal_emit(purple_blist_get_handle(), + "buddy-privacy-changed", buddy); + } + + g_free(name); + + blist_ops = purple_blist_get_ui_ops(); + if (blist_ops != NULL && blist_ops->save_account != NULL) + blist_ops->save_account(account); + + return TRUE; +} + +/** + * This makes sure your permit list contains all buddies from your + * buddy list and ONLY buddies from your buddy list. + */ +static void +add_all_buddies_to_permit_list(PurpleAccount *account, gboolean local) +{ + GSList *list; + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + /* Remove anyone in the permit list who is not in the buddylist */ + for (list = priv->permit; list != NULL; ) { + char *person = list->data; + list = list->next; + if (!purple_blist_find_buddy(account, person)) + purple_account_privacy_permit_remove(account, person, local); + } + + /* Now make sure everyone in the buddylist is in the permit list */ + list = purple_blist_find_buddies(account, NULL); + while (list != NULL) + { + PurpleBuddy *buddy = list->data; + const gchar *name = purple_buddy_get_name(buddy); + + if (!g_slist_find_custom(priv->permit, name, (GCompareFunc)g_utf8_collate)) + purple_account_privacy_permit_add(account, name, local); + list = g_slist_delete_link(list, list); + } +} + +void +purple_account_privacy_allow(PurpleAccount *account, const char *who) +{ + GSList *list; + PurpleAccountPrivacyType type = purple_account_get_privacy_type(account); + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + switch (type) { + case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL: + return; + case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: + purple_account_privacy_permit_add(account, who, FALSE); + break; + case PURPLE_ACCOUNT_PRIVACY_DENY_USERS: + purple_account_privacy_deny_remove(account, who, FALSE); + break; + case PURPLE_ACCOUNT_PRIVACY_DENY_ALL: + { + /* Empty the allow-list. */ + const char *norm = purple_normalize(account, who); + for (list = priv->permit; list != NULL;) { + char *person = list->data; + list = list->next; + if (!purple_strequal(norm, person)) + purple_account_privacy_permit_remove(account, person, FALSE); + } + purple_account_privacy_permit_add(account, who, FALSE); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS); + } + break; + case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST: + if (!purple_blist_find_buddy(account, who)) { + add_all_buddies_to_permit_list(account, FALSE); + purple_account_privacy_permit_add(account, who, FALSE); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS); + } + break; + default: + g_return_if_reached(); + } + + /* Notify the server if the privacy setting was changed */ + if (type != purple_account_get_privacy_type(account) && purple_account_is_connected(account)) + serv_set_permit_deny(purple_account_get_connection(account)); +} + +void +purple_account_privacy_deny(PurpleAccount *account, const char *who) +{ + GSList *list; + PurpleAccountPrivacyType type = purple_account_get_privacy_type(account); + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + switch (type) { + case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL: + { + /* Empty the deny-list. */ + const char *norm = purple_normalize(account, who); + for (list = priv->deny; list != NULL; ) { + char *person = list->data; + list = list->next; + if (!purple_strequal(norm, person)) + purple_account_privacy_deny_remove(account, person, FALSE); + } + purple_account_privacy_deny_add(account, who, FALSE); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_DENY_USERS); + } + break; + case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: + purple_account_privacy_permit_remove(account, who, FALSE); + break; + case PURPLE_ACCOUNT_PRIVACY_DENY_USERS: + purple_account_privacy_deny_add(account, who, FALSE); + break; + case PURPLE_ACCOUNT_PRIVACY_DENY_ALL: + break; + case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST: + if (purple_blist_find_buddy(account, who)) { + add_all_buddies_to_permit_list(account, FALSE); + purple_account_privacy_permit_remove(account, who, FALSE); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS); + } + break; + default: + g_return_if_reached(); + } + + /* Notify the server if the privacy setting was changed */ + if (type != purple_account_get_privacy_type(account) && purple_account_is_connected(account)) + serv_set_permit_deny(purple_account_get_connection(account)); +} + +GSList * +purple_account_privacy_get_permitted(PurpleAccount *account) +{ + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); - return account->perm_deny; + g_return_val_if_fail(priv != NULL, NULL); + + return priv->permit; +} + +GSList * +purple_account_privacy_get_denied(PurpleAccount *account) +{ + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->deny; +} + +gboolean +purple_account_privacy_check(PurpleAccount *account, const char *who) +{ + GSList *list; + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + switch (purple_account_get_privacy_type(account)) { + case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL: + return TRUE; + + case PURPLE_ACCOUNT_PRIVACY_DENY_ALL: + return FALSE; + + case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: + who = purple_normalize(account, who); + for (list=priv->permit; list!=NULL; list=list->next) { + if (g_str_equal(who, list->data)) + return TRUE; + } + return FALSE; + + case PURPLE_ACCOUNT_PRIVACY_DENY_USERS: + who = purple_normalize(account, who); + for (list=priv->deny; list!=NULL; list=list->next) { + if (g_str_equal(who, list->data)) + return FALSE; + } + return TRUE; + + case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST: + return (purple_blist_find_buddy(account, who) != NULL); + + default: + g_return_val_if_reached(TRUE); + } } PurpleStatus * purple_account_get_active_status(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return purple_presence_get_active_status(account->presence); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return purple_presence_get_active_status(priv->presence); } PurpleStatus * purple_account_get_status(const PurpleAccount *account, const char *status_id) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); g_return_val_if_fail(status_id != NULL, NULL); - return purple_presence_get_status(account->presence, status_id); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + return purple_presence_get_status(priv->presence, status_id); } PurpleStatusType * @@ -2467,27 +1986,37 @@ purple_account_get_status_type_with_primitive(const PurpleAccount *account, Purp PurplePresence * purple_account_get_presence(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->presence; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->presence; } gboolean purple_account_is_status_active(const PurpleAccount *account, const char *status_id) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, FALSE); g_return_val_if_fail(status_id != NULL, FALSE); - return purple_presence_is_status_active(account->presence, status_id); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + return purple_presence_is_status_active(priv->presence, status_id); } GList * purple_account_get_status_types(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->status_types; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->status_types; } int @@ -2495,18 +2024,21 @@ purple_account_get_int(const PurpleAccount *account, const char *name, int default_value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; g_return_val_if_fail(account != NULL, default_value); g_return_val_if_fail(name != NULL, default_value); - setting = g_hash_table_lookup(account->settings, name); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + setting = g_hash_table_lookup(priv->settings, name); if (setting == NULL) return default_value; - g_return_val_if_fail(setting->type == PURPLE_PREF_INT, default_value); + g_return_val_if_fail(G_VALUE_HOLDS_INT(&setting->value), default_value); - return setting->value.integer; + return g_value_get_int(&setting->value); } const char * @@ -2514,18 +2046,21 @@ purple_account_get_string(const PurpleAccount *account, const char *name, const char *default_value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; g_return_val_if_fail(account != NULL, default_value); g_return_val_if_fail(name != NULL, default_value); - setting = g_hash_table_lookup(account->settings, name); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + setting = g_hash_table_lookup(priv->settings, name); if (setting == NULL) return default_value; - g_return_val_if_fail(setting->type == PURPLE_PREF_STRING, default_value); + g_return_val_if_fail(G_VALUE_HOLDS_STRING(&setting->value), default_value); - return setting->value.string; + return g_value_get_string(&setting->value); } gboolean @@ -2533,18 +2068,21 @@ purple_account_get_bool(const PurpleAccount *account, const char *name, gboolean default_value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; g_return_val_if_fail(account != NULL, default_value); g_return_val_if_fail(name != NULL, default_value); - setting = g_hash_table_lookup(account->settings, name); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + setting = g_hash_table_lookup(priv->settings, name); if (setting == NULL) return default_value; - g_return_val_if_fail(setting->type == PURPLE_PREF_BOOLEAN, default_value); + g_return_val_if_fail(G_VALUE_HOLDS_BOOLEAN(&setting->value), default_value); - return setting->value.boolean; + return g_value_get_boolean(&setting->value); } int @@ -2552,21 +2090,24 @@ purple_account_get_ui_int(const PurpleAccount *account, const char *ui, const char *name, int default_value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; GHashTable *table; g_return_val_if_fail(account != NULL, default_value); g_return_val_if_fail(ui != NULL, default_value); g_return_val_if_fail(name != NULL, default_value); - if ((table = g_hash_table_lookup(account->ui_settings, ui)) == NULL) + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if ((table = g_hash_table_lookup(priv->ui_settings, ui)) == NULL) return default_value; if ((setting = g_hash_table_lookup(table, name)) == NULL) return default_value; - g_return_val_if_fail(setting->type == PURPLE_PREF_INT, default_value); + g_return_val_if_fail(G_VALUE_HOLDS_INT(&setting->value), default_value); - return setting->value.integer; + return g_value_get_int(&setting->value); } const char * @@ -2574,21 +2115,24 @@ purple_account_get_ui_string(const PurpleAccount *account, const char *ui, const char *name, const char *default_value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; GHashTable *table; g_return_val_if_fail(account != NULL, default_value); g_return_val_if_fail(ui != NULL, default_value); g_return_val_if_fail(name != NULL, default_value); - if ((table = g_hash_table_lookup(account->ui_settings, ui)) == NULL) + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if ((table = g_hash_table_lookup(priv->ui_settings, ui)) == NULL) return default_value; if ((setting = g_hash_table_lookup(table, name)) == NULL) return default_value; - g_return_val_if_fail(setting->type == PURPLE_PREF_STRING, default_value); + g_return_val_if_fail(G_VALUE_HOLDS_STRING(&setting->value), default_value); - return setting->value.string; + return g_value_get_string(&setting->value); } gboolean @@ -2596,69 +2140,78 @@ purple_account_get_ui_bool(const PurpleAccount *account, const char *ui, const char *name, gboolean default_value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; GHashTable *table; g_return_val_if_fail(account != NULL, default_value); g_return_val_if_fail(ui != NULL, default_value); g_return_val_if_fail(name != NULL, default_value); - if ((table = g_hash_table_lookup(account->ui_settings, ui)) == NULL) + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if ((table = g_hash_table_lookup(priv->ui_settings, ui)) == NULL) return default_value; if ((setting = g_hash_table_lookup(table, name)) == NULL) return default_value; - g_return_val_if_fail(setting->type == PURPLE_PREF_BOOLEAN, default_value); + g_return_val_if_fail(G_VALUE_HOLDS_BOOLEAN(&setting->value), default_value); - return setting->value.boolean; + return g_value_get_boolean(&setting->value); } gpointer purple_account_get_ui_data(const PurpleAccount *account) { - g_return_val_if_fail(account != NULL, NULL); + g_return_val_if_fail(account != NULL, NULL); - return account->ui_data; + return account->ui_data; } void -purple_account_set_ui_data(PurpleAccount *account, - gpointer ui_data) +purple_account_set_ui_data(PurpleAccount *account, gpointer ui_data) { - g_return_if_fail(account != NULL); + g_return_if_fail(account != NULL); - account->ui_data = ui_data; + account->ui_data = ui_data; } - PurpleLog * purple_account_get_log(PurpleAccount *account, gboolean create) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - if(!account->system_log && create){ + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if(!priv->system_log && create){ PurplePresence *presence; int login_time; presence = purple_account_get_presence(account); login_time = purple_presence_get_login_time(presence); - account->system_log = purple_log_new(PURPLE_LOG_SYSTEM, + priv->system_log = purple_log_new(PURPLE_LOG_SYSTEM, purple_account_get_username(account), account, NULL, (login_time != 0) ? login_time : time(NULL), NULL); } - return account->system_log; + return priv->system_log; } void purple_account_destroy_log(PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - if(account->system_log){ - purple_log_free(account->system_log); - account->system_log = NULL; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if(priv->system_log){ + purple_log_free(priv->system_log); + priv->system_log = NULL; } } @@ -2829,45 +2382,27 @@ gboolean purple_account_supports_offline_message(PurpleAccount *account, PurpleB return prpl_info->offline_message(buddy); } -static void -signed_on_cb(PurpleConnection *gc, - gpointer unused) -{ - PurpleAccount *account = purple_connection_get_account(gc); - purple_account_clear_current_error(account); - - purple_signal_emit(purple_accounts_get_handle(), "account-signed-on", - account); -} - -static void -signed_off_cb(PurpleConnection *gc, - gpointer unused) -{ - PurpleAccount *account = purple_connection_get_account(gc); - - purple_signal_emit(purple_accounts_get_handle(), "account-signed-off", - account); -} - -static void -set_current_error(PurpleAccount *account, PurpleConnectionErrorInfo *new_err) +void +_purple_account_set_current_error(PurpleAccount *account, + PurpleConnectionErrorInfo *new_err) { PurpleConnectionErrorInfo *old_err; + PurpleAccountPrivate *priv; g_return_if_fail(account != NULL); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); - old_err = account->current_error; + old_err = priv->current_error; if(new_err == old_err) return; - account->current_error = new_err; + priv->current_error = new_err; purple_signal_emit(purple_accounts_get_handle(), "account-error-changed", account, old_err, new_err); - schedule_accounts_save(); + purple_accounts_schedule_save(); if(old_err) g_free(old_err->description); @@ -2876,435 +2411,733 @@ set_current_error(PurpleAccount *account, PurpleConnectionErrorInfo *new_err) g_free(old_err); } -static void -connection_error_cb(PurpleConnection *gc, - PurpleConnectionError type, - const gchar *description, - gpointer unused) +const PurpleConnectionErrorInfo * +purple_account_get_current_error(PurpleAccount *account) { - PurpleAccount *account; - PurpleConnectionErrorInfo *err; + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); - account = purple_connection_get_account(gc); + return priv->current_error; +} - g_return_if_fail(account != NULL); +void +purple_account_clear_current_error(PurpleAccount *account) +{ + _purple_account_set_current_error(account, NULL); +} + +static xmlnode * +status_attribute_to_xmlnode(const PurpleStatus *status, const PurpleStatusType *type, + const PurpleStatusAttribute *attr) +{ + xmlnode *node; + const char *id; + char *value = NULL; + PurpleStatusAttribute *default_attr; + GValue *default_value; + GType attr_type; + GValue *attr_value; + + id = purple_status_attribute_get_id(attr); + g_return_val_if_fail(id, NULL); + + attr_value = purple_status_get_attr_value(status, id); + g_return_val_if_fail(attr_value, NULL); + attr_type = G_VALUE_TYPE(attr_value); + + /* + * If attr_value is a different type than it should be + * then don't write it to the file. + */ + default_attr = purple_status_type_get_attr(type, id); + default_value = purple_status_attribute_get_value(default_attr); + if (attr_type != G_VALUE_TYPE(default_value)) + return NULL; + + /* + * If attr_value is the same as the default for this status + * then there is no need to write it to the file. + */ + if (attr_type == G_TYPE_STRING) + { + const char *string_value = g_value_get_string(attr_value); + const char *default_string_value = g_value_get_string(default_value); + if (purple_strequal(string_value, default_string_value)) + return NULL; + value = g_strdup(g_value_get_string(attr_value)); + } + else if (attr_type == G_TYPE_INT) + { + int int_value = g_value_get_int(attr_value); + if (int_value == g_value_get_int(default_value)) + return NULL; + value = g_strdup_printf("%d", int_value); + } + else if (attr_type == G_TYPE_BOOLEAN) + { + gboolean boolean_value = g_value_get_boolean(attr_value); + if (boolean_value == g_value_get_boolean(default_value)) + return NULL; + value = g_strdup(boolean_value ? + "true" : "false"); + } + else + { + return NULL; + } - err = g_new0(PurpleConnectionErrorInfo, 1); - PURPLE_DBUS_REGISTER_POINTER(err, PurpleConnectionErrorInfo); + g_return_val_if_fail(value, NULL); - err->type = type; - err->description = g_strdup(description); + node = xmlnode_new("attribute"); + + xmlnode_set_attrib(node, "id", id); + xmlnode_set_attrib(node, "value", value); - set_current_error(account, err); + g_free(value); - purple_signal_emit(purple_accounts_get_handle(), "account-connection-error", - account, type, description); + return node; } -static void -password_migration_cb(PurpleAccount *account) +static xmlnode * +status_attrs_to_xmlnode(const PurpleStatus *status) { - /* account may be NULL (means: all) */ + PurpleStatusType *type = purple_status_get_status_type(status); + xmlnode *node, *child; + GList *attrs, *attr; + + node = xmlnode_new("attributes"); - schedule_accounts_save(); + attrs = purple_status_type_get_attrs(type); + for (attr = attrs; attr != NULL; attr = attr->next) + { + child = status_attribute_to_xmlnode(status, type, (const PurpleStatusAttribute *)attr->data); + if (child) + xmlnode_insert_child(node, child); + } + + return node; } -const PurpleConnectionErrorInfo * -purple_account_get_current_error(PurpleAccount *account) +static xmlnode * +status_to_xmlnode(const PurpleStatus *status) { - return account->current_error; + xmlnode *node, *child; + + node = xmlnode_new("status"); + xmlnode_set_attrib(node, "type", purple_status_get_id(status)); + if (purple_status_get_name(status) != NULL) + xmlnode_set_attrib(node, "name", purple_status_get_name(status)); + xmlnode_set_attrib(node, "active", purple_status_is_active(status) ? "true" : "false"); + + child = status_attrs_to_xmlnode(status); + xmlnode_insert_child(node, child); + + return node; } -void -purple_account_clear_current_error(PurpleAccount *account) +static xmlnode * +statuses_to_xmlnode(const PurplePresence *presence) { - set_current_error(account, NULL); + xmlnode *node, *child; + GList *statuses; + PurpleStatus *status; + + node = xmlnode_new("statuses"); + + statuses = purple_presence_get_statuses(presence); + for (; statuses != NULL; statuses = statuses->next) + { + status = statuses->data; + if (purple_status_type_is_saveable(purple_status_get_status_type(status))) + { + child = status_to_xmlnode(status); + xmlnode_insert_child(node, child); + } + } + + return node; } -void -purple_accounts_add(PurpleAccount *account) +static xmlnode * +proxy_settings_to_xmlnode(PurpleProxyInfo *proxy_info) { - g_return_if_fail(account != NULL); + xmlnode *node, *child; + PurpleProxyType proxy_type; + const char *value; + int int_value; + char buf[21]; - if (g_list_find(accounts, account) != NULL) - return; + proxy_type = purple_proxy_info_get_type(proxy_info); - accounts = g_list_append(accounts, account); + node = xmlnode_new("proxy"); - schedule_accounts_save(); + child = xmlnode_new_child(node, "type"); + xmlnode_insert_data(child, + (proxy_type == PURPLE_PROXY_USE_GLOBAL ? "global" : + proxy_type == PURPLE_PROXY_NONE ? "none" : + proxy_type == PURPLE_PROXY_HTTP ? "http" : + proxy_type == PURPLE_PROXY_SOCKS4 ? "socks4" : + proxy_type == PURPLE_PROXY_SOCKS5 ? "socks5" : + proxy_type == PURPLE_PROXY_TOR ? "tor" : + proxy_type == PURPLE_PROXY_USE_ENVVAR ? "envvar" : "unknown"), -1); + + if ((value = purple_proxy_info_get_host(proxy_info)) != NULL) + { + child = xmlnode_new_child(node, "host"); + xmlnode_insert_data(child, value, -1); + } - purple_signal_emit(purple_accounts_get_handle(), "account-added", account); + if ((int_value = purple_proxy_info_get_port(proxy_info)) != 0) + { + g_snprintf(buf, sizeof(buf), "%d", int_value); + child = xmlnode_new_child(node, "port"); + xmlnode_insert_data(child, buf, -1); + } + + if ((value = purple_proxy_info_get_username(proxy_info)) != NULL) + { + child = xmlnode_new_child(node, "username"); + xmlnode_insert_data(child, value, -1); + } + + if ((value = purple_proxy_info_get_password(proxy_info)) != NULL) + { + child = xmlnode_new_child(node, "password"); + xmlnode_insert_data(child, value, -1); + } + + return node; } -void -purple_accounts_remove(PurpleAccount *account) +static xmlnode * +current_error_to_xmlnode(PurpleConnectionErrorInfo *err) { - g_return_if_fail(account != NULL); + xmlnode *node, *child; + char type_str[3]; - accounts = g_list_remove(accounts, account); + node = xmlnode_new("current_error"); - schedule_accounts_save(); + if(err == NULL) + return node; - /* Clearing the error ensures that account-error-changed is emitted, - * which is the end of the guarantee that the the error's pointer is - * valid. + /* It doesn't make sense to have transient errors persist across a + * restart. */ - purple_account_clear_current_error(account); - purple_signal_emit(purple_accounts_get_handle(), "account-removed", account); + if(!purple_connection_error_is_fatal (err->type)) + return node; + + child = xmlnode_new_child(node, "type"); + g_snprintf(type_str, sizeof(type_str), "%u", err->type); + xmlnode_insert_data(child, type_str, -1); + + child = xmlnode_new_child(node, "description"); + if(err->description) { + char *utf8ized = purple_utf8_try_convert(err->description); + if(utf8ized == NULL) + utf8ized = purple_utf8_salvage(err->description); + xmlnode_insert_data(child, utf8ized, -1); + g_free(utf8ized); + } + + return node; } static void -purple_accounts_delete_set(PurpleAccount *account, GError *error, gpointer data) +setting_to_xmlnode(gpointer key, gpointer value, gpointer user_data) { - purple_account_destroy(account); + const char *name; + PurpleAccountSetting *setting; + xmlnode *node, *child; + char buf[21]; + + name = (const char *)key; + setting = (PurpleAccountSetting *)value; + node = (xmlnode *)user_data; + + child = xmlnode_new_child(node, "setting"); + xmlnode_set_attrib(child, "name", name); + + if (G_VALUE_HOLDS_INT(&setting->value)) { + xmlnode_set_attrib(child, "type", "int"); + g_snprintf(buf, sizeof(buf), "%d", g_value_get_int(&setting->value)); + xmlnode_insert_data(child, buf, -1); + } + else if (G_VALUE_HOLDS_STRING(&setting->value) && g_value_get_string(&setting->value) != NULL) { + xmlnode_set_attrib(child, "type", "string"); + xmlnode_insert_data(child, g_value_get_string(&setting->value), -1); + } + else if (G_VALUE_HOLDS_BOOLEAN(&setting->value)) { + xmlnode_set_attrib(child, "type", "bool"); + g_snprintf(buf, sizeof(buf), "%d", g_value_get_boolean(&setting->value)); + xmlnode_insert_data(child, buf, -1); + } } -void -purple_accounts_delete(PurpleAccount *account) +static void +ui_setting_to_xmlnode(gpointer key, gpointer value, gpointer user_data) { - PurpleBlistNode *gnode, *cnode, *bnode; - GList *iter; + const char *ui; + GHashTable *table; + xmlnode *node, *child; - g_return_if_fail(account != NULL); + ui = (const char *)key; + table = (GHashTable *)value; + node = (xmlnode *)user_data; - /* - * Disable the account before blowing it out of the water. - * Conceptually it probably makes more sense to disable the - * account for all UIs rather than the just the current UI, - * but it doesn't really matter. - */ - purple_account_set_enabled(account, purple_core_get_ui(), FALSE); + if (g_hash_table_size(table) > 0) + { + child = xmlnode_new_child(node, "settings"); + xmlnode_set_attrib(child, "ui", ui); + g_hash_table_foreach(table, setting_to_xmlnode, child); + } +} - purple_notify_close_with_handle(account); - purple_request_close_with_handle(account); +xmlnode * +purple_account_to_xmlnode(PurpleAccount *account) +{ + xmlnode *node, *child; + const char *tmp; + PurplePresence *presence; + PurpleProxyInfo *proxy_info; + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + node = xmlnode_new("account"); + + child = xmlnode_new_child(node, "protocol"); + xmlnode_insert_data(child, purple_account_get_protocol_id(account), -1); - purple_accounts_remove(account); + child = xmlnode_new_child(node, "name"); + xmlnode_insert_data(child, purple_account_get_username(account), -1); - /* Remove this account's buddies */ - for (gnode = purple_blist_get_root(); - gnode != NULL; - gnode = purple_blist_node_get_sibling_next(gnode)) + if (purple_account_get_remember_password(account)) { - if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) - continue; + const char *keyring_id = NULL; + const char *mode = NULL; + char *data = NULL; + GError *error = NULL; + GDestroyNotify destroy = NULL; + gboolean exported = purple_keyring_export_password(account, + &keyring_id, &mode, &data, &error, &destroy); + + if (error != NULL) { + purple_debug_error("account", + "Failed to export password for account %s: %s.\n", + purple_account_get_username(account), + error->message); + } else if (exported) { + child = xmlnode_new_child(node, "password"); + if (keyring_id != NULL) + xmlnode_set_attrib(child, "keyring_id", keyring_id); + if (mode != NULL) + xmlnode_set_attrib(child, "mode", mode); + if (data != NULL) + xmlnode_insert_data(child, data, -1); + + if (destroy != NULL) + destroy(data); + } + } - cnode = purple_blist_node_get_first_child(gnode); - while (cnode) { - PurpleBlistNode *cnode_next = purple_blist_node_get_sibling_next(cnode); + if ((tmp = purple_account_get_private_alias(account)) != NULL) + { + child = xmlnode_new_child(node, "alias"); + xmlnode_insert_data(child, tmp, -1); + } - if(PURPLE_BLIST_NODE_IS_CONTACT(cnode)) { - bnode = purple_blist_node_get_first_child(cnode); - while (bnode) { - PurpleBlistNode *bnode_next = purple_blist_node_get_sibling_next(bnode); + if ((presence = purple_account_get_presence(account)) != NULL) + { + child = statuses_to_xmlnode(presence); + xmlnode_insert_child(node, child); + } - if (PURPLE_BLIST_NODE_IS_BUDDY(bnode)) { - PurpleBuddy *b = (PurpleBuddy *)bnode; + if ((tmp = purple_account_get_user_info(account)) != NULL) + { + /* TODO: Do we need to call purple_str_strip_char(tmp, '\r') here? */ + child = xmlnode_new_child(node, "userinfo"); + xmlnode_insert_data(child, tmp, -1); + } - if (purple_buddy_get_account(b) == account) - purple_blist_remove_buddy(b); - } - bnode = bnode_next; - } - } else if (PURPLE_BLIST_NODE_IS_CHAT(cnode)) { - PurpleChat *c = (PurpleChat *)cnode; + if (g_hash_table_size(priv->settings) > 0) + { + child = xmlnode_new_child(node, "settings"); + g_hash_table_foreach(priv->settings, setting_to_xmlnode, child); + } - if (purple_chat_get_account(c) == account) - purple_blist_remove_chat(c); - } - cnode = cnode_next; - } + if (g_hash_table_size(priv->ui_settings) > 0) + { + g_hash_table_foreach(priv->ui_settings, ui_setting_to_xmlnode, node); } - /* Remove any open conversation for this account */ - for (iter = purple_get_conversations(); iter; ) { - PurpleConversation *conv = iter->data; - iter = iter->next; - if (purple_conversation_get_account(conv) == account) - purple_conversation_destroy(conv); + if ((proxy_info = purple_account_get_proxy_info(account)) != NULL) + { + child = proxy_settings_to_xmlnode(proxy_info); + xmlnode_insert_child(node, child); } - /* Remove this account's pounces */ - purple_pounce_destroy_all_by_account(account); + child = current_error_to_xmlnode(priv->current_error); + xmlnode_insert_child(node, child); - /* This will cause the deletion of an old buddy icon. */ - purple_buddy_icons_set_account_icon(account, NULL, 0); + return node; +} - /* This is async because we do not want the - * account being overwritten before we are done. - */ - purple_keyring_set_password(account, NULL, - purple_accounts_delete_set, NULL); +/**************** + * GObject Code * + ****************/ + +/* GObject Property names */ +#define PROP_USERNAME_S "username" +#define PROP_PRIVATE_ALIAS_S "private-alias" +#define PROP_ENABLED_S "enabled" +#define PROP_CONNECTION_S "connection" +#define PROP_PROTOCOL_ID_S "protocol-id" +#define PROP_USER_INFO_S "userinfo" +#define PROP_BUDDY_ICON_PATH_S "buddy-icon-path" +#define PROP_REMEMBER_PASSWORD_S "remember-password" +#define PROP_CHECK_MAIL_S "check-mail" + +/* Set method for GObject properties */ +static void +purple_account_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleAccount *account = PURPLE_ACCOUNT(obj); + + switch (param_id) { + case PROP_USERNAME: + purple_account_set_username(account, g_value_get_string(value)); + break; + case PROP_PRIVATE_ALIAS: + purple_account_set_private_alias(account, g_value_get_string(value)); + break; + case PROP_ENABLED: + purple_account_set_enabled(account, purple_core_get_ui(), + g_value_get_boolean(value)); + break; + case PROP_CONNECTION: + purple_account_set_connection(account, g_value_get_object(value)); + break; + case PROP_PROTOCOL_ID: + purple_account_set_protocol_id(account, g_value_get_string(value)); + break; + case PROP_USER_INFO: + purple_account_set_user_info(account, g_value_get_string(value)); + break; + case PROP_BUDDY_ICON_PATH: + purple_account_set_buddy_icon_path(account, + g_value_get_string(value)); + break; + case PROP_REMEMBER_PASSWORD: + purple_account_set_remember_password(account, + g_value_get_boolean(value)); + break; + case PROP_CHECK_MAIL: + purple_account_set_check_mail(account, g_value_get_boolean(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_account_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleAccount *account = PURPLE_ACCOUNT(obj); + + switch (param_id) { + case PROP_USERNAME: + g_value_set_string(value, purple_account_get_username(account)); + break; + case PROP_PRIVATE_ALIAS: + g_value_set_string(value, purple_account_get_private_alias(account)); + break; + case PROP_ENABLED: + g_value_set_boolean(value, purple_account_get_enabled(account, + purple_core_get_ui())); + break; + case PROP_CONNECTION: + g_value_set_object(value, purple_account_get_connection(account)); + break; + case PROP_PROTOCOL_ID: + g_value_set_string(value, purple_account_get_protocol_id(account)); + break; + case PROP_USER_INFO: + g_value_set_string(value, purple_account_get_user_info(account)); + break; + case PROP_BUDDY_ICON_PATH: + g_value_set_string(value, + purple_account_get_buddy_icon_path(account)); + break; + case PROP_REMEMBER_PASSWORD: + g_value_set_boolean(value, + purple_account_get_remember_password(account)); + break; + case PROP_CHECK_MAIL: + g_value_set_boolean(value, purple_account_get_check_mail(account)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* GObject initialization function */ +static void purple_account_init(GTypeInstance *instance, gpointer klass) +{ + PurpleAccount *account = PURPLE_ACCOUNT(instance); + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + priv->settings = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, delete_setting); + priv->ui_settings = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, (GDestroyNotify)g_hash_table_destroy); + priv->system_log = NULL; + + priv->privacy_type = PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL; + + PURPLE_DBUS_REGISTER_POINTER(account, PurpleAccount); } -void -purple_accounts_reorder(PurpleAccount *account, guint new_index) +/* Called when done constructing */ +static void +purple_account_constructed(GObject *object) { - gint index; - GList *l; + PurpleAccount *account = PURPLE_ACCOUNT(object); + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + gchar *username, *protocol_id; + PurplePlugin *prpl = NULL; + PurplePluginProtocolInfo *prpl_info = NULL; + PurpleStatusType *status_type; - g_return_if_fail(account != NULL); - g_return_if_fail(new_index <= g_list_length(accounts)); + parent_class->constructed(object); - index = g_list_index(accounts, account); + g_object_get(object, + PROP_USERNAME_S, &username, + PROP_PROTOCOL_ID_S, &protocol_id, + NULL); - if (index < 0) { - purple_debug_error("account", - "Unregistered account (%s) discovered during reorder!\n", - purple_account_get_username(account)); + purple_signal_emit(purple_accounts_get_handle(), "account-created", + account); + + prpl = purple_find_prpl(protocol_id); + if (prpl == NULL) { + g_free(username); + g_free(protocol_id); return; } - l = g_list_nth(accounts, index); - - if (new_index > (guint)index) - new_index--; - - /* Remove the old one. */ - accounts = g_list_delete_link(accounts, l); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + if (prpl_info != NULL && prpl_info->status_types != NULL) + purple_account_set_status_types(account, + prpl_info->status_types(account)); - /* Insert it where it should go. */ - accounts = g_list_insert(accounts, account, new_index); + priv->presence = PURPLE_PRESENCE(purple_account_presence_new(account)); - schedule_accounts_save(); -} + status_type = purple_account_get_status_type_with_primitive(account, + PURPLE_STATUS_AVAILABLE); + if (status_type != NULL) + purple_presence_set_status_active(priv->presence, + purple_status_type_get_id(status_type), + TRUE); + else + purple_presence_set_status_active(priv->presence, + "offline", + TRUE); -GList * -purple_accounts_get_all(void) -{ - return accounts; + g_free(username); + g_free(protocol_id); } -GList * -purple_accounts_get_all_active(void) +/* GObject dispose function */ +static void +purple_account_dispose(GObject *object) { - GList *list = NULL; - GList *all = purple_accounts_get_all(); + GList *l; + PurpleAccount *account = PURPLE_ACCOUNT(object); + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); - while (all != NULL) { - PurpleAccount *account = all->data; + purple_debug_info("account", "Destroying account %p\n", account); + purple_signal_emit(purple_accounts_get_handle(), "account-destroying", + account); - if (purple_account_get_enabled(account, purple_core_get_ui())) - list = g_list_append(list, account); + for (l = purple_conversations_get_all(); l != NULL; l = l->next) + { + PurpleConversation *conv = (PurpleConversation *)l->data; - all = all->next; + if (purple_conversation_get_account(conv) == account) + purple_conversation_set_account(conv, NULL); } - return list; -} + purple_account_set_status_types(account, NULL); -PurpleAccount * -purple_accounts_find(const char *name, const char *protocol_id) -{ - PurpleAccount *account = NULL; - GList *l; - char *who; + if (priv->proxy_info) + purple_proxy_info_destroy(priv->proxy_info); - g_return_val_if_fail(name != NULL, NULL); - g_return_val_if_fail(protocol_id != NULL, NULL); + if (priv->presence) + g_object_unref(priv->presence); - for (l = purple_accounts_get_all(); l != NULL; l = l->next) { - account = (PurpleAccount *)l->data; - if (!purple_strequal(account->protocol_id, protocol_id)) - continue; + if(priv->system_log) + purple_log_free(priv->system_log); - who = g_strdup(purple_normalize(account, name)); - if (purple_strequal(purple_normalize(account, purple_account_get_username(account)), who)) { - g_free(who); - return account; - } - g_free(who); + if (priv->current_error) { + g_free(priv->current_error->description); + g_free(priv->current_error); } - return NULL; + PURPLE_DBUS_UNREGISTER_POINTER(priv->current_error); + PURPLE_DBUS_UNREGISTER_POINTER(account); + + parent_class->dispose(object); } -void -purple_accounts_restore_current_statuses() +/* GObject finalize function */ +static void +purple_account_finalize(GObject *object) { - GList *l; - PurpleAccount *account; + PurpleAccount *account = PURPLE_ACCOUNT(object); + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); - /* If we're not connected to the Internet right now, we bail on this */ - if (!purple_network_is_available()) - { - purple_debug_warning("account", "Network not connected; skipping reconnect\n"); - return; + g_free(priv->username); + g_free(priv->alias); + purple_str_wipe(priv->password); + g_free(priv->user_info); + g_free(priv->buddy_icon_path); + g_free(priv->protocol_id); + + g_hash_table_destroy(priv->settings); + g_hash_table_destroy(priv->ui_settings); + + while (priv->deny) { + g_free(priv->deny->data); + priv->deny = g_slist_delete_link(priv->deny, priv->deny); } - for (l = purple_accounts_get_all(); l != NULL; l = l->next) - { - account = (PurpleAccount *)l->data; - if (purple_account_get_enabled(account, purple_core_get_ui()) && - (purple_presence_is_online(account->presence))) - { - purple_account_connect(account); - } + while (priv->permit) { + g_free(priv->permit->data); + priv->permit = g_slist_delete_link(priv->permit, priv->permit); } -} -void -purple_accounts_set_ui_ops(PurpleAccountUiOps *ops) -{ - account_ui_ops = ops; + parent_class->finalize(object); } -PurpleAccountUiOps * -purple_accounts_get_ui_ops(void) -{ - return account_ui_ops; +/* Class initializer function */ +static void +purple_account_class_init(PurpleAccountClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->dispose = purple_account_dispose; + obj_class->finalize = purple_account_finalize; + obj_class->constructed = purple_account_constructed; + + /* Setup properties */ + obj_class->get_property = purple_account_get_property; + obj_class->set_property = purple_account_set_property; + + g_object_class_install_property(obj_class, PROP_USERNAME, + g_param_spec_string(PROP_USERNAME_S, _("Username"), + _("The username for the account."), NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_object_class_install_property(obj_class, PROP_PRIVATE_ALIAS, + g_param_spec_string(PROP_PRIVATE_ALIAS_S, _("Private Alias"), + _("The private alias for the account."), NULL, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PROP_USER_INFO, + g_param_spec_string(PROP_USER_INFO_S, _("User information"), + _("Detailed user information for the account."), NULL, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PROP_BUDDY_ICON_PATH, + g_param_spec_string(PROP_BUDDY_ICON_PATH_S, _("Buddy icon path"), + _("Path to the buddyicon for the account."), NULL, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PROP_ENABLED, + g_param_spec_boolean(PROP_ENABLED_S, _("Enabled"), + _("Whether the account is enabled or not."), FALSE, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PROP_REMEMBER_PASSWORD, + g_param_spec_boolean(PROP_REMEMBER_PASSWORD_S, _("Remember password"), + _("Whether to remember and store the password for this account."), FALSE, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PROP_CHECK_MAIL, + g_param_spec_boolean(PROP_CHECK_MAIL_S, _("Check mail"), + _("Whether to check mails for this account."), FALSE, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PROP_CONNECTION, + g_param_spec_object(PROP_CONNECTION_S, _("Connection"), + _("The connection for the account."), PURPLE_TYPE_CONNECTION, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PROP_PROTOCOL_ID, + g_param_spec_string(PROP_PROTOCOL_ID_S, _("Protocol ID"), + _("ID of the protocol that is responsible for the account."), NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY) + ); + + g_type_class_add_private(klass, sizeof(PurpleAccountPrivate)); +} + +GType +purple_account_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleAccountClass), + NULL, + NULL, + (GClassInitFunc)purple_account_class_init, + NULL, + NULL, + sizeof(PurpleAccount), + 0, + (GInstanceInitFunc)purple_account_init, + NULL, + }; + + type = g_type_register_static(G_TYPE_OBJECT, + "PurpleAccount", + &info, 0); + } + + return type; } -void * -purple_accounts_get_handle(void) +PurpleAccount * +purple_account_new(const char *username, const char *protocol_id) { - static int handle; - - return &handle; -} + PurpleAccount *account; -void -purple_accounts_init(void) -{ - void *handle = purple_accounts_get_handle(); - void *conn_handle = purple_connections_get_handle(); - - purple_signal_register(handle, "account-connecting", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-disabled", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-enabled", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-setting-info", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "account-set-info", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "account-created", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-destroying", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-added", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-removed", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-status-changed", - purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_STATUS), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_STATUS)); - - purple_signal_register(handle, "account-actions-changed", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-alias-changed", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "account-authorization-requested", - purple_marshal_INT__POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_INT), 4, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "account-authorization-denied", - purple_marshal_VOID__POINTER_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "account-authorization-granted", - purple_marshal_VOID__POINTER_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "account-error-changed", - purple_marshal_VOID__POINTER_POINTER_POINTER, - NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_POINTER), - purple_value_new(PURPLE_TYPE_POINTER)); - - purple_signal_register(handle, "account-signed-on", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-signed-off", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-connection-error", - purple_marshal_VOID__POINTER_INT_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_ENUM), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_connect(conn_handle, "signed-on", handle, - PURPLE_CALLBACK(signed_on_cb), NULL); - purple_signal_connect(conn_handle, "signed-off", handle, - PURPLE_CALLBACK(signed_off_cb), NULL); - purple_signal_connect(conn_handle, "connection-error", handle, - PURPLE_CALLBACK(connection_error_cb), NULL); - purple_signal_connect(purple_keyring_get_handle(), "password-migration", handle, - PURPLE_CALLBACK(password_migration_cb), NULL); - - load_accounts(); + g_return_val_if_fail(username != NULL, NULL); + g_return_val_if_fail(protocol_id != NULL, NULL); -} + account = purple_accounts_find(username, protocol_id); -void -purple_accounts_uninit(void) -{ - gpointer handle = purple_accounts_get_handle(); - if (save_timer != 0) - { - purple_timeout_remove(save_timer); - save_timer = 0; - sync_accounts(); - } + if (account != NULL) + return account; - for (; accounts; accounts = g_list_delete_link(accounts, accounts)) - purple_account_destroy(accounts->data); + account = g_object_new(PURPLE_TYPE_ACCOUNT, + PROP_USERNAME_S, username, + PROP_PROTOCOL_ID_S, protocol_id, + NULL); - purple_signals_disconnect_by_handle(handle); - purple_signals_unregister_by_instance(handle); + return account; } diff --git a/libpurple/account.h b/libpurple/account.h index b1b689d4b2..4cdb7ef6a0 100644 --- a/libpurple/account.h +++ b/libpurple/account.h @@ -1,7 +1,6 @@ /** * @file account.h Account API * @ingroup core - * @see @ref account-signals */ /* purple @@ -30,10 +29,17 @@ #include <glib.h> #include <glib-object.h> -/** @copydoc _PurpleAccountUiOps */ -typedef struct _PurpleAccountUiOps PurpleAccountUiOps; +#define PURPLE_TYPE_ACCOUNT (purple_account_get_type()) +#define PURPLE_ACCOUNT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_ACCOUNT, PurpleAccount)) +#define PURPLE_ACCOUNT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_ACCOUNT, PurpleAccountClass)) +#define PURPLE_IS_ACCOUNT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_ACCOUNT)) +#define PURPLE_IS_ACCOUNT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_ACCOUNT)) +#define PURPLE_ACCOUNT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_ACCOUNT, PurpleAccountClass)) + /** @copydoc _PurpleAccount */ -typedef struct _PurpleAccount PurpleAccount; +typedef struct _PurpleAccount PurpleAccount; +/** @copydoc _PurpleAccountClass */ +typedef struct _PurpleAccountClass PurpleAccountClass; typedef gboolean (*PurpleFilterAccountFunc)(PurpleAccount *account); typedef void (*PurpleAccountRequestAuthorizationCb)(const char *, void *); @@ -46,11 +52,11 @@ typedef void (*PurpleGetPublicAliasFailureCallback)(PurpleAccount *account, cons #include "connection.h" #include "log.h" -#include "privacy.h" #include "proxy.h" #include "prpl.h" #include "status.h" #include "keyring.h" +#include "xmlnode.h" /** * Account request types. @@ -71,106 +77,45 @@ typedef enum PURPLE_ACCOUNT_RESPONSE_ACCEPT = 1 } PurpleAccountRequestResponse; -/** Account UI operations, used to notify the user of status changes and when - * buddies add this account to their buddy lists. +/** + * Privacy data types. */ -struct _PurpleAccountUiOps +typedef enum { - /** A buddy who is already on this account's buddy list added this account - * to their buddy list. - */ - void (*notify_added)(PurpleAccount *account, - const char *remote_user, - const char *id, - const char *alias, - const char *message); - - /** This account's status changed. */ - void (*status_changed)(PurpleAccount *account, - PurpleStatus *status); - - /** Someone we don't have on our list added us; prompt to add them. */ - void (*request_add)(PurpleAccount *account, - const char *remote_user, - const char *id, - const char *alias, - const char *message); - - /** Prompt for authorization when someone adds this account to their buddy - * list. To authorize them to see this account's presence, call \a - * authorize_cb (\a message, \a user_data); otherwise call - * \a deny_cb (\a message, \a user_data); - * @return a UI-specific handle, as passed to #close_account_request. - */ - void *(*request_authorize)(PurpleAccount *account, - const char *remote_user, - const char *id, - const char *alias, - const char *message, - gboolean on_list, - PurpleAccountRequestAuthorizationCb authorize_cb, - PurpleAccountRequestAuthorizationCb deny_cb, - void *user_data); - - /** Close a pending request for authorization. \a ui_handle is a handle - * as returned by #request_authorize. - */ - void (*close_account_request)(void *ui_handle); + PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL = 1, + PURPLE_ACCOUNT_PRIVACY_DENY_ALL, + PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS, + PURPLE_ACCOUNT_PRIVACY_DENY_USERS, + PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST +} PurpleAccountPrivacyType; - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -/** Structure representing an account. +/** + * Structure representing an account. */ struct _PurpleAccount { - char *username; /**< The username. */ - char *alias; /**< How you appear to yourself. */ - char *password; /**< The account password. */ - char *user_info; /**< User information. */ - - char *buddy_icon_path; /**< The buddy icon's non-cached path. */ - - gboolean remember_pass; /**< Remember the password. */ - - char *protocol_id; /**< The ID of the protocol. */ + /*< private >*/ + GObject gparent; - PurpleConnection *gc; /**< The connection handle. */ - gboolean disconnecting; /**< The account is currently disconnecting */ - - GHashTable *settings; /**< Protocol-specific settings. */ - GHashTable *ui_settings; /**< UI-specific settings. */ - - PurpleProxyInfo *proxy_info; /**< Proxy information. This will be set */ - /* to NULL when the account inherits */ - /* proxy settings from global prefs. */ - - /* - * TODO: Supplementing the next two linked lists with hash tables - * should help performance a lot when these lists are long. This - * matters quite a bit for protocols like MSN, where all your - * buddies are added to your permit list. Currently we have to - * iterate through the entire list if we want to check if someone - * is permitted or denied. We should do this for 3.0.0. - * Or maybe use a GTree. + /** The UI data associated with this account. This is a convenience + * field provided to the UIs -- it is not used by the libpurple core. */ - GSList *permit; /**< Permit list. */ - GSList *deny; /**< Deny list. */ - PurplePrivacyType perm_deny; /**< The permit/deny setting. */ - - GList *status_types; /**< Status types. */ - - PurplePresence *presence; /**< Presence. */ - PurpleLog *system_log; /**< The system log */ + gpointer ui_data; +}; - void *ui_data; /**< The UI can put data here. */ - PurpleAccountRegistrationCb registration_cb; - void *registration_cb_user_data; +/** + * PurpleAccountClass: + * + * The base class for all #PurpleAccount's. + */ +struct _PurpleAccountClass { + /*< private >*/ + GObjectClass parent_class; - PurpleConnectionErrorInfo *current_error; /**< Errors */ + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); }; G_BEGIN_DECLS @@ -181,6 +126,11 @@ G_BEGIN_DECLS /*@{*/ /** + * Returns the GType for the Account object. + */ +GType purple_account_get_type(void); + +/** * Creates a new account. * * @param username The username. @@ -191,13 +141,6 @@ G_BEGIN_DECLS PurpleAccount *purple_account_new(const char *username, const char *protocol_id); /** - * Destroys an account. - * - * @param account The account to destroy. - */ -void purple_account_destroy(PurpleAccount *account); - -/** * Connects to an account. * * @param account The account to connect to. @@ -379,12 +322,12 @@ void purple_account_set_password(PurpleAccount *account, const gchar *password, PurpleKeyringSaveCallback cb, gpointer data); /** - * Sets the account's alias. + * Sets the account's private alias. * * @param account The account. * @param alias The alias. */ -void purple_account_set_alias(PurpleAccount *account, const char *alias); +void purple_account_set_private_alias(PurpleAccount *account, const char *alias); /** * Sets the account's user information @@ -460,7 +403,7 @@ void purple_account_set_proxy_info(PurpleAccount *account, PurpleProxyInfo *info * @param account The account. * @param privacy_type The privacy type. */ -void purple_account_set_privacy_type(PurpleAccount *account, PurplePrivacyType privacy_type); +void purple_account_set_privacy_type(PurpleAccount *account, PurpleAccountPrivacyType privacy_type); /** * Sets the account's status types. @@ -629,23 +572,23 @@ void purple_account_set_ui_bool(PurpleAccount *account, const char *ui, const char *name, gboolean value); /** - * Returns the UI data associated with this account. + * Set the UI data associated with this account. * * @param account The account. - * - * @return The UI data associated with this object. This is a - * convenience field provided to the UIs--it is not - * used by the libuprple core. + * @param ui_data A pointer to associate with this object. */ -gpointer purple_account_get_ui_data(const PurpleAccount *account); +void purple_account_set_ui_data(PurpleAccount *account, gpointer ui_data); /** - * Set the UI data associated with this account. + * Returns the UI data associated with this account. * * @param account The account. - * @param ui_data A pointer to associate with this object. + * + * @return The UI data associated with this account. This is a + * convenience field provided to the UIs--it is not + * used by the libuprple core. */ -void purple_account_set_ui_data(PurpleAccount *account, gpointer ui_data); +gpointer purple_account_get_ui_data(const PurpleAccount *account); /** * Returns whether or not the account is connected. @@ -699,13 +642,13 @@ void purple_account_get_password(PurpleAccount *account, PurpleKeyringReadCallback cb, gpointer data); /** - * Returns the account's alias. + * Returns the account's private alias. * * @param account The account. * * @return The alias. */ -const char *purple_account_get_alias(const PurpleAccount *account); +const char *purple_account_get_private_alias(const PurpleAccount *account); /** * Returns the account's user information. @@ -810,7 +753,135 @@ PurpleProxyInfo *purple_account_get_proxy_info(const PurpleAccount *account); * * @return The privacy type. */ -PurplePrivacyType purple_account_get_privacy_type(const PurpleAccount *account); +PurpleAccountPrivacyType purple_account_get_privacy_type(const PurpleAccount *account); + +/** + * Adds a user to the account's permit list. + * + * @param account The account. + * @param name The name of the user to add to the list. + * @param local_only If TRUE, only the local list is updated, and not + * the server. + * + * @return TRUE if the user was added successfully, or @c FALSE otherwise. + */ +gboolean purple_account_privacy_permit_add(PurpleAccount *account, + const char *name, gboolean local_only); + +/** + * Removes a user from the account's permit list. + * + * @param account The account. + * @param name The name of the user to add to the list. + * @param local_only If TRUE, only the local list is updated, and not + * the server. + * + * @return TRUE if the user was removed successfully, or @c FALSE otherwise. + */ +gboolean purple_account_privacy_permit_remove(PurpleAccount *account, + const char *name, gboolean local_only); + +/** + * Adds a user to the account's deny list. + * + * @param account The account. + * @param name The name of the user to add to the list. + * @param local_only If TRUE, only the local list is updated, and not + * the server. + * + * @return TRUE if the user was added successfully, or @c FALSE otherwise. + */ +gboolean purple_account_privacy_deny_add(PurpleAccount *account, + const char *name, gboolean local_only); + +/** + * Removes a user from the account's deny list. + * + * @param account The account. + * @param name The name of the user to add to the list. + * @param local_only If TRUE, only the local list is updated, and not + * the server. + * + * @return TRUE if the user was removed successfully, or @c FALSE otherwise. + */ +gboolean purple_account_privacy_deny_remove(PurpleAccount *account, + const char *name, gboolean local_only); + +/** + * Allow a user to send messages. If current privacy setting for the account is: + * PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: The user is added to the allow-list. + * PURPLE_ACCOUNT_PRIVACY_DENY_USERS : The user is removed from the + * deny-list. + * PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL : No changes made. + * PURPLE_ACCOUNT_PRIVACY_DENY_ALL : The privacy setting is changed to + * PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS and the + * user is added to the allow-list. + * PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST: No changes made if the user is + * already in the buddy-list. Otherwise the + * setting is changed to + * PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS, all the buddies are added to the + * allow-list, and the user is also added to + * the allow-list. + * + * The changes are reflected on the server. The previous allow/deny list is not + * restored if the privacy setting is changed. + * + * @param account The account. + * @param who The name of the user. + */ +void purple_account_privacy_allow(PurpleAccount *account, const char *who); + +/** + * Block messages from a user. If current privacy setting for the account is: + * PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: The user is removed from the + * allow-list. + * PURPLE_ACCOUNT_PRIVACY_DENY_USERS: The user is added to the deny-list. + * PURPLE_ACCOUNT_PRIVACY_DENY_ALL: No changes made. + * PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL: The privacy setting is changed to + * PURPLE_ACCOUNT_PRIVACY_DENY_USERS and the + * user is added to the deny-list. + * PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST: If the user is not in the + * buddy-list, then no changes made. Otherwise, + * the setting is changed to + * PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS, all + * the buddies are added to the allow-list, and + * this user is removed from the list. + * + * The changes are reflected on the server. The previous allow/deny list is not + * restored if the privacy setting is changed. + * + * @param account The account. + * @param who The name of the user. + */ +void purple_account_privacy_deny(PurpleAccount *account, const char *who); + +/** + * Returns the account's permit list. + * + * @param account The account. + * @constreturn A list of the permitted users + */ +GSList *purple_account_privacy_get_permitted(PurpleAccount *account); + +/** + * Returns the account's deny list. + * + * @param account The account. + * @constreturn A list of the denied users + */ +GSList *purple_account_privacy_get_denied(PurpleAccount *account); + +/** + * Check the privacy-setting for a user. + * + * @param account The account. + * @param who The name of the user. + * + * @return @c FALSE if the specified account's privacy settings block the user + * or @c TRUE otherwise. The meaning of "block" is protocol-dependent and + * generally relates to status and/or sending of messages. + */ +gboolean purple_account_privacy_check(PurpleAccount *account, const char *who); /** * Returns the active status for this account. This looks through @@ -1080,128 +1151,13 @@ const PurpleConnectionErrorInfo *purple_account_get_current_error(PurpleAccount */ void purple_account_clear_current_error(PurpleAccount *account); -/*@}*/ - -/**************************************************************************/ -/** @name Accounts API */ -/**************************************************************************/ -/*@{*/ - -/** - * Adds an account to the list of accounts. - * - * @param account The account. - */ -void purple_accounts_add(PurpleAccount *account); - -/** - * Removes an account from the list of accounts. - * - * @param account The account. - */ -void purple_accounts_remove(PurpleAccount *account); - -/** - * Deletes an account. - * - * This will remove any buddies from the buddy list that belong to this - * account, buddy pounces that belong to this account, and will also - * destroy @a account. - * - * @param account The account. - */ -void purple_accounts_delete(PurpleAccount *account); - -/** - * Reorders an account. - * - * @param account The account to reorder. - * @param new_index The new index for the account. - */ -void purple_accounts_reorder(PurpleAccount *account, guint new_index); - -/** - * Returns a list of all accounts. - * - * @constreturn A list of all accounts. - */ -GList *purple_accounts_get_all(void); - -/** - * Returns a list of all enabled accounts - * - * @return A list of all enabled accounts. The list is owned - * by the caller, and must be g_list_free()d to avoid - * leaking the nodes. - */ -GList *purple_accounts_get_all_active(void); - /** - * Finds an account with the specified name and protocol id. - * - * @param name The account username. - * @param protocol The account protocol ID. + * Get an XML description of an account. * - * @return The account, if found, or @c FALSE otherwise. - */ -PurpleAccount *purple_accounts_find(const char *name, const char *protocol); - -/** - * This is called by the core after all subsystems and what - * not have been initialized. It sets all enabled accounts - * to their startup status by signing them on, setting them - * away, etc. - * - * You probably shouldn't call this unless you really know - * what you're doing. - */ -void purple_accounts_restore_current_statuses(void); - -/*@}*/ - - -/**************************************************************************/ -/** @name UI Registration Functions */ -/**************************************************************************/ -/*@{*/ -/** - * Sets the UI operations structure to be used for accounts. - * - * @param ops The UI operations structure. - */ -void purple_accounts_set_ui_ops(PurpleAccountUiOps *ops); - -/** - * Returns the UI operations structure used for accounts. - * - * @return The UI operations structure in use. - */ -PurpleAccountUiOps *purple_accounts_get_ui_ops(void); - -/*@}*/ - - -/**************************************************************************/ -/** @name Accounts Subsystem */ -/**************************************************************************/ -/*@{*/ - -/** - * Returns the accounts subsystem handle. - * - * @return The accounts subsystem handle. - */ -void *purple_accounts_get_handle(void); - -/** - * Initializes the accounts subsystem. - */ -void purple_accounts_init(void); - -/** - * Uninitializes the accounts subsystem. + * @param account The account + * @return The XML description of the account. */ -void purple_accounts_uninit(void); +xmlnode *purple_account_to_xmlnode(PurpleAccount *account); /*@}*/ diff --git a/libpurple/accounts.c b/libpurple/accounts.c new file mode 100644 index 0000000000..a8a852f7c7 --- /dev/null +++ b/libpurple/accounts.c @@ -0,0 +1,1022 @@ +/** + * @file accounts.c Accounts API + * @ingroup core + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#include "internal.h" +#include "accounts.h" +#include "core.h" +#include "dbus-maybe.h" +#include "debug.h" +#include "enums.h" +#include "network.h" +#include "pounce.h" + +static PurpleAccountUiOps *account_ui_ops = NULL; + +static GList *accounts = NULL; +static guint save_timer = 0; +static gboolean accounts_loaded = FALSE; + +void _purple_account_set_current_error(PurpleAccount *account, + PurpleConnectionErrorInfo *new_err); + +/********************************************************************* + * Writing to disk * + *********************************************************************/ +static xmlnode * +accounts_to_xmlnode(void) +{ + xmlnode *node, *child; + GList *cur; + + node = xmlnode_new("account"); + xmlnode_set_attrib(node, "version", "1.0"); + + for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next) + { + child = purple_account_to_xmlnode(cur->data); + xmlnode_insert_child(node, child); + } + + return node; +} + +static void +sync_accounts(void) +{ + xmlnode *node; + char *data; + + if (!accounts_loaded) + { + purple_debug_error("account", "Attempted to save accounts before " + "they were read!\n"); + return; + } + + node = accounts_to_xmlnode(); + data = xmlnode_to_formatted_str(node, NULL); + purple_util_write_data_to_file("accounts.xml", data, -1); + g_free(data); + xmlnode_free(node); +} + +static gboolean +save_cb(gpointer data) +{ + sync_accounts(); + save_timer = 0; + return FALSE; +} + +void +purple_accounts_schedule_save(void) +{ + if (save_timer == 0) + save_timer = purple_timeout_add_seconds(5, save_cb, NULL); +} + +/********************************************************************* + * Reading from disk * + *********************************************************************/ +static void +migrate_yahoo_japan(PurpleAccount *account) +{ + /* detect a Yahoo! JAPAN account that existed prior to 2.6.0 and convert it + * to use the new prpl-yahoojp. Also remove the account-specific settings + * we no longer need */ + + if(purple_strequal(purple_account_get_protocol_id(account), "prpl-yahoo")) { + if(purple_account_get_bool(account, "yahoojp", FALSE)) { + const char *serverjp = purple_account_get_string(account, "serverjp", NULL); + const char *xferjp_host = purple_account_get_string(account, "xferjp_host", NULL); + + g_return_if_fail(serverjp != NULL); + g_return_if_fail(xferjp_host != NULL); + + purple_account_set_string(account, "server", serverjp); + purple_account_set_string(account, "xfer_host", xferjp_host); + + purple_account_set_protocol_id(account, "prpl-yahoojp"); + } + + /* these should always be nuked */ + purple_account_remove_setting(account, "yahoojp"); + purple_account_remove_setting(account, "serverjp"); + purple_account_remove_setting(account, "xferjp_host"); + + } +} + +static void +migrate_icq_server(PurpleAccount *account) +{ + /* Migrate the login server setting for ICQ accounts. See + * 'mtn log --last 1 --no-graph --from b6d7712e90b68610df3bd2d8cbaf46d94c8b3794' + * for details on the change. */ + + if(purple_strequal(purple_account_get_protocol_id(account), "prpl-icq")) { + const char *tmp = purple_account_get_string(account, "server", NULL); + + /* Non-secure server */ + if(purple_strequal(tmp, "login.messaging.aol.com") || + purple_strequal(tmp, "login.oscar.aol.com")) + purple_account_set_string(account, "server", "login.icq.com"); + + /* Secure server */ + if(purple_strequal(tmp, "slogin.oscar.aol.com")) + purple_account_set_string(account, "server", "slogin.icq.com"); + } +} + +static void +migrate_xmpp_encryption(PurpleAccount *account) +{ + /* When this is removed, nuke the "old_ssl" and "require_tls" settings */ + if (g_str_equal(purple_account_get_protocol_id(account), "prpl-jabber")) { + const char *sec = purple_account_get_string(account, "connection_security", ""); + + if (g_str_equal("", sec)) { + const char *val = "require_tls"; + if (purple_account_get_bool(account, "old_ssl", FALSE)) + val = "old_ssl"; + else if (!purple_account_get_bool(account, "require_tls", TRUE)) + val = "opportunistic_tls"; + + purple_account_set_string(account, "connection_security", val); + } + } +} + +static void +parse_settings(xmlnode *node, PurpleAccount *account) +{ + const char *ui; + xmlnode *child; + + /* Get the UI string, if these are UI settings */ + ui = xmlnode_get_attrib(node, "ui"); + + /* Read settings, one by one */ + for (child = xmlnode_get_child(node, "setting"); child != NULL; + child = xmlnode_get_next_twin(child)) + { + const char *name, *str_type; + PurplePrefType type; + char *data; + + name = xmlnode_get_attrib(child, "name"); + if (name == NULL) + /* Ignore this setting */ + continue; + + str_type = xmlnode_get_attrib(child, "type"); + if (str_type == NULL) + /* Ignore this setting */ + continue; + + if (purple_strequal(str_type, "string")) + type = PURPLE_PREF_STRING; + else if (purple_strequal(str_type, "int")) + type = PURPLE_PREF_INT; + else if (purple_strequal(str_type, "bool")) + type = PURPLE_PREF_BOOLEAN; + else + /* Ignore this setting */ + continue; + + data = xmlnode_get_data(child); + if (data == NULL) + /* Ignore this setting */ + continue; + + if (ui == NULL) + { + if (type == PURPLE_PREF_STRING) + purple_account_set_string(account, name, data); + else if (type == PURPLE_PREF_INT) + purple_account_set_int(account, name, atoi(data)); + else if (type == PURPLE_PREF_BOOLEAN) + purple_account_set_bool(account, name, + (*data == '0' ? FALSE : TRUE)); + } else { + if (type == PURPLE_PREF_STRING) + purple_account_set_ui_string(account, ui, name, data); + else if (type == PURPLE_PREF_INT) + purple_account_set_ui_int(account, ui, name, atoi(data)); + else if (type == PURPLE_PREF_BOOLEAN) + purple_account_set_ui_bool(account, ui, name, + (*data == '0' ? FALSE : TRUE)); + } + + g_free(data); + } + + /* we do this here because we need access to account settings to determine + * if we can/should migrate an old Yahoo! JAPAN account */ + migrate_yahoo_japan(account); + /* we do this here because we need access to account settings to determine + * if we can/should migrate an ICQ account's server setting */ + migrate_icq_server(account); + /* we do this here because we need to do it before the user views the + * Edit Account dialog. */ + migrate_xmpp_encryption(account); +} + +static GList * +parse_status_attrs(xmlnode *node, PurpleStatus *status) +{ + GList *list = NULL; + xmlnode *child; + GValue *attr_value; + + for (child = xmlnode_get_child(node, "attribute"); child != NULL; + child = xmlnode_get_next_twin(child)) + { + const char *id = xmlnode_get_attrib(child, "id"); + const char *value = xmlnode_get_attrib(child, "value"); + + if (!id || !*id || !value || !*value) + continue; + + attr_value = purple_status_get_attr_value(status, id); + if (!attr_value) + continue; + + list = g_list_append(list, (char *)id); + + switch (G_VALUE_TYPE(attr_value)) + { + case G_TYPE_STRING: + list = g_list_append(list, (char *)value); + break; + case G_TYPE_INT: + case G_TYPE_BOOLEAN: + { + int v; + if (sscanf(value, "%d", &v) == 1) + list = g_list_append(list, GINT_TO_POINTER(v)); + else + list = g_list_remove(list, id); + break; + } + default: + break; + } + } + + return list; +} + +static void +parse_status(xmlnode *node, PurpleAccount *account) +{ + gboolean active = FALSE; + const char *data; + const char *type; + xmlnode *child; + GList *attrs = NULL; + + /* Get the active/inactive state */ + data = xmlnode_get_attrib(node, "active"); + if (data == NULL) + return; + if (g_ascii_strcasecmp(data, "true") == 0) + active = TRUE; + else if (g_ascii_strcasecmp(data, "false") == 0) + active = FALSE; + else + return; + + /* Get the type of the status */ + type = xmlnode_get_attrib(node, "type"); + if (type == NULL) + return; + + /* Read attributes into a GList */ + child = xmlnode_get_child(node, "attributes"); + if (child != NULL) + { + attrs = parse_status_attrs(child, + purple_account_get_status(account, type)); + } + + purple_account_set_status_list(account, type, active, attrs); + + g_list_free(attrs); +} + +static void +parse_statuses(xmlnode *node, PurpleAccount *account) +{ + xmlnode *child; + + for (child = xmlnode_get_child(node, "status"); child != NULL; + child = xmlnode_get_next_twin(child)) + { + parse_status(child, account); + } +} + +static void +parse_proxy_info(xmlnode *node, PurpleAccount *account) +{ + PurpleProxyInfo *proxy_info; + xmlnode *child; + char *data; + + proxy_info = purple_proxy_info_new(); + + /* Use the global proxy settings, by default */ + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_USE_GLOBAL); + + /* Read proxy type */ + child = xmlnode_get_child(node, "type"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + if (purple_strequal(data, "global")) + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_USE_GLOBAL); + else if (purple_strequal(data, "none")) + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_NONE); + else if (purple_strequal(data, "http")) + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_HTTP); + else if (purple_strequal(data, "socks4")) + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_SOCKS4); + else if (purple_strequal(data, "socks5")) + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_SOCKS5); + else if (purple_strequal(data, "tor")) + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_TOR); + else if (purple_strequal(data, "envvar")) + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_USE_ENVVAR); + else + { + purple_debug_error("account", "Invalid proxy type found when " + "loading account information for %s\n", + purple_account_get_username(account)); + } + g_free(data); + } + + /* Read proxy host */ + child = xmlnode_get_child(node, "host"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + purple_proxy_info_set_host(proxy_info, data); + g_free(data); + } + + /* Read proxy port */ + child = xmlnode_get_child(node, "port"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + purple_proxy_info_set_port(proxy_info, atoi(data)); + g_free(data); + } + + /* Read proxy username */ + child = xmlnode_get_child(node, "username"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + purple_proxy_info_set_username(proxy_info, data); + g_free(data); + } + + /* Read proxy password */ + child = xmlnode_get_child(node, "password"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + purple_proxy_info_set_password(proxy_info, data); + g_free(data); + } + + /* If there are no values set then proxy_info NULL */ + if ((purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_USE_GLOBAL) && + (purple_proxy_info_get_host(proxy_info) == NULL) && + (purple_proxy_info_get_port(proxy_info) == 0) && + (purple_proxy_info_get_username(proxy_info) == NULL) && + (purple_proxy_info_get_password(proxy_info) == NULL)) + { + purple_proxy_info_destroy(proxy_info); + return; + } + + purple_account_set_proxy_info(account, proxy_info); +} + +static void +parse_current_error(xmlnode *node, PurpleAccount *account) +{ + guint type; + char *type_str = NULL, *description = NULL; + xmlnode *child; + PurpleConnectionErrorInfo *current_error = NULL; + + child = xmlnode_get_child(node, "type"); + if (child == NULL || (type_str = xmlnode_get_data(child)) == NULL) + return; + type = atoi(type_str); + g_free(type_str); + + if (type > PURPLE_CONNECTION_ERROR_OTHER_ERROR) + { + purple_debug_error("account", + "Invalid PurpleConnectionError value %d found when " + "loading account information for %s\n", + type, purple_account_get_username(account)); + type = PURPLE_CONNECTION_ERROR_OTHER_ERROR; + } + + child = xmlnode_get_child(node, "description"); + if (child) + description = xmlnode_get_data(child); + if (description == NULL) + description = g_strdup(""); + + current_error = g_new0(PurpleConnectionErrorInfo, 1); + PURPLE_DBUS_REGISTER_POINTER(current_error, PurpleConnectionErrorInfo); + current_error->type = type; + current_error->description = description; + + _purple_account_set_current_error(account, current_error); +} + +static PurpleAccount * +parse_account(xmlnode *node) +{ + PurpleAccount *ret; + xmlnode *child; + char *protocol_id = NULL; + char *name = NULL; + char *data; + + child = xmlnode_get_child(node, "protocol"); + if (child != NULL) + protocol_id = xmlnode_get_data(child); + + child = xmlnode_get_child(node, "name"); + if (child != NULL) + name = xmlnode_get_data(child); + if (name == NULL) + { + /* Do we really need to do this? */ + child = xmlnode_get_child(node, "username"); + if (child != NULL) + name = xmlnode_get_data(child); + } + + if ((protocol_id == NULL) || (name == NULL)) + { + g_free(protocol_id); + g_free(name); + return NULL; + } + + ret = purple_account_new(name, protocol_id); + g_free(name); + g_free(protocol_id); + + /* Read the alias */ + child = xmlnode_get_child(node, "alias"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + if (*data != '\0') + purple_account_set_private_alias(ret, data); + g_free(data); + } + + /* Read the statuses */ + child = xmlnode_get_child(node, "statuses"); + if (child != NULL) + { + parse_statuses(child, ret); + } + + /* Read the userinfo */ + child = xmlnode_get_child(node, "userinfo"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + purple_account_set_user_info(ret, data); + g_free(data); + } + + /* Read an old buddyicon */ + child = xmlnode_get_child(node, "buddyicon"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + const char *dirname = purple_buddy_icons_get_cache_dir(); + char *filename = g_build_filename(dirname, data, NULL); + gchar *contents; + gsize len; + + if (g_file_get_contents(filename, &contents, &len, NULL)) + { + purple_buddy_icons_set_account_icon(ret, (guchar *)contents, len); + } + + g_free(filename); + g_free(data); + } + + /* Read settings (both core and UI) */ + for (child = xmlnode_get_child(node, "settings"); child != NULL; + child = xmlnode_get_next_twin(child)) + { + parse_settings(child, ret); + } + + /* Read proxy */ + child = xmlnode_get_child(node, "proxy"); + if (child != NULL) + { + parse_proxy_info(child, ret); + } + + /* Read current error */ + child = xmlnode_get_child(node, "current_error"); + if (child != NULL) + { + parse_current_error(child, ret); + } + + /* Read the password */ + child = xmlnode_get_child(node, "password"); + if (child != NULL) + { + const char *keyring_id = xmlnode_get_attrib(child, "keyring_id"); + const char *mode = xmlnode_get_attrib(child, "mode"); + gboolean result; + + data = xmlnode_get_data(child); + result = purple_keyring_import_password(ret, keyring_id, mode, data, NULL); + + if (result == TRUE || purple_keyring_get_inuse() == NULL) { + purple_account_set_remember_password(ret, TRUE); + } else { + purple_debug_error("account", "Failed to import password.\n"); + } + purple_str_wipe(data); + } + + return ret; +} + +static void +load_accounts(void) +{ + xmlnode *node, *child; + + accounts_loaded = TRUE; + + node = purple_util_read_xml_from_file("accounts.xml", _("accounts")); + + if (node == NULL) + return; + + for (child = xmlnode_get_child(node, "account"); child != NULL; + child = xmlnode_get_next_twin(child)) + { + PurpleAccount *new_acct; + new_acct = parse_account(child); + purple_accounts_add(new_acct); + } + + xmlnode_free(node); + + _purple_buddy_icons_account_loaded_cb(); +} + +void +purple_accounts_add(PurpleAccount *account) +{ + g_return_if_fail(account != NULL); + + if (g_list_find(accounts, account) != NULL) + return; + + accounts = g_list_append(accounts, account); + + purple_accounts_schedule_save(); + + purple_signal_emit(purple_accounts_get_handle(), "account-added", account); +} + +void +purple_accounts_remove(PurpleAccount *account) +{ + g_return_if_fail(account != NULL); + + accounts = g_list_remove(accounts, account); + + purple_accounts_schedule_save(); + + /* Clearing the error ensures that account-error-changed is emitted, + * which is the end of the guarantee that the the error's pointer is + * valid. + */ + purple_account_clear_current_error(account); + purple_signal_emit(purple_accounts_get_handle(), "account-removed", account); +} + +static void +purple_accounts_delete_set(PurpleAccount *account, GError *error, gpointer data) +{ + g_object_unref(G_OBJECT(account)); +} + +void +purple_accounts_delete(PurpleAccount *account) +{ + PurpleBlistNode *gnode, *cnode, *bnode; + GList *iter; + + g_return_if_fail(account != NULL); + + /* + * Disable the account before blowing it out of the water. + * Conceptually it probably makes more sense to disable the + * account for all UIs rather than the just the current UI, + * but it doesn't really matter. + */ + purple_account_set_enabled(account, purple_core_get_ui(), FALSE); + + purple_notify_close_with_handle(account); + purple_request_close_with_handle(account); + + purple_accounts_remove(account); + + /* Remove this account's buddies */ + for (gnode = purple_blist_get_root(); + gnode != NULL; + gnode = purple_blist_node_get_sibling_next(gnode)) + { + if (!PURPLE_IS_GROUP(gnode)) + continue; + + cnode = purple_blist_node_get_first_child(gnode); + while (cnode) { + PurpleBlistNode *cnode_next = purple_blist_node_get_sibling_next(cnode); + + if(PURPLE_IS_CONTACT(cnode)) { + bnode = purple_blist_node_get_first_child(cnode); + while (bnode) { + PurpleBlistNode *bnode_next = purple_blist_node_get_sibling_next(bnode); + + if (PURPLE_IS_BUDDY(bnode)) { + PurpleBuddy *b = (PurpleBuddy *)bnode; + + if (purple_buddy_get_account(b) == account) + purple_blist_remove_buddy(b); + } + bnode = bnode_next; + } + } else if (PURPLE_IS_CHAT(cnode)) { + PurpleChat *c = (PurpleChat *)cnode; + + if (purple_chat_get_account(c) == account) + purple_blist_remove_chat(c); + } + cnode = cnode_next; + } + } + + /* Remove any open conversation for this account */ + for (iter = purple_conversations_get_all(); iter; ) { + PurpleConversation *conv = iter->data; + iter = iter->next; + if (purple_conversation_get_account(conv) == account) + g_object_unref(conv); + } + + /* Remove this account's pounces */ + purple_pounce_destroy_all_by_account(account); + + /* This will cause the deletion of an old buddy icon. */ + purple_buddy_icons_set_account_icon(account, NULL, 0); + + /* This is async because we do not want the + * account being overwritten before we are done. + */ + purple_keyring_set_password(account, NULL, + purple_accounts_delete_set, NULL); +} + +void +purple_accounts_reorder(PurpleAccount *account, guint new_index) +{ + gint index; + GList *l; + + g_return_if_fail(account != NULL); + g_return_if_fail(new_index <= g_list_length(accounts)); + + index = g_list_index(accounts, account); + + if (index < 0) { + purple_debug_error("account", + "Unregistered account (%s) discovered during reorder!\n", + purple_account_get_username(account)); + return; + } + + l = g_list_nth(accounts, index); + + if (new_index > (guint)index) + new_index--; + + /* Remove the old one. */ + accounts = g_list_delete_link(accounts, l); + + /* Insert it where it should go. */ + accounts = g_list_insert(accounts, account, new_index); + + purple_accounts_schedule_save(); +} + +GList * +purple_accounts_get_all(void) +{ + return accounts; +} + +GList * +purple_accounts_get_all_active(void) +{ + GList *list = NULL; + GList *all = purple_accounts_get_all(); + + while (all != NULL) { + PurpleAccount *account = all->data; + + if (purple_account_get_enabled(account, purple_core_get_ui())) + list = g_list_append(list, account); + + all = all->next; + } + + return list; +} + +PurpleAccount * +purple_accounts_find(const char *name, const char *protocol_id) +{ + PurpleAccount *account = NULL; + GList *l; + char *who; + + g_return_val_if_fail(name != NULL, NULL); + g_return_val_if_fail(protocol_id != NULL, NULL); + + for (l = purple_accounts_get_all(); l != NULL; l = l->next) { + account = (PurpleAccount *)l->data; + + if (!purple_strequal(purple_account_get_protocol_id(account), protocol_id)) + continue; + + who = g_strdup(purple_normalize(account, name)); + if (purple_strequal(purple_normalize(account, purple_account_get_username(account)), who)) { + g_free(who); + return account; + } + g_free(who); + } + + return NULL; +} + +void +purple_accounts_restore_current_statuses() +{ + GList *l; + PurpleAccount *account; + + /* If we're not connected to the Internet right now, we bail on this */ + if (!purple_network_is_available()) + { + purple_debug_warning("account", "Network not connected; skipping reconnect\n"); + return; + } + + for (l = purple_accounts_get_all(); l != NULL; l = l->next) + { + account = (PurpleAccount *)l->data; + + if (purple_account_get_enabled(account, purple_core_get_ui()) && + (purple_presence_is_online(purple_account_get_presence(account)))) + { + purple_account_connect(account); + } + } +} + +void +purple_accounts_set_ui_ops(PurpleAccountUiOps *ops) +{ + account_ui_ops = ops; +} + +PurpleAccountUiOps * +purple_accounts_get_ui_ops(void) +{ + return account_ui_ops; +} + +void * +purple_accounts_get_handle(void) +{ + static int handle; + + return &handle; +} + +static void +signed_on_cb(PurpleConnection *gc, + gpointer unused) +{ + PurpleAccount *account = purple_connection_get_account(gc); + purple_account_clear_current_error(account); + + purple_signal_emit(purple_accounts_get_handle(), "account-signed-on", + account); +} + +static void +signed_off_cb(PurpleConnection *gc, + gpointer unused) +{ + PurpleAccount *account = purple_connection_get_account(gc); + + purple_signal_emit(purple_accounts_get_handle(), "account-signed-off", + account); +} + +static void +connection_error_cb(PurpleConnection *gc, + PurpleConnectionError type, + const gchar *description, + gpointer unused) +{ + PurpleAccount *account; + PurpleConnectionErrorInfo *err; + + account = purple_connection_get_account(gc); + + g_return_if_fail(account != NULL); + + err = g_new0(PurpleConnectionErrorInfo, 1); + PURPLE_DBUS_REGISTER_POINTER(err, PurpleConnectionErrorInfo); + + err->type = type; + err->description = g_strdup(description); + + _purple_account_set_current_error(account, err); + + purple_signal_emit(purple_accounts_get_handle(), "account-connection-error", + account, type, description); +} + +static void +password_migration_cb(PurpleAccount *account) +{ + /* account may be NULL (means: all) */ + + purple_accounts_schedule_save(); +} + +void +purple_accounts_init(void) +{ + void *handle = purple_accounts_get_handle(); + void *conn_handle = purple_connections_get_handle(); + + purple_signal_register(handle, "account-connecting", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_ACCOUNT); + + purple_signal_register(handle, "account-disabled", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_ACCOUNT); + + purple_signal_register(handle, "account-enabled", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_ACCOUNT); + + purple_signal_register(handle, "account-setting-info", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_ACCOUNT, G_TYPE_STRING); + + purple_signal_register(handle, "account-set-info", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_ACCOUNT, G_TYPE_STRING); + + purple_signal_register(handle, "account-created", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_ACCOUNT); + + purple_signal_register(handle, "account-destroying", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_ACCOUNT); + + purple_signal_register(handle, "account-added", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_ACCOUNT); + + purple_signal_register(handle, "account-removed", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_ACCOUNT); + + purple_signal_register(handle, "account-status-changed", + purple_marshal_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, PURPLE_TYPE_ACCOUNT, + PURPLE_TYPE_STATUS, PURPLE_TYPE_STATUS); + + purple_signal_register(handle, "account-actions-changed", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_ACCOUNT); + + purple_signal_register(handle, "account-alias-changed", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_ACCOUNT, G_TYPE_STRING); + + purple_signal_register(handle, "account-authorization-requested", + purple_marshal_INT__POINTER_POINTER_POINTER, + G_TYPE_INT, 4, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING); + + purple_signal_register(handle, "account-authorization-denied", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 3, + PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, G_TYPE_STRING); + + purple_signal_register(handle, "account-authorization-granted", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 3, + PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, G_TYPE_STRING); + + purple_signal_register(handle, "account-error-changed", + purple_marshal_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, PURPLE_TYPE_ACCOUNT, + PURPLE_TYPE_CONNECTION_ERROR_INFO, + PURPLE_TYPE_CONNECTION_ERROR_INFO); + + purple_signal_register(handle, "account-signed-on", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_ACCOUNT); + + purple_signal_register(handle, "account-signed-off", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_ACCOUNT); + + purple_signal_register(handle, "account-connection-error", + purple_marshal_VOID__POINTER_INT_POINTER, + G_TYPE_NONE, 3, PURPLE_TYPE_ACCOUNT, + PURPLE_TYPE_CONNECTION_ERROR, G_TYPE_STRING); + + purple_signal_connect(conn_handle, "signed-on", handle, + PURPLE_CALLBACK(signed_on_cb), NULL); + purple_signal_connect(conn_handle, "signed-off", handle, + PURPLE_CALLBACK(signed_off_cb), NULL); + purple_signal_connect(conn_handle, "connection-error", handle, + PURPLE_CALLBACK(connection_error_cb), NULL); + purple_signal_connect(purple_keyring_get_handle(), "password-migration", handle, + PURPLE_CALLBACK(password_migration_cb), NULL); + + load_accounts(); + +} + +void +purple_accounts_uninit(void) +{ + gpointer handle = purple_accounts_get_handle(); + if (save_timer != 0) + { + purple_timeout_remove(save_timer); + save_timer = 0; + sync_accounts(); + } + + for (; accounts; accounts = g_list_delete_link(accounts, accounts)) + g_object_unref(G_OBJECT(accounts->data)); + + purple_signals_disconnect_by_handle(handle); + purple_signals_unregister_by_instance(handle); +} diff --git a/libpurple/accounts.h b/libpurple/accounts.h new file mode 100644 index 0000000000..82e1ced0a4 --- /dev/null +++ b/libpurple/accounts.h @@ -0,0 +1,225 @@ +/** + * @file accounts.h Accounts API + * @ingroup core + * @see @ref account-signals + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef _PURPLE_ACCOUNTS_H_ +#define _PURPLE_ACCOUNTS_H_ + +#include "account.h" +#include "status.h" + +/** @copydoc _PurpleAccountUiOps */ +typedef struct _PurpleAccountUiOps PurpleAccountUiOps; + +/** Account UI operations, used to notify the user of status changes and when + * buddies add this account to their buddy lists. + */ +struct _PurpleAccountUiOps +{ + /** A buddy who is already on this account's buddy list added this account + * to their buddy list. + */ + void (*notify_added)(PurpleAccount *account, + const char *remote_user, + const char *id, + const char *alias, + const char *message); + + /** This account's status changed. */ + void (*status_changed)(PurpleAccount *account, + PurpleStatus *status); + + /** Someone we don't have on our list added us; prompt to add them. */ + void (*request_add)(PurpleAccount *account, + const char *remote_user, + const char *id, + const char *alias, + const char *message); + + /** Prompt for authorization when someone adds this account to their buddy + * list. To authorize them to see this account's presence, call \a + * authorize_cb (\a message, \a user_data); otherwise call + * \a deny_cb (\a message, \a user_data); + * @return a UI-specific handle, as passed to #close_account_request. + */ + void *(*request_authorize)(PurpleAccount *account, + const char *remote_user, + const char *id, + const char *alias, + const char *message, + gboolean on_list, + PurpleAccountRequestAuthorizationCb authorize_cb, + PurpleAccountRequestAuthorizationCb deny_cb, + void *user_data); + + /** Close a pending request for authorization. \a ui_handle is a handle + * as returned by #request_authorize. + */ + void (*close_account_request)(void *ui_handle); + + void (*permit_added)(PurpleAccount *account, const char *name); + void (*permit_removed)(PurpleAccount *account, const char *name); + void (*deny_added)(PurpleAccount *account, const char *name); + void (*deny_removed)(PurpleAccount *account, const char *name); + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +/**************************************************************************/ +/** @name Accounts API */ +/**************************************************************************/ +/*@{*/ + +/** + * Adds an account to the list of accounts. + * + * @param account The account. + */ +void purple_accounts_add(PurpleAccount *account); + +/** + * Removes an account from the list of accounts. + * + * @param account The account. + */ +void purple_accounts_remove(PurpleAccount *account); + +/** + * Deletes an account. + * + * This will remove any buddies from the buddy list that belong to this + * account, buddy pounces that belong to this account, and will also + * destroy @a account. + * + * @param account The account. + */ +void purple_accounts_delete(PurpleAccount *account); + +/** + * Reorders an account. + * + * @param account The account to reorder. + * @param new_index The new index for the account. + */ +void purple_accounts_reorder(PurpleAccount *account, guint new_index); + +/** + * Returns a list of all accounts. + * + * @constreturn A list of all accounts. + */ +GList *purple_accounts_get_all(void); + +/** + * Returns a list of all enabled accounts + * + * @return A list of all enabled accounts. The list is owned + * by the caller, and must be g_list_free()d to avoid + * leaking the nodes. + */ +GList *purple_accounts_get_all_active(void); + +/** + * Finds an account with the specified name and protocol id. + * + * @param name The account username. + * @param protocol The account protocol ID. + * + * @return The account, if found, or @c FALSE otherwise. + */ +PurpleAccount *purple_accounts_find(const char *name, const char *protocol); + +/** + * This is called by the core after all subsystems and what + * not have been initialized. It sets all enabled accounts + * to their startup status by signing them on, setting them + * away, etc. + * + * You probably shouldn't call this unless you really know + * what you're doing. + */ +void purple_accounts_restore_current_statuses(void); + +/*@}*/ + + +/**************************************************************************/ +/** @name UI Registration Functions */ +/**************************************************************************/ +/*@{*/ +/** + * Sets the UI operations structure to be used for accounts. + * + * @param ops The UI operations structure. + */ +void purple_accounts_set_ui_ops(PurpleAccountUiOps *ops); + +/** + * Returns the UI operations structure used for accounts. + * + * @return The UI operations structure in use. + */ +PurpleAccountUiOps *purple_accounts_get_ui_ops(void); + +/*@}*/ + + +/**************************************************************************/ +/** @name Accounts Subsystem */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the accounts subsystem handle. + * + * @return The accounts subsystem handle. + */ +void *purple_accounts_get_handle(void); + +/** + * Initializes the accounts subsystem. + */ +void purple_accounts_init(void); + +/** + * Uninitializes the accounts subsystem. + */ +void purple_accounts_uninit(void); + +/** + * Schedules saving of accounts + */ +void purple_accounts_schedule_save(void); + +/*@}*/ + +G_END_DECLS + +#endif /* _PURPLE_ACCOUNTS_H_ */ diff --git a/libpurple/blist.c b/libpurple/blist.c deleted file mode 100644 index d44c6c037f..0000000000 --- a/libpurple/blist.c +++ /dev/null @@ -1,3251 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - * - */ -#define _PURPLE_BLIST_C_ - -#include "internal.h" -#include "blist.h" -#include "conversation.h" -#include "dbus-maybe.h" -#include "debug.h" -#include "notify.h" -#include "pounce.h" -#include "prefs.h" -#include "privacy.h" -#include "prpl.h" -#include "server.h" -#include "signals.h" -#include "util.h" -#include "value.h" -#include "xmlnode.h" - -static PurpleBlistUiOps *blist_ui_ops = NULL; - -static PurpleBuddyList *purplebuddylist = NULL; - -/** - * A hash table used for efficient lookups of buddies by name. - * PurpleAccount* => GHashTable*, with the inner hash table being - * struct _purple_hbuddy => PurpleBuddy* - */ -static GHashTable *buddies_cache = NULL; - -/** - * A hash table used for efficient lookups of groups by name. - * UTF-8 collate-key => PurpleGroup*. - */ -static GHashTable *groups_cache = NULL; - -static guint save_timer = 0; -static gboolean blist_loaded = FALSE; - -/********************************************************************* - * Private utility functions * - *********************************************************************/ - -static PurpleBlistNode *purple_blist_get_last_sibling(PurpleBlistNode *node) -{ - PurpleBlistNode *n = node; - if (!n) - return NULL; - while (n->next) - n = n->next; - return n; -} - -static PurpleBlistNode *purple_blist_get_last_child(PurpleBlistNode *node) -{ - if (!node) - return NULL; - return purple_blist_get_last_sibling(node->child); -} - -struct _list_account_buddies { - GSList *list; - PurpleAccount *account; -}; - -struct _purple_hbuddy { - char *name; - PurpleAccount *account; - PurpleBlistNode *group; -}; - -/* This function must not use purple_normalize */ -static guint _purple_blist_hbuddy_hash(struct _purple_hbuddy *hb) -{ - return g_str_hash(hb->name) ^ g_direct_hash(hb->group) ^ g_direct_hash(hb->account); -} - -/* This function must not use purple_normalize */ -static guint _purple_blist_hbuddy_equal(struct _purple_hbuddy *hb1, struct _purple_hbuddy *hb2) -{ - return (hb1->group == hb2->group && - hb1->account == hb2->account && - g_str_equal(hb1->name, hb2->name)); -} - -static void _purple_blist_hbuddy_free_key(struct _purple_hbuddy *hb) -{ - g_free(hb->name); - g_free(hb); -} - -static void -purple_blist_buddies_cache_add_account(PurpleAccount *account) -{ - GHashTable *account_buddies = g_hash_table_new_full((GHashFunc)_purple_blist_hbuddy_hash, - (GEqualFunc)_purple_blist_hbuddy_equal, - (GDestroyNotify)_purple_blist_hbuddy_free_key, NULL); - g_hash_table_insert(buddies_cache, account, account_buddies); -} - -static void -purple_blist_buddies_cache_remove_account(const PurpleAccount *account) -{ - g_hash_table_remove(buddies_cache, account); -} - - -/********************************************************************* - * Writing to disk * - *********************************************************************/ - -static void -value_to_xmlnode(gpointer key, gpointer hvalue, gpointer user_data) -{ - const char *name; - PurpleValue *value; - xmlnode *node, *child; - char buf[21]; - - name = (const char *)key; - value = (PurpleValue *)hvalue; - node = (xmlnode *)user_data; - - g_return_if_fail(value != NULL); - - child = xmlnode_new_child(node, "setting"); - xmlnode_set_attrib(child, "name", name); - - if (purple_value_get_type(value) == PURPLE_TYPE_INT) { - xmlnode_set_attrib(child, "type", "int"); - g_snprintf(buf, sizeof(buf), "%d", purple_value_get_int(value)); - xmlnode_insert_data(child, buf, -1); - } - else if (purple_value_get_type(value) == PURPLE_TYPE_STRING) { - xmlnode_set_attrib(child, "type", "string"); - xmlnode_insert_data(child, purple_value_get_string(value), -1); - } - else if (purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN) { - xmlnode_set_attrib(child, "type", "bool"); - g_snprintf(buf, sizeof(buf), "%d", purple_value_get_boolean(value)); - xmlnode_insert_data(child, buf, -1); - } -} - -static void -chat_component_to_xmlnode(gpointer key, gpointer value, gpointer user_data) -{ - const char *name; - const char *data; - xmlnode *node, *child; - - name = (const char *)key; - data = (const char *)value; - node = (xmlnode *)user_data; - - g_return_if_fail(data != NULL); - - child = xmlnode_new_child(node, "component"); - xmlnode_set_attrib(child, "name", name); - xmlnode_insert_data(child, data, -1); -} - -static xmlnode * -buddy_to_xmlnode(PurpleBlistNode *bnode) -{ - xmlnode *node, *child; - PurpleBuddy *buddy; - - buddy = (PurpleBuddy *)bnode; - - node = xmlnode_new("buddy"); - xmlnode_set_attrib(node, "account", purple_account_get_username(buddy->account)); - xmlnode_set_attrib(node, "proto", purple_account_get_protocol_id(buddy->account)); - - child = xmlnode_new_child(node, "name"); - xmlnode_insert_data(child, buddy->name, -1); - - if (buddy->alias != NULL) - { - child = xmlnode_new_child(node, "alias"); - xmlnode_insert_data(child, buddy->alias, -1); - } - - /* Write buddy settings */ - g_hash_table_foreach(buddy->node.settings, value_to_xmlnode, node); - - return node; -} - -static xmlnode * -contact_to_xmlnode(PurpleBlistNode *cnode) -{ - xmlnode *node, *child; - PurpleContact *contact; - PurpleBlistNode *bnode; - - contact = (PurpleContact *)cnode; - - node = xmlnode_new("contact"); - - if (contact->alias != NULL) - { - xmlnode_set_attrib(node, "alias", contact->alias); - } - - /* Write buddies */ - for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) - { - if (!PURPLE_BLIST_NODE_SHOULD_SAVE(bnode)) - continue; - if (PURPLE_BLIST_NODE_IS_BUDDY(bnode)) - { - child = buddy_to_xmlnode(bnode); - xmlnode_insert_child(node, child); - } - } - - /* Write contact settings */ - g_hash_table_foreach(cnode->settings, value_to_xmlnode, node); - - return node; -} - -static xmlnode * -chat_to_xmlnode(PurpleBlistNode *cnode) -{ - xmlnode *node, *child; - PurpleChat *chat; - - chat = (PurpleChat *)cnode; - - node = xmlnode_new("chat"); - xmlnode_set_attrib(node, "proto", purple_account_get_protocol_id(chat->account)); - xmlnode_set_attrib(node, "account", purple_account_get_username(chat->account)); - - if (chat->alias != NULL) - { - child = xmlnode_new_child(node, "alias"); - xmlnode_insert_data(child, chat->alias, -1); - } - - /* Write chat components */ - g_hash_table_foreach(chat->components, chat_component_to_xmlnode, node); - - /* Write chat settings */ - g_hash_table_foreach(chat->node.settings, value_to_xmlnode, node); - - return node; -} - -static xmlnode * -group_to_xmlnode(PurpleBlistNode *gnode) -{ - xmlnode *node, *child; - PurpleGroup *group; - PurpleBlistNode *cnode; - - group = (PurpleGroup *)gnode; - - node = xmlnode_new("group"); - xmlnode_set_attrib(node, "name", group->name); - - /* Write settings */ - g_hash_table_foreach(group->node.settings, value_to_xmlnode, node); - - /* Write contacts and chats */ - for (cnode = gnode->child; cnode != NULL; cnode = cnode->next) - { - if (!PURPLE_BLIST_NODE_SHOULD_SAVE(cnode)) - continue; - if (PURPLE_BLIST_NODE_IS_CONTACT(cnode)) - { - child = contact_to_xmlnode(cnode); - xmlnode_insert_child(node, child); - } - else if (PURPLE_BLIST_NODE_IS_CHAT(cnode)) - { - child = chat_to_xmlnode(cnode); - xmlnode_insert_child(node, child); - } - } - - return node; -} - -static xmlnode * -accountprivacy_to_xmlnode(PurpleAccount *account) -{ - xmlnode *node, *child; - GSList *cur; - char buf[10]; - - node = xmlnode_new("account"); - xmlnode_set_attrib(node, "proto", purple_account_get_protocol_id(account)); - xmlnode_set_attrib(node, "name", purple_account_get_username(account)); - g_snprintf(buf, sizeof(buf), "%d", purple_account_get_privacy_type(account)); - xmlnode_set_attrib(node, "mode", buf); - - for (cur = account->permit; cur; cur = cur->next) - { - child = xmlnode_new_child(node, "permit"); - xmlnode_insert_data(child, cur->data, -1); - } - - for (cur = account->deny; cur; cur = cur->next) - { - child = xmlnode_new_child(node, "block"); - xmlnode_insert_data(child, cur->data, -1); - } - - return node; -} - -static xmlnode * -blist_to_xmlnode(void) -{ - xmlnode *node, *child, *grandchild; - PurpleBlistNode *gnode; - GList *cur; - - node = xmlnode_new("purple"); - xmlnode_set_attrib(node, "version", "1.0"); - - /* Write groups */ - child = xmlnode_new_child(node, "blist"); - for (gnode = purplebuddylist->root; gnode != NULL; gnode = gnode->next) - { - if (!PURPLE_BLIST_NODE_SHOULD_SAVE(gnode)) - continue; - if (PURPLE_BLIST_NODE_IS_GROUP(gnode)) - { - grandchild = group_to_xmlnode(gnode); - xmlnode_insert_child(child, grandchild); - } - } - - /* Write privacy settings */ - child = xmlnode_new_child(node, "privacy"); - for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next) - { - grandchild = accountprivacy_to_xmlnode(cur->data); - xmlnode_insert_child(child, grandchild); - } - - return node; -} - -static void -purple_blist_sync(void) -{ - xmlnode *node; - char *data; - - if (!blist_loaded) - { - purple_debug_error("blist", "Attempted to save buddy list before it " - "was read!\n"); - return; - } - - node = blist_to_xmlnode(); - data = xmlnode_to_formatted_str(node, NULL); - purple_util_write_data_to_file("blist.xml", data, -1); - g_free(data); - xmlnode_free(node); -} - -static gboolean -save_cb(gpointer data) -{ - purple_blist_sync(); - save_timer = 0; - return FALSE; -} - -static void -_purple_blist_schedule_save() -{ - if (save_timer == 0) - save_timer = purple_timeout_add_seconds(5, save_cb, NULL); -} - -static void -purple_blist_save_account(PurpleAccount *account) -{ -#if 1 - _purple_blist_schedule_save(); -#else - if (account != NULL) { - /* Save the buddies and privacy data for this account */ - } else { - /* Save all buddies and privacy data */ - } -#endif -} - -static void -purple_blist_save_node(PurpleBlistNode *node) -{ - _purple_blist_schedule_save(); -} - -void purple_blist_schedule_save() -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - - /* Save everything */ - if (ops && ops->save_account) - ops->save_account(NULL); -} - - -/********************************************************************* - * Reading from disk * - *********************************************************************/ - -static void -parse_setting(PurpleBlistNode *node, xmlnode *setting) -{ - const char *name = xmlnode_get_attrib(setting, "name"); - const char *type = xmlnode_get_attrib(setting, "type"); - char *value = xmlnode_get_data(setting); - - if (!value) - return; - - if (!type || purple_strequal(type, "string")) - purple_blist_node_set_string(node, name, value); - else if (purple_strequal(type, "bool")) - purple_blist_node_set_bool(node, name, atoi(value)); - else if (purple_strequal(type, "int")) - purple_blist_node_set_int(node, name, atoi(value)); - - g_free(value); -} - -static void -parse_buddy(PurpleGroup *group, PurpleContact *contact, xmlnode *bnode) -{ - PurpleAccount *account; - PurpleBuddy *buddy; - char *name = NULL, *alias = NULL; - const char *acct_name, *proto; - xmlnode *x; - - acct_name = xmlnode_get_attrib(bnode, "account"); - proto = xmlnode_get_attrib(bnode, "proto"); - - if (!acct_name || !proto) - return; - - account = purple_accounts_find(acct_name, proto); - - if (!account) - return; - - if ((x = xmlnode_get_child(bnode, "name"))) - name = xmlnode_get_data(x); - - if (!name) - return; - - if ((x = xmlnode_get_child(bnode, "alias"))) - alias = xmlnode_get_data(x); - - buddy = purple_buddy_new(account, name, alias); - purple_blist_add_buddy(buddy, contact, group, - purple_blist_get_last_child((PurpleBlistNode*)contact)); - - for (x = xmlnode_get_child(bnode, "setting"); x; x = xmlnode_get_next_twin(x)) { - parse_setting((PurpleBlistNode*)buddy, x); - } - - g_free(name); - g_free(alias); -} - -static void -parse_contact(PurpleGroup *group, xmlnode *cnode) -{ - PurpleContact *contact = purple_contact_new(); - xmlnode *x; - const char *alias; - - purple_blist_add_contact(contact, group, - purple_blist_get_last_child((PurpleBlistNode*)group)); - - if ((alias = xmlnode_get_attrib(cnode, "alias"))) { - purple_blist_alias_contact(contact, alias); - } - - for (x = cnode->child; x; x = x->next) { - if (x->type != XMLNODE_TYPE_TAG) - continue; - if (purple_strequal(x->name, "buddy")) - parse_buddy(group, contact, x); - else if (purple_strequal(x->name, "setting")) - parse_setting((PurpleBlistNode*)contact, x); - } - - /* if the contact is empty, don't keep it around. it causes problems */ - if (!((PurpleBlistNode*)contact)->child) - purple_blist_remove_contact(contact); -} - -static void -parse_chat(PurpleGroup *group, xmlnode *cnode) -{ - PurpleChat *chat; - PurpleAccount *account; - const char *acct_name, *proto; - xmlnode *x; - char *alias = NULL; - GHashTable *components; - - acct_name = xmlnode_get_attrib(cnode, "account"); - proto = xmlnode_get_attrib(cnode, "proto"); - - if (!acct_name || !proto) - return; - - account = purple_accounts_find(acct_name, proto); - - if (!account) - return; - - if ((x = xmlnode_get_child(cnode, "alias"))) - alias = xmlnode_get_data(x); - - components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - - for (x = xmlnode_get_child(cnode, "component"); x; x = xmlnode_get_next_twin(x)) { - const char *name; - char *value; - - name = xmlnode_get_attrib(x, "name"); - value = xmlnode_get_data(x); - g_hash_table_replace(components, g_strdup(name), value); - } - - chat = purple_chat_new(account, alias, components); - purple_blist_add_chat(chat, group, - purple_blist_get_last_child((PurpleBlistNode*)group)); - - for (x = xmlnode_get_child(cnode, "setting"); x; x = xmlnode_get_next_twin(x)) { - parse_setting((PurpleBlistNode*)chat, x); - } - - g_free(alias); -} - -static void -parse_group(xmlnode *groupnode) -{ - const char *name = xmlnode_get_attrib(groupnode, "name"); - PurpleGroup *group; - xmlnode *cnode; - - if (!name) - name = _("Buddies"); - - group = purple_group_new(name); - purple_blist_add_group(group, - purple_blist_get_last_sibling(purplebuddylist->root)); - - for (cnode = groupnode->child; cnode; cnode = cnode->next) { - if (cnode->type != XMLNODE_TYPE_TAG) - continue; - if (purple_strequal(cnode->name, "setting")) - parse_setting((PurpleBlistNode*)group, cnode); - else if (purple_strequal(cnode->name, "contact") || - purple_strequal(cnode->name, "person")) - parse_contact(group, cnode); - else if (purple_strequal(cnode->name, "chat")) - parse_chat(group, cnode); - } -} - -static void -load_blist(void) -{ - xmlnode *purple, *blist, *privacy; - - blist_loaded = TRUE; - - purple = purple_util_read_xml_from_file("blist.xml", _("buddy list")); - - if (purple == NULL) - return; - - blist = xmlnode_get_child(purple, "blist"); - if (blist) { - xmlnode *groupnode; - for (groupnode = xmlnode_get_child(blist, "group"); groupnode != NULL; - groupnode = xmlnode_get_next_twin(groupnode)) { - parse_group(groupnode); - } - } - - privacy = xmlnode_get_child(purple, "privacy"); - if (privacy) { - xmlnode *anode; - for (anode = privacy->child; anode; anode = anode->next) { - xmlnode *x; - PurpleAccount *account; - int imode; - const char *acct_name, *proto, *mode; - - acct_name = xmlnode_get_attrib(anode, "name"); - proto = xmlnode_get_attrib(anode, "proto"); - mode = xmlnode_get_attrib(anode, "mode"); - - if (!acct_name || !proto || !mode) - continue; - - account = purple_accounts_find(acct_name, proto); - - if (!account) - continue; - - imode = atoi(mode); - purple_account_set_privacy_type(account, (imode != 0 ? imode : PURPLE_PRIVACY_ALLOW_ALL)); - - for (x = anode->child; x; x = x->next) { - char *name; - if (x->type != XMLNODE_TYPE_TAG) - continue; - - if (purple_strequal(x->name, "permit")) { - name = xmlnode_get_data(x); - purple_privacy_permit_add(account, name, TRUE); - g_free(name); - } else if (purple_strequal(x->name, "block")) { - name = xmlnode_get_data(x); - purple_privacy_deny_add(account, name, TRUE); - g_free(name); - } - } - } - } - - xmlnode_free(purple); - - /* This tells the buddy icon code to do its thing. */ - _purple_buddy_icons_blist_loaded_cb(); -} - - -/********************************************************************* - * Stuff * - *********************************************************************/ - -static void -purple_contact_compute_priority_buddy(PurpleContact *contact) -{ - PurpleBlistNode *bnode; - PurpleBuddy *new_priority = NULL; - - g_return_if_fail(contact != NULL); - - contact->priority = NULL; - for (bnode = ((PurpleBlistNode*)contact)->child; - bnode != NULL; - bnode = bnode->next) - { - PurpleBuddy *buddy; - - if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) - continue; - - buddy = (PurpleBuddy*)bnode; - if (new_priority == NULL) - { - new_priority = buddy; - continue; - } - - if (purple_account_is_connected(buddy->account)) - { - int cmp = 1; - if (purple_account_is_connected(new_priority->account)) - cmp = purple_presence_compare(purple_buddy_get_presence(new_priority), - purple_buddy_get_presence(buddy)); - - if (cmp > 0 || (cmp == 0 && - purple_prefs_get_bool("/purple/contact/last_match"))) - { - new_priority = buddy; - } - } - } - - contact->priority = new_priority; - contact->priority_valid = TRUE; -} - - -/***************************************************************************** - * Public API functions * - *****************************************************************************/ - -void -purple_blist_boot(void) -{ - PurpleBlistUiOps *ui_ops; - GList *account; - PurpleBuddyList *gbl = g_new0(PurpleBuddyList, 1); - PURPLE_DBUS_REGISTER_POINTER(gbl, PurpleBuddyList); - - ui_ops = purple_blist_get_ui_ops(); - - gbl->buddies = g_hash_table_new_full((GHashFunc)_purple_blist_hbuddy_hash, - (GEqualFunc)_purple_blist_hbuddy_equal, - (GDestroyNotify)_purple_blist_hbuddy_free_key, NULL); - - buddies_cache = g_hash_table_new_full(g_direct_hash, g_direct_equal, - NULL, (GDestroyNotify)g_hash_table_destroy); - - groups_cache = g_hash_table_new_full((GHashFunc)g_str_hash, - (GEqualFunc)g_str_equal, - (GDestroyNotify)g_free, NULL); - - for (account = purple_accounts_get_all(); account != NULL; account = account->next) - { - purple_blist_buddies_cache_add_account(account->data); - } - - if (ui_ops != NULL && ui_ops->new_list != NULL) - ui_ops->new_list(gbl); - - purplebuddylist = gbl; - - load_blist(); -} - -PurpleBuddyList * -purple_get_blist() -{ - return purplebuddylist; -} - -PurpleBlistNode * -purple_blist_get_root() -{ - return purplebuddylist ? purplebuddylist->root : NULL; -} - -static void -append_buddy(gpointer key, gpointer value, gpointer user_data) -{ - GSList **list = user_data; - *list = g_slist_prepend(*list, value); -} - -GSList * -purple_blist_get_buddies() -{ - GSList *buddies = NULL; - - if (!purplebuddylist) - return NULL; - - g_hash_table_foreach(purplebuddylist->buddies, append_buddy, &buddies); - return buddies; -} - -void * -purple_blist_get_ui_data() -{ - return purplebuddylist->ui_data; -} - -void -purple_blist_set_ui_data(void *ui_data) -{ - purplebuddylist->ui_data = ui_data; -} - -void purple_blist_show() -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - - if (ops && ops->show) - ops->show(purplebuddylist); -} - -void purple_blist_destroy() -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - - purple_debug(PURPLE_DEBUG_INFO, "blist", "Destroying\n"); - - if (ops && ops->destroy) - ops->destroy(purplebuddylist); -} - -void purple_blist_set_visible(gboolean show) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - - if (ops && ops->set_visible) - ops->set_visible(purplebuddylist, show); -} - -static PurpleBlistNode *get_next_node(PurpleBlistNode *node, gboolean godeep) -{ - if (node == NULL) - return NULL; - - if (godeep && node->child) - return node->child; - - if (node->next) - return node->next; - - return get_next_node(node->parent, FALSE); -} - -PurpleBlistNode *purple_blist_node_next(PurpleBlistNode *node, gboolean offline) -{ - PurpleBlistNode *ret = node; - - if (offline) - return get_next_node(ret, TRUE); - do - { - ret = get_next_node(ret, TRUE); - } while (ret && PURPLE_BLIST_NODE_IS_BUDDY(ret) && - !purple_account_is_connected(purple_buddy_get_account((PurpleBuddy *)ret))); - - return ret; -} - -PurpleBlistNode *purple_blist_node_get_parent(PurpleBlistNode *node) -{ - return node ? node->parent : NULL; -} - -PurpleBlistNode *purple_blist_node_get_first_child(PurpleBlistNode *node) -{ - return node ? node->child : NULL; -} - -PurpleBlistNode *purple_blist_node_get_sibling_next(PurpleBlistNode *node) -{ - return node? node->next : NULL; -} - -PurpleBlistNode *purple_blist_node_get_sibling_prev(PurpleBlistNode *node) -{ - return node? node->prev : NULL; -} - -void * -purple_blist_node_get_ui_data(const PurpleBlistNode *node) -{ - g_return_val_if_fail(node, NULL); - - return node->ui_data; -} - -void -purple_blist_node_set_ui_data(PurpleBlistNode *node, void *ui_data) { - g_return_if_fail(node); - - node->ui_data = ui_data; -} - -void -purple_blist_update_buddy_status(PurpleBuddy *buddy, PurpleStatus *old_status) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurplePresence *presence; - PurpleStatus *status; - PurpleBlistNode *cnode; - - g_return_if_fail(buddy != NULL); - - presence = purple_buddy_get_presence(buddy); - status = purple_presence_get_active_status(presence); - - purple_debug_info("blist", "Updating buddy status for %s (%s)\n", - buddy->name, purple_account_get_protocol_name(buddy->account)); - - if (purple_status_is_online(status) && - !purple_status_is_online(old_status)) { - - purple_signal_emit(purple_blist_get_handle(), "buddy-signed-on", buddy); - - cnode = buddy->node.parent; - if (++(PURPLE_CONTACT(cnode)->online) == 1) - PURPLE_GROUP(cnode->parent)->online++; - } else if (!purple_status_is_online(status) && - purple_status_is_online(old_status)) { - - purple_blist_node_set_int(&buddy->node, "last_seen", time(NULL)); - purple_signal_emit(purple_blist_get_handle(), "buddy-signed-off", buddy); - - cnode = buddy->node.parent; - if (--(PURPLE_CONTACT(cnode)->online) == 0) - PURPLE_GROUP(cnode->parent)->online--; - } else { - purple_signal_emit(purple_blist_get_handle(), - "buddy-status-changed", buddy, old_status, - status); - } - - /* - * This function used to only call the following two functions if one of - * the above signals had been triggered, but that's not good, because - * if someone's away message changes and they don't go from away to back - * to away then no signal is triggered. - * - * It's a safe assumption that SOMETHING called this function. PROBABLY - * because something, somewhere changed. Calling the stuff below - * certainly won't hurt anything. Unless you're on a K6-2 300. - */ - purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy)); - if (ops && ops->update) - ops->update(purplebuddylist, (PurpleBlistNode *)buddy); -} - -void -purple_blist_update_node_icon(PurpleBlistNode *node) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - - g_return_if_fail(node != NULL); - - if (ops && ops->update) - ops->update(purplebuddylist, node); -} - -/* - * TODO: Maybe remove the call to this from server.c and call it - * from oscar.c and toc.c instead? - */ -void purple_blist_rename_buddy(PurpleBuddy *buddy, const char *name) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - struct _purple_hbuddy *hb, *hb2; - GHashTable *account_buddies; - - g_return_if_fail(buddy != NULL); - - hb = g_new(struct _purple_hbuddy, 1); - hb->name = (gchar *)purple_normalize(buddy->account, buddy->name); - hb->account = buddy->account; - hb->group = ((PurpleBlistNode *)buddy)->parent->parent; - g_hash_table_remove(purplebuddylist->buddies, hb); - - account_buddies = g_hash_table_lookup(buddies_cache, buddy->account); - g_hash_table_remove(account_buddies, hb); - - hb->name = g_strdup(purple_normalize(buddy->account, name)); - g_hash_table_replace(purplebuddylist->buddies, hb, buddy); - - hb2 = g_new(struct _purple_hbuddy, 1); - hb2->name = g_strdup(hb->name); - hb2->account = buddy->account; - hb2->group = ((PurpleBlistNode *)buddy)->parent->parent; - - g_hash_table_replace(account_buddies, hb2, buddy); - - g_free(buddy->name); - buddy->name = g_strdup(name); - - if (ops && ops->save_node) - ops->save_node((PurpleBlistNode *) buddy); - - if (ops && ops->update) - ops->update(purplebuddylist, (PurpleBlistNode *)buddy); -} - -static gboolean -purple_strings_are_different(const char *one, const char *two) -{ - return !((one && two && g_utf8_collate(one, two) == 0) || - ((one == NULL || *one == '\0') && (two == NULL || *two == '\0'))); -} - -void purple_blist_alias_contact(PurpleContact *contact, const char *alias) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurpleConversation *conv; - PurpleBlistNode *bnode; - char *old_alias; - char *new_alias = NULL; - - g_return_if_fail(contact != NULL); - - if ((alias != NULL) && (*alias != '\0')) - new_alias = purple_utf8_strip_unprintables(alias); - - if (!purple_strings_are_different(contact->alias, new_alias)) { - g_free(new_alias); - return; - } - - old_alias = contact->alias; - - if ((new_alias != NULL) && (*new_alias != '\0')) - contact->alias = new_alias; - else { - contact->alias = NULL; - g_free(new_alias); /* could be "\0" */ - } - - if (ops && ops->save_node) - ops->save_node((PurpleBlistNode*) contact); - - if (ops && ops->update) - ops->update(purplebuddylist, (PurpleBlistNode *)contact); - - for(bnode = ((PurpleBlistNode *)contact)->child; bnode != NULL; bnode = bnode->next) - { - PurpleBuddy *buddy = (PurpleBuddy *)bnode; - - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, - buddy->account); - if (conv) - purple_conversation_autoset_title(conv); - } - - purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased", - contact, old_alias); - g_free(old_alias); -} - -void purple_blist_alias_chat(PurpleChat *chat, const char *alias) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - char *old_alias; - char *new_alias = NULL; - - g_return_if_fail(chat != NULL); - - if ((alias != NULL) && (*alias != '\0')) - new_alias = purple_utf8_strip_unprintables(alias); - - if (!purple_strings_are_different(chat->alias, new_alias)) { - g_free(new_alias); - return; - } - - old_alias = chat->alias; - - if ((new_alias != NULL) && (*new_alias != '\0')) - chat->alias = new_alias; - else { - chat->alias = NULL; - g_free(new_alias); /* could be "\0" */ - } - - if (ops && ops->save_node) - ops->save_node((PurpleBlistNode*) chat); - - if (ops && ops->update) - ops->update(purplebuddylist, (PurpleBlistNode *)chat); - - purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased", - chat, old_alias); - g_free(old_alias); -} - -void purple_blist_alias_buddy(PurpleBuddy *buddy, const char *alias) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurpleConversation *conv; - char *old_alias; - char *new_alias = NULL; - - g_return_if_fail(buddy != NULL); - - if ((alias != NULL) && (*alias != '\0')) - new_alias = purple_utf8_strip_unprintables(alias); - - if (!purple_strings_are_different(buddy->alias, new_alias)) { - g_free(new_alias); - return; - } - - old_alias = buddy->alias; - - if ((new_alias != NULL) && (*new_alias != '\0')) - buddy->alias = new_alias; - else { - buddy->alias = NULL; - g_free(new_alias); /* could be "\0" */ - } - - if (ops && ops->save_node) - ops->save_node((PurpleBlistNode*) buddy); - - if (ops && ops->update) - ops->update(purplebuddylist, (PurpleBlistNode *)buddy); - - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, - buddy->account); - if (conv) - purple_conversation_autoset_title(conv); - - purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased", - buddy, old_alias); - g_free(old_alias); -} - -void purple_blist_server_alias_buddy(PurpleBuddy *buddy, const char *alias) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurpleConversation *conv; - char *old_alias; - char *new_alias = NULL; - - g_return_if_fail(buddy != NULL); - - if ((alias != NULL) && (*alias != '\0') && g_utf8_validate(alias, -1, NULL)) - new_alias = purple_utf8_strip_unprintables(alias); - - if (!purple_strings_are_different(buddy->server_alias, new_alias)) { - g_free(new_alias); - return; - } - - old_alias = buddy->server_alias; - - if ((new_alias != NULL) && (*new_alias != '\0')) - buddy->server_alias = new_alias; - else { - buddy->server_alias = NULL; - g_free(new_alias); /* could be "\0"; */ - } - - if (ops && ops->save_node) - ops->save_node((PurpleBlistNode*) buddy); - - if (ops && ops->update) - ops->update(purplebuddylist, (PurpleBlistNode *)buddy); - - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, - buddy->account); - if (conv) - purple_conversation_autoset_title(conv); - - purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased", - buddy, old_alias); - g_free(old_alias); -} - -/* - * TODO: If merging, prompt the user if they want to merge. - */ -void purple_blist_rename_group(PurpleGroup *source, const char *name) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurpleGroup *dest; - gchar *old_name; - gchar *new_name; - GList *moved_buddies = NULL; - GSList *accts; - - g_return_if_fail(source != NULL); - g_return_if_fail(name != NULL); - - new_name = purple_utf8_strip_unprintables(name); - - if (*new_name == '\0' || purple_strequal(new_name, source->name)) { - g_free(new_name); - return; - } - - dest = purple_find_group(new_name); - if (dest != NULL && purple_utf8_strcasecmp(source->name, dest->name) != 0) { - /* We're merging two groups */ - PurpleBlistNode *prev, *child, *next; - - prev = purple_blist_get_last_child((PurpleBlistNode*)dest); - child = ((PurpleBlistNode*)source)->child; - - /* - * TODO: This seems like a dumb way to do this... why not just - * append all children from the old group to the end of the new - * one? PRPLs might be expecting to receive an add_buddy() for - * each moved buddy... - */ - while (child) - { - next = child->next; - if (PURPLE_BLIST_NODE_IS_CONTACT(child)) { - PurpleBlistNode *bnode; - purple_blist_add_contact((PurpleContact *)child, dest, prev); - for (bnode = child->child; bnode != NULL; bnode = bnode->next) { - purple_blist_add_buddy((PurpleBuddy *)bnode, (PurpleContact *)child, - NULL, bnode->prev); - moved_buddies = g_list_append(moved_buddies, bnode); - } - prev = child; - } else if (PURPLE_BLIST_NODE_IS_CHAT(child)) { - purple_blist_add_chat((PurpleChat *)child, dest, prev); - prev = child; - } else { - purple_debug(PURPLE_DEBUG_ERROR, "blist", - "Unknown child type in group %s\n", source->name); - } - child = next; - } - - /* Make a copy of the old group name and then delete the old group */ - old_name = g_strdup(source->name); - purple_blist_remove_group(source); - source = dest; - g_free(new_name); - } else { - /* A simple rename */ - PurpleBlistNode *cnode, *bnode; - gchar* key; - - /* Build a GList of all buddies in this group */ - for (cnode = ((PurpleBlistNode *)source)->child; cnode != NULL; cnode = cnode->next) { - if (PURPLE_BLIST_NODE_IS_CONTACT(cnode)) - for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) - moved_buddies = g_list_append(moved_buddies, bnode); - } - - old_name = source->name; - source->name = new_name; - - key = g_utf8_collate_key(old_name, -1); - g_hash_table_remove(groups_cache, key); - g_free(key); - - key = g_utf8_collate_key(new_name, -1); - g_hash_table_insert(groups_cache, key, source); - } - - /* Save our changes */ - if (ops && ops->save_node) - ops->save_node((PurpleBlistNode*) source); - - /* Update the UI */ - if (ops && ops->update) - ops->update(purplebuddylist, (PurpleBlistNode*)source); - - /* Notify all PRPLs */ - /* TODO: Is this condition needed? Seems like it would always be TRUE */ - if(old_name && !purple_strequal(source->name, old_name)) { - for (accts = purple_group_get_accounts(source); accts; accts = g_slist_remove(accts, accts->data)) { - PurpleAccount *account = accts->data; - PurpleConnection *gc = NULL; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; - GList *l = NULL, *buddies = NULL; - - gc = purple_account_get_connection(account); - - if(gc) - prpl = purple_connection_get_prpl(gc); - - if(gc && prpl) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if(!prpl_info) - continue; - - for(l = moved_buddies; l; l = l->next) { - PurpleBuddy *buddy = (PurpleBuddy *)l->data; - - if(buddy && buddy->account == account) - buddies = g_list_append(buddies, (PurpleBlistNode *)buddy); - } - - if(prpl_info->rename_group) { - prpl_info->rename_group(gc, old_name, source, buddies); - } else { - GList *cur, *groups = NULL; - - /* Make a list of what the groups each buddy is in */ - for(cur = buddies; cur; cur = cur->next) { - PurpleBlistNode *node = (PurpleBlistNode *)cur->data; - groups = g_list_prepend(groups, node->parent->parent); - } - - purple_account_remove_buddies(account, buddies, groups); - g_list_free(groups); - purple_account_add_buddies(account, buddies, NULL); - } - - g_list_free(buddies); - } - } - g_list_free(moved_buddies); - g_free(old_name); -} - -static void purple_blist_node_initialize_settings(PurpleBlistNode *node); - -PurpleChat *purple_chat_new(PurpleAccount *account, const char *alias, GHashTable *components) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurpleChat *chat; - - g_return_val_if_fail(account != NULL, NULL); - g_return_val_if_fail(components != NULL, NULL); - - chat = g_new0(PurpleChat, 1); - chat->account = account; - if ((alias != NULL) && (*alias != '\0')) - chat->alias = purple_utf8_strip_unprintables(alias); - chat->components = components; - purple_blist_node_initialize_settings((PurpleBlistNode *)chat); - ((PurpleBlistNode *)chat)->type = PURPLE_BLIST_CHAT_NODE; - - if (ops != NULL && ops->new_node != NULL) - ops->new_node((PurpleBlistNode *)chat); - - PURPLE_DBUS_REGISTER_POINTER(chat, PurpleChat); - return chat; -} - -void -purple_chat_destroy(PurpleChat *chat) -{ - g_hash_table_destroy(chat->components); - g_hash_table_destroy(chat->node.settings); - g_free(chat->alias); - PURPLE_DBUS_UNREGISTER_POINTER(chat); - g_free(chat); -} - -PurpleBuddy *purple_buddy_new(PurpleAccount *account, const char *name, const char *alias) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurpleBuddy *buddy; - - g_return_val_if_fail(account != NULL, NULL); - g_return_val_if_fail(name != NULL, NULL); - - buddy = g_new0(PurpleBuddy, 1); - buddy->account = account; - buddy->name = purple_utf8_strip_unprintables(name); - buddy->alias = purple_utf8_strip_unprintables(alias); - buddy->presence = purple_presence_new_for_buddy(buddy); - ((PurpleBlistNode *)buddy)->type = PURPLE_BLIST_BUDDY_NODE; - - purple_presence_set_status_active(buddy->presence, "offline", TRUE); - - purple_blist_node_initialize_settings((PurpleBlistNode *)buddy); - - if (ops && ops->new_node) - ops->new_node((PurpleBlistNode *)buddy); - - PURPLE_DBUS_REGISTER_POINTER(buddy, PurpleBuddy); - return buddy; -} - -void -purple_buddy_destroy(PurpleBuddy *buddy) -{ - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; - - /* - * Tell the owner PRPL that we're about to free the buddy so it - * can free proto_data - */ - prpl = purple_find_prpl(purple_account_get_protocol_id(buddy->account)); - if (prpl) { - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info && prpl_info->buddy_free) - prpl_info->buddy_free(buddy); - } - - /* Delete the node */ - purple_buddy_icon_unref(buddy->icon); - g_hash_table_destroy(buddy->node.settings); - purple_presence_destroy(buddy->presence); - g_free(buddy->name); - g_free(buddy->alias); - g_free(buddy->server_alias); - - PURPLE_DBUS_UNREGISTER_POINTER(buddy); - g_free(buddy); - - /* FIXME: Once PurpleBuddy is a GObject, timeout callbacks can - * g_object_ref() it when connecting the callback and - * g_object_unref() it in the handler. That way, it won't - * get freed while the timeout is pending and this line can - * be removed. */ - while (g_source_remove_by_user_data((gpointer *)buddy)); -} - -void -purple_buddy_set_icon(PurpleBuddy *buddy, PurpleBuddyIcon *icon) -{ - g_return_if_fail(buddy != NULL); - - if (buddy->icon != icon) - { - purple_buddy_icon_unref(buddy->icon); - buddy->icon = (icon != NULL ? purple_buddy_icon_ref(icon) : NULL); - } - - purple_signal_emit(purple_blist_get_handle(), "buddy-icon-changed", buddy); - - purple_blist_update_node_icon((PurpleBlistNode*)buddy); -} - -PurpleAccount * -purple_buddy_get_account(const PurpleBuddy *buddy) -{ - g_return_val_if_fail(buddy != NULL, NULL); - - return buddy->account; -} - -const char * -purple_buddy_get_name(const PurpleBuddy *buddy) -{ - g_return_val_if_fail(buddy != NULL, NULL); - - return buddy->name; -} - -PurpleBuddyIcon * -purple_buddy_get_icon(const PurpleBuddy *buddy) -{ - g_return_val_if_fail(buddy != NULL, NULL); - - return buddy->icon; -} - -gpointer -purple_buddy_get_protocol_data(const PurpleBuddy *buddy) -{ - g_return_val_if_fail(buddy != NULL, NULL); - - return buddy->proto_data; -} - -void -purple_buddy_set_protocol_data(PurpleBuddy *buddy, gpointer data) -{ - g_return_if_fail(buddy != NULL); - - buddy->proto_data = data; -} - - -void purple_blist_add_chat(PurpleChat *chat, PurpleGroup *group, PurpleBlistNode *node) -{ - PurpleBlistNode *cnode = (PurpleBlistNode*)chat; - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - - g_return_if_fail(chat != NULL); - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT((PurpleBlistNode *)chat)); - - if (node == NULL) { - if (group == NULL) - group = purple_group_new(_("Chats")); - - /* Add group to blist if isn't already on it. Fixes #2752. */ - if (!purple_find_group(group->name)) { - purple_blist_add_group(group, - purple_blist_get_last_sibling(purplebuddylist->root)); - } - } else { - group = (PurpleGroup*)node->parent; - } - - /* if we're moving to overtop of ourselves, do nothing */ - if (cnode == node) - return; - - if (cnode->parent) { - /* This chat was already in the list and is - * being moved. - */ - ((PurpleGroup *)cnode->parent)->totalsize--; - if (purple_account_is_connected(chat->account)) { - ((PurpleGroup *)cnode->parent)->online--; - ((PurpleGroup *)cnode->parent)->currentsize--; - } - if (cnode->next) - cnode->next->prev = cnode->prev; - if (cnode->prev) - cnode->prev->next = cnode->next; - if (cnode->parent->child == cnode) - cnode->parent->child = cnode->next; - - if (ops && ops->remove) - ops->remove(purplebuddylist, cnode); - /* ops->remove() cleaned up the cnode's ui_data, so we need to - * reinitialize it */ - if (ops && ops->new_node) - ops->new_node(cnode); - } - - if (node != NULL) { - if (node->next) - node->next->prev = cnode; - cnode->next = node->next; - cnode->prev = node; - cnode->parent = node->parent; - node->next = cnode; - ((PurpleGroup *)node->parent)->totalsize++; - if (purple_account_is_connected(chat->account)) { - ((PurpleGroup *)node->parent)->online++; - ((PurpleGroup *)node->parent)->currentsize++; - } - } else { - if (((PurpleBlistNode *)group)->child) - ((PurpleBlistNode *)group)->child->prev = cnode; - cnode->next = ((PurpleBlistNode *)group)->child; - cnode->prev = NULL; - ((PurpleBlistNode *)group)->child = cnode; - cnode->parent = (PurpleBlistNode *)group; - group->totalsize++; - if (purple_account_is_connected(chat->account)) { - group->online++; - group->currentsize++; - } - } - - if (ops && ops->save_node) - ops->save_node(cnode); - - if (ops && ops->update) - ops->update(purplebuddylist, (PurpleBlistNode *)cnode); - - purple_signal_emit(purple_blist_get_handle(), "blist-node-added", - cnode); -} - -void purple_blist_add_buddy(PurpleBuddy *buddy, PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node) -{ - PurpleBlistNode *cnode, *bnode; - PurpleGroup *g; - PurpleContact *c; - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - struct _purple_hbuddy *hb, *hb2; - GHashTable *account_buddies; - - g_return_if_fail(buddy != NULL); - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY((PurpleBlistNode*)buddy)); - - bnode = (PurpleBlistNode *)buddy; - - /* if we're moving to overtop of ourselves, do nothing */ - if (bnode == node || (!node && bnode->parent && - contact && bnode->parent == (PurpleBlistNode*)contact - && bnode == bnode->parent->child)) - return; - - if (node && PURPLE_BLIST_NODE_IS_BUDDY(node)) { - c = (PurpleContact*)node->parent; - g = (PurpleGroup*)node->parent->parent; - } else if (contact) { - c = contact; - g = PURPLE_GROUP(PURPLE_BLIST_NODE(c)->parent); - } else { - g = group; - if (g == NULL) - g = purple_group_new(_("Buddies")); - /* Add group to blist if isn't already on it. Fixes #2752. */ - if (!purple_find_group(g->name)) { - purple_blist_add_group(g, - purple_blist_get_last_sibling(purplebuddylist->root)); - } - c = purple_contact_new(); - purple_blist_add_contact(c, g, - purple_blist_get_last_child((PurpleBlistNode*)g)); - } - - cnode = (PurpleBlistNode *)c; - - if (bnode->parent) { - if (PURPLE_BUDDY_IS_ONLINE(buddy)) { - ((PurpleContact*)bnode->parent)->online--; - if (((PurpleContact*)bnode->parent)->online == 0) - ((PurpleGroup*)bnode->parent->parent)->online--; - } - if (purple_account_is_connected(buddy->account)) { - ((PurpleContact*)bnode->parent)->currentsize--; - if (((PurpleContact*)bnode->parent)->currentsize == 0) - ((PurpleGroup*)bnode->parent->parent)->currentsize--; - } - ((PurpleContact*)bnode->parent)->totalsize--; - /* the group totalsize will be taken care of by remove_contact below */ - - if (bnode->parent->parent != (PurpleBlistNode*)g) - serv_move_buddy(buddy, (PurpleGroup *)bnode->parent->parent, g); - - if (bnode->next) - bnode->next->prev = bnode->prev; - if (bnode->prev) - bnode->prev->next = bnode->next; - if (bnode->parent->child == bnode) - bnode->parent->child = bnode->next; - - if (ops && ops->remove) - ops->remove(purplebuddylist, bnode); - - if (bnode->parent->parent != (PurpleBlistNode*)g) { - struct _purple_hbuddy hb; - hb.name = (gchar *)purple_normalize(buddy->account, buddy->name); - hb.account = buddy->account; - hb.group = bnode->parent->parent; - g_hash_table_remove(purplebuddylist->buddies, &hb); - - account_buddies = g_hash_table_lookup(buddies_cache, buddy->account); - g_hash_table_remove(account_buddies, &hb); - } - - if (!bnode->parent->child) { - purple_blist_remove_contact((PurpleContact*)bnode->parent); - } else { - purple_contact_invalidate_priority_buddy((PurpleContact*)bnode->parent); - if (ops && ops->update) - ops->update(purplebuddylist, bnode->parent); - } - } - - if (node && PURPLE_BLIST_NODE_IS_BUDDY(node)) { - if (node->next) - node->next->prev = bnode; - bnode->next = node->next; - bnode->prev = node; - bnode->parent = node->parent; - node->next = bnode; - } else { - if (cnode->child) - cnode->child->prev = bnode; - bnode->prev = NULL; - bnode->next = cnode->child; - cnode->child = bnode; - bnode->parent = cnode; - } - - if (PURPLE_BUDDY_IS_ONLINE(buddy)) { - if (++(PURPLE_CONTACT(bnode->parent)->online) == 1) - PURPLE_GROUP(bnode->parent->parent)->online++; - } - if (purple_account_is_connected(buddy->account)) { - if (++(PURPLE_CONTACT(bnode->parent)->currentsize) == 1) - PURPLE_GROUP(bnode->parent->parent)->currentsize++; - } - PURPLE_CONTACT(bnode->parent)->totalsize++; - - hb = g_new(struct _purple_hbuddy, 1); - hb->name = g_strdup(purple_normalize(buddy->account, buddy->name)); - hb->account = buddy->account; - hb->group = ((PurpleBlistNode*)buddy)->parent->parent; - - g_hash_table_replace(purplebuddylist->buddies, hb, buddy); - - account_buddies = g_hash_table_lookup(buddies_cache, buddy->account); - - hb2 = g_new(struct _purple_hbuddy, 1); - hb2->name = g_strdup(hb->name); - hb2->account = buddy->account; - hb2->group = ((PurpleBlistNode*)buddy)->parent->parent; - - g_hash_table_replace(account_buddies, hb2, buddy); - - purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy)); - - if (ops && ops->save_node) - ops->save_node((PurpleBlistNode*) buddy); - - if (ops && ops->update) - ops->update(purplebuddylist, (PurpleBlistNode*)buddy); - - /* Signal that the buddy has been added */ - purple_signal_emit(purple_blist_get_handle(), "buddy-added", buddy); - - purple_signal_emit(purple_blist_get_handle(), "blist-node-added", - PURPLE_BLIST_NODE(buddy)); -} - -PurpleContact *purple_contact_new() -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - - PurpleContact *contact = g_new0(PurpleContact, 1); - contact->totalsize = 0; - contact->currentsize = 0; - contact->online = 0; - purple_blist_node_initialize_settings((PurpleBlistNode *)contact); - ((PurpleBlistNode *)contact)->type = PURPLE_BLIST_CONTACT_NODE; - - if (ops && ops->new_node) - ops->new_node((PurpleBlistNode *)contact); - - PURPLE_DBUS_REGISTER_POINTER(contact, PurpleContact); - return contact; -} - -void -purple_contact_destroy(PurpleContact *contact) -{ - g_hash_table_destroy(contact->node.settings); - g_free(contact->alias); - PURPLE_DBUS_UNREGISTER_POINTER(contact); - g_free(contact); -} - -PurpleGroup * -purple_contact_get_group(const PurpleContact *contact) -{ - g_return_val_if_fail(contact, NULL); - - return (PurpleGroup *)(((PurpleBlistNode *)contact)->parent); -} - -const char *purple_contact_get_alias(PurpleContact* contact) -{ - g_return_val_if_fail(contact != NULL, NULL); - - if (contact->alias) - return contact->alias; - - return purple_buddy_get_alias(purple_contact_get_priority_buddy(contact)); -} - -gboolean purple_contact_on_account(PurpleContact *c, PurpleAccount *account) -{ - PurpleBlistNode *bnode, *cnode = (PurpleBlistNode *) c; - - g_return_val_if_fail(c != NULL, FALSE); - g_return_val_if_fail(account != NULL, FALSE); - - for (bnode = cnode->child; bnode; bnode = bnode->next) { - PurpleBuddy *buddy; - - if (! PURPLE_BLIST_NODE_IS_BUDDY(bnode)) - continue; - - buddy = (PurpleBuddy *)bnode; - if (buddy->account == account) - return TRUE; - } - return FALSE; -} - -void purple_contact_invalidate_priority_buddy(PurpleContact *contact) -{ - g_return_if_fail(contact != NULL); - - contact->priority_valid = FALSE; -} - -int purple_contact_get_contact_size(PurpleContact *contact, gboolean offline) -{ - g_return_val_if_fail(contact != NULL, 0); - - return offline ? contact->totalsize : contact->currentsize; -} - -PurpleGroup *purple_group_new(const char *name) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurpleGroup *group; - - g_return_val_if_fail(name != NULL, NULL); - g_return_val_if_fail(*name != '\0', NULL); - - group = purple_find_group(name); - if (group != NULL) - return group; - - group = g_new0(PurpleGroup, 1); - group->name = purple_utf8_strip_unprintables(name); - group->totalsize = 0; - group->currentsize = 0; - group->online = 0; - purple_blist_node_initialize_settings((PurpleBlistNode *)group); - ((PurpleBlistNode *)group)->type = PURPLE_BLIST_GROUP_NODE; - - if (ops && ops->new_node) - ops->new_node((PurpleBlistNode *)group); - - PURPLE_DBUS_REGISTER_POINTER(group, PurpleGroup); - return group; -} - -void -purple_group_destroy(PurpleGroup *group) -{ - g_hash_table_destroy(group->node.settings); - g_free(group->name); - PURPLE_DBUS_UNREGISTER_POINTER(group); - g_free(group); -} - -void purple_blist_add_contact(PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurpleGroup *g; - PurpleBlistNode *gnode, *cnode, *bnode; - - g_return_if_fail(contact != NULL); - g_return_if_fail(PURPLE_BLIST_NODE_IS_CONTACT((PurpleBlistNode*)contact)); - - if (PURPLE_BLIST_NODE(contact) == node) - return; - - if (node && (PURPLE_BLIST_NODE_IS_CONTACT(node) || - PURPLE_BLIST_NODE_IS_CHAT(node))) - g = (PurpleGroup*)node->parent; - else if (group) - g = group; - else { - g = purple_find_group(_("Buddies")); - if (g == NULL) { - g = purple_group_new(_("Buddies")); - purple_blist_add_group(g, - purple_blist_get_last_sibling(purplebuddylist->root)); - } - } - - gnode = (PurpleBlistNode*)g; - cnode = (PurpleBlistNode*)contact; - - if (cnode->parent) { - if (cnode->parent->child == cnode) - cnode->parent->child = cnode->next; - if (cnode->prev) - cnode->prev->next = cnode->next; - if (cnode->next) - cnode->next->prev = cnode->prev; - - if (cnode->parent != gnode) { - bnode = cnode->child; - while (bnode) { - PurpleBlistNode *next_bnode = bnode->next; - PurpleBuddy *b = (PurpleBuddy*)bnode; - GHashTable *account_buddies; - - struct _purple_hbuddy *hb, *hb2; - - hb = g_new(struct _purple_hbuddy, 1); - hb->name = g_strdup(purple_normalize(b->account, b->name)); - hb->account = b->account; - hb->group = cnode->parent; - - g_hash_table_remove(purplebuddylist->buddies, hb); - - account_buddies = g_hash_table_lookup(buddies_cache, b->account); - g_hash_table_remove(account_buddies, hb); - - if (!purple_find_buddy_in_group(b->account, b->name, g)) { - hb->group = gnode; - g_hash_table_replace(purplebuddylist->buddies, hb, b); - - hb2 = g_new(struct _purple_hbuddy, 1); - hb2->name = g_strdup(hb->name); - hb2->account = b->account; - hb2->group = gnode; - - g_hash_table_replace(account_buddies, hb2, b); - - if (purple_account_get_connection(b->account)) - serv_move_buddy(b, (PurpleGroup *)cnode->parent, g); - } else { - gboolean empty_contact = FALSE; - - /* this buddy already exists in the group, so we're - * gonna delete it instead */ - g_free(hb->name); - g_free(hb); - if (purple_account_get_connection(b->account)) - purple_account_remove_buddy(b->account, b, (PurpleGroup *)cnode->parent); - - if (!cnode->child->next) - empty_contact = TRUE; - purple_blist_remove_buddy(b); - - /** in purple_blist_remove_buddy(), if the last buddy in a - * contact is removed, the contact is cleaned up and - * g_free'd, so we mustn't try to reference bnode->next */ - if (empty_contact) - return; - } - bnode = next_bnode; - } - } - - if (contact->online > 0) - ((PurpleGroup*)cnode->parent)->online--; - if (contact->currentsize > 0) - ((PurpleGroup*)cnode->parent)->currentsize--; - ((PurpleGroup*)cnode->parent)->totalsize--; - - if (ops && ops->remove) - ops->remove(purplebuddylist, cnode); - - if (ops && ops->remove_node) - ops->remove_node(cnode); - } - - if (node && (PURPLE_BLIST_NODE_IS_CONTACT(node) || - PURPLE_BLIST_NODE_IS_CHAT(node))) { - if (node->next) - node->next->prev = cnode; - cnode->next = node->next; - cnode->prev = node; - cnode->parent = node->parent; - node->next = cnode; - } else { - if (gnode->child) - gnode->child->prev = cnode; - cnode->prev = NULL; - cnode->next = gnode->child; - gnode->child = cnode; - cnode->parent = gnode; - } - - if (contact->online > 0) - g->online++; - if (contact->currentsize > 0) - g->currentsize++; - g->totalsize++; - - if (ops && ops->save_node) - { - if (cnode->child) - ops->save_node(cnode); - for (bnode = cnode->child; bnode; bnode = bnode->next) - ops->save_node(bnode); - } - - if (ops && ops->update) - { - if (cnode->child) - ops->update(purplebuddylist, cnode); - - for (bnode = cnode->child; bnode; bnode = bnode->next) - ops->update(purplebuddylist, bnode); - } -} - -void purple_blist_merge_contact(PurpleContact *source, PurpleBlistNode *node) -{ - PurpleBlistNode *sourcenode = (PurpleBlistNode*)source; - PurpleBlistNode *prev, *cur, *next; - PurpleContact *target; - - g_return_if_fail(source != NULL); - g_return_if_fail(node != NULL); - - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { - target = (PurpleContact *)node; - prev = purple_blist_get_last_child(node); - } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { - target = (PurpleContact *)node->parent; - prev = node; - } else { - return; - } - - if (source == target || !target) - return; - - next = sourcenode->child; - - while (next) { - cur = next; - next = cur->next; - if (PURPLE_BLIST_NODE_IS_BUDDY(cur)) { - purple_blist_add_buddy((PurpleBuddy *)cur, target, NULL, prev); - prev = cur; - } - } -} - -void purple_blist_add_group(PurpleGroup *group, PurpleBlistNode *node) -{ - PurpleBlistUiOps *ops; - PurpleBlistNode *gnode = (PurpleBlistNode*)group; - gchar* key; - - g_return_if_fail(group != NULL); - g_return_if_fail(PURPLE_BLIST_NODE_IS_GROUP((PurpleBlistNode *)group)); - - ops = purple_blist_get_ui_ops(); - - /* if we're moving to overtop of ourselves, do nothing */ - if (gnode == node) { - if (!purplebuddylist->root) - node = NULL; - else - return; - } - - if (purple_find_group(group->name)) { - /* This is just being moved */ - - if (ops && ops->remove) - ops->remove(purplebuddylist, (PurpleBlistNode *)group); - - if (gnode == purplebuddylist->root) - purplebuddylist->root = gnode->next; - if (gnode->prev) - gnode->prev->next = gnode->next; - if (gnode->next) - gnode->next->prev = gnode->prev; - } else { - key = g_utf8_collate_key(group->name, -1); - g_hash_table_insert(groups_cache, key, group); - } - - if (node && PURPLE_BLIST_NODE_IS_GROUP(node)) { - gnode->next = node->next; - gnode->prev = node; - if (node->next) - node->next->prev = gnode; - node->next = gnode; - } else { - if (purplebuddylist->root) - purplebuddylist->root->prev = gnode; - gnode->next = purplebuddylist->root; - gnode->prev = NULL; - purplebuddylist->root = gnode; - } - - if (ops && ops->save_node) { - ops->save_node(gnode); - for (node = gnode->child; node; node = node->next) - ops->save_node(node); - } - - if (ops && ops->update) { - ops->update(purplebuddylist, gnode); - for (node = gnode->child; node; node = node->next) - ops->update(purplebuddylist, node); - } - - purple_signal_emit(purple_blist_get_handle(), "blist-node-added", - gnode); -} - -void purple_blist_remove_contact(PurpleContact *contact) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurpleBlistNode *node, *gnode; - PurpleGroup *group; - - g_return_if_fail(contact != NULL); - - node = (PurpleBlistNode *)contact; - gnode = node->parent; - group = PURPLE_GROUP(gnode); - - if (node->child) { - /* - * If this contact has children then remove them. When the last - * buddy is removed from the contact, the contact is automatically - * deleted. - */ - while (node->child->next) { - purple_blist_remove_buddy((PurpleBuddy*)node->child); - } - /* - * Remove the last buddy and trigger the deletion of the contact. - * It would probably be cleaner if contact-deletion was done after - * a timeout? Or if it had to be done manually, like below? - */ - purple_blist_remove_buddy((PurpleBuddy*)node->child); - } else { - /* Remove the node from its parent */ - if (gnode->child == node) - gnode->child = node->next; - if (node->prev) - node->prev->next = node->next; - if (node->next) - node->next->prev = node->prev; - group->totalsize--; - - /* Update the UI */ - if (ops && ops->remove) - ops->remove(purplebuddylist, node); - - if (ops && ops->remove_node) - ops->remove_node(node); - - purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", - PURPLE_BLIST_NODE(contact)); - - /* Delete the node */ - purple_contact_destroy(contact); - } -} - -void purple_blist_remove_buddy(PurpleBuddy *buddy) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurpleBlistNode *node, *cnode, *gnode; - PurpleContact *contact; - PurpleGroup *group; - struct _purple_hbuddy hb; - GHashTable *account_buddies; - - g_return_if_fail(buddy != NULL); - - node = (PurpleBlistNode *)buddy; - cnode = node->parent; - gnode = (cnode != NULL) ? cnode->parent : NULL; - contact = (PurpleContact *)cnode; - group = (PurpleGroup *)gnode; - - /* Remove the node from its parent */ - if (node->prev) - node->prev->next = node->next; - if (node->next) - node->next->prev = node->prev; - if ((cnode != NULL) && (cnode->child == node)) - cnode->child = node->next; - - /* Adjust size counts */ - if (contact != NULL) { - if (PURPLE_BUDDY_IS_ONLINE(buddy)) { - contact->online--; - if (contact->online == 0) - group->online--; - } - if (purple_account_is_connected(buddy->account)) { - contact->currentsize--; - if (contact->currentsize == 0) - group->currentsize--; - } - contact->totalsize--; - - /* Re-sort the contact */ - if (cnode->child && contact->priority == buddy) { - purple_contact_invalidate_priority_buddy(contact); - if (ops && ops->update) - ops->update(purplebuddylist, cnode); - } - } - - /* Remove this buddy from the buddies hash table */ - hb.name = (gchar *)purple_normalize(buddy->account, buddy->name); - hb.account = buddy->account; - hb.group = gnode; - g_hash_table_remove(purplebuddylist->buddies, &hb); - - account_buddies = g_hash_table_lookup(buddies_cache, buddy->account); - g_hash_table_remove(account_buddies, &hb); - - /* Update the UI */ - if (ops && ops->remove) - ops->remove(purplebuddylist, node); - - if (ops && ops->remove_node) - ops->remove_node(node); - - /* Remove this buddy's pounces */ - purple_pounce_destroy_all_by_buddy(buddy); - - /* Signal that the buddy has been removed before freeing the memory for it */ - purple_signal_emit(purple_blist_get_handle(), "buddy-removed", buddy); - - purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", - PURPLE_BLIST_NODE(buddy)); - - purple_buddy_destroy(buddy); - - /* If the contact is empty then remove it */ - if ((contact != NULL) && !cnode->child) - purple_blist_remove_contact(contact); -} - -void purple_blist_remove_chat(PurpleChat *chat) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurpleBlistNode *node, *gnode; - PurpleGroup *group; - - g_return_if_fail(chat != NULL); - - node = (PurpleBlistNode *)chat; - gnode = node->parent; - group = (PurpleGroup *)gnode; - - if (gnode != NULL) - { - /* Remove the node from its parent */ - if (gnode->child == node) - gnode->child = node->next; - if (node->prev) - node->prev->next = node->next; - if (node->next) - node->next->prev = node->prev; - - /* Adjust size counts */ - if (purple_account_is_connected(chat->account)) { - group->online--; - group->currentsize--; - } - group->totalsize--; - - } - - /* Update the UI */ - if (ops && ops->remove) - ops->remove(purplebuddylist, node); - - if (ops && ops->remove_node) - ops->remove_node(node); - - purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", - PURPLE_BLIST_NODE(chat)); - - /* Delete the node */ - purple_chat_destroy(chat); -} - -void purple_blist_remove_group(PurpleGroup *group) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurpleBlistNode *node; - GList *l; - gchar* key; - - g_return_if_fail(group != NULL); - - node = (PurpleBlistNode *)group; - - /* Make sure the group is empty */ - if (node->child) - return; - - /* Remove the node from its parent */ - if (purplebuddylist->root == node) - purplebuddylist->root = node->next; - if (node->prev) - node->prev->next = node->next; - if (node->next) - node->next->prev = node->prev; - - key = g_utf8_collate_key(group->name, -1); - g_hash_table_remove(groups_cache, key); - g_free(key); - - /* Update the UI */ - if (ops && ops->remove) - ops->remove(purplebuddylist, node); - - if (ops && ops->remove_node) - ops->remove_node(node); - - purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", - PURPLE_BLIST_NODE(group)); - - /* Remove the group from all accounts that are online */ - for (l = purple_connections_get_all(); l != NULL; l = l->next) - { - PurpleConnection *gc = (PurpleConnection *)l->data; - - if (purple_connection_get_state(gc) == PURPLE_CONNECTED) - purple_account_remove_group(purple_connection_get_account(gc), group); - } - - /* Delete the node */ - purple_group_destroy(group); -} - -PurpleBuddy *purple_contact_get_priority_buddy(PurpleContact *contact) -{ - g_return_val_if_fail(contact != NULL, NULL); - - if (!contact->priority_valid) - purple_contact_compute_priority_buddy(contact); - - return contact->priority; -} - -const char *purple_buddy_get_alias_only(PurpleBuddy *buddy) -{ - g_return_val_if_fail(buddy != NULL, NULL); - - if ((buddy->alias != NULL) && (*buddy->alias != '\0')) { - return buddy->alias; - } else if ((buddy->server_alias != NULL) && - (*buddy->server_alias != '\0')) { - - return buddy->server_alias; - } - - return NULL; -} - - -const char *purple_buddy_get_contact_alias(PurpleBuddy *buddy) -{ - PurpleContact *c; - - g_return_val_if_fail(buddy != NULL, NULL); - - /* Search for an alias for the buddy. In order of precedence: */ - /* The buddy alias */ - if (buddy->alias != NULL) - return buddy->alias; - - /* The contact alias */ - c = purple_buddy_get_contact(buddy); - if ((c != NULL) && (c->alias != NULL)) - return c->alias; - - /* The server alias */ - if ((buddy->server_alias) && (*buddy->server_alias)) - return buddy->server_alias; - - /* The buddy's user name (i.e. no alias) */ - return buddy->name; -} - - -const char *purple_buddy_get_alias(PurpleBuddy *buddy) -{ - g_return_val_if_fail(buddy != NULL, NULL); - - /* Search for an alias for the buddy. In order of precedence: */ - /* The buddy alias */ - if (buddy->alias != NULL) - return buddy->alias; - - /* The server alias */ - if ((buddy->server_alias) && (*buddy->server_alias)) - return buddy->server_alias; - - /* The buddy's user name (i.e. no alias) */ - return buddy->name; -} - -const char *purple_buddy_get_local_buddy_alias(PurpleBuddy *buddy) -{ - g_return_val_if_fail(buddy, NULL); - return buddy->alias; -} - -const char *purple_buddy_get_server_alias(PurpleBuddy *buddy) -{ - g_return_val_if_fail(buddy != NULL, NULL); - - if ((buddy->server_alias) && (*buddy->server_alias)) - return buddy->server_alias; - - return NULL; -} - -const char *purple_chat_get_name(PurpleChat *chat) -{ - char *ret = NULL; - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info = NULL; - - g_return_val_if_fail(chat != NULL, NULL); - - if ((chat->alias != NULL) && (*chat->alias != '\0')) - return chat->alias; - - prpl = purple_find_prpl(purple_account_get_protocol_id(chat->account)); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if (prpl_info->chat_info) { - struct proto_chat_entry *pce; - GList *parts = prpl_info->chat_info(purple_account_get_connection(chat->account)); - pce = parts->data; - ret = g_hash_table_lookup(chat->components, pce->identifier); - g_list_foreach(parts, (GFunc)g_free, NULL); - g_list_free(parts); - } - - return ret; -} - -PurpleBuddy *purple_find_buddy(PurpleAccount *account, const char *name) -{ - PurpleBuddy *buddy; - struct _purple_hbuddy hb; - PurpleBlistNode *group; - - g_return_val_if_fail(purplebuddylist != NULL, NULL); - g_return_val_if_fail(account != NULL, NULL); - g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL); - - hb.account = account; - hb.name = (gchar *)purple_normalize(account, name); - - for (group = purplebuddylist->root; group; group = group->next) { - if (!group->child) - continue; - - hb.group = group; - if ((buddy = g_hash_table_lookup(purplebuddylist->buddies, &hb))) { - return buddy; - } - } - - return NULL; -} - -PurpleBuddy *purple_find_buddy_in_group(PurpleAccount *account, const char *name, - PurpleGroup *group) -{ - struct _purple_hbuddy hb; - - g_return_val_if_fail(purplebuddylist != NULL, NULL); - g_return_val_if_fail(account != NULL, NULL); - g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL); - - hb.name = (gchar *)purple_normalize(account, name); - hb.account = account; - hb.group = (PurpleBlistNode*)group; - - return g_hash_table_lookup(purplebuddylist->buddies, &hb); -} - -static void find_acct_buddies(gpointer key, gpointer value, gpointer data) -{ - PurpleBuddy *buddy = value; - GSList **list = data; - - *list = g_slist_prepend(*list, buddy); -} - -GSList *purple_find_buddies(PurpleAccount *account, const char *name) -{ - PurpleBuddy *buddy; - PurpleBlistNode *node; - GSList *ret = NULL; - - g_return_val_if_fail(purplebuddylist != NULL, NULL); - g_return_val_if_fail(account != NULL, NULL); - - if ((name != NULL) && (*name != '\0')) { - struct _purple_hbuddy hb; - - hb.name = (gchar *)purple_normalize(account, name); - hb.account = account; - - for (node = purplebuddylist->root; node != NULL; node = node->next) { - if (!node->child) - continue; - - hb.group = node; - if ((buddy = g_hash_table_lookup(purplebuddylist->buddies, &hb)) != NULL) - ret = g_slist_prepend(ret, buddy); - } - } else { - GSList *list = NULL; - GHashTable *buddies = g_hash_table_lookup(buddies_cache, account); - g_hash_table_foreach(buddies, find_acct_buddies, &list); - ret = list; - } - - return ret; -} - -PurpleGroup *purple_find_group(const char *name) -{ - gchar* key; - PurpleGroup *group; - - g_return_val_if_fail(purplebuddylist != NULL, NULL); - g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL); - - key = g_utf8_collate_key(name, -1); - group = g_hash_table_lookup(groups_cache, key); - g_free(key); - - return group; -} - -PurpleChat * -purple_blist_find_chat(PurpleAccount *account, const char *name) -{ - char *chat_name; - PurpleChat *chat; - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info = NULL; - struct proto_chat_entry *pce; - PurpleBlistNode *node, *group; - GList *parts; - char *normname; - - g_return_val_if_fail(purplebuddylist != NULL, NULL); - g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL); - - if (!purple_account_is_connected(account)) - return NULL; - - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if (prpl_info->find_blist_chat != NULL) - return prpl_info->find_blist_chat(account, name); - - normname = g_strdup(purple_normalize(account, name)); - for (group = purplebuddylist->root; group != NULL; group = group->next) { - for (node = group->child; node != NULL; node = node->next) { - if (PURPLE_BLIST_NODE_IS_CHAT(node)) { - - chat = (PurpleChat*)node; - - if (account != chat->account) - continue; - - parts = prpl_info->chat_info( - purple_account_get_connection(chat->account)); - - pce = parts->data; - chat_name = g_hash_table_lookup(chat->components, - pce->identifier); - g_list_foreach(parts, (GFunc)g_free, NULL); - g_list_free(parts); - - if (chat->account == account && chat_name != NULL && - normname != NULL && !strcmp(purple_normalize(account, chat_name), normname)) { - g_free(normname); - return chat; - } - } - } - } - - g_free(normname); - return NULL; -} - -PurpleGroup * -purple_chat_get_group(PurpleChat *chat) -{ - g_return_val_if_fail(chat != NULL, NULL); - - return (PurpleGroup *)(((PurpleBlistNode *)chat)->parent); -} - -PurpleAccount * -purple_chat_get_account(PurpleChat *chat) -{ - g_return_val_if_fail(chat != NULL, NULL); - - return chat->account; -} - -GHashTable * -purple_chat_get_components(PurpleChat *chat) -{ - g_return_val_if_fail(chat != NULL, NULL); - - return chat->components; -} - -PurpleContact *purple_buddy_get_contact(PurpleBuddy *buddy) -{ - g_return_val_if_fail(buddy != NULL, NULL); - - return PURPLE_CONTACT(PURPLE_BLIST_NODE(buddy)->parent); -} - -PurplePresence *purple_buddy_get_presence(const PurpleBuddy *buddy) -{ - g_return_val_if_fail(buddy != NULL, NULL); - return buddy->presence; -} - -PurpleMediaCaps purple_buddy_get_media_caps(const PurpleBuddy *buddy) -{ - g_return_val_if_fail(buddy != NULL, 0); - return buddy->media_caps; -} - -void purple_buddy_set_media_caps(PurpleBuddy *buddy, PurpleMediaCaps media_caps) -{ - g_return_if_fail(buddy != NULL); - buddy->media_caps = media_caps; -} - -PurpleGroup *purple_buddy_get_group(PurpleBuddy *buddy) -{ - g_return_val_if_fail(buddy != NULL, NULL); - - if (((PurpleBlistNode *)buddy)->parent == NULL) - return NULL; - - return (PurpleGroup *)(((PurpleBlistNode*)buddy)->parent->parent); -} - -GSList *purple_group_get_accounts(PurpleGroup *group) -{ - GSList *l = NULL; - PurpleBlistNode *gnode, *cnode, *bnode; - - gnode = (PurpleBlistNode *)group; - - for (cnode = gnode->child; cnode; cnode = cnode->next) { - if (PURPLE_BLIST_NODE_IS_CHAT(cnode)) { - if (!g_slist_find(l, ((PurpleChat *)cnode)->account)) - l = g_slist_append(l, ((PurpleChat *)cnode)->account); - } else if (PURPLE_BLIST_NODE_IS_CONTACT(cnode)) { - for (bnode = cnode->child; bnode; bnode = bnode->next) { - if (PURPLE_BLIST_NODE_IS_BUDDY(bnode)) { - if (!g_slist_find(l, ((PurpleBuddy *)bnode)->account)) - l = g_slist_append(l, ((PurpleBuddy *)bnode)->account); - } - } - } - } - - return l; -} - -void purple_blist_add_account(PurpleAccount *account) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurpleBlistNode *gnode, *cnode, *bnode; - - g_return_if_fail(purplebuddylist != NULL); - - if (!ops || !ops->update) - return; - - for (gnode = purplebuddylist->root; gnode; gnode = gnode->next) { - if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) - continue; - for (cnode = gnode->child; cnode; cnode = cnode->next) { - if (PURPLE_BLIST_NODE_IS_CONTACT(cnode)) { - gboolean recompute = FALSE; - for (bnode = cnode->child; bnode; bnode = bnode->next) { - if (PURPLE_BLIST_NODE_IS_BUDDY(bnode) && - ((PurpleBuddy*)bnode)->account == account) { - recompute = TRUE; - ((PurpleContact*)cnode)->currentsize++; - if (((PurpleContact*)cnode)->currentsize == 1) - ((PurpleGroup*)gnode)->currentsize++; - ops->update(purplebuddylist, bnode); - } - } - if (recompute || - purple_blist_node_get_bool(cnode, "show_offline")) { - purple_contact_invalidate_priority_buddy((PurpleContact*)cnode); - ops->update(purplebuddylist, cnode); - } - } else if (PURPLE_BLIST_NODE_IS_CHAT(cnode) && - ((PurpleChat*)cnode)->account == account) { - ((PurpleGroup *)gnode)->online++; - ((PurpleGroup *)gnode)->currentsize++; - ops->update(purplebuddylist, cnode); - } - } - ops->update(purplebuddylist, gnode); - } -} - -void purple_blist_remove_account(PurpleAccount *account) -{ - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurpleBlistNode *gnode, *cnode, *bnode; - PurpleBuddy *buddy; - PurpleChat *chat; - PurpleContact *contact; - PurpleGroup *group; - GList *list = NULL, *iter = NULL; - - g_return_if_fail(purplebuddylist != NULL); - - for (gnode = purplebuddylist->root; gnode; gnode = gnode->next) { - if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) - continue; - - group = (PurpleGroup *)gnode; - - for (cnode = gnode->child; cnode; cnode = cnode->next) { - if (PURPLE_BLIST_NODE_IS_CONTACT(cnode)) { - gboolean recompute = FALSE; - contact = (PurpleContact *)cnode; - - for (bnode = cnode->child; bnode; bnode = bnode->next) { - if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) - continue; - - buddy = (PurpleBuddy *)bnode; - if (account == buddy->account) { - PurplePresence *presence; - - presence = purple_buddy_get_presence(buddy); - - if(purple_presence_is_online(presence)) { - contact->online--; - if (contact->online == 0) - group->online--; - - purple_blist_node_set_int(&buddy->node, - "last_seen", time(NULL)); - } - - contact->currentsize--; - if (contact->currentsize == 0) - group->currentsize--; - - if (!g_list_find(list, presence)) - list = g_list_prepend(list, presence); - - if (contact->priority == buddy) - purple_contact_invalidate_priority_buddy(contact); - else - recompute = TRUE; - - if (ops && ops->remove) { - ops->remove(purplebuddylist, bnode); - } - } - } - if (recompute) { - purple_contact_invalidate_priority_buddy(contact); - if (ops && ops->update) - ops->update(purplebuddylist, cnode); - } - } else if (PURPLE_BLIST_NODE_IS_CHAT(cnode)) { - chat = (PurpleChat *)cnode; - - if(chat->account == account) { - group->currentsize--; - group->online--; - - if (ops && ops->remove) - ops->remove(purplebuddylist, cnode); - } - } - } - } - - for (iter = list; iter; iter = iter->next) - { - purple_presence_set_status_active(iter->data, "offline", TRUE); - } - g_list_free(list); -} - -gboolean purple_group_on_account(PurpleGroup *g, PurpleAccount *account) -{ - PurpleBlistNode *cnode; - for (cnode = ((PurpleBlistNode *)g)->child; cnode; cnode = cnode->next) { - if (PURPLE_BLIST_NODE_IS_CONTACT(cnode)) { - if(purple_contact_on_account((PurpleContact *) cnode, account)) - return TRUE; - } else if (PURPLE_BLIST_NODE_IS_CHAT(cnode)) { - PurpleChat *chat = (PurpleChat *)cnode; - if ((!account && purple_account_is_connected(chat->account)) - || chat->account == account) - return TRUE; - } - } - return FALSE; -} - -const char *purple_group_get_name(PurpleGroup *group) -{ - g_return_val_if_fail(group != NULL, NULL); - - return group->name; -} - -void -purple_blist_request_add_buddy(PurpleAccount *account, const char *username, - const char *group, const char *alias) -{ - PurpleBlistUiOps *ui_ops; - - ui_ops = purple_blist_get_ui_ops(); - - if (ui_ops != NULL && ui_ops->request_add_buddy != NULL) - ui_ops->request_add_buddy(account, username, group, alias); -} - -void -purple_blist_request_add_chat(PurpleAccount *account, PurpleGroup *group, - const char *alias, const char *name) -{ - PurpleBlistUiOps *ui_ops; - - ui_ops = purple_blist_get_ui_ops(); - - if (ui_ops != NULL && ui_ops->request_add_chat != NULL) - ui_ops->request_add_chat(account, group, alias, name); -} - -void -purple_blist_request_add_group(void) -{ - PurpleBlistUiOps *ui_ops; - - ui_ops = purple_blist_get_ui_ops(); - - if (ui_ops != NULL && ui_ops->request_add_group != NULL) - ui_ops->request_add_group(); -} - -static void -purple_blist_node_destroy(PurpleBlistNode *node) -{ - PurpleBlistUiOps *ui_ops; - PurpleBlistNode *child, *next_child; - - ui_ops = purple_blist_get_ui_ops(); - child = node->child; - while (child) { - next_child = child->next; - purple_blist_node_destroy(child); - child = next_child; - } - - /* Allow the UI to free data */ - node->parent = NULL; - node->child = NULL; - node->next = NULL; - node->prev = NULL; - if (ui_ops && ui_ops->remove) - ui_ops->remove(purplebuddylist, node); - - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) - purple_buddy_destroy((PurpleBuddy*)node); - else if (PURPLE_BLIST_NODE_IS_CHAT(node)) - purple_chat_destroy((PurpleChat*)node); - else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) - purple_contact_destroy((PurpleContact*)node); - else if (PURPLE_BLIST_NODE_IS_GROUP(node)) - purple_group_destroy((PurpleGroup*)node); -} - -static void -purple_blist_node_setting_free(gpointer data) -{ - PurpleValue *value; - - value = (PurpleValue *)data; - - purple_value_destroy(value); -} - -static void purple_blist_node_initialize_settings(PurpleBlistNode *node) -{ - if (node->settings) - return; - - node->settings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, - (GDestroyNotify)purple_blist_node_setting_free); -} - -void purple_blist_node_remove_setting(PurpleBlistNode *node, const char *key) -{ - PurpleBlistUiOps *ops; - g_return_if_fail(node != NULL); - g_return_if_fail(node->settings != NULL); - g_return_if_fail(key != NULL); - - g_hash_table_remove(node->settings, key); - - ops = purple_blist_get_ui_ops(); - if (ops && ops->save_node) - ops->save_node(node); -} - -void -purple_blist_node_set_flags(PurpleBlistNode *node, PurpleBlistNodeFlags flags) -{ - g_return_if_fail(node != NULL); - - node->flags = flags; -} - -PurpleBlistNodeFlags -purple_blist_node_get_flags(PurpleBlistNode *node) -{ - g_return_val_if_fail(node != NULL, 0); - - return node->flags; -} - -PurpleBlistNodeType -purple_blist_node_get_type(PurpleBlistNode *node) -{ - g_return_val_if_fail(node != NULL, PURPLE_BLIST_OTHER_NODE); - return node->type; -} - -gboolean -purple_blist_node_has_setting(PurpleBlistNode* node, const char *key) -{ - g_return_val_if_fail(node != NULL, FALSE); - g_return_val_if_fail(node->settings != NULL, FALSE); - g_return_val_if_fail(key != NULL, FALSE); - - /* Boxed type, so it won't ever be NULL, so no need for _extended */ - return (g_hash_table_lookup(node->settings, key) != NULL); -} - -void -purple_blist_node_set_bool(PurpleBlistNode* node, const char *key, gboolean data) -{ - PurpleValue *value; - PurpleBlistUiOps *ops; - - g_return_if_fail(node != NULL); - g_return_if_fail(node->settings != NULL); - g_return_if_fail(key != NULL); - - value = purple_value_new(PURPLE_TYPE_BOOLEAN); - purple_value_set_boolean(value, data); - - g_hash_table_replace(node->settings, g_strdup(key), value); - - ops = purple_blist_get_ui_ops(); - if (ops && ops->save_node) - ops->save_node(node); -} - -gboolean -purple_blist_node_get_bool(PurpleBlistNode* node, const char *key) -{ - PurpleValue *value; - - g_return_val_if_fail(node != NULL, FALSE); - g_return_val_if_fail(node->settings != NULL, FALSE); - g_return_val_if_fail(key != NULL, FALSE); - - value = g_hash_table_lookup(node->settings, key); - - if (value == NULL) - return FALSE; - - g_return_val_if_fail(purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN, FALSE); - - return purple_value_get_boolean(value); -} - -void -purple_blist_node_set_int(PurpleBlistNode* node, const char *key, int data) -{ - PurpleValue *value; - PurpleBlistUiOps *ops; - - g_return_if_fail(node != NULL); - g_return_if_fail(node->settings != NULL); - g_return_if_fail(key != NULL); - - value = purple_value_new(PURPLE_TYPE_INT); - purple_value_set_int(value, data); - - g_hash_table_replace(node->settings, g_strdup(key), value); - - ops = purple_blist_get_ui_ops(); - if (ops && ops->save_node) - ops->save_node(node); -} - -int -purple_blist_node_get_int(PurpleBlistNode* node, const char *key) -{ - PurpleValue *value; - - g_return_val_if_fail(node != NULL, 0); - g_return_val_if_fail(node->settings != NULL, 0); - g_return_val_if_fail(key != NULL, 0); - - value = g_hash_table_lookup(node->settings, key); - - if (value == NULL) - return 0; - - g_return_val_if_fail(purple_value_get_type(value) == PURPLE_TYPE_INT, 0); - - return purple_value_get_int(value); -} - -void -purple_blist_node_set_string(PurpleBlistNode* node, const char *key, const char *data) -{ - PurpleValue *value; - PurpleBlistUiOps *ops; - - g_return_if_fail(node != NULL); - g_return_if_fail(node->settings != NULL); - g_return_if_fail(key != NULL); - - value = purple_value_new(PURPLE_TYPE_STRING); - purple_value_set_string(value, data); - - g_hash_table_replace(node->settings, g_strdup(key), value); - - ops = purple_blist_get_ui_ops(); - if (ops && ops->save_node) - ops->save_node(node); -} - -const char * -purple_blist_node_get_string(PurpleBlistNode* node, const char *key) -{ - PurpleValue *value; - - g_return_val_if_fail(node != NULL, NULL); - g_return_val_if_fail(node->settings != NULL, NULL); - g_return_val_if_fail(key != NULL, NULL); - - value = g_hash_table_lookup(node->settings, key); - - if (value == NULL) - return NULL; - - g_return_val_if_fail(purple_value_get_type(value) == PURPLE_TYPE_STRING, NULL); - - return purple_value_get_string(value); -} - -GList * -purple_blist_node_get_extended_menu(PurpleBlistNode *n) -{ - GList *menu = NULL; - - g_return_val_if_fail(n != NULL, NULL); - - purple_signal_emit(purple_blist_get_handle(), - "blist-node-extended-menu", - n, &menu); - return menu; -} - -int purple_blist_get_group_size(PurpleGroup *group, gboolean offline) -{ - if (!group) - return 0; - - return offline ? group->totalsize : group->currentsize; -} - -int purple_blist_get_group_online_count(PurpleGroup *group) -{ - if (!group) - return 0; - - return group->online; -} - -void -purple_blist_set_ui_ops(PurpleBlistUiOps *ops) -{ - gboolean overrode = FALSE; - blist_ui_ops = ops; - - if (!ops) - return; - - if (!ops->save_node) { - ops->save_node = purple_blist_save_node; - overrode = TRUE; - } - if (!ops->remove_node) { - ops->remove_node = purple_blist_save_node; - overrode = TRUE; - } - if (!ops->save_account) { - ops->save_account = purple_blist_save_account; - overrode = TRUE; - } - - if (overrode && (ops->save_node != purple_blist_save_node || - ops->remove_node != purple_blist_save_node || - ops->save_account != purple_blist_save_account)) { - purple_debug_warning("blist", "Only some of the blist saving UI ops " - "were overridden. This probably is not what you want!\n"); - } -} - -PurpleBlistUiOps * -purple_blist_get_ui_ops(void) -{ - return blist_ui_ops; -} - - -void * -purple_blist_get_handle(void) -{ - static int handle; - - return &handle; -} - -void -purple_blist_init(void) -{ - void *handle = purple_blist_get_handle(); - - purple_signal_register(handle, "buddy-status-changed", - purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, - 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_BUDDY), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_STATUS), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_STATUS)); - purple_signal_register(handle, "buddy-privacy-changed", - purple_marshal_VOID__POINTER, NULL, - 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_BUDDY)); - - purple_signal_register(handle, "buddy-idle-changed", - purple_marshal_VOID__POINTER_INT_INT, NULL, - 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_BUDDY), - purple_value_new(PURPLE_TYPE_INT), - purple_value_new(PURPLE_TYPE_INT)); - - - purple_signal_register(handle, "buddy-signed-on", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_BUDDY)); - - purple_signal_register(handle, "buddy-signed-off", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_BUDDY)); - - purple_signal_register(handle, "buddy-got-login-time", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_BUDDY)); - - purple_signal_register(handle, "blist-node-added", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_NODE)); - - purple_signal_register(handle, "blist-node-removed", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_NODE)); - - purple_signal_register(handle, "buddy-added", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_BUDDY)); - - purple_signal_register(handle, "buddy-removed", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_BUDDY)); - - purple_signal_register(handle, "buddy-icon-changed", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_BUDDY)); - - purple_signal_register(handle, "update-idle", purple_marshal_VOID, NULL, 0); - - purple_signal_register(handle, "blist-node-extended-menu", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_NODE), - purple_value_new(PURPLE_TYPE_BOXED, "GList **")); - - purple_signal_register(handle, "blist-node-aliased", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_NODE), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "buddy-caps-changed", - purple_marshal_VOID__POINTER_INT_INT, NULL, - 3, purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_BUDDY), - purple_value_new(PURPLE_TYPE_INT), - purple_value_new(PURPLE_TYPE_INT)); - - purple_signal_connect(purple_accounts_get_handle(), "account-created", - handle, - PURPLE_CALLBACK(purple_blist_buddies_cache_add_account), - NULL); - - purple_signal_connect(purple_accounts_get_handle(), "account-destroying", - handle, - PURPLE_CALLBACK(purple_blist_buddies_cache_remove_account), - NULL); -} - -void -purple_blist_uninit(void) -{ - PurpleBlistNode *node, *next_node; - - /* This happens if we quit before purple_set_blist is called. */ - if (purplebuddylist == NULL) - return; - - if (save_timer != 0) { - purple_timeout_remove(save_timer); - save_timer = 0; - purple_blist_sync(); - } - - purple_blist_destroy(); - - node = purple_blist_get_root(); - while (node) { - next_node = node->next; - purple_blist_node_destroy(node); - node = next_node; - } - purplebuddylist->root = NULL; - - g_hash_table_destroy(purplebuddylist->buddies); - g_hash_table_destroy(buddies_cache); - g_hash_table_destroy(groups_cache); - - buddies_cache = NULL; - groups_cache = NULL; - - PURPLE_DBUS_UNREGISTER_POINTER(purplebuddylist); - g_free(purplebuddylist); - purplebuddylist = NULL; - - purple_signals_disconnect_by_handle(purple_blist_get_handle()); - purple_signals_unregister_by_instance(purple_blist_get_handle()); -} diff --git a/libpurple/blist.h b/libpurple/blist.h deleted file mode 100644 index eddbef948d..0000000000 --- a/libpurple/blist.h +++ /dev/null @@ -1,1204 +0,0 @@ -/** - * @file blist.h Buddy List API - * @ingroup core - * @see @ref blist-signals - */ - -/* purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _PURPLE_BLIST_H_ -#define _PURPLE_BLIST_H_ - -/* I can't believe I let ChipX86 inspire me to write good code. -Sean */ - -#include <glib.h> - -/** @copydoc _PurpleBuddyList */ -typedef struct _PurpleBuddyList PurpleBuddyList; -/** @copydoc _PurpleBlistUiOps */ -typedef struct _PurpleBlistUiOps PurpleBlistUiOps; -/** @copydoc _PurpleBlistNode */ -typedef struct _PurpleBlistNode PurpleBlistNode; - -/** @copydoc _PurpleChat */ -typedef struct _PurpleChat PurpleChat; -/** @copydoc _PurpleGroup */ -typedef struct _PurpleGroup PurpleGroup; -/** @copydoc _PurpleContact */ -typedef struct _PurpleContact PurpleContact; -/** @copydoc _PurpleBuddy */ -typedef struct _PurpleBuddy PurpleBuddy; - -/**************************************************************************/ -/* Enumerations */ -/**************************************************************************/ -typedef enum -{ - PURPLE_BLIST_GROUP_NODE, - PURPLE_BLIST_CONTACT_NODE, - PURPLE_BLIST_BUDDY_NODE, - PURPLE_BLIST_CHAT_NODE, - PURPLE_BLIST_OTHER_NODE - -} PurpleBlistNodeType; - -#define PURPLE_BLIST_NODE_IS_CHAT(n) (purple_blist_node_get_type(n) == PURPLE_BLIST_CHAT_NODE) -#define PURPLE_BLIST_NODE_IS_BUDDY(n) (purple_blist_node_get_type(n) == PURPLE_BLIST_BUDDY_NODE) -#define PURPLE_BLIST_NODE_IS_CONTACT(n) (purple_blist_node_get_type(n) == PURPLE_BLIST_CONTACT_NODE) -#define PURPLE_BLIST_NODE_IS_GROUP(n) (purple_blist_node_get_type(n) == PURPLE_BLIST_GROUP_NODE) - -#define PURPLE_BUDDY_IS_ONLINE(b) \ - ((b) != NULL && purple_account_is_connected(purple_buddy_get_account(b)) && \ - purple_presence_is_online(purple_buddy_get_presence(b))) - -typedef enum -{ - PURPLE_BLIST_NODE_FLAG_NO_SAVE = 1 << 0 /**< node should not be saved with the buddy list */ - -} PurpleBlistNodeFlags; - -#define PURPLE_BLIST_NODE(obj) ((PurpleBlistNode *)(obj)) - -#define PURPLE_BLIST_NODE_HAS_FLAG(b, f) (purple_blist_node_get_flags((PurpleBlistNode*)(b)) & (f)) -#define PURPLE_BLIST_NODE_SHOULD_SAVE(b) (! PURPLE_BLIST_NODE_HAS_FLAG(b, PURPLE_BLIST_NODE_FLAG_NO_SAVE)) - -#define PURPLE_BLIST_NODE_NAME(n) (purple_blist_node_get_type(n) == PURPLE_BLIST_CHAT_NODE ? purple_chat_get_name((PurpleChat*)n) : \ - purple_blist_node_get_type(n) == PURPLE_BLIST_BUDDY_NODE ? purple_buddy_get_name((PurpleBuddy*)n) : NULL) - -#define PURPLE_GROUP(obj) ((PurpleGroup *)(obj)) - -#define PURPLE_CONTACT(obj) ((PurpleContact *)(obj)) - -#define PURPLE_BUDDY(obj) ((PurpleBuddy *)(obj)) - -#define PURPLE_CHAT(obj) ((PurpleChat *)(obj)) - -#include "account.h" -#include "buddyicon.h" -#include "media.h" -#include "status.h" - -/**************************************************************************/ -/* Data Structures */ -/**************************************************************************/ - -#if !(defined PURPLE_HIDE_STRUCTS) || (defined _PURPLE_BLIST_C_) - -/** - * A Buddy list node. This can represent a group, a buddy, or anything else. - * This is a base class for PurpleBuddy, PurpleContact, PurpleGroup, and for - * anything else that wants to put itself in the buddy list. */ -struct _PurpleBlistNode { - PurpleBlistNodeType type; /**< The type of node this is */ - PurpleBlistNode *prev; /**< The sibling before this buddy. */ - PurpleBlistNode *next; /**< The sibling after this buddy. */ - PurpleBlistNode *parent; /**< The parent of this node */ - PurpleBlistNode *child; /**< The child of this node */ - GHashTable *settings; /**< per-node settings */ - void *ui_data; /**< The UI can put data here. */ - PurpleBlistNodeFlags flags; /**< The buddy flags */ -}; - -/** - * A buddy. This contains everything Purple will ever need to know about someone on the buddy list. Everything. - */ -struct _PurpleBuddy { - PurpleBlistNode node; /**< The node that this buddy inherits from */ - char *name; /**< The name of the buddy. */ - char *alias; /**< The user-set alias of the buddy */ - char *server_alias; /**< The server-specified alias of the buddy. (i.e. MSN "Friendly Names") */ - void *proto_data; /**< This allows the prpl to associate whatever data it wants with a buddy */ - PurpleBuddyIcon *icon; /**< The buddy icon. */ - PurpleAccount *account; /**< the account this buddy belongs to */ - PurplePresence *presence; - PurpleMediaCaps media_caps; /**< The media capabilities of the buddy. */ -}; - -/** - * A contact. This contains everything Purple will ever need to know about a contact. - */ -struct _PurpleContact { - PurpleBlistNode node; /**< The node that this contact inherits from. */ - char *alias; /**< The user-set alias of the contact */ - int totalsize; /**< The number of buddies in this contact */ - int currentsize; /**< The number of buddies in this contact corresponding to online accounts */ - int online; /**< The number of buddies in this contact who are currently online */ - PurpleBuddy *priority; /**< The "top" buddy for this contact */ - gboolean priority_valid; /**< Is priority valid? */ -}; - - -/** - * A group. This contains everything Purple will ever need to know about a group. - */ -struct _PurpleGroup { - PurpleBlistNode node; /**< The node that this group inherits from */ - char *name; /**< The name of this group. */ - int totalsize; /**< The number of chats and contacts in this group */ - int currentsize; /**< The number of chats and contacts in this group corresponding to online accounts */ - int online; /**< The number of chats and contacts in this group who are currently online */ -}; - -/** - * A chat. This contains everything Purple needs to put a chat room in the - * buddy list. - */ -struct _PurpleChat { - PurpleBlistNode node; /**< The node that this chat inherits from */ - char *alias; /**< The display name of this chat. */ - GHashTable *components; /**< the stuff the protocol needs to know to join the chat */ - PurpleAccount *account; /**< The account this chat is attached to */ -}; - -/** - * The Buddy List - */ -struct _PurpleBuddyList { - PurpleBlistNode *root; /**< The first node in the buddy list */ - GHashTable *buddies; /**< Every buddy in this list */ - void *ui_data; /**< UI-specific data. */ -}; - -#endif /* PURPLE_HIDE_STRUCTS && PURPLE_BLIST_STRUCTS */ - -/** - * Buddy list UI operations. - * - * Any UI representing a buddy list must assign a filled-out PurpleBlistUiOps - * structure to the buddy list core. - */ -struct _PurpleBlistUiOps -{ - void (*new_list)(PurpleBuddyList *list); /**< Sets UI-specific data on a buddy list. */ - void (*new_node)(PurpleBlistNode *node); /**< Sets UI-specific data on a node. */ - void (*show)(PurpleBuddyList *list); /**< The core will call this when it's finished doing its core stuff */ - void (*update)(PurpleBuddyList *list, - PurpleBlistNode *node); /**< This will update a node in the buddy list. */ - void (*remove)(PurpleBuddyList *list, - PurpleBlistNode *node); /**< This removes a node from the list */ - void (*destroy)(PurpleBuddyList *list); /**< When the list is destroyed, this is called to destroy the UI. */ - void (*set_visible)(PurpleBuddyList *list, - gboolean show); /**< Hides or unhides the buddy list */ - void (*request_add_buddy)(PurpleAccount *account, const char *username, - const char *group, const char *alias); - void (*request_add_chat)(PurpleAccount *account, PurpleGroup *group, - const char *alias, const char *name); - void (*request_add_group)(void); - - /** - * This is called when a node has been modified and should be saved. - * - * Implementation of this UI op is OPTIONAL. If not implemented, it will - * be set to a fallback function that saves data to blist.xml like in - * previous libpurple versions. - * - * @param node The node which has been modified. - */ - void (*save_node)(PurpleBlistNode *node); - - /** - * Called when a node is about to be removed from the buddy list. - * The UI op should update the relevant data structures to remove this - * node (for example, removing a buddy from the group this node is in). - * - * Implementation of this UI op is OPTIONAL. If not implemented, it will - * be set to a fallback function that saves data to blist.xml like in - * previous libpurple versions. - * - * @param node The node which has been modified. - */ - void (*remove_node)(PurpleBlistNode *node); - - /** - * Called to save all the data for an account. If the UI sets this, - * the callback must save the privacy and buddy list data for an account. - * If the account is NULL, save the data for all accounts. - * - * Implementation of this UI op is OPTIONAL. If not implemented, it will - * be set to a fallback function that saves data to blist.xml like in - * previous libpurple versions. - * - * @param account The account whose data to save. If NULL, save all data - * for all accounts. - */ - void (*save_account)(PurpleAccount *account); - - void (*_purple_reserved1)(void); -}; - -G_BEGIN_DECLS - -/**************************************************************************/ -/** @name Buddy List API */ -/**************************************************************************/ -/*@{*/ - -/** - * Returns the main buddy list. - * - * @return The main buddy list. - */ -PurpleBuddyList *purple_get_blist(void); - -/** - * Returns the root node of the main buddy list. - * - * @return The root node. - */ -PurpleBlistNode *purple_blist_get_root(void); - -/** - * Returns a list of every buddy in the list. Use of this function is - * discouraged if you do not actually need every buddy in the list. Use - * purple_find_buddies instead. - * - * @return A list of every buddy in the list. Caller is responsible for - * freeing the list. - * - * @see purple_find_buddies - */ -GSList *purple_blist_get_buddies(void); - -/** - * Returns the UI data for the list. - * - * @return The UI data for the list. - */ -gpointer purple_blist_get_ui_data(void); - -/** - * Sets the UI data for the list. - * - * @param ui_data The UI data for the list. - */ -void purple_blist_set_ui_data(gpointer ui_data); - -/** - * Returns the next node of a given node. This function is to be used to iterate - * over the tree returned by purple_get_blist. - * - * @param node A node. - * @param offline Whether to include nodes for offline accounts - * @return The next node - * @see purple_blist_node_get_parent - * @see purple_blist_node_get_first_child - * @see purple_blist_node_get_sibling_next - * @see purple_blist_node_get_sibling_prev - */ -PurpleBlistNode *purple_blist_node_next(PurpleBlistNode *node, gboolean offline); - -/** - * Returns the parent node of a given node. - * - * @param node A node. - * @return The parent node. - * - * @see purple_blist_node_get_first_child - * @see purple_blist_node_get_sibling_next - * @see purple_blist_node_get_sibling_prev - * @see purple_blist_node_next - */ -PurpleBlistNode *purple_blist_node_get_parent(PurpleBlistNode *node); - -/** - * Returns the the first child node of a given node. - * - * @param node A node. - * @return The child node. - * - * @see purple_blist_node_get_parent - * @see purple_blist_node_get_sibling_next - * @see purple_blist_node_get_sibling_prev - * @see purple_blist_node_next - */ -PurpleBlistNode *purple_blist_node_get_first_child(PurpleBlistNode *node); - -/** - * Returns the sibling node of a given node. - * - * @param node A node. - * @return The sibling node. - * - * @see purple_blist_node_get_parent - * @see purple_blist_node_get_first_child - * @see purple_blist_node_get_sibling_prev - * @see purple_blist_node_next - */ -PurpleBlistNode *purple_blist_node_get_sibling_next(PurpleBlistNode *node); - -/** - * Returns the previous sibling node of a given node. - * - * @param node A node. - * @return The sibling node. - * - * @see purple_blist_node_get_parent - * @see purple_blist_node_get_first_child - * @see purple_blist_node_get_sibling_next - * @see purple_blist_node_next - */ -PurpleBlistNode *purple_blist_node_get_sibling_prev(PurpleBlistNode *node); - -/** - * Returns the UI data of a given node. - * - * @param node The node. - * @return The UI data. - */ -gpointer purple_blist_node_get_ui_data(const PurpleBlistNode *node); - -/** - * Sets the UI data of a given node. - * - * @param node The node. - * @param ui_data The UI data. - */ -void purple_blist_node_set_ui_data(PurpleBlistNode *node, gpointer ui_data); - -/** - * Shows the buddy list, creating a new one if necessary. - */ -void purple_blist_show(void); - - -/** - * Destroys the buddy list window. - * - * @deprecated The UI is responsible for cleaning up the - * PurpleBuddyList->ui_data. purple_blist_uninit() will free the - * PurpleBuddyList* itself. - */ -void purple_blist_destroy(void); - -/** - * Hides or unhides the buddy list. - * - * @param show Whether or not to show the buddy list - */ -void purple_blist_set_visible(gboolean show); - -/** - * Updates a buddy's status. - * - * This should only be called from within Purple. - * - * @param buddy The buddy whose status has changed. - * @param old_status The status from which we are changing. - */ -void purple_blist_update_buddy_status(PurpleBuddy *buddy, PurpleStatus *old_status); - -/** - * Updates a node's custom icon. - * - * @param node The PurpleBlistNode whose custom icon has changed. - */ -void purple_blist_update_node_icon(PurpleBlistNode *node); - -/** - * Renames a buddy in the buddy list. - * - * @param buddy The buddy whose name will be changed. - * @param name The new name of the buddy. - */ -void purple_blist_rename_buddy(PurpleBuddy *buddy, const char *name); - -/** - * Aliases a contact in the buddy list. - * - * @param contact The contact whose alias will be changed. - * @param alias The contact's alias. - */ -void purple_blist_alias_contact(PurpleContact *contact, const char *alias); - -/** - * Aliases a buddy in the buddy list. - * - * @param buddy The buddy whose alias will be changed. - * @param alias The buddy's alias. - */ -void purple_blist_alias_buddy(PurpleBuddy *buddy, const char *alias); - -/** - * Sets the server-sent alias of a buddy in the buddy list. - * PRPLs should call serv_got_alias() instead of this. - * - * @param buddy The buddy whose alias will be changed. - * @param alias The buddy's "official" alias. - */ -void purple_blist_server_alias_buddy(PurpleBuddy *buddy, const char *alias); - -/** - * Aliases a chat in the buddy list. - * - * @param chat The chat whose alias will be changed. - * @param alias The chat's new alias. - */ -void purple_blist_alias_chat(PurpleChat *chat, const char *alias); - -/** - * Renames a group - * - * @param group The group to rename - * @param name The new name - */ -void purple_blist_rename_group(PurpleGroup *group, const char *name); - -/** - * Creates a new chat for the buddy list - * - * @param account The account this chat will get added to - * @param alias The alias of the new chat - * @param components The info the prpl needs to join the chat. The - * hash function should be g_str_hash() and the - * equal function should be g_str_equal(). - * @return A newly allocated chat - */ -PurpleChat *purple_chat_new(PurpleAccount *account, const char *alias, GHashTable *components); - -/** - * Destroys a chat - * - * @param chat The chat to destroy - */ -void purple_chat_destroy(PurpleChat *chat); - -/** - * Adds a new chat to the buddy list. - * - * The chat will be inserted right after node or appended to the end - * of group if node is NULL. If both are NULL, the buddy will be added to - * the "Chats" group. - * - * @param chat The new chat who gets added - * @param group The group to add the new chat to. - * @param node The insertion point - */ -void purple_blist_add_chat(PurpleChat *chat, PurpleGroup *group, PurpleBlistNode *node); - -/** - * Creates a new buddy. - * - * This function only creates the PurpleBuddy. Use purple_blist_add_buddy - * to add the buddy to the list and purple_account_add_buddy to sync up - * with the server. - * - * @param account The account this buddy will get added to - * @param name The name of the new buddy - * @param alias The alias of the new buddy (or NULL if unaliased) - * @return A newly allocated buddy - * - * @see purple_account_add_buddy - * @see purple_blist_add_buddy - */ -PurpleBuddy *purple_buddy_new(PurpleAccount *account, const char *name, const char *alias); - -/** - * Destroys a buddy - * - * @param buddy The buddy to destroy - */ -void purple_buddy_destroy(PurpleBuddy *buddy); - -/** - * Sets a buddy's icon. - * - * This should only be called from within Purple. You probably want to - * call purple_buddy_icon_set_data(). - * - * @param buddy The buddy. - * @param icon The buddy icon. - * - * @see purple_buddy_icon_set_data() - */ -void purple_buddy_set_icon(PurpleBuddy *buddy, PurpleBuddyIcon *icon); - -/** - * Returns a buddy's account. - * - * @param buddy The buddy. - * - * @return The account - */ -PurpleAccount *purple_buddy_get_account(const PurpleBuddy *buddy); - -/** - * Returns a buddy's name - * - * @param buddy The buddy. - * - * @return The name. - */ -const char *purple_buddy_get_name(const PurpleBuddy *buddy); - -/** - * Returns a buddy's icon. - * - * @param buddy The buddy. - * - * @return The buddy icon. - */ -PurpleBuddyIcon *purple_buddy_get_icon(const PurpleBuddy *buddy); - -/** - * Returns a buddy's protocol-specific data. - * - * This should only be called from the associated prpl. - * - * @param buddy The buddy. - * @return The protocol data. - * - * @see purple_buddy_set_protocol_data() - */ -gpointer purple_buddy_get_protocol_data(const PurpleBuddy *buddy); - -/** - * Sets a buddy's protocol-specific data. - * - * This should only be called from the associated prpl. - * - * @param buddy The buddy. - * @param data The data. - * - * @see purple_buddy_get_protocol_data() - */ -void purple_buddy_set_protocol_data(PurpleBuddy *buddy, gpointer data); - -/** - * Returns a buddy's contact. - * - * @param buddy The buddy. - * - * @return The buddy's contact. - */ -PurpleContact *purple_buddy_get_contact(PurpleBuddy *buddy); - -/** - * Returns a buddy's presence. - * - * @param buddy The buddy. - * - * @return The buddy's presence. - */ -PurplePresence *purple_buddy_get_presence(const PurpleBuddy *buddy); - -/** - * Gets the media caps from a buddy. - * - * @param buddy The buddy. - * @return The media caps. - */ -PurpleMediaCaps purple_buddy_get_media_caps(const PurpleBuddy *buddy); - -/** - * Sets the media caps for a buddy. - * - * @param buddy The PurpleBuddy. - * @param media_caps The PurpleMediaCaps. - */ -void purple_buddy_set_media_caps(PurpleBuddy *buddy, PurpleMediaCaps media_caps); - -/** - * Adds a new buddy to the buddy list. - * - * The buddy will be inserted right after node or prepended to the - * group if node is NULL. If both are NULL, the buddy will be added to - * the "Buddies" group. - * - * @param buddy The new buddy who gets added - * @param contact The optional contact to place the buddy in. - * @param group The group to add the new buddy to. - * @param node The insertion point. Pass in NULL to add the node as - * the first child in the given group. - */ -void purple_blist_add_buddy(PurpleBuddy *buddy, PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node); - -/** - * Creates a new group - * - * You can't have more than one group with the same name. Sorry. If you pass - * this the name of a group that already exists, it will return that group. - * - * @param name The name of the new group - * @return A new group struct -*/ -PurpleGroup *purple_group_new(const char *name); - -/** - * Destroys a group - * - * @param group The group to destroy -*/ -void purple_group_destroy(PurpleGroup *group); - -/** - * Adds a new group to the buddy list. - * - * The new group will be inserted after insert or prepended to the list if - * node is NULL. - * - * @param group The group - * @param node The insertion point - */ -void purple_blist_add_group(PurpleGroup *group, PurpleBlistNode *node); - -/** - * Creates a new contact - * - * @return A new contact struct - */ -PurpleContact *purple_contact_new(void); - -/** - * Destroys a contact - * - * @param contact The contact to destroy - */ -void purple_contact_destroy(PurpleContact *contact); - -/** - * Gets the PurpleGroup from a PurpleContact - * - * @param contact The contact - * @return The group - */ -PurpleGroup *purple_contact_get_group(const PurpleContact *contact); - -/** - * Adds a new contact to the buddy list. - * - * The new contact will be inserted after insert or prepended to the list if - * node is NULL. - * - * @param contact The contact - * @param group The group to add the contact to - * @param node The insertion point - */ -void purple_blist_add_contact(PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node); - -/** - * Merges two contacts - * - * All of the buddies from source will be moved to target - * - * @param source The contact to merge - * @param node The place to merge to (a buddy or contact) - */ -void purple_blist_merge_contact(PurpleContact *source, PurpleBlistNode *node); - -/** - * Returns the highest priority buddy for a given contact. - * - * @param contact The contact - * @return The highest priority buddy - */ -PurpleBuddy *purple_contact_get_priority_buddy(PurpleContact *contact); - -/** - * Gets the alias for a contact. - * - * @param contact The contact - * @return The alias, or NULL if it is not set. - */ -const char *purple_contact_get_alias(PurpleContact *contact); - -/** - * Determines whether an account owns any buddies in a given contact - * - * @param contact The contact to search through. - * @param account The account. - * - * @return TRUE if there are any buddies from account in the contact, or FALSE otherwise. - */ -gboolean purple_contact_on_account(PurpleContact *contact, PurpleAccount *account); - -/** - * Invalidates the priority buddy so that the next call to - * purple_contact_get_priority_buddy recomputes it. - * - * @param contact The contact - */ -void purple_contact_invalidate_priority_buddy(PurpleContact *contact); - -/** - * Determines the total size of a contact. - * - * @param contact The contact - * @param offline Count buddies in offline accounts - * @return The number of buddies in the contact - */ -int purple_contact_get_contact_size(PurpleContact *contact, gboolean offline); - -/** - * Removes a buddy from the buddy list and frees the memory allocated to it. - * This doesn't actually try to remove the buddy from the server list. - * - * @param buddy The buddy to be removed - * - * @see purple_account_remove_buddy - */ -void purple_blist_remove_buddy(PurpleBuddy *buddy); - -/** - * Removes a contact, and any buddies it contains, and frees the memory - * allocated to it. This calls purple_blist_remove_buddy and therefore - * doesn't remove the buddies from the server list. - * - * @param contact The contact to be removed - * - * @see purple_blist_remove_buddy - */ -void purple_blist_remove_contact(PurpleContact *contact); - -/** - * Removes a chat from the buddy list and frees the memory allocated to it. - * - * @param chat The chat to be removed - */ -void purple_blist_remove_chat(PurpleChat *chat); - -/** - * Removes a group from the buddy list and frees the memory allocated to it and to - * its children - * - * @param group The group to be removed - */ -void purple_blist_remove_group(PurpleGroup *group); - -/** - * Returns the alias of a buddy. - * - * @param buddy The buddy whose name will be returned. - * @return The alias (if set), server alias (if set), - * or NULL. - */ -const char *purple_buddy_get_alias_only(PurpleBuddy *buddy); - -/** - * Gets the server alias for a buddy. - * - * @param buddy The buddy whose name will be returned - * @return The server alias, or NULL if it is not set. - */ -const char *purple_buddy_get_server_alias(PurpleBuddy *buddy); - -/** - * Returns the correct name to display for a buddy, taking the contact alias - * into account. In order of precedence: the buddy's alias; the buddy's - * contact alias; the buddy's server alias; the buddy's user name. - * - * @param buddy The buddy whose name will be returned - * @return The appropriate name or alias, or NULL. - * - */ -const char *purple_buddy_get_contact_alias(PurpleBuddy *buddy); - -/** - * Returns the correct name to display for a buddy. In order of precedence: - * the buddy's alias; the buddy's server alias; the buddy's contact alias; - * the buddy's user name. - * - * @param buddy The buddy whose name will be returned. - * @return The appropriate name or alias, or NULL - */ -const char *purple_buddy_get_alias(PurpleBuddy *buddy); - -/** - * Returns the local alias for the buddy, or @c NULL if none exists. - * - * @param buddy The buddy - * @return The local alias for the buddy - */ -const char *purple_buddy_get_local_buddy_alias(PurpleBuddy *buddy); - -/** - * Returns the correct name to display for a blist chat. - * - * @param chat The chat whose name will be returned. - * @return The alias (if set), or first component value. - */ -const char *purple_chat_get_name(PurpleChat *chat); - -/** - * Finds the buddy struct given a name and an account - * - * @param account The account this buddy belongs to - * @param name The buddy's name - * @return The buddy or NULL if the buddy does not exist - */ -PurpleBuddy *purple_find_buddy(PurpleAccount *account, const char *name); - -/** - * Finds the buddy struct given a name, an account, and a group - * - * @param account The account this buddy belongs to - * @param name The buddy's name - * @param group The group to look in - * @return The buddy or NULL if the buddy does not exist in the group - */ -PurpleBuddy *purple_find_buddy_in_group(PurpleAccount *account, const char *name, - PurpleGroup *group); - -/** - * Finds all PurpleBuddy structs given a name and an account - * - * @param account The account this buddy belongs to - * @param name The buddy's name (or NULL to return all buddies for the account) - * - * @return NULL if the buddy doesn't exist, or a GSList of - * PurpleBuddy structs. You must free the GSList using - * g_slist_free. Do not free the PurpleBuddy structs that - * the list points to. - */ -GSList *purple_find_buddies(PurpleAccount *account, const char *name); - - -/** - * Finds a group by name - * - * @param name The group's name - * @return The group or NULL if the group does not exist - */ -PurpleGroup *purple_find_group(const char *name); - -/** - * Finds a chat by name. - * - * @param account The chat's account. - * @param name The chat's name. - * - * @return The chat, or @c NULL if the chat does not exist. - */ -PurpleChat *purple_blist_find_chat(PurpleAccount *account, const char *name); - -/** - * Returns the group of which the chat is a member. - * - * @param chat The chat. - * - * @return The parent group, or @c NULL if the chat is not in a group. - */ -PurpleGroup *purple_chat_get_group(PurpleChat *chat); - -/** - * Returns the account the chat belongs to. - * - * @param chat The chat. - * - * @return The account the chat belongs to. - */ -PurpleAccount *purple_chat_get_account(PurpleChat *chat); - -/** - * Get a hashtable containing information about a chat. - * - * @param chat The chat. - * - * @constreturn The hashtable. - */ -GHashTable *purple_chat_get_components(PurpleChat *chat); - -/** - * Returns the group of which the buddy is a member. - * - * @param buddy The buddy - * @return The group or NULL if the buddy is not in a group - */ -PurpleGroup *purple_buddy_get_group(PurpleBuddy *buddy); - - -/** - * Returns a list of accounts that have buddies in this group - * - * @param g The group - * - * @return A GSList of accounts (which must be freed), or NULL if the group - * has no accounts. - */ -GSList *purple_group_get_accounts(PurpleGroup *g); - -/** - * Determines whether an account owns any buddies in a given group - * - * @param g The group to search through. - * @param account The account. - * - * @return TRUE if there are any buddies in the group, or FALSE otherwise. - */ -gboolean purple_group_on_account(PurpleGroup *g, PurpleAccount *account); - -/** - * Returns the name of a group. - * - * @param group The group. - * - * @return The name of the group. - */ -const char *purple_group_get_name(PurpleGroup *group); - -/** - * Called when an account connects. Tells the UI to update all the - * buddies. - * - * @param account The account - */ -void purple_blist_add_account(PurpleAccount *account); - - -/** - * Called when an account disconnects. Sets the presence of all the buddies to 0 - * and tells the UI to update them. - * - * @param account The account - */ -void purple_blist_remove_account(PurpleAccount *account); - - -/** - * Determines the total size of a group - * - * @param group The group - * @param offline Count buddies in offline accounts - * @return The number of buddies in the group - */ -int purple_blist_get_group_size(PurpleGroup *group, gboolean offline); - -/** - * Determines the number of online buddies in a group - * - * @param group The group - * @return The number of online buddies in the group, or 0 if the group is NULL - */ -int purple_blist_get_group_online_count(PurpleGroup *group); - -/*@}*/ - -/****************************************************************************************/ -/** @name Buddy list file management API */ -/****************************************************************************************/ - -/** - * Schedule a save of the blist.xml file. This is used by the privacy - * API whenever the privacy settings are changed. If you make a change - * to blist.xml using one of the functions in the buddy list API, then - * the buddy list is saved automatically, so you should not need to - * call this. - */ -void purple_blist_schedule_save(void); - -/** - * Requests from the user information needed to add a buddy to the - * buddy list. - * - * @param account The account the buddy is added to. - * @param username The username of the buddy. - * @param group The name of the group to place the buddy in. - * @param alias The optional alias for the buddy. - */ -void purple_blist_request_add_buddy(PurpleAccount *account, const char *username, - const char *group, const char *alias); - -/** - * Requests from the user information needed to add a chat to the - * buddy list. - * - * @param account The account the buddy is added to. - * @param group The optional group to add the chat to. - * @param alias The optional alias for the chat. - * @param name The required chat name. - */ -void purple_blist_request_add_chat(PurpleAccount *account, PurpleGroup *group, - const char *alias, const char *name); - -/** - * Requests from the user information needed to add a group to the - * buddy list. - */ -void purple_blist_request_add_group(void); - -/** - * Checks whether a named setting exists for a node in the buddy list - * - * @param node The node to check from which to check settings - * @param key The identifier of the data - * - * @return TRUE if a value exists, or FALSE if there is no setting - */ -gboolean purple_blist_node_has_setting(PurpleBlistNode *node, const char *key); - -/** - * Associates a boolean with a node in the buddy list - * - * @param node The node to associate the data with - * @param key The identifier for the data - * @param value The value to set - */ -void purple_blist_node_set_bool(PurpleBlistNode *node, const char *key, gboolean value); - -/** - * Retrieves a named boolean setting from a node in the buddy list - * - * @param node The node to retrieve the data from - * @param key The identifier of the data - * - * @return The value, or FALSE if there is no setting - */ -gboolean purple_blist_node_get_bool(PurpleBlistNode *node, const char *key); - -/** - * Associates an integer with a node in the buddy list - * - * @param node The node to associate the data with - * @param key The identifier for the data - * @param value The value to set - */ -void purple_blist_node_set_int(PurpleBlistNode *node, const char *key, int value); - -/** - * Retrieves a named integer setting from a node in the buddy list - * - * @param node The node to retrieve the data from - * @param key The identifier of the data - * - * @return The value, or 0 if there is no setting - */ -int purple_blist_node_get_int(PurpleBlistNode *node, const char *key); - -/** - * Associates a string with a node in the buddy list - * - * @param node The node to associate the data with - * @param key The identifier for the data - * @param value The value to set - */ -void purple_blist_node_set_string(PurpleBlistNode *node, const char *key, - const char *value); - -/** - * Retrieves a named string setting from a node in the buddy list - * - * @param node The node to retrieve the data from - * @param key The identifier of the data - * - * @return The value, or NULL if there is no setting - */ -const char *purple_blist_node_get_string(PurpleBlistNode *node, const char *key); - -/** - * Removes a named setting from a blist node - * - * @param node The node from which to remove the setting - * @param key The name of the setting - */ -void purple_blist_node_remove_setting(PurpleBlistNode *node, const char *key); - -/** - * Set the flags for the given node. Setting a node's flags will overwrite - * the old flags, so if you want to save them, you must first call - * purple_blist_node_get_flags and modify that appropriately. - * - * @param node The node on which to set the flags. - * @param flags The flags to set. This is a bitmask. - */ -void purple_blist_node_set_flags(PurpleBlistNode *node, PurpleBlistNodeFlags flags); - -/** - * Get the current flags on a given node. - * - * @param node The node from which to get the flags. - * - * @return The flags on the node. This is a bitmask. - */ -PurpleBlistNodeFlags purple_blist_node_get_flags(PurpleBlistNode *node); - -/** - * Get the type of a given node. - * - * @param node The node. - * - * @return The type of the node. - */ -PurpleBlistNodeType purple_blist_node_get_type(PurpleBlistNode *node); - -/*@}*/ - -/** - * Retrieves the extended menu items for a buddy list node. - * @param n The blist node for which to obtain the extended menu items. - * @return A list of PurpleMenuAction items, as harvested by the - * blist-node-extended-menu signal. - */ -GList *purple_blist_node_get_extended_menu(PurpleBlistNode *n); - -/**************************************************************************/ -/** @name UI Registration Functions */ -/**************************************************************************/ -/*@{*/ - -/** - * Sets the UI operations structure to be used for the buddy list. - * - * @param ops The ops struct. - */ -void purple_blist_set_ui_ops(PurpleBlistUiOps *ops); - -/** - * Returns the UI operations structure to be used for the buddy list. - * - * @return The UI operations structure. - */ -PurpleBlistUiOps *purple_blist_get_ui_ops(void); - -/*@}*/ - -/**************************************************************************/ -/** @name Buddy List Subsystem */ -/**************************************************************************/ -/*@{*/ - -/** - * Returns the handle for the buddy list subsystem. - * - * @return The buddy list subsystem handle. - */ -void *purple_blist_get_handle(void); - -/** - * Initializes the buddy list subsystem. - */ -void purple_blist_init(void); - -/** - * Loads the buddy list. - * - * You shouldn't call this. purple_core_init() will do it for you. - */ -void purple_blist_boot(void); - -/** - * Uninitializes the buddy list subsystem. - */ -void purple_blist_uninit(void); - -/*@}*/ - -G_END_DECLS - -#endif /* _PURPLE_BLIST_H_ */ diff --git a/libpurple/blistnode.c b/libpurple/blistnode.c new file mode 100644 index 0000000000..b0cc8aa9ee --- /dev/null +++ b/libpurple/blistnode.c @@ -0,0 +1,662 @@ +/* + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ +#include "blistnodetypes.h" +#include "internal.h" + +#define PURPLE_BLIST_NODE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_BLIST_NODE, PurpleBlistNodePrivate)) + +/** @copydoc _PurpleBlistNodePrivate */ +typedef struct _PurpleBlistNodePrivate PurpleBlistNodePrivate; + +#define PURPLE_COUNTING_NODE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_COUNTING_NODE, PurpleCountingNodePrivate)) + +/** @copydoc _PurpleCountingNodePrivate */ +typedef struct _PurpleCountingNodePrivate PurpleCountingNodePrivate; + +/** Private data of a buddy list node */ +struct _PurpleBlistNodePrivate { + GHashTable *settings; /**< per-node settings */ + gboolean transient; /**< node should not be saved with the buddy list */ +}; + +/* Blist node property enums */ +enum +{ + BLNODE_PROP_0, + BLNODE_PROP_DONT_SAVE, + BLNODE_PROP_LAST +}; + +/** Private data of a counting node */ +struct _PurpleCountingNodePrivate { + int totalsize; /**< The number of children under this node */ + int currentsize; /**< The number of children under this node + corresponding to online accounts */ + int onlinecount; /**< The number of children under this contact who are + currently online */ +}; + +/* Counting node property enums */ +enum +{ + CNODE_PROP_0, + CNODE_PROP_TOTAL_SIZE, + CNODE_PROP_CURRENT_SIZE, + CNODE_PROP_ONLINE_COUNT, + CNODE_PROP_LAST +}; + +static GObjectClass *parent_class; + +/**************************************************************************/ +/* Buddy list node API */ +/**************************************************************************/ + +static PurpleBlistNode *get_next_node(PurpleBlistNode *node, gboolean godeep) +{ + if (node == NULL) + return NULL; + + if (godeep && node->child) + return node->child; + + if (node->next) + return node->next; + + return get_next_node(node->parent, FALSE); +} + +PurpleBlistNode *purple_blist_node_next(PurpleBlistNode *node, gboolean offline) +{ + PurpleBlistNode *ret = node; + + if (offline) + return get_next_node(ret, TRUE); + do + { + ret = get_next_node(ret, TRUE); + } while (ret && PURPLE_IS_BUDDY(ret) && + !purple_account_is_connected(purple_buddy_get_account((PurpleBuddy *)ret))); + + return ret; +} + +PurpleBlistNode *purple_blist_node_get_parent(PurpleBlistNode *node) +{ + return node ? node->parent : NULL; +} + +PurpleBlistNode *purple_blist_node_get_first_child(PurpleBlistNode *node) +{ + return node ? node->child : NULL; +} + +PurpleBlistNode *purple_blist_node_get_sibling_next(PurpleBlistNode *node) +{ + return node? node->next : NULL; +} + +PurpleBlistNode *purple_blist_node_get_sibling_prev(PurpleBlistNode *node) +{ + return node? node->prev : NULL; +} + +void * +purple_blist_node_get_ui_data(const PurpleBlistNode *node) +{ + g_return_val_if_fail(node, NULL); + + return node->ui_data; +} + +void +purple_blist_node_set_ui_data(PurpleBlistNode *node, void *ui_data) { + g_return_if_fail(node); + + node->ui_data = ui_data; +} + +void purple_blist_node_remove_setting(PurpleBlistNode *node, const char *key) +{ + PurpleBlistUiOps *ops; + PurpleBlistNodePrivate *priv = PURPLE_BLIST_NODE_GET_PRIVATE(node); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->settings != NULL); + g_return_if_fail(key != NULL); + + g_hash_table_remove(priv->settings, key); + + ops = purple_blist_get_ui_ops(); + if (ops && ops->save_node) + ops->save_node(node); +} + +void +purple_blist_node_set_transient(PurpleBlistNode *node, gboolean transient) +{ + PurpleBlistNodePrivate *priv = PURPLE_BLIST_NODE_GET_PRIVATE(node); + + g_return_if_fail(priv != NULL); + + priv->transient = transient; +} + +gboolean +purple_blist_node_is_transient(PurpleBlistNode *node) +{ + PurpleBlistNodePrivate *priv = PURPLE_BLIST_NODE_GET_PRIVATE(node); + + g_return_val_if_fail(priv != NULL, 0); + + return priv->transient; +} + +GHashTable * +purple_blist_node_get_settings(PurpleBlistNode *node) +{ + PurpleBlistNodePrivate *priv = PURPLE_BLIST_NODE_GET_PRIVATE(node); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->settings; +} + +gboolean +purple_blist_node_has_setting(PurpleBlistNode* node, const char *key) +{ + PurpleBlistNodePrivate *priv = PURPLE_BLIST_NODE_GET_PRIVATE(node); + + g_return_val_if_fail(priv != NULL, FALSE); + g_return_val_if_fail(priv->settings != NULL, FALSE); + g_return_val_if_fail(key != NULL, FALSE); + + /* Boxed type, so it won't ever be NULL, so no need for _extended */ + return (g_hash_table_lookup(priv->settings, key) != NULL); +} + +void +purple_blist_node_set_bool(PurpleBlistNode* node, const char *key, gboolean data) +{ + GValue *value; + PurpleBlistUiOps *ops; + PurpleBlistNodePrivate *priv = PURPLE_BLIST_NODE_GET_PRIVATE(node); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->settings != NULL); + g_return_if_fail(key != NULL); + + value = purple_g_value_new(G_TYPE_BOOLEAN); + g_value_set_boolean(value, data); + + g_hash_table_replace(priv->settings, g_strdup(key), value); + + ops = purple_blist_get_ui_ops(); + if (ops && ops->save_node) + ops->save_node(node); +} + +gboolean +purple_blist_node_get_bool(PurpleBlistNode* node, const char *key) +{ + GValue *value; + PurpleBlistNodePrivate *priv = PURPLE_BLIST_NODE_GET_PRIVATE(node); + + g_return_val_if_fail(priv != NULL, FALSE); + g_return_val_if_fail(priv->settings != NULL, FALSE); + g_return_val_if_fail(key != NULL, FALSE); + + value = g_hash_table_lookup(priv->settings, key); + + if (value == NULL) + return FALSE; + + g_return_val_if_fail(G_VALUE_HOLDS_BOOLEAN(value), FALSE); + + return g_value_get_boolean(value); +} + +void +purple_blist_node_set_int(PurpleBlistNode* node, const char *key, int data) +{ + GValue *value; + PurpleBlistUiOps *ops; + PurpleBlistNodePrivate *priv = PURPLE_BLIST_NODE_GET_PRIVATE(node); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->settings != NULL); + g_return_if_fail(key != NULL); + + value = purple_g_value_new(G_TYPE_INT); + g_value_set_int(value, data); + + g_hash_table_replace(priv->settings, g_strdup(key), value); + + ops = purple_blist_get_ui_ops(); + if (ops && ops->save_node) + ops->save_node(node); +} + +int +purple_blist_node_get_int(PurpleBlistNode* node, const char *key) +{ + GValue *value; + PurpleBlistNodePrivate *priv = PURPLE_BLIST_NODE_GET_PRIVATE(node); + + g_return_val_if_fail(priv != NULL, 0); + g_return_val_if_fail(priv->settings != NULL, 0); + g_return_val_if_fail(key != NULL, 0); + + value = g_hash_table_lookup(priv->settings, key); + + if (value == NULL) + return 0; + + g_return_val_if_fail(G_VALUE_HOLDS_INT(value), 0); + + return g_value_get_int(value); +} + +void +purple_blist_node_set_string(PurpleBlistNode* node, const char *key, const char *data) +{ + GValue *value; + PurpleBlistUiOps *ops; + PurpleBlistNodePrivate *priv = PURPLE_BLIST_NODE_GET_PRIVATE(node); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->settings != NULL); + g_return_if_fail(key != NULL); + + value = purple_g_value_new(G_TYPE_STRING); + g_value_set_string(value, data); + + g_hash_table_replace(priv->settings, g_strdup(key), value); + + ops = purple_blist_get_ui_ops(); + if (ops && ops->save_node) + ops->save_node(node); +} + +const char * +purple_blist_node_get_string(PurpleBlistNode* node, const char *key) +{ + GValue *value; + PurpleBlistNodePrivate *priv = PURPLE_BLIST_NODE_GET_PRIVATE(node); + + g_return_val_if_fail(priv != NULL, NULL); + g_return_val_if_fail(priv->settings != NULL, NULL); + g_return_val_if_fail(key != NULL, NULL); + + value = g_hash_table_lookup(priv->settings, key); + + if (value == NULL) + return NULL; + + g_return_val_if_fail(G_VALUE_HOLDS_STRING(value), NULL); + + return g_value_get_string(value); +} + +GList * +purple_blist_node_get_extended_menu(PurpleBlistNode *n) +{ + GList *menu = NULL; + + g_return_val_if_fail(n != NULL, NULL); + + purple_signal_emit(purple_blist_get_handle(), "blist-node-extended-menu", + n, &menu); + return menu; +} + +/************************************************************************** + * GObject code for PurpleBlistNode + **************************************************************************/ + +/* GObject Property names */ +#define BLNODE_PROP_DONT_SAVE_S "dont-save" + +/* Set method for GObject properties */ +static void +purple_blist_node_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleBlistNode *node = PURPLE_BLIST_NODE(obj); + + switch (param_id) { + case BLNODE_PROP_DONT_SAVE: + purple_blist_node_set_transient(node, g_value_get_boolean(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_blist_node_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleBlistNode *node = PURPLE_BLIST_NODE(obj); + + switch (param_id) { + case BLNODE_PROP_DONT_SAVE: + g_value_set_boolean(value, purple_blist_node_is_transient(node)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* GObject initialization function */ +static void +purple_blist_node_init(GTypeInstance *instance, gpointer klass) +{ + PurpleBlistNodePrivate *priv = PURPLE_BLIST_NODE_GET_PRIVATE(instance); + + priv->settings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, + (GDestroyNotify)purple_g_value_free); +} + +/* GObject finalize function */ +static void +purple_blist_node_finalize(GObject *object) +{ + PurpleBlistNodePrivate *priv = PURPLE_BLIST_NODE_GET_PRIVATE(object); + + g_hash_table_destroy(priv->settings); + + parent_class->finalize(object); +} + +/* Class initializer function */ +static void +purple_blist_node_class_init(PurpleBlistNodeClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->finalize = purple_blist_node_finalize; + + /* Setup properties */ + obj_class->get_property = purple_blist_node_get_property; + obj_class->set_property = purple_blist_node_set_property; + + g_object_class_install_property(obj_class, BLNODE_PROP_DONT_SAVE, + g_param_spec_boolean(BLNODE_PROP_DONT_SAVE_S, _("Do not save"), + _("Whether node should not be saved with the buddy list."), + FALSE, G_PARAM_READWRITE) + ); + + g_type_class_add_private(klass, sizeof(PurpleBlistNodePrivate)); +} + +GType +purple_blist_node_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleBlistNodeClass), + NULL, + NULL, + (GClassInitFunc)purple_blist_node_class_init, + NULL, + NULL, + sizeof(PurpleBlistNode), + 0, + (GInstanceInitFunc)purple_blist_node_init, + NULL, + }; + + type = g_type_register_static(G_TYPE_OBJECT, "PurpleBlistNode", + &info, G_TYPE_FLAG_ABSTRACT); + } + + return type; +} + +/**************************************************************************/ +/* Counting node API */ +/**************************************************************************/ + +int +purple_counting_node_get_total_size(PurpleCountingNode *counter) +{ + PurpleCountingNodePrivate *priv = PURPLE_COUNTING_NODE_GET_PRIVATE(counter); + + g_return_val_if_fail(priv != NULL, -1); + + return priv->totalsize; +} + +int +purple_counting_node_get_current_size(PurpleCountingNode *counter) +{ + PurpleCountingNodePrivate *priv = PURPLE_COUNTING_NODE_GET_PRIVATE(counter); + + g_return_val_if_fail(priv != NULL, -1); + + return priv->currentsize; +} + +int +purple_counting_node_get_online_count(PurpleCountingNode *counter) +{ + PurpleCountingNodePrivate *priv = PURPLE_COUNTING_NODE_GET_PRIVATE(counter); + + g_return_val_if_fail(priv != NULL, -1); + + return priv->onlinecount; +} + +void +purple_counting_node_change_total_size(PurpleCountingNode *counter, int delta) +{ + PurpleCountingNodePrivate *priv = PURPLE_COUNTING_NODE_GET_PRIVATE(counter); + + g_return_if_fail(priv != NULL); + + priv->totalsize += delta; +} + +void +purple_counting_node_change_current_size(PurpleCountingNode *counter, int delta) +{ + PurpleCountingNodePrivate *priv = PURPLE_COUNTING_NODE_GET_PRIVATE(counter); + + g_return_if_fail(priv != NULL); + + priv->currentsize += delta; +} + +void +purple_counting_node_change_online_count(PurpleCountingNode *counter, int delta) +{ + PurpleCountingNodePrivate *priv = PURPLE_COUNTING_NODE_GET_PRIVATE(counter); + + g_return_if_fail(priv != NULL); + + priv->onlinecount += delta; +} + +void +purple_counting_node_set_total_size(PurpleCountingNode *counter, int totalsize) +{ + PurpleCountingNodePrivate *priv = PURPLE_COUNTING_NODE_GET_PRIVATE(counter); + + g_return_if_fail(priv != NULL); + + priv->totalsize = totalsize; +} + +void +purple_counting_node_set_current_size(PurpleCountingNode *counter, int currentsize) +{ + PurpleCountingNodePrivate *priv = PURPLE_COUNTING_NODE_GET_PRIVATE(counter); + + g_return_if_fail(priv != NULL); + + priv->currentsize = currentsize; +} + +void +purple_counting_node_set_online_count(PurpleCountingNode *counter, int onlinecount) +{ + PurpleCountingNodePrivate *priv = PURPLE_COUNTING_NODE_GET_PRIVATE(counter); + + g_return_if_fail(priv != NULL); + + priv->onlinecount = onlinecount; +} + +/************************************************************************** + * GObject code for PurpleCountingNode + **************************************************************************/ + +/* GObject Property names */ +#define CNODE_PROP_TOTAL_SIZE_S "total-size" +#define CNODE_PROP_CURRENT_SIZE_S "current-size" +#define CNODE_PROP_ONLINE_COUNT_S "online-count" + +/* Set method for GObject properties */ +static void +purple_counting_node_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleCountingNode *node = PURPLE_COUNTING_NODE(obj); + + switch (param_id) { + case CNODE_PROP_TOTAL_SIZE: + purple_counting_node_set_total_size(node, g_value_get_int(value)); + break; + case CNODE_PROP_CURRENT_SIZE: + purple_counting_node_set_current_size(node, g_value_get_int(value)); + break; + case CNODE_PROP_ONLINE_COUNT: + purple_counting_node_set_online_count(node, g_value_get_int(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_counting_node_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleCountingNode *node = PURPLE_COUNTING_NODE(obj); + + switch (param_id) { + case CNODE_PROP_TOTAL_SIZE: + g_value_set_int(value, purple_counting_node_get_total_size(node)); + break; + case CNODE_PROP_CURRENT_SIZE: + g_value_set_int(value, purple_counting_node_get_current_size(node)); + break; + case CNODE_PROP_ONLINE_COUNT: + g_value_set_int(value, purple_counting_node_get_online_count(node)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* GObject initialization function */ +static void +purple_counting_node_init(GTypeInstance *instance, gpointer klass) +{ + PurpleCountingNodePrivate *priv = PURPLE_COUNTING_NODE_GET_PRIVATE(instance); + + priv->totalsize = 0; + priv->currentsize = 0; + priv->onlinecount = 0; +} + +/* Class initializer function */ +static void +purple_counting_node_class_init(PurpleCountingNodeClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + /* Setup properties */ + obj_class->get_property = purple_counting_node_get_property; + obj_class->set_property = purple_counting_node_set_property; + + g_object_class_install_property(obj_class, CNODE_PROP_TOTAL_SIZE, + g_param_spec_int(CNODE_PROP_TOTAL_SIZE_S, _("Total size"), + _("The number of children under this node."), + G_MININT, G_MAXINT, 0, G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, CNODE_PROP_CURRENT_SIZE, + g_param_spec_int(CNODE_PROP_CURRENT_SIZE_S, _("Current size"), + _("The number of children with online accounts."), + G_MININT, G_MAXINT, 0, G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, CNODE_PROP_ONLINE_COUNT, + g_param_spec_int(CNODE_PROP_ONLINE_COUNT_S, _("Online count"), + _("The number of children that are online."), + G_MININT, G_MAXINT, 0, G_PARAM_READWRITE) + ); + + g_type_class_add_private(klass, sizeof(PurpleCountingNodePrivate)); +} + +GType +purple_counting_node_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleCountingNodeClass), + NULL, + NULL, + (GClassInitFunc)purple_counting_node_class_init, + NULL, + NULL, + sizeof(PurpleCountingNode), + 0, + (GInstanceInitFunc)purple_counting_node_init, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_BLIST_NODE, + "PurpleCountingNode", + &info, G_TYPE_FLAG_ABSTRACT); + } + + return type; +} diff --git a/libpurple/blistnode.h b/libpurple/blistnode.h new file mode 100644 index 0000000000..80362c9ecb --- /dev/null +++ b/libpurple/blistnode.h @@ -0,0 +1,423 @@ +/** + * @file blistnode.h Buddy list node and Counting node API + * @ingroup core + */ +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef _PURPLE_BLIST_NODE_H_ +#define _PURPLE_BLIST_NODE_H_ + +#include <glib.h> +#include <glib-object.h> + +#define PURPLE_TYPE_BLIST_NODE (purple_blist_node_get_type()) +#define PURPLE_BLIST_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_BLIST_NODE, PurpleBlistNode)) +#define PURPLE_BLIST_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_BLIST_NODE, PurpleBlistNodeClass)) +#define PURPLE_IS_BLIST_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_BLIST_NODE)) +#define PURPLE_IS_BLIST_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_BLIST_NODE)) +#define PURPLE_BLIST_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_BLIST_NODE, PurpleBlistNodeClass)) + +/** @copydoc _PurpleBlistNode */ +typedef struct _PurpleBlistNode PurpleBlistNode; +/** @copydoc _PurpleBlistNodeClass */ +typedef struct _PurpleBlistNodeClass PurpleBlistNodeClass; + +#define PURPLE_TYPE_COUNTING_NODE (purple_counting_node_get_type()) +#define PURPLE_COUNTING_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_COUNTING_NODE, PurpleCountingNode)) +#define PURPLE_COUNTING_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_COUNTING_NODE, PurpleCountingNodeClass)) +#define PURPLE_IS_COUNTING_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_COUNTING_NODE)) +#define PURPLE_IS_COUNTING_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_COUNTING_NODE)) +#define PURPLE_COUNTING_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_COUNTING_NODE, PurpleCountingNodeClass)) + +/** @copydoc _PurpleCountingNode */ +typedef struct _PurpleCountingNode PurpleCountingNode; +/** @copydoc _PurpleCountingNodeClass */ +typedef struct _PurpleCountingNodeClass PurpleCountingNodeClass; + +/**************************************************************************/ +/* Data Structures */ +/**************************************************************************/ + +/** + * A Buddy list node. This can represent a group, a buddy, or anything else. + * This is a base class for PurpleBuddy, PurpleContact, PurpleGroup, and for + * anything else that wants to put itself in the buddy list. */ +struct _PurpleBlistNode { + /*< private >*/ + GObject gparent; + + /** The UI data associated with this node. This is a convenience + * field provided to the UIs -- it is not used by the libpurple core. + */ + gpointer ui_data; + + PurpleBlistNode *prev; /**< The sibling before this buddy. */ + PurpleBlistNode *next; /**< The sibling after this buddy. */ + PurpleBlistNode *parent; /**< The parent of this node */ + PurpleBlistNode *child; /**< The child of this node */ +}; + +/** The base class for all #PurpleBlistNode's. */ +struct _PurpleBlistNodeClass { + /*< private >*/ + GObjectClass gparent_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/** + * A node that keeps count of the number of children that it has. It tracks the + * total number of children, the number of children corresponding to online + * accounts, and the number of online children. + * + * The two types of counting nodes are: + * 1. Contact: Keeps track of the number of buddies under it. + * 2. Group: Keeps track of the number of chats and contacts under it. + * + * @see PurpleContact + * @see PurpleGroup + */ +struct _PurpleCountingNode { + /** The blist node that this counting node inherits from */ + PurpleBlistNode node; +}; + +/** The base class for all #PurpleCountingNode's. */ +struct _PurpleCountingNodeClass { + /*< private >*/ + PurpleBlistNodeClass node_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +/**************************************************************************/ +/** @name Buddy list node API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the PurpleBlistNode object. + */ +GType purple_blist_node_get_type(void); + +/** + * Returns the next node of a given node. This function is to be used to iterate + * over the tree returned by purple_blist_get_buddy_list. + * + * @param node A node. + * @param offline Whether to include nodes for offline accounts + * @return The next node + * @see purple_blist_node_get_parent + * @see purple_blist_node_get_first_child + * @see purple_blist_node_get_sibling_next + * @see purple_blist_node_get_sibling_prev + */ +PurpleBlistNode *purple_blist_node_next(PurpleBlistNode *node, gboolean offline); + +/** + * Returns the parent node of a given node. + * + * @param node A node. + * @return The parent node. + * + * @see purple_blist_node_get_first_child + * @see purple_blist_node_get_sibling_next + * @see purple_blist_node_get_sibling_prev + * @see purple_blist_node_next + */ +PurpleBlistNode *purple_blist_node_get_parent(PurpleBlistNode *node); + +/** + * Returns the the first child node of a given node. + * + * @param node A node. + * @return The child node. + * + * @see purple_blist_node_get_parent + * @see purple_blist_node_get_sibling_next + * @see purple_blist_node_get_sibling_prev + * @see purple_blist_node_next + */ +PurpleBlistNode *purple_blist_node_get_first_child(PurpleBlistNode *node); + +/** + * Returns the sibling node of a given node. + * + * @param node A node. + * @return The sibling node. + * + * @see purple_blist_node_get_parent + * @see purple_blist_node_get_first_child + * @see purple_blist_node_get_sibling_prev + * @see purple_blist_node_next + */ +PurpleBlistNode *purple_blist_node_get_sibling_next(PurpleBlistNode *node); + +/** + * Returns the previous sibling node of a given node. + * + * @param node A node. + * @return The sibling node. + * + * @see purple_blist_node_get_parent + * @see purple_blist_node_get_first_child + * @see purple_blist_node_get_sibling_next + * @see purple_blist_node_next + */ +PurpleBlistNode *purple_blist_node_get_sibling_prev(PurpleBlistNode *node); + +/** + * Returns the UI data of a given node. + * + * @param node The node. + * @return The UI data. + */ +gpointer purple_blist_node_get_ui_data(const PurpleBlistNode *node); + +/** + * Sets the UI data of a given node. + * + * @param node The node. + * @param ui_data The UI data. + */ +void purple_blist_node_set_ui_data(PurpleBlistNode *node, gpointer ui_data); + +/** + * Returns a node's settings + * + * @param node The node to from which to get settings + * + * @return The hash table with the node's settings + */ +GHashTable *purple_blist_node_get_settings(PurpleBlistNode *node); + +/** + * Checks whether a named setting exists for a node in the buddy list + * + * @param node The node to check from which to check settings + * @param key The identifier of the data + * + * @return TRUE if a value exists, or FALSE if there is no setting + */ +gboolean purple_blist_node_has_setting(PurpleBlistNode *node, const char *key); + +/** + * Associates a boolean with a node in the buddy list + * + * @param node The node to associate the data with + * @param key The identifier for the data + * @param value The value to set + */ +void purple_blist_node_set_bool(PurpleBlistNode *node, const char *key, gboolean value); + +/** + * Retrieves a named boolean setting from a node in the buddy list + * + * @param node The node to retrieve the data from + * @param key The identifier of the data + * + * @return The value, or FALSE if there is no setting + */ +gboolean purple_blist_node_get_bool(PurpleBlistNode *node, const char *key); + +/** + * Associates an integer with a node in the buddy list + * + * @param node The node to associate the data with + * @param key The identifier for the data + * @param value The value to set + */ +void purple_blist_node_set_int(PurpleBlistNode *node, const char *key, int value); + +/** + * Retrieves a named integer setting from a node in the buddy list + * + * @param node The node to retrieve the data from + * @param key The identifier of the data + * + * @return The value, or 0 if there is no setting + */ +int purple_blist_node_get_int(PurpleBlistNode *node, const char *key); + +/** + * Associates a string with a node in the buddy list + * + * @param node The node to associate the data with + * @param key The identifier for the data + * @param value The value to set + */ +void purple_blist_node_set_string(PurpleBlistNode *node, const char *key, + const char *value); + +/** + * Retrieves a named string setting from a node in the buddy list + * + * @param node The node to retrieve the data from + * @param key The identifier of the data + * + * @return The value, or NULL if there is no setting + */ +const char *purple_blist_node_get_string(PurpleBlistNode *node, const char *key); + +/** + * Removes a named setting from a blist node + * + * @param node The node from which to remove the setting + * @param key The name of the setting + */ +void purple_blist_node_remove_setting(PurpleBlistNode *node, const char *key); + +/** + * Sets whether the node should be saved with the buddy list or not + * + * @param node The node + * @param transient TRUE if the node should NOT be saved, FALSE if node should + * be saved + */ +void purple_blist_node_set_transient(PurpleBlistNode *node, gboolean transient); + +/** + * Gets whether the node should be saved with the buddy list or not + * + * @param node The node + * + * @return TRUE if the node should NOT be saved, FALSE if node should be saved + */ +gboolean purple_blist_node_is_transient(PurpleBlistNode *node); + +/*@}*/ + +/** + * Retrieves the extended menu items for a buddy list node. + * @param n The blist node for which to obtain the extended menu items. + * @return A list of PurpleMenuAction items, as harvested by the + * blist-node-extended-menu signal. + */ +GList *purple_blist_node_get_extended_menu(PurpleBlistNode *n); + +/*@}*/ + +/**************************************************************************/ +/** @name Counting node API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the PurpleCountingNode object. + */ +GType purple_counting_node_get_type(void); + +/** + * Returns the total number of children of the counting node. + * + * @param counter The node + * + * @return The total number of children of the node + */ +int purple_counting_node_get_total_size(PurpleCountingNode *counter); + +/** + * Returns the number of children of the counting node corresponding to online + * accounts. + * + * @param counter The node + * + * @return The number of children with online accounts + */ +int purple_counting_node_get_current_size(PurpleCountingNode *counter); + +/** + * Returns the number of children of the counting node that are online. + * + * @param counter The node + * + * @return The total number of online children + */ +int purple_counting_node_get_online_count(PurpleCountingNode *counter); + +/** + * Changes the total number of children of the counting node. The provided + * delta value is added to the count, or if it's negative, the count is + * decreased. + * + * @param counter The node + * @param delta The value to change the total size by + */ +void purple_counting_node_change_total_size(PurpleCountingNode *counter, int delta); + +/** + * Changes the number of children of the counting node corresponding to online + * accounts. The provided delta value is added to the count, or if it's + * negative, the count is decreased. + * + * @param counter The node + * @param delta The value to change the current size by + */ +void purple_counting_node_change_current_size(PurpleCountingNode *counter, int delta); + +/** + * Changes the number of children of the counting node that are online. The + * provided delta value is added to the count, or if it's negative, the count is + * decreased. + * + * @param counter The node + * @param delta The value to change the online count by + */ +void purple_counting_node_change_online_count(PurpleCountingNode *counter, int delta); + +/** + * Sets the total number of children of the counting node. + * + * @param counter The node + * @param totalsize The total number of children of the node + */ +void purple_counting_node_set_total_size(PurpleCountingNode *counter, int totalsize); + +/** + * Sets the number of children of the counting node corresponding to online + * accounts. + * + * @param counter The node + * @param currentsize The number of children with online accounts + */ +void purple_counting_node_set_current_size(PurpleCountingNode *counter, int currentsize); + +/** + * Sets the number of children of the counting node that are online. + * + * @param counter The node + * @param onlinecount The total number of online children + */ +void purple_counting_node_set_online_count(PurpleCountingNode *counter, int onlinecount); + +/*@}*/ + +G_END_DECLS + +#endif /* _PURPLE_BLIST_NODE_H_ */ diff --git a/libpurple/blistnodetypes.c b/libpurple/blistnodetypes.c new file mode 100644 index 0000000000..190ab04df0 --- /dev/null +++ b/libpurple/blistnodetypes.c @@ -0,0 +1,1722 @@ +/* + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ +#include "internal.h" +#include "dbus-maybe.h" +#include "debug.h" + +#define PURPLE_BUDDY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_BUDDY, PurpleBuddyPrivate)) + +/** @copydoc _PurpleBuddyPrivate */ +typedef struct _PurpleBuddyPrivate PurpleBuddyPrivate; + +#define PURPLE_CONTACT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_CONTACT, PurpleContactPrivate)) + +/** @copydoc _PurpleContactPrivate */ +typedef struct _PurpleContactPrivate PurpleContactPrivate; + +#define PURPLE_GROUP_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_GROUP, PurpleGroupPrivate)) + +/** @copydoc _PurpleGroupPrivate */ +typedef struct _PurpleGroupPrivate PurpleGroupPrivate; + +#define PURPLE_CHAT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_CHAT, PurpleChatPrivate)) + +/** @copydoc _PurpleChatPrivate */ +typedef struct _PurpleChatPrivate PurpleChatPrivate; + +/**************************************************************************/ +/* Private data */ +/**************************************************************************/ +/** Private data for a buddy. */ +struct _PurpleBuddyPrivate { + char *name; /**< The name of the buddy. */ + char *local_alias; /**< The user-set alias of the buddy */ + char *server_alias; /**< The server-specified alias of the buddy. + (i.e. MSN "Friendly Names") */ + void *proto_data; /**< This allows the prpl to associate + whatever data it wants with a buddy + TODO Remove this field. Protocols should + subclass PurpleBuddy and store + their data as they see fit. */ + PurpleBuddyIcon *icon; /**< The buddy icon. */ + PurpleAccount *account; /**< the account this buddy belongs to */ + PurplePresence *presence; /**< Presense information of the buddy */ + PurpleMediaCaps media_caps; /**< The media capabilities of the buddy. */ +}; + +/* Buddy property enums */ +enum +{ + BUDDY_PROP_0, + BUDDY_PROP_NAME, + BUDDY_PROP_LOCAL_ALIAS, + BUDDY_PROP_SERVER_ALIAS, + BUDDY_PROP_ICON, + BUDDY_PROP_ACCOUNT, + BUDDY_PROP_PRESENCE, + BUDDY_PROP_MEDIA_CAPS, + BUDDY_PROP_LAST +}; + +/** Private data for a contact */ +struct _PurpleContactPrivate { + char *alias; /**< The user-set alias of the contact */ + PurpleBuddy *priority_buddy; /**< The "top" buddy for this contact */ + gboolean priority_valid; /**< Is priority valid? */ +}; + +/* Contact property enums */ +enum +{ + CONTACT_PROP_0, + CONTACT_PROP_ALIAS, + CONTACT_PROP_PRIORITY_BUDDY, + CONTACT_PROP_LAST +}; + +/** Private data for a group */ +struct _PurpleGroupPrivate { + char *name; /**< The name of this group. */ +}; + +/* Group property enums */ +enum +{ + GROUP_PROP_0, + GROUP_PROP_NAME, + GROUP_PROP_LAST +}; + +/** Private data for a chat node */ +struct _PurpleChatPrivate { + char *alias; /**< The display name of this chat. */ + PurpleAccount *account; /**< The account this chat is attached to */ + GHashTable *components; /**< the stuff the protocol needs to know to join + the chat */ +}; + +/* Chat property enums */ +enum +{ + CHAT_PROP_0, + CHAT_PROP_ALIAS, + CHAT_PROP_ACCOUNT, + CHAT_PROP_COMPONENTS, + CHAT_PROP_LAST +}; + +static PurpleBlistNode *blistnode_parent_class; +static PurpleCountingNode *counting_parent_class; + +static gboolean +purple_strings_are_different(const char *one, const char *two) +{ + return !((one && two && g_utf8_collate(one, two) == 0) || + ((one == NULL || *one == '\0') && (two == NULL || *two == '\0'))); +} + +PurpleBlistNode *_purple_blist_get_last_child(PurpleBlistNode *node); + +/**************************************************************************/ +/* Buddy API */ +/**************************************************************************/ + +void +purple_buddy_set_icon(PurpleBuddy *buddy, PurpleBuddyIcon *icon) +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_if_fail(priv != NULL); + + if (priv->icon != icon) + { + purple_buddy_icon_unref(priv->icon); + priv->icon = (icon != NULL ? purple_buddy_icon_ref(icon) : NULL); + } + + purple_signal_emit(purple_blist_get_handle(), "buddy-icon-changed", buddy); + + if (ops && ops->update) + ops->update(purple_blist_get_buddy_list(), PURPLE_BLIST_NODE(buddy)); +} + +PurpleBuddyIcon * +purple_buddy_get_icon(const PurpleBuddy *buddy) +{ + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->icon; +} + +PurpleAccount * +purple_buddy_get_account(const PurpleBuddy *buddy) +{ + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->account; +} + +void +purple_buddy_set_name(PurpleBuddy *buddy, const char *name) +{ + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + + g_return_if_fail(priv != NULL); + + purple_blist_update_buddies_cache(buddy, name); + + g_free(priv->name); + priv->name = purple_utf8_strip_unprintables(name); + + if (ops) { + if (ops->save_node) + ops->save_node(PURPLE_BLIST_NODE(buddy)); + if (ops->update) + ops->update(purple_blist_get_buddy_list(), PURPLE_BLIST_NODE(buddy)); + } +} + +const char * +purple_buddy_get_name(const PurpleBuddy *buddy) +{ + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->name; +} + +gpointer +purple_buddy_get_protocol_data(const PurpleBuddy *buddy) +{ + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->proto_data; +} + +void +purple_buddy_set_protocol_data(PurpleBuddy *buddy, gpointer data) +{ + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_if_fail(priv != NULL); + + priv->proto_data = data; +} + +const char *purple_buddy_get_alias_only(PurpleBuddy *buddy) +{ + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_val_if_fail(priv != NULL, NULL); + + if ((priv->local_alias != NULL) && (*priv->local_alias != '\0')) { + return priv->local_alias; + } else if ((priv->server_alias != NULL) && + (*priv->server_alias != '\0')) { + + return priv->server_alias; + } + + return NULL; +} + +const char *purple_buddy_get_contact_alias(PurpleBuddy *buddy) +{ + PurpleContact *c; + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_val_if_fail(priv != NULL, NULL); + + /* Search for an alias for the buddy. In order of precedence: */ + /* The local buddy alias */ + if (priv->local_alias != NULL) + return priv->local_alias; + + /* The contact alias */ + c = purple_buddy_get_contact(buddy); + if ((c != NULL) && (purple_contact_get_alias(c) != NULL)) + return purple_contact_get_alias(c); + + /* The server alias */ + if ((priv->server_alias) && (*priv->server_alias)) + return priv->server_alias; + + /* The buddy's user name (i.e. no alias) */ + return priv->name; +} + +const char *purple_buddy_get_alias(PurpleBuddy *buddy) +{ + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_val_if_fail(priv != NULL, NULL); + + /* Search for an alias for the buddy. In order of precedence: */ + /* The buddy alias */ + if (priv->local_alias != NULL) + return priv->local_alias; + + /* The server alias */ + if ((priv->server_alias) && (*priv->server_alias)) + return priv->server_alias; + + /* The buddy's user name (i.e. no alias) */ + return priv->name; +} + +void +purple_buddy_set_local_alias(PurpleBuddy *buddy, const char *alias) +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleIMConversation *im; + char *old_alias; + char *new_alias = NULL; + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_if_fail(buddy != NULL); + + if ((alias != NULL) && (*alias != '\0')) + new_alias = purple_utf8_strip_unprintables(alias); + + if (!purple_strings_are_different(priv->local_alias, new_alias)) { + g_free(new_alias); + return; + } + + old_alias = priv->local_alias; + + if ((new_alias != NULL) && (*new_alias != '\0')) + priv->local_alias = new_alias; + else { + priv->local_alias = NULL; + g_free(new_alias); /* could be "\0" */ + } + + if (ops && ops->save_node) + ops->save_node(PURPLE_BLIST_NODE(buddy)); + + if (ops && ops->update) + ops->update(purple_blist_get_buddy_list(), PURPLE_BLIST_NODE(buddy)); + + im = purple_conversations_find_im_with_account(priv->name, + priv->account); + if (im) + purple_conversation_autoset_title(PURPLE_CONVERSATION(im)); + + purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased", + buddy, old_alias); + g_free(old_alias); +} + +const char *purple_buddy_get_local_alias(PurpleBuddy *buddy) +{ + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->local_alias; +} + +void +purple_buddy_set_server_alias(PurpleBuddy *buddy, const char *alias) +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleIMConversation *im; + char *old_alias; + char *new_alias = NULL; + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_if_fail(priv != NULL); + + if ((alias != NULL) && (*alias != '\0') && g_utf8_validate(alias, -1, NULL)) + new_alias = purple_utf8_strip_unprintables(alias); + + if (!purple_strings_are_different(priv->server_alias, new_alias)) { + g_free(new_alias); + return; + } + + old_alias = priv->server_alias; + + if ((new_alias != NULL) && (*new_alias != '\0')) + priv->server_alias = new_alias; + else { + priv->server_alias = NULL; + g_free(new_alias); /* could be "\0"; */ + } + + if (ops) { + if (ops->save_node) + ops->save_node(PURPLE_BLIST_NODE(buddy)); + if (ops->update) + ops->update(purple_blist_get_buddy_list(), PURPLE_BLIST_NODE(buddy)); + } + + im = purple_conversations_find_im_with_account(priv->name, + priv->account); + if (im) + purple_conversation_autoset_title(PURPLE_CONVERSATION(im)); + + purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased", + buddy, old_alias); + g_free(old_alias); +} + +const char *purple_buddy_get_server_alias(PurpleBuddy *buddy) +{ + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_val_if_fail(priv != NULL, NULL); + + if ((priv->server_alias) && (*priv->server_alias)) + return priv->server_alias; + + return NULL; +} + +PurpleContact *purple_buddy_get_contact(PurpleBuddy *buddy) +{ + g_return_val_if_fail(buddy != NULL, NULL); + + return PURPLE_CONTACT(PURPLE_BLIST_NODE(buddy)->parent); +} + +PurplePresence *purple_buddy_get_presence(const PurpleBuddy *buddy) +{ + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->presence; +} + +void +purple_buddy_update_status(PurpleBuddy *buddy, PurpleStatus *old_status) +{ + PurpleStatus *status; + PurpleBlistNode *cnode; + PurpleContact *contact; + PurpleCountingNode *contact_counter, *group_counter; + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_if_fail(priv != NULL); + + status = purple_presence_get_active_status(priv->presence); + + purple_debug_info("blist", "Updating buddy status for %s (%s)\n", + priv->name, purple_account_get_protocol_name(priv->account)); + + if (purple_status_is_online(status) && + !purple_status_is_online(old_status)) { + + purple_signal_emit(purple_blist_get_handle(), "buddy-signed-on", buddy); + + cnode = PURPLE_BLIST_NODE(buddy)->parent; + contact = PURPLE_CONTACT(cnode); + contact_counter = PURPLE_COUNTING_NODE(contact); + group_counter = PURPLE_COUNTING_NODE(cnode->parent); + + purple_counting_node_change_online_count(contact_counter, +1); + if (purple_counting_node_get_online_count(contact_counter) == 1) + purple_counting_node_change_online_count(group_counter, +1); + } else if (!purple_status_is_online(status) && + purple_status_is_online(old_status)) { + + purple_blist_node_set_int(PURPLE_BLIST_NODE(buddy), "last_seen", time(NULL)); + purple_signal_emit(purple_blist_get_handle(), "buddy-signed-off", buddy); + + cnode = PURPLE_BLIST_NODE(buddy)->parent; + contact = PURPLE_CONTACT(cnode); + contact_counter = PURPLE_COUNTING_NODE(contact); + group_counter = PURPLE_COUNTING_NODE(cnode->parent); + + purple_counting_node_change_online_count(contact_counter, -1); + if (purple_counting_node_get_online_count(contact_counter) == 0) + purple_counting_node_change_online_count(group_counter, -1); + } else { + purple_signal_emit(purple_blist_get_handle(), + "buddy-status-changed", buddy, old_status, + status); + } + + /* + * This function used to only call the following two functions if one of + * the above signals had been triggered, but that's not good, because + * if someone's away message changes and they don't go from away to back + * to away then no signal is triggered. + * + * It's a safe assumption that SOMETHING called this function. PROBABLY + * because something, somewhere changed. Calling the stuff below + * certainly won't hurt anything. Unless you're on a K6-2 300. + */ + purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy)); + + if (ops && ops->update) + ops->update(purple_blist_get_buddy_list(), PURPLE_BLIST_NODE(buddy)); +} + +PurpleMediaCaps purple_buddy_get_media_caps(const PurpleBuddy *buddy) +{ + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_val_if_fail(priv != NULL, 0); + + return priv->media_caps; +} + +void purple_buddy_set_media_caps(PurpleBuddy *buddy, PurpleMediaCaps media_caps) +{ + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + g_return_if_fail(priv != NULL); + + priv->media_caps = media_caps; +} + +PurpleGroup *purple_buddy_get_group(PurpleBuddy *buddy) +{ + g_return_val_if_fail(buddy != NULL, NULL); + + if (PURPLE_BLIST_NODE(buddy)->parent == NULL) + return NULL; + + return PURPLE_GROUP(PURPLE_BLIST_NODE(buddy)->parent->parent); +} + +/************************************************************************** + * GObject code for PurpleBuddy + **************************************************************************/ + +/* GObject Property names */ +#define BUDDY_PROP_NAME_S "name" +#define BUDDY_PROP_LOCAL_ALIAS_S "local-alias" +#define BUDDY_PROP_SERVER_ALIAS_S "server-alias" +#define BUDDY_PROP_ICON_S "icon" +#define BUDDY_PROP_ACCOUNT_S "account" +#define BUDDY_PROP_PRESENCE_S "presence" +#define BUDDY_PROP_MEDIA_CAPS_S "media-caps" + +/* Set method for GObject properties */ +static void +purple_buddy_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleBuddy *buddy = PURPLE_BUDDY(obj); + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + + switch (param_id) { + case BUDDY_PROP_NAME: + priv->name = purple_utf8_strip_unprintables(g_value_get_string(value)); + break; + case BUDDY_PROP_LOCAL_ALIAS: + priv->local_alias = purple_utf8_strip_unprintables(g_value_get_string(value)); + break; + case BUDDY_PROP_SERVER_ALIAS: + purple_buddy_set_server_alias(buddy, g_value_get_string(value)); + break; + case BUDDY_PROP_ICON: + purple_buddy_set_icon(buddy, g_value_get_pointer(value)); + break; + case BUDDY_PROP_ACCOUNT: + priv->account = g_value_get_object(value); + break; + case BUDDY_PROP_MEDIA_CAPS: + purple_buddy_set_media_caps(buddy, g_value_get_enum(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_buddy_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleBuddy *buddy = PURPLE_BUDDY(obj); + + switch (param_id) { + case BUDDY_PROP_NAME: + g_value_set_string(value, purple_buddy_get_name(buddy)); + break; + case BUDDY_PROP_LOCAL_ALIAS: + g_value_set_string(value, purple_buddy_get_local_alias(buddy)); + break; + case BUDDY_PROP_SERVER_ALIAS: + g_value_set_string(value, purple_buddy_get_server_alias(buddy)); + break; + case BUDDY_PROP_ICON: + g_value_set_pointer(value, purple_buddy_get_icon(buddy)); + break; + case BUDDY_PROP_ACCOUNT: + g_value_set_object(value, purple_buddy_get_account(buddy)); + break; + case BUDDY_PROP_PRESENCE: + g_value_set_object(value, purple_buddy_get_presence(buddy)); + break; + case BUDDY_PROP_MEDIA_CAPS: + g_value_set_enum(value, purple_buddy_get_media_caps(buddy)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* GObject initialization function */ +static void +purple_buddy_init(GTypeInstance *instance, gpointer klass) +{ + PURPLE_DBUS_REGISTER_POINTER(PURPLE_BUDDY(instance), PurpleBuddy); +} + +/* Called when done constructing */ +static void +purple_buddy_constructed(GObject *object) +{ + PurpleBuddy *buddy = PURPLE_BUDDY(object); + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + + G_OBJECT_CLASS(blistnode_parent_class)->constructed(object); + + priv->presence = PURPLE_PRESENCE(purple_buddy_presence_new(buddy)); + purple_presence_set_status_active(priv->presence, "offline", TRUE); + + if (ops && ops->new_node) + ops->new_node((PurpleBlistNode *)buddy); +} + +/* GObject dispose function */ +static void +purple_buddy_dispose(GObject *object) +{ + PurpleBuddy *buddy = PURPLE_BUDDY(object); + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); + PurplePlugin *prpl; + PurplePluginProtocolInfo *prpl_info; + + /* + * Tell the owner PRPL that we're about to free the buddy so it + * can free proto_data + */ + prpl = purple_find_prpl(purple_account_get_protocol_id(priv->account)); + if (prpl) { + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + if (prpl_info && prpl_info->buddy_free) + prpl_info->buddy_free(buddy); + } + + /* Delete the node */ + purple_buddy_icon_unref(priv->icon); + g_object_unref(priv->presence); + + PURPLE_DBUS_UNREGISTER_POINTER(buddy); + + G_OBJECT_CLASS(blistnode_parent_class)->dispose(object); +} + +/* GObject finalize function */ +static void +purple_buddy_finalize(GObject *object) +{ + PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(object); + + g_free(priv->name); + g_free(priv->local_alias); + g_free(priv->server_alias); + + G_OBJECT_CLASS(blistnode_parent_class)->finalize(object); +} + +/* Class initializer function */ +static void purple_buddy_class_init(PurpleBuddyClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + blistnode_parent_class = g_type_class_peek_parent(klass); + + obj_class->dispose = purple_buddy_dispose; + obj_class->finalize = purple_buddy_finalize; + + /* Setup properties */ + obj_class->get_property = purple_buddy_get_property; + obj_class->set_property = purple_buddy_set_property; + obj_class->constructed = purple_buddy_constructed; + + g_object_class_install_property(obj_class, BUDDY_PROP_NAME, + g_param_spec_string(BUDDY_PROP_NAME_S, _("Name"), + _("The name of the buddy."), NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_object_class_install_property(obj_class, BUDDY_PROP_LOCAL_ALIAS, + g_param_spec_string(BUDDY_PROP_LOCAL_ALIAS_S, _("Local alias"), + _("Local alias of thee buddy."), NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_object_class_install_property(obj_class, BUDDY_PROP_SERVER_ALIAS, + g_param_spec_string(BUDDY_PROP_SERVER_ALIAS_S, _("Server alias"), + _("Server-side alias of the buddy."), NULL, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, BUDDY_PROP_ICON, + g_param_spec_pointer(BUDDY_PROP_ICON_S, _("Buddy icon"), + _("The icon for the buddy."), + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, BUDDY_PROP_ACCOUNT, + g_param_spec_object(BUDDY_PROP_ACCOUNT_S, _("Account"), + _("The account for the buddy."), PURPLE_TYPE_ACCOUNT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY) + ); + + g_object_class_install_property(obj_class, BUDDY_PROP_PRESENCE, + g_param_spec_object(BUDDY_PROP_PRESENCE_S, _("Presence"), + _("The status information for the buddy."), PURPLE_TYPE_PRESENCE, + G_PARAM_READABLE) + ); + + g_object_class_install_property(obj_class, BUDDY_PROP_MEDIA_CAPS, + g_param_spec_enum(BUDDY_PROP_MEDIA_CAPS_S, _("Media capabilities"), + _("The media capabilities of the buddy."), + PURPLE_MEDIA_TYPE_CAPS, PURPLE_MEDIA_CAPS_NONE, + G_PARAM_READWRITE) + ); + + g_type_class_add_private(klass, sizeof(PurpleBuddyPrivate)); +} + +GType +purple_buddy_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleBuddyClass), + NULL, + NULL, + (GClassInitFunc)purple_buddy_class_init, + NULL, + NULL, + sizeof(PurpleBuddy), + 0, + (GInstanceInitFunc)purple_buddy_init, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_BLIST_NODE, + "PurpleBuddy", + &info, 0); + } + + return type; +} + +PurpleBuddy * +purple_buddy_new(PurpleAccount *account, const char *name, const char *alias) +{ + g_return_val_if_fail(account != NULL, NULL); + g_return_val_if_fail(name != NULL, NULL); + + return g_object_new(PURPLE_TYPE_BUDDY, + BUDDY_PROP_ACCOUNT_S, account, + BUDDY_PROP_NAME_S, name, + BUDDY_PROP_LOCAL_ALIAS_S, alias, + NULL); +} + +/**************************************************************************/ +/* Contact API */ +/**************************************************************************/ + +static void +purple_contact_compute_priority_buddy(PurpleContact *contact) +{ + PurpleBlistNode *bnode; + PurpleBuddy *new_priority = NULL; + PurpleContactPrivate *priv = PURPLE_CONTACT_GET_PRIVATE(contact); + + g_return_if_fail(priv != NULL); + + priv->priority_buddy = NULL; + for (bnode = PURPLE_BLIST_NODE(contact)->child; + bnode != NULL; + bnode = bnode->next) + { + PurpleBuddy *buddy; + + if (!PURPLE_IS_BUDDY(bnode)) + continue; + + buddy = PURPLE_BUDDY(bnode); + if (new_priority == NULL) + { + new_priority = buddy; + continue; + } + + if (purple_account_is_connected(purple_buddy_get_account(buddy))) + { + int cmp = 1; + if (purple_account_is_connected(purple_buddy_get_account(new_priority))) + cmp = purple_buddy_presence_compare( + PURPLE_BUDDY_PRESENCE(purple_buddy_get_presence(new_priority)), + PURPLE_BUDDY_PRESENCE(purple_buddy_get_presence(buddy))); + + if (cmp > 0 || (cmp == 0 && + purple_prefs_get_bool("/purple/contact/last_match"))) + { + new_priority = buddy; + } + } + } + + priv->priority_buddy = new_priority; + priv->priority_valid = TRUE; +} + +PurpleGroup * +purple_contact_get_group(const PurpleContact *contact) +{ + g_return_val_if_fail(contact, NULL); + + return PURPLE_GROUP(PURPLE_BLIST_NODE(contact)->parent); +} + +void +purple_contact_set_alias(PurpleContact *contact, const char *alias) +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleIMConversation *im; + PurpleBlistNode *bnode; + char *old_alias; + char *new_alias = NULL; + PurpleContactPrivate *priv = PURPLE_CONTACT_GET_PRIVATE(contact); + + g_return_if_fail(priv != NULL); + + if ((alias != NULL) && (*alias != '\0')) + new_alias = purple_utf8_strip_unprintables(alias); + + if (!purple_strings_are_different(priv->alias, new_alias)) { + g_free(new_alias); + return; + } + + old_alias = priv->alias; + + if ((new_alias != NULL) && (*new_alias != '\0')) + priv->alias = new_alias; + else { + priv->alias = NULL; + g_free(new_alias); /* could be "\0" */ + } + + if (ops) { + if (ops->save_node) + ops->save_node(PURPLE_BLIST_NODE(contact)); + if (ops->update) + ops->update(purple_blist_get_buddy_list(), PURPLE_BLIST_NODE(contact)); + } + + for(bnode = PURPLE_BLIST_NODE(contact)->child; bnode != NULL; bnode = bnode->next) + { + PurpleBuddy *buddy = PURPLE_BUDDY(bnode); + + im = purple_conversations_find_im_with_account(purple_buddy_get_name(buddy), + purple_buddy_get_account(buddy)); + if (im) + purple_conversation_autoset_title(PURPLE_CONVERSATION(im)); + } + + purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased", + contact, old_alias); + g_free(old_alias); +} + +const char *purple_contact_get_alias(PurpleContact* contact) +{ + PurpleContactPrivate *priv = PURPLE_CONTACT_GET_PRIVATE(contact); + + g_return_val_if_fail(priv != NULL, NULL); + + if (priv->alias) + return priv->alias; + + return purple_buddy_get_alias(purple_contact_get_priority_buddy(contact)); +} + +gboolean purple_contact_on_account(PurpleContact *c, PurpleAccount *account) +{ + PurpleBlistNode *bnode, *cnode = (PurpleBlistNode *) c; + + g_return_val_if_fail(c != NULL, FALSE); + g_return_val_if_fail(account != NULL, FALSE); + + for (bnode = cnode->child; bnode; bnode = bnode->next) { + PurpleBuddy *buddy; + + if (! PURPLE_IS_BUDDY(bnode)) + continue; + + buddy = (PurpleBuddy *)bnode; + if (purple_buddy_get_account(buddy) == account) + return TRUE; + } + return FALSE; +} + +void purple_contact_invalidate_priority_buddy(PurpleContact *contact) +{ + PurpleContactPrivate *priv = PURPLE_CONTACT_GET_PRIVATE(contact); + + g_return_if_fail(priv != NULL); + + priv->priority_valid = FALSE; +} + +PurpleBuddy *purple_contact_get_priority_buddy(PurpleContact *contact) +{ + PurpleContactPrivate *priv = PURPLE_CONTACT_GET_PRIVATE(contact); + + g_return_val_if_fail(priv != NULL, NULL); + + if (!priv->priority_valid) + purple_contact_compute_priority_buddy(contact); + + return priv->priority_buddy; +} + +void purple_contact_merge(PurpleContact *source, PurpleBlistNode *node) +{ + PurpleBlistNode *sourcenode = (PurpleBlistNode*)source; + PurpleBlistNode *prev, *cur, *next; + PurpleContact *target; + + g_return_if_fail(source != NULL); + g_return_if_fail(node != NULL); + + if (PURPLE_IS_CONTACT(node)) { + target = (PurpleContact *)node; + prev = _purple_blist_get_last_child(node); + } else if (PURPLE_IS_BUDDY(node)) { + target = (PurpleContact *)node->parent; + prev = node; + } else { + return; + } + + if (source == target || !target) + return; + + next = sourcenode->child; + + while (next) { + cur = next; + next = cur->next; + if (PURPLE_IS_BUDDY(cur)) { + purple_blist_add_buddy((PurpleBuddy *)cur, target, NULL, prev); + prev = cur; + } + } +} + +/************************************************************************** + * GObject code for PurpleContact + **************************************************************************/ + +/* GObject Property names */ +#define CONTACT_PROP_ALIAS_S "alias" +#define CONTACT_PROP_PRIORITY_BUDDY_S "priority-buddy" + +/* Set method for GObject properties */ +static void +purple_contact_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleContact *contact = PURPLE_CONTACT(obj); + + switch (param_id) { + case CONTACT_PROP_ALIAS: + purple_contact_set_alias(contact, g_value_get_string(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_contact_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleContact *contact = PURPLE_CONTACT(obj); + PurpleContactPrivate *priv = PURPLE_CONTACT_GET_PRIVATE(contact); + + switch (param_id) { + case CONTACT_PROP_ALIAS: + g_value_set_string(value, priv->alias); + break; + case CONTACT_PROP_PRIORITY_BUDDY: + g_value_set_object(value, purple_contact_get_priority_buddy(contact)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* GObject initialization function */ +static void +purple_contact_init(GTypeInstance *instance, gpointer klass) +{ + PurpleContact *contact = PURPLE_CONTACT(instance); + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + + if (ops && ops->new_node) + ops->new_node(PURPLE_BLIST_NODE(contact)); + + PURPLE_DBUS_REGISTER_POINTER(contact, PurpleContact); +} + +/* GObject dispose function */ +static void +purple_contact_dispose(GObject *object) +{ + PURPLE_DBUS_UNREGISTER_POINTER(object); + + G_OBJECT_CLASS(counting_parent_class)->dispose(object); +} + +/* GObject finalize function */ +static void +purple_contact_finalize(GObject *object) +{ + g_free(PURPLE_CONTACT_GET_PRIVATE(object)->alias); + + G_OBJECT_CLASS(counting_parent_class)->finalize(object); +} + +/* Class initializer function */ +static void purple_contact_class_init(PurpleContactClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + counting_parent_class = g_type_class_peek_parent(klass); + + obj_class->dispose = purple_contact_dispose; + obj_class->finalize = purple_contact_finalize; + + /* Setup properties */ + obj_class->get_property = purple_contact_get_property; + obj_class->set_property = purple_contact_set_property; + + g_object_class_install_property(obj_class, CONTACT_PROP_ALIAS, + g_param_spec_string(CONTACT_PROP_ALIAS_S, _("Alias"), + _("The alias for the contact."), NULL, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, CONTACT_PROP_PRIORITY_BUDDY, + g_param_spec_object(CONTACT_PROP_PRIORITY_BUDDY_S, + _("Priority buddy"), _("The priority buddy of the contact."), + PURPLE_TYPE_BUDDY, G_PARAM_READABLE) + ); + + g_type_class_add_private(klass, sizeof(PurpleContactPrivate)); +} + +GType +purple_contact_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleContactClass), + NULL, + NULL, + (GClassInitFunc)purple_contact_class_init, + NULL, + NULL, + sizeof(PurpleContact), + 0, + (GInstanceInitFunc)purple_contact_init, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_COUNTING_NODE, + "PurpleContact", + &info, 0); + } + + return type; +} + +PurpleContact * +purple_contact_new(void) +{ + return g_object_new(PURPLE_TYPE_CONTACT, NULL); +} + +/**************************************************************************/ +/* Chat API */ +/**************************************************************************/ + +const char *purple_chat_get_name(PurpleChat *chat) +{ + PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat); + + g_return_val_if_fail(priv != NULL, NULL); + + if ((priv->alias != NULL) && (*priv->alias != '\0')) + return priv->alias; + + return purple_chat_get_name_only(chat); +} + +const char *purple_chat_get_name_only(PurpleChat *chat) +{ + char *ret = NULL; + PurplePlugin *prpl; + PurplePluginProtocolInfo *prpl_info = NULL; + PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat); + + g_return_val_if_fail(priv != NULL, NULL); + + prpl = purple_find_prpl(purple_account_get_protocol_id(priv->account)); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + + if (prpl_info->chat_info) { + struct proto_chat_entry *pce; + GList *parts = prpl_info->chat_info(purple_account_get_connection(priv->account)); + pce = parts->data; + ret = g_hash_table_lookup(priv->components, pce->identifier); + g_list_foreach(parts, (GFunc)g_free, NULL); + g_list_free(parts); + } + + return ret; +} + +void +purple_chat_set_alias(PurpleChat *chat, const char *alias) +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + char *old_alias; + char *new_alias = NULL; + PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat); + + g_return_if_fail(priv != NULL); + + if ((alias != NULL) && (*alias != '\0')) + new_alias = purple_utf8_strip_unprintables(alias); + + if (!purple_strings_are_different(priv->alias, new_alias)) { + g_free(new_alias); + return; + } + + old_alias = priv->alias; + + if ((new_alias != NULL) && (*new_alias != '\0')) + priv->alias = new_alias; + else { + priv->alias = NULL; + g_free(new_alias); /* could be "\0" */ + } + + if (ops) { + if (ops->save_node) + ops->save_node(PURPLE_BLIST_NODE(chat)); + if (ops->update) + ops->update(purple_blist_get_buddy_list(), PURPLE_BLIST_NODE(chat)); + } + + purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased", + chat, old_alias); + g_free(old_alias); +} + +PurpleGroup * +purple_chat_get_group(PurpleChat *chat) +{ + g_return_val_if_fail(chat != NULL, NULL); + + return PURPLE_GROUP(PURPLE_BLIST_NODE(chat)->parent); +} + +PurpleAccount * +purple_chat_get_account(PurpleChat *chat) +{ + PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->account; +} + +GHashTable * +purple_chat_get_components(PurpleChat *chat) +{ + PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->components; +} + +/************************************************************************** + * GObject code for PurpleChat + **************************************************************************/ + +/* GObject Property names */ +#define CHAT_PROP_ALIAS_S "alias" +#define CHAT_PROP_ACCOUNT_S "account" +#define CHAT_PROP_COMPONENTS_S "components" + +/* Set method for GObject properties */ +static void +purple_chat_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleChat *chat = PURPLE_CHAT(obj); + PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat); + + switch (param_id) { + case CHAT_PROP_ALIAS: + priv->alias = purple_utf8_strip_unprintables(g_value_get_string(value)); + break; + case CHAT_PROP_ACCOUNT: + priv->account = g_value_get_object(value); + break; + case CHAT_PROP_COMPONENTS: + priv->components = g_value_get_pointer(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_chat_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleChat *chat = PURPLE_CHAT(obj); + PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat); + + switch (param_id) { + case CHAT_PROP_ALIAS: + g_value_set_string(value, priv->alias); + break; + case CHAT_PROP_ACCOUNT: + g_value_set_object(value, purple_chat_get_account(chat)); + break; + case CHAT_PROP_COMPONENTS: + g_value_set_pointer(value, purple_chat_get_components(chat)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* GObject initialization function */ +static void +purple_chat_init(GTypeInstance *instance, gpointer klass) +{ + PURPLE_DBUS_REGISTER_POINTER(PURPLE_CHAT(instance), PurpleChat); +} + +/* Called when done constructing */ +static void +purple_chat_constructed(GObject *object) +{ + PurpleChat *chat = PURPLE_CHAT(object); + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + + G_OBJECT_CLASS(blistnode_parent_class)->constructed(object); + + if (ops != NULL && ops->new_node != NULL) + ops->new_node(PURPLE_BLIST_NODE(chat)); +} + +/* GObject dispose function */ +static void +purple_chat_dispose(GObject *object) +{ + PURPLE_DBUS_UNREGISTER_POINTER(object); + + G_OBJECT_CLASS(blistnode_parent_class)->dispose(object); +} + +/* GObject finalize function */ +static void +purple_chat_finalize(GObject *object) +{ + PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(object); + + g_free(priv->alias); + g_hash_table_destroy(priv->components); + + G_OBJECT_CLASS(blistnode_parent_class)->finalize(object); +} + +/* Class initializer function */ +static void purple_chat_class_init(PurpleChatClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + blistnode_parent_class = g_type_class_peek_parent(klass); + + obj_class->dispose = purple_chat_dispose; + obj_class->finalize = purple_chat_finalize; + + /* Setup properties */ + obj_class->get_property = purple_chat_get_property; + obj_class->set_property = purple_chat_set_property; + obj_class->constructed = purple_chat_constructed; + + g_object_class_install_property(obj_class, CHAT_PROP_ALIAS, + g_param_spec_string(CHAT_PROP_ALIAS_S, _("Alias"), + _("The alias for the chat."), NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_object_class_install_property(obj_class, CHAT_PROP_ACCOUNT, + g_param_spec_object(CHAT_PROP_ACCOUNT_S, _("Account"), + _("The account that the chat belongs to."), PURPLE_TYPE_ACCOUNT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY) + ); + + g_object_class_install_property(obj_class, CHAT_PROP_COMPONENTS, + g_param_spec_pointer(CHAT_PROP_COMPONENTS_S, _("Components"), + _("The protocol components of the chat."), + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY) + ); + + g_type_class_add_private(klass, sizeof(PurpleChatPrivate)); +} + +GType +purple_chat_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleChatClass), + NULL, + NULL, + (GClassInitFunc)purple_chat_class_init, + NULL, + NULL, + sizeof(PurpleChat), + 0, + (GInstanceInitFunc)purple_chat_init, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_BLIST_NODE, + "PurpleChat", + &info, 0); + } + + return type; +} + +PurpleChat * +purple_chat_new(PurpleAccount *account, const char *alias, GHashTable *components) +{ + g_return_val_if_fail(account != NULL, NULL); + g_return_val_if_fail(components != NULL, NULL); + + return g_object_new(PURPLE_TYPE_CHAT, + CHAT_PROP_ACCOUNT_S, account, + CHAT_PROP_ALIAS_S, alias, + CHAT_PROP_COMPONENTS_S, components, + NULL); +} + +/**************************************************************************/ +/* Group API */ +/**************************************************************************/ + +GSList *purple_group_get_accounts(PurpleGroup *group) +{ + GSList *l = NULL; + PurpleBlistNode *gnode, *cnode, *bnode; + + gnode = (PurpleBlistNode *)group; + + for (cnode = gnode->child; cnode; cnode = cnode->next) { + if (PURPLE_IS_CHAT(cnode)) { + if (!g_slist_find(l, purple_chat_get_account(PURPLE_CHAT(cnode)))) + l = g_slist_append(l, purple_chat_get_account(PURPLE_CHAT(cnode))); + } else if (PURPLE_IS_CONTACT(cnode)) { + for (bnode = cnode->child; bnode; bnode = bnode->next) { + if (PURPLE_IS_BUDDY(bnode)) { + if (!g_slist_find(l, purple_buddy_get_account(PURPLE_BUDDY(bnode)))) + l = g_slist_append(l, purple_buddy_get_account(PURPLE_BUDDY(bnode))); + } + } + } + } + + return l; +} + +gboolean purple_group_on_account(PurpleGroup *g, PurpleAccount *account) +{ + PurpleBlistNode *cnode; + for (cnode = ((PurpleBlistNode *)g)->child; cnode; cnode = cnode->next) { + if (PURPLE_IS_CONTACT(cnode)) { + if(purple_contact_on_account((PurpleContact *) cnode, account)) + return TRUE; + } else if (PURPLE_IS_CHAT(cnode)) { + PurpleChat *chat = (PurpleChat *)cnode; + if ((!account && purple_account_is_connected(purple_chat_get_account(chat))) + || purple_chat_get_account(chat) == account) + return TRUE; + } + } + return FALSE; +} + +/* + * TODO: If merging, prompt the user if they want to merge. + */ +void purple_group_set_name(PurpleGroup *source, const char *name) +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleGroup *dest; + gchar *old_name; + gchar *new_name; + GList *moved_buddies = NULL; + GSList *accts; + PurpleGroupPrivate *priv = PURPLE_GROUP_GET_PRIVATE(source); + + g_return_if_fail(priv != NULL); + g_return_if_fail(name != NULL); + + new_name = purple_utf8_strip_unprintables(name); + + if (*new_name == '\0' || purple_strequal(new_name, priv->name)) { + g_free(new_name); + return; + } + + dest = purple_blist_find_group(new_name); + if (dest != NULL && purple_utf8_strcasecmp(priv->name, + PURPLE_GROUP_GET_PRIVATE(dest)->name) != 0) { + /* We're merging two groups */ + PurpleBlistNode *prev, *child, *next; + + prev = _purple_blist_get_last_child((PurpleBlistNode*)dest); + child = PURPLE_BLIST_NODE(source)->child; + + /* + * TODO: This seems like a dumb way to do this... why not just + * append all children from the old group to the end of the new + * one? PRPLs might be expecting to receive an add_buddy() for + * each moved buddy... + */ + while (child) + { + next = child->next; + if (PURPLE_IS_CONTACT(child)) { + PurpleBlistNode *bnode; + purple_blist_add_contact((PurpleContact *)child, dest, prev); + for (bnode = child->child; bnode != NULL; bnode = bnode->next) { + purple_blist_add_buddy((PurpleBuddy *)bnode, (PurpleContact *)child, + NULL, bnode->prev); + moved_buddies = g_list_append(moved_buddies, bnode); + } + prev = child; + } else if (PURPLE_IS_CHAT(child)) { + purple_blist_add_chat((PurpleChat *)child, dest, prev); + prev = child; + } else { + purple_debug(PURPLE_DEBUG_ERROR, "blist", + "Unknown child type in group %s\n", priv->name); + } + child = next; + } + + /* Make a copy of the old group name and then delete the old group */ + old_name = g_strdup(priv->name); + purple_blist_remove_group(source); + source = dest; + g_free(new_name); + } else { + /* A simple rename */ + PurpleBlistNode *cnode, *bnode; + + /* Build a GList of all buddies in this group */ + for (cnode = PURPLE_BLIST_NODE(source)->child; cnode != NULL; cnode = cnode->next) { + if (PURPLE_IS_CONTACT(cnode)) + for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) + moved_buddies = g_list_append(moved_buddies, bnode); + } + + purple_blist_update_groups_cache(source, new_name); + + old_name = priv->name; + priv->name = new_name; + } + + /* Save our changes */ + if (ops && ops->save_node) + ops->save_node(PURPLE_BLIST_NODE(source)); + + /* Update the UI */ + if (ops && ops->update) + ops->update(purple_blist_get_buddy_list(), PURPLE_BLIST_NODE(source)); + + /* Notify all PRPLs */ + /* TODO: Is this condition needed? Seems like it would always be TRUE */ + if(old_name && !purple_strequal(priv->name, old_name)) { + for (accts = purple_group_get_accounts(source); accts; accts = g_slist_remove(accts, accts->data)) { + PurpleAccount *account = accts->data; + PurpleConnection *gc = NULL; + PurplePlugin *prpl = NULL; + PurplePluginProtocolInfo *prpl_info = NULL; + GList *l = NULL, *buddies = NULL; + + gc = purple_account_get_connection(account); + + if(gc) + prpl = purple_connection_get_prpl(gc); + + if(gc && prpl) + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + + if(!prpl_info) + continue; + + for(l = moved_buddies; l; l = l->next) { + PurpleBuddy *buddy = PURPLE_BUDDY(l->data); + + if(buddy && purple_buddy_get_account(buddy) == account) + buddies = g_list_append(buddies, (PurpleBlistNode *)buddy); + } + + if(prpl_info->rename_group) { + prpl_info->rename_group(gc, old_name, source, buddies); + } else { + GList *cur, *groups = NULL; + + /* Make a list of what the groups each buddy is in */ + for(cur = buddies; cur; cur = cur->next) { + PurpleBlistNode *node = (PurpleBlistNode *)cur->data; + groups = g_list_prepend(groups, node->parent->parent); + } + + purple_account_remove_buddies(account, buddies, groups); + g_list_free(groups); + purple_account_add_buddies(account, buddies, NULL); + } + + g_list_free(buddies); + } + } + g_list_free(moved_buddies); + g_free(old_name); +} + +const char *purple_group_get_name(PurpleGroup *group) +{ + PurpleGroupPrivate *priv = PURPLE_GROUP_GET_PRIVATE(group); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->name; +} + +/************************************************************************** + * GObject code for PurpleGroup + **************************************************************************/ + +/* GObject Property names */ +#define GROUP_PROP_NAME_S "name" + +/* Set method for GObject properties */ +static void +purple_group_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleGroupPrivate *priv = PURPLE_GROUP_GET_PRIVATE(obj); + + switch (param_id) { + case GROUP_PROP_NAME: + priv->name = purple_utf8_strip_unprintables(g_value_get_string(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_group_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleGroup *group = PURPLE_GROUP(obj); + + switch (param_id) { + case GROUP_PROP_NAME: + g_value_set_string(value, purple_group_get_name(group)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* GObject initialization function */ +static void +purple_group_init(GTypeInstance *instance, gpointer klass) +{ + PURPLE_DBUS_REGISTER_POINTER(PURPLE_GROUP(instance), PurpleGroup); +} + +/* Called when done constructing */ +static void +purple_group_constructed(GObject *object) +{ + PurpleGroup *group = PURPLE_GROUP(object); + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + + G_OBJECT_CLASS(counting_parent_class)->constructed(object); + + if (ops && ops->new_node) + ops->new_node(PURPLE_BLIST_NODE(group)); +} + +/* GObject dispose function */ +static void +purple_group_dispose(GObject *object) +{ + PURPLE_DBUS_UNREGISTER_POINTER(object); + + G_OBJECT_CLASS(counting_parent_class)->dispose(object); +} + +/* GObject finalize function */ +static void +purple_group_finalize(GObject *object) +{ + g_free(PURPLE_GROUP_GET_PRIVATE(object)->name); + + G_OBJECT_CLASS(counting_parent_class)->finalize(object); +} + +/* Class initializer function */ +static void purple_group_class_init(PurpleGroupClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + counting_parent_class = g_type_class_peek_parent(klass); + + obj_class->dispose = purple_group_dispose; + obj_class->finalize = purple_group_finalize; + obj_class->constructed = purple_group_constructed; + + /* Setup properties */ + obj_class->get_property = purple_group_get_property; + obj_class->set_property = purple_group_set_property; + + g_object_class_install_property(obj_class, GROUP_PROP_NAME, + g_param_spec_string(GROUP_PROP_NAME_S, _("Name"), + _("Name of the group."), NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_type_class_add_private(klass, sizeof(PurpleGroupPrivate)); +} + +GType +purple_group_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleGroupClass), + NULL, + NULL, + (GClassInitFunc)purple_group_class_init, + NULL, + NULL, + sizeof(PurpleGroup), + 0, + (GInstanceInitFunc)purple_group_init, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_COUNTING_NODE, + "PurpleGroup", + &info, 0); + } + + return type; +} + +PurpleGroup * +purple_group_new(const char *name) +{ + PurpleGroup *group; + + g_return_val_if_fail(name != NULL, NULL); + g_return_val_if_fail(*name != '\0', NULL); + + group = purple_blist_find_group(name); + if (group != NULL) + return group; + + return g_object_new(PURPLE_TYPE_GROUP, GROUP_PROP_NAME_S, name, NULL); +} diff --git a/libpurple/blistnodetypes.h b/libpurple/blistnodetypes.h new file mode 100644 index 0000000000..578955bc7f --- /dev/null +++ b/libpurple/blistnodetypes.h @@ -0,0 +1,611 @@ +/** + * @file blistnodetypes.h Buddy, Chat, Contact and Group API + * @ingroup core + */ +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef _PURPLE_BLISTNODE_TYPES_H_ +#define _PURPLE_BLISTNODE_TYPES_H_ + +#include "blistnode.h" + +#define PURPLE_TYPE_BUDDY (purple_buddy_get_type()) +#define PURPLE_BUDDY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_BUDDY, PurpleBuddy)) +#define PURPLE_BUDDY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_BUDDY, PurpleBuddyClass)) +#define PURPLE_IS_BUDDY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_BUDDY)) +#define PURPLE_IS_BUDDY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_BUDDY)) +#define PURPLE_BUDDY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_BUDDY, PurpleBuddyClass)) + +/** @copydoc _PurpleBuddy */ +typedef struct _PurpleBuddy PurpleBuddy; +/** @copydoc _PurpleBuddyClass */ +typedef struct _PurpleBuddyClass PurpleBuddyClass; + +#define PURPLE_TYPE_CONTACT (purple_contact_get_type()) +#define PURPLE_CONTACT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_CONTACT, PurpleContact)) +#define PURPLE_CONTACT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_CONTACT, PurpleContactClass)) +#define PURPLE_IS_CONTACT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_CONTACT)) +#define PURPLE_IS_CONTACT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_CONTACT)) +#define PURPLE_CONTACT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_CONTACT, PurpleContactClass)) + +/** @copydoc _PurpleContact */ +typedef struct _PurpleContact PurpleContact; +/** @copydoc _PurpleContactClass */ +typedef struct _PurpleContactClass PurpleContactClass; + +#define PURPLE_TYPE_GROUP (purple_group_get_type()) +#define PURPLE_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_GROUP, PurpleGroup)) +#define PURPLE_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_GROUP, PurpleGroupClass)) +#define PURPLE_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_GROUP)) +#define PURPLE_IS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_GROUP)) +#define PURPLE_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_GROUP, PurpleGroupClass)) + +/** @copydoc _PurpleGroup */ +typedef struct _PurpleGroup PurpleGroup; +/** @copydoc _PurpleGroupClass */ +typedef struct _PurpleGroupClass PurpleGroupClass; + +#define PURPLE_TYPE_CHAT (purple_chat_get_type()) +#define PURPLE_CHAT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_CHAT, PurpleChat)) +#define PURPLE_CHAT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_CHAT, PurpleChatClass)) +#define PURPLE_IS_CHAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_CHAT)) +#define PURPLE_IS_CHAT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_CHAT)) +#define PURPLE_CHAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_CHAT, PurpleChatClass)) + +/** @copydoc _PurpleChat */ +typedef struct _PurpleChat PurpleChat; +/** @copydoc _PurpleChatClass */ +typedef struct _PurpleChatClass PurpleChatClass; + +#include "account.h" +#include "buddyicon.h" +#include "media.h" +#include "presence.h" +#include "status.h" + +#define PURPLE_BUDDY_IS_ONLINE(b) \ + (PURPLE_IS_BUDDY(b) \ + && purple_account_is_connected(purple_buddy_get_account(PURPLE_BUDDY(b))) \ + && purple_presence_is_online(purple_buddy_get_presence(PURPLE_BUDDY(b)))) + +#define PURPLE_BLIST_NODE_NAME(n) \ + (PURPLE_IS_CHAT(n) ? purple_chat_get_name(PURPLE_CHAT(n)) : \ + PURPLE_IS_BUDDY(n) ? purple_buddy_get_name(PURPLE_BUDDY(n)) : NULL) + +/**************************************************************************/ +/* Data Structures */ +/**************************************************************************/ +/** + * A buddy on the buddy list. + */ +struct _PurpleBuddy { + /** The node that this buddy inherits from */ + PurpleBlistNode node; +}; + +/** The base class for all #PurpleBuddy's. */ +struct _PurpleBuddyClass { + /*< private >*/ + PurpleBlistNodeClass node_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/** + * A contact on the buddy list. + */ +struct _PurpleContact { + /** + * The counting node that this contact inherits from. This keeps track + * of the counts of the buddies under this contact. + */ + PurpleCountingNode counting; +}; + +/** The base class for all #PurpleContact's. */ +struct _PurpleContactClass { + /*< private >*/ + PurpleCountingNodeClass counting_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/** + * A group on the buddy list. + */ +struct _PurpleGroup { + /** + * The counting node that this group inherits from. This keeps track + * of the counts of the chats and contacts under this group. + */ + PurpleCountingNode counting; +}; + +/** The base class for all #PurpleGroup's. */ +struct _PurpleGroupClass { + /*< private >*/ + PurpleCountingNodeClass counting_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/** + * A chat on the buddy list. + */ +struct _PurpleChat { + /** The node that this chat inherits from */ + PurpleBlistNode node; +}; + +/** The base class for all #PurpleChat's. */ +struct _PurpleChatClass { + /*< private >*/ + PurpleBlistNodeClass node_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +/**************************************************************************/ +/** @name Buddy API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the PurpleBuddy object. + */ +GType purple_buddy_get_type(void); + +/** + * Creates a new buddy. + * + * This function only creates the PurpleBuddy. Use purple_blist_add_buddy + * to add the buddy to the list and purple_account_add_buddy to sync up + * with the server. + * + * @param account The account this buddy will get added to + * @param name The name of the new buddy + * @param alias The alias of the new buddy (or NULL if unaliased) + * @return A newly allocated buddy + * + * @see purple_account_add_buddy + * @see purple_blist_add_buddy + */ +PurpleBuddy *purple_buddy_new(PurpleAccount *account, const char *name, const char *alias); + +/** + * Sets a buddy's icon. + * + * This should only be called from within Purple. You probably want to + * call purple_buddy_icon_set_data(). + * + * @param buddy The buddy. + * @param icon The buddy icon. + * + * @see purple_buddy_icon_set_data() + */ +void purple_buddy_set_icon(PurpleBuddy *buddy, PurpleBuddyIcon *icon); + +/** + * Returns a buddy's icon. + * + * @param buddy The buddy. + * + * @return The buddy icon. + */ +PurpleBuddyIcon *purple_buddy_get_icon(const PurpleBuddy *buddy); + +/** + * Returns a buddy's account. + * + * @param buddy The buddy. + * + * @return The account + */ +PurpleAccount *purple_buddy_get_account(const PurpleBuddy *buddy); + +/** + * Sets a buddy's name + * + * @param buddy The buddy. + * @param name The name. + */ +void purple_buddy_set_name(PurpleBuddy *buddy, const char *name); + +/** + * Returns a buddy's name + * + * @param buddy The buddy. + * + * @return The name. + */ +const char *purple_buddy_get_name(const PurpleBuddy *buddy); + +/** + * Returns a buddy's protocol-specific data. + * + * This should only be called from the associated prpl. + * + * @param buddy The buddy. + * @return The protocol data. + * + * @see purple_buddy_set_protocol_data() + */ +gpointer purple_buddy_get_protocol_data(const PurpleBuddy *buddy); + +/** + * Sets a buddy's protocol-specific data. + * + * This should only be called from the associated prpl. + * + * @param buddy The buddy. + * @param data The data. + * + * @see purple_buddy_get_protocol_data() + */ +void purple_buddy_set_protocol_data(PurpleBuddy *buddy, gpointer data); + +/** + * Returns a buddy's contact. + * + * @param buddy The buddy. + * + * @return The buddy's contact. + */ +PurpleContact *purple_buddy_get_contact(PurpleBuddy *buddy); + +/** + * Returns a buddy's presence. + * + * @param buddy The buddy. + * + * @return The buddy's presence. + */ +PurplePresence *purple_buddy_get_presence(const PurpleBuddy *buddy); + +/** + * Updates a buddy's status. + * + * This should only be called from within Purple. + * + * @param buddy The buddy whose status has changed. + * @param old_status The status from which we are changing. + */ +void purple_buddy_update_status(PurpleBuddy *buddy, PurpleStatus *old_status); + +/** + * Gets the media caps from a buddy. + * + * @param buddy The buddy. + * @return The media caps. + */ +PurpleMediaCaps purple_buddy_get_media_caps(const PurpleBuddy *buddy); + +/** + * Sets the media caps for a buddy. + * + * @param buddy The PurpleBuddy. + * @param media_caps The PurpleMediaCaps. + */ +void purple_buddy_set_media_caps(PurpleBuddy *buddy, PurpleMediaCaps media_caps); + +/** + * Returns the alias of a buddy. + * + * @param buddy The buddy whose alias will be returned. + * @return The alias (if set), server alias (if set), + * or NULL. + */ +const char *purple_buddy_get_alias_only(PurpleBuddy *buddy); + +/** + * Sets the server alias for a buddy. + * + * @param buddy The buddy. + * @param alias The server alias to be set. + */ +void purple_buddy_set_server_alias(PurpleBuddy *buddy, const char *alias); + +/** + * Gets the server alias for a buddy. + * + * @param buddy The buddy whose server alias will be returned + * @return The server alias, or NULL if it is not set. + */ +const char *purple_buddy_get_server_alias(PurpleBuddy *buddy); + +/** + * Returns the correct name to display for a buddy, taking the contact alias + * into account. In order of precedence: the buddy's alias; the buddy's + * contact alias; the buddy's server alias; the buddy's user name. + * + * @param buddy The buddy whose alias will be returned + * @return The appropriate name or alias, or NULL. + * + */ +const char *purple_buddy_get_contact_alias(PurpleBuddy *buddy); + +/** + * Returns the correct name to display for a buddy. In order of precedence: + * the buddy's local alias; the buddy's server alias; the buddy's contact alias; + * the buddy's user name. + * + * @param buddy The buddy whose alias will be returned. + * @return The appropriate name or alias, or NULL + */ +const char *purple_buddy_get_alias(PurpleBuddy *buddy); + +/** + * Sets the local alias for the buddy. + * + * @param buddy The buddy + * @param alias The local alias for the buddy + */ +void purple_buddy_set_local_alias(PurpleBuddy *buddy, const char *alias); + +/** + * Returns the local alias for the buddy, or @c NULL if none exists. + * + * @param buddy The buddy + * @return The local alias for the buddy + */ +const char *purple_buddy_get_local_alias(PurpleBuddy *buddy); + +/** + * Returns the group of which the buddy is a member. + * + * @param buddy The buddy + * @return The group or NULL if the buddy is not in a group + */ +PurpleGroup *purple_buddy_get_group(PurpleBuddy *buddy); + +/*@}*/ + +/**************************************************************************/ +/** @name Contact API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the PurpleContact object. + */ +GType purple_contact_get_type(void); + +/** + * Creates a new contact + * + * @return A new contact struct + */ +PurpleContact *purple_contact_new(void); + +/** + * Gets the PurpleGroup from a PurpleContact + * + * @param contact The contact + * @return The group + */ +PurpleGroup *purple_contact_get_group(const PurpleContact *contact); + +/** + * Returns the highest priority buddy for a given contact. + * + * @param contact The contact + * @return The highest priority buddy + */ +PurpleBuddy *purple_contact_get_priority_buddy(PurpleContact *contact); + +/** + * Sets the alias for a contact. + * + * @param contact The contact + * @param alias The alias + */ +void purple_contact_set_alias(PurpleContact *contact, const char *alias); + +/** + * Gets the alias for a contact. + * + * @param contact The contact + * @return The alias, or NULL if it is not set. + */ +const char *purple_contact_get_alias(PurpleContact *contact); + +/** + * Determines whether an account owns any buddies in a given contact + * + * @param contact The contact to search through. + * @param account The account. + * + * @return TRUE if there are any buddies from account in the contact, or FALSE otherwise. + */ +gboolean purple_contact_on_account(PurpleContact *contact, PurpleAccount *account); + +/** + * Invalidates the priority buddy so that the next call to + * purple_contact_get_priority_buddy recomputes it. + * + * @param contact The contact + */ +void purple_contact_invalidate_priority_buddy(PurpleContact *contact); + +/** + * Merges two contacts + * + * All of the buddies from source will be moved to target + * + * @param source The contact to merge + * @param node The place to merge to (a buddy or contact) + */ +void purple_contact_merge(PurpleContact *source, PurpleBlistNode *node); + +/*@}*/ + +/**************************************************************************/ +/** @name Chat API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the PurpleChat object. + */ +GType purple_chat_get_type(void); + +/** + * Creates a new chat for the buddy list + * + * @param account The account this chat will get added to + * @param alias The alias of the new chat + * @param components The info the prpl needs to join the chat. The + * hash function should be g_str_hash() and the + * equal function should be g_str_equal(). + * @return A newly allocated chat + */ +PurpleChat *purple_chat_new(PurpleAccount *account, const char *alias, GHashTable *components); + +/** + * Returns the correct name to display for a blist chat. + * + * @param chat The chat whose name will be returned. + * @return The alias (if set), or first component value. + */ +const char *purple_chat_get_name(PurpleChat *chat); + +/** + * Returns the name of the chat + * + * @param chat The chat whose name will be returned. + * @return The first component value. + */ +const char *purple_chat_get_name_only(PurpleChat *chat); + +/** + * Sets the alias for a blist chat. + * + * @param chat The chat + * @param alias The alias + */ +void purple_chat_set_alias(PurpleChat *chat, const char *alias); + +/** + * Returns the group of which the chat is a member. + * + * @param chat The chat. + * + * @return The parent group, or @c NULL if the chat is not in a group. + */ +PurpleGroup *purple_chat_get_group(PurpleChat *chat); + +/** + * Returns the account the chat belongs to. + * + * @param chat The chat. + * + * @return The account the chat belongs to. + */ +PurpleAccount *purple_chat_get_account(PurpleChat *chat); + +/** + * Get a hashtable containing information about a chat. + * + * @param chat The chat. + * + * @constreturn The hashtable. + */ +GHashTable *purple_chat_get_components(PurpleChat *chat); + +/*@}*/ + +/**************************************************************************/ +/** @name Group API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the PurpleGroup object. + */ +GType purple_group_get_type(void); + +/** + * Creates a new group + * + * You can't have more than one group with the same name. Sorry. If you pass + * this the name of a group that already exists, it will return that group. + * + * @param name The name of the new group + * @return A new group struct +*/ +PurpleGroup *purple_group_new(const char *name); + +/** + * Returns a list of accounts that have buddies in this group + * + * @param g The group + * + * @return A GSList of accounts (which must be freed), or NULL if the group + * has no accounts. + */ +GSList *purple_group_get_accounts(PurpleGroup *g); + +/** + * Determines whether an account owns any buddies in a given group + * + * @param g The group to search through. + * @param account The account. + * + * @return TRUE if there are any buddies in the group, or FALSE otherwise. + */ +gboolean purple_group_on_account(PurpleGroup *g, PurpleAccount *account); + +/** + * Sets the name of a group. + * + * @param group The group. + * @param name The name of the group. + */ +void purple_group_set_name(PurpleGroup *group, const char *name); + +/** + * Returns the name of a group. + * + * @param group The group. + * + * @return The name of the group. + */ +const char *purple_group_get_name(PurpleGroup *group); + +/*@}*/ + +G_END_DECLS + +#endif /* _PURPLE_BLISTNODE_TYPES_H_ */ diff --git a/libpurple/buddyicon.c b/libpurple/buddyicon.c index e5ee76ee71..edb3828bfe 100644 --- a/libpurple/buddyicon.c +++ b/libpurple/buddyicon.c @@ -371,7 +371,7 @@ purple_buddy_icon_unref(PurpleBuddyIcon *icon) void purple_buddy_icon_update(PurpleBuddyIcon *icon) { - PurpleConversation *conv; + PurpleIMConversation *im; PurpleAccount *account; const char *username; PurpleBuddyIcon *icon_to_set; @@ -392,7 +392,7 @@ purple_buddy_icon_update(PurpleBuddyIcon *icon) /* Ensure that icon remains valid throughout */ purple_buddy_icon_ref(icon); - buddies = purple_find_buddies(account, username); + buddies = purple_blist_find_buddies(account, username); while (buddies != NULL) { PurpleBuddy *buddy = (PurpleBuddy *)buddies->data; @@ -432,10 +432,10 @@ purple_buddy_icon_update(PurpleBuddyIcon *icon) buddies = g_slist_delete_link(buddies, buddies); } - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, account); + im = purple_conversations_find_im_with_account(username, account); - if (conv != NULL) - purple_conv_im_set_icon(PURPLE_CONV_IM(conv), icon_to_set); + if (im != NULL) + purple_im_conversation_set_icon(im, icon_to_set); /* icon's refcount was incremented above */ purple_buddy_icon_unref(icon); @@ -554,7 +554,7 @@ purple_buddy_icons_set_for_user(PurpleAccount *account, const char *username, * Since we know we're deleting the icon, we only * need a subset of purple_buddy_icon_update(). */ - GSList *buddies = purple_find_buddies(account, username); + GSList *buddies = purple_blist_find_buddies(account, username); while (buddies != NULL) { PurpleBuddy *buddy = (PurpleBuddy *)buddies->data; @@ -625,7 +625,7 @@ purple_buddy_icons_find(PurpleAccount *account, const char *username) if ((icon_cache == NULL) || ((icon = g_hash_table_lookup(icon_cache, username)) == NULL)) { /* The icon is not currently cached in memory--try reading from disk */ - PurpleBuddy *b = purple_find_buddy(account, username); + PurpleBuddy *b = purple_blist_find_buddy(account, username); const char *protocol_icon_file; const char *dirname; gboolean caching; @@ -838,12 +838,13 @@ purple_buddy_icons_node_set_custom_icon(PurpleBlistNode *node, char *old_icon; PurpleStoredImage *old_img; PurpleStoredImage *img = NULL; + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); g_return_val_if_fail(node != NULL, NULL); - if (!PURPLE_BLIST_NODE_IS_CONTACT(node) && - !PURPLE_BLIST_NODE_IS_CHAT(node) && - !PURPLE_BLIST_NODE_IS_GROUP(node)) { + if (!PURPLE_IS_CONTACT(node) && + !PURPLE_IS_CHAT(node) && + !PURPLE_IS_GROUP(node)) { return NULL; } @@ -870,39 +871,41 @@ purple_buddy_icons_node_set_custom_icon(PurpleBlistNode *node, else g_hash_table_remove(pointer_icon_cache, node); - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if (PURPLE_IS_CONTACT(node)) { PurpleBlistNode *child; for (child = purple_blist_node_get_first_child(node); child; child = purple_blist_node_get_sibling_next(child)) { PurpleBuddy *buddy; - PurpleConversation *conv; + PurpleIMConversation *im; - if (!PURPLE_BLIST_NODE_IS_BUDDY(child)) + if (!PURPLE_IS_BUDDY(child)) continue; buddy = (PurpleBuddy *)child; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); - if (conv) - purple_conversation_update(conv, PURPLE_CONV_UPDATE_ICON); + im = purple_conversations_find_im_with_account(purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); + if (im) + purple_conversation_update(PURPLE_CONVERSATION(im), PURPLE_CONVERSATION_UPDATE_ICON); /* Is this call necessary anymore? Can the buddies * themselves need updating when the custom buddy * icon changes? */ - purple_blist_update_node_icon((PurpleBlistNode*)buddy); + if (ops && ops->update) + ops->update(purple_blist_get_buddy_list(), PURPLE_BLIST_NODE(buddy)); } - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { - PurpleConversation *conv = NULL; + } else if (PURPLE_IS_CHAT(node)) { + PurpleChatConversation *chat = NULL; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, purple_chat_get_name((PurpleChat*)node), purple_chat_get_account((PurpleChat*)node)); - if (conv) { - purple_conversation_update(conv, PURPLE_CONV_UPDATE_ICON); + chat = purple_conversations_find_chat_with_account(purple_chat_get_name((PurpleChat*)node), purple_chat_get_account((PurpleChat*)node)); + if (chat) { + purple_conversation_update(PURPLE_CONVERSATION(chat), PURPLE_CONVERSATION_UPDATE_ICON); } } - purple_blist_update_node_icon(node); + if (ops && ops->update) + ops->update(purple_blist_get_buddy_list(), node); if (old_img) { purple_imgstore_unref(old_img); @@ -926,9 +929,9 @@ purple_buddy_icons_node_set_custom_icon_from_file(PurpleBlistNode *node, g_return_val_if_fail(node != NULL, NULL); - if (!PURPLE_BLIST_NODE_IS_CONTACT(node) && - !PURPLE_BLIST_NODE_IS_CHAT(node) && - !PURPLE_BLIST_NODE_IS_GROUP(node)) { + if (!PURPLE_IS_CONTACT(node) && + !PURPLE_IS_CHAT(node) && + !PURPLE_IS_GROUP(node)) { return NULL; } @@ -986,7 +989,7 @@ _purple_buddy_icons_blist_loaded_cb() while (node != NULL) { - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (PURPLE_IS_BUDDY(node)) { const char *filename; @@ -1006,9 +1009,9 @@ _purple_buddy_icons_blist_loaded_cb() g_free(path); } } - else if (PURPLE_BLIST_NODE_IS_CONTACT(node) || - PURPLE_BLIST_NODE_IS_CHAT(node) || - PURPLE_BLIST_NODE_IS_GROUP(node)) + else if (PURPLE_IS_CONTACT(node) || + PURPLE_IS_CHAT(node) || + PURPLE_IS_GROUP(node)) { const char *filename; @@ -1128,3 +1131,17 @@ void purple_buddy_icon_get_scale_size(PurpleBuddyIconSpec *spec, int *width, int *width = new_width; *height = new_height; } + +GType +purple_buddy_icon_get_type(void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static("PurpleBuddyIcon", + (GBoxedCopyFunc)purple_buddy_icon_ref, + (GBoxedFreeFunc)purple_buddy_icon_unref); + } + + return type; +} diff --git a/libpurple/buddyicon.h b/libpurple/buddyicon.h index 3be957594f..f395a85c55 100644 --- a/libpurple/buddyicon.h +++ b/libpurple/buddyicon.h @@ -26,6 +26,8 @@ #ifndef _PURPLE_BUDDYICON_H_ #define _PURPLE_BUDDYICON_H_ +#define PURPLE_TYPE_BUDDY_ICON (purple_buddy_icon_get_type()) + /** An opaque structure representing a buddy icon for a particular user on a * particular #PurpleAccount. Instances are reference-counted; use * purple_buddy_icon_ref() and purple_buddy_icon_unref() to take and release @@ -34,7 +36,7 @@ typedef struct _PurpleBuddyIcon PurpleBuddyIcon; #include "account.h" -#include "blist.h" +#include "buddylist.h" #include "imgstore.h" #include "prpl.h" #include "util.h" @@ -47,6 +49,11 @@ G_BEGIN_DECLS /*@{*/ /** + * Returns the GType for the PurpleBuddyIcon boxed structure. + */ +GType purple_buddy_icon_get_type(void); + +/** * Creates a new buddy icon structure and populates it. * * If an icon for this account+username already exists, you'll get a reference diff --git a/libpurple/buddylist.c b/libpurple/buddylist.c new file mode 100644 index 0000000000..11c2092d5d --- /dev/null +++ b/libpurple/buddylist.c @@ -0,0 +1,2108 @@ +/* + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ +#include "internal.h" +#include "buddylist.h" +#include "conversation.h" +#include "dbus-maybe.h" +#include "debug.h" +#include "notify.h" +#include "pounce.h" +#include "prefs.h" +#include "prpl.h" +#include "server.h" +#include "signals.h" +#include "util.h" +#include "xmlnode.h" + +#define PURPLE_BUDDY_LIST_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_BUDDY_LIST, PurpleBuddyListPrivate)) + +/** Private data for a buddy list. */ +typedef struct { + GHashTable *buddies; /**< Every buddy in this list */ +} PurpleBuddyListPrivate; + +static PurpleBlistUiOps *blist_ui_ops = NULL; + +static PurpleBuddyList *purplebuddylist = NULL; + +static GObjectClass *parent_class; + +/** + * A hash table used for efficient lookups of buddies by name. + * PurpleAccount* => GHashTable*, with the inner hash table being + * struct _purple_hbuddy => PurpleBuddy* + */ +static GHashTable *buddies_cache = NULL; + +/** + * A hash table used for efficient lookups of groups by name. + * UTF-8 collate-key => PurpleGroup*. + */ +static GHashTable *groups_cache = NULL; + +static guint save_timer = 0; +static gboolean blist_loaded = FALSE; + +PurpleBlistNode *_purple_blist_get_last_child(PurpleBlistNode *node); + +/********************************************************************* + * Private utility functions * + *********************************************************************/ + +static PurpleBlistNode *purple_blist_get_last_sibling(PurpleBlistNode *node) +{ + PurpleBlistNode *n = node; + if (!n) + return NULL; + while (n->next) + n = n->next; + return n; +} + +PurpleBlistNode *_purple_blist_get_last_child(PurpleBlistNode *node) +{ + if (!node) + return NULL; + return purple_blist_get_last_sibling(node->child); +} + +struct _list_account_buddies { + GSList *list; + PurpleAccount *account; +}; + +struct _purple_hbuddy { + char *name; + PurpleAccount *account; + PurpleBlistNode *group; +}; + +/* This function must not use purple_normalize */ +static guint _purple_blist_hbuddy_hash(struct _purple_hbuddy *hb) +{ + return g_str_hash(hb->name) ^ g_direct_hash(hb->group) ^ g_direct_hash(hb->account); +} + +/* This function must not use purple_normalize */ +static guint _purple_blist_hbuddy_equal(struct _purple_hbuddy *hb1, struct _purple_hbuddy *hb2) +{ + return (hb1->group == hb2->group && + hb1->account == hb2->account && + g_str_equal(hb1->name, hb2->name)); +} + +static void _purple_blist_hbuddy_free_key(struct _purple_hbuddy *hb) +{ + g_free(hb->name); + g_free(hb); +} + +static void +purple_blist_buddies_cache_add_account(PurpleAccount *account) +{ + GHashTable *account_buddies = g_hash_table_new_full((GHashFunc)_purple_blist_hbuddy_hash, + (GEqualFunc)_purple_blist_hbuddy_equal, + (GDestroyNotify)_purple_blist_hbuddy_free_key, NULL); + g_hash_table_insert(buddies_cache, account, account_buddies); +} + +static void +purple_blist_buddies_cache_remove_account(const PurpleAccount *account) +{ + g_hash_table_remove(buddies_cache, account); +} + +/********************************************************************* + * Writing to disk * + *********************************************************************/ + +static void +value_to_xmlnode(gpointer key, gpointer hvalue, gpointer user_data) +{ + const char *name; + GValue *value; + xmlnode *node, *child; + char buf[21]; + + name = (const char *)key; + value = (GValue *)hvalue; + node = (xmlnode *)user_data; + + g_return_if_fail(value != NULL); + + child = xmlnode_new_child(node, "setting"); + xmlnode_set_attrib(child, "name", name); + + if (G_VALUE_HOLDS_INT(value)) { + xmlnode_set_attrib(child, "type", "int"); + g_snprintf(buf, sizeof(buf), "%d", g_value_get_int(value)); + xmlnode_insert_data(child, buf, -1); + } + else if (G_VALUE_HOLDS_STRING(value)) { + xmlnode_set_attrib(child, "type", "string"); + xmlnode_insert_data(child, g_value_get_string(value), -1); + } + else if (G_VALUE_HOLDS_BOOLEAN(value)) { + xmlnode_set_attrib(child, "type", "bool"); + g_snprintf(buf, sizeof(buf), "%d", g_value_get_boolean(value)); + xmlnode_insert_data(child, buf, -1); + } +} + +static void +chat_component_to_xmlnode(gpointer key, gpointer value, gpointer user_data) +{ + const char *name; + const char *data; + xmlnode *node, *child; + + name = (const char *)key; + data = (const char *)value; + node = (xmlnode *)user_data; + + g_return_if_fail(data != NULL); + + child = xmlnode_new_child(node, "component"); + xmlnode_set_attrib(child, "name", name); + xmlnode_insert_data(child, data, -1); +} + +static xmlnode * +buddy_to_xmlnode(PurpleBuddy *buddy) +{ + xmlnode *node, *child; + PurpleAccount *account = purple_buddy_get_account(buddy); + const char *alias = purple_buddy_get_local_alias(buddy); + + node = xmlnode_new("buddy"); + xmlnode_set_attrib(node, "account", purple_account_get_username(account)); + xmlnode_set_attrib(node, "proto", purple_account_get_protocol_id(account)); + + child = xmlnode_new_child(node, "name"); + xmlnode_insert_data(child, purple_buddy_get_name(buddy), -1); + + if (alias != NULL) + { + child = xmlnode_new_child(node, "alias"); + xmlnode_insert_data(child, alias, -1); + } + + /* Write buddy settings */ + g_hash_table_foreach(purple_blist_node_get_settings(PURPLE_BLIST_NODE(buddy)), + value_to_xmlnode, node); + + return node; +} + +static xmlnode * +contact_to_xmlnode(PurpleContact *contact) +{ + xmlnode *node, *child; + PurpleBlistNode *bnode; + gchar *alias; + + node = xmlnode_new("contact"); + g_object_get(contact, "alias", &alias, NULL); + + if (alias != NULL) + { + xmlnode_set_attrib(node, "alias", alias); + } + + /* Write buddies */ + for (bnode = PURPLE_BLIST_NODE(contact)->child; bnode != NULL; bnode = bnode->next) + { + if (purple_blist_node_is_transient(bnode)) + continue; + if (PURPLE_IS_BUDDY(bnode)) + { + child = buddy_to_xmlnode(PURPLE_BUDDY(bnode)); + xmlnode_insert_child(node, child); + } + } + + /* Write contact settings */ + g_hash_table_foreach(purple_blist_node_get_settings(PURPLE_BLIST_NODE(contact)), + value_to_xmlnode, node); + + g_free(alias); + return node; +} + +static xmlnode * +chat_to_xmlnode(PurpleChat *chat) +{ + xmlnode *node, *child; + PurpleAccount *account = purple_chat_get_account(chat); + gchar *alias; + + g_object_get(chat, "alias", &alias, NULL); + + node = xmlnode_new("chat"); + xmlnode_set_attrib(node, "proto", purple_account_get_protocol_id(account)); + xmlnode_set_attrib(node, "account", purple_account_get_username(account)); + + if (alias != NULL) + { + child = xmlnode_new_child(node, "alias"); + xmlnode_insert_data(child, alias, -1); + } + + /* Write chat components */ + g_hash_table_foreach(purple_chat_get_components(chat), + chat_component_to_xmlnode, node); + + /* Write chat settings */ + g_hash_table_foreach(purple_blist_node_get_settings(PURPLE_BLIST_NODE(chat)), + value_to_xmlnode, node); + + g_free(alias); + return node; +} + +static xmlnode * +group_to_xmlnode(PurpleGroup *group) +{ + xmlnode *node, *child; + PurpleBlistNode *cnode; + + node = xmlnode_new("group"); + xmlnode_set_attrib(node, "name", purple_group_get_name(group)); + + /* Write settings */ + g_hash_table_foreach(purple_blist_node_get_settings(PURPLE_BLIST_NODE(group)), + value_to_xmlnode, node); + + /* Write contacts and chats */ + for (cnode = PURPLE_BLIST_NODE(group)->child; cnode != NULL; cnode = cnode->next) + { + if (purple_blist_node_is_transient(cnode)) + continue; + if (PURPLE_IS_CONTACT(cnode)) + { + child = contact_to_xmlnode(PURPLE_CONTACT(cnode)); + xmlnode_insert_child(node, child); + } + else if (PURPLE_IS_CHAT(cnode)) + { + child = chat_to_xmlnode(PURPLE_CHAT(cnode)); + xmlnode_insert_child(node, child); + } + } + + return node; +} + +static xmlnode * +accountprivacy_to_xmlnode(PurpleAccount *account) +{ + xmlnode *node, *child; + GSList *cur; + char buf[10]; + + node = xmlnode_new("account"); + xmlnode_set_attrib(node, "proto", purple_account_get_protocol_id(account)); + xmlnode_set_attrib(node, "name", purple_account_get_username(account)); + g_snprintf(buf, sizeof(buf), "%d", purple_account_get_privacy_type(account)); + xmlnode_set_attrib(node, "mode", buf); + + for (cur = purple_account_privacy_get_permitted(account); cur; cur = cur->next) + { + child = xmlnode_new_child(node, "permit"); + xmlnode_insert_data(child, cur->data, -1); + } + + for (cur = purple_account_privacy_get_denied(account); cur; cur = cur->next) + { + child = xmlnode_new_child(node, "block"); + xmlnode_insert_data(child, cur->data, -1); + } + + return node; +} + +static xmlnode * +blist_to_xmlnode(void) +{ + xmlnode *node, *child, *grandchild; + PurpleBlistNode *gnode; + GList *cur; + + node = xmlnode_new("purple"); + xmlnode_set_attrib(node, "version", "1.0"); + + /* Write groups */ + child = xmlnode_new_child(node, "blist"); + for (gnode = purplebuddylist->root; gnode != NULL; gnode = gnode->next) + { + if (purple_blist_node_is_transient(gnode)) + continue; + if (PURPLE_IS_GROUP(gnode)) + { + grandchild = group_to_xmlnode(PURPLE_GROUP(gnode)); + xmlnode_insert_child(child, grandchild); + } + } + + /* Write privacy settings */ + child = xmlnode_new_child(node, "privacy"); + for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next) + { + grandchild = accountprivacy_to_xmlnode(cur->data); + xmlnode_insert_child(child, grandchild); + } + + return node; +} + +static void +purple_blist_sync(void) +{ + xmlnode *node; + char *data; + + if (!blist_loaded) + { + purple_debug_error("blist", "Attempted to save buddy list before it " + "was read!\n"); + return; + } + + node = blist_to_xmlnode(); + data = xmlnode_to_formatted_str(node, NULL); + purple_util_write_data_to_file("blist.xml", data, -1); + g_free(data); + xmlnode_free(node); +} + +static gboolean +save_cb(gpointer data) +{ + purple_blist_sync(); + save_timer = 0; + return FALSE; +} + +static void +_purple_blist_schedule_save() +{ + if (save_timer == 0) + save_timer = purple_timeout_add_seconds(5, save_cb, NULL); +} + +static void +purple_blist_save_account(PurpleAccount *account) +{ +#if 1 + _purple_blist_schedule_save(); +#else + if (account != NULL) { + /* Save the buddies and privacy data for this account */ + } else { + /* Save all buddies and privacy data */ + } +#endif +} + +static void +purple_blist_save_node(PurpleBlistNode *node) +{ + _purple_blist_schedule_save(); +} + +void purple_blist_schedule_save() +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + + /* Save everything */ + if (ops && ops->save_account) + ops->save_account(NULL); +} + +/********************************************************************* + * Reading from disk * + *********************************************************************/ + +static void +parse_setting(PurpleBlistNode *node, xmlnode *setting) +{ + const char *name = xmlnode_get_attrib(setting, "name"); + const char *type = xmlnode_get_attrib(setting, "type"); + char *value = xmlnode_get_data(setting); + + if (!value) + return; + + if (!type || purple_strequal(type, "string")) + purple_blist_node_set_string(node, name, value); + else if (purple_strequal(type, "bool")) + purple_blist_node_set_bool(node, name, atoi(value)); + else if (purple_strequal(type, "int")) + purple_blist_node_set_int(node, name, atoi(value)); + + g_free(value); +} + +static void +parse_buddy(PurpleGroup *group, PurpleContact *contact, xmlnode *bnode) +{ + PurpleAccount *account; + PurpleBuddy *buddy; + char *name = NULL, *alias = NULL; + const char *acct_name, *proto; + xmlnode *x; + + acct_name = xmlnode_get_attrib(bnode, "account"); + proto = xmlnode_get_attrib(bnode, "proto"); + + if (!acct_name || !proto) + return; + + account = purple_accounts_find(acct_name, proto); + + if (!account) + return; + + if ((x = xmlnode_get_child(bnode, "name"))) + name = xmlnode_get_data(x); + + if (!name) + return; + + if ((x = xmlnode_get_child(bnode, "alias"))) + alias = xmlnode_get_data(x); + + buddy = purple_buddy_new(account, name, alias); + purple_blist_add_buddy(buddy, contact, group, + _purple_blist_get_last_child((PurpleBlistNode*)contact)); + + for (x = xmlnode_get_child(bnode, "setting"); x; x = xmlnode_get_next_twin(x)) { + parse_setting((PurpleBlistNode*)buddy, x); + } + + g_free(name); + g_free(alias); +} + +static void +parse_contact(PurpleGroup *group, xmlnode *cnode) +{ + PurpleContact *contact = purple_contact_new(); + xmlnode *x; + const char *alias; + + purple_blist_add_contact(contact, group, + _purple_blist_get_last_child((PurpleBlistNode*)group)); + + if ((alias = xmlnode_get_attrib(cnode, "alias"))) { + purple_contact_set_alias(contact, alias); + } + + for (x = cnode->child; x; x = x->next) { + if (x->type != XMLNODE_TYPE_TAG) + continue; + if (purple_strequal(x->name, "buddy")) + parse_buddy(group, contact, x); + else if (purple_strequal(x->name, "setting")) + parse_setting(PURPLE_BLIST_NODE(contact), x); + } + + /* if the contact is empty, don't keep it around. it causes problems */ + if (!PURPLE_BLIST_NODE(contact)->child) + purple_blist_remove_contact(contact); +} + +static void +parse_chat(PurpleGroup *group, xmlnode *cnode) +{ + PurpleChat *chat; + PurpleAccount *account; + const char *acct_name, *proto; + xmlnode *x; + char *alias = NULL; + GHashTable *components; + + acct_name = xmlnode_get_attrib(cnode, "account"); + proto = xmlnode_get_attrib(cnode, "proto"); + + if (!acct_name || !proto) + return; + + account = purple_accounts_find(acct_name, proto); + + if (!account) + return; + + if ((x = xmlnode_get_child(cnode, "alias"))) + alias = xmlnode_get_data(x); + + components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + + for (x = xmlnode_get_child(cnode, "component"); x; x = xmlnode_get_next_twin(x)) { + const char *name; + char *value; + + name = xmlnode_get_attrib(x, "name"); + value = xmlnode_get_data(x); + g_hash_table_replace(components, g_strdup(name), value); + } + + chat = purple_chat_new(account, alias, components); + purple_blist_add_chat(chat, group, + _purple_blist_get_last_child((PurpleBlistNode*)group)); + + for (x = xmlnode_get_child(cnode, "setting"); x; x = xmlnode_get_next_twin(x)) { + parse_setting((PurpleBlistNode*)chat, x); + } + + g_free(alias); +} + +static void +parse_group(xmlnode *groupnode) +{ + const char *name = xmlnode_get_attrib(groupnode, "name"); + PurpleGroup *group; + xmlnode *cnode; + + if (!name) + name = _("Buddies"); + + group = purple_group_new(name); + purple_blist_add_group(group, + purple_blist_get_last_sibling(purplebuddylist->root)); + + for (cnode = groupnode->child; cnode; cnode = cnode->next) { + if (cnode->type != XMLNODE_TYPE_TAG) + continue; + if (purple_strequal(cnode->name, "setting")) + parse_setting((PurpleBlistNode*)group, cnode); + else if (purple_strequal(cnode->name, "contact") || + purple_strequal(cnode->name, "person")) + parse_contact(group, cnode); + else if (purple_strequal(cnode->name, "chat")) + parse_chat(group, cnode); + } +} + +static void +load_blist(void) +{ + xmlnode *purple, *blist, *privacy; + + blist_loaded = TRUE; + + purple = purple_util_read_xml_from_file("blist.xml", _("buddy list")); + + if (purple == NULL) + return; + + blist = xmlnode_get_child(purple, "blist"); + if (blist) { + xmlnode *groupnode; + for (groupnode = xmlnode_get_child(blist, "group"); groupnode != NULL; + groupnode = xmlnode_get_next_twin(groupnode)) { + parse_group(groupnode); + } + } + + privacy = xmlnode_get_child(purple, "privacy"); + if (privacy) { + xmlnode *anode; + for (anode = privacy->child; anode; anode = anode->next) { + xmlnode *x; + PurpleAccount *account; + int imode; + const char *acct_name, *proto, *mode; + + acct_name = xmlnode_get_attrib(anode, "name"); + proto = xmlnode_get_attrib(anode, "proto"); + mode = xmlnode_get_attrib(anode, "mode"); + + if (!acct_name || !proto || !mode) + continue; + + account = purple_accounts_find(acct_name, proto); + + if (!account) + continue; + + imode = atoi(mode); + purple_account_set_privacy_type(account, (imode != 0 ? imode : PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL)); + + for (x = anode->child; x; x = x->next) { + char *name; + if (x->type != XMLNODE_TYPE_TAG) + continue; + + if (purple_strequal(x->name, "permit")) { + name = xmlnode_get_data(x); + purple_account_privacy_permit_add(account, name, TRUE); + g_free(name); + } else if (purple_strequal(x->name, "block")) { + name = xmlnode_get_data(x); + purple_account_privacy_deny_add(account, name, TRUE); + g_free(name); + } + } + } + } + + xmlnode_free(purple); + + /* This tells the buddy icon code to do its thing. */ + _purple_buddy_icons_blist_loaded_cb(); +} + +/***************************************************************************** + * Public API functions * + *****************************************************************************/ + +void +purple_blist_boot(void) +{ + PurpleBlistUiOps *ui_ops; + GList *account; + PurpleBuddyList *gbl = g_object_new(PURPLE_TYPE_BUDDY_LIST, NULL); + + ui_ops = purple_blist_get_ui_ops(); + + buddies_cache = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, (GDestroyNotify)g_hash_table_destroy); + + groups_cache = g_hash_table_new_full((GHashFunc)g_str_hash, + (GEqualFunc)g_str_equal, + (GDestroyNotify)g_free, NULL); + + for (account = purple_accounts_get_all(); account != NULL; account = account->next) + { + purple_blist_buddies_cache_add_account(account->data); + } + + if (ui_ops != NULL && ui_ops->new_list != NULL) + ui_ops->new_list(gbl); + + purplebuddylist = gbl; + + load_blist(); +} + +PurpleBuddyList * +purple_blist_get_buddy_list() +{ + return purplebuddylist; +} + +PurpleBlistNode * +purple_blist_get_root() +{ + return purplebuddylist ? purplebuddylist->root : NULL; +} + +static void +append_buddy(gpointer key, gpointer value, gpointer user_data) +{ + GSList **list = user_data; + *list = g_slist_prepend(*list, value); +} + +GSList * +purple_blist_get_buddies() +{ + GSList *buddies = NULL; + + if (!purplebuddylist) + return NULL; + + g_hash_table_foreach(PURPLE_BUDDY_LIST_GET_PRIVATE(purplebuddylist)->buddies, + append_buddy, &buddies); + return buddies; +} + +void * +purple_blist_get_ui_data() +{ + return purplebuddylist->ui_data; +} + +void +purple_blist_set_ui_data(void *ui_data) +{ + purplebuddylist->ui_data = ui_data; +} + +void purple_blist_show() +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + + if (ops && ops->show) + ops->show(purplebuddylist); +} + +void purple_blist_set_visible(gboolean show) +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + + if (ops && ops->set_visible) + ops->set_visible(purplebuddylist, show); +} + +void purple_blist_update_buddies_cache(PurpleBuddy *buddy, const char *new_name) +{ + struct _purple_hbuddy *hb, *hb2; + GHashTable *account_buddies; + PurpleAccount *account; + gchar *name; + PurpleBuddyListPrivate *priv = PURPLE_BUDDY_LIST_GET_PRIVATE(purplebuddylist); + + g_return_if_fail(buddy != NULL); + + account = purple_buddy_get_account(buddy); + name = (gchar *)purple_buddy_get_name(buddy); + + hb = g_new(struct _purple_hbuddy, 1); + hb->name = (gchar *)purple_normalize(account, name); + hb->account = account; + hb->group = PURPLE_BLIST_NODE(buddy)->parent->parent; + g_hash_table_remove(priv->buddies, hb); + + account_buddies = g_hash_table_lookup(buddies_cache, account); + g_hash_table_remove(account_buddies, hb); + + hb->name = g_strdup(purple_normalize(account, new_name)); + g_hash_table_replace(priv->buddies, hb, buddy); + + hb2 = g_new(struct _purple_hbuddy, 1); + hb2->name = g_strdup(hb->name); + hb2->account = account; + hb2->group = PURPLE_BLIST_NODE(buddy)->parent->parent; + + g_hash_table_replace(account_buddies, hb2, buddy); +} + +void purple_blist_update_groups_cache(PurpleGroup *group, const char *new_name) +{ + gchar* key = g_utf8_collate_key(purple_group_get_name(group), -1); + g_hash_table_remove(groups_cache, key); + g_free(key); + + key = g_utf8_collate_key(new_name, -1); + g_hash_table_insert(groups_cache, key, group); +} + +void purple_blist_add_chat(PurpleChat *chat, PurpleGroup *group, PurpleBlistNode *node) +{ + PurpleBlistNode *cnode = PURPLE_BLIST_NODE(chat); + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleCountingNode *group_counter; + + g_return_if_fail(chat != NULL); + + if (node == NULL) { + if (group == NULL) + group = purple_group_new(_("Chats")); + + /* Add group to blist if isn't already on it. Fixes #2752. */ + if (!purple_blist_find_group(purple_group_get_name(group))) { + purple_blist_add_group(group, + purple_blist_get_last_sibling(purplebuddylist->root)); + } + } else { + group = PURPLE_GROUP(node->parent); + } + + /* if we're moving to overtop of ourselves, do nothing */ + if (cnode == node) + return; + + if (cnode->parent) { + /* This chat was already in the list and is + * being moved. + */ + group_counter = PURPLE_COUNTING_NODE(cnode->parent); + purple_counting_node_change_total_size(group_counter, -1); + if (purple_account_is_connected(purple_chat_get_account(chat))) { + purple_counting_node_change_online_count(group_counter, -1); + purple_counting_node_change_current_size(group_counter, -1); + } + if (cnode->next) + cnode->next->prev = cnode->prev; + if (cnode->prev) + cnode->prev->next = cnode->next; + if (cnode->parent->child == cnode) + cnode->parent->child = cnode->next; + + if (ops && ops->remove) + ops->remove(purplebuddylist, cnode); + /* ops->remove() cleaned up the cnode's ui_data, so we need to + * reinitialize it */ + if (ops && ops->new_node) + ops->new_node(cnode); + } + + if (node != NULL) { + if (node->next) + node->next->prev = cnode; + cnode->next = node->next; + cnode->prev = node; + cnode->parent = node->parent; + node->next = cnode; + group_counter = PURPLE_COUNTING_NODE(node->parent); + purple_counting_node_change_total_size(group_counter, +1); + if (purple_account_is_connected(purple_chat_get_account(chat))) { + purple_counting_node_change_online_count(group_counter, +1); + purple_counting_node_change_current_size(group_counter, +1); + } + } else { + if (((PurpleBlistNode *)group)->child) + ((PurpleBlistNode *)group)->child->prev = cnode; + cnode->next = ((PurpleBlistNode *)group)->child; + cnode->prev = NULL; + ((PurpleBlistNode *)group)->child = cnode; + cnode->parent = PURPLE_BLIST_NODE(group); + group_counter = PURPLE_COUNTING_NODE(group); + purple_counting_node_change_total_size(group_counter, +1); + if (purple_account_is_connected(purple_chat_get_account(chat))) { + purple_counting_node_change_online_count(group_counter, +1); + purple_counting_node_change_current_size(group_counter, +1); + } + } + + if (ops) { + if (ops->save_node) + ops->save_node(cnode); + if (ops->update) + ops->update(purplebuddylist, PURPLE_BLIST_NODE(cnode)); + } + + purple_signal_emit(purple_blist_get_handle(), "blist-node-added", + cnode); +} + +void purple_blist_add_buddy(PurpleBuddy *buddy, PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node) +{ + PurpleBlistNode *cnode, *bnode; + PurpleCountingNode *contact_counter, *group_counter; + PurpleGroup *g; + PurpleContact *c; + PurpleAccount *account; + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + struct _purple_hbuddy *hb, *hb2; + GHashTable *account_buddies; + PurpleBuddyListPrivate *priv = PURPLE_BUDDY_LIST_GET_PRIVATE(purplebuddylist); + + g_return_if_fail(buddy != NULL); + g_return_if_fail(PURPLE_IS_BUDDY((PurpleBlistNode*)buddy)); + + bnode = PURPLE_BLIST_NODE(buddy); + account = purple_buddy_get_account(buddy); + + /* if we're moving to overtop of ourselves, do nothing */ + if (bnode == node || (!node && bnode->parent && + contact && bnode->parent == (PurpleBlistNode*)contact + && bnode == bnode->parent->child)) + return; + + if (node && PURPLE_IS_BUDDY(node)) { + c = (PurpleContact*)node->parent; + g = (PurpleGroup*)node->parent->parent; + } else if (contact) { + c = contact; + g = PURPLE_GROUP(PURPLE_BLIST_NODE(c)->parent); + } else { + g = group; + if (g == NULL) + g = purple_group_new(_("Buddies")); + /* Add group to blist if isn't already on it. Fixes #2752. */ + if (!purple_blist_find_group(purple_group_get_name(g))) { + purple_blist_add_group(g, + purple_blist_get_last_sibling(purplebuddylist->root)); + } + c = purple_contact_new(); + purple_blist_add_contact(c, g, + _purple_blist_get_last_child((PurpleBlistNode*)g)); + } + + cnode = PURPLE_BLIST_NODE(c); + + if (bnode->parent) { + contact_counter = PURPLE_COUNTING_NODE(bnode->parent); + group_counter = PURPLE_COUNTING_NODE(bnode->parent->parent); + + if (PURPLE_BUDDY_IS_ONLINE(buddy)) { + purple_counting_node_change_online_count(contact_counter, -1); + if (purple_counting_node_get_online_count(contact_counter) == 0) + purple_counting_node_change_online_count(group_counter, -1); + } + if (purple_account_is_connected(account)) { + purple_counting_node_change_current_size(contact_counter, -1); + if (purple_counting_node_get_current_size(contact_counter) == 0) + purple_counting_node_change_current_size(group_counter, -1); + } + purple_counting_node_change_total_size(contact_counter, -1); + /* the group totalsize will be taken care of by remove_contact below */ + + if (bnode->parent->parent != (PurpleBlistNode*)g) + serv_move_buddy(buddy, (PurpleGroup *)bnode->parent->parent, g); + + if (bnode->next) + bnode->next->prev = bnode->prev; + if (bnode->prev) + bnode->prev->next = bnode->next; + if (bnode->parent->child == bnode) + bnode->parent->child = bnode->next; + + if (ops && ops->remove) + ops->remove(purplebuddylist, bnode); + + if (bnode->parent->parent != (PurpleBlistNode*)g) { + struct _purple_hbuddy hb; + hb.name = (gchar *)purple_normalize(account, + purple_buddy_get_name(buddy)); + hb.account = account; + hb.group = bnode->parent->parent; + g_hash_table_remove(priv->buddies, &hb); + + account_buddies = g_hash_table_lookup(buddies_cache, account); + g_hash_table_remove(account_buddies, &hb); + } + + if (!bnode->parent->child) { + purple_blist_remove_contact((PurpleContact*)bnode->parent); + } else { + purple_contact_invalidate_priority_buddy((PurpleContact*)bnode->parent); + + if (ops && ops->update) + ops->update(purplebuddylist, bnode->parent); + } + } + + if (node && PURPLE_IS_BUDDY(node)) { + if (node->next) + node->next->prev = bnode; + bnode->next = node->next; + bnode->prev = node; + bnode->parent = node->parent; + node->next = bnode; + } else { + if (cnode->child) + cnode->child->prev = bnode; + bnode->prev = NULL; + bnode->next = cnode->child; + cnode->child = bnode; + bnode->parent = cnode; + } + + contact_counter = PURPLE_COUNTING_NODE(bnode->parent); + group_counter = PURPLE_COUNTING_NODE(bnode->parent->parent); + + if (PURPLE_BUDDY_IS_ONLINE(buddy)) { + purple_counting_node_change_online_count(contact_counter, +1); + if (purple_counting_node_get_online_count(contact_counter) == 1) + purple_counting_node_change_online_count(group_counter, +1); + } + if (purple_account_is_connected(account)) { + purple_counting_node_change_current_size(contact_counter, +1); + if (purple_counting_node_get_online_count(contact_counter) == 1) + purple_counting_node_change_current_size(group_counter, +1); + } + purple_counting_node_change_total_size(contact_counter, +1); + + hb = g_new(struct _purple_hbuddy, 1); + hb->name = g_strdup(purple_normalize(account, purple_buddy_get_name(buddy))); + hb->account = account; + hb->group = PURPLE_BLIST_NODE(buddy)->parent->parent; + + g_hash_table_replace(priv->buddies, hb, buddy); + + account_buddies = g_hash_table_lookup(buddies_cache, account); + + hb2 = g_new(struct _purple_hbuddy, 1); + hb2->name = g_strdup(hb->name); + hb2->account = account; + hb2->group = ((PurpleBlistNode*)buddy)->parent->parent; + + g_hash_table_replace(account_buddies, hb2, buddy); + + purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy)); + + if (ops) { + if (ops->save_node) + ops->save_node((PurpleBlistNode*) buddy); + if (ops->update) + ops->update(purplebuddylist, PURPLE_BLIST_NODE(buddy)); + } + + /* Signal that the buddy has been added */ + purple_signal_emit(purple_blist_get_handle(), "buddy-added", buddy); + + purple_signal_emit(purple_blist_get_handle(), "blist-node-added", + PURPLE_BLIST_NODE(buddy)); +} + +void purple_blist_add_contact(PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node) +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleGroup *g; + PurpleBlistNode *gnode, *cnode, *bnode; + PurpleCountingNode *contact_counter, *group_counter; + PurpleBuddyListPrivate *priv = PURPLE_BUDDY_LIST_GET_PRIVATE(purplebuddylist); + + g_return_if_fail(contact != NULL); + + if (PURPLE_BLIST_NODE(contact) == node) + return; + + if (node && (PURPLE_IS_CONTACT(node) || + PURPLE_IS_CHAT(node))) + g = PURPLE_GROUP(node->parent); + else if (group) + g = group; + else { + g = purple_blist_find_group(_("Buddies")); + if (g == NULL) { + g = purple_group_new(_("Buddies")); + purple_blist_add_group(g, + purple_blist_get_last_sibling(purplebuddylist->root)); + } + } + + gnode = (PurpleBlistNode*)g; + cnode = (PurpleBlistNode*)contact; + + if (cnode->parent) { + if (cnode->parent->child == cnode) + cnode->parent->child = cnode->next; + if (cnode->prev) + cnode->prev->next = cnode->next; + if (cnode->next) + cnode->next->prev = cnode->prev; + + if (cnode->parent != gnode) { + bnode = cnode->child; + while (bnode) { + PurpleBlistNode *next_bnode = bnode->next; + PurpleBuddy *b = PURPLE_BUDDY(bnode); + PurpleAccount *account = purple_buddy_get_account(b); + GHashTable *account_buddies; + + struct _purple_hbuddy *hb, *hb2; + + hb = g_new(struct _purple_hbuddy, 1); + hb->name = g_strdup(purple_normalize(account, purple_buddy_get_name(b))); + hb->account = account; + hb->group = cnode->parent; + + g_hash_table_remove(priv->buddies, hb); + + account_buddies = g_hash_table_lookup(buddies_cache, account); + g_hash_table_remove(account_buddies, hb); + + if (!purple_blist_find_buddy_in_group(account, purple_buddy_get_name(b), g)) { + hb->group = gnode; + g_hash_table_replace(priv->buddies, hb, b); + + hb2 = g_new(struct _purple_hbuddy, 1); + hb2->name = g_strdup(hb->name); + hb2->account = account; + hb2->group = gnode; + + g_hash_table_replace(account_buddies, hb2, b); + + if (purple_account_get_connection(account)) + serv_move_buddy(b, (PurpleGroup *)cnode->parent, g); + } else { + gboolean empty_contact = FALSE; + + /* this buddy already exists in the group, so we're + * gonna delete it instead */ + g_free(hb->name); + g_free(hb); + if (purple_account_get_connection(account)) + purple_account_remove_buddy(account, b, PURPLE_GROUP(cnode->parent)); + + if (!cnode->child->next) + empty_contact = TRUE; + purple_blist_remove_buddy(b); + + /** in purple_blist_remove_buddy(), if the last buddy in a + * contact is removed, the contact is cleaned up and + * g_free'd, so we mustn't try to reference bnode->next */ + if (empty_contact) + return; + } + bnode = next_bnode; + } + } + + contact_counter = PURPLE_COUNTING_NODE(contact); + group_counter = PURPLE_COUNTING_NODE(cnode->parent); + + if (purple_counting_node_get_online_count(contact_counter) > 0) + purple_counting_node_change_online_count(group_counter, -1); + if (purple_counting_node_get_current_size(contact_counter) > 0) + purple_counting_node_change_current_size(group_counter, -1); + purple_counting_node_change_total_size(group_counter, -1); + + if (ops && ops->remove) + ops->remove(purplebuddylist, cnode); + + if (ops && ops->remove_node) + ops->remove_node(cnode); + } + + if (node && (PURPLE_IS_CONTACT(node) || + PURPLE_IS_CHAT(node))) { + if (node->next) + node->next->prev = cnode; + cnode->next = node->next; + cnode->prev = node; + cnode->parent = node->parent; + node->next = cnode; + } else { + if (gnode->child) + gnode->child->prev = cnode; + cnode->prev = NULL; + cnode->next = gnode->child; + gnode->child = cnode; + cnode->parent = gnode; + } + + contact_counter = PURPLE_COUNTING_NODE(contact); + group_counter = PURPLE_COUNTING_NODE(g); + + if (purple_counting_node_get_online_count(contact_counter) > 0) + purple_counting_node_change_online_count(group_counter, +1); + if (purple_counting_node_get_current_size(contact_counter) > 0) + purple_counting_node_change_current_size(group_counter, +1); + purple_counting_node_change_total_size(group_counter, +1); + + if (ops && ops->save_node) + { + if (cnode->child) + ops->save_node(cnode); + for (bnode = cnode->child; bnode; bnode = bnode->next) + ops->save_node(bnode); + } + + if (ops && ops->update) + { + if (cnode->child) + ops->update(purplebuddylist, cnode); + + for (bnode = cnode->child; bnode; bnode = bnode->next) + ops->update(purplebuddylist, bnode); + } +} + +void purple_blist_add_group(PurpleGroup *group, PurpleBlistNode *node) +{ + PurpleBlistUiOps *ops; + PurpleBlistNode *gnode = (PurpleBlistNode*)group; + gchar* key; + + g_return_if_fail(group != NULL); + g_return_if_fail(PURPLE_IS_GROUP((PurpleBlistNode *)group)); + + ops = purple_blist_get_ui_ops(); + + /* if we're moving to overtop of ourselves, do nothing */ + if (gnode == node) { + if (!purplebuddylist->root) + node = NULL; + else + return; + } + + if (purple_blist_find_group(purple_group_get_name(group))) { + /* This is just being moved */ + + if (ops && ops->remove) + ops->remove(purplebuddylist, (PurpleBlistNode *)group); + + if (gnode == purplebuddylist->root) + purplebuddylist->root = gnode->next; + if (gnode->prev) + gnode->prev->next = gnode->next; + if (gnode->next) + gnode->next->prev = gnode->prev; + } else { + key = g_utf8_collate_key(purple_group_get_name(group), -1); + g_hash_table_insert(groups_cache, key, group); + } + + if (node && PURPLE_IS_GROUP(node)) { + gnode->next = node->next; + gnode->prev = node; + if (node->next) + node->next->prev = gnode; + node->next = gnode; + } else { + if (purplebuddylist->root) + purplebuddylist->root->prev = gnode; + gnode->next = purplebuddylist->root; + gnode->prev = NULL; + purplebuddylist->root = gnode; + } + + if (ops && ops->save_node) { + ops->save_node(gnode); + for (node = gnode->child; node; node = node->next) + ops->save_node(node); + } + + if (ops && ops->update) { + ops->update(purplebuddylist, gnode); + for (node = gnode->child; node; node = node->next) + ops->update(purplebuddylist, node); + } + + purple_signal_emit(purple_blist_get_handle(), "blist-node-added", + gnode); +} + +void purple_blist_remove_contact(PurpleContact *contact) +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleBlistNode *node, *gnode; + PurpleGroup *group; + + g_return_if_fail(contact != NULL); + + node = (PurpleBlistNode *)contact; + gnode = node->parent; + group = PURPLE_GROUP(gnode); + + if (node->child) { + /* + * If this contact has children then remove them. When the last + * buddy is removed from the contact, the contact is automatically + * deleted. + */ + while (node->child->next) { + purple_blist_remove_buddy((PurpleBuddy*)node->child); + } + /* + * Remove the last buddy and trigger the deletion of the contact. + * It would probably be cleaner if contact-deletion was done after + * a timeout? Or if it had to be done manually, like below? + */ + purple_blist_remove_buddy((PurpleBuddy*)node->child); + } else { + /* Remove the node from its parent */ + if (gnode->child == node) + gnode->child = node->next; + if (node->prev) + node->prev->next = node->next; + if (node->next) + node->next->prev = node->prev; + purple_counting_node_change_total_size(PURPLE_COUNTING_NODE(group), -1); + + /* Update the UI */ + if (ops && ops->remove) + ops->remove(purplebuddylist, node); + + if (ops && ops->remove_node) + ops->remove_node(node); + + purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", + PURPLE_BLIST_NODE(contact)); + + /* Delete the node */ + g_object_unref(contact); + } +} + +void purple_blist_remove_buddy(PurpleBuddy *buddy) +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleBlistNode *node, *cnode, *gnode; + PurpleCountingNode *contact_counter, *group_counter; + PurpleContact *contact; + PurpleGroup *group; + struct _purple_hbuddy hb; + GHashTable *account_buddies; + PurpleAccount *account; + + g_return_if_fail(buddy != NULL); + + account = purple_buddy_get_account(buddy); + node = PURPLE_BLIST_NODE(buddy); + cnode = node->parent; + gnode = (cnode != NULL) ? cnode->parent : NULL; + contact = (PurpleContact *)cnode; + group = (PurpleGroup *)gnode; + + /* Remove the node from its parent */ + if (node->prev) + node->prev->next = node->next; + if (node->next) + node->next->prev = node->prev; + if ((cnode != NULL) && (cnode->child == node)) + cnode->child = node->next; + + /* Adjust size counts */ + if (contact != NULL) { + contact_counter = PURPLE_COUNTING_NODE(contact); + group_counter = PURPLE_COUNTING_NODE(group); + + if (PURPLE_BUDDY_IS_ONLINE(buddy)) { + purple_counting_node_change_online_count(contact_counter, -1); + if (purple_counting_node_get_online_count(contact_counter) == 0) + purple_counting_node_set_online_count(group_counter, -1); + } + if (purple_account_is_connected(account)) { + purple_counting_node_change_current_size(contact_counter, -1); + if (purple_counting_node_get_current_size(contact_counter) == 0) + purple_counting_node_change_current_size(group_counter, -1); + } + purple_counting_node_change_total_size(contact_counter, -1); + + /* Re-sort the contact */ + if (cnode->child && purple_contact_get_priority_buddy(contact) == buddy) { + purple_contact_invalidate_priority_buddy(contact); + + if (ops && ops->update) + ops->update(purplebuddylist, cnode); + } + } + + /* Remove this buddy from the buddies hash table */ + hb.name = (gchar *)purple_normalize(account, purple_buddy_get_name(buddy)); + hb.account = account; + hb.group = gnode; + g_hash_table_remove(PURPLE_BUDDY_LIST_GET_PRIVATE(purplebuddylist)->buddies, &hb); + + account_buddies = g_hash_table_lookup(buddies_cache, account); + g_hash_table_remove(account_buddies, &hb); + + /* Update the UI */ + if (ops && ops->remove) + ops->remove(purplebuddylist, node); + + if (ops && ops->remove_node) + ops->remove_node(node); + + /* Remove this buddy's pounces */ + purple_pounce_destroy_all_by_buddy(buddy); + + /* Signal that the buddy has been removed before freeing the memory for it */ + purple_signal_emit(purple_blist_get_handle(), "buddy-removed", buddy); + + purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", + PURPLE_BLIST_NODE(buddy)); + + g_object_unref(buddy); + + /* If the contact is empty then remove it */ + if ((contact != NULL) && !cnode->child) + purple_blist_remove_contact(contact); +} + +void purple_blist_remove_chat(PurpleChat *chat) +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleBlistNode *node, *gnode; + PurpleGroup *group; + PurpleCountingNode *group_counter; + + g_return_if_fail(chat != NULL); + + node = (PurpleBlistNode *)chat; + gnode = node->parent; + group = (PurpleGroup *)gnode; + + if (gnode != NULL) + { + /* Remove the node from its parent */ + if (gnode->child == node) + gnode->child = node->next; + if (node->prev) + node->prev->next = node->next; + if (node->next) + node->next->prev = node->prev; + + /* Adjust size counts */ + group_counter = PURPLE_COUNTING_NODE(group); + if (purple_account_is_connected(purple_chat_get_account(chat))) { + purple_counting_node_change_online_count(group_counter, -1); + purple_counting_node_change_current_size(group_counter, -1); + } + purple_counting_node_change_total_size(group_counter, -1); + } + + /* Update the UI */ + if (ops && ops->remove) + ops->remove(purplebuddylist, node); + + if (ops && ops->remove_node) + ops->remove_node(node); + + purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", + PURPLE_BLIST_NODE(chat)); + + /* Delete the node */ + g_object_unref(chat); +} + +void purple_blist_remove_group(PurpleGroup *group) +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleBlistNode *node; + GList *l; + gchar* key; + + g_return_if_fail(group != NULL); + + node = (PurpleBlistNode *)group; + + /* Make sure the group is empty */ + if (node->child) + return; + + /* Remove the node from its parent */ + if (purplebuddylist->root == node) + purplebuddylist->root = node->next; + if (node->prev) + node->prev->next = node->next; + if (node->next) + node->next->prev = node->prev; + + key = g_utf8_collate_key(purple_group_get_name(group), -1); + g_hash_table_remove(groups_cache, key); + g_free(key); + + /* Update the UI */ + if (ops && ops->remove) + ops->remove(purplebuddylist, node); + + if (ops && ops->remove_node) + ops->remove_node(node); + + purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", + PURPLE_BLIST_NODE(group)); + + /* Remove the group from all accounts that are online */ + for (l = purple_connections_get_all(); l != NULL; l = l->next) + { + PurpleConnection *gc = (PurpleConnection *)l->data; + + if (purple_connection_get_state(gc) == PURPLE_CONNECTION_CONNECTED) + purple_account_remove_group(purple_connection_get_account(gc), group); + } + + /* Delete the node */ + g_object_unref(group); +} + +PurpleBuddy *purple_blist_find_buddy(PurpleAccount *account, const char *name) +{ + PurpleBuddy *buddy; + struct _purple_hbuddy hb; + PurpleBlistNode *group; + + g_return_val_if_fail(purplebuddylist != NULL, NULL); + g_return_val_if_fail(account != NULL, NULL); + g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL); + + hb.account = account; + hb.name = (gchar *)purple_normalize(account, name); + + for (group = purplebuddylist->root; group; group = group->next) { + if (!group->child) + continue; + + hb.group = group; + if ((buddy = g_hash_table_lookup(PURPLE_BUDDY_LIST_GET_PRIVATE(purplebuddylist)->buddies, + &hb))) { + return buddy; + } + } + + return NULL; +} + +PurpleBuddy *purple_blist_find_buddy_in_group(PurpleAccount *account, const char *name, + PurpleGroup *group) +{ + struct _purple_hbuddy hb; + + g_return_val_if_fail(purplebuddylist != NULL, NULL); + g_return_val_if_fail(account != NULL, NULL); + g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL); + + hb.name = (gchar *)purple_normalize(account, name); + hb.account = account; + hb.group = (PurpleBlistNode*)group; + + return g_hash_table_lookup(PURPLE_BUDDY_LIST_GET_PRIVATE(purplebuddylist)->buddies, + &hb); +} + +static void find_acct_buddies(gpointer key, gpointer value, gpointer data) +{ + PurpleBuddy *buddy = value; + GSList **list = data; + + *list = g_slist_prepend(*list, buddy); +} + +GSList *purple_blist_find_buddies(PurpleAccount *account, const char *name) +{ + PurpleBuddy *buddy; + PurpleBlistNode *node; + GSList *ret = NULL; + + g_return_val_if_fail(purplebuddylist != NULL, NULL); + g_return_val_if_fail(account != NULL, NULL); + + if ((name != NULL) && (*name != '\0')) { + struct _purple_hbuddy hb; + + hb.name = (gchar *)purple_normalize(account, name); + hb.account = account; + + for (node = purplebuddylist->root; node != NULL; node = node->next) { + if (!node->child) + continue; + + hb.group = node; + if ((buddy = g_hash_table_lookup(PURPLE_BUDDY_LIST_GET_PRIVATE(purplebuddylist)->buddies, + &hb)) != NULL) + ret = g_slist_prepend(ret, buddy); + } + } else { + GSList *list = NULL; + GHashTable *buddies = g_hash_table_lookup(buddies_cache, account); + g_hash_table_foreach(buddies, find_acct_buddies, &list); + ret = list; + } + + return ret; +} + +PurpleGroup *purple_blist_find_group(const char *name) +{ + gchar* key; + PurpleGroup *group; + + g_return_val_if_fail(purplebuddylist != NULL, NULL); + g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL); + + key = g_utf8_collate_key(name, -1); + group = g_hash_table_lookup(groups_cache, key); + g_free(key); + + return group; +} + +PurpleChat * +purple_blist_find_chat(PurpleAccount *account, const char *name) +{ + char *chat_name; + PurpleChat *chat; + PurplePlugin *prpl; + PurplePluginProtocolInfo *prpl_info = NULL; + struct proto_chat_entry *pce; + PurpleBlistNode *node, *group; + GList *parts; + char *normname; + + g_return_val_if_fail(purplebuddylist != NULL, NULL); + g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL); + + if (!purple_account_is_connected(account)) + return NULL; + + prpl = purple_find_prpl(purple_account_get_protocol_id(account)); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + + if (prpl_info->find_blist_chat != NULL) + return prpl_info->find_blist_chat(account, name); + + normname = g_strdup(purple_normalize(account, name)); + for (group = purplebuddylist->root; group != NULL; group = group->next) { + for (node = group->child; node != NULL; node = node->next) { + if (PURPLE_IS_CHAT(node)) { + + chat = (PurpleChat*)node; + + if (account != purple_chat_get_account(chat)) + continue; + + parts = prpl_info->chat_info( + purple_account_get_connection(purple_chat_get_account(chat))); + + pce = parts->data; + chat_name = g_hash_table_lookup(purple_chat_get_components(chat), + pce->identifier); + g_list_foreach(parts, (GFunc)g_free, NULL); + g_list_free(parts); + + if (purple_chat_get_account(chat) == account && chat_name != NULL && + normname != NULL && !strcmp(purple_normalize(account, chat_name), normname)) { + g_free(normname); + return chat; + } + } + } + } + + g_free(normname); + return NULL; +} + +void purple_blist_add_account(PurpleAccount *account) +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleBlistNode *gnode, *cnode, *bnode; + PurpleCountingNode *contact_counter, *group_counter; + + g_return_if_fail(purplebuddylist != NULL); + + if (!ops || !ops->update) + return; + + for (gnode = purplebuddylist->root; gnode; gnode = gnode->next) { + if (!PURPLE_IS_GROUP(gnode)) + continue; + for (cnode = gnode->child; cnode; cnode = cnode->next) { + if (PURPLE_IS_CONTACT(cnode)) { + gboolean recompute = FALSE; + for (bnode = cnode->child; bnode; bnode = bnode->next) { + if (PURPLE_IS_BUDDY(bnode) && + purple_buddy_get_account(PURPLE_BUDDY(bnode)) == account) { + recompute = TRUE; + contact_counter = PURPLE_COUNTING_NODE(cnode); + group_counter = PURPLE_COUNTING_NODE(gnode); + purple_counting_node_change_current_size(contact_counter, +1); + if (purple_counting_node_get_current_size(contact_counter) == 1) + purple_counting_node_change_current_size(group_counter, +1); + ops->update(purplebuddylist, bnode); + } + } + if (recompute || + purple_blist_node_get_bool(cnode, "show_offline")) { + purple_contact_invalidate_priority_buddy((PurpleContact*)cnode); + ops->update(purplebuddylist, cnode); + } + } else if (PURPLE_IS_CHAT(cnode) && + purple_chat_get_account(PURPLE_CHAT(cnode)) == account) { + group_counter = PURPLE_COUNTING_NODE(gnode); + purple_counting_node_change_online_count(group_counter, +1); + purple_counting_node_change_current_size(group_counter, +1); + ops->update(purplebuddylist, cnode); + } + } + ops->update(purplebuddylist, gnode); + } +} + +void purple_blist_remove_account(PurpleAccount *account) +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleBlistNode *gnode, *cnode, *bnode; + PurpleCountingNode *contact_counter, *group_counter; + PurpleBuddy *buddy; + PurpleChat *chat; + PurpleContact *contact; + PurpleGroup *group; + GList *list = NULL, *iter = NULL; + + g_return_if_fail(purplebuddylist != NULL); + + for (gnode = purplebuddylist->root; gnode; gnode = gnode->next) { + if (!PURPLE_IS_GROUP(gnode)) + continue; + + group = (PurpleGroup *)gnode; + + for (cnode = gnode->child; cnode; cnode = cnode->next) { + if (PURPLE_IS_CONTACT(cnode)) { + gboolean recompute = FALSE; + contact = (PurpleContact *)cnode; + + for (bnode = cnode->child; bnode; bnode = bnode->next) { + if (!PURPLE_IS_BUDDY(bnode)) + continue; + + buddy = (PurpleBuddy *)bnode; + if (account == purple_buddy_get_account(buddy)) { + PurplePresence *presence; + + presence = purple_buddy_get_presence(buddy); + contact_counter = PURPLE_COUNTING_NODE(contact); + group_counter = PURPLE_COUNTING_NODE(group); + + if(purple_presence_is_online(presence)) { + purple_counting_node_change_online_count(contact_counter, -1); + if (purple_counting_node_get_online_count(contact_counter) == 0) + purple_counting_node_change_online_count(group_counter, -1); + + purple_blist_node_set_int(PURPLE_BLIST_NODE(buddy), + "last_seen", time(NULL)); + } + + purple_counting_node_change_current_size(contact_counter, -1); + if (purple_counting_node_get_current_size(contact_counter) == 0) + purple_counting_node_change_current_size(group_counter, -1); + + if (!g_list_find(list, presence)) + list = g_list_prepend(list, presence); + + if (purple_contact_get_priority_buddy(contact) == buddy) + purple_contact_invalidate_priority_buddy(contact); + else + recompute = TRUE; + + if (ops && ops->remove) { + ops->remove(purplebuddylist, bnode); + } + } + } + if (recompute) { + purple_contact_invalidate_priority_buddy(contact); + + if (ops && ops->update) + ops->update(purplebuddylist, cnode); + } + } else if (PURPLE_IS_CHAT(cnode)) { + chat = PURPLE_CHAT(cnode); + + if(purple_chat_get_account(chat) == account) { + group_counter = PURPLE_COUNTING_NODE(group); + purple_counting_node_change_current_size(group_counter, -1); + purple_counting_node_change_online_count(group_counter, -1); + + if (ops && ops->remove) + ops->remove(purplebuddylist, cnode); + } + } + } + } + + for (iter = list; iter; iter = iter->next) + { + purple_presence_set_status_active(iter->data, "offline", TRUE); + } + g_list_free(list); +} + +void +purple_blist_request_add_buddy(PurpleAccount *account, const char *username, + const char *group, const char *alias) +{ + PurpleBlistUiOps *ui_ops; + + ui_ops = purple_blist_get_ui_ops(); + + if (ui_ops != NULL && ui_ops->request_add_buddy != NULL) + ui_ops->request_add_buddy(account, username, group, alias); +} + +void +purple_blist_request_add_chat(PurpleAccount *account, PurpleGroup *group, + const char *alias, const char *name) +{ + PurpleBlistUiOps *ui_ops; + + ui_ops = purple_blist_get_ui_ops(); + + if (ui_ops != NULL && ui_ops->request_add_chat != NULL) + ui_ops->request_add_chat(account, group, alias, name); +} + +void +purple_blist_request_add_group(void) +{ + PurpleBlistUiOps *ui_ops; + + ui_ops = purple_blist_get_ui_ops(); + + if (ui_ops != NULL && ui_ops->request_add_group != NULL) + ui_ops->request_add_group(); +} + +void +purple_blist_set_ui_ops(PurpleBlistUiOps *ops) +{ + gboolean overrode = FALSE; + blist_ui_ops = ops; + + if (!ops) + return; + + if (!ops->save_node) { + ops->save_node = purple_blist_save_node; + overrode = TRUE; + } + if (!ops->remove_node) { + ops->remove_node = purple_blist_save_node; + overrode = TRUE; + } + if (!ops->save_account) { + ops->save_account = purple_blist_save_account; + overrode = TRUE; + } + + if (overrode && (ops->save_node != purple_blist_save_node || + ops->remove_node != purple_blist_save_node || + ops->save_account != purple_blist_save_account)) { + purple_debug_warning("blist", "Only some of the blist saving UI ops " + "were overridden. This probably is not what you want!\n"); + } +} + +PurpleBlistUiOps * +purple_blist_get_ui_ops(void) +{ + return blist_ui_ops; +} + + +void * +purple_blist_get_handle(void) +{ + static int handle; + + return &handle; +} + +void +purple_blist_init(void) +{ + void *handle = purple_blist_get_handle(); + + purple_signal_register(handle, "buddy-status-changed", + purple_marshal_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, PURPLE_TYPE_BUDDY, PURPLE_TYPE_STATUS, + PURPLE_TYPE_STATUS); + purple_signal_register(handle, "buddy-privacy-changed", + purple_marshal_VOID__POINTER, G_TYPE_NONE, + 1, PURPLE_TYPE_BUDDY); + + purple_signal_register(handle, "buddy-idle-changed", + purple_marshal_VOID__POINTER_INT_INT, G_TYPE_NONE, + 3, PURPLE_TYPE_BUDDY, G_TYPE_INT, G_TYPE_INT); + + purple_signal_register(handle, "buddy-signed-on", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_BUDDY); + + purple_signal_register(handle, "buddy-signed-off", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_BUDDY); + + purple_signal_register(handle, "buddy-got-login-time", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_BUDDY); + + purple_signal_register(handle, "blist-node-added", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_BLIST_NODE); + + purple_signal_register(handle, "blist-node-removed", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_BLIST_NODE); + + purple_signal_register(handle, "buddy-added", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_BUDDY); + + purple_signal_register(handle, "buddy-removed", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_BUDDY); + + purple_signal_register(handle, "buddy-icon-changed", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_BUDDY); + + purple_signal_register(handle, "update-idle", purple_marshal_VOID, + G_TYPE_NONE, 0); + + purple_signal_register(handle, "blist-node-extended-menu", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_BLIST_NODE, + G_TYPE_POINTER); /* (GList **) */ + + purple_signal_register(handle, "blist-node-aliased", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_BLIST_NODE, G_TYPE_STRING); + + purple_signal_register(handle, "buddy-caps-changed", + purple_marshal_VOID__POINTER_INT_INT, G_TYPE_NONE, + 3, PURPLE_TYPE_BUDDY, G_TYPE_INT, G_TYPE_INT); + + purple_signal_connect(purple_accounts_get_handle(), "account-created", + handle, + PURPLE_CALLBACK(purple_blist_buddies_cache_add_account), + NULL); + + purple_signal_connect(purple_accounts_get_handle(), "account-destroying", + handle, + PURPLE_CALLBACK(purple_blist_buddies_cache_remove_account), + NULL); +} + +static void +blist_node_destroy(PurpleBlistNode *node) +{ + PurpleBlistUiOps *ui_ops; + PurpleBlistNode *child, *next_child; + + ui_ops = purple_blist_get_ui_ops(); + child = node->child; + while (child) { + next_child = child->next; + blist_node_destroy(child); + child = next_child; + } + + /* Allow the UI to free data */ + node->parent = NULL; + node->child = NULL; + node->next = NULL; + node->prev = NULL; + if (ui_ops && ui_ops->remove) + ui_ops->remove(purplebuddylist, node); + + g_object_unref(node); +} + +void +purple_blist_uninit(void) +{ + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleBlistNode *node, *next_node; + + /* This happens if we quit before purple_set_blist is called. */ + if (purplebuddylist == NULL) + return; + + if (save_timer != 0) { + purple_timeout_remove(save_timer); + save_timer = 0; + purple_blist_sync(); + } + + purple_debug(PURPLE_DEBUG_INFO, "blist", "Destroying\n"); + + if (ops && ops->destroy) + ops->destroy(purplebuddylist); + + node = purple_blist_get_root(); + while (node) { + next_node = node->next; + blist_node_destroy(node); + node = next_node; + } + purplebuddylist->root = NULL; + + g_hash_table_destroy(buddies_cache); + g_hash_table_destroy(groups_cache); + + buddies_cache = NULL; + groups_cache = NULL; + + g_object_unref(purplebuddylist); + purplebuddylist = NULL; + + purple_signals_disconnect_by_handle(purple_blist_get_handle()); + purple_signals_unregister_by_instance(purple_blist_get_handle()); +} + +/************************************************************************** + * GObject code + **************************************************************************/ + +/* GObject initialization function */ +static void +purple_buddy_list_init(GTypeInstance *instance, gpointer klass) +{ + PurpleBuddyList *blist = PURPLE_BUDDY_LIST(instance); + + PURPLE_DBUS_REGISTER_POINTER(blist, PurpleBuddyList); + + PURPLE_BUDDY_LIST_GET_PRIVATE(blist)->buddies = g_hash_table_new_full( + (GHashFunc)_purple_blist_hbuddy_hash, + (GEqualFunc)_purple_blist_hbuddy_equal, + (GDestroyNotify)_purple_blist_hbuddy_free_key, NULL); +} + +/* GObject dispose function */ +static void +purple_buddy_list_dispose(GObject *object) +{ + PURPLE_DBUS_UNREGISTER_POINTER(object); + + G_OBJECT_CLASS(parent_class)->dispose(object); +} + +/* GObject finalize function */ +static void +purple_buddy_list_finalize(GObject *object) +{ + g_hash_table_destroy(PURPLE_BUDDY_LIST_GET_PRIVATE(object)->buddies); + + G_OBJECT_CLASS(parent_class)->finalize(object); +} + +/* Class initializer function */ +static void purple_buddy_list_class_init(PurpleBuddyListClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->dispose = purple_buddy_list_dispose; + obj_class->finalize = purple_buddy_list_finalize; + + g_type_class_add_private(klass, sizeof(PurpleBuddyListPrivate)); +} + +GType +purple_buddy_list_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleBuddyListClass), + NULL, + NULL, + (GClassInitFunc)purple_buddy_list_class_init, + NULL, + NULL, + sizeof(PurpleBuddyList), + 0, + (GInstanceInitFunc)purple_buddy_list_init, + NULL, + }; + + type = g_type_register_static(G_TYPE_OBJECT, + "PurpleBuddyList", &info, 0); + } + + return type; +} diff --git a/libpurple/buddylist.h b/libpurple/buddylist.h new file mode 100644 index 0000000000..e731e5eab0 --- /dev/null +++ b/libpurple/buddylist.h @@ -0,0 +1,481 @@ +/** + * @file buddylist.h Buddy List API + * @ingroup core + * @see @ref blist-signals + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef _PURPLE_BUDDY_LIST_H_ +#define _PURPLE_BUDDY_LIST_H_ + +/* I can't believe I let ChipX86 inspire me to write good code. -Sean */ + +#include "blistnodetypes.h" + +#define PURPLE_TYPE_BUDDY_LIST (purple_buddy_list_get_type()) +#define PURPLE_BUDDY_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_BUDDY_LIST, PurpleBuddyList)) +#define PURPLE_BUDDY_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_BUDDY_LIST, PurpleBuddyListClass)) +#define PURPLE_IS_BUDDY_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_BUDDY_LIST)) +#define PURPLE_IS_BUDDY_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_BUDDY_LIST)) +#define PURPLE_BUDDY_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_BUDDY_LIST, PurpleBuddyListClass)) + +/** @copydoc _PurpleBuddyList */ +typedef struct _PurpleBuddyList PurpleBuddyList; +/** @copydoc _PurpleBuddyList */ +typedef struct _PurpleBuddyListClass PurpleBuddyListClass; + +/** @copydoc _PurpleBlistUiOps */ +typedef struct _PurpleBlistUiOps PurpleBlistUiOps; + +/**************************************************************************/ +/* Data Structures */ +/**************************************************************************/ +/** + * The Buddy List + */ +struct _PurpleBuddyList { + /*< private >*/ + GObject gparent; + + /** The UI data associated with this buddy list. This is a convenience + * field provided to the UIs -- it is not used by the libpurple core. + */ + gpointer ui_data; + + /** The first node in the buddy list */ + PurpleBlistNode *root; +}; + +/** The base class for all #PurpleBuddyList's. */ +struct _PurpleBuddyListClass { + /*< private >*/ + GObjectClass gparent_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/** + * Buddy list UI operations. + * + * Any UI representing a buddy list must assign a filled-out PurpleBlistUiOps + * structure to the buddy list core. + */ +struct _PurpleBlistUiOps +{ + void (*new_list)(PurpleBuddyList *list); /**< Sets UI-specific data on a buddy list. */ + void (*new_node)(PurpleBlistNode *node); /**< Sets UI-specific data on a node. */ + void (*show)(PurpleBuddyList *list); /**< The core will call this when it's finished doing its core stuff */ + void (*update)(PurpleBuddyList *list, + PurpleBlistNode *node); /**< This will update a node in the buddy list. */ + void (*remove)(PurpleBuddyList *list, + PurpleBlistNode *node); /**< This removes a node from the list */ + void (*destroy)(PurpleBuddyList *list); /**< When the list is destroyed, this is called to destroy the UI. */ + void (*set_visible)(PurpleBuddyList *list, + gboolean show); /**< Hides or unhides the buddy list */ + void (*request_add_buddy)(PurpleAccount *account, const char *username, + const char *group, const char *alias); + void (*request_add_chat)(PurpleAccount *account, PurpleGroup *group, + const char *alias, const char *name); + void (*request_add_group)(void); + + /** + * This is called when a node has been modified and should be saved. + * + * Implementation of this UI op is OPTIONAL. If not implemented, it will + * be set to a fallback function that saves data to blist.xml like in + * previous libpurple versions. + * + * @param node The node which has been modified. + */ + void (*save_node)(PurpleBlistNode *node); + + /** + * Called when a node is about to be removed from the buddy list. + * The UI op should update the relevant data structures to remove this + * node (for example, removing a buddy from the group this node is in). + * + * Implementation of this UI op is OPTIONAL. If not implemented, it will + * be set to a fallback function that saves data to blist.xml like in + * previous libpurple versions. + * + * @param node The node which has been modified. + */ + void (*remove_node)(PurpleBlistNode *node); + + /** + * Called to save all the data for an account. If the UI sets this, + * the callback must save the privacy and buddy list data for an account. + * If the account is NULL, save the data for all accounts. + * + * Implementation of this UI op is OPTIONAL. If not implemented, it will + * be set to a fallback function that saves data to blist.xml like in + * previous libpurple versions. + * + * @param account The account whose data to save. If NULL, save all data + * for all accounts. + */ + void (*save_account)(PurpleAccount *account); + + void (*_purple_reserved1)(void); +}; + +G_BEGIN_DECLS + +/**************************************************************************/ +/** @name Buddy List API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the PurpleBuddyList object. + */ +GType purple_buddy_list_get_type(void); + +/** + * Returns the main buddy list. + * + * @return The main buddy list. + */ +PurpleBuddyList *purple_blist_get_buddy_list(void); + +/** + * Returns the root node of the main buddy list. + * + * @return The root node. + */ +PurpleBlistNode *purple_blist_get_root(void); + +/** + * Returns a list of every buddy in the list. Use of this function is + * discouraged if you do not actually need every buddy in the list. Use + * purple_blist_find_buddies instead. + * + * @return A list of every buddy in the list. Caller is responsible for + * freeing the list. + * + * @see purple_blist_find_buddies + */ +GSList *purple_blist_get_buddies(void); + +/** + * Returns the UI data for the list. + * + * @return The UI data for the list. + */ +gpointer purple_blist_get_ui_data(void); + +/** + * Sets the UI data for the list. + * + * @param ui_data The UI data for the list. + */ +void purple_blist_set_ui_data(gpointer ui_data); + +/** + * Shows the buddy list, creating a new one if necessary. + */ +void purple_blist_show(void); + +/** + * Hides or unhides the buddy list. + * + * @param show Whether or not to show the buddy list + */ +void purple_blist_set_visible(gboolean show); + +/** + * Updates the buddies hash table when a buddy has been renamed. This only + * updates the cache, the caller is responsible for the actual renaming of + * the buddy after updating the cache. + * + * @param buddy The buddy whose name will be changed. + * @param name The new name of the buddy. + */ +void purple_blist_update_buddies_cache(PurpleBuddy *buddy, const char *new_name); + +/** + * Updates the groups hash table when a group has been renamed. This only + * updates the cache, the caller is responsible for the actual renaming of + * the group after updating the cache. + * + * @param group The group whose name will be changed. + * @param name The new name of the group. + */ +void purple_blist_update_groups_cache(PurpleGroup *group, const char *new_name); + +/** + * Adds a new chat to the buddy list. + * + * The chat will be inserted right after node or appended to the end + * of group if node is NULL. If both are NULL, the buddy will be added to + * the "Chats" group. + * + * @param chat The new chat who gets added + * @param group The group to add the new chat to. + * @param node The insertion point + */ +void purple_blist_add_chat(PurpleChat *chat, PurpleGroup *group, PurpleBlistNode *node); + +/** + * Adds a new buddy to the buddy list. + * + * The buddy will be inserted right after node or prepended to the + * group if node is NULL. If both are NULL, the buddy will be added to + * the "Buddies" group. + * + * @param buddy The new buddy who gets added + * @param contact The optional contact to place the buddy in. + * @param group The group to add the new buddy to. + * @param node The insertion point. Pass in NULL to add the node as + * the first child in the given group. + */ +void purple_blist_add_buddy(PurpleBuddy *buddy, PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node); + +/** + * Adds a new group to the buddy list. + * + * The new group will be inserted after insert or prepended to the list if + * node is NULL. + * + * @param group The group + * @param node The insertion point + */ +void purple_blist_add_group(PurpleGroup *group, PurpleBlistNode *node); + +/** + * Adds a new contact to the buddy list. + * + * The new contact will be inserted after insert or prepended to the list if + * node is NULL. + * + * @param contact The contact + * @param group The group to add the contact to + * @param node The insertion point + */ +void purple_blist_add_contact(PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node); + +/** + * Removes a buddy from the buddy list and frees the memory allocated to it. + * This doesn't actually try to remove the buddy from the server list. + * + * @param buddy The buddy to be removed + * + * @see purple_account_remove_buddy + */ +void purple_blist_remove_buddy(PurpleBuddy *buddy); + +/** + * Removes a contact, and any buddies it contains, and frees the memory + * allocated to it. This calls purple_blist_remove_buddy and therefore + * doesn't remove the buddies from the server list. + * + * @param contact The contact to be removed + * + * @see purple_blist_remove_buddy + */ +void purple_blist_remove_contact(PurpleContact *contact); + +/** + * Removes a chat from the buddy list and frees the memory allocated to it. + * + * @param chat The chat to be removed + */ +void purple_blist_remove_chat(PurpleChat *chat); + +/** + * Removes a group from the buddy list and frees the memory allocated to it and to + * its children + * + * @param group The group to be removed + */ +void purple_blist_remove_group(PurpleGroup *group); + +/** + * Finds the buddy struct given a name and an account + * + * @param account The account this buddy belongs to + * @param name The buddy's name + * @return The buddy or NULL if the buddy does not exist + */ +PurpleBuddy *purple_blist_find_buddy(PurpleAccount *account, const char *name); + +/** + * Finds the buddy struct given a name, an account, and a group + * + * @param account The account this buddy belongs to + * @param name The buddy's name + * @param group The group to look in + * @return The buddy or NULL if the buddy does not exist in the group + */ +PurpleBuddy *purple_blist_find_buddy_in_group(PurpleAccount *account, const char *name, + PurpleGroup *group); + +/** + * Finds all PurpleBuddy structs given a name and an account + * + * @param account The account this buddy belongs to + * @param name The buddy's name (or NULL to return all buddies for the account) + * + * @return NULL if the buddy doesn't exist, or a GSList of + * PurpleBuddy structs. You must free the GSList using + * g_slist_free. Do not free the PurpleBuddy structs that + * the list points to. + */ +GSList *purple_blist_find_buddies(PurpleAccount *account, const char *name); + +/** + * Finds a group by name + * + * @param name The group's name + * @return The group or NULL if the group does not exist + */ +PurpleGroup *purple_blist_find_group(const char *name); + +/** + * Finds a chat by name. + * + * @param account The chat's account. + * @param name The chat's name. + * + * @return The chat, or @c NULL if the chat does not exist. + */ +PurpleChat *purple_blist_find_chat(PurpleAccount *account, const char *name); + +/** + * Called when an account connects. Tells the UI to update all the + * buddies. + * + * @param account The account + */ +void purple_blist_add_account(PurpleAccount *account); + +/** + * Called when an account disconnects. Sets the presence of all the buddies to 0 + * and tells the UI to update them. + * + * @param account The account + */ +void purple_blist_remove_account(PurpleAccount *account); + +/*@}*/ + +/****************************************************************************************/ +/** @name Buddy list file management API */ +/****************************************************************************************/ + +/** + * Schedule a save of the blist.xml file. This is used by the privacy + * API whenever the privacy settings are changed. If you make a change + * to blist.xml using one of the functions in the buddy list API, then + * the buddy list is saved automatically, so you should not need to + * call this. + */ +void purple_blist_schedule_save(void); + +/** + * Requests from the user information needed to add a buddy to the + * buddy list. + * + * @param account The account the buddy is added to. + * @param username The username of the buddy. + * @param group The name of the group to place the buddy in. + * @param alias The optional alias for the buddy. + */ +void purple_blist_request_add_buddy(PurpleAccount *account, const char *username, + const char *group, const char *alias); + +/** + * Requests from the user information needed to add a chat to the + * buddy list. + * + * @param account The account the buddy is added to. + * @param group The optional group to add the chat to. + * @param alias The optional alias for the chat. + * @param name The required chat name. + */ +void purple_blist_request_add_chat(PurpleAccount *account, PurpleGroup *group, + const char *alias, const char *name); + +/** + * Requests from the user information needed to add a group to the + * buddy list. + */ +void purple_blist_request_add_group(void); + +/**************************************************************************/ +/** @name UI Registration Functions */ +/**************************************************************************/ +/*@{*/ + +/** + * Sets the UI operations structure to be used for the buddy list. + * + * @param ops The ops struct. + */ +void purple_blist_set_ui_ops(PurpleBlistUiOps *ops); + +/** + * Returns the UI operations structure to be used for the buddy list. + * + * @return The UI operations structure. + */ +PurpleBlistUiOps *purple_blist_get_ui_ops(void); + +/*@}*/ + +/**************************************************************************/ +/** @name Buddy List Subsystem */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the handle for the buddy list subsystem. + * + * @return The buddy list subsystem handle. + */ +void *purple_blist_get_handle(void); + +/** + * Initializes the buddy list subsystem. + */ +void purple_blist_init(void); + +/** + * Loads the buddy list. + * + * You shouldn't call this. purple_core_init() will do it for you. + */ +void purple_blist_boot(void); + +/** + * Uninitializes the buddy list subsystem. + */ +void purple_blist_uninit(void); + +/*@}*/ + +G_END_DECLS + +#endif /* _PURPLE_BUDDY_LIST_H_ */ diff --git a/libpurple/certificate.c b/libpurple/certificate.c index a62aa711ae..fd4d0a98d4 100644 --- a/libpurple/certificate.c +++ b/libpurple/certificate.c @@ -511,6 +511,20 @@ purple_certificate_get_display_string(PurpleCertificate *crt) return str; } +GType +purple_certificate_get_type(void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static("PurpleCertificate", + (GBoxedCopyFunc)purple_certificate_copy, + (GBoxedFreeFunc)purple_certificate_destroy); + } + + return type; +} + gchar * purple_certificate_pool_mkpath(PurpleCertificatePool *pool, const gchar *id) { @@ -650,6 +664,33 @@ purple_certificate_pool_destroy_idlist(GList *idlist) g_list_free(idlist); } +static PurpleCertificatePool * +purple_certificate_pool_copy(PurpleCertificatePool *certificate_pool) +{ + PurpleCertificatePool *certificate_pool_copy; + + g_return_val_if_fail(certificate_pool != NULL, NULL); + + certificate_pool_copy = g_new(PurpleCertificatePool, 1); + *certificate_pool_copy = *certificate_pool; + + return certificate_pool_copy; +} + +GType +purple_certificate_pool_get_type(void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static("PurpleCertificatePool", + (GBoxedCopyFunc)purple_certificate_pool_copy, + (GBoxedFreeFunc)g_free); + } + + return type; +} + /****************************************************************************/ /* Builtin Verifiers, Pools, etc. */ @@ -2034,20 +2075,16 @@ purple_certificate_register_pool(PurpleCertificatePool *pool) purple_signal_register(pool, /* Signals emitted from pool */ "certificate-stored", purple_marshal_VOID__POINTER_POINTER, - NULL, /* No callback return value */ + G_TYPE_NONE, /* No callback return value */ 2, /* Two non-data arguments */ - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CERTIFICATEPOOL), - purple_value_new(PURPLE_TYPE_STRING)); + PURPLE_TYPE_CERTIFICATE_POOL, G_TYPE_STRING); purple_signal_register(pool, /* Signals emitted from pool */ "certificate-deleted", purple_marshal_VOID__POINTER_POINTER, - NULL, /* No callback return value */ + G_TYPE_NONE, /* No callback return value */ 2, /* Two non-data arguments */ - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CERTIFICATEPOOL), - purple_value_new(PURPLE_TYPE_STRING)); + PURPLE_TYPE_CERTIFICATE_POOL, G_TYPE_STRING); purple_debug_info("certificate", "CertificatePool %s registered\n", diff --git a/libpurple/certificate.h b/libpurple/certificate.h index d34aa5e21d..8235f2e854 100644 --- a/libpurple/certificate.h +++ b/libpurple/certificate.h @@ -81,8 +81,12 @@ typedef enum PURPLE_CERTIFICATE_LAST = 0x80000, } PurpleCertificateVerificationStatus; +#define PURPLE_TYPE_CERTIFICATE (purple_certificate_get_type()) typedef struct _PurpleCertificate PurpleCertificate; + +#define PURPLE_TYPE_CERTIFICATE_POOL (purple_certificate_pool_get_type()) typedef struct _PurpleCertificatePool PurpleCertificatePool; + typedef struct _PurpleCertificateScheme PurpleCertificateScheme; typedef struct _PurpleCertificateVerifier PurpleCertificateVerifier; typedef struct _PurpleCertificateVerificationRequest PurpleCertificateVerificationRequest; @@ -456,6 +460,11 @@ purple_certificate_verify_complete(PurpleCertificateVerificationRequest *vrq, /*@{*/ /** + * Returns the GType for the PurpleCertificate boxed structure. + */ +GType purple_certificate_get_type(void); + +/** * Makes a duplicate of a certificate * * @param crt Instance to duplicate @@ -643,6 +652,15 @@ purple_certificate_get_display_string(PurpleCertificate *crt); /** @name Certificate Pool Functions */ /*****************************************************************************/ /*@{*/ + +/** + * Returns the GType for the PurpleCertificatePool boxed structure. + * TODO Boxing of PurpleCertificatePool is a temporary solution to having a + * GType for certificate pools. This should rather be a GObject instead of + * a GBoxed. + */ +GType purple_certificate_pool_get_type(void); + /** * Helper function for generating file paths in ~/.purple/certificates for * CertificatePools that use them. diff --git a/libpurple/cipher.c b/libpurple/cipher.c index 1df779caab..14ca9aee53 100644 --- a/libpurple/cipher.c +++ b/libpurple/cipher.c @@ -1,24 +1,9 @@ -/* - * purple +/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. * - * Original des taken from gpg - * - * des.c - DES and Triple-DES encryption/decryption Algorithm - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * Please see below for more legal information! - * - * According to the definition of DES in FIPS PUB 46-2 from December 1993. - * For a description of triple encryption, see: - * Bruce Schneier: Applied Cryptography. Second Edition. - * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. - * - * This file is part of GnuPG. - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -35,435 +20,208 @@ */ #include "internal.h" #include "cipher.h" -#include "ciphers/ciphers.h" -#include "dbus-maybe.h" #include "debug.h" -#include "signals.h" -#include "value.h" - -/******************************************************************************* - * Structs - ******************************************************************************/ -struct _PurpleCipher { - gchar *name; /**< Internal name - used for searching */ - PurpleCipherOps *ops; /**< Operations supported by this cipher */ - guint ref; /**< Reference count */ -}; - -struct _PurpleCipherContext { - PurpleCipher *cipher; /**< Cipher this context is under */ - gpointer data; /**< Internal cipher state data */ -}; - -/****************************************************************************** - * Globals - *****************************************************************************/ -static GList *ciphers = NULL; /****************************************************************************** * PurpleCipher API *****************************************************************************/ const gchar * purple_cipher_get_name(PurpleCipher *cipher) { - g_return_val_if_fail(cipher, NULL); - - return cipher->name; -} - -guint -purple_cipher_get_capabilities(PurpleCipher *cipher) { - PurpleCipherOps *ops = NULL; - guint caps = 0; - - g_return_val_if_fail(cipher, 0); - - ops = cipher->ops; - g_return_val_if_fail(ops, 0); - - if(ops->set_option) - caps |= PURPLE_CIPHER_CAPS_SET_OPT; - if(ops->get_option) - caps |= PURPLE_CIPHER_CAPS_GET_OPT; - if(ops->init) - caps |= PURPLE_CIPHER_CAPS_INIT; - if(ops->reset) - caps |= PURPLE_CIPHER_CAPS_RESET; - if(ops->reset_state) - caps |= PURPLE_CIPHER_CAPS_RESET_STATE; - if(ops->uninit) - caps |= PURPLE_CIPHER_CAPS_UNINIT; - if(ops->set_iv) - caps |= PURPLE_CIPHER_CAPS_SET_IV; - if(ops->append) - caps |= PURPLE_CIPHER_CAPS_APPEND; - if(ops->digest) - caps |= PURPLE_CIPHER_CAPS_DIGEST; - if(ops->get_digest_size) - caps |= PURPLE_CIPHER_CAPS_GET_DIGEST_SIZE; - if(ops->encrypt) - caps |= PURPLE_CIPHER_CAPS_ENCRYPT; - if(ops->decrypt) - caps |= PURPLE_CIPHER_CAPS_DECRYPT; - if(ops->set_salt) - caps |= PURPLE_CIPHER_CAPS_SET_SALT; - if(ops->get_salt_size) - caps |= PURPLE_CIPHER_CAPS_GET_SALT_SIZE; - if(ops->set_key) - caps |= PURPLE_CIPHER_CAPS_SET_KEY; - if (ops->get_key_size) - caps |= PURPLE_CIPHER_CAPS_GET_KEY_SIZE; - if(ops->set_batch_mode) - caps |= PURPLE_CIPHER_CAPS_SET_BATCH_MODE; - if(ops->get_batch_mode) - caps |= PURPLE_CIPHER_CAPS_GET_BATCH_MODE; - if(ops->get_block_size) - caps |= PURPLE_CIPHER_CAPS_GET_BLOCK_SIZE; - - return caps; -} - -ssize_t -purple_cipher_digest_region(const gchar *name, const guchar *data, - size_t data_len, guchar digest[], size_t out_size) -{ - PurpleCipher *cipher; - PurpleCipherContext *context; - ssize_t digest_size; - gboolean succ; - - g_return_val_if_fail(name, -1); - g_return_val_if_fail(data, -1); - - cipher = purple_ciphers_find_cipher(name); - - g_return_val_if_fail(cipher, -1); - - if(!cipher->ops->append || !cipher->ops->digest || !cipher->ops->get_digest_size) { - purple_debug_warning("cipher", "purple_cipher_region failed: " - "the %s cipher does not support appending and or " - "digesting.", cipher->name); - return -1; - } - - context = purple_cipher_context_new(cipher, NULL); - digest_size = purple_cipher_context_get_digest_size(context); - if (out_size < digest_size) { - purple_debug_error("cipher", "purple_cipher_region failed: " - "provided output buffer too small\n"); - purple_cipher_context_destroy(context); - return -1; - } - purple_cipher_context_append(context, data, data_len); - succ = purple_cipher_context_digest(context, digest, out_size); - purple_cipher_context_destroy(context); - - return succ ? digest_size : -1; -} + PurpleCipherClass *klass = NULL; -/****************************************************************************** - * PurpleCiphers API - *****************************************************************************/ -PurpleCipher * -purple_ciphers_find_cipher(const gchar *name) { - PurpleCipher *cipher; - GList *l; - - g_return_val_if_fail(name, NULL); - - for(l = ciphers; l; l = l->next) { - cipher = PURPLE_CIPHER(l->data); - - if(!g_ascii_strcasecmp(cipher->name, name)) - return cipher; - } - - return NULL; -} - -PurpleCipher * -purple_ciphers_register_cipher(const gchar *name, PurpleCipherOps *ops) { - PurpleCipher *cipher = NULL; - - g_return_val_if_fail(name, NULL); - g_return_val_if_fail(ops, NULL); - g_return_val_if_fail(!purple_ciphers_find_cipher(name), NULL); - - cipher = g_new0(PurpleCipher, 1); - PURPLE_DBUS_REGISTER_POINTER(cipher, PurpleCipher); - - cipher->name = g_strdup(name); - cipher->ops = ops; - - ciphers = g_list_append(ciphers, cipher); - - purple_signal_emit(purple_ciphers_get_handle(), "cipher-added", cipher); - - return cipher; -} - -gboolean -purple_ciphers_unregister_cipher(PurpleCipher *cipher) { - g_return_val_if_fail(cipher, FALSE); - g_return_val_if_fail(cipher->ref == 0, FALSE); - - purple_signal_emit(purple_ciphers_get_handle(), "cipher-removed", cipher); - - ciphers = g_list_remove(ciphers, cipher); - - g_free(cipher->name); - - PURPLE_DBUS_UNREGISTER_POINTER(cipher); - g_free(cipher); - - return TRUE; -} - -GList * -purple_ciphers_get_ciphers() { - return ciphers; -} - -/****************************************************************************** - * PurpleCipher Subsystem API - *****************************************************************************/ -gpointer -purple_ciphers_get_handle() { - static gint handle; - - return &handle; -} - -void -purple_ciphers_init() { - gpointer handle; - - handle = purple_ciphers_get_handle(); - - purple_signal_register(handle, "cipher-added", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CIPHER)); - purple_signal_register(handle, "cipher-removed", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CIPHER)); - - purple_ciphers_register_all(); -} - -void -purple_ciphers_uninit() { - PurpleCipher *cipher; - GList *l, *ll; - - for(l = ciphers; l; l = ll) { - ll = l->next; - - cipher = PURPLE_CIPHER(l->data); - purple_ciphers_unregister_cipher(cipher); - } - - g_list_free(ciphers); - - purple_signals_unregister_by_instance(purple_ciphers_get_handle()); -} - -/****************************************************************************** - * PurpleCipherContext API - *****************************************************************************/ -void -purple_cipher_context_set_option(PurpleCipherContext *context, const gchar *name, - gpointer value) -{ - PurpleCipher *cipher = NULL; - - g_return_if_fail(context); - g_return_if_fail(name); - - cipher = context->cipher; - g_return_if_fail(cipher); - - if(cipher->ops && cipher->ops->set_option) - cipher->ops->set_option(context, name, value); - else - purple_debug_warning("cipher", "the %s cipher does not support the " - "set_option operation\n", cipher->name); -} - -gpointer -purple_cipher_context_get_option(PurpleCipherContext *context, const gchar *name) { - PurpleCipher *cipher = NULL; - - g_return_val_if_fail(context, NULL); - g_return_val_if_fail(name, NULL); - - cipher = context->cipher; g_return_val_if_fail(cipher, NULL); - - if(cipher->ops && cipher->ops->get_option) - return cipher->ops->get_option(context, name); - else { - purple_debug_warning("cipher", "the %s cipher does not support the " - "get_option operation\n", cipher->name); - - return NULL; + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), NULL); + + klass = PURPLE_CIPHER_GET_CLASS(cipher); + g_return_val_if_fail(klass->get_name, NULL); + + return klass->get_name(cipher); +} + +GType +purple_cipher_get_type(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleCipherClass), + NULL, + NULL, + NULL, + NULL, + NULL, + sizeof(PurpleCipher), + 0, + NULL, + NULL + }; + + type = g_type_register_static(G_TYPE_OBJECT, + "PurpleCipher", + &info, G_TYPE_FLAG_ABSTRACT); } -} - -PurpleCipherContext * -purple_cipher_context_new(PurpleCipher *cipher, void *extra) { - PurpleCipherContext *context = NULL; - - g_return_val_if_fail(cipher, NULL); - - cipher->ref++; - - context = g_new0(PurpleCipherContext, 1); - context->cipher = cipher; - if(cipher->ops->init) - cipher->ops->init(context, extra); - - return context; -} - -PurpleCipherContext * -purple_cipher_context_new_by_name(const gchar *name, void *extra) { - PurpleCipher *cipher; - - g_return_val_if_fail(name, NULL); - - cipher = purple_ciphers_find_cipher(name); - - g_return_val_if_fail(cipher, NULL); - - return purple_cipher_context_new(cipher, extra); -} - -void -purple_cipher_context_reset(PurpleCipherContext *context, void *extra) { - PurpleCipher *cipher = NULL; - - g_return_if_fail(context); - - cipher = context->cipher; - g_return_if_fail(cipher); - - if(cipher->ops && cipher->ops->reset) - context->cipher->ops->reset(context, extra); + return type; } +/** + * purple_cipher_reset: + * @cipher: The cipher to reset + * + * Resets a cipher to it's default value + * + * @note If you have set an IV you will have to set it after resetting + */ void -purple_cipher_context_reset_state(PurpleCipherContext *context, void *extra) { - PurpleCipher *cipher = NULL; - - g_return_if_fail(context); +purple_cipher_reset(PurpleCipher *cipher) { + PurpleCipherClass *klass = NULL; - cipher = context->cipher; - g_return_if_fail(cipher); - g_return_if_fail(cipher->ops); + g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - if (cipher->ops->reset_state) { - context->cipher->ops->reset_state(context, extra); - return; - } + klass = PURPLE_CIPHER_GET_CLASS(cipher); - purple_debug_warning("cipher", "the %s cipher does not support the " - "reset_state operation\n", cipher->name); - purple_cipher_context_reset(context, extra); + if(klass && klass->reset) + klass->reset(cipher); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "reset method\n", + klass->get_name ? klass->get_name(cipher) : ""); } +/** + * Resets a cipher state to it's default value, but doesn't touch stateless + * configuration. + * + * That means, IV and digest context will be wiped out, but keys, ops or salt + * will remain untouched. + */ void -purple_cipher_context_destroy(PurpleCipherContext *context) { - PurpleCipher *cipher = NULL; +purple_cipher_reset_state(PurpleCipher *cipher) { + PurpleCipherClass *klass = NULL; - g_return_if_fail(context); + g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - cipher = context->cipher; - g_return_if_fail(cipher); + klass = PURPLE_CIPHER_GET_CLASS(cipher); - cipher->ref--; - - if(cipher->ops && cipher->ops->uninit) - cipher->ops->uninit(context); - - memset(context, 0, sizeof(*context)); - g_free(context); - context = NULL; + if(klass && klass->reset_state) + klass->reset_state(cipher); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "reset_state method\n", + klass->get_name ? klass->get_name(cipher) : ""); } +/** + * purple_cipher_set_iv: + * @cipher: The cipher to set the IV to + * @iv: The initialization vector to set + * @len: The len of the IV + * + * @note This should only be called right after a cipher is created or reset + * + * Sets the initialization vector for a cipher + */ void -purple_cipher_context_set_iv(PurpleCipherContext *context, guchar *iv, size_t len) +purple_cipher_set_iv(PurpleCipher *cipher, guchar *iv, size_t len) { - PurpleCipher *cipher = NULL; + PurpleCipherClass *klass = NULL; - g_return_if_fail(context); + g_return_if_fail(PURPLE_IS_CIPHER(cipher)); g_return_if_fail(iv); - cipher = context->cipher; - g_return_if_fail(cipher); + klass = PURPLE_CIPHER_GET_CLASS(cipher); - if(cipher->ops && cipher->ops->set_iv) - cipher->ops->set_iv(context, iv, len); + if(klass && klass->set_iv) + klass->set_iv(cipher, iv, len); else - purple_debug_warning("cipher", "the %s cipher does not support the set" - "initialization vector operation\n", cipher->name); + purple_debug_warning("cipher", "the %s cipher does not implement the " + "set_iv method\n", + klass->get_name ? klass->get_name(cipher) : ""); } +/** + * purple_cipher_append: + * @cipher: The cipher to append data to + * @data: The data to append + * @len: The length of the data + * + * Appends data to the cipher + */ void -purple_cipher_context_append(PurpleCipherContext *context, const guchar *data, +purple_cipher_append(PurpleCipher *cipher, const guchar *data, size_t len) { - PurpleCipher *cipher = NULL; + PurpleCipherClass *klass = NULL; - g_return_if_fail(context); + g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - cipher = context->cipher; - g_return_if_fail(cipher); + klass = PURPLE_CIPHER_GET_CLASS(cipher); - if(cipher->ops && cipher->ops->append) - cipher->ops->append(context, data, len); + if(klass && klass->append) + klass->append(cipher, data, len); else - purple_debug_warning("cipher", "the %s cipher does not support the append " - "operation\n", cipher->name); + purple_debug_warning("cipher", "the %s cipher does not implement the " + "append method\n", + klass->get_name ? klass->get_name(cipher) : ""); } +/** + * purple_cipher_digest: + * @cipher: The cipher to digest + * @in_len: The length of the buffer + * @digest: The return buffer for the digest + * @out_len: The length of the returned value + * + * Digests a cipher + * + * Return Value: TRUE if the digest was successful, FALSE otherwise. + */ gboolean -purple_cipher_context_digest(PurpleCipherContext *context, guchar digest[], - size_t len) +purple_cipher_digest(PurpleCipher *cipher, guchar digest[], size_t len) { - PurpleCipher *cipher = NULL; + PurpleCipherClass *klass = NULL; - g_return_val_if_fail(context, FALSE); + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), FALSE); - cipher = context->cipher; + klass = PURPLE_CIPHER_GET_CLASS(cipher); - if(cipher->ops && cipher->ops->digest) - return cipher->ops->digest(context, digest, len); - else { - purple_debug_warning("cipher", "the %s cipher does not support the digest " - "operation\n", cipher->name); - return FALSE; - } + if(klass && klass->digest) + return klass->digest(cipher, digest, len); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "digest method\n", + klass->get_name ? klass->get_name(cipher) : ""); + + return FALSE; } +/** + * purple_cipher_digest_to_str: + * @cipher: The cipher to get a digest from + * @in_len: The length of the buffer + * @digest_s: The return buffer for the string digest + * @out_len: The length of the returned value + * + * Converts a guchar digest into a hex string + * + * Return Value: TRUE if the digest was successful, FALSE otherwise. + */ gboolean -purple_cipher_context_digest_to_str(PurpleCipherContext *context, - gchar digest_s[], size_t len) +purple_cipher_digest_to_str(PurpleCipher *cipher, gchar digest_s[], size_t len) { /* 8k is a bit excessive, will tweak later. */ guchar digest[BUF_LEN * 4]; gint n = 0; size_t digest_size; - g_return_val_if_fail(context, FALSE); + g_return_val_if_fail(cipher, FALSE); g_return_val_if_fail(digest_s, FALSE); - digest_size = purple_cipher_context_get_digest_size(context); + digest_size = purple_cipher_get_digest_size(cipher); g_return_val_if_fail(digest_size <= BUF_LEN * 4, FALSE); - if(!purple_cipher_context_digest(context, digest, sizeof(digest))) + if(!purple_cipher_digest(cipher, digest, sizeof(digest))) return FALSE; /* Every digest byte occupies 2 chars + the NUL at the end. */ @@ -478,373 +236,240 @@ purple_cipher_context_digest_to_str(PurpleCipherContext *context, } size_t -purple_cipher_context_get_digest_size(PurpleCipherContext *context) +purple_cipher_get_digest_size(PurpleCipher *cipher) { - PurpleCipher *cipher = NULL; + PurpleCipherClass *klass = NULL; - g_return_val_if_fail(context, 0); + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), FALSE); - cipher = context->cipher; - g_return_val_if_fail(cipher, 0); + klass = PURPLE_CIPHER_GET_CLASS(cipher); - if(cipher->ops && cipher->ops->get_digest_size) - return cipher->ops->get_digest_size(context); - else { - purple_debug_warning("cipher", "The %s cipher does not support " - "the get_digest_size operation\n", cipher->name); - return 0; - } + if(klass && klass->get_digest_size) + return klass->get_digest_size(cipher); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "get_digest_size method\n", + klass->get_name ? klass->get_name(cipher) : ""); + + return FALSE; } +/** + * purple_cipher_encrypt: + * @cipher: The cipher + * @data: The data to encrypt + * @len: The length of the data + * @output: The output buffer + * @outlen: The len of data that was outputed + * + * Encrypts data using the cipher + * + * Return Value: A cipher specific status code + */ ssize_t -purple_cipher_context_encrypt(PurpleCipherContext *context, - const guchar input[], size_t in_len, guchar output[], size_t out_size) +purple_cipher_encrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) { - PurpleCipher *cipher = NULL; + PurpleCipherClass *klass = NULL; - g_return_val_if_fail(context != NULL, -1); + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), -1); g_return_val_if_fail(input != NULL, -1); g_return_val_if_fail(output != NULL, -1); g_return_val_if_fail(out_size >= in_len, -1); - cipher = context->cipher; - g_return_val_if_fail(cipher, -1); + klass = PURPLE_CIPHER_GET_CLASS(cipher); - if(cipher->ops && cipher->ops->encrypt) - return cipher->ops->encrypt(context, input, in_len, output, out_size); - else { - purple_debug_warning("cipher", "the %s cipher does not support the encrypt" - "operation\n", cipher->name); + if(klass && klass->encrypt) + return klass->encrypt(cipher, input, in_len, output, out_size); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "encrypt method\n", + klass->get_name ? klass->get_name(cipher) : ""); - return -1; - } + return -1; } +/** + * purple_cipher_decrypt: + * @cipher: The cipher + * @data: The data to encrypt + * @len: The length of the returned value + * @output: The output buffer + * @outlen: The len of data that was outputed + * + * Decrypts data using the cipher + * + * Return Value: A cipher specific status code + */ ssize_t -purple_cipher_context_decrypt(PurpleCipherContext *context, - const guchar input[], size_t in_len, guchar output[], size_t out_size) +purple_cipher_decrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) { - PurpleCipher *cipher = NULL; + PurpleCipherClass *klass = NULL; - g_return_val_if_fail(context != NULL, -1); + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), -1); g_return_val_if_fail(input != NULL, -1); g_return_val_if_fail(output != NULL, -1); - cipher = context->cipher; - g_return_val_if_fail(cipher, -1); + klass = PURPLE_CIPHER_GET_CLASS(cipher); - if(cipher->ops && cipher->ops->decrypt) - return cipher->ops->decrypt(context, input, in_len, output, out_size); - else { - purple_debug_warning("cipher", "the %s cipher does not support the decrypt" - "operation\n", cipher->name); + if(klass && klass->decrypt) + return klass->decrypt(cipher, input, in_len, output, out_size); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "decrypt method\n", + klass->get_name ? klass->get_name(cipher) : ""); - return -1; - } + return -1; } +/** + * purple_cipher_set_salt: + * @cipher: The cipher whose salt to set + * @salt: The salt + * + * Sets the salt on a cipher + */ void -purple_cipher_context_set_salt(PurpleCipherContext *context, const guchar *salt, size_t len) { - PurpleCipher *cipher = NULL; +purple_cipher_set_salt(PurpleCipher *cipher, const guchar *salt, size_t len) { + PurpleCipherClass *klass = NULL; - g_return_if_fail(context); + g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - cipher = context->cipher; - g_return_if_fail(cipher); + klass = PURPLE_CIPHER_GET_CLASS(cipher); - if(cipher->ops && cipher->ops->set_salt) - cipher->ops->set_salt(context, salt, len); + if(klass && klass->set_salt) + klass->set_salt(cipher, salt, len); else - purple_debug_warning("cipher", "the %s cipher does not support the " - "set_salt operation\n", cipher->name); -} - -size_t -purple_cipher_context_get_salt_size(PurpleCipherContext *context) { - PurpleCipher *cipher = NULL; - - g_return_val_if_fail(context, -1); - - cipher = context->cipher; - g_return_val_if_fail(cipher, -1); - - if(cipher->ops && cipher->ops->get_salt_size) - return cipher->ops->get_salt_size(context); - else { - purple_debug_warning("cipher", "the %s cipher does not support the " - "get_salt_size operation\n", cipher->name); - - return -1; - } + purple_debug_warning("cipher", "the %s cipher does not implement the " + "set_salt method\n", + klass->get_name ? klass->get_name(cipher) : ""); } +/** + * purple_cipher_set_key: + * @cipher: The cipher whose key to set + * @key: The key + * + * Sets the key on a cipher + */ void -purple_cipher_context_set_key(PurpleCipherContext *context, const guchar *key, size_t len) { - PurpleCipher *cipher = NULL; +purple_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) { + PurpleCipherClass *klass = NULL; - g_return_if_fail(context); + g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - cipher = context->cipher; - g_return_if_fail(cipher); + klass = PURPLE_CIPHER_GET_CLASS(cipher); - if(cipher->ops && cipher->ops->set_key) - cipher->ops->set_key(context, key, len); + if(klass && klass->set_key) + klass->set_key(cipher, key, len); else - purple_debug_warning("cipher", "the %s cipher does not support the " - "set_key operation\n", cipher->name); + purple_debug_warning("cipher", "the %s cipher does not implement the " + "set_key method\n", + klass->get_name ? klass->get_name(cipher) : ""); } +/** + * purple_cipher_get_key_size: + * @cipher: The cipher whose key size to get + * + * Gets the key size for a cipher + * + * Return Value: The size of the key + */ size_t -purple_cipher_context_get_key_size(PurpleCipherContext *context) { - PurpleCipher *cipher = NULL; +purple_cipher_get_key_size(PurpleCipher *cipher) { + PurpleCipherClass *klass = NULL; - g_return_val_if_fail(context, 0); + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), -1); - cipher = context->cipher; - g_return_val_if_fail(cipher, 0); + klass = PURPLE_CIPHER_GET_CLASS(cipher); - if (cipher->ops && cipher->ops->get_key_size) - return cipher->ops->get_key_size(context); - else { - purple_debug_warning("cipher", "the %s cipher does not support " - "the get_key_size operation\n", cipher->name); + if(klass && klass->get_key_size) + return klass->get_key_size(cipher); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "get_key_size method\n", + klass->get_name ? klass->get_name(cipher) : ""); - return 0; - } + return -1; } +/** + * purple_cipher_set_batch_mode: + * @cipher: The cipher whose batch mode to set + * @mode: The batch mode under which the cipher should operate + * + * Sets the batch mode of a cipher + */ void -purple_cipher_context_set_batch_mode(PurpleCipherContext *context, +purple_cipher_set_batch_mode(PurpleCipher *cipher, PurpleCipherBatchMode mode) { - PurpleCipher *cipher = NULL; + PurpleCipherClass *klass = NULL; - g_return_if_fail(context); + g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - cipher = context->cipher; - g_return_if_fail(cipher); + klass = PURPLE_CIPHER_GET_CLASS(cipher); - if(cipher->ops && cipher->ops->set_batch_mode) - cipher->ops->set_batch_mode(context, mode); + if(klass && klass->set_batch_mode) + klass->set_batch_mode(cipher, mode); else - purple_debug_warning("cipher", "The %s cipher does not support the " - "set_batch_mode operation\n", cipher->name); + purple_debug_warning("cipher", "the %s cipher does not implement the " + "set_batch_mode method\n", + klass->get_name ? klass->get_name(cipher) : ""); } +/** + * purple_cipher_get_batch_mode: + * @cipher: The cipher whose batch mode to get + * + * Gets the batch mode of a cipher + * + * Return Value: The batch mode under which the cipher is operating + */ PurpleCipherBatchMode -purple_cipher_context_get_batch_mode(PurpleCipherContext *context) +purple_cipher_get_batch_mode(PurpleCipher *cipher) { - PurpleCipher *cipher = NULL; - - g_return_val_if_fail(context, -1); + PurpleCipherClass *klass = NULL; - cipher = context->cipher; - g_return_val_if_fail(cipher, -1); + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), -1); - if(cipher->ops && cipher->ops->get_batch_mode) - return cipher->ops->get_batch_mode(context); - else { - purple_debug_warning("cipher", "The %s cipher does not support the " - "get_batch_mode operation\n", cipher->name); - return -1; - } -} + klass = PURPLE_CIPHER_GET_CLASS(cipher); -size_t -purple_cipher_context_get_block_size(PurpleCipherContext *context) -{ - PurpleCipher *cipher = NULL; - - g_return_val_if_fail(context, -1); - - cipher = context->cipher; - g_return_val_if_fail(cipher, -1); - - if(cipher->ops && cipher->ops->get_block_size) - return cipher->ops->get_block_size(context); - else { - purple_debug_warning("cipher", "The %s cipher does not support the " - "get_block_size operation\n", cipher->name); - return -1; - } -} - -void -purple_cipher_context_set_data(PurpleCipherContext *context, gpointer data) { - g_return_if_fail(context); - - context->data = data; -} - -gpointer -purple_cipher_context_get_data(PurpleCipherContext *context) { - g_return_val_if_fail(context, NULL); + if(klass && klass->get_batch_mode) + return klass->get_batch_mode(cipher); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "get_batch_mode method\n", + klass->get_name ? klass->get_name(cipher) : ""); - return context->data; + return -1; } -gchar *purple_cipher_http_digest_calculate_session_key( - const gchar *algorithm, - const gchar *username, - const gchar *realm, - const gchar *password, - const gchar *nonce, - const gchar *client_nonce) +/** + * purple_cipher_get_block_size: + * @cipher: The cipher whose block size to get + * + * Gets the block size of a cipher + * + * Return Value: The block size of the cipher + */ +size_t +purple_cipher_get_block_size(PurpleCipher *cipher) { - PurpleCipher *cipher; - PurpleCipherContext *context; - gchar hash[33]; /* We only support MD5. */ - - g_return_val_if_fail(username != NULL, NULL); - g_return_val_if_fail(realm != NULL, NULL); - g_return_val_if_fail(password != NULL, NULL); - g_return_val_if_fail(nonce != NULL, NULL); - - /* Check for a supported algorithm. */ - g_return_val_if_fail(algorithm == NULL || - *algorithm == '\0' || - g_ascii_strcasecmp(algorithm, "MD5") || - g_ascii_strcasecmp(algorithm, "MD5-sess"), NULL); - - cipher = purple_ciphers_find_cipher("md5"); - g_return_val_if_fail(cipher != NULL, NULL); - - context = purple_cipher_context_new(cipher, NULL); - - purple_cipher_context_append(context, (guchar *)username, strlen(username)); - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)realm, strlen(realm)); - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)password, strlen(password)); - - if (algorithm != NULL && !g_ascii_strcasecmp(algorithm, "MD5-sess")) - { - guchar digest[16]; - - if (client_nonce == NULL) - { - purple_cipher_context_destroy(context); - purple_debug_error("cipher", "Required client_nonce missing for MD5-sess digest calculation.\n"); - return NULL; - } - - purple_cipher_context_digest(context, digest, sizeof(digest)); - purple_cipher_context_destroy(context); - - context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, digest, sizeof(digest)); - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)nonce, strlen(nonce)); - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)client_nonce, strlen(client_nonce)); - } - - purple_cipher_context_digest_to_str(context, hash, sizeof(hash)); - purple_cipher_context_destroy(context); + PurpleCipherClass *klass = NULL; - return g_strdup(hash); -} - -gchar *purple_cipher_http_digest_calculate_response( - const gchar *algorithm, - const gchar *method, - const gchar *digest_uri, - const gchar *qop, - const gchar *entity, - const gchar *nonce, - const gchar *nonce_count, - const gchar *client_nonce, - const gchar *session_key) -{ - PurpleCipher *cipher; - PurpleCipherContext *context; - static gchar hash2[33]; /* We only support MD5. */ - - g_return_val_if_fail(method != NULL, NULL); - g_return_val_if_fail(digest_uri != NULL, NULL); - g_return_val_if_fail(nonce != NULL, NULL); - g_return_val_if_fail(session_key != NULL, NULL); - - /* Check for a supported algorithm. */ - g_return_val_if_fail(algorithm == NULL || - *algorithm == '\0' || - g_ascii_strcasecmp(algorithm, "MD5") || - g_ascii_strcasecmp(algorithm, "MD5-sess"), NULL); - - /* Check for a supported "quality of protection". */ - g_return_val_if_fail(qop == NULL || - *qop == '\0' || - g_ascii_strcasecmp(qop, "auth") || - g_ascii_strcasecmp(qop, "auth-int"), NULL); - - cipher = purple_ciphers_find_cipher("md5"); - g_return_val_if_fail(cipher != NULL, NULL); - - context = purple_cipher_context_new(cipher, NULL); - - purple_cipher_context_append(context, (guchar *)method, strlen(method)); - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)digest_uri, strlen(digest_uri)); - - if (qop != NULL && !g_ascii_strcasecmp(qop, "auth-int")) - { - PurpleCipherContext *context2; - gchar entity_hash[33]; - - if (entity == NULL) - { - purple_cipher_context_destroy(context); - purple_debug_error("cipher", "Required entity missing for auth-int digest calculation.\n"); - return NULL; - } - - context2 = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context2, (guchar *)entity, strlen(entity)); - purple_cipher_context_digest_to_str(context2, entity_hash, sizeof(entity_hash)); - purple_cipher_context_destroy(context2); - - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)entity_hash, strlen(entity_hash)); - } + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), -1); - purple_cipher_context_digest_to_str(context, hash2, sizeof(hash2)); - purple_cipher_context_destroy(context); - - context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, (guchar *)session_key, strlen(session_key)); - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)nonce, strlen(nonce)); - purple_cipher_context_append(context, (guchar *)":", 1); - - if (qop != NULL && *qop != '\0') - { - if (nonce_count == NULL) - { - purple_cipher_context_destroy(context); - purple_debug_error("cipher", "Required nonce_count missing for digest calculation.\n"); - return NULL; - } - - if (client_nonce == NULL) - { - purple_cipher_context_destroy(context); - purple_debug_error("cipher", "Required client_nonce missing for digest calculation.\n"); - return NULL; - } - - purple_cipher_context_append(context, (guchar *)nonce_count, strlen(nonce_count)); - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)client_nonce, strlen(client_nonce)); - purple_cipher_context_append(context, (guchar *)":", 1); - - purple_cipher_context_append(context, (guchar *)qop, strlen(qop)); - - purple_cipher_context_append(context, (guchar *)":", 1); - } + klass = PURPLE_CIPHER_GET_CLASS(cipher); - purple_cipher_context_append(context, (guchar *)hash2, strlen(hash2)); - purple_cipher_context_digest_to_str(context, hash2, sizeof(hash2)); - purple_cipher_context_destroy(context); + if(klass && klass->get_block_size) + return klass->get_block_size(cipher); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "get_block_size method\n", + klass->get_name ? klass->get_name(cipher) : ""); - return g_strdup(hash2); + return -1; } diff --git a/libpurple/cipher.h b/libpurple/cipher.h index 249f526856..6e52734112 100644 --- a/libpurple/cipher.h +++ b/libpurple/cipher.h @@ -28,110 +28,96 @@ #define PURPLE_CIPHER_H #include <glib.h> +#include <glib-object.h> #include <string.h> -#define PURPLE_CIPHER(obj) ((PurpleCipher *)(obj)) /**< PurpleCipher typecast helper */ -#define PURPLE_CIPHER_OPS(obj) ((PurpleCipherOps *)(obj)) /**< PurpleCipherInfo typecase helper */ -#define PURPLE_CIPHER_CONTEXT(obj) ((PurpleCipherContext *)(obj)) /**< PurpleCipherContext typecast helper */ +#include "internal.h" -typedef struct _PurpleCipher PurpleCipher; /**< A handle to a PurpleCipher */ -typedef struct _PurpleCipherOps PurpleCipherOps; /**< Ops for a PurpleCipher */ -typedef struct _PurpleCipherContext PurpleCipherContext; /**< A context for a PurpleCipher */ +#define PURPLE_TYPE_CIPHER (purple_cipher_get_type()) +#define PURPLE_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_CIPHER, PurpleCipher)) +#define PURPLE_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_CIPHER, PurpleCipherClass)) +#define PURPLE_IS_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_CIPHER)) +#define PURPLE_IS_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_CIPHER)) +#define PURPLE_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_CIPHER, PurpleCipherClass)) + +typedef struct _PurpleCipher PurpleCipher; +typedef struct _PurpleCipherClass PurpleCipherClass; /** + * PurpleCipherBatchMode: + * @PURPLE_CIPHER_BATCH_MODE_ECB: Electronic Codebook Mode + * @PURPLE_CIPHER_BATCH_MODE_CBC: Cipher Block Chaining Mode + * * Modes for batch encrypters */ -typedef enum { - PURPLE_CIPHER_BATCH_MODE_ECB, - PURPLE_CIPHER_BATCH_MODE_CBC +typedef enum { + PURPLE_CIPHER_BATCH_MODE_ECB, /*< nick=ECB Batch Mode >*/ + PURPLE_CIPHER_BATCH_MODE_CBC /*< nick=CBC Batch Mode >*/ } PurpleCipherBatchMode; /** - * The operation flags for a cipher + * PurpleCipher: + * + * Purple Cipher is an opaque data structure and should not be used directly. */ -typedef enum { - PURPLE_CIPHER_CAPS_SET_OPT = 1 << 1, /**< Set option flag */ - PURPLE_CIPHER_CAPS_GET_OPT = 1 << 2, /**< Get option flag */ - PURPLE_CIPHER_CAPS_INIT = 1 << 3, /**< Init flag */ - PURPLE_CIPHER_CAPS_RESET = 1 << 4, /**< Reset flag */ - PURPLE_CIPHER_CAPS_RESET_STATE = 1 << 5, /**< Reset state flag */ - PURPLE_CIPHER_CAPS_UNINIT = 1 << 6, /**< Uninit flag */ - PURPLE_CIPHER_CAPS_SET_IV = 1 << 7, /**< Set IV flag */ - PURPLE_CIPHER_CAPS_APPEND = 1 << 8, /**< Append flag */ - PURPLE_CIPHER_CAPS_DIGEST = 1 << 9, /**< Digest flag */ - PURPLE_CIPHER_CAPS_GET_DIGEST_SIZE = 1 << 10, /**< The get digest size flag */ - PURPLE_CIPHER_CAPS_ENCRYPT = 1 << 11, /**< Encrypt flag */ - PURPLE_CIPHER_CAPS_DECRYPT = 1 << 12, /**< Decrypt flag */ - PURPLE_CIPHER_CAPS_SET_SALT = 1 << 13, /**< Set salt flag */ - PURPLE_CIPHER_CAPS_GET_SALT_SIZE = 1 << 14, /**< Get salt size flag */ - PURPLE_CIPHER_CAPS_SET_KEY = 1 << 15, /**< Set key flag */ - PURPLE_CIPHER_CAPS_GET_KEY_SIZE = 1 << 16, /**< Get key size flag */ - PURPLE_CIPHER_CAPS_SET_BATCH_MODE = 1 << 17, /**< Set batch mode flag */ - PURPLE_CIPHER_CAPS_GET_BATCH_MODE = 1 << 18, /**< Get batch mode flag */ - PURPLE_CIPHER_CAPS_GET_BLOCK_SIZE = 1 << 19, /**< The get block size flag */ - PURPLE_CIPHER_CAPS_UNKNOWN = 1 << 20 /**< Unknown */ -} PurpleCipherCaps; +struct _PurpleCipher { + /*< private >*/ + GObject gparent; +}; /** - * The operations of a cipher. Every cipher must implement one of these. + * PurpleCipherClass: + * + * The base class for all #PurpleCipher's. */ -struct _PurpleCipherOps { - /** The set option function */ - void (*set_option)(PurpleCipherContext *context, const gchar *name, void *value); - - /** The get option function */ - void *(*get_option)(PurpleCipherContext *context, const gchar *name); - - /** The init function */ - void (*init)(PurpleCipherContext *context, void *extra); +struct _PurpleCipherClass { + /*< private >*/ + GObjectClass parent_class; /** The reset function */ - void (*reset)(PurpleCipherContext *context, void *extra); + void (*reset)(PurpleCipher *cipher); /** The reset state function */ - void (*reset_state)(PurpleCipherContext *context, void *extra); - - /** The uninit function */ - void (*uninit)(PurpleCipherContext *context); + void (*reset_state)(PurpleCipher *cipher); /** The set initialization vector function */ - void (*set_iv)(PurpleCipherContext *context, guchar *iv, size_t len); + void (*set_iv)(PurpleCipher *cipher, guchar *iv, size_t len); /** The append data function */ - void (*append)(PurpleCipherContext *context, const guchar *data, size_t len); + void (*append)(PurpleCipher *cipher, const guchar *data, size_t len); /** The digest function */ - gboolean (*digest)(PurpleCipherContext *context, guchar digest[], size_t len); + gboolean (*digest)(PurpleCipher *cipher, guchar digest[], size_t len); /** The get digest size function */ - size_t (*get_digest_size)(PurpleCipherContext *context); + size_t (*get_digest_size)(PurpleCipher *cipher); /** The encrypt function */ - ssize_t (*encrypt)(PurpleCipherContext *context, const guchar input[], size_t in_len, guchar output[], size_t out_size); + ssize_t (*encrypt)(PurpleCipher *cipher, const guchar input[], size_t in_len, guchar output[], size_t out_size); /** The decrypt function */ - ssize_t (*decrypt)(PurpleCipherContext *context, const guchar input[], size_t in_len, guchar output[], size_t out_size); + ssize_t (*decrypt)(PurpleCipher *cipher, const guchar input[], size_t in_len, guchar output[], size_t out_size); /** The set salt function */ - void (*set_salt)(PurpleCipherContext *context, const guchar *salt, size_t len); - - /** The get salt size function */ - size_t (*get_salt_size)(PurpleCipherContext *context); + void (*set_salt)(PurpleCipher *cipher, const guchar *salt, size_t len); /** The set key function */ - void (*set_key)(PurpleCipherContext *context, const guchar *key, size_t len); + void (*set_key)(PurpleCipher *cipher, const guchar *key, size_t len); /** The get key size function */ - size_t (*get_key_size)(PurpleCipherContext *context); + size_t (*get_key_size)(PurpleCipher *cipher); /** The set batch mode function */ - void (*set_batch_mode)(PurpleCipherContext *context, PurpleCipherBatchMode mode); + void (*set_batch_mode)(PurpleCipher *cipher, PurpleCipherBatchMode mode); /** The get batch mode function */ - PurpleCipherBatchMode (*get_batch_mode)(PurpleCipherContext *context); + PurpleCipherBatchMode (*get_batch_mode)(PurpleCipher *cipher); /** The get block size function */ - size_t (*get_block_size)(PurpleCipherContext *context); + size_t (*get_block_size)(PurpleCipher *cipher); + + /** The get cipher name function */ + const gchar* (*get_name)(PurpleCipher *cipher); void (*_purple_reserved1)(void); void (*_purple_reserved2)(void); @@ -147,223 +133,88 @@ G_BEGIN_DECLS /*@{*/ /** - * Gets a cipher's name - * - * @param cipher The cipher handle - * - * @return The cipher's name - */ -const gchar *purple_cipher_get_name(PurpleCipher *cipher); - -/** - * Gets a cipher's capabilities - * - * @param cipher The cipher handle - * - * @return The cipher's info - */ -guint purple_cipher_get_capabilities(PurpleCipher *cipher); - -/** - * Gets a digest from a cipher - * - * @param name The cipher's name - * @param data The data to hash - * @param data_len The length of the data - * @param digest The returned digest - * @param out_size The size of digest buffer - * - * @return The count of bytes written, or -1 if failed + * Returns the GType for the Cipher object. */ -ssize_t purple_cipher_digest_region(const gchar *name, const guchar *data, size_t data_len, guchar digest[], size_t out_size); - -/*@}*/ -/******************************************************************************/ -/** @name PurpleCiphers API */ -/******************************************************************************/ -/*@{*/ +GType purple_cipher_get_type(void); /** - * Finds a cipher by it's name - * - * @param name The name of the cipher to find - * - * @return The cipher handle or @c NULL - */ -PurpleCipher *purple_ciphers_find_cipher(const gchar *name); - -/** - * Registers a cipher as a usable cipher - * - * @param name The name of the new cipher - * @param ops The cipher ops to register - * - * @return The handle to the new cipher or @c NULL if it failed - */ -PurpleCipher *purple_ciphers_register_cipher(const gchar *name, PurpleCipherOps *ops); - -/** - * Unregisters a cipher - * - * @param cipher The cipher handle to unregister - * - * @return Whether or not the cipher was successfully unloaded - */ -gboolean purple_ciphers_unregister_cipher(PurpleCipher *cipher); - -/** - * Gets the list of ciphers - * - * @return The list of available ciphers - * @note This list should not be modified, it is owned by the cipher core - */ -GList *purple_ciphers_get_ciphers(void); - -/*@}*/ -/******************************************************************************/ -/** @name PurpleCipher Subsystem API */ -/******************************************************************************/ -/*@{*/ - -/** - * Gets the handle to the cipher subsystem - * - * @return The handle to the cipher subsystem - */ -gpointer purple_ciphers_get_handle(void); - -/** - * Initializes the cipher core - */ -void purple_ciphers_init(void); - -/** - * Uninitializes the cipher core - */ -void purple_ciphers_uninit(void); - -/*@}*/ -/******************************************************************************/ -/** @name PurpleCipherContext API */ -/******************************************************************************/ -/*@{*/ - -/** - * Sets the value an option on a cipher context - * - * @param context The cipher context - * @param name The name of the option - * @param value The value to set - */ -void purple_cipher_context_set_option(PurpleCipherContext *context, const gchar *name, gpointer value); - -/** - * Gets the vale of an option on a cipher context - * - * @param context The cipher context - * @param name The name of the option - * @return The value of the option - */ -gpointer purple_cipher_context_get_option(PurpleCipherContext *context, const gchar *name); - -/** - * Creates a new cipher context and initializes it - * - * @param cipher The cipher to use - * @param extra Extra data for the specific cipher - * - * @return The new cipher context - */ -PurpleCipherContext *purple_cipher_context_new(PurpleCipher *cipher, void *extra); - -/** - * Creates a new cipher context by the cipher name and initializes it + * Gets a cipher's name * - * @param name The cipher's name - * @param extra Extra data for the specific cipher + * @param cipher The cipher * - * @return The new cipher context + * @return The cipher's name */ -PurpleCipherContext *purple_cipher_context_new_by_name(const gchar *name, void *extra); +const gchar *purple_cipher_get_name(PurpleCipher *cipher); /** - * Resets a cipher context to it's default value + * Resets a cipher to it's default value * @note If you have set an IV you will have to set it after resetting * - * @param context The context to reset - * @param extra Extra data for the specific cipher + * @param cipher The cipher */ -void purple_cipher_context_reset(PurpleCipherContext *context, gpointer extra); +void purple_cipher_reset(PurpleCipher *cipher); /** * Resets a cipher state to it's default value, but doesn't touch stateless * configuration. * - * That means, IV and digest context will be wiped out, but keys, ops or salt + * That means, IV and digest will be wiped out, but keys, ops or salt * will remain untouched. * - * @param context The context to reset - * @param extra Extra data for the specific cipher - */ -void purple_cipher_context_reset_state(PurpleCipherContext *context, gpointer extra); - -/** - * Destorys a cipher context and deinitializes it - * - * @param context The cipher context to destory + * @param cipher The cipher */ -void purple_cipher_context_destroy(PurpleCipherContext *context); +void purple_cipher_reset_state(PurpleCipher *cipher); /** - * Sets the initialization vector for a context - * @note This should only be called right after a cipher context is created or reset + * Sets the initialization vector for a cipher + * @note This should only be called right after a cipher is created or reset * - * @param context The context to set the IV to + * @param cipher The cipher * @param iv The initialization vector to set * @param len The len of the IV */ -void purple_cipher_context_set_iv(PurpleCipherContext *context, guchar *iv, size_t len); +void purple_cipher_set_iv(PurpleCipher *cipher, guchar *iv, size_t len); /** - * Appends data to the context + * Appends data to the cipher context * - * @param context The context to append data to + * @param cipher The cipher * @param data The data to append * @param len The length of the data */ -void purple_cipher_context_append(PurpleCipherContext *context, const guchar *data, size_t len); +void purple_cipher_append(PurpleCipher *cipher, const guchar *data, size_t len); /** - * Digests a context + * Digests a cipher context * - * @param context The context to digest + * @param cipher The cipher * @param digest The return buffer for the digest * @param len The length of the buffer */ -gboolean purple_cipher_context_digest(PurpleCipherContext *context, guchar digest[], size_t len); +gboolean purple_cipher_digest(PurpleCipher *cipher, guchar digest[], size_t len); /** * Converts a guchar digest into a hex string * - * @param context The context to get a digest from + * @param cipher The cipher * @param digest_s The return buffer for the string digest * @param len The length of the buffer */ -gboolean purple_cipher_context_digest_to_str(PurpleCipherContext *context, gchar digest_s[], size_t len); +gboolean purple_cipher_digest_to_str(PurpleCipher *cipher, gchar digest_s[], size_t len); /** - * Gets the digest size of a context + * Gets the digest size of a cipher * - * @param context The context whose digest size to get + * @param cipher The cipher whose digest size to get * - * @return The digest size of the context + * @return The digest size of the cipher */ -size_t purple_cipher_context_get_digest_size(PurpleCipherContext *context); +size_t purple_cipher_get_digest_size(PurpleCipher *cipher); /** - * Encrypts data using the context + * Encrypts data using the cipher * - * @param context The context + * @param cipher The cipher * @param input The data to encrypt * @param in_len The length of the data * @param output The output buffer @@ -371,12 +222,12 @@ size_t purple_cipher_context_get_digest_size(PurpleCipherContext *context); * * @return A length of data that was outputed or -1, if failed */ -ssize_t purple_cipher_context_encrypt(PurpleCipherContext *context, const guchar input[], size_t in_len, guchar output[], size_t out_size); +ssize_t purple_cipher_encrypt(PurpleCipher *cipher, const guchar input[], size_t in_len, guchar output[], size_t out_size); /** - * Decrypts data using the context + * Decrypts data using the cipher * - * @param context The context + * @param cipher The cipher * @param input The data to encrypt * @param in_len The length of the returned value * @param output The output buffer @@ -384,135 +235,61 @@ ssize_t purple_cipher_context_encrypt(PurpleCipherContext *context, const guchar * * @return A length of data that was outputed or -1, if failed */ -ssize_t purple_cipher_context_decrypt(PurpleCipherContext *context, const guchar input[], size_t in_len, guchar output[], size_t out_size); +ssize_t purple_cipher_decrypt(PurpleCipher *cipher, const guchar input[], size_t in_len, guchar output[], size_t out_size); /** - * Sets the salt on a context + * Sets the salt on a cipher * - * @param context The context whose salt to set + * @param cipher The cipher whose salt to set * @param salt The salt * @param len The length of the salt */ -void purple_cipher_context_set_salt(PurpleCipherContext *context, const guchar *salt, size_t len); +void purple_cipher_set_salt(PurpleCipher *cipher, const guchar *salt, size_t len); /** - * Gets the size of the salt if the cipher supports it - * - * @param context The context whose salt size to get + * Sets the key on a cipher * - * @return The size of the salt - */ -size_t purple_cipher_context_get_salt_size(PurpleCipherContext *context); - -/** - * Sets the key on a context - * - * @param context The context whose key to set + * @param cipher The cipher whose key to set * @param key The key * @param len The size of the key */ -void purple_cipher_context_set_key(PurpleCipherContext *context, const guchar *key, size_t len); +void purple_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len); /** * Gets the size of the key if the cipher supports it * - * @param context The context whose key size to get + * @param cipher The cipher whose key size to get * * @return The size of the key */ -size_t purple_cipher_context_get_key_size(PurpleCipherContext *context); +size_t purple_cipher_get_key_size(PurpleCipher *cipher); /** - * Sets the batch mode of a context + * Sets the batch mode of a cipher * - * @param context The context whose batch mode to set + * @param cipher The cipher whose batch mode to set * @param mode The batch mode under which the cipher should operate * */ -void purple_cipher_context_set_batch_mode(PurpleCipherContext *context, PurpleCipherBatchMode mode); +void purple_cipher_set_batch_mode(PurpleCipher *cipher, PurpleCipherBatchMode mode); /** - * Gets the batch mode of a context + * Gets the batch mode of a cipher * - * @param context The context whose batch mode to get + * @param cipher The cipher whose batch mode to get * * @return The batch mode under which the cipher is operating */ -PurpleCipherBatchMode purple_cipher_context_get_batch_mode(PurpleCipherContext *context); - -/** - * Gets the block size of a context - * - * @param context The context whose block size to get - * - * @return The block size of the context - */ -size_t purple_cipher_context_get_block_size(PurpleCipherContext *context); +PurpleCipherBatchMode purple_cipher_get_batch_mode(PurpleCipher *cipher); /** - * Sets the cipher data for a context + * Gets the block size of a cipher * - * @param context The context whose cipher data to set - * @param data The cipher data to set - */ -void purple_cipher_context_set_data(PurpleCipherContext *context, gpointer data); - -/** - * Gets the cipher data for a context + * @param cipher The cipher whose block size to get * - * @param context The context whose cipher data to get - * - * @return The cipher data - */ -gpointer purple_cipher_context_get_data(PurpleCipherContext *context); - -/*@}*/ -/*****************************************************************************/ -/** @name Purple Cipher HTTP Digest Helper Functions */ -/*****************************************************************************/ -/*@{*/ - -/** - * Calculates a session key for HTTP Digest authentation - * - * See RFC 2617 for more information. - * - * @param algorithm The hash algorithm to use - * @param username The username provided by the user - * @param realm The authentication realm provided by the server - * @param password The password provided by the user - * @param nonce The nonce provided by the server - * @param client_nonce The nonce provided by the client - * - * @return The session key, or @c NULL if an error occurred. - */ -gchar *purple_cipher_http_digest_calculate_session_key( - const gchar *algorithm, const gchar *username, - const gchar *realm, const gchar *password, - const gchar *nonce, const gchar *client_nonce); - -/** Calculate a response for HTTP Digest authentication - * - * See RFC 2617 for more information. - * - * @param algorithm The hash algorithm to use - * @param method The HTTP method in use - * @param digest_uri The URI from the initial request - * @param qop The "quality of protection" - * @param entity The entity body - * @param nonce The nonce provided by the server - * @param nonce_count The nonce count - * @param client_nonce The nonce provided by the client - * @param session_key The session key from purple_cipher_http_digest_calculate_session_key() - * - * @return The hashed response, or @c NULL if an error occurred. + * @return The block size of the cipher */ -gchar *purple_cipher_http_digest_calculate_response( - const gchar *algorithm, const gchar *method, - const gchar *digest_uri, const gchar *qop, - const gchar *entity, const gchar *nonce, - const gchar *nonce_count, const gchar *client_nonce, - const gchar *session_key); +size_t purple_cipher_get_block_size(PurpleCipher *cipher); /*@}*/ diff --git a/libpurple/ciphers/Makefile.am b/libpurple/ciphers/Makefile.am index aa27bf9450..40a6cf8c7a 100644 --- a/libpurple/ciphers/Makefile.am +++ b/libpurple/ciphers/Makefile.am @@ -1,24 +1,23 @@ noinst_LTLIBRARIES=libpurple-ciphers.la -# XXX: cipher.lo won't be updated after a change in cipher files if USE_NSS -AES_SOURCE = aes.c +AES_SOURCE = aescipher.c endif if USE_GNUTLS -AES_SOURCE = aes.c +AES_SOURCE = aescipher.c endif libpurple_ciphers_la_SOURCES=\ $(AES_SOURCE) \ - des.c \ - gchecksum.c \ - hmac.c \ - md4.c \ - pbkdf2.c \ - rc4.c - -noinst_HEADERS =\ - ciphers.h + descipher.c \ + des3cipher.c \ + hmaccipher.c \ + md4hash.c \ + md5hash.c \ + pbkdf2cipher.c \ + rc4cipher.c \ + sha1hash.c \ + sha256hash.c AM_CPPFLAGS = \ -I$(top_srcdir)/libpurple \ diff --git a/libpurple/ciphers/aes.c b/libpurple/ciphers/aes.c deleted file mode 100644 index f085fc5d7b..0000000000 --- a/libpurple/ciphers/aes.c +++ /dev/null @@ -1,564 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - * - * Written by Tomek Wasilczyk <tomkiewicz@cpw.pidgin.im> - */ - -#include "internal.h" -#include "cipher.h" -#include "ciphers.h" -#include "debug.h" - -#if defined(HAVE_GNUTLS) -# define PURPLE_AES_USE_GNUTLS 1 -# include <gnutls/gnutls.h> -# include <gnutls/crypto.h> -#elif defined(HAVE_NSS) -# define PURPLE_AES_USE_NSS 1 -# include <nss.h> -# include <pk11pub.h> -# include <prerror.h> -#else -# error "No GnuTLS or NSS support" -#endif - -/* 128bit */ -#define PURPLE_AES_BLOCK_SIZE 16 - -typedef struct -{ - guchar iv[PURPLE_AES_BLOCK_SIZE]; - guchar key[32]; - guint key_size; - gboolean failure; -} AESContext; - -typedef gboolean (*purple_aes_crypt_func)( - const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size); - -static void -purple_aes_init(PurpleCipherContext *context, void *extra) -{ - AESContext *ctx_data; - - ctx_data = g_new0(AESContext, 1); - purple_cipher_context_set_data(context, ctx_data); - - purple_cipher_context_reset(context, extra); -} - -static void -purple_aes_uninit(PurpleCipherContext *context) -{ - AESContext *ctx_data; - - purple_cipher_context_reset(context, NULL); - - ctx_data = purple_cipher_context_get_data(context); - g_free(ctx_data); - purple_cipher_context_set_data(context, NULL); -} - -static void -purple_aes_reset(PurpleCipherContext *context, void *extra) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - - g_return_if_fail(ctx_data != NULL); - - memset(ctx_data->iv, 0, sizeof(ctx_data->iv)); - memset(ctx_data->key, 0, sizeof(ctx_data->key)); - ctx_data->key_size = 32; /* 256bit */ - ctx_data->failure = FALSE; -} - -static void -purple_aes_set_option(PurpleCipherContext *context, const gchar *name, - void *value) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - - purple_debug_error("cipher-aes", "set_option not supported\n"); - ctx_data->failure = TRUE; -} - -static void -purple_aes_set_iv(PurpleCipherContext *context, guchar *iv, size_t len) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - - if ((len > 0 && iv == NULL) || - (len != 0 && len != sizeof(ctx_data->iv))) { - purple_debug_error("cipher-aes", "invalid IV length\n"); - ctx_data->failure = TRUE; - return; - } - - if (len == 0) - memset(ctx_data->iv, 0, sizeof(ctx_data->iv)); - else - memcpy(ctx_data->iv, iv, len); -} - -static void -purple_aes_set_key(PurpleCipherContext *context, const guchar *key, size_t len) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - - if ((len > 0 && key == NULL) || - (len != 0 && len != 16 && len != 24 && len != 32)) { - purple_debug_error("cipher-aes", "invalid key length\n"); - ctx_data->failure = TRUE; - return; - } - - ctx_data->key_size = len; - memset(ctx_data->key, 0, sizeof(ctx_data->key)); - if (len > 0) - memcpy(ctx_data->key, key, len); -} - -static guchar * -purple_aes_pad_pkcs7(const guchar input[], size_t in_len, size_t *out_len) -{ - int padding_len, total_len; - guchar *padded; - - g_return_val_if_fail(input != NULL, NULL); - g_return_val_if_fail(out_len != NULL, NULL); - - padding_len = PURPLE_AES_BLOCK_SIZE - (in_len % PURPLE_AES_BLOCK_SIZE); - total_len = in_len + padding_len; - g_assert((total_len % PURPLE_AES_BLOCK_SIZE) == 0); - - padded = g_new(guchar, total_len); - *out_len = total_len; - - memcpy(padded, input, in_len); - memset(padded + in_len, padding_len, padding_len); - - return padded; -} - -static ssize_t -purple_aes_unpad_pkcs7(guchar input[], size_t in_len) -{ - guchar padding_len, i; - size_t out_len; - - g_return_val_if_fail(input != NULL, -1); - g_return_val_if_fail(in_len > 0, -1); - - padding_len = input[in_len - 1]; - if (padding_len == 0 || padding_len > PURPLE_AES_BLOCK_SIZE || - padding_len > in_len) { - purple_debug_warning("cipher-aes", - "Invalid padding length: %d (total %" G_GSIZE_FORMAT ") - " - "most probably, the key was invalid\n", - padding_len, in_len); - return -1; - } - - out_len = in_len - padding_len; - for (i = 0; i < padding_len; i++) { - if (input[out_len + i] != padding_len) { - purple_debug_warning("cipher-aes", - "Padding doesn't match at pos %d (found %02x, " - "expected %02x) - " - "most probably, the key was invalid\n", - i, input[out_len + i], padding_len); - return -1; - } - } - - memset(input + out_len, 0, padding_len); - return out_len; -} - -#ifdef PURPLE_AES_USE_GNUTLS - -static gnutls_cipher_hd_t -purple_aes_crypt_gnutls_init(guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], - guint key_size) -{ - gnutls_cipher_hd_t handle; - gnutls_cipher_algorithm_t algorithm; - gnutls_datum_t key_info, iv_info; - int ret; - - if (key_size == 16) - algorithm = GNUTLS_CIPHER_AES_128_CBC; - else if (key_size == 24) - algorithm = GNUTLS_CIPHER_AES_192_CBC; - else if (key_size == 32) - algorithm = GNUTLS_CIPHER_AES_256_CBC; - else - g_return_val_if_reached(NULL); - - key_info.data = key; - key_info.size = key_size; - - iv_info.data = iv; - iv_info.size = PURPLE_AES_BLOCK_SIZE; - - ret = gnutls_cipher_init(&handle, algorithm, &key_info, &iv_info); - if (ret != 0) { - purple_debug_error("cipher-aes", - "gnutls_cipher_init failed: %d\n", ret); - return NULL; - } - - return handle; -} - -static gboolean -purple_aes_encrypt_gnutls(const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) -{ - gnutls_cipher_hd_t handle; - int ret; - - handle = purple_aes_crypt_gnutls_init(iv, key, key_size); - if (handle == NULL) - return FALSE; - - ret = gnutls_cipher_encrypt2(handle, (void *)input, len, output, len); - gnutls_cipher_deinit(handle); - - if (ret != 0) { - purple_debug_error("cipher-aes", - "gnutls_cipher_encrypt2 failed: %d\n", ret); - return FALSE; - } - - return TRUE; -} - -static gboolean -purple_aes_decrypt_gnutls(const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) -{ - gnutls_cipher_hd_t handle; - int ret; - - handle = purple_aes_crypt_gnutls_init(iv, key, key_size); - if (handle == NULL) - return FALSE; - - ret = gnutls_cipher_decrypt2(handle, input, len, output, len); - gnutls_cipher_deinit(handle); - - if (ret != 0) { - purple_debug_error("cipher-aes", - "gnutls_cipher_decrypt2 failed: %d\n", ret); - return FALSE; - } - - return TRUE; -} - -#elif defined(PURPLE_AES_USE_NSS) - -typedef struct -{ - PK11SlotInfo *slot; - PK11SymKey *sym_key; - SECItem *sec_param; - PK11Context *enc_context; -} purple_aes_encrypt_nss_context; - -static void -purple_aes_encrypt_nss_context_cleanup(purple_aes_encrypt_nss_context *ctx) -{ - g_return_if_fail(ctx != NULL); - - if (ctx->enc_context != NULL) - PK11_DestroyContext(ctx->enc_context, TRUE); - if (ctx->sec_param != NULL) - SECITEM_FreeItem(ctx->sec_param, TRUE); - if (ctx->sym_key != NULL) - PK11_FreeSymKey(ctx->sym_key); - if (ctx->slot != NULL) - PK11_FreeSlot(ctx->slot); - - memset(ctx, 0, sizeof(purple_aes_encrypt_nss_context)); -} - -static gboolean -purple_aes_crypt_nss(const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size, - CK_ATTRIBUTE_TYPE operation) -{ - purple_aes_encrypt_nss_context ctx; - CK_MECHANISM_TYPE cipher_mech = CKM_AES_CBC; - SECItem key_item, iv_item; - SECStatus ret; - int outlen = 0; - unsigned int outlen_tmp = 0; - - memset(&ctx, 0, sizeof(purple_aes_encrypt_nss_context)); - - if (NSS_NoDB_Init(NULL) != SECSuccess) { - purple_debug_error("cipher-aes", - "NSS_NoDB_Init failed: %d\n", PR_GetError()); - return FALSE; - } - - ctx.slot = PK11_GetBestSlot(cipher_mech, NULL); - if (ctx.slot == NULL) { - purple_debug_error("cipher-aes", - "PK11_GetBestSlot failed: %d\n", PR_GetError()); - return FALSE; - } - - key_item.type = siBuffer; - key_item.data = key; - key_item.len = key_size; - ctx.sym_key = PK11_ImportSymKey(ctx.slot, cipher_mech, - PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); - if (ctx.sym_key == NULL) { - purple_debug_error("cipher-aes", - "PK11_ImportSymKey failed: %d\n", PR_GetError()); - purple_aes_encrypt_nss_context_cleanup(&ctx); - return FALSE; - } - - iv_item.type = siBuffer; - iv_item.data = iv; - iv_item.len = PURPLE_AES_BLOCK_SIZE; - ctx.sec_param = PK11_ParamFromIV(cipher_mech, &iv_item); - if (ctx.sec_param == NULL) { - purple_debug_error("cipher-aes", - "PK11_ParamFromIV failed: %d\n", PR_GetError()); - purple_aes_encrypt_nss_context_cleanup(&ctx); - return FALSE; - } - - ctx.enc_context = PK11_CreateContextBySymKey(cipher_mech, operation, - ctx.sym_key, ctx.sec_param); - if (ctx.enc_context == NULL) { - purple_debug_error("cipher-aes", - "PK11_CreateContextBySymKey failed: %d\n", - PR_GetError()); - purple_aes_encrypt_nss_context_cleanup(&ctx); - return FALSE; - } - - ret = PK11_CipherOp(ctx.enc_context, output, &outlen, len, input, len); - if (ret != SECSuccess) { - purple_debug_error("cipher-aes", - "PK11_CipherOp failed: %d\n", PR_GetError()); - purple_aes_encrypt_nss_context_cleanup(&ctx); - return FALSE; - } - - ret = PK11_DigestFinal(ctx.enc_context, output + outlen, &outlen_tmp, - len - outlen); - if (ret != SECSuccess) { - purple_debug_error("cipher-aes", - "PK11_DigestFinal failed: %d\n", PR_GetError()); - purple_aes_encrypt_nss_context_cleanup(&ctx); - return FALSE; - } - - purple_aes_encrypt_nss_context_cleanup(&ctx); - - outlen += outlen_tmp; - if (outlen != len) { - purple_debug_error("cipher-aes", - "resulting length doesn't match: %d (expected: %d)\n", - outlen, len); - return FALSE; - } - - return TRUE; -} - -static gboolean -purple_aes_encrypt_nss(const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) -{ - return purple_aes_crypt_nss(input, output, len, iv, key, key_size, - CKA_ENCRYPT); -} - -static gboolean -purple_aes_decrypt_nss(const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) -{ - return purple_aes_crypt_nss(input, output, len, iv, key, key_size, - CKA_DECRYPT); -} - -#endif /* PURPLE_AES_USE_NSS */ - -static ssize_t -purple_aes_encrypt(PurpleCipherContext *context, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - purple_aes_crypt_func encrypt_func; - guchar *input_padded; - size_t out_len = 0; - gboolean succ; - - if (ctx_data->failure) - return -1; - - input_padded = purple_aes_pad_pkcs7(input, in_len, &out_len); - - if (out_len > out_size) { - purple_debug_error("cipher-aes", "Output buffer too small\n"); - memset(input_padded, 0, out_len); - g_free(input_padded); - return -1; - } - -#if defined(PURPLE_AES_USE_GNUTLS) - encrypt_func = purple_aes_encrypt_gnutls; -#elif defined(PURPLE_AES_USE_NSS) - encrypt_func = purple_aes_encrypt_nss; -#else -# error "No matching encrypt_func" -#endif - - succ = encrypt_func(input_padded, output, out_len, ctx_data->iv, - ctx_data->key, ctx_data->key_size); - - memset(input_padded, 0, out_len); - g_free(input_padded); - - if (!succ) { - memset(output, 0, out_len); - return -1; - } - - return out_len; -} - -static ssize_t -purple_aes_decrypt(PurpleCipherContext *context, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - purple_aes_crypt_func decrypt_func; - gboolean succ; - ssize_t out_len; - - if (ctx_data->failure) - return -1; - - if (in_len > out_size) { - purple_debug_error("cipher-aes", "Output buffer too small\n"); - return -1; - } - - if ((in_len % PURPLE_AES_BLOCK_SIZE) != 0 || in_len == 0) { - purple_debug_error("cipher-aes", "Malformed data\n"); - return -1; - } - -#if defined(PURPLE_AES_USE_GNUTLS) - decrypt_func = purple_aes_decrypt_gnutls; -#elif defined(PURPLE_AES_USE_NSS) - decrypt_func = purple_aes_decrypt_nss; -#else -# error "No matching encrypt_func" -#endif - - succ = decrypt_func(input, output, in_len, ctx_data->iv, ctx_data->key, - ctx_data->key_size); - - if (!succ) { - memset(output, 0, in_len); - return -1; - } - - out_len = purple_aes_unpad_pkcs7(output, in_len); - if (out_len < 0) { - memset(output, 0, in_len); - return -1; - } - - return out_len; -} - -static size_t -purple_aes_get_key_size(PurpleCipherContext *context) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - - return ctx_data->key_size; -} - -static void -purple_aes_set_batch_mode(PurpleCipherContext *context, - PurpleCipherBatchMode mode) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - - if (mode == PURPLE_CIPHER_BATCH_MODE_CBC) - return; - - purple_debug_error("cipher-aes", "unsupported batch mode\n"); - ctx_data->failure = TRUE; -} - -static PurpleCipherBatchMode -purple_aes_get_batch_mode(PurpleCipherContext *context) -{ - return PURPLE_CIPHER_BATCH_MODE_CBC; -} - -static size_t -purple_aes_get_block_size(PurpleCipherContext *context) -{ - return PURPLE_AES_BLOCK_SIZE; -} - -static PurpleCipherOps AESOps = { - purple_aes_set_option, /* set_option */ - NULL, /* get_option */ - purple_aes_init, /* init */ - purple_aes_reset, /* reset */ - NULL, /* reset_state */ - purple_aes_uninit, /* uninit */ - purple_aes_set_iv, /* set_iv */ - NULL, /* append */ - NULL, /* digest */ - NULL, /* get_digest_size */ - purple_aes_encrypt, /* encrypt */ - purple_aes_decrypt, /* decrypt */ - NULL, /* set_salt */ - NULL, /* get_salt_size */ - purple_aes_set_key, /* set_key */ - purple_aes_get_key_size, /* get_key_size */ - purple_aes_set_batch_mode, /* set_batch_mode */ - purple_aes_get_batch_mode, /* get_batch_mode */ - purple_aes_get_block_size, /* get_block_size */ - NULL, NULL, NULL, NULL /* reserved */ -}; - -PurpleCipherOps * -purple_aes_cipher_get_ops(void) { - return &AESOps; -} diff --git a/libpurple/ciphers/aescipher.c b/libpurple/ciphers/aescipher.c new file mode 100644 index 0000000000..e21e3b7fb7 --- /dev/null +++ b/libpurple/ciphers/aescipher.c @@ -0,0 +1,657 @@ +/* + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + * Written by Tomek Wasilczyk <tomkiewicz@cpw.pidgin.im> + */ + +#include "aescipher.h" +#include "debug.h" +#include "enums.h" + +#include <string.h> + +#if defined(HAVE_GNUTLS) +# define PURPLE_AES_USE_GNUTLS 1 +# include <gnutls/gnutls.h> +# include <gnutls/crypto.h> +#elif defined(HAVE_NSS) +# define PURPLE_AES_USE_NSS 1 +# include <nss.h> +# include <pk11pub.h> +# include <prerror.h> +#else +# error "No GnuTLS or NSS support" +#endif + +/* 128bit */ +#define PURPLE_AES_BLOCK_SIZE 16 + +/****************************************************************************** + * Structs + *****************************************************************************/ +#define PURPLE_AES_CIPHER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_AES_CIPHER, PurpleAESCipherPrivate)) + +typedef struct { + guchar iv[PURPLE_AES_BLOCK_SIZE]; + guchar key[32]; + guint key_size; + gboolean failure; +} PurpleAESCipherPrivate; + +/****************************************************************************** + * Enums + *****************************************************************************/ +enum { + PROP_NONE, + PROP_BATCH_MODE, + PROP_IV, + PROP_KEY, + PROP_LAST, +}; + +/****************************************************************************** + * Cipher Stuff + *****************************************************************************/ + +typedef gboolean (*purple_aes_cipher_crypt_func)( + const guchar *input, guchar *output, size_t len, + guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size); + +static void +purple_aes_cipher_reset(PurpleCipher *cipher) +{ + PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); + + g_return_if_fail(priv != NULL); + + memset(priv->iv, 0, sizeof(priv->iv)); + memset(priv->key, 0, sizeof(priv->key)); + priv->key_size = 32; /* 256bit */ + priv->failure = FALSE; +} + +static void +purple_aes_cipher_set_iv(PurpleCipher *cipher, guchar *iv, size_t len) +{ + PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); + + if ((len > 0 && iv == NULL) || + (len != 0 && len != sizeof(priv->iv))) { + purple_debug_error("cipher-aes", "invalid IV length\n"); + priv->failure = TRUE; + return; + } + + if (len == 0) + memset(priv->iv, 0, sizeof(priv->iv)); + else + memcpy(priv->iv, iv, len); + + g_object_notify(G_OBJECT(cipher), "iv"); +} + +static void +purple_aes_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) +{ + PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); + + if ((len > 0 && key == NULL) || + (len != 0 && len != 16 && len != 24 && len != 32)) { + purple_debug_error("cipher-aes", "invalid key length\n"); + priv->failure = TRUE; + return; + } + + priv->key_size = len; + memset(priv->key, 0, sizeof(priv->key)); + if (len > 0) + memcpy(priv->key, key, len); + + g_object_notify(G_OBJECT(cipher), "key"); +} + +static guchar * +purple_aes_cipher_pad_pkcs7(const guchar input[], size_t in_len, size_t *out_len) +{ + int padding_len, total_len; + guchar *padded; + + g_return_val_if_fail(input != NULL, NULL); + g_return_val_if_fail(out_len != NULL, NULL); + + padding_len = PURPLE_AES_BLOCK_SIZE - (in_len % PURPLE_AES_BLOCK_SIZE); + total_len = in_len + padding_len; + g_assert((total_len % PURPLE_AES_BLOCK_SIZE) == 0); + + padded = g_new(guchar, total_len); + *out_len = total_len; + + memcpy(padded, input, in_len); + memset(padded + in_len, padding_len, padding_len); + + return padded; +} + +static ssize_t +purple_aes_cipher_unpad_pkcs7(guchar input[], size_t in_len) +{ + guchar padding_len, i; + size_t out_len; + + g_return_val_if_fail(input != NULL, -1); + g_return_val_if_fail(in_len > 0, -1); + + padding_len = input[in_len - 1]; + if (padding_len == 0 || padding_len > PURPLE_AES_BLOCK_SIZE || + padding_len > in_len) { + purple_debug_warning("cipher-aes", + "Invalid padding length: %d (total %" G_GSIZE_FORMAT ") - " + "most probably, the key was invalid\n", + padding_len, in_len); + return -1; + } + + out_len = in_len - padding_len; + for (i = 0; i < padding_len; i++) { + if (input[out_len + i] != padding_len) { + purple_debug_warning("cipher-aes", + "Padding doesn't match at pos %d (found %02x, " + "expected %02x) - " + "most probably, the key was invalid\n", + i, input[out_len + i], padding_len); + return -1; + } + } + + memset(input + out_len, 0, padding_len); + return out_len; +} + +#ifdef PURPLE_AES_USE_GNUTLS + +static gnutls_cipher_hd_t +purple_aes_cipher_gnutls_crypt_init(guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], + guint key_size) +{ + gnutls_cipher_hd_t handle; + gnutls_cipher_algorithm_t algorithm; + gnutls_datum_t key_info, iv_info; + int ret; + + if (key_size == 16) + algorithm = GNUTLS_CIPHER_AES_128_CBC; + else if (key_size == 24) + algorithm = GNUTLS_CIPHER_AES_192_CBC; + else if (key_size == 32) + algorithm = GNUTLS_CIPHER_AES_256_CBC; + else + g_return_val_if_reached(NULL); + + key_info.data = key; + key_info.size = key_size; + + iv_info.data = iv; + iv_info.size = PURPLE_AES_BLOCK_SIZE; + + ret = gnutls_cipher_init(&handle, algorithm, &key_info, &iv_info); + if (ret != 0) { + purple_debug_error("cipher-aes", + "gnutls_cipher_init failed: %d\n", ret); + return NULL; + } + + return handle; +} + +static gboolean +purple_aes_cipher_gnutls_encrypt(const guchar *input, guchar *output, size_t len, + guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) +{ + gnutls_cipher_hd_t handle; + int ret; + + handle = purple_aes_cipher_gnutls_crypt_init(iv, key, key_size); + if (handle == NULL) + return FALSE; + + ret = gnutls_cipher_encrypt2(handle, (guchar *)input, len, output, len); + gnutls_cipher_deinit(handle); + + if (ret != 0) { + purple_debug_error("cipher-aes", + "gnutls_cipher_encrypt2 failed: %d\n", ret); + return FALSE; + } + + return TRUE; +} + +static gboolean +purple_aes_cipher_gnutls_decrypt(const guchar *input, guchar *output, size_t len, + guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) +{ + gnutls_cipher_hd_t handle; + int ret; + + handle = purple_aes_cipher_gnutls_crypt_init(iv, key, key_size); + if (handle == NULL) + return FALSE; + + ret = gnutls_cipher_decrypt2(handle, input, len, output, len); + gnutls_cipher_deinit(handle); + + if (ret != 0) { + purple_debug_error("cipher-aes", + "gnutls_cipher_decrypt2 failed: %d\n", ret); + return FALSE; + } + + return TRUE; +} + +#elif defined(PURPLE_AES_USE_NSS) + +typedef struct { + PK11SlotInfo *slot; + PK11SymKey *sym_key; + SECItem *sec_param; + PK11Context *enc_context; +} PurpleAESCipherNSSContext; + +static void +purple_aes_cipher_nss_cleanup(PurpleAESCipherNSSContext *context) +{ + g_return_if_fail(context != NULL); + + if (context->enc_context != NULL) + PK11_DestroyContext(context->enc_context, TRUE); + if (context->sec_param != NULL) + SECITEM_FreeItem(context->sec_param, TRUE); + if (context->sym_key != NULL) + PK11_FreeSymKey(context->sym_key); + if (context->slot != NULL) + PK11_FreeSlot(context->slot); + + memset(context, 0, sizeof(PurpleAESCipherNSSContext)); +} + +static gboolean +purple_aes_cipher_nss_crypt(const guchar *input, guchar *output, size_t len, + guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size, + CK_ATTRIBUTE_TYPE operation) +{ + PurpleAESCipherNSSContext context; + CK_MECHANISM_TYPE cipher_mech = CKM_AES_CBC; + SECItem key_item, iv_item; + SECStatus ret; + int outlen = 0; + unsigned int outlen_tmp = 0; + + memset(&context, 0, sizeof(PurpleAESCipherNSSContext)); + + if (NSS_NoDB_Init(NULL) != SECSuccess) { + purple_debug_error("cipher-aes", + "NSS_NoDB_Init failed: %d\n", PR_GetError()); + return FALSE; + } + + context.slot = PK11_GetBestSlot(cipher_mech, NULL); + if (context.slot == NULL) { + purple_debug_error("cipher-aes", + "PK11_GetBestSlot failed: %d\n", PR_GetError()); + return FALSE; + } + + key_item.type = siBuffer; + key_item.data = key; + key_item.len = key_size; + context.sym_key = PK11_ImportSymKey(context.slot, cipher_mech, + PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); + if (context.sym_key == NULL) { + purple_debug_error("cipher-aes", + "PK11_ImportSymKey failed: %d\n", PR_GetError()); + purple_aes_cipher_nss_cleanup(&context); + return FALSE; + } + + iv_item.type = siBuffer; + iv_item.data = iv; + iv_item.len = PURPLE_AES_BLOCK_SIZE; + context.sec_param = PK11_ParamFromIV(cipher_mech, &iv_item); + if (context.sec_param == NULL) { + purple_debug_error("cipher-aes", + "PK11_ParamFromIV failed: %d\n", PR_GetError()); + purple_aes_cipher_nss_cleanup(&context); + return FALSE; + } + + context.enc_context = PK11_CreateContextBySymKey(cipher_mech, operation, + context.sym_key, context.sec_param); + if (context.enc_context == NULL) { + purple_debug_error("cipher-aes", + "PK11_CreateContextBySymKey failed: %d\n", + PR_GetError()); + purple_aes_cipher_nss_cleanup(&context); + return FALSE; + } + + ret = PK11_CipherOp(context.enc_context, output, &outlen, len, input, len); + if (ret != SECSuccess) { + purple_debug_error("cipher-aes", + "PK11_CipherOp failed: %d\n", PR_GetError()); + purple_aes_cipher_nss_cleanup(&context); + return FALSE; + } + + ret = PK11_DigestFinal(context.enc_context, output + outlen, &outlen_tmp, + len - outlen); + if (ret != SECSuccess) { + purple_debug_error("cipher-aes", + "PK11_DigestFinal failed: %d\n", PR_GetError()); + purple_aes_cipher_nss_cleanup(&context); + return FALSE; + } + + purple_aes_cipher_nss_cleanup(&context); + + outlen += outlen_tmp; + if (outlen != len) { + purple_debug_error("cipher-aes", + "resulting length doesn't match: %d (expected: %lu)\n", + outlen, len); + return FALSE; + } + + return TRUE; +} + +static gboolean +purple_aes_cipher_nss_encrypt(const guchar *input, guchar *output, size_t len, + guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) +{ + return purple_aes_cipher_nss_crypt(input, output, len, iv, key, key_size, + CKA_ENCRYPT); +} + +static gboolean +purple_aes_cipher_nss_decrypt(const guchar *input, guchar *output, size_t len, + guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) +{ + return purple_aes_cipher_nss_crypt(input, output, len, iv, key, key_size, + CKA_DECRYPT); +} + +#endif /* PURPLE_AES_USE_NSS */ + +static ssize_t +purple_aes_cipher_encrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); + purple_aes_cipher_crypt_func encrypt_func; + guchar *input_padded; + size_t out_len = 0; + gboolean succ; + + if (priv->failure) + return -1; + + input_padded = purple_aes_cipher_pad_pkcs7(input, in_len, &out_len); + + if (out_len > out_size) { + purple_debug_error("cipher-aes", "Output buffer too small\n"); + memset(input_padded, 0, out_len); + g_free(input_padded); + return -1; + } + +#if defined(PURPLE_AES_USE_GNUTLS) + encrypt_func = purple_aes_cipher_gnutls_encrypt; +#elif defined(PURPLE_AES_USE_NSS) + encrypt_func = purple_aes_cipher_nss_encrypt; +#else +# error "No matching encrypt_func" +#endif + + succ = encrypt_func(input_padded, output, out_len, priv->iv, + priv->key, priv->key_size); + + memset(input_padded, 0, out_len); + g_free(input_padded); + + if (!succ) { + memset(output, 0, out_len); + return -1; + } + + return out_len; +} + +static ssize_t +purple_aes_cipher_decrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); + purple_aes_cipher_crypt_func decrypt_func; + gboolean succ; + ssize_t out_len; + + if (priv->failure) + return -1; + + if (in_len > out_size) { + purple_debug_error("cipher-aes", "Output buffer too small\n"); + return -1; + } + + if ((in_len % PURPLE_AES_BLOCK_SIZE) != 0 || in_len == 0) { + purple_debug_error("cipher-aes", "Malformed data\n"); + return -1; + } + +#if defined(PURPLE_AES_USE_GNUTLS) + decrypt_func = purple_aes_cipher_gnutls_decrypt; +#elif defined(PURPLE_AES_USE_NSS) + decrypt_func = purple_aes_cipher_nss_decrypt; +#else +# error "No matching encrypt_func" +#endif + + succ = decrypt_func(input, output, in_len, priv->iv, priv->key, + priv->key_size); + + if (!succ) { + memset(output, 0, in_len); + return -1; + } + + out_len = purple_aes_cipher_unpad_pkcs7(output, in_len); + if (out_len < 0) { + memset(output, 0, in_len); + return -1; + } + + return out_len; +} + +static size_t +purple_aes_cipher_get_key_size(PurpleCipher *cipher) +{ + PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); + + return priv->key_size; +} + +static void +purple_aes_cipher_set_batch_mode(PurpleCipher *cipher, + PurpleCipherBatchMode mode) +{ + PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); + + if (mode == PURPLE_CIPHER_BATCH_MODE_CBC) { + g_object_notify(G_OBJECT(cipher), "batch_mode"); + return; + } + + purple_debug_error("cipher-aes", "unsupported batch mode\n"); + priv->failure = TRUE; +} + +static PurpleCipherBatchMode +purple_aes_cipher_get_batch_mode(PurpleCipher *cipher) +{ + return PURPLE_CIPHER_BATCH_MODE_CBC; +} + +static size_t +purple_aes_cipher_get_block_size(PurpleCipher *cipher) +{ + return PURPLE_AES_BLOCK_SIZE; +} + +static const gchar* +purple_aes_cipher_get_name(PurpleCipher *cipher) +{ + return "aes"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_aes_cipher_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + + switch(param_id) { + case PROP_BATCH_MODE: + g_value_set_enum(value, + purple_cipher_get_batch_mode(cipher)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_aes_cipher_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + + switch(param_id) { + case PROP_BATCH_MODE: + purple_cipher_set_batch_mode(cipher, + g_value_get_enum(value)); + break; + case PROP_IV: + { + guchar *iv = (guchar *)g_value_get_string(value); + purple_cipher_set_iv(cipher, iv, strlen((gchar*)iv)); + } + break; + case PROP_KEY: + purple_cipher_set_key(cipher, (guchar *)g_value_get_string(value), + purple_aes_cipher_get_key_size(cipher)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_aes_cipher_class_init(PurpleAESCipherClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); + GParamSpec *pspec; + + obj_class->get_property = purple_aes_cipher_get_property; + obj_class->set_property = purple_aes_cipher_set_property; + + cipher_class->reset = purple_aes_cipher_reset; + cipher_class->set_iv = purple_aes_cipher_set_iv; + cipher_class->encrypt = purple_aes_cipher_encrypt; + cipher_class->decrypt = purple_aes_cipher_decrypt; + cipher_class->set_key = purple_aes_cipher_set_key; + cipher_class->get_key_size = purple_aes_cipher_get_key_size; + cipher_class->set_batch_mode = purple_aes_cipher_set_batch_mode; + cipher_class->get_batch_mode = purple_aes_cipher_get_batch_mode; + cipher_class->get_block_size = purple_aes_cipher_get_block_size; + cipher_class->get_name = purple_aes_cipher_get_name; + + pspec = g_param_spec_enum("batch_mode", "batch_mode", "batch_mode", + PURPLE_TYPE_CIPHER_BATCH_MODE, 0, + G_PARAM_READWRITE); + g_object_class_install_property(obj_class, PROP_BATCH_MODE, pspec); + + pspec = g_param_spec_string("iv", "iv", "iv", NULL, + G_PARAM_WRITABLE); + g_object_class_install_property(obj_class, PROP_IV, pspec); + + pspec = g_param_spec_string("key", "key", "key", NULL, + G_PARAM_WRITABLE); + g_object_class_install_property(obj_class, PROP_KEY, pspec); + + g_type_class_add_private(klass, sizeof(PurpleAESCipherPrivate)); +} + +static void +purple_aes_cipher_init(PurpleCipher *cipher) { + purple_cipher_reset(cipher); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_aes_cipher_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleAESCipherClass), + NULL, + NULL, + (GClassInitFunc)purple_aes_cipher_class_init, + NULL, + NULL, + sizeof(PurpleAESCipher), + 0, + (GInstanceInitFunc)purple_aes_cipher_init, + NULL + }; + + type = g_type_register_static(PURPLE_TYPE_CIPHER, + "PurpleAESCipher", + &info, 0); + } + + return type; +} + +PurpleCipher * +purple_aes_cipher_new(void) { + return g_object_new(PURPLE_TYPE_AES_CIPHER, NULL); +} diff --git a/libpurple/ciphers/aescipher.h b/libpurple/ciphers/aescipher.h new file mode 100644 index 0000000000..99420585a8 --- /dev/null +++ b/libpurple/ciphers/aescipher.h @@ -0,0 +1,64 @@ +/** + * @file aes.h Purple AES Cipher + * @ingroup core + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef PURPLE_AES_CIPHER_H +#define PURPLE_AES_CIPHER_H + +#include "cipher.h" + +#define PURPLE_TYPE_AES_CIPHER (purple_aes_cipher_get_gtype()) +#define PURPLE_AES_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_AES_CIPHER, PurpleAESCipher)) +#define PURPLE_AES_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_AES_CIPHER, PurpleAESCipherClass)) +#define PURPLE_IS_AES_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_AES_CIPHER)) +#define PURPLE_IS_AES_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_AES_CIPHER)) +#define PURPLE_AES_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_AES_CIPHER, PurpleAESCipherClass)) + +typedef struct _PurpleAESCipher PurpleAESCipher; +typedef struct _PurpleAESCipherClass PurpleAESCipherClass; + +struct _PurpleAESCipher { + /*< private >*/ + PurpleCipher gparent; +}; + +struct _PurpleAESCipherClass { + /*< private >*/ + PurpleCipherClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_aes_cipher_get_gtype(void); + +PurpleCipher *purple_aes_cipher_new(void); + +G_END_DECLS + +#endif /* PURPLE_AES_CIPHER_H */ diff --git a/libpurple/ciphers/ciphers.h b/libpurple/ciphers/ciphers.h deleted file mode 100644 index f7bb5e2edf..0000000000 --- a/libpurple/ciphers/ciphers.h +++ /dev/null @@ -1,66 +0,0 @@ -/* purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -/* aes.c */ -PurpleCipherOps * purple_aes_cipher_get_ops(void); - -/* des.c */ -PurpleCipherOps * purple_des_cipher_get_ops(void); -PurpleCipherOps * purple_des3_cipher_get_ops(void); - -/* gchecksum.c */ -PurpleCipherOps * purple_md5_cipher_get_ops(void); -PurpleCipherOps * purple_sha1_cipher_get_ops(void); -PurpleCipherOps * purple_sha256_cipher_get_ops(void); - -/* hmac.c */ -PurpleCipherOps * purple_hmac_cipher_get_ops(void); - -/* md4.c */ -PurpleCipherOps * purple_md4_cipher_get_ops(void); - -/* pbkdf2.c */ -PurpleCipherOps * purple_pbkdf2_cipher_get_ops(void); - -/* rc4.c */ -PurpleCipherOps * purple_rc4_cipher_get_ops(void); - -static inline void purple_ciphers_register_all(void) -{ -#if defined(HAVE_GNUTLS) || defined(HAVE_NSS) - purple_ciphers_register_cipher("aes", purple_aes_cipher_get_ops()); -#endif - - purple_ciphers_register_cipher("des", purple_des_cipher_get_ops()); - purple_ciphers_register_cipher("des3", purple_des3_cipher_get_ops()); - - purple_ciphers_register_cipher("md5", purple_md5_cipher_get_ops()); - purple_ciphers_register_cipher("sha1", purple_sha1_cipher_get_ops()); - purple_ciphers_register_cipher("sha256", purple_sha256_cipher_get_ops()); - - purple_ciphers_register_cipher("hmac", purple_hmac_cipher_get_ops()); - - purple_ciphers_register_cipher("md4", purple_md4_cipher_get_ops()); - - purple_ciphers_register_cipher("pbkdf2", purple_pbkdf2_cipher_get_ops()); - - purple_ciphers_register_cipher("rc4", purple_rc4_cipher_get_ops()); -} diff --git a/libpurple/ciphers/des.c b/libpurple/ciphers/des.c deleted file mode 100644 index 51e2da8192..0000000000 --- a/libpurple/ciphers/des.c +++ /dev/null @@ -1,903 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * Original des taken from gpg - * - * des.c - DES and Triple-DES encryption/decryption Algorithm - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * Please see below for more legal information! - * - * According to the definition of DES in FIPS PUB 46-2 from December 1993. - * For a description of triple encryption, see: - * Bruce Schneier: Applied Cryptography. Second Edition. - * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. - * - * This file is part of GnuPG. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#include "internal.h" -#include <cipher.h> -#include "ciphers.h" - -/****************************************************************************** - * DES - *****************************************************************************/ -typedef struct _des_ctx -{ - guint32 encrypt_subkeys[32]; - guint32 decrypt_subkeys[32]; -} des_ctx[1]; - -/* - * The s-box values are permuted according to the 'primitive function P' - */ -static const guint32 sbox1[64] = -{ - 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000, - 0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002, - 0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202, - 0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000, - 0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200, - 0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202, - 0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200, - 0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002 -}; - -static const guint32 sbox2[64] = -{ - 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010, - 0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010, - 0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000, - 0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010, - 0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000, - 0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000, - 0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010, - 0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000 -}; - -static const guint32 sbox3[64] = -{ - 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100, - 0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104, - 0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104, - 0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000, - 0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000, - 0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004, - 0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004, - 0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100 -}; - -static const guint32 sbox4[64] = -{ - 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000, - 0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000, - 0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040, - 0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040, - 0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000, - 0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040, - 0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040, - 0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040 -}; - -static const guint32 sbox5[64] = -{ - 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000, - 0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000, - 0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080, - 0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080, - 0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080, - 0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000, - 0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000, - 0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080 -}; - -static const guint32 sbox6[64] = -{ - 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000, - 0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008, - 0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008, - 0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000, - 0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008, - 0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000, - 0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008, - 0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008 -}; - -static const guint32 sbox7[64] = -{ - 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400, - 0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401, - 0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001, - 0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400, - 0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001, - 0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400, - 0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401, - 0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001 -}; - -static const guint32 sbox8[64] = -{ - 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000, - 0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020, - 0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800, - 0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000, - 0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820, - 0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820, - 0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000, - 0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800 -}; - - -/* - * * These two tables are part of the 'permuted choice 1' function. - * * In this implementation several speed improvements are done. - * */ -static const guint32 leftkey_swap[16] = -{ - 0x00000000, 0x00000001, 0x00000100, 0x00000101, - 0x00010000, 0x00010001, 0x00010100, 0x00010101, - 0x01000000, 0x01000001, 0x01000100, 0x01000101, - 0x01010000, 0x01010001, 0x01010100, 0x01010101 -}; - -static const guint32 rightkey_swap[16] = -{ - 0x00000000, 0x01000000, 0x00010000, 0x01010000, - 0x00000100, 0x01000100, 0x00010100, 0x01010100, - 0x00000001, 0x01000001, 0x00010001, 0x01010001, - 0x00000101, 0x01000101, 0x00010101, 0x01010101, -}; - - -/* - * Numbers of left shifts per round for encryption subkey schedule - * To calculate the decryption key scheduling we just reverse the - * ordering of the subkeys so we can omit the table for decryption - * subkey schedule. - */ -static const guint8 encrypt_rotate_tab[16] = -{ - 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 -}; - -/* - * Macro to swap bits across two words - **/ -#define DO_PERMUTATION(a, temp, b, offset, mask) \ - temp = ((a>>offset) ^ b) & mask; \ - b ^= temp; \ - a ^= temp<<offset; - - -/* - * This performs the 'initial permutation' for the data to be encrypted or decrypted - **/ -#define INITIAL_PERMUTATION(left, temp, right) \ - DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) \ - DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ - DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ - DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ - DO_PERMUTATION(left, temp, right, 1, 0x55555555) - - -/* - * The 'inverse initial permutation' - **/ -#define FINAL_PERMUTATION(left, temp, right) \ - DO_PERMUTATION(left, temp, right, 1, 0x55555555) \ - DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ - DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ - DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ - DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) - - -/* - * A full DES round including 'expansion function', 'sbox substitution' - * and 'primitive function P' but without swapping the left and right word. - **/ -#define DES_ROUND(from, to, work, subkey) \ - work = ((from<<1) | (from>>31)) ^ *subkey++; \ - to ^= sbox8[ work & 0x3f ]; \ - to ^= sbox6[ (work>>8) & 0x3f ]; \ - to ^= sbox4[ (work>>16) & 0x3f ]; \ - to ^= sbox2[ (work>>24) & 0x3f ]; \ - work = ((from>>3) | (from<<29)) ^ *subkey++; \ - to ^= sbox7[ work & 0x3f ]; \ - to ^= sbox5[ (work>>8) & 0x3f ]; \ - to ^= sbox3[ (work>>16) & 0x3f ]; \ - to ^= sbox1[ (work>>24) & 0x3f ]; - - -/* - * Macros to convert 8 bytes from/to 32bit words - **/ -#define READ_64BIT_DATA(data, left, right) \ - left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ - right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; - -#define WRITE_64BIT_DATA(data, left, right) \ - data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \ - data[2] = (left >> 8) &0xff; data[3] = left &0xff; \ - data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ - data[6] = (right >> 8) &0xff; data[7] = right &0xff; - - -/* - * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for - * 16 encryption rounds. - * To calculate subkeys for decryption the caller - * have to reorder the generated subkeys. - * - * rawkey: 8 Bytes of key data - * subkey: Array of at least 32 guint32s. Will be filled - * with calculated subkeys. - * - **/ -static void -des_key_schedule (const guint8 * rawkey, guint32 * subkey) -{ - guint32 left, right, work; - int round; - - READ_64BIT_DATA (rawkey, left, right) - - DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f) - DO_PERMUTATION (right, work, left, 0, 0x10101010) - - left = (leftkey_swap[(left >> 0) & 0xf] << 3) | (leftkey_swap[(left >> 8) & 0xf] << 2) - | (leftkey_swap[(left >> 16) & 0xf] << 1) | (leftkey_swap[(left >> 24) & 0xf]) - | (leftkey_swap[(left >> 5) & 0xf] << 7) | (leftkey_swap[(left >> 13) & 0xf] << 6) - | (leftkey_swap[(left >> 21) & 0xf] << 5) | (leftkey_swap[(left >> 29) & 0xf] << 4); - - left &= 0x0fffffff; - - right = (rightkey_swap[(right >> 1) & 0xf] << 3) | (rightkey_swap[(right >> 9) & 0xf] << 2) - | (rightkey_swap[(right >> 17) & 0xf] << 1) | (rightkey_swap[(right >> 25) & 0xf]) - | (rightkey_swap[(right >> 4) & 0xf] << 7) | (rightkey_swap[(right >> 12) & 0xf] << 6) - | (rightkey_swap[(right >> 20) & 0xf] << 5) | (rightkey_swap[(right >> 28) & 0xf] << 4); - - right &= 0x0fffffff; - - for (round = 0; round < 16; ++round) - { - left = ((left << encrypt_rotate_tab[round]) | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; - right = ((right << encrypt_rotate_tab[round]) | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; - - *subkey++ = ((left << 4) & 0x24000000) - | ((left << 28) & 0x10000000) - | ((left << 14) & 0x08000000) - | ((left << 18) & 0x02080000) - | ((left << 6) & 0x01000000) - | ((left << 9) & 0x00200000) - | ((left >> 1) & 0x00100000) - | ((left << 10) & 0x00040000) - | ((left << 2) & 0x00020000) - | ((left >> 10) & 0x00010000) - | ((right >> 13) & 0x00002000) - | ((right >> 4) & 0x00001000) - | ((right << 6) & 0x00000800) - | ((right >> 1) & 0x00000400) - | ((right >> 14) & 0x00000200) - | (right & 0x00000100) - | ((right >> 5) & 0x00000020) - | ((right >> 10) & 0x00000010) - | ((right >> 3) & 0x00000008) - | ((right >> 18) & 0x00000004) - | ((right >> 26) & 0x00000002) - | ((right >> 24) & 0x00000001); - - *subkey++ = ((left << 15) & 0x20000000) - | ((left << 17) & 0x10000000) - | ((left << 10) & 0x08000000) - | ((left << 22) & 0x04000000) - | ((left >> 2) & 0x02000000) - | ((left << 1) & 0x01000000) - | ((left << 16) & 0x00200000) - | ((left << 11) & 0x00100000) - | ((left << 3) & 0x00080000) - | ((left >> 6) & 0x00040000) - | ((left << 15) & 0x00020000) - | ((left >> 4) & 0x00010000) - | ((right >> 2) & 0x00002000) - | ((right << 8) & 0x00001000) - | ((right >> 14) & 0x00000808) - | ((right >> 9) & 0x00000400) - | ((right) & 0x00000200) - | ((right << 7) & 0x00000100) - | ((right >> 7) & 0x00000020) - | ((right >> 3) & 0x00000011) - | ((right << 2) & 0x00000004) - | ((right >> 21) & 0x00000002); - } -} - - -/* - * Fill a DES context with subkeys calculated from a 64bit key. - * Does not check parity bits, but simply ignore them. - * Does not check for weak keys. - **/ -static void -des_set_key (PurpleCipherContext *context, const guchar * key, size_t len) -{ - struct _des_ctx *ctx = purple_cipher_context_get_data(context); - int i; - - g_return_if_fail(len == 8); - - des_key_schedule (key, ctx->encrypt_subkeys); - - for(i=0; i<32; i+=2) - { - ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; - ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; - } -} - -static size_t -des_get_key_size(PurpleCipherContext *context) -{ - return 8; -} - -/* - * Electronic Codebook Mode DES encryption/decryption of data according - * to 'mode'. - **/ -static int -des_ecb_crypt (struct _des_ctx *ctx, const guint8 * from, guint8 * to, int mode) -{ - guint32 left, right, work; - guint32 *keys; - - keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; - - READ_64BIT_DATA (from, left, right) - INITIAL_PERMUTATION (left, work, right) - - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - - FINAL_PERMUTATION (right, work, left) - WRITE_64BIT_DATA (to, right, left) - - return 0; -} - -static ssize_t -des_encrypt(PurpleCipherContext *context, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - gsize offset = 0; - int i = 0; - gsize tmp; - guint8 buf[8] = {0,0,0,0,0,0,0,0}; - gsize out_len; - - g_return_val_if_fail(out_size >= in_len, -1); - - while(offset+8<=in_len) { - des_ecb_crypt(purple_cipher_context_get_data(context), - input+offset, - output+offset, - 0); - offset+=8; - } - out_len = in_len; - if(offset<in_len) { - g_return_val_if_fail(in_len >= offset, -1); - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - while(tmp<in_len) { - buf[i++] = input[tmp]; - tmp++; - } - des_ecb_crypt(purple_cipher_context_get_data(context), - buf, - output+offset, - 0); - } - return out_len; -} - -static ssize_t -des_decrypt(PurpleCipherContext *context, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - gsize offset = 0; - int i = 0; - gsize tmp; - guint8 buf[8] = {0,0,0,0,0,0,0,0}; - gsize out_len; - - g_return_val_if_fail(out_size >= in_len, -1); - - while(offset+8<=in_len) { - des_ecb_crypt(purple_cipher_context_get_data(context), - input+offset, - output+offset, - 1); - offset+=8; - } - out_len = in_len; - if(offset<in_len) { - g_return_val_if_fail(in_len >= offset, -1); - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - while(tmp<in_len) { - buf[i++] = input[tmp]; - tmp++; - } - des_ecb_crypt(purple_cipher_context_get_data(context), - buf, - output+offset, - 1); - } - return out_len; -} - -static void -des_init(PurpleCipherContext *context, gpointer extra) { - struct _des_ctx *mctx; - mctx = g_new0(struct _des_ctx, 1); - purple_cipher_context_set_data(context, mctx); -} - -static void -des_uninit(PurpleCipherContext *context) { - struct _des_ctx *des_context; - - des_context = purple_cipher_context_get_data(context); - memset(des_context, 0, sizeof(*des_context)); - - g_free(des_context); - des_context = NULL; -} - -static PurpleCipherOps DESOps = { - NULL, /* Set option */ - NULL, /* Get option */ - des_init, /* init */ - NULL, /* reset */ - NULL, /* reset state */ - des_uninit, /* uninit */ - NULL, /* set iv */ - NULL, /* append */ - NULL, /* digest */ - NULL, /* get_digest_size */ - des_encrypt, /* encrypt */ - des_decrypt, /* decrypt */ - NULL, /* set salt */ - NULL, /* get salt size */ - des_set_key, /* set key */ - des_get_key_size, /* get key size */ - NULL, /* set batch mode */ - NULL, /* get batch mode */ - NULL, /* get block size */ - NULL, NULL, NULL, NULL /* reserved */ -}; - -/****************************************************************************** - * Triple-DES - *****************************************************************************/ - -typedef struct _des3_ctx -{ - PurpleCipherBatchMode mode; - guchar iv[8]; - /* First key for encryption */ - struct _des_ctx key1; - /* Second key for decryption */ - struct _des_ctx key2; - /* Third key for encryption */ - struct _des_ctx key3; -} des3_ctx[1]; - -/* - * Fill a DES3 context with subkeys calculated from 3 64bit key. - * Does not check parity bits, but simply ignore them. - * Does not check for weak keys. - **/ -static void -des3_set_key(PurpleCipherContext *context, const guchar * key, size_t len) -{ - struct _des3_ctx *ctx = purple_cipher_context_get_data(context); - int i; - - g_return_if_fail(len == 24); - - des_key_schedule (key + 0, ctx->key1.encrypt_subkeys); - des_key_schedule (key + 8, ctx->key2.encrypt_subkeys); - des_key_schedule (key + 16, ctx->key3.encrypt_subkeys); - - for (i = 0; i < 32; i += 2) - { - ctx->key1.decrypt_subkeys[i] = ctx->key1.encrypt_subkeys[30-i]; - ctx->key1.decrypt_subkeys[i+1] = ctx->key1.encrypt_subkeys[31-i]; - ctx->key2.decrypt_subkeys[i] = ctx->key2.encrypt_subkeys[30-i]; - ctx->key2.decrypt_subkeys[i+1] = ctx->key2.encrypt_subkeys[31-i]; - ctx->key3.decrypt_subkeys[i] = ctx->key3.encrypt_subkeys[30-i]; - ctx->key3.decrypt_subkeys[i+1] = ctx->key3.encrypt_subkeys[31-i]; - } -} - -static size_t -des3_get_key_size(PurpleCipherContext *context) -{ - return 24; -} - -static ssize_t -des3_ecb_encrypt(struct _des3_ctx *ctx, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - gsize offset = 0; - int i = 0; - gsize tmp; - guint8 buf[8] = {0,0,0,0,0,0,0,0}; - gsize out_len; - - g_return_val_if_fail(out_size >= in_len, -1); - - while (offset + 8 <= in_len) { - des_ecb_crypt(&ctx->key1, - input+offset, - output+offset, - 0); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 1); - des_ecb_crypt(&ctx->key3, - buf, - output+offset, - 0); - offset += 8; - } - out_len = in_len; - if (offset < in_len) { - g_return_val_if_fail(in_len >= offset, -1); - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - memset(buf, 0, 8); - while (tmp < in_len) { - buf[i++] = input[tmp]; - tmp++; - } - des_ecb_crypt(&ctx->key1, - buf, - output+offset, - 0); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 1); - des_ecb_crypt(&ctx->key3, - buf, - output+offset, - 0); - } - return out_len; -} - -static ssize_t -des3_cbc_encrypt(struct _des3_ctx *ctx, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - gsize offset = 0; - int i = 0; - gsize tmp; - guint8 buf[8]; - gsize out_len; - memcpy(buf, ctx->iv, 8); - - g_return_val_if_fail(out_size >= in_len, -1); - - while (offset + 8 <= in_len) { - for (i = 0; i < 8; i++) - buf[i] ^= input[offset + i]; - - des_ecb_crypt(&ctx->key1, - buf, - output+offset, - 0); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 1); - des_ecb_crypt(&ctx->key3, - buf, - output+offset, - 0); - memcpy(buf, output+offset, 8); - offset += 8; - } - out_len = in_len; - if (offset < in_len) { - g_return_val_if_fail(in_len >= offset, -1); - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - i = 0; - while (tmp < in_len) { - buf[i++] ^= input[tmp]; - tmp++; - } - des_ecb_crypt(&ctx->key1, - buf, - output+offset, - 0); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 1); - des_ecb_crypt(&ctx->key3, - buf, - output+offset, - 0); - } - return out_len; -} - -static ssize_t -des3_encrypt(PurpleCipherContext *context, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - struct _des3_ctx *ctx = purple_cipher_context_get_data(context); - - if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { - return des3_ecb_encrypt(ctx, input, in_len, output, out_size); - } else if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { - return des3_cbc_encrypt(ctx, input, in_len, output, out_size); - } else { - g_return_val_if_reached(0); - } - - return 0; -} - -static ssize_t -des3_ecb_decrypt(struct _des3_ctx *ctx, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - gsize offset = 0; - int i = 0; - gsize tmp; - guint8 buf[8] = {0,0,0,0,0,0,0,0}; - gsize out_len; - - g_return_val_if_fail(out_size >= in_len, -1); - - while (offset + 8 <= in_len) { - /* NOTE: Apply key in reverse */ - des_ecb_crypt(&ctx->key3, - input+offset, - output+offset, - 1); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 0); - des_ecb_crypt(&ctx->key1, - buf, - output+offset, - 1); - offset+=8; - } - out_len = in_len; - if (offset < in_len) { - g_return_val_if_fail(in_len >= offset, -1); - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - memset(buf, 0, 8); - while (tmp < in_len) { - buf[i++] = input[tmp]; - tmp++; - } - des_ecb_crypt(&ctx->key3, - buf, - output+offset, - 1); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 0); - des_ecb_crypt(&ctx->key1, - buf, - output+offset, - 1); - } - return out_len; -} - -static ssize_t -des3_cbc_decrypt(struct _des3_ctx *ctx, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - gsize offset = 0; - int i = 0; - gsize tmp; - guint8 buf[8] = {0,0,0,0,0,0,0,0}; - guint8 link[8]; - gsize out_len; - - g_return_val_if_fail(out_size >= in_len, -1); - - memcpy(link, ctx->iv, 8); - while (offset + 8 <= in_len) { - des_ecb_crypt(&ctx->key3, - input+offset, - output+offset, - 1); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 0); - des_ecb_crypt(&ctx->key1, - buf, - output+offset, - 1); - for (i = 0; i < 8; i++) - output[offset + i] ^= link[i]; - memcpy(link, input + offset, 8); - offset+=8; - } - out_len = in_len; - if(offset<in_len) { - g_return_val_if_fail(in_len >= offset, -1); - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - memset(buf, 0, 8); - i = 0; - while(tmp<in_len) { - buf[i++] = input[tmp]; - tmp++; - } - des_ecb_crypt(&ctx->key3, - buf, - output+offset, - 1); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 0); - des_ecb_crypt(&ctx->key1, - buf, - output+offset, - 1); - for (i = 0; i < 8; i++) - output[offset + i] ^= link[i]; - } - return out_len; -} - -static ssize_t -des3_decrypt(PurpleCipherContext *context, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - struct _des3_ctx *ctx = purple_cipher_context_get_data(context); - - if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { - return des3_ecb_decrypt(ctx, input, in_len, output, out_size); - } else if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { - return des3_cbc_decrypt(ctx, input, in_len, output, out_size); - } else { - g_return_val_if_reached(0); - } - - return 0; -} - -static void -des3_set_batch(PurpleCipherContext *context, PurpleCipherBatchMode mode) -{ - struct _des3_ctx *ctx = purple_cipher_context_get_data(context); - - ctx->mode = mode; -} - -static PurpleCipherBatchMode -des3_get_batch(PurpleCipherContext *context) -{ - struct _des3_ctx *ctx = purple_cipher_context_get_data(context); - - return ctx->mode; -} - -static void -des3_set_iv(PurpleCipherContext *context, guchar *iv, size_t len) -{ - struct _des3_ctx *ctx; - - g_return_if_fail(len == 8); - - ctx = purple_cipher_context_get_data(context); - - memcpy(ctx->iv, iv, len); -} - -static void -des3_init(PurpleCipherContext *context, gpointer extra) -{ - struct _des3_ctx *mctx; - mctx = g_new0(struct _des3_ctx, 1); - purple_cipher_context_set_data(context, mctx); -} - -static void -des3_uninit(PurpleCipherContext *context) -{ - struct _des3_ctx *des3_context; - - des3_context = purple_cipher_context_get_data(context); - memset(des3_context, 0, sizeof(*des3_context)); - - g_free(des3_context); - des3_context = NULL; -} - -static PurpleCipherOps DES3Ops = { - NULL, /* Set option */ - NULL, /* Get option */ - des3_init, /* init */ - NULL, /* reset */ - NULL, /* reset state */ - des3_uninit, /* uninit */ - des3_set_iv, /* set iv */ - NULL, /* append */ - NULL, /* digest */ - NULL, /* get_digest_size */ - des3_encrypt, /* encrypt */ - des3_decrypt, /* decrypt */ - NULL, /* set salt */ - NULL, /* get salt size */ - des3_set_key, /* set key */ - des3_get_key_size, /* get_key_size */ - des3_set_batch, /* set batch mode */ - des3_get_batch, /* get batch mode */ - NULL, /* get block size */ - NULL, NULL, NULL, NULL /* reserved */ -}; - -/****************************************************************************** - * Registration - *****************************************************************************/ -PurpleCipherOps * -purple_des_cipher_get_ops(void) { - return &DESOps; -} - -PurpleCipherOps * -purple_des3_cipher_get_ops(void) { - return &DES3Ops; -} diff --git a/libpurple/ciphers/des3cipher.c b/libpurple/ciphers/des3cipher.c new file mode 100644 index 0000000000..9ede05a032 --- /dev/null +++ b/libpurple/ciphers/des3cipher.c @@ -0,0 +1,529 @@ +/* + * Original des taken from gpg + * + * des.c - Triple-DES encryption/decryption Algorithm + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * Please see below for more legal information! + * + * According to the definition of DES in FIPS PUB 46-2 from December 1993. + * For a description of triple encryption, see: + * Bruce Schneier: Applied Cryptography. Second Edition. + * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#include "des3cipher.h" +#include "descipher.h" +#include "enums.h" + +#include <string.h> + +/****************************************************************************** + * Structs + *****************************************************************************/ + +#define PURPLE_DES3_CIPHER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_DES3_CIPHER, PurpleDES3CipherPrivate)) + +typedef struct _PurpleDES3CipherPrivate PurpleDES3CipherPrivate; +struct _PurpleDES3CipherPrivate +{ + PurpleCipherBatchMode mode; + guchar iv[8]; + /* First key for encryption */ + PurpleCipher *key1; + /* Second key for decryption */ + PurpleCipher *key2; + /* Third key for encryption */ + PurpleCipher *key3; +}; + +/****************************************************************************** + * Enums + *****************************************************************************/ +enum { + PROP_NONE, + PROP_BATCH_MODE, + PROP_IV, + PROP_KEY, + PROP_LAST, +}; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Cipher Stuff + *****************************************************************************/ + +static size_t +purple_des3_cipher_get_key_size(PurpleCipher *cipher) +{ + return 24; +} + +/* + * Fill a DES3 context with subkeys calculated from 3 64bit key. + * Does not check parity bits, but simply ignore them. + * Does not check for weak keys. + **/ +static void +purple_des3_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) +{ + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + g_return_if_fail(len == 24); + + purple_cipher_set_key(PURPLE_CIPHER(priv->key1), key + 0, + purple_cipher_get_key_size(PURPLE_CIPHER(priv->key1))); + purple_cipher_set_key(PURPLE_CIPHER(priv->key2), key + 8, + purple_cipher_get_key_size(PURPLE_CIPHER(priv->key2))); + purple_cipher_set_key(PURPLE_CIPHER(priv->key3), key + 16, + purple_cipher_get_key_size(PURPLE_CIPHER(priv->key3))); + + g_object_notify(G_OBJECT(des3_cipher), "key"); +} + +static ssize_t +purple_des3_cipher_ecb_encrypt(PurpleDES3Cipher *des3_cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + gsize offset = 0; + int i = 0; + gsize tmp; + guint8 buf[8] = {0,0,0,0,0,0,0,0}; + gsize out_len; + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + g_return_val_if_fail(out_size >= in_len, -1); + + while (offset + 8 <= in_len) { + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + input + offset, output + offset, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + buf, output + offset, 0); + + offset += 8; + } + + out_len = in_len; + if (offset < in_len) { + g_return_val_if_fail(in_len >= offset, -1); + out_len += in_len - offset; + g_return_val_if_fail(out_size >= out_len, -1); + tmp = offset; + memset(buf, 0, 8); + while (tmp < in_len) { + buf[i++] = input[tmp]; + tmp++; + } + + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + buf, output + offset, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + buf, output + offset, 0); + } + + return out_len; +} + +static ssize_t +purple_des3_cipher_cbc_encrypt(PurpleDES3Cipher *des3_cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + gsize offset = 0; + int i = 0; + gsize tmp; + guint8 buf[8]; + gsize out_len; + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + memcpy(buf, priv->iv, 8); + + g_return_val_if_fail(out_size >= in_len, -1); + + while (offset + 8 <= in_len) { + for (i = 0; i < 8; i++) + buf[i] ^= input[offset + i]; + + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + buf, output + offset, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + buf, output + offset, 0); + + memcpy(buf, output+offset, 8); + offset += 8; + } + + out_len = in_len; + if (offset < in_len) { + g_return_val_if_fail(in_len >= offset, -1); + out_len += in_len - offset; + g_return_val_if_fail(out_size >= out_len, -1); + tmp = offset; + i = 0; + while (tmp < in_len) { + buf[i++] ^= input[tmp]; + tmp++; + } + + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + buf, output + offset, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + buf, output + offset, 0); + } + + return out_len; +} + +static ssize_t +purple_des3_cipher_encrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + if (priv->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { + return purple_des3_cipher_ecb_encrypt(des3_cipher, input, in_len, output, out_size); + } else if (priv->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { + return purple_des3_cipher_cbc_encrypt(des3_cipher, input, in_len, output, out_size); + } else { + g_return_val_if_reached(0); + } + + return 0; +} + +static ssize_t +purple_des3_cipher_ecb_decrypt(PurpleDES3Cipher *des3_cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + gsize offset = 0; + int i = 0; + gsize tmp; + guint8 buf[8] = {0,0,0,0,0,0,0,0}; + gsize out_len; + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + g_return_val_if_fail(out_size >= in_len, -1); + + while (offset + 8 <= in_len) { + /* NOTE: Apply key in reverse */ + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + input + offset, output + offset, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + buf, output + offset, 1); + + offset += 8; + } + + out_len = in_len; + if (offset < in_len) { + g_return_val_if_fail(in_len >= offset, -1); + out_len += in_len - offset; + g_return_val_if_fail(out_size >= out_len, -1); + tmp = offset; + memset(buf, 0, 8); + while (tmp < in_len) { + buf[i++] = input[tmp]; + tmp++; + } + + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + buf, output + offset, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + buf, output + offset, 1); + } + + return out_len; +} + +static ssize_t +purple_des3_cipher_cbc_decrypt(PurpleDES3Cipher *des3_cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + gsize offset = 0; + int i = 0; + gsize tmp; + guint8 buf[8] = {0,0,0,0,0,0,0,0}; + guint8 link[8]; + gsize out_len; + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + g_return_val_if_fail(out_size >= in_len, -1); + + memcpy(link, priv->iv, 8); + while (offset + 8 <= in_len) { + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + input + offset, output + offset, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + buf, output + offset, 1); + + for (i = 0; i < 8; i++) + output[offset + i] ^= link[i]; + + memcpy(link, input + offset, 8); + + offset+=8; + } + + out_len = in_len; + if(offset<in_len) { + g_return_val_if_fail(in_len >= offset, -1); + out_len += in_len - offset; + g_return_val_if_fail(out_size >= out_len, -1); + tmp = offset; + memset(buf, 0, 8); + i = 0; + while(tmp<in_len) { + buf[i++] = input[tmp]; + tmp++; + } + + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + buf, output + offset, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + buf, output + offset, 1); + + for (i = 0; i < 8; i++) + output[offset + i] ^= link[i]; + } + + return out_len; +} + +static ssize_t +purple_des3_cipher_decrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(cipher); + + if (priv->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { + return purple_des3_cipher_ecb_decrypt(des3_cipher, input, in_len, output, out_size); + } else if (priv->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { + return purple_des3_cipher_cbc_decrypt(des3_cipher, input, in_len, output, out_size); + } else { + g_return_val_if_reached(0); + } + + return 0; +} + +static void +purple_des3_cipher_set_batch_mode(PurpleCipher *cipher, PurpleCipherBatchMode mode) +{ + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + priv->mode = mode; + + g_object_notify(G_OBJECT(des3_cipher), "batch_mode"); +} + +static PurpleCipherBatchMode +purple_des3_cipher_get_batch_mode(PurpleCipher *cipher) +{ + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + return priv->mode; +} + +static void +purple_des3_cipher_set_iv(PurpleCipher *cipher, guchar *iv, size_t len) +{ + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + g_return_if_fail(len == 8); + + memcpy(priv->iv, iv, len); + + g_object_notify(G_OBJECT(des3_cipher), "iv"); +} + +static const gchar* +purple_des3_cipher_get_name(PurpleCipher *cipher) +{ + return "des3"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_des3_cipher_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + + switch(param_id) { + case PROP_BATCH_MODE: + g_value_set_enum(value, + purple_cipher_get_batch_mode(cipher)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_des3_cipher_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + + switch(param_id) { + case PROP_BATCH_MODE: + purple_cipher_set_batch_mode(cipher, + g_value_get_enum(value)); + break; + case PROP_IV: + { + guchar *iv = (guchar *)g_value_get_string(value); + purple_cipher_set_iv(cipher, iv, strlen((gchar*)iv)); + } + break; + case PROP_KEY: + purple_cipher_set_key(cipher, (guchar *)g_value_get_string(value), + purple_des3_cipher_get_key_size(cipher)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_des3_cipher_finalize(GObject *obj) +{ + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(obj); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + g_object_unref(G_OBJECT(priv->key1)); + g_object_unref(G_OBJECT(priv->key2)); + g_object_unref(G_OBJECT(priv->key3)); + + memset(priv->iv, 0, sizeof(priv->iv)); + + parent_class->finalize(obj); +} + +static void +purple_des3_cipher_class_init(PurpleDES3CipherClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); + GParamSpec *pspec; + + parent_class = g_type_class_peek_parent(klass); + + obj_class->finalize = purple_des3_cipher_finalize; + obj_class->get_property = purple_des3_cipher_get_property; + obj_class->set_property = purple_des3_cipher_set_property; + + cipher_class->set_iv = purple_des3_cipher_set_iv; + cipher_class->encrypt = purple_des3_cipher_encrypt; + cipher_class->decrypt = purple_des3_cipher_decrypt; + cipher_class->set_key = purple_des3_cipher_set_key; + cipher_class->set_batch_mode = purple_des3_cipher_set_batch_mode; + cipher_class->get_batch_mode = purple_des3_cipher_get_batch_mode; + cipher_class->get_key_size = purple_des3_cipher_get_key_size; + cipher_class->get_name = purple_des3_cipher_get_name; + + pspec = g_param_spec_enum("batch_mode", "batch_mode", "batch_mode", + PURPLE_TYPE_CIPHER_BATCH_MODE, 0, + G_PARAM_READWRITE); + g_object_class_install_property(obj_class, PROP_BATCH_MODE, pspec); + + pspec = g_param_spec_string("iv", "iv", "iv", NULL, + G_PARAM_WRITABLE); + g_object_class_install_property(obj_class, PROP_IV, pspec); + + pspec = g_param_spec_string("key", "key", "key", NULL, + G_PARAM_WRITABLE); + g_object_class_install_property(obj_class, PROP_KEY, pspec); + + g_type_class_add_private(klass, sizeof(PurpleDES3CipherPrivate)); +} + +static void +purple_des3_cipher_init(PurpleCipher *cipher) { + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + priv->key1 = purple_des_cipher_new(); + priv->key2 = purple_des_cipher_new(); + priv->key3 = purple_des_cipher_new(); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_des3_cipher_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleDES3CipherClass), + NULL, + NULL, + (GClassInitFunc)purple_des3_cipher_class_init, + NULL, + NULL, + sizeof(PurpleDES3Cipher), + 0, + (GInstanceInitFunc)purple_des3_cipher_init, + NULL + }; + + type = g_type_register_static(PURPLE_TYPE_CIPHER, + "PurpleDES3Cipher", + &info, 0); + } + + return type; +} + +PurpleCipher * +purple_des3_cipher_new(void) { + return g_object_new(PURPLE_TYPE_DES3_CIPHER, NULL); +} diff --git a/libpurple/ciphers/des3cipher.h b/libpurple/ciphers/des3cipher.h new file mode 100644 index 0000000000..c981dc4b32 --- /dev/null +++ b/libpurple/ciphers/des3cipher.h @@ -0,0 +1,65 @@ +/** + * @file des3.h Purple Triple-DES Cipher + * @ingroup core + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef PURPLE_DES3_CIPHER_H +#define PURPLE_DES3_CIPHER_H + +#include "cipher.h" + +#define PURPLE_TYPE_DES3_CIPHER (purple_des3_cipher_get_gtype()) +#define PURPLE_DES3_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_DES3_CIPHER, PurpleDES3Cipher)) +#define PURPLE_DES3_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_DES3_CIPHER, PurpleDES3CipherClass)) +#define PURPLE_IS_DES3_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_DES3_CIPHER)) +#define PURPLE_IS_DES3_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_DES3_CIPHER)) +#define PURPLE_DES3_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_DES3_CIPHER, PurpleDES3CipherClass)) + +typedef struct _PurpleDES3Cipher PurpleDES3Cipher; +typedef struct _PurpleDES3CipherClass PurpleDES3CipherClass; + +struct _PurpleDES3Cipher { + /*< private >*/ + PurpleCipher gparent; +}; + +struct _PurpleDES3CipherClass { + /*< private >*/ + PurpleCipherClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_des3_cipher_get_gtype(void); + +PurpleCipher *purple_des3_cipher_new(void); + +G_END_DECLS + +#endif /* PURPLE_DES3_CIPHER_H */ + diff --git a/libpurple/ciphers/descipher.c b/libpurple/ciphers/descipher.c new file mode 100644 index 0000000000..759862f628 --- /dev/null +++ b/libpurple/ciphers/descipher.c @@ -0,0 +1,585 @@ +/* + * Original des taken from gpg + * + * des.c - DES encryption/decryption Algorithm + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * Please see below for more legal information! + * + * According to the definition of DES in FIPS PUB 46-2 from December 1993. + * For a description of triple encryption, see: + * Bruce Schneier: Applied Cryptography. Second Edition. + * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#include "descipher.h" +#include "enums.h" + +#include <string.h> + +/****************************************************************************** + * Structs + *****************************************************************************/ +#define PURPLE_DES_CIPHER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_DES_CIPHER, PurpleDESCipherPrivate)) + +typedef struct { + guint32 encrypt_subkeys[32]; + guint32 decrypt_subkeys[32]; +} PurpleDESCipherPrivate; + +/****************************************************************************** + * Enums + *****************************************************************************/ +enum { + PROP_NONE, + PROP_KEY, + PROP_LAST, +}; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/* + * The s-box values are permuted according to the 'primitive function P' + */ +static guint32 sbox1[64] = { + 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, + 0x00000002, 0x00008000, 0x00000200, 0x00808200, 0x00808202, 0x00000200, + 0x00800202, 0x00808002, 0x00800000, 0x00000002, 0x00000202, 0x00800200, + 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202, + 0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, + 0x00008202, 0x00800000, 0x00008000, 0x00808202, 0x00000002, 0x00808000, + 0x00808200, 0x00800000, 0x00800000, 0x00000200, 0x00808002, 0x00008000, + 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202, + 0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, + 0x00008202, 0x00808200, 0x00000202, 0x00800200, 0x00800200, 0x00000000, + 0x00008002, 0x00008200, 0x00000000, 0x00808002 +}; + +static guint32 sbox2[64] = { + 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, + 0x40080010, 0x40004010, 0x40000010, 0x40084010, 0x40084000, 0x40000000, + 0x40004000, 0x00080000, 0x00000010, 0x40080010, 0x00084000, 0x00080010, + 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000, + 0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, + 0x40080000, 0x00004010, 0x00000000, 0x00084010, 0x40080010, 0x00080000, + 0x40004010, 0x40080000, 0x40084000, 0x00004000, 0x40080000, 0x40004000, + 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000, + 0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, + 0x40000010, 0x00080010, 0x00084000, 0x00000000, 0x40004000, 0x00004010, + 0x40000000, 0x40080010, 0x40084010, 0x00084000 +}; + +static guint32 sbox3[64] = { + 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, + 0x00010104, 0x04000100, 0x00010004, 0x04000004, 0x04000004, 0x00010000, + 0x04010104, 0x00010004, 0x04010000, 0x00000104, 0x04000000, 0x00000004, + 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104, + 0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, + 0x00000100, 0x04000000, 0x04010100, 0x04000000, 0x00010004, 0x00000104, + 0x00010000, 0x04010100, 0x04000100, 0x00000000, 0x00000100, 0x00010004, + 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004, + 0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, + 0x00010100, 0x04000004, 0x04010000, 0x04000104, 0x00000104, 0x04010000, + 0x00010104, 0x00000004, 0x04010004, 0x00010100 +}; + +static guint32 sbox4[64] = { + 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, + 0x80400000, 0x80001000, 0x00000000, 0x00401000, 0x00401000, 0x80401040, + 0x80000040, 0x00000000, 0x00400040, 0x80400000, 0x80000000, 0x00001000, + 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040, + 0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, + 0x80401040, 0x80000040, 0x00400040, 0x80400000, 0x00401000, 0x80401040, + 0x80000040, 0x00000000, 0x00000000, 0x00401000, 0x00001040, 0x00400040, + 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040, + 0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, + 0x00401040, 0x80400040, 0x80001000, 0x00001040, 0x00400000, 0x80401000, + 0x00000040, 0x00400000, 0x00001000, 0x00401040 +}; + +static guint32 sbox5[64] = { + 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, + 0x20000000, 0x01040000, 0x20040080, 0x00040000, 0x01000080, 0x20040080, + 0x21000080, 0x21040000, 0x00040080, 0x20000000, 0x01000000, 0x20040000, + 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080, + 0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, + 0x21000000, 0x00040080, 0x00040000, 0x21000080, 0x00000080, 0x01000000, + 0x20000000, 0x01040000, 0x21000080, 0x20040080, 0x01000080, 0x20000000, + 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000, + 0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, + 0x20040000, 0x21000000, 0x00040080, 0x01000080, 0x20000080, 0x00040000, + 0x00000000, 0x20040000, 0x01040080, 0x20000080 +}; + +static guint32 sbox6[64] = { + 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, + 0x10202008, 0x00200000, 0x10002000, 0x00202008, 0x00200000, 0x10000008, + 0x00200008, 0x10002000, 0x10000000, 0x00002008, 0x00000000, 0x00200008, + 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008, + 0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, + 0x10202000, 0x10000000, 0x10002000, 0x00000008, 0x10200008, 0x00202000, + 0x10202008, 0x00200000, 0x00002008, 0x10000008, 0x00200000, 0x10002000, + 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000, + 0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, + 0x10200000, 0x00202008, 0x00002000, 0x00200008, 0x10002008, 0x00000000, + 0x10202000, 0x10000000, 0x00200008, 0x10002008 +}; + +static guint32 sbox7[64] = { + 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, + 0x00100401, 0x02100400, 0x02100401, 0x00100000, 0x00000000, 0x02000001, + 0x00000001, 0x02000000, 0x02100001, 0x00000401, 0x02000400, 0x00100401, + 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001, + 0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, + 0x02000000, 0x00100400, 0x02000000, 0x00100400, 0x00100000, 0x02000401, + 0x02000401, 0x02100001, 0x02100001, 0x00000001, 0x00100001, 0x02000000, + 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400, + 0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, + 0x00000001, 0x02100401, 0x00000000, 0x00100401, 0x02100000, 0x00000400, + 0x02000001, 0x02000400, 0x00000400, 0x00100001 +}; + +static guint32 sbox8[64] = { + 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, + 0x00000020, 0x08000000, 0x00020020, 0x08020000, 0x08020820, 0x00020800, + 0x08020800, 0x00020820, 0x00000800, 0x00000020, 0x08020000, 0x08000020, + 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800, + 0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, + 0x00020820, 0x00020000, 0x00020820, 0x00020000, 0x08020800, 0x00000800, + 0x00000020, 0x08020020, 0x00000800, 0x00020820, 0x08000800, 0x00000020, + 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820, + 0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, + 0x08000820, 0x00000000, 0x08020820, 0x00020800, 0x00020800, 0x00000820, + 0x00000820, 0x00020020, 0x08000000, 0x08020800 +}; + +/* + * These two tables are part of the 'permuted choice 1' function. + * In this implementation several speed improvements are done. + */ +static guint32 leftkey_swap[16] = { + 0x00000000, 0x00000001, 0x00000100, 0x00000101, 0x00010000, 0x00010001, + 0x00010100, 0x00010101, 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static guint32 rightkey_swap[16] = { + 0x00000000, 0x01000000, 0x00010000, 0x01010000, 0x00000100, 0x01000100, + 0x00010100, 0x01010100, 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + +/* + * Numbers of left shifts per round for encryption subkey schedule + * To calculate the decryption key scheduling we just reverse the + * ordering of the subkeys so we can omit the table for decryption + * subkey schedule. + */ +static guint8 encrypt_rotate_tab[16] = { + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 +}; + + +/****************************************************************************** + * Helpers + *****************************************************************************/ +/* + * Macro to swap bits across two words + */ +#define DO_PERMUTATION(a, temp, b, offset, mask) \ + temp = ((a>>offset) ^ b) & mask; \ + b ^= temp; \ + a ^= temp<<offset; + +/* + * This performs the 'initial permutation' for the data to be encrypted or + * decrypted + */ +#define INITIAL_PERMUTATION(left, temp, right) \ + DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) \ + DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ + DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ + DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ + DO_PERMUTATION(left, temp, right, 1, 0x55555555) + +/* + * The 'inverse initial permutation' + */ +#define FINAL_PERMUTATION(left, temp, right) \ + DO_PERMUTATION(left, temp, right, 1, 0x55555555) \ + DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ + DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ + DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ + DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) + +/* + * A full DES round including 'expansion function', 'sbox substitution' + * and 'primitive function P' but without swapping the left and right word. + */ +#define DES_ROUND(from, to, work, subkey) \ + work = ((from<<1) | (from>>31)) ^ *subkey++; \ + to ^= sbox8[ work & 0x3f ]; \ + to ^= sbox6[ (work>>8) & 0x3f ]; \ + to ^= sbox4[ (work>>16) & 0x3f ]; \ + to ^= sbox2[ (work>>24) & 0x3f ]; \ + work = ((from>>3) | (from<<29)) ^ *subkey++; \ + to ^= sbox7[ work & 0x3f ]; \ + to ^= sbox5[ (work>>8) & 0x3f ]; \ + to ^= sbox3[ (work>>16) & 0x3f ]; \ + to ^= sbox1[ (work>>24) & 0x3f ]; + + +/* + * Macros to convert 8 bytes from/to 32bit words + */ +#define READ_64BIT_DATA(data, left, right) \ + left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ + right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; + +#define WRITE_64BIT_DATA(data, left, right) \ + data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \ + data[2] = (left >> 8) &0xff; data[3] = left &0xff; \ + data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ + data[6] = (right >> 8) &0xff; data[7] = right &0xff; + +/****************************************************************************** + * Cipher Stuff + *****************************************************************************/ +/* + * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for + * 16 encryption rounds. + * To calculate subkeys for decryption the caller + * have to reorder the generated subkeys. + * + * rawkey: 8 Bytes of key data + * subkey: Array of at least 32 guint32s. Will be filled + * with calculated subkeys. + * + */ +static void +purple_des_cipher_key_schedule(const guint8 * rawkey, guint32 * subkey) { + guint32 left, right, work; + int round; + + READ_64BIT_DATA (rawkey, left, right) + + DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f) + DO_PERMUTATION (right, work, left, 0, 0x10101010) + + left = (leftkey_swap[(left >> 0) & 0xf] << 3) + | (leftkey_swap[(left >> 8) & 0xf] << 2) + | (leftkey_swap[(left >> 16) & 0xf] << 1) + | (leftkey_swap[(left >> 24) & 0xf] ) + | (leftkey_swap[(left >> 5) & 0xf] << 7) + | (leftkey_swap[(left >> 13) & 0xf] << 6) + | (leftkey_swap[(left >> 21) & 0xf] << 5) + | (leftkey_swap[(left >> 29) & 0xf] << 4); + + left &= 0x0fffffff; + + right = (rightkey_swap[(right >> 1) & 0xf] << 3) + | (rightkey_swap[(right >> 9) & 0xf] << 2) + | (rightkey_swap[(right >> 17) & 0xf] << 1) + | (rightkey_swap[(right >> 25) & 0xf] ) + | (rightkey_swap[(right >> 4) & 0xf] << 7) + | (rightkey_swap[(right >> 12) & 0xf] << 6) + | (rightkey_swap[(right >> 20) & 0xf] << 5) + | (rightkey_swap[(right >> 28) & 0xf] << 4); + + right &= 0x0fffffff; + + for (round = 0; round < 16; ++round) { + left = ((left << encrypt_rotate_tab[round]) | + (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; + right = ((right << encrypt_rotate_tab[round]) | + (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; + + *subkey++ = ((left << 4) & 0x24000000) + | ((left << 28) & 0x10000000) + | ((left << 14) & 0x08000000) + | ((left << 18) & 0x02080000) + | ((left << 6) & 0x01000000) + | ((left << 9) & 0x00200000) + | ((left >> 1) & 0x00100000) + | ((left << 10) & 0x00040000) + | ((left << 2) & 0x00020000) + | ((left >> 10) & 0x00010000) + | ((right >> 13) & 0x00002000) + | ((right >> 4) & 0x00001000) + | ((right << 6) & 0x00000800) + | ((right >> 1) & 0x00000400) + | ((right >> 14) & 0x00000200) + | (right & 0x00000100) + | ((right >> 5) & 0x00000020) + | ((right >> 10) & 0x00000010) + | ((right >> 3) & 0x00000008) + | ((right >> 18) & 0x00000004) + | ((right >> 26) & 0x00000002) + | ((right >> 24) & 0x00000001); + + *subkey++ = ((left << 15) & 0x20000000) + | ((left << 17) & 0x10000000) + | ((left << 10) & 0x08000000) + | ((left << 22) & 0x04000000) + | ((left >> 2) & 0x02000000) + | ((left << 1) & 0x01000000) + | ((left << 16) & 0x00200000) + | ((left << 11) & 0x00100000) + | ((left << 3) & 0x00080000) + | ((left >> 6) & 0x00040000) + | ((left << 15) & 0x00020000) + | ((left >> 4) & 0x00010000) + | ((right >> 2) & 0x00002000) + | ((right << 8) & 0x00001000) + | ((right >> 14) & 0x00000808) + | ((right >> 9) & 0x00000400) + | ((right) & 0x00000200) + | ((right << 7) & 0x00000100) + | ((right >> 7) & 0x00000020) + | ((right >> 3) & 0x00000011) + | ((right << 2) & 0x00000004) + | ((right >> 21) & 0x00000002); + } +} + +/* + * Fill a DES context with subkeys calculated from a 64bit key. + * Does not check parity bits, but simply ignore them. + * Does not check for weak keys. + */ +static void +purple_des_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) { + PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher); + PurpleDESCipherPrivate *priv = PURPLE_DES_CIPHER_GET_PRIVATE(des_cipher); + int i; + + g_return_if_fail(len == 8); + + purple_des_cipher_key_schedule(key, priv->encrypt_subkeys); + + for(i = 0; i < 32; i += 2) { + priv->decrypt_subkeys[i] = priv->encrypt_subkeys[30 - i]; + priv->decrypt_subkeys[i + 1] = priv->encrypt_subkeys[31 - i]; + } + + g_object_notify(G_OBJECT(cipher), "key"); +} + +static size_t +purple_des_cipher_get_key_size(PurpleCipher *cipher) +{ + return 8; +} + +/* + * Electronic Codebook Mode DES encryption/decryption of data according to + * 'mode'. + */ +int +purple_des_cipher_ecb_crypt(PurpleDESCipher *des_cipher, const guint8 * from, guint8 * to, + int mode) +{ + guint32 left, right, work; + guint32 *keys; + PurpleDESCipherPrivate *priv = PURPLE_DES_CIPHER_GET_PRIVATE(des_cipher); + + keys = mode ? priv->decrypt_subkeys : + priv->encrypt_subkeys; + + READ_64BIT_DATA (from, left, right) + INITIAL_PERMUTATION (left, work, right) + + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + + FINAL_PERMUTATION (right, work, left) + WRITE_64BIT_DATA (to, right, left) + + return 0; +} + +static ssize_t +purple_des_cipher_encrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher); + + gsize offset = 0; + int i = 0; + gsize tmp; + guint8 buf[8] = {0,0,0,0,0,0,0,0}; + gsize out_len; + + g_return_val_if_fail(out_size >= in_len, -1); + + while(offset + 8 <= in_len) { + purple_des_cipher_ecb_crypt(des_cipher, input + offset, output + offset, 0); + offset += 8; + } + + out_len = in_len; + + if(offset<in_len) { + g_return_val_if_fail(in_len >= offset, -1); + out_len += in_len - offset; + g_return_val_if_fail(out_size >= out_len, -1); + tmp = offset; + while(tmp<in_len) { + buf[i++] = input[tmp]; + tmp++; + } + + purple_des_cipher_ecb_crypt(des_cipher, buf, output + offset, 0); + } + + return out_len; +} + +static ssize_t +purple_des_cipher_decrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher); + + gsize offset = 0; + int i = 0; + gsize tmp; + guint8 buf[8] = {0,0,0,0,0,0,0,0}; + gsize out_len; + + g_return_val_if_fail(out_size >= in_len, -1); + + while(offset + 8 <= in_len) { + purple_des_cipher_ecb_crypt(des_cipher, input + offset, output + offset, 1); + offset += 8; + } + + out_len = in_len; + if(offset<in_len) { + g_return_val_if_fail(in_len >= offset, -1); + out_len += in_len - offset; + g_return_val_if_fail(out_size >= out_len, -1); + tmp = offset; + while(tmp<in_len) { + buf[i++] = input[tmp]; + tmp++; + } + + purple_des_cipher_ecb_crypt(des_cipher, buf, output + offset, 1); + } + + return out_len; +} + +static const gchar* +purple_des_cipher_get_name(PurpleCipher *cipher) +{ + return "des"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_des_cipher_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + + switch(param_id) { + case PROP_KEY: + purple_cipher_set_key(cipher, (guchar *)g_value_get_string(value), + purple_des_cipher_get_key_size(cipher)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_des_cipher_class_init(PurpleDESCipherClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); + GParamSpec *pspec; + + parent_class = g_type_class_peek_parent(klass); + + obj_class->set_property = purple_des_cipher_set_property; + + cipher_class->encrypt = purple_des_cipher_encrypt; + cipher_class->decrypt = purple_des_cipher_decrypt; + cipher_class->set_key = purple_des_cipher_set_key; + cipher_class->get_key_size = purple_des_cipher_get_key_size; + cipher_class->get_name = purple_des_cipher_get_name; + + pspec = g_param_spec_string("key", "key", "key", NULL, + G_PARAM_WRITABLE); + g_object_class_install_property(obj_class, PROP_KEY, pspec); + + g_type_class_add_private(klass, sizeof(PurpleDESCipherPrivate)); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_des_cipher_get_type(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + .class_size = sizeof(PurpleDESCipherClass), + .class_init = (GClassInitFunc)purple_des_cipher_class_init, + .instance_size = sizeof(PurpleDESCipher), + .instance_init = (GInstanceInitFunc)purple_cipher_reset, + }; + + type = g_type_register_static(PURPLE_TYPE_CIPHER, + "PurpleDESCipher", + &info, 0); + } + + return type; +} + +/** + * purple_des_cipher_new: + * + * Creates a new #PurpleCipher instance which implements the DES block cipher. + * + * Return Value: The new DES implementation of #PurpleCipher. + */ +PurpleCipher * +purple_des_cipher_new(void) { + return g_object_new(PURPLE_TYPE_DES_CIPHER, NULL); +} + diff --git a/libpurple/ciphers/descipher.h b/libpurple/ciphers/descipher.h new file mode 100644 index 0000000000..595f0458c3 --- /dev/null +++ b/libpurple/ciphers/descipher.h @@ -0,0 +1,66 @@ +/** + * @file des.h Purple DES Cipher + * @ingroup core + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef PURPLE_DES_CIPHER_H +#define PURPLE_DES_CIPHER_H + +#include "cipher.h" + +#define PURPLE_TYPE_DES_CIPHER (purple_des_cipher_get_type()) +#define PURPLE_DES_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_DES_CIPHER, PurpleDESCipher)) +#define PURPLE_DES_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_DES_CIPHER, PurpleDESCipherClass)) +#define PURPLE_IS_DES_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_DES_CIPHER)) +#define PURPLE_IS_DES_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_DES_CIPHER)) +#define PURPLE_DES_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_DES_CIPHER, PurpleDESCipherClass)) + +typedef struct _PurpleDESCipher PurpleDESCipher; +typedef struct _PurpleDESCipherClass PurpleDESCipherClass; + +struct _PurpleDESCipher { + /*< private >*/ + PurpleCipher gparent; +}; + +struct _PurpleDESCipherClass { + /*< private >*/ + PurpleCipherClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_des_cipher_get_type(void); + +PurpleCipher *purple_des_cipher_new(void); + +int purple_des_cipher_ecb_crypt(PurpleDESCipher *des_cipher, const guint8 * from, guint8 * to, int mode); + +G_END_DECLS + +#endif /* PURPLE_DES_CIPHER_H */ diff --git a/libpurple/ciphers/gchecksum.c b/libpurple/ciphers/gchecksum.c deleted file mode 100644 index 3e09ff4b54..0000000000 --- a/libpurple/ciphers/gchecksum.c +++ /dev/null @@ -1,144 +0,0 @@ -#include "internal.h" -#include <cipher.h> -#include "ciphers.h" - -static void -purple_g_checksum_init(PurpleCipherContext *context, GChecksumType type) -{ - GChecksum *checksum; - - checksum = g_checksum_new(type); - purple_cipher_context_set_data(context, checksum); -} - -static void -purple_g_checksum_reset(PurpleCipherContext *context, GChecksumType type) -{ - GChecksum *checksum; - - checksum = purple_cipher_context_get_data(context); - g_return_if_fail(checksum != NULL); - - g_checksum_reset(checksum); -} - -static void -purple_g_checksum_uninit(PurpleCipherContext *context) -{ - GChecksum *checksum; - - checksum = purple_cipher_context_get_data(context); - g_return_if_fail(checksum != NULL); - - g_checksum_free(checksum); -} - -static void -purple_g_checksum_append(PurpleCipherContext *context, const guchar *data, - gsize len) -{ - GChecksum *checksum; - - checksum = purple_cipher_context_get_data(context); - g_return_if_fail(checksum != NULL); - - while (len >= G_MAXSSIZE) { - g_checksum_update(checksum, data, G_MAXSSIZE); - len -= G_MAXSSIZE; - data += G_MAXSSIZE; - } - - if (len) - g_checksum_update(checksum, data, len); -} - -static gboolean -purple_g_checksum_digest(PurpleCipherContext *context, GChecksumType type, - guchar *digest, size_t buff_len) -{ - GChecksum *checksum; - const gssize required_len = g_checksum_type_get_length(type); - gsize digest_len = buff_len; - - checksum = purple_cipher_context_get_data(context); - - g_return_val_if_fail(required_len >= 0, FALSE); - g_return_val_if_fail(buff_len >= (gsize)required_len, FALSE); - g_return_val_if_fail(checksum != NULL, FALSE); - - g_checksum_get_digest(checksum, digest, &digest_len); - - if (digest_len != (gsize)required_len) - return FALSE; - - purple_cipher_context_reset(context, NULL); - - return TRUE; -} - -/****************************************************************************** - * Macros - *****************************************************************************/ -#define PURPLE_G_CHECKSUM_IMPLEMENTATION(lower, camel, type, block_size) \ - static size_t \ - lower##_get_block_size(PurpleCipherContext *context) { \ - return (block_size); \ - } \ - \ - static void \ - lower##_init(PurpleCipherContext *context, gpointer extra) { \ - purple_g_checksum_init(context, (type)); \ - } \ - \ - static void \ - lower##_reset(PurpleCipherContext *context, gpointer extra) { \ - purple_g_checksum_reset(context, (type)); \ - } \ - \ - static gboolean \ - lower##_digest(PurpleCipherContext *context, guchar digest[], \ - size_t len) \ - { \ - return purple_g_checksum_digest(context, (type), digest, len); \ - } \ - \ - static size_t \ - lower##_get_digest_size(PurpleCipherContext *context) \ - { \ - return g_checksum_type_get_length((type)); \ - } \ - \ - static PurpleCipherOps camel##Ops = { \ - NULL, /* Set option */ \ - NULL, /* Get option */ \ - lower##_init, /* init */ \ - lower##_reset, /* reset */ \ - lower##_reset, /* reset state */ \ - purple_g_checksum_uninit, /* uninit */ \ - NULL, /* set iv */ \ - purple_g_checksum_append, /* append */ \ - lower##_digest, /* digest */ \ - lower##_get_digest_size, /* get digest size */ \ - NULL, /* encrypt */ \ - NULL, /* decrypt */ \ - NULL, /* set salt */ \ - NULL, /* get salt size */ \ - NULL, /* set key */ \ - NULL, /* get key size */ \ - NULL, /* set batch mode */ \ - NULL, /* get batch mode */ \ - lower##_get_block_size, /* get block size */ \ - NULL, NULL, NULL, NULL /* reserved */ \ - }; \ - \ - PurpleCipherOps * \ - purple_##lower##_cipher_get_ops(void) { \ - return &camel##Ops; \ - } - -/****************************************************************************** - * Macro Expansion - *****************************************************************************/ -PURPLE_G_CHECKSUM_IMPLEMENTATION(md5, MD5, G_CHECKSUM_MD5, 64); -PURPLE_G_CHECKSUM_IMPLEMENTATION(sha1, SHA1, G_CHECKSUM_SHA1, 64); -PURPLE_G_CHECKSUM_IMPLEMENTATION(sha256, SHA256, G_CHECKSUM_SHA256, 64); diff --git a/libpurple/ciphers/hmac.c b/libpurple/ciphers/hmac.c deleted file mode 100644 index 00e6a0d99e..0000000000 --- a/libpurple/ciphers/hmac.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#include "internal.h" -#include <cipher.h> -#include "ciphers.h" - -#include <util.h> - -struct HMAC_Context { - PurpleCipherContext *hash; - char *name; - int blocksize; - guchar *opad, *ipad; -}; - - static void -hmac_init(PurpleCipherContext *context, gpointer extra) -{ - struct HMAC_Context *hctx; - hctx = g_new0(struct HMAC_Context, 1); - purple_cipher_context_set_data(context, hctx); - purple_cipher_context_reset(context, extra); -} - - static void -hmac_reset(PurpleCipherContext *context, gpointer extra) -{ - struct HMAC_Context *hctx; - - hctx = purple_cipher_context_get_data(context); - - g_free(hctx->name); - hctx->name = NULL; - if (hctx->hash) - purple_cipher_context_destroy(hctx->hash); - hctx->hash = NULL; - hctx->blocksize = 0; - g_free(hctx->opad); - hctx->opad = NULL; - g_free(hctx->ipad); - hctx->ipad = NULL; -} - - static void -hmac_reset_state(PurpleCipherContext *context, gpointer extra) -{ - struct HMAC_Context *hctx; - - hctx = purple_cipher_context_get_data(context); - - if (hctx->hash) { - purple_cipher_context_reset_state(hctx->hash, NULL); - purple_cipher_context_append(hctx->hash, hctx->ipad, hctx->blocksize); - } -} - - static void -hmac_set_opt(PurpleCipherContext *context, const gchar *name, void *value) -{ - struct HMAC_Context *hctx; - - hctx = purple_cipher_context_get_data(context); - - if (purple_strequal(name, "hash")) { - g_free(hctx->name); - if (hctx->hash) - purple_cipher_context_destroy(hctx->hash); - hctx->name = g_strdup((char*)value); - hctx->hash = purple_cipher_context_new_by_name((char *)value, NULL); - hctx->blocksize = purple_cipher_context_get_block_size(hctx->hash); - } -} - - static void * -hmac_get_opt(PurpleCipherContext *context, const gchar *name) -{ - struct HMAC_Context *hctx; - - hctx = purple_cipher_context_get_data(context); - - if (purple_strequal(name, "hash")) { - return hctx->name; - } - - return NULL; -} - - static void -hmac_append(PurpleCipherContext *context, const guchar *data, size_t len) -{ - struct HMAC_Context *hctx = purple_cipher_context_get_data(context); - - g_return_if_fail(hctx->hash != NULL); - - purple_cipher_context_append(hctx->hash, data, len); -} - - static gboolean -hmac_digest(PurpleCipherContext *context, guchar *out, size_t len) -{ - struct HMAC_Context *hctx = purple_cipher_context_get_data(context); - PurpleCipherContext *hash = hctx->hash; - guchar *inner_hash; - size_t hash_len; - gboolean result; - - g_return_val_if_fail(hash != NULL, FALSE); - - hash_len = purple_cipher_context_get_digest_size(hash); - g_return_val_if_fail(hash_len > 0, FALSE); - - inner_hash = g_malloc(hash_len); - result = purple_cipher_context_digest(hash, inner_hash, hash_len); - - purple_cipher_context_reset(hash, NULL); - - purple_cipher_context_append(hash, hctx->opad, hctx->blocksize); - purple_cipher_context_append(hash, inner_hash, hash_len); - - g_free(inner_hash); - - result = result && purple_cipher_context_digest(hash, out, len); - - return result; -} - - static size_t -hmac_get_digest_size(PurpleCipherContext *context) -{ - struct HMAC_Context *hctx = purple_cipher_context_get_data(context); - PurpleCipherContext *hash = hctx->hash; - - g_return_val_if_fail(hash != NULL, 0); - - return purple_cipher_context_get_digest_size(hash); -} - - static void -hmac_uninit(PurpleCipherContext *context) -{ - struct HMAC_Context *hctx; - - purple_cipher_context_reset(context, NULL); - - hctx = purple_cipher_context_get_data(context); - - g_free(hctx); -} - - static void -hmac_set_key(PurpleCipherContext *context, const guchar * key, size_t key_len) -{ - struct HMAC_Context *hctx = purple_cipher_context_get_data(context); - gsize blocksize, i; - guchar *full_key; - - g_return_if_fail(hctx->hash != NULL); - - g_free(hctx->opad); - g_free(hctx->ipad); - - blocksize = hctx->blocksize; - hctx->ipad = g_malloc(blocksize); - hctx->opad = g_malloc(blocksize); - - if (key_len > blocksize) { - purple_cipher_context_reset(hctx->hash, NULL); - purple_cipher_context_append(hctx->hash, key, key_len); - - key_len = purple_cipher_context_get_digest_size(hctx->hash); - full_key = g_malloc(key_len); - purple_cipher_context_digest(hctx->hash, full_key, key_len); - } else - full_key = g_memdup(key, key_len); - - if (key_len < blocksize) { - full_key = g_realloc(full_key, blocksize); - memset(full_key + key_len, 0, blocksize - key_len); - } - - for(i = 0; i < blocksize; i++) { - hctx->ipad[i] = 0x36 ^ full_key[i]; - hctx->opad[i] = 0x5c ^ full_key[i]; - } - - g_free(full_key); - - purple_cipher_context_reset(hctx->hash, NULL); - purple_cipher_context_append(hctx->hash, hctx->ipad, blocksize); -} - - static size_t -hmac_get_block_size(PurpleCipherContext *context) -{ - struct HMAC_Context *hctx = purple_cipher_context_get_data(context); - - return hctx->blocksize; -} - -static PurpleCipherOps HMACOps = { - hmac_set_opt, /* Set option */ - hmac_get_opt, /* Get option */ - hmac_init, /* init */ - hmac_reset, /* reset */ - hmac_reset_state, /* reset state */ - hmac_uninit, /* uninit */ - NULL, /* set iv */ - hmac_append, /* append */ - hmac_digest, /* digest */ - hmac_get_digest_size, /* get digest size */ - NULL, /* encrypt */ - NULL, /* decrypt */ - NULL, /* set salt */ - NULL, /* get salt size */ - hmac_set_key, /* set key */ - NULL, /* get key size */ - NULL, /* set batch mode */ - NULL, /* get batch mode */ - hmac_get_block_size, /* get block size */ - NULL, NULL, NULL, NULL /* reserved */ -}; - -PurpleCipherOps * -purple_hmac_cipher_get_ops(void) { - return &HMACOps; -} - diff --git a/libpurple/ciphers/hmaccipher.c b/libpurple/ciphers/hmaccipher.c new file mode 100644 index 0000000000..0b27147221 --- /dev/null +++ b/libpurple/ciphers/hmaccipher.c @@ -0,0 +1,345 @@ +/* + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#include "hmaccipher.h" + +#include <string.h> + +/******************************************************************************* + * Structs + ******************************************************************************/ +#define PURPLE_HMAC_CIPHER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipherPrivate)) + +typedef struct { + PurpleHash *hash; + guchar *ipad; + guchar *opad; +} PurpleHMACCipherPrivate; + +/****************************************************************************** + * Enums + *****************************************************************************/ +enum { + PROP_NONE, + PROP_HASH, + PROP_LAST, +}; + +/******************************************************************************* + * Globals + ******************************************************************************/ +static GObjectClass *parent_class = NULL; + +/******************************************************************************* + * Helpers + ******************************************************************************/ +static void +purple_hmac_cipher_set_hash(PurpleCipher *cipher, + PurpleHash *hash) +{ + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + priv->hash = g_object_ref(G_OBJECT(hash)); + g_object_notify(G_OBJECT(cipher), "hash"); +} + +/******************************************************************************* + * Cipher Stuff + ******************************************************************************/ +static void +purple_hmac_cipher_reset(PurpleCipher *cipher) { + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + if(PURPLE_IS_HASH(priv->hash)) + purple_hash_reset(priv->hash); + + if(priv->ipad) { + g_free(priv->ipad); + priv->ipad = NULL; + } + if(priv->opad) { + g_free(priv->opad); + priv->opad = NULL; + } +} + +static void +purple_hmac_cipher_reset_state(PurpleCipher *cipher) { + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + if(PURPLE_IS_HASH(priv->hash)) { + purple_hash_reset_state(priv->hash); + purple_hash_append(priv->hash, priv->ipad, + purple_hash_get_block_size(priv->hash)); + } +} + +static void +purple_hmac_cipher_append(PurpleCipher *cipher, const guchar *d, size_t l) { + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + g_return_if_fail(PURPLE_IS_HASH(priv->hash)); + + purple_hash_append(priv->hash, d, l); +} + +static gboolean +purple_hmac_cipher_digest(PurpleCipher *cipher, guchar *out, size_t len) +{ + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + guchar *digest = NULL; + size_t hash_len, block_size; + gboolean result = FALSE; + + g_return_val_if_fail(PURPLE_IS_HASH(priv->hash), FALSE); + + hash_len = purple_hash_get_digest_size(priv->hash); + g_return_val_if_fail(hash_len > 0, FALSE); + + block_size = purple_hash_get_block_size(priv->hash); + digest = g_malloc(hash_len); + + /* get the digest of the data */ + result = purple_hash_digest(priv->hash, digest, hash_len); + purple_hash_reset(priv->hash); + + if(!result) { + g_free(digest); + + return FALSE; + } + + /* now append the opad and the digest from above */ + purple_hash_append(priv->hash, priv->opad, block_size); + purple_hash_append(priv->hash, digest, hash_len); + + /* do our last digest */ + result = purple_hash_digest(priv->hash, out, len); + + /* cleanup */ + g_free(digest); + + return result; +} + +static size_t +purple_hmac_cipher_get_digest_size(PurpleCipher *cipher) +{ + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + g_return_val_if_fail(priv->hash != NULL, 0); + + return purple_hash_get_digest_size(priv->hash); +} + +static void +purple_hmac_cipher_set_key(PurpleCipher *cipher, const guchar *key, + size_t key_len) +{ + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + gsize blocksize, i; + guchar *full_key; + + g_return_if_fail(priv->hash); + + g_free(priv->ipad); + g_free(priv->opad); + + block_size = purple_hash_get_block_size(priv->hash); + priv->ipad = g_malloc(block_size); + priv->opad = g_malloc(block_size); + + if (key_len > block_size) { + purple_hash_reset(priv->hash); + purple_hash_append(priv->hash, key, key_len); + + key_len = purple_hash_get_digest_size(priv->hash); + full_key = g_malloc(key_len); + purple_hash_digest(priv->hash, full_key, key_len); + } else { + full_key = g_memdup(key, key_len); + } + + if (key_len < block_size) { + full_key = g_realloc(full_key, block_size); + memset(full_key + key_len, 0, block_size - key_len); + } + + for(i = 0; i < block_size; i++) { + priv->ipad[i] = 0x36 ^ full_key[i]; + priv->opad[i] = 0x5c ^ full_key[i]; + } + + g_free(full_key); + + purple_hash_reset(priv->hash); + purple_hash_append(priv->hash, priv->ipad, block_size); +} + +static size_t +purple_hmac_cipher_get_block_size(PurpleCipher *cipher) +{ + PurpleHMACCipherPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_HMAC_CIPHER(cipher), 0); + + priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + return purple_hash_get_block_size(priv->hash); +} + +static const gchar* +purple_hmac_cipher_get_name(PurpleCipher *cipher) +{ + return "hmac"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_hmac_cipher_set_property(GObject *obj, guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + + switch(param_id) { + case PROP_HASH: + purple_hmac_cipher_set_hash(cipher, g_value_get_object(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_hmac_cipher_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleHMACCipher *cipher = PURPLE_HMAC_CIPHER(obj); + + switch(param_id) { + case PROP_HASH: + g_value_set_object(value, + purple_hmac_cipher_get_hash(cipher)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_hmac_cipher_finalize(GObject *obj) { + PurpleCipher *cipher = PURPLE_CIPHER(obj); + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + purple_hmac_cipher_reset(cipher); + + if (priv->hash != NULL) + g_object_unref(priv->hash); + + parent_class->finalize(obj); +} + +static void +purple_hmac_cipher_class_init(PurpleHMACCipherClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); + GParamSpec *pspec; + + parent_class = g_type_class_peek_parent(klass); + + g_type_class_add_private(klass, sizeof(PurpleHMACCipherPrivate)); + + obj_class->finalize = purple_hmac_cipher_finalize; + obj_class->get_property = purple_hmac_cipher_get_property; + obj_class->set_property = purple_hmac_cipher_set_property; + + cipher_class->reset = purple_hmac_cipher_reset; + cipher_class->reset_state = purple_hmac_cipher_reset_state; + cipher_class->append = purple_hmac_cipher_append; + cipher_class->digest = purple_hmac_cipher_digest; + cipher_class->get_digest_size = purple_hmac_cipher_get_digest_size; + cipher_class->set_key = purple_hmac_cipher_set_key; + cipher_class->get_block_size = purple_hmac_cipher_get_block_size; + cipher_class->get_name = purple_hmac_cipher_get_name; + + pspec = g_param_spec_object("hash", "hash", "hash", PURPLE_TYPE_HASH, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property(obj_class, PROP_HASH, pspec); +} + +/****************************************************************************** + * PurpleHMACCipher API + *****************************************************************************/ +GType +purple_hmac_cipher_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleHMACCipherClass), + NULL, + NULL, + (GClassInitFunc)purple_hmac_cipher_class_init, + NULL, + NULL, + sizeof(PurpleHMACCipher), + 0, + (GInstanceInitFunc)purple_cipher_reset, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_CIPHER, + "PurpleHMACCipher", + &info, 0); + } + + return type; +} + +PurpleCipher * +purple_hmac_cipher_new(PurpleHash *hash) { + g_return_val_if_fail(PURPLE_IS_HASH(hash), NULL); + + return g_object_new(PURPLE_TYPE_HMAC_CIPHER, + "hash", hash, + NULL); +} + +PurpleHash * +purple_hmac_cipher_get_hash(const PurpleHMACCipher *cipher) { + PurpleHMACCipherPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_HMAC_CIPHER(cipher), NULL); + + priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + if(priv && priv->hash) + return priv->hash; + + return NULL; +} + diff --git a/libpurple/ciphers/hmaccipher.h b/libpurple/ciphers/hmaccipher.h new file mode 100644 index 0000000000..713ae99406 --- /dev/null +++ b/libpurple/ciphers/hmaccipher.h @@ -0,0 +1,67 @@ +/** + * @file hmac.h Purple HMAC Cipher + * @ingroup core + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef PURPLE_HMAC_CIPHER_H +#define PURPLE_HMAC_CIPHER_H + +#include "cipher.h" +#include "hash.h" + +#define PURPLE_TYPE_HMAC_CIPHER (purple_hmac_cipher_get_gtype()) +#define PURPLE_HMAC_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipher)) +#define PURPLE_HMAC_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipherClass)) +#define PURPLE_IS_HMAC_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_HMAC_CIPHER)) +#define PURPLE_IS_HMAC_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_HMAC_CIPHER)) +#define PURPLE_HMAC_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipherClass)) + +typedef struct _PurpleHMACCipher PurpleHMACCipher; +typedef struct _PurpleHMACCipherClass PurpleHMACCipherClass; + +struct _PurpleHMACCipher { + /*< private >*/ + PurpleCipher gparent; +}; + +struct _PurpleHMACCipherClass { + /*< private >*/ + PurpleCipherClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_hmac_cipher_get_gtype(void); + +PurpleCipher *purple_hmac_cipher_new(PurpleHash *hash); + +PurpleHash *purple_hmac_cipher_get_hash(const PurpleHMACCipher *cipher); + +G_END_DECLS + +#endif /* PURPLE_HMAC_CIPHER_H */ diff --git a/libpurple/ciphers/md4.c b/libpurple/ciphers/md4.c deleted file mode 100644 index 25583424d4..0000000000 --- a/libpurple/ciphers/md4.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * Original md4 taken from linux kernel - * MD4 Message Digest Algorithm (RFC1320). - * - * Implementation derived from Andrew Tridgell and Steve French's - * CIFS MD4 implementation, and the cryptoapi implementation - * originally based on the public domain implementation written - * by Colin Plumb in 1993. - * - * Copyright (c) Andrew Tridgell 1997-1998. - * Modified by Steve French (sfrench@us.ibm.com) 2002 - * Copyright (c) Cryptoapi developers. - * Copyright (c) 2002 David S. Miller (davem@redhat.com) - * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#include "internal.h" -#include <cipher.h> -#include "ciphers.h" - -#define MD4_DIGEST_SIZE 16 -#define MD4_HMAC_BLOCK_SIZE 64 -#define MD4_BLOCK_WORDS 16 -#define MD4_HASH_WORDS 4 - -struct MD4_Context { - guint32 hash[MD4_HASH_WORDS]; - guint32 block[MD4_BLOCK_WORDS]; - guint64 byte_count; -}; - -static inline guint32 lshift(guint32 x, unsigned int s) -{ - x &= 0xFFFFFFFF; - return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s)); -} - -static inline guint32 F(guint32 x, guint32 y, guint32 z) -{ - return (x & y) | ((~x) & z); -} - -static inline guint32 G(guint32 x, guint32 y, guint32 z) -{ - return (x & y) | (x & z) | (y & z); -} - -static inline guint32 H(guint32 x, guint32 y, guint32 z) -{ - return x ^ y ^ z; -} - -#define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s)) -#define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (guint32)0x5A827999,s)) -#define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (guint32)0x6ED9EBA1,s)) - -static inline void le32_to_cpu_array(guint32 *buf, unsigned int words) -{ - while (words--) { - *buf=GUINT_FROM_LE(*buf); - buf++; - } -} - -static inline void cpu_to_le32_array(guint32 *buf, unsigned int words) -{ - while (words--) { - *buf=GUINT_TO_LE(*buf); - buf++; - } -} - -static void md4_transform(guint32 *hash, guint32 const *in) -{ - guint32 a, b, c, d; - - a = hash[0]; - b = hash[1]; - c = hash[2]; - d = hash[3]; - - ROUND1(a, b, c, d, in[0], 3); - ROUND1(d, a, b, c, in[1], 7); - ROUND1(c, d, a, b, in[2], 11); - ROUND1(b, c, d, a, in[3], 19); - ROUND1(a, b, c, d, in[4], 3); - ROUND1(d, a, b, c, in[5], 7); - ROUND1(c, d, a, b, in[6], 11); - ROUND1(b, c, d, a, in[7], 19); - ROUND1(a, b, c, d, in[8], 3); - ROUND1(d, a, b, c, in[9], 7); - ROUND1(c, d, a, b, in[10], 11); - ROUND1(b, c, d, a, in[11], 19); - ROUND1(a, b, c, d, in[12], 3); - ROUND1(d, a, b, c, in[13], 7); - ROUND1(c, d, a, b, in[14], 11); - ROUND1(b, c, d, a, in[15], 19); - - ROUND2(a, b, c, d,in[ 0], 3); - ROUND2(d, a, b, c, in[4], 5); - ROUND2(c, d, a, b, in[8], 9); - ROUND2(b, c, d, a, in[12], 13); - ROUND2(a, b, c, d, in[1], 3); - ROUND2(d, a, b, c, in[5], 5); - ROUND2(c, d, a, b, in[9], 9); - ROUND2(b, c, d, a, in[13], 13); - ROUND2(a, b, c, d, in[2], 3); - ROUND2(d, a, b, c, in[6], 5); - ROUND2(c, d, a, b, in[10], 9); - ROUND2(b, c, d, a, in[14], 13); - ROUND2(a, b, c, d, in[3], 3); - ROUND2(d, a, b, c, in[7], 5); - ROUND2(c, d, a, b, in[11], 9); - ROUND2(b, c, d, a, in[15], 13); - - ROUND3(a, b, c, d,in[ 0], 3); - ROUND3(d, a, b, c, in[8], 9); - ROUND3(c, d, a, b, in[4], 11); - ROUND3(b, c, d, a, in[12], 15); - ROUND3(a, b, c, d, in[2], 3); - ROUND3(d, a, b, c, in[10], 9); - ROUND3(c, d, a, b, in[6], 11); - ROUND3(b, c, d, a, in[14], 15); - ROUND3(a, b, c, d, in[1], 3); - ROUND3(d, a, b, c, in[9], 9); - ROUND3(c, d, a, b, in[5], 11); - ROUND3(b, c, d, a, in[13], 15); - ROUND3(a, b, c, d, in[3], 3); - ROUND3(d, a, b, c, in[11], 9); - ROUND3(c, d, a, b, in[7], 11); - ROUND3(b, c, d, a, in[15], 15); - - hash[0] += a; - hash[1] += b; - hash[2] += c; - hash[3] += d; -} - -static inline void md4_transform_helper(struct MD4_Context *ctx) -{ - le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(guint32)); - md4_transform(ctx->hash, ctx->block); -} - -static void -md4_init(PurpleCipherContext *context, gpointer extra) { - struct MD4_Context *mctx; - mctx = g_new0(struct MD4_Context, 1); - purple_cipher_context_set_data(context, mctx); - purple_cipher_context_reset(context, extra); - - mctx->hash[0] = 0x67452301; - mctx->hash[1] = 0xefcdab89; - mctx->hash[2] = 0x98badcfe; - mctx->hash[3] = 0x10325476; - mctx->byte_count = 0; -} - -static void -md4_reset(PurpleCipherContext *context, gpointer extra) { - struct MD4_Context *mctx; - - mctx = purple_cipher_context_get_data(context); - - mctx->hash[0] = 0x67452301; - mctx->hash[1] = 0xefcdab89; - mctx->hash[2] = 0x98badcfe; - mctx->hash[3] = 0x10325476; - mctx->byte_count = 0; -} - - static void -md4_append(PurpleCipherContext *context, const guchar *data, size_t len) -{ - struct MD4_Context *mctx = purple_cipher_context_get_data(context); - const guint32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); - - mctx->byte_count += len; - - if (avail > len) { - memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), - data, len); - return; - } - - memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), - data, avail); - - md4_transform_helper(mctx); - data += avail; - len -= avail; - - while (len >= sizeof(mctx->block)) { - memcpy(mctx->block, data, sizeof(mctx->block)); - md4_transform_helper(mctx); - data += sizeof(mctx->block); - len -= sizeof(mctx->block); - } - - memcpy(mctx->block, data, len); -} - - static gboolean -md4_digest(PurpleCipherContext *context, guchar *out, size_t len) -{ - struct MD4_Context *mctx = purple_cipher_context_get_data(context); - const unsigned int offset = mctx->byte_count & 0x3f; - char *p = (char *)mctx->block + offset; - int padding = 56 - (offset + 1); - - - if(len<16) return FALSE; - *p++ = 0x80; - if (padding < 0) { - memset(p, 0x00, padding + sizeof (guint64)); - md4_transform_helper(mctx); - p = (char *)mctx->block; - padding = 56; - } - - memset(p, 0, padding); - mctx->block[14] = mctx->byte_count << 3; - mctx->block[15] = mctx->byte_count >> 29; - le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - - sizeof(guint64)) / sizeof(guint32)); - md4_transform(mctx->hash, mctx->block); - cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(guint32)); - memcpy(out, mctx->hash, sizeof(mctx->hash)); - memset(mctx, 0, sizeof(*mctx)); - return TRUE; -} - - static size_t -md4_get_digest_size(PurpleCipherContext *context) -{ - return 16; -} - -static void -md4_uninit(PurpleCipherContext *context) { - struct MD4_Context *md4_context; - - purple_cipher_context_reset(context, NULL); - - md4_context = purple_cipher_context_get_data(context); - memset(md4_context, 0, sizeof(*md4_context)); - - g_free(md4_context); - md4_context = NULL; -} - - static size_t -md4_get_block_size(PurpleCipherContext *context) -{ - /* This does not change (in this case) */ - return MD4_HMAC_BLOCK_SIZE; -} - -static PurpleCipherOps MD4Ops = { - NULL, /* Set option */ - NULL, /* Get option */ - md4_init, /* init */ - md4_reset, /* reset */ - md4_reset, /* reset state */ - md4_uninit, /* uninit */ - NULL, /* set iv */ - md4_append, /* append */ - md4_digest, /* digest */ - md4_get_digest_size, /* get digest size */ - NULL, /* encrypt */ - NULL, /* decrypt */ - NULL, /* set salt */ - NULL, /* get salt size */ - NULL, /* set key */ - NULL, /* get key size */ - NULL, /* set batch mode */ - NULL, /* get batch mode */ - md4_get_block_size, /* get block size */ - NULL, NULL, NULL, NULL /* reserved */ -}; - -PurpleCipherOps * -purple_md4_cipher_get_ops(void) { - return &MD4Ops; -} - diff --git a/libpurple/ciphers/md4hash.c b/libpurple/ciphers/md4hash.c new file mode 100644 index 0000000000..b6a9a2e469 --- /dev/null +++ b/libpurple/ciphers/md4hash.c @@ -0,0 +1,317 @@ +/* + * Original md4 taken from linux kernel + * MD4 Message Digest Algorithm (RFC1320). + * + * Implementation derived from Andrew Tridgell and Steve French's + * CIFS MD4 implementation, and the cryptoapi implementation + * originally based on the public domain implementation written + * by Colin Plumb in 1993. + * + * Copyright (c) Andrew Tridgell 1997-1998. + * Modified by Steve French (sfrench@us.ibm.com) 2002 + * Copyright (c) Cryptoapi developers. + * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + */ +#include "md4hash.h" + +#include <string.h> + +#define MD4_DIGEST_SIZE 16 +#define MD4_BLOCK_WORDS 16 +#define MD4_HASH_WORDS 4 + +#define PURPLE_MD4_HASH_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MD4_HASH, PurpleMD4HashPrivate)) + +/****************************************************************************** + * Structs + *****************************************************************************/ +typedef struct { + guint32 hash[MD4_HASH_WORDS]; + guint32 block[MD4_BLOCK_WORDS]; + guint64 byte_count; +} PurpleMD4HashPrivate; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Helpers + *****************************************************************************/ +#define ROUND1(a,b,c,d,k,s) \ + (a = lshift(a + F(b,c,d) + k, s)) + +#define ROUND2(a,b,c,d,k,s) \ + (a = lshift(a + G(b,c,d) + k + (guint32)0x5a827999,s)) + +#define ROUND3(a,b,c,d,k,s) \ + (a = lshift(a + H(b,c,d) + k + (guint32)0x6ed9eba1,s)) + +static inline guint32 +lshift(guint32 x, unsigned int s) { + x &= 0xffffffff; + return (((x << s) & 0xffffffff) | (x >> (32 - s))); +} + +static inline guint32 +F(guint32 x, guint32 y, guint32 z) { + return ((x & y) | ((~x) & z)); +} + +static inline guint32 +G(guint32 x, guint32 y, guint32 z) { + return ((x & y) | (x & z) | (y & z)); +} + +static inline guint32 +H(guint32 x, guint32 y, guint32 z) { + return (x ^ y ^ z); +} + +static inline void +le32_to_cpu_array(guint32 *buf, unsigned int words) { + while(words--) { + *buf = GUINT_FROM_LE(*buf); + buf++; + } +} + +static inline void +cpu_to_le32_array(guint32 *buf, unsigned int words) { + while(words--) { + *buf = GUINT_TO_LE(*buf); + buf++; + } +} + +static void +md4_transform(guint32 *hash, guint32 const *in) { + guint32 a, b, c, d; + + a = hash[0]; + b = hash[1]; + c = hash[2]; + d = hash[3]; + + ROUND1(a, b, c, d, in[0], 3); + ROUND1(d, a, b, c, in[1], 7); + ROUND1(c, d, a, b, in[2], 11); + ROUND1(b, c, d, a, in[3], 19); + ROUND1(a, b, c, d, in[4], 3); + ROUND1(d, a, b, c, in[5], 7); + ROUND1(c, d, a, b, in[6], 11); + ROUND1(b, c, d, a, in[7], 19); + ROUND1(a, b, c, d, in[8], 3); + ROUND1(d, a, b, c, in[9], 7); + ROUND1(c, d, a, b, in[10], 11); + ROUND1(b, c, d, a, in[11], 19); + ROUND1(a, b, c, d, in[12], 3); + ROUND1(d, a, b, c, in[13], 7); + ROUND1(c, d, a, b, in[14], 11); + ROUND1(b, c, d, a, in[15], 19); + + ROUND2(a, b, c, d,in[ 0], 3); + ROUND2(d, a, b, c, in[4], 5); + ROUND2(c, d, a, b, in[8], 9); + ROUND2(b, c, d, a, in[12], 13); + ROUND2(a, b, c, d, in[1], 3); + ROUND2(d, a, b, c, in[5], 5); + ROUND2(c, d, a, b, in[9], 9); + ROUND2(b, c, d, a, in[13], 13); + ROUND2(a, b, c, d, in[2], 3); + ROUND2(d, a, b, c, in[6], 5); + ROUND2(c, d, a, b, in[10], 9); + ROUND2(b, c, d, a, in[14], 13); + ROUND2(a, b, c, d, in[3], 3); + ROUND2(d, a, b, c, in[7], 5); + ROUND2(c, d, a, b, in[11], 9); + ROUND2(b, c, d, a, in[15], 13); + + ROUND3(a, b, c, d,in[ 0], 3); + ROUND3(d, a, b, c, in[8], 9); + ROUND3(c, d, a, b, in[4], 11); + ROUND3(b, c, d, a, in[12], 15); + ROUND3(a, b, c, d, in[2], 3); + ROUND3(d, a, b, c, in[10], 9); + ROUND3(c, d, a, b, in[6], 11); + ROUND3(b, c, d, a, in[14], 15); + ROUND3(a, b, c, d, in[1], 3); + ROUND3(d, a, b, c, in[9], 9); + ROUND3(c, d, a, b, in[5], 11); + ROUND3(b, c, d, a, in[13], 15); + ROUND3(a, b, c, d, in[3], 3); + ROUND3(d, a, b, c, in[11], 9); + ROUND3(c, d, a, b, in[7], 11); + ROUND3(b, c, d, a, in[15], 15); + + hash[0] += a; + hash[1] += b; + hash[2] += c; + hash[3] += d; +} + +static inline void +md4_transform_helper(PurpleHash *hash) { + PurpleMD4HashPrivate *priv = PURPLE_MD4_HASH_GET_PRIVATE(hash); + + le32_to_cpu_array(priv->block, sizeof(priv->block) / sizeof(guint32)); + md4_transform(priv->hash, priv->block); +} + +/****************************************************************************** + * Hash Stuff + *****************************************************************************/ +static void +purple_md4_hash_reset(PurpleHash *hash) { + PurpleMD4HashPrivate *priv = PURPLE_MD4_HASH_GET_PRIVATE(hash); + + priv->hash[0] = 0x67452301; + priv->hash[1] = 0xefcdab89; + priv->hash[2] = 0x98badcfe; + priv->hash[3] = 0x10325476; + + priv->byte_count = 0; + + memset(priv->block, 0, sizeof(priv->block)); +} + +static void +purple_md4_hash_append(PurpleHash *hash, const guchar *data, size_t len) { + PurpleMD4HashPrivate *priv = PURPLE_MD4_HASH_GET_PRIVATE(hash); + const guint32 avail = sizeof(priv->block) - (priv->byte_count & 0x3f); + + priv->byte_count += len; + + if(avail > len) { + memcpy((char *)priv->block + + (sizeof(priv->block) - avail), + data, len); + return; + } + + memcpy((char *)priv->block + + (sizeof(priv->block) - avail), + data, avail); + + md4_transform_helper(hash); + data += avail; + len -= avail; + + while(len >= sizeof(priv->block)) { + memcpy(priv->block, data, sizeof(priv->block)); + md4_transform_helper(hash); + data += sizeof(priv->block); + len -= sizeof(priv->block); + } + + memcpy(priv->block, data, len); +} + +static gboolean +purple_md4_hash_digest(PurpleHash *hash, guchar *out, size_t len) +{ + PurpleMD4HashPrivate *priv = PURPLE_MD4_HASH_GET_PRIVATE(hash); + const unsigned int offset = priv->byte_count & 0x3f; + gchar *p = (gchar *)priv->block + offset; + gint padding = 56 - (offset + 1); + + if(len < 16) + return FALSE; + + *p++ = 0x80; + + if(padding < 0) { + memset(p, 0x00, padding + sizeof(guint64)); + md4_transform_helper(hash); + p = (gchar *)priv->block; + padding = 56; + } + + memset(p, 0, padding); + priv->block[14] = priv->byte_count << 3; + priv->block[15] = priv->byte_count >> 29; + le32_to_cpu_array(priv->block, + (sizeof(priv->block) - sizeof(guint64)) / + sizeof(guint32)); + md4_transform(priv->hash, priv->block); + cpu_to_le32_array(priv->hash, sizeof(priv->hash) / sizeof(guint32)); + memcpy(out, priv->hash, sizeof(priv->hash)); + + return TRUE; +} + +static size_t +purple_md4_hash_get_digest_size(PurpleHash *hash) +{ + return 16; +} + +static size_t +purple_md4_hash_get_block_size(PurpleHash *hash) +{ + /* This does not change (in this case) */ + return 64; +} + +static const gchar* +purple_md4_hash_get_name(PurpleHash *hash) +{ + return "md4"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_md4_hash_class_init(PurpleMD4HashClass *klass) { + PurpleHashClass *hash_class = PURPLE_HASH_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + g_type_class_add_private(klass, sizeof(PurpleMD4HashPrivate)); + + hash_class->reset = purple_md4_hash_reset; + hash_class->reset_state = purple_md4_hash_reset; + hash_class->append = purple_md4_hash_append; + hash_class->digest = purple_md4_hash_digest; + hash_class->get_digest_size = purple_md4_hash_get_digest_size; + hash_class->get_block_size = purple_md4_hash_get_block_size; + hash_class->get_name = purple_md4_hash_get_name; +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_md4_hash_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleMD4HashClass), + NULL, + NULL, + (GClassInitFunc)purple_md4_hash_class_init, + NULL, + NULL, + sizeof(PurpleMD4Hash), + 0, + (GInstanceInitFunc)purple_hash_reset, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_HASH, + "PurpleMD4Hash", + &info, 0); + } + + return type; +} + +PurpleHash * +purple_md4_hash_new(void) { + return g_object_new(PURPLE_TYPE_MD4_HASH, NULL); +} diff --git a/libpurple/ciphers/md4hash.h b/libpurple/ciphers/md4hash.h new file mode 100644 index 0000000000..6ebb3ec3b2 --- /dev/null +++ b/libpurple/ciphers/md4hash.h @@ -0,0 +1,63 @@ +/** + * @file md4.h Purple MD4 hash + * @ingroup core + * + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef PURPLE_MD4_HASH_H +#define PURPLE_MD4_HASH_H + +#include "hash.h" + +#define PURPLE_TYPE_MD4_HASH (purple_md4_hash_get_gtype()) +#define PURPLE_MD4_HASH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MD4_HASH, PurpleMD4Hash)) +#define PURPLE_MD4_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_MD4_HASH, PurpleMD4HashClass)) +#define PURPLE_IS_MD4_HASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_MD4_HASH)) +#define PURPLE_IS_MD4_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_MD4_HASH)) +#define PURPLE_MD4_HASH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MD4_HASH, PurpleMD4HashClass)) + +typedef struct _PurpleMD4Hash PurpleMD4Hash; +typedef struct _PurpleMD4HashClass PurpleMD4HashClass; + +struct _PurpleMD4Hash { + /*< private >*/ + PurpleHash parent; +}; + +struct _PurpleMD4HashClass { + /*< private >*/ + PurpleHashClass parent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_md4_hash_get_gtype(void); + +PurpleHash *purple_md4_hash_new(void); + +G_END_DECLS + +#endif /* PURPLE_MD4_HASH_H */ diff --git a/libpurple/ciphers/md5hash.c b/libpurple/ciphers/md5hash.c new file mode 100644 index 0000000000..6100a94361 --- /dev/null +++ b/libpurple/ciphers/md5hash.c @@ -0,0 +1,195 @@ +/* + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#include "md5hash.h" + +/******************************************************************************* + * Structs + ******************************************************************************/ +#define PURPLE_MD5_HASH_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MD5_HASH, PurpleMD5HashPrivate)) + +typedef struct { + GChecksum *checksum; +} PurpleMD5HashPrivate; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Hash Stuff + *****************************************************************************/ + +static void +purple_md5_hash_reset(PurpleHash *hash) +{ + PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(hash); + PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->checksum != NULL); + + g_checksum_reset(priv->checksum); +} + +static void +purple_md5_hash_append(PurpleHash *hash, const guchar *data, + gsize len) +{ + PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(hash); + PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->checksum != NULL); + + while (len >= G_MAXSSIZE) { + g_checksum_update(priv->checksum, data, G_MAXSSIZE); + len -= G_MAXSSIZE; + data += G_MAXSSIZE; + } + + if (len) + g_checksum_update(priv->checksum, data, len); +} + +static gboolean +purple_md5_hash_digest(PurpleHash *hash, guchar *digest, size_t buff_len) +{ + PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(hash); + PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash); + + const gssize required_len = g_checksum_type_get_length(G_CHECKSUM_MD5); + gsize digest_len = buff_len; + + g_return_val_if_fail(priv != NULL, FALSE); + g_return_val_if_fail(priv->checksum != NULL, FALSE); + g_return_val_if_fail(buff_len >= required_len, FALSE); + + g_checksum_get_digest(priv->checksum, digest, &digest_len); + + if (digest_len != required_len) + return FALSE; + + purple_md5_hash_reset(hash); + + return TRUE; +} + +static size_t +purple_md5_hash_get_block_size(PurpleHash *hash) +{ + return 64; +} + +static size_t +purple_md5_hash_get_digest_size(PurpleHash *hash) +{ + return g_checksum_type_get_length(G_CHECKSUM_MD5); +} + +static const gchar* +purple_md5_hash_get_name(PurpleHash *hash) +{ + return "md5"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ + +static void +purple_md5_hash_finalize(GObject *obj) +{ + PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(obj); + PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash); + + if (priv->checksum) + g_checksum_free(priv->checksum); + + parent_class->finalize(obj); +} + +static void +purple_md5_hash_class_init(PurpleMD5HashClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleHashClass *hash_class = PURPLE_HASH_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->finalize = purple_md5_hash_finalize; + + hash_class->reset = purple_md5_hash_reset; + hash_class->reset_state = purple_md5_hash_reset; + hash_class->append = purple_md5_hash_append; + hash_class->digest = purple_md5_hash_digest; + hash_class->get_digest_size = purple_md5_hash_get_digest_size; + hash_class->get_block_size = purple_md5_hash_get_block_size; + hash_class->get_name = purple_md5_hash_get_name; + + g_type_class_add_private(klass, sizeof(PurpleMD5HashPrivate)); +} + +static void +purple_md5_hash_init(PurpleHash *hash) +{ + PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(hash); + PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash); + + priv->checksum = g_checksum_new(G_CHECKSUM_MD5); + + purple_md5_hash_reset(hash); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_md5_hash_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleMD5HashClass), + NULL, + NULL, + (GClassInitFunc)purple_md5_hash_class_init, + NULL, + NULL, + sizeof(PurpleMD5Hash), + 0, + (GInstanceInitFunc)purple_md5_hash_init, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_HASH, + "PurpleMD5Hash", + &info, 0); + } + + return type; +} + +PurpleHash * +purple_md5_hash_new(void) { + return g_object_new(PURPLE_TYPE_MD5_HASH, NULL); +} diff --git a/libpurple/ciphers/md5hash.h b/libpurple/ciphers/md5hash.h new file mode 100644 index 0000000000..3501bcf1c0 --- /dev/null +++ b/libpurple/ciphers/md5hash.h @@ -0,0 +1,64 @@ +/** + * @file md5.h Purple MD5 Hash + * @ingroup core + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef PURPLE_MD5_HASH_H +#define PURPLE_MD5_HASH_H + +#include "hash.h" + +#define PURPLE_TYPE_MD5_HASH (purple_md5_hash_get_gtype()) +#define PURPLE_MD5_HASH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MD5_HASH, PurpleMD5Hash)) +#define PURPLE_MD5_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_MD5_HASH, PurpleMD5HashClass)) +#define PURPLE_IS_MD5_HASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_MD5_HASH)) +#define PURPLE_IS_MD5_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_MD5_HASH)) +#define PURPLE_MD5_HASH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MD5_HASH, PurpleMD5HashClass)) + +typedef struct _PurpleMD5Hash PurpleMD5Hash; +typedef struct _PurpleMD5HashClass PurpleMD5HashClass; + +struct _PurpleMD5Hash { + /*< private >*/ + PurpleHash gparent; +}; + +struct _PurpleMD5HashClass { + /*< private >*/ + PurpleHashClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_md5_hash_get_gtype(void); + +PurpleHash *purple_md5_hash_new(void); + +G_END_DECLS + +#endif /* PURPLE_MD5_HASH_H */ diff --git a/libpurple/ciphers/pbkdf2.c b/libpurple/ciphers/pbkdf2.c deleted file mode 100644 index 51f31d08c9..0000000000 --- a/libpurple/ciphers/pbkdf2.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - * - * Written by Tomek Wasilczyk <tomkiewicz@cpw.pidgin.im> - */ - -#include "internal.h" -#include "cipher.h" -#include "ciphers.h" -#include "debug.h" - -/* 1024bit */ -#define PBKDF2_HASH_MAX_LEN 128 - -typedef struct -{ - gchar *hash_func; - guint iter_count; - size_t out_len; - - guchar *salt; - size_t salt_len; - guchar *passphrase; - size_t passphrase_len; -} Pbkdf2Context; - -static void -purple_pbkdf2_init(PurpleCipherContext *context, void *extra) -{ - Pbkdf2Context *ctx_data; - - ctx_data = g_new0(Pbkdf2Context, 1); - purple_cipher_context_set_data(context, ctx_data); - - purple_cipher_context_reset(context, extra); -} - -static void -purple_pbkdf2_uninit(PurpleCipherContext *context) -{ - Pbkdf2Context *ctx_data; - - purple_cipher_context_reset(context, NULL); - - ctx_data = purple_cipher_context_get_data(context); - g_free(ctx_data); - purple_cipher_context_set_data(context, NULL); -} - -static void -purple_pbkdf2_reset(PurpleCipherContext *context, void *extra) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - - g_return_if_fail(ctx_data != NULL); - - g_free(ctx_data->hash_func); - ctx_data->hash_func = NULL; - ctx_data->iter_count = 1; - ctx_data->out_len = 256; - - purple_cipher_context_reset_state(context, extra); -} - -static void -purple_pbkdf2_reset_state(PurpleCipherContext *context, void *extra) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - - g_return_if_fail(ctx_data != NULL); - - purple_cipher_context_set_salt(context, NULL, 0); - purple_cipher_context_set_key(context, NULL, 0); -} - -static void -purple_pbkdf2_set_option(PurpleCipherContext *context, const gchar *name, - void *value) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - - g_return_if_fail(ctx_data != NULL); - - if (g_strcmp0(name, "hash") == 0) { - g_free(ctx_data->hash_func); - ctx_data->hash_func = g_strdup(value); - return; - } - - if (g_strcmp0(name, "iter_count") == 0) { - ctx_data->iter_count = GPOINTER_TO_UINT(value); - return; - } - - if (g_strcmp0(name, "out_len") == 0) { - ctx_data->out_len = GPOINTER_TO_UINT(value); - return; - } - - purple_debug_warning("pbkdf2", "Unknown option: %s\n", - name ? name : "(null)"); -} - -static void * -purple_pbkdf2_get_option(PurpleCipherContext *context, const gchar *name) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - - g_return_val_if_fail(ctx_data != NULL, NULL); - - if (g_strcmp0(name, "hash") == 0) - return ctx_data->hash_func; - - if (g_strcmp0(name, "iter_count") == 0) - return GUINT_TO_POINTER(ctx_data->iter_count); - - if (g_strcmp0(name, "out_len") == 0) - return GUINT_TO_POINTER(ctx_data->out_len); - - purple_debug_warning("pbkdf2", "Unknown option: %s\n", - name ? name : "(null)"); - return NULL; -} - -static size_t -purple_pbkdf2_get_digest_size(PurpleCipherContext *context) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - - g_return_val_if_fail(ctx_data != NULL, 0); - - return ctx_data->out_len; -} - -static void -purple_pbkdf2_set_salt(PurpleCipherContext *context, const guchar *salt, size_t len) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - - g_return_if_fail(ctx_data != NULL); - - g_free(ctx_data->salt); - ctx_data->salt = NULL; - ctx_data->salt_len = 0; - - if (len == 0) - return; - g_return_if_fail(salt != NULL); - - ctx_data->salt = g_memdup(salt, len); - ctx_data->salt_len = len; -} - -static void -purple_pbkdf2_set_key(PurpleCipherContext *context, const guchar *key, - size_t len) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - - g_return_if_fail(ctx_data != NULL); - - if (ctx_data->passphrase != NULL) { - memset(ctx_data->passphrase, 0, ctx_data->passphrase_len); - g_free(ctx_data->passphrase); - ctx_data->passphrase = NULL; - } - ctx_data->passphrase_len = 0; - - if (len == 0) - return; - g_return_if_fail(key != NULL); - - ctx_data->passphrase = g_memdup(key, len); - ctx_data->passphrase_len = len; -} - -/* inspired by gnutls 3.1.10, pbkdf2-sha1.c */ -static gboolean -purple_pbkdf2_digest(PurpleCipherContext *context, guchar digest[], size_t len) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - guchar halfkey[PBKDF2_HASH_MAX_LEN], halfkey_hash[PBKDF2_HASH_MAX_LEN]; - guint halfkey_len, halfkey_count, halfkey_pad, halfkey_no; - guchar *salt_ext; - size_t salt_ext_len; - guint iter_no; - PurpleCipherContext *hash; - - g_return_val_if_fail(ctx_data != NULL, FALSE); - g_return_val_if_fail(digest != NULL, FALSE); - g_return_val_if_fail(len >= ctx_data->out_len, FALSE); - - g_return_val_if_fail(ctx_data->hash_func != NULL, FALSE); - g_return_val_if_fail(ctx_data->iter_count > 0, FALSE); - g_return_val_if_fail(ctx_data->passphrase != NULL || - ctx_data->passphrase_len == 0, FALSE); - g_return_val_if_fail(ctx_data->salt != NULL || ctx_data->salt_len == 0, - FALSE); - g_return_val_if_fail(ctx_data->out_len > 0, FALSE); - g_return_val_if_fail(ctx_data->out_len < 0xFFFFFFFFU, FALSE); - - salt_ext_len = ctx_data->salt_len + 4; - - hash = purple_cipher_context_new_by_name("hmac", NULL); - if (hash == NULL) { - purple_debug_error("pbkdf2", "Couldn't create new hmac " - "context\n"); - return FALSE; - } - purple_cipher_context_set_option(hash, "hash", - (void*)ctx_data->hash_func); - purple_cipher_context_set_key(hash, (const guchar*)ctx_data->passphrase, - ctx_data->passphrase_len); - - halfkey_len = purple_cipher_context_get_digest_size(hash); - if (halfkey_len <= 0 || halfkey_len > PBKDF2_HASH_MAX_LEN) { - purple_debug_error("pbkdf2", "Unsupported hash function: %s " - "(digest size: %d)\n", - ctx_data->hash_func ? ctx_data->hash_func : "(null)", - halfkey_len); - return FALSE; - } - - halfkey_count = ((ctx_data->out_len - 1) / halfkey_len) + 1; - halfkey_pad = ctx_data->out_len - (halfkey_count - 1) * halfkey_len; - - salt_ext = g_new(guchar, salt_ext_len); - memcpy(salt_ext, ctx_data->salt, ctx_data->salt_len); - - for (halfkey_no = 1; halfkey_no <= halfkey_count; halfkey_no++) { - memset(halfkey, 0, halfkey_len); - - for (iter_no = 1; iter_no <= ctx_data->iter_count; iter_no++) { - guint i; - - purple_cipher_context_reset_state(hash, NULL); - - if (iter_no == 1) { - salt_ext[salt_ext_len - 4] = - (halfkey_no & 0xff000000) >> 24; - salt_ext[salt_ext_len - 3] = - (halfkey_no & 0x00ff0000) >> 16; - salt_ext[salt_ext_len - 2] = - (halfkey_no & 0x0000ff00) >> 8; - salt_ext[salt_ext_len - 1] = - (halfkey_no & 0x000000ff) >> 0; - - purple_cipher_context_append(hash, salt_ext, - salt_ext_len); - } - else - purple_cipher_context_append(hash, halfkey_hash, - halfkey_len); - - if (!purple_cipher_context_digest(hash, halfkey_hash, - halfkey_len)) { - purple_debug_error("pbkdf2", - "Couldn't retrieve a digest\n"); - g_free(salt_ext); - purple_cipher_context_destroy(hash); - return FALSE; - } - - for (i = 0; i < halfkey_len; i++) - halfkey[i] ^= halfkey_hash[i]; - } - - memcpy(digest + (halfkey_no - 1) * halfkey_len, halfkey, - (halfkey_no == halfkey_count) ? halfkey_pad : - halfkey_len); - } - - g_free(salt_ext); - purple_cipher_context_destroy(hash); - - return TRUE; -} - -static PurpleCipherOps PBKDF2Ops = { - purple_pbkdf2_set_option, /* set_option */ - purple_pbkdf2_get_option, /* get_option */ - purple_pbkdf2_init, /* init */ - purple_pbkdf2_reset, /* reset */ - purple_pbkdf2_reset_state, /* reset_state */ - purple_pbkdf2_uninit, /* uninit */ - NULL, /* set_iv */ - NULL, /* append */ - purple_pbkdf2_digest, /* digest */ - purple_pbkdf2_get_digest_size, /* get_digest_size */ - NULL, /* encrypt */ - NULL, /* decrypt */ - purple_pbkdf2_set_salt, /* set_salt */ - NULL, /* get_salt_size */ - purple_pbkdf2_set_key, /* set_key */ - NULL, /* get_key_size */ - NULL, /* set_batch_mode */ - NULL, /* get_batch_mode */ - NULL, /* get_block_size */ - NULL, NULL, NULL, NULL /* reserved */ -}; - -PurpleCipherOps * -purple_pbkdf2_cipher_get_ops(void) { - return &PBKDF2Ops; -} diff --git a/libpurple/ciphers/pbkdf2cipher.c b/libpurple/ciphers/pbkdf2cipher.c new file mode 100644 index 0000000000..bd54c41348 --- /dev/null +++ b/libpurple/ciphers/pbkdf2cipher.c @@ -0,0 +1,418 @@ +/* + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + * Written by Tomek Wasilczyk <tomkiewicz@cpw.pidgin.im> + */ + +#include "pbkdf2cipher.h" +#include "hmaccipher.h" +#include "debug.h" + +/* 1024bit */ +#define PBKDF2_HASH_MAX_LEN 128 + +/****************************************************************************** + * Structs + *****************************************************************************/ +#define PURPLE_PBKDF2_CIPHER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_PBKDF2_CIPHER, PurplePBKDF2CipherPrivate)) + +typedef struct { + PurpleHash *hash; + guint iter_count; + size_t out_len; + + guchar *salt; + size_t salt_len; + guchar *passphrase; + size_t passphrase_len; +} PurplePBKDF2CipherPrivate; + +/****************************************************************************** + * Enums + *****************************************************************************/ +enum { + PROP_NONE, + PROP_HASH, + PROP_ITER_COUNT, + PROP_OUT_LEN, + PROP_LAST, +}; + +/******************************************************************************* + * Globals + ******************************************************************************/ +static GObjectClass *parent_class = NULL; + +/******************************************************************************* + * Helpers + ******************************************************************************/ +static void +purple_pbkdf2_cipher_set_hash(PurpleCipher *cipher, + PurpleHash *hash) +{ + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + priv->hash = g_object_ref(G_OBJECT(hash)); + g_object_notify(G_OBJECT(cipher), "hash"); +} + +/****************************************************************************** + * Cipher Stuff + *****************************************************************************/ +static void +purple_pbkdf2_cipher_reset(PurpleCipher *cipher) +{ + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + g_return_if_fail(priv != NULL); + + if(PURPLE_IS_HASH(priv->hash)) + purple_hash_reset(priv->hash); + priv->iter_count = 1; + priv->out_len = 256; + + purple_cipher_reset_state(cipher); +} + +static void +purple_pbkdf2_cipher_reset_state(PurpleCipher *cipher) +{ + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + g_return_if_fail(priv != NULL); + + purple_cipher_set_salt(cipher, NULL, 0); + purple_cipher_set_key(cipher, NULL, 0); +} + +static size_t +purple_pbkdf2_cipher_get_digest_size(PurpleCipher *cipher) +{ + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + g_return_val_if_fail(priv != NULL, 0); + + return priv->out_len; +} + +static void +purple_pbkdf2_cipher_set_salt(PurpleCipher *cipher, const guchar *salt, size_t len) +{ + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + g_return_if_fail(priv != NULL); + + g_free(priv->salt); + priv->salt = NULL; + priv->salt_len = 0; + + if (len == 0) + return; + g_return_if_fail(salt != NULL); + + priv->salt = g_memdup(salt, len); + priv->salt_len = len; +} + +static void +purple_pbkdf2_cipher_set_key(PurpleCipher *cipher, const guchar *key, + size_t len) +{ + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + g_return_if_fail(priv != NULL); + + if (priv->passphrase != NULL) { + memset(priv->passphrase, 0, priv->passphrase_len); + g_free(priv->passphrase); + priv->passphrase = NULL; + } + priv->passphrase_len = 0; + + if (len == 0) + return; + g_return_if_fail(key != NULL); + + priv->passphrase = g_memdup(key, len); + priv->passphrase_len = len; +} + +/* inspired by gnutls 3.1.10, pbkdf2-sha1.c */ +static gboolean +purple_pbkdf2_cipher_digest(PurpleCipher *cipher, guchar digest[], size_t len) +{ + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + guchar halfkey[PBKDF2_HASH_MAX_LEN], halfkey_hash[PBKDF2_HASH_MAX_LEN]; + guint halfkey_len, halfkey_count, halfkey_pad, halfkey_no; + guchar *salt_ext; + size_t salt_ext_len; + guint iter_no; + PurpleCipher *hash; + + g_return_val_if_fail(priv != NULL, FALSE); + g_return_val_if_fail(digest != NULL, FALSE); + g_return_val_if_fail(len >= priv->out_len, FALSE); + + g_return_val_if_fail(priv->hash != NULL, FALSE); + g_return_val_if_fail(priv->iter_count > 0, FALSE); + g_return_val_if_fail(priv->passphrase != NULL || + priv->passphrase_len == 0, FALSE); + g_return_val_if_fail(priv->salt != NULL || priv->salt_len == 0, + FALSE); + g_return_val_if_fail(priv->out_len > 0, FALSE); + g_return_val_if_fail(priv->out_len < 0xFFFFFFFFU, FALSE); + + salt_ext_len = priv->salt_len + 4; + + hash = purple_hmac_cipher_new(priv->hash); + if (hash == NULL) { + purple_debug_error("pbkdf2", "Couldn't create new hmac " + "cipher\n"); + return FALSE; + } + purple_cipher_set_key(hash, (const guchar*)priv->passphrase, + priv->passphrase_len); + + halfkey_len = purple_cipher_get_digest_size(hash); + if (halfkey_len <= 0 || halfkey_len > PBKDF2_HASH_MAX_LEN) { + purple_debug_error("pbkdf2", "Unsupported hash function. " + "(digest size: %d)\n", halfkey_len); + return FALSE; + } + + halfkey_count = ((priv->out_len - 1) / halfkey_len) + 1; + halfkey_pad = priv->out_len - (halfkey_count - 1) * halfkey_len; + + salt_ext = g_new(guchar, salt_ext_len); + memcpy(salt_ext, priv->salt, priv->salt_len); + + for (halfkey_no = 1; halfkey_no <= halfkey_count; halfkey_no++) { + memset(halfkey, 0, halfkey_len); + + for (iter_no = 1; iter_no <= priv->iter_count; iter_no++) { + guint i; + + purple_cipher_reset_state(hash); + + if (iter_no == 1) { + salt_ext[salt_ext_len - 4] = + (halfkey_no & 0xff000000) >> 24; + salt_ext[salt_ext_len - 3] = + (halfkey_no & 0x00ff0000) >> 16; + salt_ext[salt_ext_len - 2] = + (halfkey_no & 0x0000ff00) >> 8; + salt_ext[salt_ext_len - 1] = + (halfkey_no & 0x000000ff) >> 0; + + purple_cipher_append(hash, salt_ext, + salt_ext_len); + } + else + purple_cipher_append(hash, halfkey_hash, + halfkey_len); + + if (!purple_cipher_digest(hash, halfkey_hash, + halfkey_len)) { + purple_debug_error("pbkdf2", + "Couldn't retrieve a digest\n"); + g_free(salt_ext); + g_object_unref(hash); + return FALSE; + } + + for (i = 0; i < halfkey_len; i++) + halfkey[i] ^= halfkey_hash[i]; + } + + memcpy(digest + (halfkey_no - 1) * halfkey_len, halfkey, + (halfkey_no == halfkey_count) ? halfkey_pad : + halfkey_len); + } + + g_free(salt_ext); + g_object_unref(hash); + + return TRUE; +} + +static const gchar* +purple_pbkdf2_cipher_get_name(PurpleCipher *cipher) +{ + return "pbkdf2"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_pbkdf2_cipher_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurplePBKDF2Cipher *cipher = PURPLE_PBKDF2_CIPHER(obj); + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + switch(param_id) { + case PROP_HASH: + g_value_set_object(value, purple_pbkdf2_cipher_get_hash(cipher)); + break; + case PROP_ITER_COUNT: + g_value_set_uint(value, priv->iter_count); + break; + case PROP_OUT_LEN: + g_value_set_uint(value, priv->out_len); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_pbkdf2_cipher_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + switch(param_id) { + case PROP_HASH: + purple_pbkdf2_cipher_set_hash(cipher, g_value_get_object(value)); + break; + case PROP_ITER_COUNT: + priv->iter_count = GPOINTER_TO_UINT(value); + break; + case PROP_OUT_LEN: + priv->out_len = GPOINTER_TO_UINT(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_pbkdf2_cipher_finalize(GObject *obj) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + purple_pbkdf2_cipher_reset(cipher); + + if (priv->hash != NULL) + g_object_unref(priv->hash); + + parent_class->finalize(obj); +} + +static void +purple_pbkdf2_cipher_class_init(PurplePBKDF2CipherClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); + GParamSpec *pspec; + + parent_class = g_type_class_peek_parent(klass); + + obj_class->finalize = purple_pbkdf2_cipher_finalize; + obj_class->get_property = purple_pbkdf2_cipher_get_property; + obj_class->set_property = purple_pbkdf2_cipher_set_property; + + cipher_class->reset = purple_pbkdf2_cipher_reset; + cipher_class->reset_state = purple_pbkdf2_cipher_reset_state; + cipher_class->digest = purple_pbkdf2_cipher_digest; + cipher_class->get_digest_size = purple_pbkdf2_cipher_get_digest_size; + cipher_class->set_salt = purple_pbkdf2_cipher_set_salt; + cipher_class->set_key = purple_pbkdf2_cipher_set_key; + cipher_class->get_name = purple_pbkdf2_cipher_get_name; + + pspec = g_param_spec_object("hash", "hash", "hash", PURPLE_TYPE_HASH, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property(obj_class, PROP_HASH, pspec); + + pspec = g_param_spec_uint("iter_count", "iter_count", "iter_count", 0, + G_MAXUINT, 0, G_PARAM_READWRITE); + g_object_class_install_property(obj_class, PROP_ITER_COUNT, pspec); + + pspec = g_param_spec_uint("out_len", "out_len", "out_len", 0, + G_MAXUINT, 0, G_PARAM_READWRITE); + g_object_class_install_property(obj_class, PROP_OUT_LEN, pspec); + + g_type_class_add_private(klass, sizeof(PurplePBKDF2CipherPrivate)); +} + +static void +purple_pbkdf2_cipher_init(PurpleCipher *cipher) +{ + purple_cipher_reset(cipher); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_pbkdf2_cipher_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurplePBKDF2CipherClass), + NULL, + NULL, + (GClassInitFunc)purple_pbkdf2_cipher_class_init, + NULL, + NULL, + sizeof(PurplePBKDF2Cipher), + 0, + (GInstanceInitFunc)purple_pbkdf2_cipher_init, + NULL + }; + + type = g_type_register_static(PURPLE_TYPE_CIPHER, + "PurplePBKDF2Cipher", + &info, 0); + } + + return type; +} + +PurpleCipher * +purple_pbkdf2_cipher_new(PurpleHash *hash) { + g_return_val_if_fail(PURPLE_IS_HASH(hash), NULL); + + return g_object_new(PURPLE_TYPE_PBKDF2_CIPHER, + "hash", hash, + NULL); +} + +PurpleHash * +purple_pbkdf2_cipher_get_hash(const PurplePBKDF2Cipher *cipher) { + PurplePBKDF2CipherPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_PBKDF2_CIPHER(cipher), NULL); + + priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + if(priv && priv->hash) + return priv->hash; + + return NULL; +} diff --git a/libpurple/ciphers/pbkdf2cipher.h b/libpurple/ciphers/pbkdf2cipher.h new file mode 100644 index 0000000000..fc09e6236c --- /dev/null +++ b/libpurple/ciphers/pbkdf2cipher.h @@ -0,0 +1,68 @@ +/** + * @file pbkdf2.h Purple PBKDF2 Cipher + * @ingroup core + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef PURPLE_PBKDF2_CIPHER_H +#define PURPLE_PBKDF2_CIPHER_H + +#include "cipher.h" +#include "hash.h" + +#define PURPLE_TYPE_PBKDF2_CIPHER (purple_pbkdf2_cipher_get_gtype()) +#define PURPLE_PBKDF2_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_PBKDF2_CIPHER, PurplePBKDF2Cipher)) +#define PURPLE_PBKDF2_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_PBKDF2_CIPHER, PurplePBKDF2CipherClass)) +#define PURPLE_IS_PBKDF2_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_PBKDF2_CIPHER)) +#define PURPLE_IS_PBKDF2_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_PBKDF2_CIPHER)) +#define PURPLE_PBKDF2_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_PBKDF2_CIPHER, PurplePBKDF2CipherClass)) + +typedef struct _PurplePBKDF2Cipher PurplePBKDF2Cipher; +typedef struct _PurplePBKDF2CipherClass PurplePBKDF2CipherClass; + +struct _PurplePBKDF2Cipher { + /*< private >*/ + PurpleCipher gparent; +}; + +struct _PurplePBKDF2CipherClass { + /*< private >*/ + PurpleCipherClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_pbkdf2_cipher_get_gtype(void); + +PurpleCipher *purple_pbkdf2_cipher_new(PurpleHash *hash); + +PurpleHash *purple_pbkdf2_cipher_get_hash(const PurplePBKDF2Cipher *cipher); + +G_END_DECLS + +#endif /* PURPLE_PBKDF2_CIPHER_H */ + diff --git a/libpurple/ciphers/rc4.c b/libpurple/ciphers/rc4.c deleted file mode 100644 index de8101f58b..0000000000 --- a/libpurple/ciphers/rc4.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#include "internal.h" -#include <cipher.h> -#include "ciphers.h" -#include <util.h> - -struct RC4Context { - guchar state[256]; - guchar x; - guchar y; - gint key_len; -}; - -static void -rc4_init(PurpleCipherContext *context, void *extra) { - struct RC4Context *rc4_ctx; - rc4_ctx = g_new0(struct RC4Context, 1); - purple_cipher_context_set_data(context, rc4_ctx); - purple_cipher_context_reset(context, extra); -} - - -static void -rc4_reset(PurpleCipherContext *context, void *extra) { - struct RC4Context *rc4_ctx; - guint i; - - rc4_ctx = purple_cipher_context_get_data(context); - - g_return_if_fail(rc4_ctx); - - for(i = 0; i < 256; i++) - rc4_ctx->state[i] = i; - rc4_ctx->x = 0; - rc4_ctx->y = 0; - - /* default is 5 bytes (40bit key) */ - rc4_ctx->key_len = 5; - -} - -static void -rc4_uninit(PurpleCipherContext *context) { - struct RC4Context *rc4_ctx; - - rc4_ctx = purple_cipher_context_get_data(context); - memset(rc4_ctx, 0, sizeof(*rc4_ctx)); - - g_free(rc4_ctx); - rc4_ctx = NULL; -} - - - -static void -rc4_set_key (PurpleCipherContext *context, const guchar * key, size_t len) { - struct RC4Context *ctx; - guchar *state; - guchar temp_swap; - guchar x, y; - guint i; - - ctx = purple_cipher_context_get_data(context); - - x = 0; - y = 0; - state = &ctx->state[0]; - ctx->key_len = len; - for(i = 0; i < 256; i++) - { - y = (key[x] + state[i] + y) % 256; - temp_swap = state[i]; - state[i] = state[y]; - state[y] = temp_swap; - x = (x + 1) % len; - } -} - - -static ssize_t -rc4_encrypt(PurpleCipherContext *context, const guchar input[], size_t in_len, - guchar output[], size_t out_size) { - struct RC4Context *ctx; - guchar temp_swap; - guchar x, y, z; - guchar *state; - guint i; - - ctx = purple_cipher_context_get_data(context); - - x = ctx->x; - y = ctx->y; - state = &ctx->state[0]; - - for(i = 0; i < in_len; i++) - { - x = (x + 1) % 256; - y = (state[x] + y) % 256; - temp_swap = state[x]; - state[x] = state[y]; - state[y] = temp_swap; - z = state[x] + (state[y]) % 256; - output[i] = input[i] ^ state[z]; - } - ctx->x = x; - ctx->y = y; - - return in_len; -} - -static PurpleCipherOps RC4Ops = { - NULL, /* Set Option */ - NULL, /* Get Option */ - rc4_init, /* init */ - rc4_reset, /* reset */ - NULL, /* reset state */ - rc4_uninit, /* uninit */ - NULL, /* set iv */ - NULL, /* append */ - NULL, /* digest */ - NULL, /* get digest size */ - rc4_encrypt, /* encrypt */ - NULL, /* decrypt */ - NULL, /* set salt */ - NULL, /* get salt size */ - rc4_set_key, /* set key */ - NULL, /* get key size */ - NULL, /* set batch mode */ - NULL, /* get batch mode */ - NULL, /* get block size */ - NULL, NULL, NULL, NULL /* reserved */ -}; - -PurpleCipherOps * -purple_rc4_cipher_get_ops(void) { - return &RC4Ops; -} - diff --git a/libpurple/ciphers/rc4cipher.c b/libpurple/ciphers/rc4cipher.c new file mode 100644 index 0000000000..a4388f0d3f --- /dev/null +++ b/libpurple/ciphers/rc4cipher.c @@ -0,0 +1,266 @@ +/* + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#include "rc4cipher.h" + +/******************************************************************************* + * Structs + ******************************************************************************/ +#define PURPLE_RC4_CIPHER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_RC4_CIPHER, PurpleRC4CipherPrivate)) + +typedef struct { + guchar state[256]; + guchar x; + guchar y; + gint key_len; +} PurpleRC4CipherPrivate; + +/****************************************************************************** + * Enums + *****************************************************************************/ +enum { + PROP_ZERO, + PROP_KEY_LEN, + PROP_KEY, + PROP_LAST, +}; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Cipher Stuff + *****************************************************************************/ +static void +purple_rc4_cipher_reset(PurpleCipher *cipher) { + PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher); + PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher); + guint i; + + for(i = 0; i < 256; i++) + priv->state[i] = i; + priv->x = 0; + priv->y = 0; + + /* default is 5 bytes (40bit key) */ + priv->key_len = 5; +} + +static void +purple_rc4_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) { + PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher); + PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher); + guchar *state; + guchar temp_swap; + guchar x, y; + guint i; + + x = 0; + y = 0; + state = &priv->state[0]; + priv->key_len = len; + for(i = 0; i < 256; i++) + { + y = (key[x] + state[i] + y) % 256; + temp_swap = state[i]; + state[i] = state[y]; + state[y] = temp_swap; + x = (x + 1) % len; + } + + g_object_notify(G_OBJECT(rc4_cipher), "key"); +} + +static ssize_t +purple_rc4_cipher_encrypt(PurpleCipher *cipher, const guchar input[], size_t in_len, + guchar output[], size_t out_size) +{ + PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher); + guchar temp_swap; + guchar x, y, z; + guchar *state; + guint i; + PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher); + + x = priv->x; + y = priv->y; + state = &priv->state[0]; + + for(i = 0; i < in_len; i++) + { + x = (x + 1) % 256; + y = (state[x] + y) % 256; + temp_swap = state[x]; + state[x] = state[y]; + state[y] = temp_swap; + z = state[x] + (state[y]) % 256; + output[i] = input[i] ^ state[z]; + } + priv->x = x; + priv->y = y; + + return in_len; +} + +static const gchar* +purple_rc4_cipher_get_name(PurpleCipher *cipher) +{ + return "rc4"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_rc4_cipher_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(obj); + + switch(param_id) { + case PROP_KEY_LEN: + purple_rc4_cipher_set_key_len(rc4_cipher, g_value_get_int(value)); + break; + case PROP_KEY: + { + guchar *key = (guchar *)g_value_get_string(value); + purple_rc4_cipher_set_key(cipher, key, strlen((gchar *) key)); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_rc4_cipher_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(obj); + + switch(param_id) { + case PROP_KEY_LEN: + g_value_set_int(value, + purple_rc4_cipher_get_key_len(rc4_cipher)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_rc4_cipher_class_init(PurpleRC4CipherClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); + GParamSpec *pspec = NULL; + + parent_class = g_type_class_peek_parent(klass); + + obj_class->set_property = purple_rc4_cipher_set_property; + obj_class->get_property = purple_rc4_cipher_get_property; + + cipher_class->reset = purple_rc4_cipher_reset; + cipher_class->encrypt = purple_rc4_cipher_encrypt; + cipher_class->set_key = purple_rc4_cipher_set_key; + cipher_class->get_name = purple_rc4_cipher_get_name; + + pspec = g_param_spec_int("key_len", "key_len", "key_len", + G_MININT, G_MAXINT, 0, + G_PARAM_READWRITE); + g_object_class_install_property(obj_class, PROP_KEY_LEN, pspec); + + pspec = g_param_spec_string("key", "key", "key", NULL, + G_PARAM_WRITABLE); + g_object_class_install_property(obj_class, PROP_KEY, pspec); + + g_type_class_add_private(klass, sizeof(PurpleRC4CipherPrivate)); +} + +static void +purple_rc4_cipher_init(PurpleCipher *cipher) { + purple_rc4_cipher_reset(cipher); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_rc4_cipher_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleRC4CipherClass), + NULL, + NULL, + (GClassInitFunc)purple_rc4_cipher_class_init, + NULL, + NULL, + sizeof(PurpleRC4Cipher), + 0, + (GInstanceInitFunc)purple_rc4_cipher_init, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_CIPHER, + "PurpleRC4Cipher", + &info, 0); + } + + return type; +} + +PurpleCipher * +purple_rc4_cipher_new(void) { + return g_object_new(PURPLE_TYPE_RC4_CIPHER, NULL); +} + +void +purple_rc4_cipher_set_key_len(PurpleRC4Cipher *rc4_cipher, + gint key_len) +{ + PurpleRC4CipherPrivate *priv; + + g_return_if_fail(PURPLE_IS_RC4_CIPHER(rc4_cipher)); + + priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher); + priv->key_len = key_len; + + g_object_notify(G_OBJECT(rc4_cipher), "key_len"); +} + +gint +purple_rc4_cipher_get_key_len(PurpleRC4Cipher *rc4_cipher) +{ + PurpleRC4CipherPrivate *priv; + + g_return_val_if_fail(PURPLE_IS_RC4_CIPHER(rc4_cipher), 0); + + priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher); + + return priv->key_len; +} diff --git a/libpurple/ciphers/rc4cipher.h b/libpurple/ciphers/rc4cipher.h new file mode 100644 index 0000000000..9565a43d12 --- /dev/null +++ b/libpurple/ciphers/rc4cipher.h @@ -0,0 +1,69 @@ +/** + * @file rc4.h Purple RC4 Cipher + * @ingroup core + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef PURPLE_RC4_CIPHER_H +#define PURPLE_RC4_CIPHER_H + +#include "cipher.h" + +#define PURPLE_TYPE_RC4_CIPHER (purple_rc4_cipher_get_gtype()) +#define PURPLE_RC4_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_RC4_CIPHER, PurpleRC4Cipher)) +#define PURPLE_RC4_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_RC4_CIPHER, PurpleRC4CipherClass)) +#define PURPLE_IS_RC4_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_RC4_CIPHER)) +#define PURPLE_IS_RC4_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_RC4_CIPHER)) +#define PURPLE_RC4_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_RC4_CIPHER, PurpleRC4CipherClass)) + +typedef struct _PurpleRC4Cipher PurpleRC4Cipher; +typedef struct _PurpleRC4CipherClass PurpleRC4CipherClass; + +struct _PurpleRC4Cipher { + /*< private >*/ + PurpleCipher gparent; +}; + +struct _PurpleRC4CipherClass { + /*< private >*/ + PurpleCipherClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_rc4_cipher_get_gtype(void); + +PurpleCipher *purple_rc4_cipher_new(void); + +gint purple_rc4_cipher_get_key_len(PurpleRC4Cipher *rc4_cipher); +void purple_rc4_cipher_set_key_len(PurpleRC4Cipher *rc4_cipher, gint key_len); + +G_END_DECLS + +#endif /* PURPLE_RC4_CIPHER_H */ + + diff --git a/libpurple/ciphers/sha1hash.c b/libpurple/ciphers/sha1hash.c new file mode 100644 index 0000000000..4ebd34fa15 --- /dev/null +++ b/libpurple/ciphers/sha1hash.c @@ -0,0 +1,195 @@ +/* + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#include "sha1hash.h" + +/******************************************************************************* + * Structs + ******************************************************************************/ +#define PURPLE_SHA1_HASH_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_SHA1_HASH, PurpleSHA1HashPrivate)) + +typedef struct { + GChecksum *checksum; +} PurpleSHA1HashPrivate; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Hash Stuff + *****************************************************************************/ + +static void +purple_sha1_hash_reset(PurpleHash *hash) +{ + PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(hash); + PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->checksum != NULL); + + g_checksum_reset(priv->checksum); +} + +static void +purple_sha1_hash_append(PurpleHash *hash, const guchar *data, + gsize len) +{ + PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(hash); + PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->checksum != NULL); + + while (len >= G_MAXSSIZE) { + g_checksum_update(priv->checksum, data, G_MAXSSIZE); + len -= G_MAXSSIZE; + data += G_MAXSSIZE; + } + + if (len) + g_checksum_update(priv->checksum, data, len); +} + +static gboolean +purple_sha1_hash_digest(PurpleHash *hash, guchar *digest, size_t buff_len) +{ + PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(hash); + PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash); + + const gssize required_len = g_checksum_type_get_length(G_CHECKSUM_SHA1); + gsize digest_len = buff_len; + + g_return_val_if_fail(priv != NULL, FALSE); + g_return_val_if_fail(priv->checksum != NULL, FALSE); + g_return_val_if_fail(buff_len >= required_len, FALSE); + + g_checksum_get_digest(priv->checksum, digest, &digest_len); + + if (digest_len != required_len) + return FALSE; + + purple_sha1_hash_reset(hash); + + return TRUE; +} + +static size_t +purple_sha1_hash_get_block_size(PurpleHash *hash) +{ + return 64; +} + +static size_t +purple_sha1_hash_get_digest_size(PurpleHash *hash) +{ + return g_checksum_type_get_length(G_CHECKSUM_SHA1); +} + +static const gchar* +purple_sha1_hash_get_name(PurpleHash *hash) +{ + return "sha1"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ + +static void +purple_sha1_hash_finalize(GObject *obj) +{ + PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(obj); + PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash); + + if (priv->checksum) + g_checksum_free(priv->checksum); + + parent_class->finalize(obj); +} + +static void +purple_sha1_hash_class_init(PurpleSHA1HashClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleHashClass *hash_class = PURPLE_HASH_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->finalize = purple_sha1_hash_finalize; + + hash_class->reset = purple_sha1_hash_reset; + hash_class->reset_state = purple_sha1_hash_reset; + hash_class->append = purple_sha1_hash_append; + hash_class->digest = purple_sha1_hash_digest; + hash_class->get_digest_size = purple_sha1_hash_get_digest_size; + hash_class->get_block_size = purple_sha1_hash_get_block_size; + hash_class->get_name = purple_sha1_hash_get_name; + + g_type_class_add_private(klass, sizeof(PurpleSHA1HashPrivate)); +} + +static void +purple_sha1_hash_init(PurpleHash *hash) +{ + PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(hash); + PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash); + + priv->checksum = g_checksum_new(G_CHECKSUM_SHA1); + + purple_sha1_hash_reset(hash); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_sha1_hash_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleSHA1HashClass), + NULL, + NULL, + (GClassInitFunc)purple_sha1_hash_class_init, + NULL, + NULL, + sizeof(PurpleSHA1Hash), + 0, + (GInstanceInitFunc)purple_sha1_hash_init, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_HASH, + "PurpleSHA1Hash", + &info, 0); + } + + return type; +} + +PurpleHash * +purple_sha1_hash_new(void) { + return g_object_new(PURPLE_TYPE_SHA1_HASH, NULL); +} diff --git a/libpurple/ciphers/sha1hash.h b/libpurple/ciphers/sha1hash.h new file mode 100644 index 0000000000..bd4731374e --- /dev/null +++ b/libpurple/ciphers/sha1hash.h @@ -0,0 +1,64 @@ +/** + * @file sha1.h Purple SHA1 Hash + * @ingroup core + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef PURPLE_SHA1_HASH_H +#define PURPLE_SHA1_HASH_H + +#include "hash.h" + +#define PURPLE_TYPE_SHA1_HASH (purple_sha1_hash_get_gtype()) +#define PURPLE_SHA1_HASH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_SHA1_HASH, PurpleSHA1Hash)) +#define PURPLE_SHA1_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_SHA1_HASH, PurpleSHA1HashClass)) +#define PURPLE_IS_SHA1_HASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_SHA1_HASH)) +#define PURPLE_IS_SHA1_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_SHA1_HASH)) +#define PURPLE_SHA1_HASH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_SHA1_HASH, PurpleSHA1HashClass)) + +typedef struct _PurpleSHA1Hash PurpleSHA1Hash; +typedef struct _PurpleSHA1HashClass PurpleSHA1HashClass; + +struct _PurpleSHA1Hash { + /*< private >*/ + PurpleHash gparent; +}; + +struct _PurpleSHA1HashClass { + /*< private >*/ + PurpleHashClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_sha1_hash_get_gtype(void); + +PurpleHash *purple_sha1_hash_new(void); + +G_END_DECLS + +#endif /* PURPLE_SHA1_HASH_H */ diff --git a/libpurple/ciphers/sha256hash.c b/libpurple/ciphers/sha256hash.c new file mode 100644 index 0000000000..04b4674a86 --- /dev/null +++ b/libpurple/ciphers/sha256hash.c @@ -0,0 +1,195 @@ +/* + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#include "sha256hash.h" + +/******************************************************************************* + * Structs + ******************************************************************************/ +#define PURPLE_SHA256_HASH_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_SHA256_HASH, PurpleSHA256HashPrivate)) + +typedef struct { + GChecksum *checksum; +} PurpleSHA256HashPrivate; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Hash Stuff + *****************************************************************************/ + +static void +purple_sha256_hash_reset(PurpleHash *hash) +{ + PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(hash); + PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->checksum != NULL); + + g_checksum_reset(priv->checksum); +} + +static void +purple_sha256_hash_append(PurpleHash *hash, const guchar *data, + gsize len) +{ + PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(hash); + PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->checksum != NULL); + + while (len >= G_MAXSSIZE) { + g_checksum_update(priv->checksum, data, G_MAXSSIZE); + len -= G_MAXSSIZE; + data += G_MAXSSIZE; + } + + if (len) + g_checksum_update(priv->checksum, data, len); +} + +static gboolean +purple_sha256_hash_digest(PurpleHash *hash, guchar *digest, size_t buff_len) +{ + PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(hash); + PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash); + + const gssize required_len = g_checksum_type_get_length(G_CHECKSUM_SHA256); + gsize digest_len = buff_len; + + g_return_val_if_fail(priv != NULL, FALSE); + g_return_val_if_fail(priv->checksum != NULL, FALSE); + g_return_val_if_fail(buff_len >= required_len, FALSE); + + g_checksum_get_digest(priv->checksum, digest, &digest_len); + + if (digest_len != required_len) + return FALSE; + + purple_sha256_hash_reset(hash); + + return TRUE; +} + +static size_t +purple_sha256_hash_get_block_size(PurpleHash *hash) +{ + return 64; +} + +static size_t +purple_sha256_hash_get_digest_size(PurpleHash *hash) +{ + return g_checksum_type_get_length(G_CHECKSUM_SHA256); +} + +static const gchar* +purple_sha256_hash_get_name(PurpleHash *hash) +{ + return "sha256"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ + +static void +purple_sha256_hash_finalize(GObject *obj) +{ + PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(obj); + PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash); + + if (priv->checksum) + g_checksum_free(priv->checksum); + + parent_class->finalize(obj); +} + +static void +purple_sha256_hash_class_init(PurpleSHA256HashClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleHashClass *hash_class = PURPLE_HASH_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->finalize = purple_sha256_hash_finalize; + + hash_class->reset = purple_sha256_hash_reset; + hash_class->reset_state = purple_sha256_hash_reset; + hash_class->append = purple_sha256_hash_append; + hash_class->digest = purple_sha256_hash_digest; + hash_class->get_digest_size = purple_sha256_hash_get_digest_size; + hash_class->get_block_size = purple_sha256_hash_get_block_size; + hash_class->get_name = purple_sha256_hash_get_name; + + g_type_class_add_private(klass, sizeof(PurpleSHA256HashPrivate)); +} + +static void +purple_sha256_hash_init(PurpleHash *hash) +{ + PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(hash); + PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash); + + priv->checksum = g_checksum_new(G_CHECKSUM_SHA256); + + purple_sha256_hash_reset(hash); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_sha256_hash_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleSHA256HashClass), + NULL, + NULL, + (GClassInitFunc)purple_sha256_hash_class_init, + NULL, + NULL, + sizeof(PurpleSHA256Hash), + 0, + (GInstanceInitFunc)purple_sha256_hash_init, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_HASH, + "PurpleSHA256Hash", + &info, 0); + } + + return type; +} + +PurpleHash * +purple_sha256_hash_new(void) { + return g_object_new(PURPLE_TYPE_SHA256_HASH, NULL); +} diff --git a/libpurple/ciphers/sha256hash.h b/libpurple/ciphers/sha256hash.h new file mode 100644 index 0000000000..72c778cf6f --- /dev/null +++ b/libpurple/ciphers/sha256hash.h @@ -0,0 +1,64 @@ +/** + * @file sha256.h Purple SHA256 Hash + * @ingroup core + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef PURPLE_SHA256_HASH_H +#define PURPLE_SHA256_HASH_H + +#include "hash.h" + +#define PURPLE_TYPE_SHA256_HASH (purple_sha256_hash_get_gtype()) +#define PURPLE_SHA256_HASH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_SHA256_HASH, PurpleSHA256Hash)) +#define PURPLE_SHA256_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_SHA256_HASH, PurpleSHA256HashClass)) +#define PURPLE_IS_SHA256_HASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_SHA256_HASH)) +#define PURPLE_IS_SHA256_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_SHA256_HASH)) +#define PURPLE_SHA256_HASH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_SHA256_HASH, PurpleSHA256HashClass)) + +typedef struct _PurpleSHA256Hash PurpleSHA256Hash; +typedef struct _PurpleSHA256HashClass PurpleSHA256HashClass; + +struct _PurpleSHA256Hash { + /*< private >*/ + PurpleHash gparent; +}; + +struct _PurpleSHA256HashClass { + /*< private >*/ + PurpleHashClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_sha256_hash_get_gtype(void); + +PurpleHash *purple_sha256_hash_new(void); + +G_END_DECLS + +#endif /* PURPLE_SHA256_HASH_H */ diff --git a/libpurple/circbuffer.c b/libpurple/circbuffer.c deleted file mode 100644 index 619d9c9758..0000000000 --- a/libpurple/circbuffer.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * @file circbuffer.h Buffer Utility Functions - * @ingroup core - */ - -/* Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "internal.h" - -#include "circbuffer.h" - -#define DEFAULT_BUF_SIZE 256 - -PurpleCircBuffer * -purple_circ_buffer_new(gsize growsize) { - PurpleCircBuffer *buf = g_new0(PurpleCircBuffer, 1); - buf->growsize = growsize ? growsize : DEFAULT_BUF_SIZE; - return buf; -} - -void purple_circ_buffer_destroy(PurpleCircBuffer *buf) { - g_return_if_fail(buf != NULL); - - g_free(buf->buffer); - g_free(buf); -} - -static void grow_circ_buffer(PurpleCircBuffer *buf, gsize len) { - int in_offset = 0, out_offset = 0; - int start_buflen; - - g_return_if_fail(buf != NULL); - - start_buflen = buf->buflen; - - while ((buf->buflen - buf->bufused) < len) - buf->buflen += buf->growsize; - - if (buf->inptr != NULL) { - in_offset = buf->inptr - buf->buffer; - out_offset = buf->outptr - buf->buffer; - } - buf->buffer = g_realloc(buf->buffer, buf->buflen); - - /* adjust the fill and remove pointer locations */ - if (buf->inptr == NULL) { - buf->inptr = buf->outptr = buf->buffer; - } else { - buf->inptr = buf->buffer + in_offset; - buf->outptr = buf->buffer + out_offset; - } - - /* If the fill pointer is wrapped to before the remove - * pointer, we need to shift the data */ - if (in_offset < out_offset - || (in_offset == out_offset && buf->bufused > 0)) { - int shift_n = MIN(buf->buflen - start_buflen, - in_offset); - memcpy(buf->buffer + start_buflen, buf->buffer, - shift_n); - - /* If we couldn't fit the wrapped read buffer - * at the end */ - if (shift_n < in_offset) { - memmove(buf->buffer, - buf->buffer + shift_n, - in_offset - shift_n); - buf->inptr = buf->buffer + - (in_offset - shift_n); - } else { - buf->inptr = buf->buffer + - start_buflen + in_offset; - } - } -} - -void purple_circ_buffer_append(PurpleCircBuffer *buf, gconstpointer src, gsize len) { - - int len_stored; - - g_return_if_fail(buf != NULL); - - /* Grow the buffer, if necessary */ - if ((buf->buflen - buf->bufused) < len) - grow_circ_buffer(buf, len); - - /* If there is not enough room to copy all of src before hitting - * the end of the buffer then we will need to do two copies. - * One copy from inptr to the end of the buffer, and the - * second copy from the start of the buffer to the end of src. */ - if (buf->inptr >= buf->outptr) - len_stored = MIN(len, buf->buflen - - (buf->inptr - buf->buffer)); - else - len_stored = len; - - if (len_stored > 0) - memcpy(buf->inptr, src, len_stored); - - if (len_stored < len) { - memcpy(buf->buffer, (char*)src + len_stored, len - len_stored); - buf->inptr = buf->buffer + (len - len_stored); - } else { - buf->inptr += len_stored; - } - - buf->bufused += len; -} - -gsize purple_circ_buffer_get_max_read(const PurpleCircBuffer *buf) { - gsize max_read; - - g_return_val_if_fail(buf != NULL, 0); - - if (buf->bufused == 0) - max_read = 0; - else if ((buf->outptr - buf->inptr) >= 0) - max_read = buf->buflen - (buf->outptr - buf->buffer); - else - max_read = buf->inptr - buf->outptr; - - return max_read; -} - -gboolean purple_circ_buffer_mark_read(PurpleCircBuffer *buf, gsize len) { - g_return_val_if_fail(buf != NULL, FALSE); - g_return_val_if_fail(purple_circ_buffer_get_max_read(buf) >= len, FALSE); - - buf->outptr += len; - buf->bufused -= len; - /* wrap to the start if we're at the end */ - if ((buf->outptr - buf->buffer) == buf->buflen) - buf->outptr = buf->buffer; - - return TRUE; -} - diff --git a/libpurple/circularbuffer.c b/libpurple/circularbuffer.c new file mode 100644 index 0000000000..fa1e592d46 --- /dev/null +++ b/libpurple/circularbuffer.c @@ -0,0 +1,444 @@ +/* + * @file circbuffer.h Buffer Utility Functions + * @ingroup core + */ + +/* Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#include "internal.h" + +#include "circularbuffer.h" + +#define DEFAULT_BUF_SIZE 256 + +#define PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_CIRCULAR_BUFFER, PurpleCircularBufferPrivate)) + +/****************************************************************************** + * Structs + *****************************************************************************/ +typedef struct { + gchar *buffer; + gsize growsize; + gsize buflen; + gsize bufused; + gchar *input; + gchar *output; +} PurpleCircularBufferPrivate; + +/****************************************************************************** + * Enums + *****************************************************************************/ +enum { + PROP_ZERO, + PROP_GROW_SIZE, + PROP_BUFFER_USED, + PROP_INPUT, + PROP_OUTPUT, + PROP_LAST, +}; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Circular Buffer Implementation + *****************************************************************************/ +static void +purple_circular_buffer_real_grow(PurpleCircularBuffer *buffer, gsize len) { + PurpleCircularBufferPrivate *priv = NULL; + gint in_offset = 0, out_offset = 0; + gint start_buflen; + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + start_buflen = priv->buflen; + + while((priv->buflen - priv->bufused) < len) + priv->buflen += priv->growsize; + + if(priv->input != NULL) { + in_offset = priv->input - priv->buffer; + out_offset = priv->output - priv->buffer; + } + + priv->buffer = g_realloc(priv->buffer, priv->buflen); + + /* adjust the fill and remove pointer locations */ + if(priv->input == NULL) { + priv->input = priv->output = priv->buffer; + } else { + priv->input = priv->buffer + in_offset; + priv->output = priv->buffer + out_offset; + } + + /* If the fill pointer is wrapped to before the remove + * pointer, we need to shift the data */ + if(in_offset < out_offset + || (in_offset == out_offset && priv->bufused > 0)) + { + gint shift_n = MIN(priv->buflen - start_buflen, in_offset); + memcpy(priv->buffer + start_buflen, priv->buffer, shift_n); + + /* If we couldn't fit the wrapped read buffer at the end */ + if (shift_n < in_offset) { + memmove(priv->buffer, priv->buffer + shift_n, in_offset - shift_n); + priv->input = priv->buffer + (in_offset - shift_n); + } else { + priv->input = priv->buffer + start_buflen + in_offset; + } + } +} + +static void +purple_circular_buffer_real_append(PurpleCircularBuffer *buffer, + gconstpointer src, gsize len) +{ + PurpleCircularBufferPrivate *priv = NULL; + gint len_stored; + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + /* Grow the buffer, if necessary */ + if((priv->buflen - priv->bufused) < len) + purple_circular_buffer_grow(buffer, len); + + /* If there is not enough room to copy all of src before hitting + * the end of the buffer then we will need to do two copies. + * One copy from input to the end of the buffer, and the + * second copy from the start of the buffer to the end of src. */ + if(priv->input >= priv->output) + len_stored = MIN(len, priv->buflen - (priv->input - priv->buffer)); + else + len_stored = len; + + if(len_stored > 0) + memcpy(priv->input, src, len_stored); + + if(len_stored < len) { + memcpy(priv->buffer, (char*)src + len_stored, len - len_stored); + priv->input = priv->buffer + (len - len_stored); + } else { + priv->input += len_stored; + } + + priv->bufused += len; +} + +static gsize +purple_circular_buffer_real_max_read_size(const PurpleCircularBuffer *buffer) { + PurpleCircularBufferPrivate *priv = NULL; + gsize max_read; + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + if(priv->bufused == 0) + max_read = 0; + else if((priv->output - priv->input) >= 0) + max_read = priv->buflen - (priv->output - priv->buffer); + else + max_read = priv->input - priv->output; + + return max_read; +} + +static gboolean +purple_circular_buffer_real_mark_read(PurpleCircularBuffer *buffer, + gsize len) +{ + PurpleCircularBufferPrivate *priv = NULL; + + g_return_val_if_fail(purple_circular_buffer_get_max_read(buffer) >= len, FALSE); + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + priv->output += len; + priv->bufused -= len; + + /* wrap to the start if we're at the end */ + if((priv->output - priv->buffer) == priv->buflen) + priv->output = priv->buffer; + + return TRUE; +} + +/****************************************************************************** + * Private API + *****************************************************************************/ +static void +purple_circular_buffer_set_grow_size(PurpleCircularBuffer *buffer, + gsize grow_size) +{ + PurpleCircularBufferPrivate *priv = + PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + priv->growsize = (grow_size != 0) ? grow_size : DEFAULT_BUF_SIZE; + + g_object_notify(G_OBJECT(buffer), "grow-size"); +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_circular_buffer_finalize(GObject *obj) { + PurpleCircularBufferPrivate *priv = + PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(obj); + + g_free(priv->buffer); + + G_OBJECT_CLASS(parent_class)->finalize(obj); +} + +static void +purple_circular_buffer_get_property(GObject *obj, guint param_id, + GValue *value, GParamSpec *pspec) +{ + PurpleCircularBuffer *buffer = PURPLE_CIRCULAR_BUFFER(obj); + + switch(param_id) { + case PROP_GROW_SIZE: + g_value_set_ulong(value, + purple_circular_buffer_get_grow_size(buffer)); + break; + case PROP_BUFFER_USED: + g_value_set_ulong(value, + purple_circular_buffer_get_used(buffer)); + break; + case PROP_INPUT: + g_value_set_pointer(value, + (void*) purple_circular_buffer_get_input(buffer)); + break; + case PROP_OUTPUT: + g_value_set_pointer(value, + (void*) purple_circular_buffer_get_output(buffer)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_circular_buffer_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + PurpleCircularBuffer *buffer = PURPLE_CIRCULAR_BUFFER(obj); + + switch(param_id) { + case PROP_GROW_SIZE: + purple_circular_buffer_set_grow_size(buffer, + g_value_get_ulong(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_circular_buffer_class_init(PurpleCircularBufferClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleCircularBufferClass *buffer_class = PURPLE_CIRCULAR_BUFFER_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + g_type_class_add_private(klass, sizeof(PurpleCircularBufferPrivate)); + + obj_class->finalize = purple_circular_buffer_finalize; + obj_class->get_property = purple_circular_buffer_get_property; + obj_class->set_property = purple_circular_buffer_set_property; + + buffer_class->grow = purple_circular_buffer_real_grow; + buffer_class->append = purple_circular_buffer_real_append; + buffer_class->max_read_size = purple_circular_buffer_real_max_read_size; + buffer_class->mark_read = purple_circular_buffer_real_mark_read; + + /* using a ulong for the gsize properties since there is no + * g_param_spec_size, and the ulong should always work. --gk 3/21/11 + */ + g_object_class_install_property(obj_class, PROP_GROW_SIZE, + g_param_spec_ulong("grow-size", "grow-size", + "The grow size of the buffer", + 0, G_MAXSIZE, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property(obj_class, PROP_BUFFER_USED, + g_param_spec_ulong("buffer-used", "buffer-used", + "The amount of the buffer used", + 0, G_MAXSIZE, 0, + G_PARAM_READABLE)); + + g_object_class_install_property(obj_class, PROP_INPUT, + g_param_spec_pointer("input", "input", + "The input pointer of the buffer", + G_PARAM_READABLE)); + + g_object_class_install_property(obj_class, PROP_OUTPUT, + g_param_spec_pointer("output", "output", + "The output pointer of the buffer", + G_PARAM_READABLE)); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_circular_buffer_get_type(void) { + static GType type = 0; + + if(G_UNLIKELY(type == 0)) { + static const GTypeInfo info = { + .class_size = sizeof(PurpleCircularBufferClass), + .class_init = (GClassInitFunc)purple_circular_buffer_class_init, + .instance_size = sizeof(PurpleCircularBuffer), + }; + + type = g_type_register_static(G_TYPE_OBJECT, + "PurpleCircularBuffer", + &info, 0); + } + + return type; +} + +PurpleCircularBuffer * +purple_circular_buffer_new(gsize growsize) { + return g_object_new(PURPLE_TYPE_CIRCULAR_BUFFER, + "grow-size", growsize ? growsize : DEFAULT_BUF_SIZE, + NULL); +} + +void +purple_circular_buffer_grow(PurpleCircularBuffer *buffer, gsize len) { + PurpleCircularBufferClass *klass = NULL; + + g_return_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer)); + + klass = PURPLE_CIRCULAR_BUFFER_GET_CLASS(buffer); + if(klass && klass->grow) + klass->grow(buffer, len); +} + +void +purple_circular_buffer_append(PurpleCircularBuffer *buffer, gconstpointer src, + gsize len) +{ + PurpleCircularBufferClass *klass = NULL; + + g_return_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer)); + g_return_if_fail(src != NULL); + + klass = PURPLE_CIRCULAR_BUFFER_GET_CLASS(buffer); + if(klass && klass->append) + klass->append(buffer, src, len); +} + +gsize +purple_circular_buffer_get_max_read(const PurpleCircularBuffer *buffer) { + PurpleCircularBufferClass *klass = NULL; + + g_return_val_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer), 0); + + klass = PURPLE_CIRCULAR_BUFFER_GET_CLASS(buffer); + if(klass && klass->max_read_size) + return klass->max_read_size(buffer); + + return 0; +} + +gboolean +purple_circular_buffer_mark_read(PurpleCircularBuffer *buffer, gsize len) { + PurpleCircularBufferClass *klass = NULL; + + g_return_val_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer), FALSE); + + klass = PURPLE_CIRCULAR_BUFFER_CLASS(buffer); + if(klass && klass->mark_read) + return klass->mark_read(buffer, len); + + return FALSE; +} + +gsize +purple_circular_buffer_get_grow_size(const PurpleCircularBuffer *buffer) { + + PurpleCircularBufferPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer), 0); + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + return priv->growsize; +} + +gsize +purple_circular_buffer_get_used(const PurpleCircularBuffer *buffer) { + PurpleCircularBufferPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer), 0); + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + return priv->bufused; +} + +const gchar * +purple_circular_buffer_get_input(const PurpleCircularBuffer *buffer) { + PurpleCircularBufferPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer), NULL); + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + return priv->input; +} + +const gchar * +purple_circular_buffer_get_output(const PurpleCircularBuffer *buffer) { + PurpleCircularBufferPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer), NULL); + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + return priv->output; +} + +void +purple_circular_buffer_reset(PurpleCircularBuffer *buffer) { + PurpleCircularBufferPrivate *priv = NULL; + GObject *obj = NULL; + + g_return_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer)); + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + priv->input = priv->buffer; + priv->output = priv->buffer; + + obj = G_OBJECT(buffer); + g_object_freeze_notify(obj); + g_object_notify(obj, "input"); + g_object_notify(obj, "output"); + g_object_thaw_notify(obj); +} + diff --git a/libpurple/circbuffer.h b/libpurple/circularbuffer.h index 7e9283404c..080c2cf3ff 100644 --- a/libpurple/circbuffer.h +++ b/libpurple/circularbuffer.h @@ -21,38 +21,46 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _CIRCBUFFER_H -#define _CIRCBUFFER_H +#ifndef PURPLE_CIRCULAR_BUFFER_H +#define PURPLE_CIRCULAR_BUFFER_H #include <glib.h> - -typedef struct _PurpleCircBuffer { - - /** A pointer to the starting address of our chunk of memory. */ - gchar *buffer; - - /** The incremental amount to increase this buffer by when - * the buffer is not big enough to hold incoming data, in bytes. */ - gsize growsize; - - /** The length of this buffer, in bytes. */ - gsize buflen; - - /** The number of bytes of this buffer that contain unread data. */ - gsize bufused; - - /** A pointer to the next byte where new incoming data is - * buffered to. */ - gchar *inptr; - - /** A pointer to the next byte of buffered data that should be - * read by the consumer. */ - gchar *outptr; - -} PurpleCircBuffer; +#include <glib-object.h> + +#define PURPLE_TYPE_CIRCULAR_BUFFER (purple_circular_buffer_get_type()) +#define PURPLE_CIRCULAR_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_CIRCULAR_BUFFER, PurpleCircularBuffer)) +#define PURPLE_CIRCULAR_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_CIRCULAR_BUFFER, PurpleCircularBufferClass)) +#define PURPLE_IS_CIRCULAR_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_CIRCULAR_BUFFER)) +#define PURPLE_IS_CIRCULAR_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_CIRCULAR_BUFFER)) +#define PURPLE_CIRCULAR_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_CIRCULAR_BUFFER, PurpleCircularBufferClass)) + +typedef struct _PurpleCircularBuffer PurpleCircularBuffer; +typedef struct _PurpleCircularBufferClass PurpleCircularBufferClass; + +struct _PurpleCircularBuffer { + /*< private >*/ + GObject parent; +}; + +struct _PurpleCircularBufferClass { + /*< private >*/ + GObjectClass parent; + + void (*grow)(PurpleCircularBuffer *buffer, gsize len); + void (*append)(PurpleCircularBuffer *buffer, gconstpointer src, gsize len); + gsize (*max_read_size)(const PurpleCircularBuffer *buffer); + gboolean (*mark_read)(PurpleCircularBuffer *buffer, gsize len); + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); +}; G_BEGIN_DECLS +GType purple_circular_buffer_get_type(void); + /** * Creates a new circular buffer. This will not allocate any memory for the * actual buffer until data is appended to it. @@ -64,15 +72,7 @@ G_BEGIN_DECLS * @return The new PurpleCircBuffer. This should be freed with * purple_circ_buffer_destroy when you are done with it */ -PurpleCircBuffer *purple_circ_buffer_new(gsize growsize); - -/** - * Dispose of the PurpleCircBuffer and free any memory used by it (including any - * memory used by the internal buffer). - * - * @param buf The PurpleCircBuffer to free - */ -void purple_circ_buffer_destroy(PurpleCircBuffer *buf); +PurpleCircularBuffer *purple_circular_buffer_new(gsize growsize); /** * Append data to the PurpleCircBuffer. This will grow the internal @@ -82,7 +82,7 @@ void purple_circ_buffer_destroy(PurpleCircBuffer *buf); * @param src pointer to the data to copy into the buffer * @param len number of bytes to copy into the buffer */ -void purple_circ_buffer_append(PurpleCircBuffer *buf, gconstpointer src, gsize len); +void purple_circular_buffer_append(PurpleCircularBuffer *buf, gconstpointer src, gsize len); /** * Determine the maximum number of contiguous bytes that can be read from the @@ -96,7 +96,7 @@ void purple_circ_buffer_append(PurpleCircBuffer *buf, gconstpointer src, gsize l * * @return the number of bytes that can be read from the PurpleCircBuffer */ -gsize purple_circ_buffer_get_max_read(const PurpleCircBuffer *buf); +gsize purple_circular_buffer_get_max_read(const PurpleCircularBuffer *buf); /** * Mark the number of bytes that have been read from the buffer. @@ -107,8 +107,16 @@ gsize purple_circ_buffer_get_max_read(const PurpleCircBuffer *buf); * @return TRUE if we successfully marked the bytes as having been read, FALSE * otherwise. */ -gboolean purple_circ_buffer_mark_read(PurpleCircBuffer *buf, gsize len); +gboolean purple_circular_buffer_mark_read(PurpleCircularBuffer *buf, gsize len); + +void purple_circular_buffer_grow(PurpleCircularBuffer *buffer, gsize len); +gsize purple_circular_buffer_get_grow_size(const PurpleCircularBuffer *buffer); +gsize purple_circular_buffer_get_used(const PurpleCircularBuffer *buffer); +const gchar *purple_circular_buffer_get_input(const PurpleCircularBuffer *buffer); +const gchar *purple_circular_buffer_get_output(const PurpleCircularBuffer *buffer); +void purple_circular_buffer_reset(PurpleCircularBuffer *buffer); G_END_DECLS -#endif /* _CIRCBUFFER_H */ +#endif /* PURPLE_CIRCULAR_BUFFER_H */ + diff --git a/libpurple/cmds.c b/libpurple/cmds.c index b29e4c4818..8ec906bb58 100644 --- a/libpurple/cmds.c +++ b/libpurple/cmds.c @@ -202,7 +202,7 @@ PurpleCmdStatus purple_cmd_do_command(PurpleConversation *conv, const gchar *cmd PurpleCmd *c; GList *l; gchar *err = NULL; - gboolean is_im; + gboolean is_im = TRUE; gboolean found = FALSE, tried_cmd = FALSE, right_type = FALSE, right_prpl = FALSE; const gchar *prpl_id; gchar **args = NULL; @@ -212,12 +212,8 @@ PurpleCmdStatus purple_cmd_do_command(PurpleConversation *conv, const gchar *cmd *error = NULL; prpl_id = purple_account_get_protocol_id(purple_conversation_get_account(conv)); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) - is_im = TRUE; - else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) + if (PURPLE_IS_CHAT_CONVERSATION(conv)) is_im = FALSE; - else - return PURPLE_CMD_STATUS_FAILED; rest = strchr(cmdline, ' '); if (rest) { @@ -311,10 +307,10 @@ GList *purple_cmd_list(PurpleConversation *conv) for (l = cmds; l; l = l->next) { c = l->data; - if (conv && (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)) + if (conv && PURPLE_IS_IM_CONVERSATION(conv)) if (!(c->flags & PURPLE_CMD_FLAG_IM)) continue; - if (conv && (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT)) + if (conv && PURPLE_IS_CHAT_CONVERSATION(conv)) if (!(c->flags & PURPLE_CMD_FLAG_CHAT)) continue; @@ -343,10 +339,10 @@ GList *purple_cmd_help(PurpleConversation *conv, const gchar *cmd) if (cmd && !purple_strequal(cmd, c->cmd)) continue; - if (conv && (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)) + if (conv && PURPLE_IS_IM_CONVERSATION(conv)) if (!(c->flags & PURPLE_CMD_FLAG_IM)) continue; - if (conv && (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT)) + if (conv && PURPLE_IS_CHAT_CONVERSATION(conv)) if (!(c->flags & PURPLE_CMD_FLAG_CHAT)) continue; @@ -373,13 +369,11 @@ void purple_cmds_init(void) gpointer handle = purple_cmds_get_handle(); purple_signal_register(handle, "cmd-added", - purple_marshal_VOID__POINTER_INT_INT, NULL, 3, - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_INT), - purple_value_new(PURPLE_TYPE_INT)); + purple_marshal_VOID__POINTER_INT_INT, G_TYPE_NONE, 3, + G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT); purple_signal_register(handle, "cmd-removed", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_STRING)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + G_TYPE_STRING); } void purple_cmds_uninit(void) diff --git a/libpurple/connection.c b/libpurple/connection.c index 08f97f565b..b03c48e94f 100644 --- a/libpurple/connection.c +++ b/libpurple/connection.c @@ -27,10 +27,11 @@ #include "internal.h" #include "account.h" -#include "blist.h" +#include "buddylist.h" #include "connection.h" #include "dbus-maybe.h" #include "debug.h" +#include "enums.h" #include "http.h" #include "log.h" #include "notify.h" @@ -43,25 +44,84 @@ #define KEEPALIVE_INTERVAL 30 +#define PURPLE_CONNECTION_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_CONNECTION, PurpleConnectionPrivate)) + +/** @copydoc _PurpleConnectionPrivate */ +typedef struct _PurpleConnectionPrivate PurpleConnectionPrivate; + +/** Private data for a connection */ +struct _PurpleConnectionPrivate +{ + PurplePlugin *prpl; /**< The protocol plugin. */ + PurpleConnectionFlags flags; /**< Connection flags. */ + + PurpleConnectionState state; /**< The connection state. */ + + PurpleAccount *account; /**< The account being connected to. */ + char *password; /**< The password used. */ + + GSList *active_chats; /**< A list of active chats + (#PurpleChatConversation structs). */ + void *proto_data; /**< Protocol-specific data. + TODO Remove this, and use + protocol-specific subclasses */ + + char *display_name; /**< How you appear to other people. */ + guint keepalive; /**< Keep-alive. */ + + /** Wants to Die state. This is set when the user chooses to log out, or + * when the protocol is disconnected and should not be automatically + * reconnected (incorrect password, etc.). prpls should rely on + * purple_connection_error() to set this for them rather than + * setting it themselves. + * @see purple_connection_error_is_fatal + */ + gboolean wants_to_die; + + guint disconnect_timeout; /**< Timer used for nasty stack tricks */ + time_t last_received; /**< When we last received a packet. Set by the + prpl to avoid sending unneeded keepalives */ +}; + +/* GObject property enums */ +enum +{ + PROP_0, + PROP_PRPL, + PROP_FLAGS, + PROP_STATE, + PROP_ACCOUNT, + PROP_PASSWORD, + PROP_DISPLAY_NAME, + PROP_LAST +}; + +static GObjectClass *parent_class; + static GList *connections = NULL; static GList *connections_connecting = NULL; static PurpleConnectionUiOps *connection_ui_ops = NULL; static int connections_handle; +/************************************************************************** + * Connection API + **************************************************************************/ static gboolean send_keepalive(gpointer data) { PurpleConnection *gc = data; PurplePluginProtocolInfo *prpl_info; + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); /* Only send keep-alives if we haven't heard from the * server in a while. */ - if ((time(NULL) - gc->last_received) < KEEPALIVE_INTERVAL) + if ((time(NULL) - priv->last_received) < KEEPALIVE_INTERVAL) return TRUE; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(priv->prpl); if (prpl_info->keepalive) prpl_info->keepalive(gc); @@ -72,228 +132,27 @@ static void update_keepalive(PurpleConnection *gc, gboolean on) { PurplePluginProtocolInfo *prpl_info = NULL; + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); - if (gc != NULL && gc->prpl != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + if (priv != NULL && priv->prpl != NULL) + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(priv->prpl); if (!prpl_info || !prpl_info->keepalive) return; - if (on && !gc->keepalive) + if (on && !priv->keepalive) { purple_debug_info("connection", "Activating keepalive.\n"); - gc->keepalive = purple_timeout_add_seconds(KEEPALIVE_INTERVAL, send_keepalive, gc); + priv->keepalive = purple_timeout_add_seconds(KEEPALIVE_INTERVAL, send_keepalive, gc); } - else if (!on && gc->keepalive > 0) + else if (!on && priv->keepalive > 0) { purple_debug_info("connection", "Deactivating keepalive.\n"); - purple_timeout_remove(gc->keepalive); - gc->keepalive = 0; - } -} - -void -_purple_connection_new(PurpleAccount *account, gboolean regist, const char *password) -{ - PurpleConnection *gc; - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; - - g_return_if_fail(account != NULL); - - if (!purple_account_is_disconnected(account)) - return; - - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); - - if (prpl != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - else { - gchar *message; - - message = g_strdup_printf(_("Missing protocol plugin for %s"), - purple_account_get_username(account)); - purple_notify_error(NULL, regist ? _("Registration Error") : - _("Connection Error"), message, NULL); - g_free(message); - return; - } - - if (regist) - { - if (prpl_info->register_user == NULL) - return; - } - else - { - if (((password == NULL) || (*password == '\0')) && - !(prpl_info->options & OPT_PROTO_NO_PASSWORD) && - !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL)) - { - purple_debug_error("connection", "Cannot connect to account %s without " - "a password.\n", purple_account_get_username(account)); - return; - } - } - - gc = g_new0(PurpleConnection, 1); - PURPLE_DBUS_REGISTER_POINTER(gc, PurpleConnection); - - gc->prpl = prpl; - if ((password != NULL) && (*password != '\0')) - gc->password = g_strdup(password); - purple_connection_set_account(gc, account); - purple_connection_set_state(gc, PURPLE_CONNECTING); - connections = g_list_append(connections, gc); - purple_account_set_connection(account, gc); - - purple_signal_emit(purple_connections_get_handle(), "signing-on", gc); - - if (regist) - { - purple_debug_info("connection", "Registering. gc = %p\n", gc); - - /* set this so we don't auto-reconnect after registering */ - gc->wants_to_die = TRUE; - - prpl_info->register_user(account); - } - else - { - purple_debug_info("connection", "Connecting. gc = %p\n", gc); - - purple_signal_emit(purple_accounts_get_handle(), "account-connecting", account); - prpl_info->login(account); + purple_timeout_remove(priv->keepalive); + priv->keepalive = 0; } } -void -_purple_connection_new_unregister(PurpleAccount *account, const char *password, PurpleAccountUnregistrationCb cb, void *user_data) -{ - /* Lots of copy/pasted code to avoid API changes. You might want to integrate that into the previous function when posssible. */ - PurpleConnection *gc; - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; - - g_return_if_fail(account != NULL); - - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); - - if (prpl != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - else { - gchar *message; - - message = g_strdup_printf(_("Missing protocol plugin for %s"), - purple_account_get_username(account)); - purple_notify_error(NULL, _("Unregistration Error"), message, NULL); - g_free(message); - return; - } - - if (!purple_account_is_disconnected(account)) { - prpl_info->unregister_user(account, cb, user_data); - return; - } - - if (((password == NULL) || (*password == '\0')) && - !(prpl_info->options & OPT_PROTO_NO_PASSWORD) && - !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL)) - { - purple_debug_error("connection", "Cannot connect to account %s without " - "a password.\n", purple_account_get_username(account)); - return; - } - - gc = g_new0(PurpleConnection, 1); - PURPLE_DBUS_REGISTER_POINTER(gc, PurpleConnection); - - gc->prpl = prpl; - if ((password != NULL) && (*password != '\0')) - gc->password = g_strdup(password); - purple_connection_set_account(gc, account); - purple_connection_set_state(gc, PURPLE_CONNECTING); - connections = g_list_append(connections, gc); - purple_account_set_connection(account, gc); - - purple_signal_emit(purple_connections_get_handle(), "signing-on", gc); - - purple_debug_info("connection", "Unregistering. gc = %p\n", gc); - - prpl_info->unregister_user(account, cb, user_data); -} - -void -_purple_connection_destroy(PurpleConnection *gc) -{ - PurpleAccount *account; - GSList *buddies; - PurplePluginProtocolInfo *prpl_info = NULL; - gboolean remove = FALSE; - - g_return_if_fail(gc != NULL); - - account = purple_connection_get_account(gc); - - purple_debug_info("connection", "Disconnecting connection %p\n", gc); - - if (purple_connection_get_state(gc) != PURPLE_CONNECTING) - remove = TRUE; - - purple_signal_emit(purple_connections_get_handle(), "signing-off", gc); - - while (gc->buddy_chats) - { - PurpleConversation *b = gc->buddy_chats->data; - - gc->buddy_chats = g_slist_remove(gc->buddy_chats, b); - purple_conv_chat_left(PURPLE_CONV_CHAT(b)); - } - - update_keepalive(gc, FALSE); - - purple_http_conn_cancel_all(gc); - purple_proxy_connect_cancel_with_handle(gc); - - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); - if (prpl_info->close) - (prpl_info->close)(gc); - - /* Clear out the proto data that was freed in the prpl close method*/ - buddies = purple_find_buddies(account, NULL); - while (buddies != NULL) { - PurpleBuddy *buddy = buddies->data; - purple_buddy_set_protocol_data(buddy, NULL); - buddies = g_slist_delete_link(buddies, buddies); - } - - connections = g_list_remove(connections, gc); - - purple_connection_set_state(gc, PURPLE_DISCONNECTED); - - if (remove) - purple_blist_remove_account(account); - - purple_signal_emit(purple_connections_get_handle(), "signed-off", gc); - - purple_account_request_close_with_account(account); - purple_request_close_with_handle(gc); - purple_notify_close_with_handle(gc); - - purple_debug_info("connection", "Destroying connection %p\n", gc); - - purple_account_set_connection(account, NULL); - - purple_str_wipe(gc->password); - g_free(gc->display_name); - - if (gc->disconnect_timeout > 0) - purple_timeout_remove(gc->disconnect_timeout); - - PURPLE_DBUS_UNREGISTER_POINTER(gc); - g_free(gc); -} - /* * d:)->-< * @@ -308,24 +167,25 @@ void purple_connection_set_state(PurpleConnection *gc, PurpleConnectionState state) { PurpleConnectionUiOps *ops; + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); - g_return_if_fail(gc != NULL); + g_return_if_fail(priv != NULL); - if (gc->state == state) + if (priv->state == state) return; - gc->state = state; + priv->state = state; ops = purple_connections_get_ui_ops(); - if (gc->state == PURPLE_CONNECTING) { + if (priv->state == PURPLE_CONNECTION_CONNECTING) { connections_connecting = g_list_append(connections_connecting, gc); } else { connections_connecting = g_list_remove(connections_connecting, gc); } - if (gc->state == PURPLE_CONNECTED) { + if (priv->state == PURPLE_CONNECTION_CONNECTED) { PurpleAccount *account; PurplePresence *presence; @@ -363,7 +223,7 @@ purple_connection_set_state(PurpleConnection *gc, PurpleConnectionState state) update_keepalive(gc, TRUE); } - else if (gc->state == PURPLE_DISCONNECTED) { + else if (priv->state == PURPLE_CONNECTION_DISCONNECTED) { PurpleAccount *account = purple_connection_get_account(gc); if (purple_prefs_get_bool("/purple/logging/log_system")) @@ -391,89 +251,153 @@ purple_connection_set_state(PurpleConnection *gc, PurpleConnectionState state) void purple_connection_set_flags(PurpleConnection *gc, PurpleConnectionFlags flags) { - g_return_if_fail(gc != NULL); + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); - gc->flags = flags; + g_return_if_fail(priv != NULL); + + priv->flags = flags; } void purple_connection_set_account(PurpleConnection *gc, PurpleAccount *account) { - g_return_if_fail(gc != NULL); + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); + + g_return_if_fail(priv != NULL); g_return_if_fail(account != NULL); - gc->account = account; + priv->account = account; } void purple_connection_set_display_name(PurpleConnection *gc, const char *name) { - g_return_if_fail(gc != NULL); + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); + + g_return_if_fail(priv != NULL); - g_free(gc->display_name); - gc->display_name = g_strdup(name); + g_free(priv->display_name); + priv->display_name = g_strdup(name); } void -purple_connection_set_protocol_data(PurpleConnection *connection, void *proto_data) { - g_return_if_fail(connection != NULL); +purple_connection_set_protocol_data(PurpleConnection *gc, void *proto_data) +{ + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); + + g_return_if_fail(priv != NULL); - connection->proto_data = proto_data; + priv->proto_data = proto_data; } PurpleConnectionState purple_connection_get_state(const PurpleConnection *gc) { - g_return_val_if_fail(gc != NULL, PURPLE_DISCONNECTED); + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); - return gc->state; + g_return_val_if_fail(priv != NULL, PURPLE_CONNECTION_DISCONNECTED); + + return priv->state; } PurpleConnectionFlags purple_connection_get_flags(const PurpleConnection *gc) { - g_return_val_if_fail(gc != NULL, 0); + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); + + g_return_val_if_fail(priv != NULL, 0); - return gc->flags; + return priv->flags; } PurpleAccount * purple_connection_get_account(const PurpleConnection *gc) { - g_return_val_if_fail(gc != NULL, NULL); + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); - return gc->account; + g_return_val_if_fail(priv != NULL, NULL); + + return priv->account; } PurplePlugin * purple_connection_get_prpl(const PurpleConnection *gc) { - g_return_val_if_fail(gc != NULL, NULL); + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); + + g_return_val_if_fail(priv != NULL, NULL); - return gc->prpl; + return priv->prpl; } const char * purple_connection_get_password(const PurpleConnection *gc) { - g_return_val_if_fail(gc != NULL, NULL); + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->password; +} + +GSList * +purple_connection_get_active_chats(const PurpleConnection *gc) +{ + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); - return gc->password; + g_return_val_if_fail(priv != NULL, NULL); + + return priv->active_chats; } const char * purple_connection_get_display_name(const PurpleConnection *gc) { - g_return_val_if_fail(gc != NULL, NULL); + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); + + g_return_val_if_fail(priv != NULL, NULL); - return gc->display_name; + return priv->display_name; } void * -purple_connection_get_protocol_data(const PurpleConnection *connection) { - g_return_val_if_fail(connection != NULL, NULL); +purple_connection_get_protocol_data(const PurpleConnection *gc) +{ + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); - return connection->proto_data; + g_return_val_if_fail(priv != NULL, NULL); + + return priv->proto_data; +} + +void +_purple_connection_add_active_chat(PurpleConnection *gc, PurpleChatConversation *chat) +{ + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); + + g_return_if_fail(priv != NULL); + + priv->active_chats = g_slist_append(priv->active_chats, chat); +} + +void +_purple_connection_remove_active_chat(PurpleConnection *gc, PurpleChatConversation *chat) +{ + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); + + g_return_if_fail(priv != NULL); + + priv->active_chats = g_slist_remove(priv->active_chats, chat); +} + +gboolean +_purple_connection_wants_to_die(const PurpleConnection *gc) +{ + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); + + g_return_val_if_fail(priv != NULL, FALSE); + + return priv->wants_to_die; } void @@ -512,12 +436,14 @@ purple_connection_disconnect_cb(gpointer data) { PurpleAccount *account; PurpleConnection *gc; + PurpleConnectionPrivate *priv; account = data; gc = purple_account_get_connection(account); + priv = PURPLE_CONNECTION_GET_PRIVATE(gc); - if (gc != NULL) - gc->disconnect_timeout = 0; + if (priv != NULL) + priv->disconnect_timeout = 0; purple_account_disconnect(account); return FALSE; @@ -529,8 +455,9 @@ purple_connection_error (PurpleConnection *gc, const char *description) { PurpleConnectionUiOps *ops; + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); - g_return_if_fail(gc != NULL); + g_return_if_fail(priv != NULL); /* This sanity check relies on PURPLE_CONNECTION_ERROR_OTHER_ERROR * being the last member of the PurpleConnectionError enum in * connection.h; if other reasons are added after it, this check should @@ -549,10 +476,10 @@ purple_connection_error (PurpleConnection *gc, } /* If we've already got one error, we don't need any more */ - if (gc->disconnect_timeout > 0) + if (priv->disconnect_timeout > 0) return; - gc->wants_to_die = purple_connection_error_is_fatal (reason); + priv->wants_to_die = purple_connection_error_is_fatal (reason); purple_debug_info("connection", "Connection error on %p (reason: %u description: %s)\n", gc, reason, description); @@ -565,7 +492,7 @@ purple_connection_error (PurpleConnection *gc, purple_signal_emit(purple_connections_get_handle(), "connection-error", gc, reason, description); - gc->disconnect_timeout = purple_timeout_add(0, purple_connection_disconnect_cb, + priv->disconnect_timeout = purple_timeout_add(0, purple_connection_disconnect_cb, purple_connection_get_account(gc)); } @@ -626,21 +553,457 @@ purple_connection_error_is_fatal (PurpleConnectionError reason) void purple_connection_update_last_received(PurpleConnection *gc) { - g_return_if_fail(gc != NULL); + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); + + g_return_if_fail(priv != NULL); + + priv->last_received = time(NULL); +} + +/************************************************************************** + * GBoxed code + **************************************************************************/ +static PurpleConnectionErrorInfo * +purple_connection_error_info_copy(PurpleConnectionErrorInfo *err) +{ + PurpleConnectionErrorInfo *newerr; - gc->last_received = time(NULL); + g_return_val_if_fail(err != NULL, NULL); + + newerr = g_new(PurpleConnectionErrorInfo, 1); + newerr->type = err->type; + newerr->description = g_strdup(err->description); + + return newerr; +} + +static void +purple_connection_error_info_free(PurpleConnectionErrorInfo *err) +{ + g_return_if_fail(err != NULL); + + g_free(err->description); + g_free(err); +} + +GType +purple_connection_error_info_get_type(void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static("PurpleConnectionErrorInfo", + (GBoxedCopyFunc)purple_connection_error_info_copy, + (GBoxedFreeFunc)purple_connection_error_info_free); + } + + return type; +} + +/************************************************************************** + * GObject code + **************************************************************************/ +/* GObject Property names */ +#define PROP_PRPL_S "prpl" +#define PROP_FLAGS_S "flags" +#define PROP_STATE_S "state" +#define PROP_ACCOUNT_S "account" +#define PROP_PASSWORD_S "password" +#define PROP_DISPLAY_NAME_S "display-name" + +/* Set method for GObject properties */ +static void +purple_connection_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleConnection *gc = PURPLE_CONNECTION(obj); + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); + + switch (param_id) { + case PROP_PRPL: +#warning TODO: change get_pointer to get_object when prpl is a GObject + priv->prpl = g_value_get_pointer(value); + break; + case PROP_FLAGS: + purple_connection_set_flags(gc, g_value_get_flags(value)); + break; + case PROP_STATE: + purple_connection_set_state(gc, g_value_get_enum(value)); + break; + case PROP_ACCOUNT: + purple_connection_set_account(gc, g_value_get_object(value)); + break; + case PROP_PASSWORD: + g_free(priv->password); + priv->password = g_strdup(g_value_get_string(value)); + break; + case PROP_DISPLAY_NAME: + purple_connection_set_display_name(gc, g_value_get_string(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_connection_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleConnection *gc = PURPLE_CONNECTION(obj); + + switch (param_id) { + case PROP_PRPL: +#warning TODO: change set_pointer to set_object when prpl is a GObject + g_value_set_pointer(value, purple_connection_get_prpl(gc)); + break; + case PROP_FLAGS: + g_value_set_flags(value, purple_connection_get_flags(gc)); + break; + case PROP_STATE: + g_value_set_enum(value, purple_connection_get_state(gc)); + break; + case PROP_ACCOUNT: + g_value_set_object(value, purple_connection_get_account(gc)); + break; + case PROP_PASSWORD: + g_value_set_string(value, purple_connection_get_password(gc)); + break; + case PROP_DISPLAY_NAME: + g_value_set_string(value, purple_connection_get_display_name(gc)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* GObject initialization function */ +static void +purple_connection_init(GTypeInstance *instance, gpointer klass) +{ + PurpleConnection *gc = PURPLE_CONNECTION(instance); + + purple_connection_set_state(gc, PURPLE_CONNECTION_CONNECTING); + connections = g_list_append(connections, gc); + + PURPLE_DBUS_REGISTER_POINTER(gc, PurpleConnection); +} + +/* Called when done constructing */ +static void +purple_connection_constructed(GObject *object) +{ + PurpleConnection *gc = PURPLE_CONNECTION(object); + PurpleAccount *account; + + G_OBJECT_CLASS(parent_class)->constructed(object); + + g_object_get(gc, PROP_ACCOUNT_S, &account, NULL); + purple_account_set_connection(account, gc); + + purple_signal_emit(purple_connections_get_handle(), "signing-on", gc); +} + +/* GObject dispose function */ +static void +purple_connection_dispose(GObject *object) +{ + PurpleConnection *gc = PURPLE_CONNECTION(object); + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); + PurpleAccount *account; + GSList *buddies; + PurplePluginProtocolInfo *prpl_info = NULL; + gboolean remove = FALSE; + + account = purple_connection_get_account(gc); + + purple_debug_info("connection", "Disconnecting connection %p\n", gc); + + if (purple_connection_get_state(gc) != PURPLE_CONNECTION_CONNECTING) + remove = TRUE; + + purple_signal_emit(purple_connections_get_handle(), "signing-off", gc); + + while (priv->active_chats) + { + PurpleChatConversation *b = priv->active_chats->data; + + priv->active_chats = g_slist_remove(priv->active_chats, b); + purple_chat_conversation_leave(b); + } + + update_keepalive(gc, FALSE); + + purple_http_conn_cancel_all(gc); + purple_proxy_connect_cancel_with_handle(gc); + + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(priv->prpl); + if (prpl_info->close) + (prpl_info->close)(gc); + + /* Clear out the proto data that was freed in the prpl close method*/ + buddies = purple_blist_find_buddies(account, NULL); + while (buddies != NULL) { + PurpleBuddy *buddy = buddies->data; + purple_buddy_set_protocol_data(buddy, NULL); + buddies = g_slist_delete_link(buddies, buddies); + } + + connections = g_list_remove(connections, gc); + + purple_connection_set_state(gc, PURPLE_CONNECTION_DISCONNECTED); + + if (remove) + purple_blist_remove_account(account); + + purple_signal_emit(purple_connections_get_handle(), "signed-off", gc); + + purple_account_request_close_with_account(account); + purple_request_close_with_handle(gc); + purple_notify_close_with_handle(gc); + + purple_debug_info("connection", "Destroying connection %p\n", gc); + + purple_account_set_connection(account, NULL); + + if (priv->disconnect_timeout > 0) + purple_timeout_remove(priv->disconnect_timeout); + + PURPLE_DBUS_UNREGISTER_POINTER(gc); + + G_OBJECT_CLASS(parent_class)->dispose(object); +} + +/* GObject finalize function */ +static void +purple_connection_finalize(GObject *object) +{ + PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(object); + + purple_str_wipe(priv->password); + g_free(priv->display_name); + + G_OBJECT_CLASS(parent_class)->finalize(object); +} + +/* Class initializer function */ +static void purple_connection_class_init(PurpleConnectionClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->dispose = purple_connection_dispose; + obj_class->finalize = purple_connection_finalize; + obj_class->constructed = purple_connection_constructed; + + /* Setup properties */ + obj_class->get_property = purple_connection_get_property; + obj_class->set_property = purple_connection_set_property; + +#warning TODO: change spec_pointer to spec_object when prpl is a GObject + g_object_class_install_property(obj_class, PROP_PRPL, + g_param_spec_pointer(PROP_PRPL_S, _("Protocol plugin"), + _("The prpl that is using the connection."), + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY) + ); + + g_object_class_install_property(obj_class, PROP_FLAGS, + g_param_spec_flags(PROP_FLAGS_S, _("Connection flags"), + _("The flags of the connection."), + PURPLE_TYPE_CONNECTION_FLAGS, 0, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PROP_STATE, + g_param_spec_enum(PROP_STATE_S, _("Connection state"), + _("The current state of the connection."), + PURPLE_TYPE_CONNECTION_STATE, PURPLE_CONNECTION_DISCONNECTED, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PROP_ACCOUNT, + g_param_spec_object(PROP_ACCOUNT_S, _("Account"), + _("The account using the connection."), PURPLE_TYPE_ACCOUNT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_object_class_install_property(obj_class, PROP_PASSWORD, + g_param_spec_string(PROP_PASSWORD_S, _("Password"), + _("The password used for connection."), NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY) + ); + + g_object_class_install_property(obj_class, PROP_DISPLAY_NAME, + g_param_spec_string(PROP_DISPLAY_NAME_S, _("Display name"), + _("Your name that appears to other people."), NULL, + G_PARAM_READWRITE) + ); + + g_type_class_add_private(klass, sizeof(PurpleConnectionPrivate)); +} + +GType +purple_connection_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleConnectionClass), + NULL, + NULL, + (GClassInitFunc)purple_connection_class_init, + NULL, + NULL, + sizeof(PurpleConnection), + 0, + (GInstanceInitFunc)purple_connection_init, + NULL, + }; + + type = g_type_register_static(G_TYPE_OBJECT, "PurpleConnection", + &info, 0); + } + + return type; +} + +void +_purple_connection_new(PurpleAccount *account, gboolean regist, const char *password) +{ + PurpleConnection *gc; + PurplePlugin *prpl; + PurplePluginProtocolInfo *prpl_info; + + g_return_if_fail(account != NULL); + + if (!purple_account_is_disconnected(account)) + return; + + prpl = purple_find_prpl(purple_account_get_protocol_id(account)); + + if (prpl != NULL) + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + else { + gchar *message; + + message = g_strdup_printf(_("Missing protocol plugin for %s"), + purple_account_get_username(account)); + purple_notify_error(NULL, regist ? _("Registration Error") : + _("Connection Error"), message, NULL); + g_free(message); + return; + } + + if (regist) + { + if (prpl_info->register_user == NULL) + return; + } + else + { + if (((password == NULL) || (*password == '\0')) && + !(prpl_info->options & OPT_PROTO_NO_PASSWORD) && + !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL)) + { + purple_debug_error("connection", "Cannot connect to account %s without " + "a password.\n", purple_account_get_username(account)); + return; + } + } + + gc = g_object_new(PURPLE_TYPE_CONNECTION, + PROP_PRPL_S, prpl, + PROP_PASSWORD_S, password, + PROP_ACCOUNT_S, account, + NULL); + + if (regist) + { + purple_debug_info("connection", "Registering. gc = %p\n", gc); + + /* set this so we don't auto-reconnect after registering */ + PURPLE_CONNECTION_GET_PRIVATE(gc)->wants_to_die = TRUE; + + prpl_info->register_user(account); + } + else + { + purple_debug_info("connection", "Connecting. gc = %p\n", gc); + + purple_signal_emit(purple_accounts_get_handle(), "account-connecting", account); + prpl_info->login(account); + } +} + +void +_purple_connection_new_unregister(PurpleAccount *account, const char *password, + PurpleAccountUnregistrationCb cb, void *user_data) +{ + /* Lots of copy/pasted code to avoid API changes. You might want to integrate that into the previous function when posssible. */ + PurpleConnection *gc; + PurplePlugin *prpl; + PurplePluginProtocolInfo *prpl_info; + + g_return_if_fail(account != NULL); + + prpl = purple_find_prpl(purple_account_get_protocol_id(account)); + + if (prpl != NULL) + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + else { + gchar *message; + + message = g_strdup_printf(_("Missing protocol plugin for %s"), + purple_account_get_username(account)); + purple_notify_error(NULL, _("Unregistration Error"), message, NULL); + g_free(message); + return; + } + + if (!purple_account_is_disconnected(account)) { + prpl_info->unregister_user(account, cb, user_data); + return; + } + + if (((password == NULL) || (*password == '\0')) && + !(prpl_info->options & OPT_PROTO_NO_PASSWORD) && + !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL)) + { + purple_debug_error("connection", "Cannot connect to account %s without " + "a password.\n", purple_account_get_username(account)); + return; + } + + gc = g_object_new(PURPLE_TYPE_CONNECTION, + PROP_PRPL_S, prpl, + PROP_PASSWORD_S, password, + PROP_ACCOUNT_S, account, + NULL); + + purple_debug_info("connection", "Unregistering. gc = %p\n", gc); + + prpl_info->unregister_user(account, cb, user_data); } +/************************************************************************** + * Connections API + **************************************************************************/ void purple_connections_disconnect_all(void) { GList *l; PurpleConnection *gc; + PurpleConnectionPrivate *priv; while ((l = purple_connections_get_all()) != NULL) { gc = l->data; - gc->wants_to_die = TRUE; - purple_account_disconnect(gc->account); + priv = PURPLE_CONNECTION_GET_PRIVATE(gc); + priv->wants_to_die = TRUE; + purple_account_disconnect(priv->account); } } @@ -674,36 +1037,29 @@ purple_connections_init(void) void *handle = purple_connections_get_handle(); purple_signal_register(handle, "signing-on", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONNECTION)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_CONNECTION); purple_signal_register(handle, "signed-on", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONNECTION)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_CONNECTION); purple_signal_register(handle, "signing-off", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONNECTION)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_CONNECTION); purple_signal_register(handle, "signed-off", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONNECTION)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_CONNECTION); purple_signal_register(handle, "connection-error", - purple_marshal_VOID__POINTER_INT_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONNECTION), - purple_value_new(PURPLE_TYPE_ENUM), - purple_value_new(PURPLE_TYPE_STRING)); + purple_marshal_VOID__POINTER_INT_POINTER, + G_TYPE_NONE, 3, PURPLE_TYPE_CONNECTION, + PURPLE_TYPE_CONNECTION_ERROR, G_TYPE_STRING); purple_signal_register(handle, "autojoin", - purple_marshal_BOOLEAN__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONNECTION)); + purple_marshal_BOOLEAN__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_CONNECTION); } diff --git a/libpurple/connection.h b/libpurple/connection.h index 65c88d61b1..abfc31cf5a 100644 --- a/libpurple/connection.h +++ b/libpurple/connection.h @@ -27,33 +27,43 @@ #ifndef _PURPLE_CONNECTION_H_ #define _PURPLE_CONNECTION_H_ +#define PURPLE_TYPE_CONNECTION (purple_connection_get_type()) +#define PURPLE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_CONNECTION, PurpleConnection)) +#define PURPLE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_CONNECTION, PurpleConnectionClass)) +#define PURPLE_IS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_CONNECTION)) +#define PURPLE_IS_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_CONNECTION)) +#define PURPLE_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_CONNECTION, PurpleConnectionClass)) + +#define PURPLE_TYPE_CONNECTION_ERROR_INFO (purple_connection_error_info_get_type()) + /** @copydoc _PurpleConnection */ typedef struct _PurpleConnection PurpleConnection; +/** @copydoc _PurpleConnectionClass */ +typedef struct _PurpleConnectionClass PurpleConnectionClass; /** * Flags to change behavior of the client for a given connection. */ -typedef enum +typedef enum /*< flags >*/ { - PURPLE_CONNECTION_HTML = 0x0001, /**< Connection sends/receives in 'HTML'. */ - PURPLE_CONNECTION_NO_BGCOLOR = 0x0002, /**< Connection does not send/receive - background colors. */ - PURPLE_CONNECTION_AUTO_RESP = 0x0004, /**< Send auto responses when away. */ - PURPLE_CONNECTION_FORMATTING_WBFO = 0x0008, /**< The text buffer must be formatted as a whole */ - PURPLE_CONNECTION_NO_NEWLINES = 0x0010, /**< No new lines are allowed in outgoing messages */ - PURPLE_CONNECTION_NO_FONTSIZE = 0x0020, /**< Connection does not send/receive font sizes */ - PURPLE_CONNECTION_NO_URLDESC = 0x0040, /**< Connection does not support descriptions with links */ - PURPLE_CONNECTION_NO_IMAGES = 0x0080, /**< Connection does not support sending of images */ - PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY = 0x0100, /**< Connection supports sending and receiving custom smileys */ - PURPLE_CONNECTION_SUPPORT_MOODS = 0x0200, /**< Connection supports setting moods */ - PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES = 0x0400 /**< Connection supports setting a message on moods */ + PURPLE_CONNECTION_FLAG_HTML = 0x0001, /**< Connection sends/receives in 'HTML' */ + PURPLE_CONNECTION_FLAG_NO_BGCOLOR = 0x0002, /**< Connection does not send/receive background colors */ + PURPLE_CONNECTION_FLAG_AUTO_RESP = 0x0004, /**< Send auto responses when away */ + PURPLE_CONNECTION_FLAG_FORMATTING_WBFO = 0x0008, /**< The text buffer must be formatted as a whole */ + PURPLE_CONNECTION_FLAG_NO_NEWLINES = 0x0010, /**< No new lines are allowed in outgoing messages */ + PURPLE_CONNECTION_FLAG_NO_FONTSIZE = 0x0020, /**< Connection does not send/receive font sizes */ + PURPLE_CONNECTION_FLAG_NO_URLDESC = 0x0040, /**< Connection does not support descriptions with links */ + PURPLE_CONNECTION_FLAG_NO_IMAGES = 0x0080, /**< Connection does not support sending of images */ + PURPLE_CONNECTION_FLAG_ALLOW_CUSTOM_SMILEY = 0x0100, /**< Connection supports sending and receiving custom smileys */ + PURPLE_CONNECTION_FLAG_SUPPORT_MOODS = 0x0200, /**< Connection supports setting moods */ + PURPLE_CONNECTION_FLAG_SUPPORT_MOOD_MESSAGES = 0x0400 /**< Connection supports setting a message on moods */ } PurpleConnectionFlags; typedef enum { - PURPLE_DISCONNECTED = 0, /**< Disconnected. */ - PURPLE_CONNECTED, /**< Connected. */ - PURPLE_CONNECTING /**< Connecting. */ + PURPLE_CONNECTION_DISCONNECTED = 0, /**< Disconnected. */ + PURPLE_CONNECTION_CONNECTED, /**< Connected. */ + PURPLE_CONNECTION_CONNECTING /**< Connecting. */ } PurpleConnectionState; @@ -222,40 +232,27 @@ typedef struct void (*_purple_reserved1)(void); void (*_purple_reserved2)(void); void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); } PurpleConnectionUiOps; - -/* Represents an active connection on an account. */ +/** + * Represents an active connection on an account. + */ struct _PurpleConnection { - PurplePlugin *prpl; /**< The protocol plugin. */ - PurpleConnectionFlags flags; /**< Connection flags. */ - - PurpleConnectionState state; /**< The connection state. */ - - PurpleAccount *account; /**< The account being connected to. */ - char *password; /**< The password used. */ - - GSList *buddy_chats; /**< A list of active chats - (#PurpleConversation structs of type - #PURPLE_CONV_TYPE_CHAT). */ - void *proto_data; /**< Protocol-specific data. */ + /*< private >*/ + GObject gparent; +}; - char *display_name; /**< How you appear to other people. */ - guint keepalive; /**< Keep-alive. */ +/** Base class for all #PurpleConnection's */ +struct _PurpleConnectionClass { + /*< private >*/ + GObjectClass parent_class; - /** Wants to Die state. This is set when the user chooses to log out, or - * when the protocol is disconnected and should not be automatically - * reconnected (incorrect password, etc.). prpls should rely on - * purple_connection_error() to set this for them rather than - * setting it themselves. - * @see purple_connection_error_is_fatal - */ - gboolean wants_to_die; - - guint disconnect_timeout; /**< Timer used for nasty stack tricks */ - time_t last_received; /**< When we last received a packet. Set by the - prpl to avoid sending unneeded keepalives */ + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); }; G_BEGIN_DECLS @@ -266,8 +263,18 @@ G_BEGIN_DECLS /*@{*/ /** + * Returns the GType for the Connection object. + */ +GType purple_connection_get_type(void); + +/** + * Returns the GType for the PurpleConnectionErrorInfo boxed structure. + */ +GType purple_connection_error_info_get_type(void); + +/** * Sets the connection state. PRPLs should call this and pass in - * the state #PURPLE_CONNECTED when the account is completely + * the state #PURPLE_CONNECTION_CONNECTED when the account is completely * signed on. What does it mean to be completely signed on? If * the core can call prpl->set_status, and it successfully changes * your status, then the account is online. @@ -333,7 +340,7 @@ PurpleConnectionFlags purple_connection_get_flags(const PurpleConnection *gc); * @return TRUE if the account is connected, otherwise returns FALSE. */ #define PURPLE_CONNECTION_IS_CONNECTED(gc) \ - (purple_connection_get_state(gc) == PURPLE_CONNECTED) + (purple_connection_get_state(gc) == PURPLE_CONNECTION_CONNECTED) /** * Returns the connection's account. @@ -363,6 +370,15 @@ PurplePlugin * purple_connection_get_prpl(const PurpleConnection *gc); const char *purple_connection_get_password(const PurpleConnection *gc); /** + * Returns a list of active chat conversations on a connection. + * + * @param gc The connection. + * + * @return The active chats on the connection. + */ +GSList *purple_connection_get_active_chats(const PurpleConnection *gc); + +/** * Returns the connection's displayed name. * * @param gc The connection. @@ -401,9 +417,7 @@ void purple_connection_notice(PurpleConnection *gc, const char *text); /** * Closes a connection with an error and a human-readable description of the - * error. It also sets @c gc->wants_to_die to the value of - * #purple_connection_error_is_fatal(@a reason), mainly for - * backwards-compatibility. + * error. * * @param gc the connection which is closing. * @param reason why the connection is closing. @@ -436,8 +450,6 @@ purple_connection_ssl_error (PurpleConnection *gc, * <tt> purple_connection_error_is_fatal * (PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED)</tt> is @c TRUE. * - * (This function is meant to replace checking PurpleConnection.wants_to_die.) - * * @return @c TRUE if the account should not be automatically reconnected, and * @c FALSE otherwise. */ diff --git a/libpurple/conversation.c b/libpurple/conversation.c index b6a6058675..6e1a2c723d 100644 --- a/libpurple/conversation.c +++ b/libpurple/conversation.c @@ -20,11 +20,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ #include "internal.h" -#include "blist.h" +#include "buddylist.h" #include "cmds.h" #include "conversation.h" #include "dbus-maybe.h" #include "debug.h" +#include "enums.h" #include "imgstore.h" #include "notify.h" #include "prefs.h" @@ -33,123 +34,35 @@ #include "signals.h" #include "util.h" -#define SEND_TYPED_TIMEOUT_SECONDS 5 +#define PURPLE_CONVERSATION_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_CONVERSATION, PurpleConversationPrivate)) -/** - * Data specific to Chats. - */ -struct _PurpleConvChat -{ - PurpleConversation *conv; /**< The parent conversation. */ - - GList *in_room; /**< The users in the room. - * @deprecated Will be removed in 3.0.0 - */ - GList *ignored; /**< Ignored users. */ - char *who; /**< The person who set the topic. */ - char *topic; /**< The topic. */ - int id; /**< The chat ID. */ - char *nick; /**< Your nick in this chat. */ - - gboolean left; /**< We left the chat and kept the window open */ - GHashTable *users; /**< Hash table of the users in the room. */ -}; - -/** - * Data specific to Instant Messages. - */ -struct _PurpleConvIm -{ - PurpleConversation *conv; /**< The parent conversation. */ - - PurpleTypingState typing_state; /**< The current typing state. */ - guint typing_timeout; /**< The typing timer handle. */ - time_t type_again; /**< The type again time. */ - guint send_typed_timeout; /**< The type again timer handle. */ - - PurpleBuddyIcon *icon; /**< The buddy icon. */ -}; - -/** - * Data for "Chat Buddies" - */ -struct _PurpleConvChatBuddy -{ - /** The chat participant's name in the chat. */ - char *name; - - /** The chat participant's alias, if known; @a NULL otherwise. */ - char *alias; - - /** - * A string by which this buddy will be sorted, or @c NULL if the - * buddy should be sorted by its @c name. (This is currently always - * @c NULL. - */ - char *alias_key; - - /** - * @a TRUE if this chat participant is on the buddy list; - * @a FALSE otherwise. - */ - gboolean buddy; +/** @copydoc _PurpleConversationPrivate */ +typedef struct _PurpleConversationPrivate PurpleConversationPrivate; - /** - * A bitwise OR of flags for this participant, such as whether they - * are a channel operator. - */ - PurpleConvChatBuddyFlags flags; - - /** - * A hash table of attributes about the user, such as real name, - * user\@host, etc. - */ - GHashTable *attributes; - - /** The UI can put whatever it wants here. */ - gpointer ui_data; -}; - -/** - * A core representation of a conversation between two or more people. - * - * The conversation can be an IM or a chat. - */ -struct _PurpleConversation +/** General private data for a conversation */ +struct _PurpleConversationPrivate { - PurpleConversationType type; /**< The type of conversation. */ - - PurpleAccount *account; /**< The user using this conversation. */ - - - char *name; /**< The name of the conversation. */ - char *title; /**< The window title. */ - - gboolean logging; /**< The status of logging. */ - - GList *logs; /**< This conversation's logs */ + PurpleAccount *account; /**< The user using this conversation. */ - union - { - PurpleConvIm *im; /**< IM-specific data. */ - PurpleConvChat *chat; /**< Chat-specific data. */ - void *misc; /**< Misc. data. */ + char *name; /**< The name of the conversation. */ + char *title; /**< The window title. */ - } u; + gboolean logging; /**< The status of logging. */ - PurpleConversationUiOps *ui_ops; /**< UI-specific operations. */ - void *ui_data; /**< UI-specific data. */ + GList *logs; /**< This conversation's logs */ - GHashTable *data; /**< Plugin-specific data. */ + PurpleConversationUiOps *ui_ops; /**< UI-specific operations. */ - PurpleConnectionFlags features; /**< The supported features */ - GList *message_history; /**< Message history, as a GList of PurpleConvMessage's */ + PurpleConnectionFlags features; /**< The supported features */ + GList *message_history; /**< Message history, as a GList of + PurpleConversationMessage's */ }; /** * Description of a conversation message */ -struct _PurpleConvMessage +struct _PurpleConversationMessage { char *who; char *what; @@ -159,124 +72,40 @@ struct _PurpleConvMessage char *alias; }; - -static GList *conversations = NULL; -static GList *ims = NULL; -static GList *chats = NULL; -static PurpleConversationUiOps *default_ops = NULL; - -/** - * A hash table used for efficient lookups of conversations by name. - * struct _purple_hconv => PurpleConversation* - */ -static GHashTable *conversation_cache = NULL; - -struct _purple_hconv { - PurpleConversationType type; - char *name; - const PurpleAccount *account; -}; - -static guint _purple_conversations_hconv_hash(struct _purple_hconv *hc) -{ - return g_str_hash(hc->name) ^ hc->type ^ g_direct_hash(hc->account); -} - -static guint _purple_conversations_hconv_equal(struct _purple_hconv *hc1, struct _purple_hconv *hc2) -{ - return (hc1->type == hc2->type && - hc1->account == hc2->account && - g_str_equal(hc1->name, hc2->name)); -} - -static void _purple_conversations_hconv_free_key(struct _purple_hconv *hc) +/* GObject Property enums */ +enum { - g_free(hc->name); - g_free(hc); -} - -static guint _purple_conversation_user_hash(gconstpointer data) -{ - const gchar *name = data; - gchar *collated; - guint hash; - - collated = g_utf8_collate_key(name, -1); - hash = g_str_hash(collated); - g_free(collated); - return hash; -} - -static gboolean _purple_conversation_user_equal(gconstpointer a, gconstpointer b) -{ - return !g_utf8_collate(a, b); -} - -void -purple_conversations_set_ui_ops(PurpleConversationUiOps *ops) -{ - default_ops = ops; -} - -static gboolean -reset_typing_cb(gpointer data) -{ - PurpleConversation *c = (PurpleConversation *)data; - PurpleConvIm *im; - - im = PURPLE_CONV_IM(c); - - purple_conv_im_set_typing_state(im, PURPLE_NOT_TYPING); - purple_conv_im_stop_typing_timeout(im); - - return FALSE; -} - -static gboolean -send_typed_cb(gpointer data) -{ - PurpleConversation *conv = (PurpleConversation *)data; - PurpleConnection *gc; - const char *name; - - g_return_val_if_fail(conv != NULL, FALSE); - - gc = purple_conversation_get_connection(conv); - name = purple_conversation_get_name(conv); - - if (gc != NULL && name != NULL) { - /* We set this to 1 so that PURPLE_TYPING will be sent - * if the Purple user types anything else. - */ - purple_conv_im_set_type_again(PURPLE_CONV_IM(conv), 1); - - serv_send_typing(gc, name, PURPLE_TYPED); + PROP_0, + PROP_ACCOUNT, + PROP_NAME, + PROP_TITLE, + PROP_LOGGING, + PROP_FEATURES, + PROP_LAST +}; - purple_debug(PURPLE_DEBUG_MISC, "conversation", "typed...\n"); - } +static GObjectClass *parent_class; - return FALSE; -} static void common_send(PurpleConversation *conv, const char *message, PurpleMessageFlags msgflags) { - PurpleConversationType type; PurpleAccount *account; PurpleConnection *gc; + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); char *displayed = NULL, *sent = NULL; int err = 0; + g_return_if_fail(priv != NULL); + if (*message == '\0') return; account = purple_conversation_get_account(conv); - gc = purple_conversation_get_connection(conv); - g_return_if_fail(account != NULL); - g_return_if_fail(gc != NULL); - type = purple_conversation_get_type(conv); + gc = purple_account_get_connection(account); + g_return_if_fail(gc != NULL); /* Always linkfy the text for display, unless we're * explicitly asked to do otheriwse*/ @@ -287,7 +116,7 @@ common_send(PurpleConversation *conv, const char *message, PurpleMessageFlags ms displayed = purple_markup_linkify(message); } - if (displayed && (conv->features & PURPLE_CONNECTION_HTML) && + if (displayed && (priv->features & PURPLE_CONNECTION_FLAG_HTML) && !(msgflags & PURPLE_MESSAGE_RAW)) { sent = g_strdup(displayed); } else @@ -295,9 +124,7 @@ common_send(PurpleConversation *conv, const char *message, PurpleMessageFlags ms msgflags |= PURPLE_MESSAGE_SEND; - if (type == PURPLE_CONV_TYPE_IM) { - PurpleConvIm *im = PURPLE_CONV_IM(conv); - + if (PURPLE_IS_IM_CONVERSATION(conv)) { purple_signal_emit(purple_conversations_get_handle(), "sending-im-msg", account, purple_conversation_get_name(conv), &sent); @@ -308,7 +135,7 @@ common_send(PurpleConversation *conv, const char *message, PurpleMessageFlags ms sent, msgflags); if ((err > 0) && (displayed != NULL)) - purple_conv_im_write(im, NULL, displayed, msgflags, time(NULL)); + purple_conversation_write_message(conv, NULL, displayed, msgflags, time(NULL)); purple_signal_emit(purple_conversations_get_handle(), "sent-im-msg", account, @@ -316,16 +143,17 @@ common_send(PurpleConversation *conv, const char *message, PurpleMessageFlags ms } } else { + PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(conv); purple_signal_emit(purple_conversations_get_handle(), "sending-chat-msg", account, &sent, - purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv))); + purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv))); if (sent != NULL && sent[0] != '\0') { - err = serv_chat_send(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), sent, msgflags); + err = serv_chat_send(gc, purple_chat_conversation_get_id(chat), sent, msgflags); purple_signal_emit(purple_conversations_get_handle(), "sent-chat-msg", account, sent, - purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv))); + purple_chat_conversation_get_id(chat)); } } @@ -338,7 +166,7 @@ common_send(PurpleConversation *conv, const char *message, PurpleMessageFlags ms if (err == -E2BIG) { msg = _("Unable to send message: The message is too large."); - if (!purple_conv_present_error(who, account, msg)) { + if (!purple_conversation_present_error(who, account, msg)) { char *msg2 = g_strdup_printf(_("Unable to send message to %s."), who); purple_notify_error(gc, NULL, msg2, _("The message is too large.")); g_free(msg2); @@ -351,7 +179,7 @@ common_send(PurpleConversation *conv, const char *message, PurpleMessageFlags ms else { msg = _("Unable to send message."); - if (!purple_conv_present_error(who, account, msg)) { + if (!purple_conversation_present_error(who, account, msg)) { char *msg2 = g_strdup_printf(_("Unable to send message to %s."), who); purple_notify_error(gc, NULL, msg2, NULL); g_free(msg2); @@ -366,33 +194,40 @@ common_send(PurpleConversation *conv, const char *message, PurpleMessageFlags ms static void open_log(PurpleConversation *conv) { - conv->logs = g_list_append(NULL, purple_log_new(conv->type == PURPLE_CONV_TYPE_CHAT ? PURPLE_LOG_CHAT : - PURPLE_LOG_IM, conv->name, conv->account, + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); + + g_return_if_fail(priv != NULL); + + priv->logs = g_list_append(NULL, purple_log_new(PURPLE_IS_CHAT_CONVERSATION(conv) ? PURPLE_LOG_CHAT : + PURPLE_LOG_IM, priv->name, priv->account, conv, time(NULL), NULL)); } -/* Functions that deal with PurpleConvMessage */ +/* Functions that deal with PurpleConversationMessage */ static void add_message_to_history(PurpleConversation *conv, const char *who, const char *alias, const char *message, PurpleMessageFlags flags, time_t when) { - PurpleConvMessage *msg; + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); + PurpleConversationMessage *msg; PurpleConnection *gc; - gc = purple_account_get_connection(conv->account); + g_return_if_fail(priv != NULL); + + gc = purple_account_get_connection(priv->account); if (flags & PURPLE_MESSAGE_SEND) { const char *me = NULL; if (gc) me = purple_connection_get_display_name(gc); if (!me) - me = purple_account_get_username(conv->account); + me = purple_account_get_username(priv->account); who = me; } - msg = g_new0(PurpleConvMessage, 1); - PURPLE_DBUS_REGISTER_POINTER(msg, PurpleConvMessage); + msg = g_new0(PurpleConversationMessage, 1); + PURPLE_DBUS_REGISTER_POINTER(msg, PurpleConversationMessage); msg->who = g_strdup(who); msg->alias = g_strdup(alias); msg->flags = flags; @@ -400,11 +235,11 @@ add_message_to_history(PurpleConversation *conv, const char *who, const char *al msg->when = when; msg->conv = conv; - conv->message_history = g_list_prepend(conv->message_history, msg); + priv->message_history = g_list_prepend(priv->message_history, msg); } static void -free_conv_message(PurpleConvMessage *msg) +free_conv_message(PurpleConversationMessage *msg) { g_free(msg->who); g_free(msg->alias); @@ -423,316 +258,6 @@ message_history_free(GList *list) /************************************************************************** * Conversation API **************************************************************************/ -static void -purple_conversation_chat_cleanup_for_rejoin(PurpleConversation *conv) -{ - const char *disp; - PurpleAccount *account; - PurpleConnection *gc; - - account = purple_conversation_get_account(conv); - - purple_conversation_close_logs(conv); - open_log(conv); - - gc = purple_account_get_connection(account); - - if ((disp = purple_connection_get_display_name(gc)) != NULL) - purple_conv_chat_set_nick(PURPLE_CONV_CHAT(conv), disp); - else - { - purple_conv_chat_set_nick(PURPLE_CONV_CHAT(conv), - purple_account_get_username(account)); - } - - purple_conv_chat_clear_users(PURPLE_CONV_CHAT(conv)); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(conv), NULL, NULL); - PURPLE_CONV_CHAT(conv)->left = FALSE; - - purple_conversation_update(conv, PURPLE_CONV_UPDATE_CHATLEFT); -} - -PurpleConversation * -purple_conversation_new(PurpleConversationType type, PurpleAccount *account, - const char *name) -{ - PurpleConversation *conv; - PurpleConnection *gc; - PurpleConversationUiOps *ops; - struct _purple_hconv *hc; - - g_return_val_if_fail(type != PURPLE_CONV_TYPE_UNKNOWN, NULL); - g_return_val_if_fail(account != NULL, NULL); - g_return_val_if_fail(name != NULL, NULL); - - /* Check if this conversation already exists. */ - if ((conv = purple_find_conversation_with_account(type, name, account)) != NULL) - { - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && - !purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) { - purple_debug_warning("conversation", "Trying to create multiple " - "chats (%s) with the same name is deprecated and will be " - "removed in libpurple 3.0.0", name); - } - - /* - * This hack is necessary because some prpls (MSN) have unnamed chats - * that all use the same name. A PurpleConversation for one of those - * is only ever re-used if the user has left, so calls to - * purple_conversation_new need to fall-through to creating a new - * chat. - * TODO 3.0.0: Remove this workaround and mandate unique names. - */ - if (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT || - purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) - { - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) - purple_conversation_chat_cleanup_for_rejoin(conv); - - return conv; - } - } - - gc = purple_account_get_connection(account); - g_return_val_if_fail(gc != NULL, NULL); - - conv = g_new0(PurpleConversation, 1); - PURPLE_DBUS_REGISTER_POINTER(conv, PurpleConversation); - - conv->type = type; - conv->account = account; - conv->name = g_strdup(name); - conv->title = g_strdup(name); - conv->data = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, NULL); - /* copy features from the connection. */ - conv->features = purple_connection_get_flags(gc); - - if (type == PURPLE_CONV_TYPE_IM) - { - PurpleBuddyIcon *icon; - conv->u.im = g_new0(PurpleConvIm, 1); - conv->u.im->conv = conv; - PURPLE_DBUS_REGISTER_POINTER(conv->u.im, PurpleConvIm); - - ims = g_list_prepend(ims, conv); - if ((icon = purple_buddy_icons_find(account, name))) - { - purple_conv_im_set_icon(conv->u.im, icon); - /* purple_conv_im_set_icon refs the icon. */ - purple_buddy_icon_unref(icon); - } - - if (purple_prefs_get_bool("/purple/logging/log_ims")) - { - purple_conversation_set_logging(conv, TRUE); - open_log(conv); - } - } - else if (type == PURPLE_CONV_TYPE_CHAT) - { - const char *disp; - - conv->u.chat = g_new0(PurpleConvChat, 1); - conv->u.chat->conv = conv; - conv->u.chat->users = g_hash_table_new_full(_purple_conversation_user_hash, - _purple_conversation_user_equal, g_free, NULL); - PURPLE_DBUS_REGISTER_POINTER(conv->u.chat, PurpleConvChat); - - chats = g_list_prepend(chats, conv); - - if ((disp = purple_connection_get_display_name(purple_account_get_connection(account)))) - purple_conv_chat_set_nick(conv->u.chat, disp); - else - purple_conv_chat_set_nick(conv->u.chat, - purple_account_get_username(account)); - - if (purple_prefs_get_bool("/purple/logging/log_chats")) - { - purple_conversation_set_logging(conv, TRUE); - open_log(conv); - } - } - - conversations = g_list_prepend(conversations, conv); - - hc = g_new(struct _purple_hconv, 1); - hc->name = g_strdup(purple_normalize(account, conv->name)); - hc->account = account; - hc->type = type; - - g_hash_table_insert(conversation_cache, hc, conv); - - /* Auto-set the title. */ - purple_conversation_autoset_title(conv); - - /* Don't move this.. it needs to be one of the last things done otherwise - * it causes mysterious crashes on my system. - * -- Gary - */ - ops = conv->ui_ops = default_ops; - if (ops != NULL && ops->create_conversation != NULL) - ops->create_conversation(conv); - - purple_signal_emit(purple_conversations_get_handle(), - "conversation-created", conv); - - return conv; -} - -void -purple_conversation_destroy(PurpleConversation *conv) -{ - PurplePluginProtocolInfo *prpl_info = NULL; - PurpleConversationUiOps *ops; - PurpleConnection *gc; - const char *name; - struct _purple_hconv hc; - - g_return_if_fail(conv != NULL); - - purple_request_close_with_handle(conv); - - ops = purple_conversation_get_ui_ops(conv); - gc = purple_conversation_get_connection(conv); - name = purple_conversation_get_name(conv); - - if (gc != NULL) - { - /* Still connected */ - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) - { - if (purple_prefs_get_bool("/purple/conversations/im/send_typing")) - serv_send_typing(gc, name, PURPLE_NOT_TYPING); - - if (gc && prpl_info->convo_closed != NULL) - prpl_info->convo_closed(gc, name); - } - else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) - { - int chat_id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)); -#if 0 - /* - * This is unfortunately necessary, because calling - * serv_chat_leave() calls this purple_conversation_destroy(), - * which leads to two calls here.. We can't just return after - * this, because then it'll return on the next pass. So, since - * serv_got_chat_left(), which is eventually called from the - * prpl that serv_chat_leave() calls, removes this conversation - * from the gc's buddy_chats list, we're going to check to see - * if this exists in the list. If so, we want to return after - * calling this, because it'll be called again. If not, fall - * through, because it'll have already been removed, and we'd - * be on the 2nd pass. - * - * Long paragraph. <-- Short sentence. - * - * -- ChipX86 - */ - - if (gc && g_slist_find(gc->buddy_chats, conv) != NULL) { - serv_chat_leave(gc, chat_id); - - return; - } -#endif - /* - * Instead of all of that, lets just close the window when - * the user tells us to, and let the prpl deal with the - * internals on it's own time. Don't do this if the prpl already - * knows it left the chat. - */ - if (!purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) - serv_chat_leave(gc, chat_id); - - /* - * If they didn't call serv_got_chat_left by now, it's too late. - * So we better do it for them before we destroy the thing. - */ - if (!purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) - serv_got_chat_left(gc, chat_id); - } - } - - /* remove from conversations and im/chats lists prior to emit */ - conversations = g_list_remove(conversations, conv); - - if(conv->type==PURPLE_CONV_TYPE_IM) - ims = g_list_remove(ims, conv); - else if(conv->type==PURPLE_CONV_TYPE_CHAT) - chats = g_list_remove(chats, conv); - - hc.name = (gchar *)purple_normalize(conv->account, conv->name); - hc.account = conv->account; - hc.type = conv->type; - - g_hash_table_remove(conversation_cache, &hc); - - purple_signal_emit(purple_conversations_get_handle(), - "deleting-conversation", conv); - - g_free(conv->name); - g_free(conv->title); - - conv->name = NULL; - conv->title = NULL; - - if (conv->type == PURPLE_CONV_TYPE_IM) { - purple_conv_im_stop_typing_timeout(conv->u.im); - purple_conv_im_stop_send_typed_timeout(conv->u.im); - - purple_buddy_icon_unref(conv->u.im->icon); - conv->u.im->icon = NULL; - - PURPLE_DBUS_UNREGISTER_POINTER(conv->u.im); - g_free(conv->u.im); - conv->u.im = NULL; - } - else if (conv->type == PURPLE_CONV_TYPE_CHAT) { - g_hash_table_destroy(conv->u.chat->users); - conv->u.chat->users = NULL; - - g_list_foreach(conv->u.chat->in_room, (GFunc)purple_conv_chat_cb_destroy, NULL); - g_list_free(conv->u.chat->in_room); - - g_list_foreach(conv->u.chat->ignored, (GFunc)g_free, NULL); - g_list_free(conv->u.chat->ignored); - - conv->u.chat->in_room = NULL; - conv->u.chat->ignored = NULL; - - g_free(conv->u.chat->who); - conv->u.chat->who = NULL; - - g_free(conv->u.chat->topic); - conv->u.chat->topic = NULL; - - g_free(conv->u.chat->nick); - - PURPLE_DBUS_UNREGISTER_POINTER(conv->u.chat); - g_free(conv->u.chat); - conv->u.chat = NULL; - } - - g_hash_table_destroy(conv->data); - conv->data = NULL; - - if (ops != NULL && ops->destroy_conversation != NULL) - ops->destroy_conversation(conv); - conv->ui_data = NULL; - - purple_conversation_close_logs(conv); - - purple_conversation_clear_message_history(conv); - - PURPLE_DBUS_UNREGISTER_POINTER(conv); - g_free(conv); - conv = NULL; -} - - void purple_conversation_present(PurpleConversation *conv) { PurpleConversationUiOps *ops; @@ -744,78 +269,78 @@ purple_conversation_present(PurpleConversation *conv) { ops->present(conv); } - void purple_conversation_set_features(PurpleConversation *conv, PurpleConnectionFlags features) { - g_return_if_fail(conv != NULL); + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); - conv->features = features; + g_return_if_fail(priv != NULL); - purple_conversation_update(conv, PURPLE_CONV_UPDATE_FEATURES); + priv->features = features; + purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_FEATURES); } - PurpleConnectionFlags purple_conversation_get_features(PurpleConversation *conv) { - g_return_val_if_fail(conv != NULL, 0); - return conv->features; -} + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); + g_return_val_if_fail(priv != NULL, 0); -PurpleConversationType -purple_conversation_get_type(const PurpleConversation *conv) -{ - g_return_val_if_fail(conv != NULL, PURPLE_CONV_TYPE_UNKNOWN); - - return conv->type; + return priv->features; } void purple_conversation_set_ui_ops(PurpleConversation *conv, PurpleConversationUiOps *ops) { - g_return_if_fail(conv != NULL); + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); - if (conv->ui_ops == ops) - return; + g_return_if_fail(priv != NULL); - if (conv->ui_ops != NULL && conv->ui_ops->destroy_conversation != NULL) - conv->ui_ops->destroy_conversation(conv); + if (priv->ui_ops == ops) + return; - conv->ui_data = NULL; + if (priv->ui_ops != NULL && priv->ui_ops->destroy_conversation != NULL) + priv->ui_ops->destroy_conversation(conv); - conv->ui_ops = ops; + priv->ui_ops = ops; } PurpleConversationUiOps * purple_conversation_get_ui_ops(const PurpleConversation *conv) { - g_return_val_if_fail(conv != NULL, NULL); + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); + + g_return_val_if_fail(priv != NULL, NULL); - return conv->ui_ops; + return priv->ui_ops; } void purple_conversation_set_account(PurpleConversation *conv, PurpleAccount *account) { - g_return_if_fail(conv != NULL); + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); + + g_return_if_fail(priv != NULL); if (account == purple_conversation_get_account(conv)) return; - conv->account = account; + purple_conversations_update_cache(conv, NULL, account); + priv->account = account; - purple_conversation_update(conv, PURPLE_CONV_UPDATE_ACCOUNT); + purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_ACCOUNT); } PurpleAccount * purple_conversation_get_account(const PurpleConversation *conv) { - g_return_val_if_fail(conv != NULL, NULL); + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); + + g_return_val_if_fail(priv != NULL, NULL); - return conv->account; + return priv->account; } PurpleConnection * @@ -836,21 +361,25 @@ purple_conversation_get_connection(const PurpleConversation *conv) void purple_conversation_set_title(PurpleConversation *conv, const char *title) { - g_return_if_fail(conv != NULL); + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); + + g_return_if_fail(priv != NULL); g_return_if_fail(title != NULL); - g_free(conv->title); - conv->title = g_strdup(title); + g_free(priv->title); + priv->title = g_strdup(title); - purple_conversation_update(conv, PURPLE_CONV_UPDATE_TITLE); + purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_TITLE); } const char * purple_conversation_get_title(const PurpleConversation *conv) { - g_return_val_if_fail(conv != NULL, NULL); + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); + + g_return_val_if_fail(priv != NULL, NULL); - return conv->title; + return priv->title; } void @@ -866,15 +395,14 @@ purple_conversation_autoset_title(PurpleConversation *conv) account = purple_conversation_get_account(conv); name = purple_conversation_get_name(conv); - if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - if(account && ((b = purple_find_buddy(account, name)) != NULL)) + if (PURPLE_IS_IM_CONVERSATION(conv)) { + if (account && ((b = purple_blist_find_buddy(account, name)) != NULL)) text = purple_buddy_get_contact_alias(b); - } else if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { - if(account && ((chat = purple_blist_find_chat(account, name)) != NULL)) + } else if (PURPLE_IS_CHAT_CONVERSATION(conv)) { + if (account && ((chat = purple_blist_find_chat(account, name)) != NULL)) text = purple_chat_get_name(chat); } - if(text == NULL) text = name; @@ -882,37 +410,16 @@ purple_conversation_autoset_title(PurpleConversation *conv) } void -purple_conversation_foreach(void (*func)(PurpleConversation *conv)) -{ - PurpleConversation *conv; - GList *l; - - g_return_if_fail(func != NULL); - - for (l = purple_get_conversations(); l != NULL; l = l->next) { - conv = (PurpleConversation *)l->data; - - func(conv); - } -} - -void purple_conversation_set_name(PurpleConversation *conv, const char *name) { - struct _purple_hconv *hc; - g_return_if_fail(conv != NULL); + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); - hc = g_new(struct _purple_hconv, 1); - hc->type = conv->type; - hc->account = conv->account; - hc->name = (gchar *)purple_normalize(conv->account, conv->name); + g_return_if_fail(priv != NULL); - g_hash_table_remove(conversation_cache, hc); - g_free(conv->name); + purple_conversations_update_cache(conv, name, NULL); - conv->name = g_strdup(name); - hc->name = g_strdup(purple_normalize(conv->account, conv->name)); - g_hash_table_insert(conversation_cache, hc, conv); + g_free(priv->name); + priv->name = g_strdup(name); purple_conversation_autoset_title(conv); } @@ -920,133 +427,50 @@ purple_conversation_set_name(PurpleConversation *conv, const char *name) const char * purple_conversation_get_name(const PurpleConversation *conv) { - g_return_val_if_fail(conv != NULL, NULL); + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); + + g_return_val_if_fail(priv != NULL, NULL); - return conv->name; + return priv->name; } void purple_conversation_set_logging(PurpleConversation *conv, gboolean log) { - g_return_if_fail(conv != NULL); + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); - if (conv->logging != log) + g_return_if_fail(priv != NULL); + + if (priv->logging != log) { - conv->logging = log; - purple_conversation_update(conv, PURPLE_CONV_UPDATE_LOGGING); + priv->logging = log; + if (log && priv->logs == NULL) + open_log(conv); + + purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_LOGGING); } } gboolean purple_conversation_is_logging(const PurpleConversation *conv) { - g_return_val_if_fail(conv != NULL, FALSE); + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); - return conv->logging; -} + g_return_val_if_fail(priv != NULL, FALSE); -void -purple_conversation_close_logs(PurpleConversation *conv) -{ - g_return_if_fail(conv != NULL); - - g_list_foreach(conv->logs, (GFunc)purple_log_free, NULL); - g_list_free(conv->logs); - conv->logs = NULL; -} - -PurpleConvIm * -purple_conversation_get_im_data(const PurpleConversation *conv) -{ - g_return_val_if_fail(conv != NULL, NULL); - - if (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_IM) - return NULL; - - return conv->u.im; -} - -PurpleConvChat * -purple_conversation_get_chat_data(const PurpleConversation *conv) -{ - g_return_val_if_fail(conv != NULL, NULL); - - if (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT) - return NULL; - - return conv->u.chat; + return priv->logging; } void -purple_conversation_set_data(PurpleConversation *conv, const char *key, - gpointer data) -{ - g_return_if_fail(conv != NULL); - g_return_if_fail(key != NULL); - - g_hash_table_replace(conv->data, g_strdup(key), data); -} - -gpointer -purple_conversation_get_data(PurpleConversation *conv, const char *key) -{ - g_return_val_if_fail(conv != NULL, NULL); - g_return_val_if_fail(key != NULL, NULL); - - return g_hash_table_lookup(conv->data, key); -} - -GList * -purple_get_conversations(void) -{ - return conversations; -} - -GList * -purple_get_ims(void) -{ - return ims; -} - -GList * -purple_get_chats(void) -{ - return chats; -} - - -PurpleConversation * -purple_find_conversation_with_account(PurpleConversationType type, - const char *name, - const PurpleAccount *account) +purple_conversation_close_logs(PurpleConversation *conv) { - PurpleConversation *c = NULL; - struct _purple_hconv hc; + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); - g_return_val_if_fail(name != NULL, NULL); + g_return_if_fail(priv != NULL); - hc.name = (gchar *)purple_normalize(account, name); - hc.account = account; - hc.type = type; - - switch (type) { - case PURPLE_CONV_TYPE_IM: - case PURPLE_CONV_TYPE_CHAT: - c = g_hash_table_lookup(conversation_cache, &hc); - break; - case PURPLE_CONV_TYPE_ANY: - hc.type = PURPLE_CONV_TYPE_IM; - c = g_hash_table_lookup(conversation_cache, &hc); - if (!c) { - hc.type = PURPLE_CONV_TYPE_CHAT; - c = g_hash_table_lookup(conversation_cache, &hc); - } - break; - default: - g_return_val_if_reached(NULL); - } - - return c; + g_list_foreach(priv->logs, (GFunc)purple_log_free, NULL); + g_list_free(priv->logs); + priv->logs = NULL; } void @@ -1062,26 +486,25 @@ purple_conversation_write(PurpleConversation *conv, const char *who, char *displayed = NULL; PurpleBuddy *b; int plugin_return; - PurpleConversationType type; + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); /* int logging_font_options = 0; */ - g_return_if_fail(conv != NULL); + g_return_if_fail(priv != NULL); g_return_if_fail(message != NULL); ops = purple_conversation_get_ui_ops(conv); account = purple_conversation_get_account(conv); - type = purple_conversation_get_type(conv); if (account != NULL) gc = purple_account_get_connection(account); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && - (gc != NULL && !g_slist_find(gc->buddy_chats, conv))) + if (PURPLE_IS_CHAT_CONVERSATION(conv) && + (gc != NULL && !g_slist_find(purple_connection_get_active_chats(gc), conv))) return; - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM && - !g_list_find(purple_get_conversations(), conv)) + if (PURPLE_IS_IM_CONVERSATION(conv) && + !g_list_find(purple_conversations_get_all(), conv)) return; displayed = g_strdup(message); @@ -1093,7 +516,7 @@ purple_conversation_write(PurpleConversation *conv, const char *who, plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1( purple_conversations_get_handle(), - (type == PURPLE_CONV_TYPE_IM ? "writing-im-msg" : "writing-chat-msg"), + (PURPLE_IS_IM_CONVERSATION(conv) ? "writing-im-msg" : "writing-chat-msg"), account, who, &displayed, conv, flags)); if (displayed == NULL) @@ -1107,15 +530,15 @@ purple_conversation_write(PurpleConversation *conv, const char *who, if (account != NULL) { prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account))); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM || + if (PURPLE_IS_IM_CONVERSATION(conv) || !(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { if (flags & PURPLE_MESSAGE_SEND) { - b = purple_find_buddy(account, + b = purple_blist_find_buddy(account, purple_account_get_username(account)); - if (purple_account_get_alias(account) != NULL) - alias = purple_account_get_alias(account); + if (purple_account_get_private_alias(account) != NULL) + alias = purple_account_get_private_alias(account); else if (b != NULL && !purple_strequal(purple_buddy_get_name(b), purple_buddy_get_contact_alias(b))) alias = purple_buddy_get_contact_alias(b); else if (purple_connection_get_display_name(gc) != NULL) @@ -1125,7 +548,7 @@ purple_conversation_write(PurpleConversation *conv, const char *who, } else { - b = purple_find_buddy(account, who); + b = purple_blist_find_buddy(account, who); if (b != NULL) alias = purple_buddy_get_contact_alias(b); @@ -1136,10 +559,7 @@ purple_conversation_write(PurpleConversation *conv, const char *who, if (!(flags & PURPLE_MESSAGE_NO_LOG) && purple_conversation_is_logging(conv)) { GList *log; - if (conv->logs == NULL) - open_log(conv); - - log = conv->logs; + log = priv->logs; while (log != NULL) { purple_log_write((PurpleLog *)log->data, flags, alias, mtime, displayed); log = log->next; @@ -1152,12 +572,42 @@ purple_conversation_write(PurpleConversation *conv, const char *who, add_message_to_history(conv, who, alias, message, flags, mtime); purple_signal_emit(purple_conversations_get_handle(), - (type == PURPLE_CONV_TYPE_IM ? "wrote-im-msg" : "wrote-chat-msg"), + (PURPLE_IS_IM_CONVERSATION(conv) ? "wrote-im-msg" : "wrote-chat-msg"), account, who, displayed, conv, flags); g_free(displayed); } +void +purple_conversation_write_message(PurpleConversation *conv, const char *who, + const char *message, PurpleMessageFlags flags, time_t mtime) +{ + PurpleConversationClass *klass = NULL; + + g_return_if_fail(PURPLE_IS_CONVERSATION(conv)); + + klass = PURPLE_CONVERSATION_GET_CLASS(conv); + + if (klass && klass->write_message) + klass->write_message(conv, who, message, flags, mtime); +} + +void +purple_conversation_send(PurpleConversation *conv, const char *message) +{ + purple_conversation_send_with_flags(conv, message, 0); +} + +void +purple_conversation_send_with_flags(PurpleConversation *conv, const char *message, + PurpleMessageFlags flags) +{ + g_return_if_fail(conv != NULL); + g_return_if_fail(message != NULL); + + common_send(conv, message, flags); +} + gboolean purple_conversation_has_focus(PurpleConversation *conv) { @@ -1181,7 +631,7 @@ purple_conversation_has_focus(PurpleConversation *conv) * when chats are added/removed from the blist. */ void -purple_conversation_update(PurpleConversation *conv, PurpleConvUpdateType type) +purple_conversation_update(PurpleConversation *conv, PurpleConversationUpdateType type) { g_return_if_fail(conv != NULL); @@ -1189,194 +639,7 @@ purple_conversation_update(PurpleConversation *conv, PurpleConvUpdateType type) "conversation-updated", conv, type); } -/************************************************************************** - * IM Conversation API - **************************************************************************/ -PurpleConversation * -purple_conv_im_get_conversation(const PurpleConvIm *im) -{ - g_return_val_if_fail(im != NULL, NULL); - - return im->conv; -} - -void -purple_conv_im_set_icon(PurpleConvIm *im, PurpleBuddyIcon *icon) -{ - g_return_if_fail(im != NULL); - - if (im->icon != icon) - { - purple_buddy_icon_unref(im->icon); - - im->icon = (icon == NULL ? NULL : purple_buddy_icon_ref(icon)); - } - - purple_conversation_update(purple_conv_im_get_conversation(im), - PURPLE_CONV_UPDATE_ICON); -} - -PurpleBuddyIcon * -purple_conv_im_get_icon(const PurpleConvIm *im) -{ - g_return_val_if_fail(im != NULL, NULL); - - return im->icon; -} - -void -purple_conv_im_set_typing_state(PurpleConvIm *im, PurpleTypingState state) -{ - g_return_if_fail(im != NULL); - - if (im->typing_state != state) - { - im->typing_state = state; - - switch (state) - { - case PURPLE_TYPING: - purple_signal_emit(purple_conversations_get_handle(), - "buddy-typing", im->conv->account, im->conv->name); - break; - case PURPLE_TYPED: - purple_signal_emit(purple_conversations_get_handle(), - "buddy-typed", im->conv->account, im->conv->name); - break; - case PURPLE_NOT_TYPING: - purple_signal_emit(purple_conversations_get_handle(), - "buddy-typing-stopped", im->conv->account, im->conv->name); - break; - } - - purple_conv_im_update_typing(im); - } -} - -PurpleTypingState -purple_conv_im_get_typing_state(const PurpleConvIm *im) -{ - g_return_val_if_fail(im != NULL, 0); - - return im->typing_state; -} - -void -purple_conv_im_start_typing_timeout(PurpleConvIm *im, int timeout) -{ - PurpleConversation *conv; - - g_return_if_fail(im != NULL); - - if (im->typing_timeout > 0) - purple_conv_im_stop_typing_timeout(im); - - conv = purple_conv_im_get_conversation(im); - - im->typing_timeout = purple_timeout_add_seconds(timeout, reset_typing_cb, conv); -} - -void -purple_conv_im_stop_typing_timeout(PurpleConvIm *im) -{ - g_return_if_fail(im != NULL); - - if (im->typing_timeout == 0) - return; - - purple_timeout_remove(im->typing_timeout); - im->typing_timeout = 0; -} - -guint -purple_conv_im_get_typing_timeout(const PurpleConvIm *im) -{ - g_return_val_if_fail(im != NULL, 0); - - return im->typing_timeout; -} - -void -purple_conv_im_set_type_again(PurpleConvIm *im, unsigned int val) -{ - g_return_if_fail(im != NULL); - - if (val == 0) - im->type_again = 0; - else - im->type_again = time(NULL) + val; -} - -time_t -purple_conv_im_get_type_again(const PurpleConvIm *im) -{ - g_return_val_if_fail(im != NULL, 0); - - return im->type_again; -} - -void -purple_conv_im_start_send_typed_timeout(PurpleConvIm *im) -{ - g_return_if_fail(im != NULL); - - im->send_typed_timeout = purple_timeout_add_seconds(SEND_TYPED_TIMEOUT_SECONDS, - send_typed_cb, - purple_conv_im_get_conversation(im)); -} - -void -purple_conv_im_stop_send_typed_timeout(PurpleConvIm *im) -{ - g_return_if_fail(im != NULL); - - if (im->send_typed_timeout == 0) - return; - - purple_timeout_remove(im->send_typed_timeout); - im->send_typed_timeout = 0; -} - -guint -purple_conv_im_get_send_typed_timeout(const PurpleConvIm *im) -{ - g_return_val_if_fail(im != NULL, 0); - - return im->send_typed_timeout; -} - -void -purple_conv_im_update_typing(PurpleConvIm *im) -{ - g_return_if_fail(im != NULL); - - purple_conversation_update(purple_conv_im_get_conversation(im), - PURPLE_CONV_UPDATE_TYPING); -} - -void -purple_conv_im_write(PurpleConvIm *im, const char *who, const char *message, - PurpleMessageFlags flags, time_t mtime) -{ - PurpleConversation *c; - - g_return_if_fail(im != NULL); - g_return_if_fail(message != NULL); - - c = purple_conv_im_get_conversation(im); - - if ((flags & PURPLE_MESSAGE_RECV) == PURPLE_MESSAGE_RECV) { - purple_conv_im_set_typing_state(im, PURPLE_NOT_TYPING); - } - - /* Pass this on to either the ops structure or the default write func. */ - if (c->ui_ops != NULL && c->ui_ops->write_im != NULL) - c->ui_ops->write_im(c, who, message, flags, mtime); - else - purple_conversation_write(c, who, message, flags, mtime); -} - -gboolean purple_conv_present_error(const char *who, PurpleAccount *account, const char *what) +gboolean purple_conversation_present_error(const char *who, PurpleAccount *account, const char *what) { PurpleConversation *conv; @@ -1384,7 +647,7 @@ gboolean purple_conv_present_error(const char *who, PurpleAccount *account, cons g_return_val_if_fail(account !=NULL, FALSE); g_return_val_if_fail(what != NULL, FALSE); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, who, account); + conv = purple_conversations_find_with_account(who, account); if (conv != NULL) purple_conversation_write(conv, NULL, what, PURPLE_MESSAGE_ERROR, time(NULL)); else @@ -1393,14 +656,8 @@ gboolean purple_conv_present_error(const char *who, PurpleAccount *account, cons return TRUE; } -void -purple_conv_im_send(PurpleConvIm *im, const char *message) -{ - purple_conv_im_send_with_flags(im, message, 0); -} - static void -purple_conv_send_confirm_cb(gpointer *data) +purple_conversation_send_confirm_cb(gpointer *data) { PurpleConversation *conv = data[0]; char *message = data[1]; @@ -1410,17 +667,18 @@ purple_conv_send_confirm_cb(gpointer *data) } void -purple_conv_send_confirm(PurpleConversation *conv, const char *message) +purple_conversation_send_confirm(PurpleConversation *conv, const char *message) { char *text; gpointer *data; + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); - g_return_if_fail(conv != NULL); + g_return_if_fail(priv != NULL); g_return_if_fail(message != NULL); - if (conv->ui_ops != NULL && conv->ui_ops->send_confirm != NULL) + if (priv->ui_ops != NULL && priv->ui_ops->send_confirm != NULL) { - conv->ui_ops->send_confirm(conv, message); + priv->ui_ops->send_confirm(conv, message); return; } @@ -1432,32 +690,27 @@ purple_conv_send_confirm(PurpleConversation *conv, const char *message) purple_request_action(conv, NULL, _("Send Message"), text, 0, purple_conversation_get_account(conv), NULL, conv, data, 2, - _("_Send Message"), G_CALLBACK(purple_conv_send_confirm_cb), + _("_Send Message"), G_CALLBACK(purple_conversation_send_confirm_cb), _("Cancel"), NULL); } -void -purple_conv_im_send_with_flags(PurpleConvIm *im, const char *message, PurpleMessageFlags flags) -{ - g_return_if_fail(im != NULL); - g_return_if_fail(message != NULL); - - common_send(purple_conv_im_get_conversation(im), message, flags); -} - gboolean -purple_conv_custom_smiley_add(PurpleConversation *conv, const char *smile, +purple_conversation_custom_smiley_add(PurpleConversation *conv, const char *smile, const char *cksum_type, const char *chksum, gboolean remote) { - if (conv == NULL || smile == NULL || !*smile) { + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); + + g_return_val_if_fail(priv != NULL, FALSE); + + if (smile == NULL || !*smile) { return FALSE; } /* TODO: check if the icon is in the cache and return false if so */ /* TODO: add an icon cache (that doesn't suck) */ - if (conv->ui_ops != NULL && conv->ui_ops->custom_smiley_add !=NULL) { - return conv->ui_ops->custom_smiley_add(conv, smile, remote); + if (priv->ui_ops != NULL && priv->ui_ops->custom_smiley_add !=NULL) { + return priv->ui_ops->custom_smiley_add(conv, smile, remote); } else { purple_debug_info("conversation", "Could not find add custom smiley function"); return FALSE; @@ -1466,1390 +719,409 @@ purple_conv_custom_smiley_add(PurpleConversation *conv, const char *smile, } void -purple_conv_custom_smiley_write(PurpleConversation *conv, const char *smile, +purple_conversation_custom_smiley_write(PurpleConversation *conv, const char *smile, const guchar *data, gsize size) { - g_return_if_fail(conv != NULL); + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); + + g_return_if_fail(priv != NULL); g_return_if_fail(smile != NULL && *smile); - if (conv->ui_ops != NULL && conv->ui_ops->custom_smiley_write != NULL) - conv->ui_ops->custom_smiley_write(conv, smile, data, size); + if (priv->ui_ops != NULL && priv->ui_ops->custom_smiley_write != NULL) + priv->ui_ops->custom_smiley_write(conv, smile, data, size); else purple_debug_info("conversation", "Could not find the smiley write function"); } void -purple_conv_custom_smiley_close(PurpleConversation *conv, const char *smile) +purple_conversation_custom_smiley_close(PurpleConversation *conv, const char *smile) { - g_return_if_fail(conv != NULL); + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); + + g_return_if_fail(priv != NULL); g_return_if_fail(smile != NULL && *smile); - if (conv->ui_ops != NULL && conv->ui_ops->custom_smiley_close != NULL) - conv->ui_ops->custom_smiley_close(conv, smile); + if (priv->ui_ops != NULL && priv->ui_ops->custom_smiley_close != NULL) + priv->ui_ops->custom_smiley_close(conv, smile); else purple_debug_info("conversation", "Could not find custom smiley close function"); } - -/************************************************************************** - * Chat Conversation API - **************************************************************************/ - -PurpleConversation * -purple_conv_chat_get_conversation(const PurpleConvChat *chat) -{ - g_return_val_if_fail(chat != NULL, NULL); - - return chat->conv; -} - GList * -purple_conv_chat_get_users(const PurpleConvChat *chat) -{ - g_return_val_if_fail(chat != NULL, NULL); - - return chat->in_room; -} - -void -purple_conv_chat_ignore(PurpleConvChat *chat, const char *name) +purple_conversation_get_extended_menu(PurpleConversation *conv) { - g_return_if_fail(chat != NULL); - g_return_if_fail(name != NULL); + GList *menu = NULL; - /* Make sure the user isn't already ignored. */ - if (purple_conv_chat_is_user_ignored(chat, name)) - return; + g_return_val_if_fail(conv != NULL, NULL); - purple_conv_chat_set_ignored(chat, - g_list_append(chat->ignored, g_strdup(name))); + purple_signal_emit(purple_conversations_get_handle(), + "conversation-extended-menu", conv, &menu); + return menu; } -void -purple_conv_chat_unignore(PurpleConvChat *chat, const char *name) +void purple_conversation_clear_message_history(PurpleConversation *conv) { - GList *item; + GList *list; + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); - g_return_if_fail(chat != NULL); - g_return_if_fail(name != NULL); - - /* Make sure the user is actually ignored. */ - if (!purple_conv_chat_is_user_ignored(chat, name)) - return; + g_return_if_fail(priv != NULL); - item = g_list_find(purple_conv_chat_get_ignored(chat), - purple_conv_chat_get_ignored_user(chat, name)); - - purple_conv_chat_set_ignored(chat, - g_list_remove_link(chat->ignored, item)); + list = priv->message_history; + message_history_free(list); + priv->message_history = NULL; - g_free(item->data); - g_list_free_1(item); + purple_signal_emit(purple_conversations_get_handle(), + "cleared-message-history", conv); } -GList * -purple_conv_chat_set_ignored(PurpleConvChat *chat, GList *ignored) +GList *purple_conversation_get_message_history(PurpleConversation *conv) { - g_return_val_if_fail(chat != NULL, NULL); - - chat->ignored = ignored; + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); - return ignored; -} - -GList * -purple_conv_chat_get_ignored(const PurpleConvChat *chat) -{ - g_return_val_if_fail(chat != NULL, NULL); + g_return_val_if_fail(priv != NULL, NULL); - return chat->ignored; + return priv->message_history; } -const char * -purple_conv_chat_get_ignored_user(const PurpleConvChat *chat, const char *user) +const char *purple_conversation_message_get_sender(const PurpleConversationMessage *msg) { - GList *ignored; - - g_return_val_if_fail(chat != NULL, NULL); - g_return_val_if_fail(user != NULL, NULL); - - for (ignored = purple_conv_chat_get_ignored(chat); - ignored != NULL; - ignored = ignored->next) { - - const char *ign = (const char *)ignored->data; - - if (!purple_utf8_strcasecmp(user, ign) || - ((*ign == '+' || *ign == '%') && !purple_utf8_strcasecmp(user, ign + 1))) - return ign; - - if (*ign == '@') { - ign++; - - if ((*ign == '+' && !purple_utf8_strcasecmp(user, ign + 1)) || - (*ign != '+' && !purple_utf8_strcasecmp(user, ign))) - return ign; - } - } - - return NULL; + g_return_val_if_fail(msg, NULL); + return msg->who; } -gboolean -purple_conv_chat_is_user_ignored(const PurpleConvChat *chat, const char *user) +const char *purple_conversation_message_get_message(const PurpleConversationMessage *msg) { - g_return_val_if_fail(chat != NULL, FALSE); - g_return_val_if_fail(user != NULL, FALSE); - - return (purple_conv_chat_get_ignored_user(chat, user) != NULL); + g_return_val_if_fail(msg, NULL); + return msg->what; } -void -purple_conv_chat_set_topic(PurpleConvChat *chat, const char *who, const char *topic) +PurpleMessageFlags purple_conversation_message_get_flags(const PurpleConversationMessage *msg) { - g_return_if_fail(chat != NULL); - - g_free(chat->who); - g_free(chat->topic); - - chat->who = g_strdup(who); - chat->topic = g_strdup(topic); - - purple_conversation_update(purple_conv_chat_get_conversation(chat), - PURPLE_CONV_UPDATE_TOPIC); - - purple_signal_emit(purple_conversations_get_handle(), "chat-topic-changed", - chat->conv, chat->who, chat->topic); + g_return_val_if_fail(msg, 0); + return msg->flags; } -const char * -purple_conv_chat_get_topic(const PurpleConvChat *chat) +time_t purple_conversation_message_get_timestamp(const PurpleConversationMessage *msg) { - g_return_val_if_fail(chat != NULL, NULL); - - return chat->topic; + g_return_val_if_fail(msg, 0); + return msg->when; } -void -purple_conv_chat_set_id(PurpleConvChat *chat, int id) +const char *purple_conversation_message_get_alias(const PurpleConversationMessage *msg) { - g_return_if_fail(chat != NULL); - - chat->id = id; + g_return_val_if_fail(msg, NULL); + return msg->alias; } -int -purple_conv_chat_get_id(const PurpleConvChat *chat) +PurpleConversation *purple_conversation_message_get_conversation(const PurpleConversationMessage *msg) { - g_return_val_if_fail(chat != NULL, -1); - - return chat->id; + g_return_val_if_fail(msg, NULL); + return msg->conv; } -void -purple_conv_chat_write(PurpleConvChat *chat, const char *who, const char *message, - PurpleMessageFlags flags, time_t mtime) +static PurpleConversationMessage * +purple_conversation_message_copy(PurpleConversationMessage *msg) { - PurpleAccount *account; - PurpleConversation *conv; - PurpleConnection *gc; - - g_return_if_fail(chat != NULL); - g_return_if_fail(who != NULL); - g_return_if_fail(message != NULL); - - conv = purple_conv_chat_get_conversation(chat); - gc = purple_conversation_get_connection(conv); - account = purple_connection_get_account(gc); - - /* Don't display this if the person who wrote it is ignored. */ - if (purple_conv_chat_is_user_ignored(chat, who)) - return; - - if (!(flags & PURPLE_MESSAGE_WHISPER)) { - const char *str; - - str = purple_normalize(account, who); - - if (purple_strequal(str, chat->nick)) { - flags |= PURPLE_MESSAGE_SEND; - } else { - flags |= PURPLE_MESSAGE_RECV; - - if (purple_utf8_has_word(message, chat->nick)) - flags |= PURPLE_MESSAGE_NICK; - } - } + PurpleConversationMessage *newmsg; - /* Pass this on to either the ops structure or the default write func. */ - if (conv->ui_ops != NULL && conv->ui_ops->write_chat != NULL) - conv->ui_ops->write_chat(conv, who, message, flags, mtime); - else - purple_conversation_write(conv, who, message, flags, mtime); -} - -void -purple_conv_chat_send(PurpleConvChat *chat, const char *message) -{ - purple_conv_chat_send_with_flags(chat, message, 0); -} + g_return_val_if_fail(msg != NULL, NULL); -void -purple_conv_chat_send_with_flags(PurpleConvChat *chat, const char *message, PurpleMessageFlags flags) -{ - g_return_if_fail(chat != NULL); - g_return_if_fail(message != NULL); + newmsg = g_new(PurpleConversationMessage, 1); + *newmsg = *msg; + newmsg->who = g_strdup(msg->who); + newmsg->what = g_strdup(msg->what); + newmsg->alias = g_strdup(msg->alias); - common_send(purple_conv_chat_get_conversation(chat), message, flags); + return newmsg; } -void -purple_conv_chat_add_user(PurpleConvChat *chat, const char *user, - const char *extra_msg, PurpleConvChatBuddyFlags flags, - gboolean new_arrival) +static void +purple_conversation_message_free(PurpleConversationMessage *msg) { - GList *users = g_list_append(NULL, (char *)user); - GList *extra_msgs = g_list_append(NULL, (char *)extra_msg); - GList *flags2 = g_list_append(NULL, GINT_TO_POINTER(flags)); + g_return_if_fail(msg != NULL); - purple_conv_chat_add_users(chat, users, extra_msgs, flags2, new_arrival); + g_free(msg->who); + g_free(msg->what); + g_free(msg->alias); - g_list_free(users); - g_list_free(extra_msgs); - g_list_free(flags2); + g_free(msg); } -static int -purple_conv_chat_cb_compare(PurpleConvChatBuddy *a, PurpleConvChatBuddy *b) +GType +purple_conversation_message_get_type(void) { - PurpleConvChatBuddyFlags f1 = 0, f2 = 0; - char *user1 = NULL, *user2 = NULL; - gint ret = 0; - - if (a) { - f1 = a->flags; - if (a->alias_key) - user1 = a->alias_key; - else if (a->name) - user1 = a->name; - } + static GType type = 0; - if (b) { - f2 = b->flags; - if (b->alias_key) - user2 = b->alias_key; - else if (b->name) - user2 = b->name; - } - - if (user1 == NULL || user2 == NULL) { - if (!(user1 == NULL && user2 == NULL)) - ret = (user1 == NULL) ? -1: 1; - } else if (f1 != f2) { - /* sort more important users first */ - ret = (f1 > f2) ? -1 : 1; - } else if (a->buddy != b->buddy) { - ret = a->buddy ? -1 : 1; - } else { - ret = purple_utf8_strcasecmp(user1, user2); + if (type == 0) { + type = g_boxed_type_register_static("PurpleConversationMessage", + (GBoxedCopyFunc)purple_conversation_message_copy, + (GBoxedFreeFunc)purple_conversation_message_free); } - return ret; + return type; } -void -purple_conv_chat_add_users(PurpleConvChat *chat, GList *users, GList *extra_msgs, - GList *flags, gboolean new_arrivals) +void purple_conversation_set_ui_data(PurpleConversation *conv, gpointer ui_data) { - PurpleConversation *conv; - PurpleConversationUiOps *ops; - PurpleConvChatBuddy *cbuddy; - PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info; - GList *ul, *fl; - GList *cbuddies = NULL; - - g_return_if_fail(chat != NULL); - g_return_if_fail(users != NULL); - - conv = purple_conv_chat_get_conversation(chat); - ops = purple_conversation_get_ui_ops(conv); - - gc = purple_conversation_get_connection(conv); - g_return_if_fail(gc != NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - g_return_if_fail(prpl_info != NULL); - - ul = users; - fl = flags; - while ((ul != NULL) && (fl != NULL)) { - const char *user = (const char *)ul->data; - const char *alias = user; - gboolean quiet; - PurpleConvChatBuddyFlags flag = GPOINTER_TO_INT(fl->data); - const char *extra_msg = (extra_msgs ? extra_msgs->data : NULL); - - if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { - if (purple_strequal(chat->nick, purple_normalize(conv->account, user))) { - const char *alias2 = purple_account_get_alias(conv->account); - if (alias2 != NULL) - alias = alias2; - else - { - const char *display_name = purple_connection_get_display_name(gc); - if (display_name != NULL) - alias = display_name; - } - } else { - PurpleBuddy *buddy; - if ((buddy = purple_find_buddy(purple_connection_get_account(gc), user)) != NULL) - alias = purple_buddy_get_contact_alias(buddy); - } - } - - quiet = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_conversations_get_handle(), - "chat-buddy-joining", conv, user, flag)) || - purple_conv_chat_is_user_ignored(chat, user); - - cbuddy = purple_conv_chat_cb_new(user, alias, flag); - cbuddy->buddy = purple_find_buddy(conv->account, user) != NULL; - - chat->in_room = g_list_prepend(chat->in_room, cbuddy); - g_hash_table_replace(chat->users, g_strdup(cbuddy->name), cbuddy); - - cbuddies = g_list_prepend(cbuddies, cbuddy); - - if (!quiet && new_arrivals) { - char *alias_esc = g_markup_escape_text(alias, -1); - char *tmp; - - if (extra_msg == NULL) - tmp = g_strdup_printf(_("%s entered the room."), alias_esc); - else { - char *extra_msg_esc = g_markup_escape_text(extra_msg, -1); - tmp = g_strdup_printf(_("%s [<I>%s</I>] entered the room."), - alias_esc, extra_msg_esc); - g_free(extra_msg_esc); - } - g_free(alias_esc); - - purple_conversation_write(conv, NULL, tmp, - PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, - time(NULL)); - g_free(tmp); - } - - purple_signal_emit(purple_conversations_get_handle(), - "chat-buddy-joined", conv, user, flag, new_arrivals); - ul = ul->next; - fl = fl->next; - if (extra_msgs != NULL) - extra_msgs = extra_msgs->next; - } - - cbuddies = g_list_sort(cbuddies, (GCompareFunc)purple_conv_chat_cb_compare); - - if (ops != NULL && ops->chat_add_users != NULL) - ops->chat_add_users(conv, cbuddies, new_arrivals); + g_return_if_fail(conv != NULL); - g_list_free(cbuddies); + conv->ui_data = ui_data; } -void -purple_conv_chat_rename_user(PurpleConvChat *chat, const char *old_user, - const char *new_user) +gpointer purple_conversation_get_ui_data(const PurpleConversation *conv) { - PurpleConversation *conv; - PurpleConversationUiOps *ops; - PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info; - PurpleConvChatBuddy *cb; - PurpleConvChatBuddyFlags flags; - const char *new_alias = new_user; - char tmp[BUF_LONG]; - gboolean is_me = FALSE; - - g_return_if_fail(chat != NULL); - g_return_if_fail(old_user != NULL); - g_return_if_fail(new_user != NULL); - - conv = purple_conv_chat_get_conversation(chat); - ops = purple_conversation_get_ui_ops(conv); - - gc = purple_conversation_get_connection(conv); - g_return_if_fail(gc != NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - g_return_if_fail(prpl_info != NULL); - - if (purple_strequal(chat->nick, purple_normalize(conv->account, old_user))) { - const char *alias; - - /* Note this for later. */ - is_me = TRUE; - - if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { - alias = purple_account_get_alias(conv->account); - if (alias != NULL) - new_alias = alias; - else - { - const char *display_name = purple_connection_get_display_name(gc); - if (display_name != NULL) - new_alias = display_name; - } - } - } else if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { - PurpleBuddy *buddy; - if ((buddy = purple_find_buddy(purple_connection_get_account(gc), new_user)) != NULL) - new_alias = purple_buddy_get_contact_alias(buddy); - } - - flags = purple_conv_chat_user_get_flags(chat, old_user); - cb = purple_conv_chat_cb_new(new_user, new_alias, flags); - cb->buddy = purple_find_buddy(conv->account, new_user) != NULL; - - chat->in_room = g_list_prepend(chat->in_room, cb); - g_hash_table_replace(chat->users, g_strdup(cb->name), cb); - - if (ops != NULL && ops->chat_rename_user != NULL) - ops->chat_rename_user(conv, old_user, new_user, new_alias); - - cb = purple_conv_chat_cb_find(chat, old_user); - - if (cb) { - chat->in_room = g_list_remove(chat->in_room, cb); - g_hash_table_remove(chat->users, cb->name); - purple_conv_chat_cb_destroy(cb); - } - - if (purple_conv_chat_is_user_ignored(chat, old_user)) { - purple_conv_chat_unignore(chat, old_user); - purple_conv_chat_ignore(chat, new_user); - } - else if (purple_conv_chat_is_user_ignored(chat, new_user)) - purple_conv_chat_unignore(chat, new_user); - - if (is_me) - purple_conv_chat_set_nick(chat, new_user); - - if (purple_prefs_get_bool("/purple/conversations/chat/show_nick_change") && - !purple_conv_chat_is_user_ignored(chat, new_user)) { - - if (is_me) { - char *escaped = g_markup_escape_text(new_user, -1); - g_snprintf(tmp, sizeof(tmp), - _("You are now known as %s"), escaped); - g_free(escaped); - } else { - const char *old_alias = old_user; - const char *new_alias = new_user; - char *escaped; - char *escaped2; - - if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { - PurpleBuddy *buddy; - - if ((buddy = purple_find_buddy(purple_connection_get_account(gc), old_user)) != NULL) - old_alias = purple_buddy_get_contact_alias(buddy); - if ((buddy = purple_find_buddy(purple_connection_get_account(gc), new_user)) != NULL) - new_alias = purple_buddy_get_contact_alias(buddy); - } - - escaped = g_markup_escape_text(old_alias, -1); - escaped2 = g_markup_escape_text(new_alias, -1); - g_snprintf(tmp, sizeof(tmp), - _("%s is now known as %s"), escaped, escaped2); - g_free(escaped); - g_free(escaped2); - } + g_return_val_if_fail(conv != NULL, NULL); - purple_conversation_write(conv, NULL, tmp, - PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, - time(NULL)); - } + return conv->ui_data; } -void -purple_conv_chat_remove_user(PurpleConvChat *chat, const char *user, const char *reason) +gboolean +purple_conversation_do_command(PurpleConversation *conv, const gchar *cmdline, + const gchar *markup, gchar **error) { - GList *users = g_list_append(NULL, (char *)user); - - purple_conv_chat_remove_users(chat, users, reason); - - g_list_free(users); + char *mark = (markup && *markup) ? NULL : g_markup_escape_text(cmdline, -1), *err = NULL; + PurpleCmdStatus status = purple_cmd_do_command(conv, cmdline, mark ? mark : markup, error ? error : &err); + g_free(mark); + g_free(err); + return (status == PURPLE_CMD_STATUS_OK); } -void -purple_conv_chat_remove_users(PurpleConvChat *chat, GList *users, const char *reason) -{ - PurpleConversation *conv; - PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info; - PurpleConversationUiOps *ops; - PurpleConvChatBuddy *cb; - GList *l; - gboolean quiet; - - g_return_if_fail(chat != NULL); - g_return_if_fail(users != NULL); - - conv = purple_conv_chat_get_conversation(chat); - - gc = purple_conversation_get_connection(conv); - g_return_if_fail(gc != NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - g_return_if_fail(prpl_info != NULL); - - ops = purple_conversation_get_ui_ops(conv); - - for (l = users; l != NULL; l = l->next) { - const char *user = (const char *)l->data; - quiet = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_conversations_get_handle(), - "chat-buddy-leaving", conv, user, reason)) | - purple_conv_chat_is_user_ignored(chat, user); - - cb = purple_conv_chat_cb_find(chat, user); - - if (cb) { - chat->in_room = g_list_remove(chat->in_room, cb); - g_hash_table_remove(chat->users, cb->name); - purple_conv_chat_cb_destroy(cb); - } - - /* NOTE: Don't remove them from ignored in case they re-enter. */ - - if (!quiet) { - const char *alias = user; - char *alias_esc; - char *tmp; - - if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { - PurpleBuddy *buddy; - - if ((buddy = purple_find_buddy(purple_connection_get_account(gc), user)) != NULL) - alias = purple_buddy_get_contact_alias(buddy); - } - - alias_esc = g_markup_escape_text(alias, -1); - - if (reason == NULL || !*reason) - tmp = g_strdup_printf(_("%s left the room."), alias_esc); - else { - char *reason_esc = g_markup_escape_text(reason, -1); - tmp = g_strdup_printf(_("%s left the room (%s)."), - alias_esc, reason_esc); - g_free(reason_esc); - } - g_free(alias_esc); +/************************************************************************** + * GObject code + **************************************************************************/ - purple_conversation_write(conv, NULL, tmp, - PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, - time(NULL)); - g_free(tmp); - } +/* GObject Property names */ +#define PROP_ACCOUNT_S "account" +#define PROP_NAME_S "name" +#define PROP_TITLE_S "title" +#define PROP_LOGGING_S "logging" +#define PROP_FEATURES_S "features" - purple_signal_emit(purple_conversations_get_handle(), "chat-buddy-left", - conv, user, reason); +/* Set method for GObject properties */ +static void +purple_conversation_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleConversation *conv = PURPLE_CONVERSATION(obj); + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); + + switch (param_id) { + /* account, name and title are assigned directly here as + * purple_im_conversation_new() and purple_chat_conversation_new() + * pass these properties as parameters, and so the conversation hasn't + * finished being set up */ + case PROP_ACCOUNT: + priv->account = g_value_get_object(value); + break; + case PROP_NAME: + g_free(priv->name); + priv->name = g_strdup(g_value_get_string(value)); + break; + case PROP_TITLE: + g_free(priv->title); + priv->title = g_strdup(g_value_get_string(value)); + break; + case PROP_LOGGING: + purple_conversation_set_logging(conv, g_value_get_boolean(value)); + break; + case PROP_FEATURES: + purple_conversation_set_features(conv, g_value_get_flags(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; } - - if (ops != NULL && ops->chat_remove_users != NULL) - ops->chat_remove_users(conv, users); } -void -purple_conv_chat_clear_users(PurpleConvChat *chat) +/* Get method for GObject properties */ +static void +purple_conversation_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) { - PurpleConversation *conv; - PurpleConversationUiOps *ops; - GList *users; - GList *l; - GList *names = NULL; - - g_return_if_fail(chat != NULL); - - conv = purple_conv_chat_get_conversation(chat); - ops = purple_conversation_get_ui_ops(conv); - users = chat->in_room; + PurpleConversation *conv = PURPLE_CONVERSATION(obj); - if (ops != NULL && ops->chat_remove_users != NULL) { - for (l = users; l; l = l->next) { - PurpleConvChatBuddy *cb = l->data; - names = g_list_prepend(names, cb->name); - } - ops->chat_remove_users(conv, names); - g_list_free(names); - } - - for (l = users; l; l = l->next) - { - PurpleConvChatBuddy *cb = l->data; - - purple_signal_emit(purple_conversations_get_handle(), - "chat-buddy-leaving", conv, cb->name, NULL); - purple_signal_emit(purple_conversations_get_handle(), - "chat-buddy-left", conv, cb->name, NULL); - - purple_conv_chat_cb_destroy(cb); + switch (param_id) { + case PROP_ACCOUNT: + g_value_set_object(value, purple_conversation_get_account(conv)); + break; + case PROP_NAME: + g_value_set_string(value, purple_conversation_get_name(conv)); + break; + case PROP_TITLE: + g_value_set_string(value, purple_conversation_get_title(conv)); + break; + case PROP_LOGGING: + g_value_set_boolean(value, purple_conversation_is_logging(conv)); + break; + case PROP_FEATURES: + g_value_set_flags(value, purple_conversation_get_features(conv)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; } - - g_hash_table_remove_all(chat->users); - - g_list_free(users); - chat->in_room = NULL; } - -gboolean -purple_conv_chat_find_user(PurpleConvChat *chat, const char *user) +/* GObject initialization function */ +static void +purple_conversation_init(GTypeInstance *instance, gpointer klass) { - g_return_val_if_fail(chat != NULL, FALSE); - g_return_val_if_fail(user != NULL, FALSE); - - return (purple_conv_chat_cb_find(chat, user) != NULL); + PURPLE_DBUS_REGISTER_POINTER(PURPLE_CONVERSATION(instance), PurpleConversation); } -void -purple_conv_chat_user_set_flags(PurpleConvChat *chat, const char *user, - PurpleConvChatBuddyFlags flags) +/* Called when done constructing */ +static void +purple_conversation_constructed(GObject *object) { - PurpleConversation *conv; + PurpleConversation *conv = PURPLE_CONVERSATION(object); + PurpleAccount *account; + PurpleConnection *gc; PurpleConversationUiOps *ops; - PurpleConvChatBuddy *cb; - PurpleConvChatBuddyFlags oldflags; - g_return_if_fail(chat != NULL); - g_return_if_fail(user != NULL); + parent_class->constructed(object); - cb = purple_conv_chat_cb_find(chat, user); - - if (!cb) - return; + g_object_get(object, PROP_ACCOUNT_S, &account, NULL); + gc = purple_account_get_connection(account); - if (flags == cb->flags) - return; + /* copy features from the connection. */ + purple_conversation_set_features(conv, purple_connection_get_flags(gc)); - oldflags = cb->flags; - cb->flags = flags; + /* add the conversation to the appropriate lists */ + purple_conversations_add(conv); - conv = purple_conv_chat_get_conversation(chat); - ops = purple_conversation_get_ui_ops(conv); + /* Auto-set the title. */ + purple_conversation_autoset_title(conv); - if (ops != NULL && ops->chat_update_user != NULL) - ops->chat_update_user(conv, user); + /* Don't move this.. it needs to be one of the last things done otherwise + * it causes mysterious crashes on my system. + * -- Gary + */ + ops = purple_conversations_get_ui_ops(); + purple_conversation_set_ui_ops(conv, ops); + if (ops != NULL && ops->create_conversation != NULL) + ops->create_conversation(conv); purple_signal_emit(purple_conversations_get_handle(), - "chat-buddy-flags", conv, user, oldflags, flags); -} - -PurpleConvChatBuddyFlags -purple_conv_chat_user_get_flags(PurpleConvChat *chat, const char *user) -{ - PurpleConvChatBuddy *cb; - - g_return_val_if_fail(chat != NULL, 0); - g_return_val_if_fail(user != NULL, 0); - - cb = purple_conv_chat_cb_find(chat, user); - - if (!cb) - return PURPLE_CBFLAGS_NONE; - - return cb->flags; -} - -void purple_conv_chat_set_nick(PurpleConvChat *chat, const char *nick) { - g_return_if_fail(chat != NULL); - - g_free(chat->nick); - chat->nick = g_strdup(purple_normalize(chat->conv->account, nick)); -} - -const char *purple_conv_chat_get_nick(PurpleConvChat *chat) { - g_return_val_if_fail(chat != NULL, NULL); - - return chat->nick; -} - -PurpleConversation * -purple_find_chat(const PurpleConnection *gc, int id) -{ - GList *l; - PurpleConversation *conv; - - for (l = purple_get_chats(); l != NULL; l = l->next) { - conv = (PurpleConversation *)l->data; - - if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)) == id && - purple_conversation_get_connection(conv) == gc) - return conv; - } - - return NULL; -} - -void -purple_conv_chat_left(PurpleConvChat *chat) -{ - g_return_if_fail(chat != NULL); - - chat->left = TRUE; - purple_conversation_update(chat->conv, PURPLE_CONV_UPDATE_CHATLEFT); + "conversation-created", conv); } +/* GObject dispose function */ static void -invite_user_to_chat(gpointer data, PurpleRequestFields *fields) -{ - PurpleConversation *conv; - PurpleConvChat *chat; - const char *user, *message; - - conv = data; - chat = PURPLE_CONV_CHAT(conv); - user = purple_request_fields_get_string(fields, "screenname"); - message = purple_request_fields_get_string(fields, "message"); - - serv_chat_invite(purple_conversation_get_connection(conv), chat->id, message, user); -} - -void purple_conv_chat_invite_user(PurpleConvChat *chat, const char *user, - const char *message, gboolean confirm) -{ - PurpleAccount *account; - PurpleConversation *conv; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *group; - PurpleRequestField *field; - - g_return_if_fail(chat); - - if (!user || !*user || !message || !*message) - confirm = TRUE; - - conv = chat->conv; - account = conv->account; - - if (!confirm) { - serv_chat_invite(purple_account_get_connection(account), - purple_conv_chat_get_id(chat), message, user); - return; - } - - fields = purple_request_fields_new(); - group = purple_request_field_group_new(_("Invite to chat")); - purple_request_fields_add_group(fields, group); - - field = purple_request_field_string_new("screenname", _("Buddy"), user, FALSE); - purple_request_field_group_add_field(group, field); - purple_request_field_set_required(field, TRUE); - purple_request_field_set_type_hint(field, "screenname"); - - field = purple_request_field_string_new("message", _("Message"), message, FALSE); - purple_request_field_group_add_field(group, field); - - purple_request_fields(conv, _("Invite to chat"), NULL, - _("Please enter the name of the user you wish to invite, " - "along with an optional invite message."), - fields, - _("Invite"), G_CALLBACK(invite_user_to_chat), - _("Cancel"), NULL, - account, user, conv, - conv); -} - -gboolean -purple_conv_chat_has_left(PurpleConvChat *chat) +purple_conversation_dispose(GObject *object) { - g_return_val_if_fail(chat != NULL, TRUE); - - return chat->left; -} - -PurpleConvChatBuddy * -purple_conv_chat_cb_new(const char *name, const char *alias, PurpleConvChatBuddyFlags flags) -{ - PurpleConvChatBuddy *cb; - - g_return_val_if_fail(name != NULL, NULL); + PurpleConversation *conv = PURPLE_CONVERSATION(object); - cb = g_new0(PurpleConvChatBuddy, 1); - cb->name = g_strdup(name); - cb->flags = flags; - cb->alias = g_strdup(alias); - cb->attributes = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, g_free); - - PURPLE_DBUS_REGISTER_POINTER(cb, PurpleConvChatBuddy); - return cb; -} - -PurpleConvChatBuddy * -purple_conv_chat_cb_find(PurpleConvChat *chat, const char *name) -{ - g_return_val_if_fail(chat != NULL, NULL); - g_return_val_if_fail(name != NULL, NULL); + g_return_if_fail(conv != NULL); - return g_hash_table_lookup(chat->users, name); -} + purple_request_close_with_handle(conv); -void -purple_conv_chat_cb_destroy(PurpleConvChatBuddy *cb) -{ - if (cb == NULL) - return; + /* remove from conversations and im/chats lists prior to emit */ + purple_conversations_remove(conv); purple_signal_emit(purple_conversations_get_handle(), - "deleting-chat-buddy", cb); - - g_free(cb->alias); - g_free(cb->alias_key); - g_free(cb->name); - g_hash_table_destroy(cb->attributes); - - PURPLE_DBUS_UNREGISTER_POINTER(cb); - g_free(cb); -} - -void purple_conv_chat_cb_set_ui_data(PurpleConvChatBuddy *cb, gpointer ui_data) -{ - g_return_if_fail(cb != NULL); - - cb->ui_data = ui_data; -} - -gpointer purple_conv_chat_cb_get_ui_data(const PurpleConvChatBuddy *cb) -{ - g_return_val_if_fail(cb != NULL, NULL); - - return cb->ui_data; -} - -const char * -purple_conv_chat_cb_get_alias(const PurpleConvChatBuddy *cb) -{ - g_return_val_if_fail(cb != NULL, NULL); + "deleting-conversation", conv); - return cb->alias; -} + purple_conversation_close_logs(conv); + purple_conversation_clear_message_history(conv); -const char * -purple_conv_chat_cb_get_name(const PurpleConvChatBuddy *cb) -{ - g_return_val_if_fail(cb != NULL, NULL); + PURPLE_DBUS_UNREGISTER_POINTER(conv); - return cb->name; + parent_class->dispose(object); } -PurpleConvChatBuddyFlags -purple_conv_chat_cb_get_flags(const PurpleConvChatBuddy *cb) +/* GObject finalize function */ +static void +purple_conversation_finalize(GObject *object) { - g_return_val_if_fail(cb != NULL, PURPLE_CBFLAGS_NONE); + PurpleConversation *conv = PURPLE_CONVERSATION(object); + PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); + PurpleConversationUiOps *ops = purple_conversation_get_ui_ops(conv); - return cb->flags; -} + g_free(priv->name); + g_free(priv->title); -gboolean purple_conv_chat_cb_is_buddy(const PurpleConvChatBuddy *cb) -{ - g_return_val_if_fail(cb != NULL, FALSE); + priv->name = NULL; + priv->title = NULL; - return cb->buddy; -} + if (ops != NULL && ops->destroy_conversation != NULL) + ops->destroy_conversation(conv); -const char * -purple_conv_chat_cb_get_attribute(PurpleConvChatBuddy *cb, const char *key) -{ - g_return_val_if_fail(cb != NULL, NULL); - g_return_val_if_fail(key != NULL, NULL); - - return g_hash_table_lookup(cb->attributes, key); + parent_class->finalize(object); } +/* Class initializer function */ static void -append_attribute_key(gpointer key, gpointer value, gpointer user_data) -{ - GList **list = user_data; - *list = g_list_prepend(*list, key); -} - -GList * -purple_conv_chat_cb_get_attribute_keys(PurpleConvChatBuddy *cb) -{ - GList *keys = NULL; - - g_return_val_if_fail(cb != NULL, NULL); - - g_hash_table_foreach(cb->attributes, (GHFunc)append_attribute_key, &keys); - - return keys; -} - -void -purple_conv_chat_cb_set_attribute(PurpleConvChat *chat, PurpleConvChatBuddy *cb, const char *key, const char *value) -{ - PurpleConversation *conv; - PurpleConversationUiOps *ops; - - g_return_if_fail(cb != NULL); - g_return_if_fail(key != NULL); - g_return_if_fail(value != NULL); - - g_hash_table_replace(cb->attributes, g_strdup(key), g_strdup(value)); - - conv = purple_conv_chat_get_conversation(chat); - ops = purple_conversation_get_ui_ops(conv); - - if (ops != NULL && ops->chat_update_user != NULL) - ops->chat_update_user(conv, cb->name); -} - -void -purple_conv_chat_cb_set_attributes(PurpleConvChat *chat, PurpleConvChatBuddy *cb, GList *keys, GList *values) -{ - PurpleConversation *conv; - PurpleConversationUiOps *ops; - - g_return_if_fail(cb != NULL); - g_return_if_fail(keys != NULL); - g_return_if_fail(values != NULL); - - while (keys != NULL && values != NULL) { - g_hash_table_replace(cb->attributes, g_strdup(keys->data), g_strdup(values->data)); - keys = g_list_next(keys); - values = g_list_next(values); +purple_conversation_class_init(PurpleConversationClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->dispose = purple_conversation_dispose; + obj_class->finalize = purple_conversation_finalize; + obj_class->constructed = purple_conversation_constructed; + + /* Setup properties */ + obj_class->get_property = purple_conversation_get_property; + obj_class->set_property = purple_conversation_set_property; + + g_object_class_install_property(obj_class, PROP_ACCOUNT, + g_param_spec_object(PROP_ACCOUNT_S, _("Account"), + _("The account for the conversation."), PURPLE_TYPE_ACCOUNT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_object_class_install_property(obj_class, PROP_NAME, + g_param_spec_string(PROP_NAME_S, _("Name"), + _("The name of the conversation."), NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_object_class_install_property(obj_class, PROP_TITLE, + g_param_spec_string(PROP_TITLE_S, _("Title"), + _("The title of the conversation."), NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_object_class_install_property(obj_class, PROP_LOGGING, + g_param_spec_boolean(PROP_LOGGING_S, _("Logging status"), + _("Whether logging is enabled or not."), FALSE, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PROP_FEATURES, + g_param_spec_flags(PROP_FEATURES_S, _("Connection features"), + _("The connection features of the conversation."), + PURPLE_TYPE_CONNECTION_FLAGS, 0, + G_PARAM_READWRITE) + ); + + g_type_class_add_private(klass, sizeof(PurpleConversationPrivate)); +} + +GType +purple_conversation_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleConversationClass), + NULL, + NULL, + (GClassInitFunc)purple_conversation_class_init, + NULL, + NULL, + sizeof(PurpleConversation), + 0, + (GInstanceInitFunc)purple_conversation_init, + NULL, + }; + + type = g_type_register_static(G_TYPE_OBJECT, + "PurpleConversation", + &info, G_TYPE_FLAG_ABSTRACT); } - - conv = purple_conv_chat_get_conversation(chat); - ops = purple_conversation_get_ui_ops(conv); - - if (ops != NULL && ops->chat_update_user != NULL) - ops->chat_update_user(conv, cb->name); -} - -GList * -purple_conversation_get_extended_menu(PurpleConversation *conv) -{ - GList *menu = NULL; - - g_return_val_if_fail(conv != NULL, NULL); - - purple_signal_emit(purple_conversations_get_handle(), - "conversation-extended-menu", conv, &menu); - return menu; -} - -void purple_conversation_clear_message_history(PurpleConversation *conv) -{ - GList *list = conv->message_history; - message_history_free(list); - conv->message_history = NULL; - - purple_signal_emit(purple_conversations_get_handle(), - "cleared-message-history", conv); -} - -GList *purple_conversation_get_message_history(PurpleConversation *conv) -{ - return conv->message_history; -} - -const char *purple_conversation_message_get_sender(const PurpleConvMessage *msg) -{ - g_return_val_if_fail(msg, NULL); - return msg->who; -} - -const char *purple_conversation_message_get_message(const PurpleConvMessage *msg) -{ - g_return_val_if_fail(msg, NULL); - return msg->what; -} - -PurpleMessageFlags purple_conversation_message_get_flags(const PurpleConvMessage *msg) -{ - g_return_val_if_fail(msg, 0); - return msg->flags; -} - -time_t purple_conversation_message_get_timestamp(const PurpleConvMessage *msg) -{ - g_return_val_if_fail(msg, 0); - return msg->when; -} - -const char *purple_conversation_message_get_alias(const PurpleConvMessage *msg) -{ - g_return_val_if_fail(msg, NULL); - return msg->alias; -} - -PurpleConversation *purple_conversation_message_get_conv(const PurpleConvMessage *msg) -{ - g_return_val_if_fail(msg, NULL); - return msg->conv; -} - -void purple_conversation_set_ui_data(PurpleConversation *conv, gpointer ui_data) -{ - g_return_if_fail(conv != NULL); - conv->ui_data = ui_data; + return type; } - -gpointer purple_conversation_get_ui_data(const PurpleConversation *conv) -{ - g_return_val_if_fail(conv != NULL, NULL); - - return conv->ui_data; -} - - -gboolean -purple_conversation_do_command(PurpleConversation *conv, const gchar *cmdline, - const gchar *markup, gchar **error) -{ - char *mark = (markup && *markup) ? NULL : g_markup_escape_text(cmdline, -1), *err = NULL; - PurpleCmdStatus status = purple_cmd_do_command(conv, cmdline, mark ? mark : markup, error ? error : &err); - g_free(mark); - g_free(err); - return (status == PURPLE_CMD_STATUS_OK); -} - -void * -purple_conversations_get_handle(void) -{ - static int handle; - - return &handle; -} - -void -purple_conversations_init(void) -{ - void *handle = purple_conversations_get_handle(); - - conversation_cache = g_hash_table_new_full((GHashFunc)_purple_conversations_hconv_hash, - (GEqualFunc)_purple_conversations_hconv_equal, - (GDestroyNotify)_purple_conversations_hconv_free_key, NULL); - - /********************************************************************** - * Register preferences - **********************************************************************/ - - /* Conversations */ - purple_prefs_add_none("/purple/conversations"); - - /* Conversations -> Chat */ - purple_prefs_add_none("/purple/conversations/chat"); - purple_prefs_add_bool("/purple/conversations/chat/show_nick_change", TRUE); - - /* Conversations -> IM */ - purple_prefs_add_none("/purple/conversations/im"); - purple_prefs_add_bool("/purple/conversations/im/send_typing", TRUE); - - - /********************************************************************** - * Register signals - **********************************************************************/ - purple_signal_register(handle, "writing-im-msg", - purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_UINT, - purple_value_new(PURPLE_TYPE_BOOLEAN), 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "wrote-im-msg", - purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, - NULL, 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "sent-attention", - purple_marshal_VOID__POINTER_POINTER_POINTER_UINT, - NULL, 4, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "got-attention", - purple_marshal_VOID__POINTER_POINTER_POINTER_UINT, - NULL, 4, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "sending-im-msg", - purple_marshal_VOID__POINTER_POINTER_POINTER, - NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new_outgoing(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "sent-im-msg", - purple_marshal_VOID__POINTER_POINTER_POINTER, - NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "receiving-im-msg", - purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new_outgoing(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "received-im-msg", - purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, - NULL, 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "blocked-im-msg", - purple_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT, - NULL, 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_UINT), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "writing-chat-msg", - purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_UINT, - purple_value_new(PURPLE_TYPE_BOOLEAN), 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "wrote-chat-msg", - purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, - NULL, 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "sending-chat-msg", - purple_marshal_VOID__POINTER_POINTER_UINT, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "sent-chat-msg", - purple_marshal_VOID__POINTER_POINTER_UINT, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "receiving-chat-msg", - purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new_outgoing(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "received-chat-msg", - purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, - NULL, 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "conversation-created", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION)); - - purple_signal_register(handle, "conversation-updated", - purple_marshal_VOID__POINTER_UINT, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "deleting-conversation", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION)); - - purple_signal_register(handle, "buddy-typing", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "buddy-typed", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "buddy-typing-stopped", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "chat-buddy-joining", - purple_marshal_BOOLEAN__POINTER_POINTER_UINT, - purple_value_new(PURPLE_TYPE_BOOLEAN), 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "chat-buddy-joined", - purple_marshal_VOID__POINTER_POINTER_UINT_UINT, NULL, 4, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_UINT), - purple_value_new(PURPLE_TYPE_BOOLEAN)); - - purple_signal_register(handle, "chat-buddy-flags", - purple_marshal_VOID__POINTER_POINTER_UINT_UINT, NULL, 4, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_UINT), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "chat-buddy-leaving", - purple_marshal_BOOLEAN__POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "chat-buddy-left", - purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "deleting-chat-buddy", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CHATBUDDY)); - - purple_signal_register(handle, "chat-inviting-user", - purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new_outgoing(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "chat-invited-user", - purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "chat-invited", - purple_marshal_INT__POINTER_POINTER_POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_INT), 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_POINTER)); - - purple_signal_register(handle, "chat-invite-blocked", - purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_POINTER, - NULL, 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_BOXED, "GHashTable *")); - - purple_signal_register(handle, "chat-joined", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION)); - - purple_signal_register(handle, "chat-join-failed", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONNECTION), - purple_value_new(PURPLE_TYPE_POINTER)); - - purple_signal_register(handle, "chat-left", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION)); - - purple_signal_register(handle, "chat-topic-changed", - purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "cleared-message-history", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION)); - - purple_signal_register(handle, "conversation-extended-menu", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_BOXED, "GList **")); -} - -void -purple_conversations_uninit(void) -{ - while (conversations) - purple_conversation_destroy((PurpleConversation*)conversations->data); - g_hash_table_destroy(conversation_cache); - purple_signals_unregister_by_instance(purple_conversations_get_handle()); -} - diff --git a/libpurple/conversation.h b/libpurple/conversation.h index 80262ef809..b8eb85feea 100644 --- a/libpurple/conversation.h +++ b/libpurple/conversation.h @@ -1,7 +1,6 @@ /** - * @file conversation.h Conversation API + * @file conversation.h Conversation base class API * @ingroup core - * @see @ref conversation-signals */ /* purple @@ -27,128 +26,140 @@ #ifndef _PURPLE_CONVERSATION_H_ #define _PURPLE_CONVERSATION_H_ +#define PURPLE_TYPE_CONVERSATION (purple_conversation_get_type()) +#define PURPLE_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_CONVERSATION, PurpleConversation)) +#define PURPLE_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_CONVERSATION, PurpleConversationClass)) +#define PURPLE_IS_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_CONVERSATION)) +#define PURPLE_IS_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_CONVERSATION)) +#define PURPLE_CONVERSATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_CONVERSATION, PurpleConversationClass)) + +#define PURPLE_TYPE_CONVERSATION_MESSAGE (purple_conversation_message_get_type()) + /**************************************************************************/ /** Data Structures */ /**************************************************************************/ - -/** @copydoc _PurpleConversationUiOps */ -typedef struct _PurpleConversationUiOps PurpleConversationUiOps; /** @copydoc _PurpleConversation */ -typedef struct _PurpleConversation PurpleConversation; -/** @copydoc _PurpleConvIm */ -typedef struct _PurpleConvIm PurpleConvIm; -/** @copydoc _PurpleConvChat */ -typedef struct _PurpleConvChat PurpleConvChat; -/** @copydoc _PurpleConvChatBuddy */ -typedef struct _PurpleConvChatBuddy PurpleConvChatBuddy; -/** @copydoc _PurpleConvMessage */ -typedef struct _PurpleConvMessage PurpleConvMessage; - -/** - * A type of conversation. - */ -typedef enum -{ - PURPLE_CONV_TYPE_UNKNOWN = 0, /**< Unknown conversation type. */ - PURPLE_CONV_TYPE_IM, /**< Instant Message. */ - PURPLE_CONV_TYPE_CHAT, /**< Chat room. */ - PURPLE_CONV_TYPE_MISC, /**< A misc. conversation. */ - PURPLE_CONV_TYPE_ANY /**< Any type of conversation. */ +typedef struct _PurpleConversation PurpleConversation; +/** @copydoc _PurpleConversation */ +typedef struct _PurpleConversationClass PurpleConversationClass; -} PurpleConversationType; +/** @copydoc _PurpleConversationUiOps */ +typedef struct _PurpleConversationUiOps PurpleConversationUiOps; +/** @copydoc _PurpleConversationMessage */ +typedef struct _PurpleConversationMessage PurpleConversationMessage; /** * Conversation update type. */ typedef enum { - PURPLE_CONV_UPDATE_ADD = 0, /**< The buddy associated with the conversation - was added. */ - PURPLE_CONV_UPDATE_REMOVE, /**< The buddy associated with the conversation - was removed. */ - PURPLE_CONV_UPDATE_ACCOUNT, /**< The purple_account was changed. */ - PURPLE_CONV_UPDATE_TYPING, /**< The typing state was updated. */ - PURPLE_CONV_UPDATE_UNSEEN, /**< The unseen state was updated. */ - PURPLE_CONV_UPDATE_LOGGING, /**< Logging for this conversation was - enabled or disabled. */ - PURPLE_CONV_UPDATE_TOPIC, /**< The topic for a chat was updated. */ + PURPLE_CONVERSATION_UPDATE_ADD = 0, /**< The buddy associated with the conversation + was added. */ + PURPLE_CONVERSATION_UPDATE_REMOVE, /**< The buddy associated with the conversation + was removed. */ + PURPLE_CONVERSATION_UPDATE_ACCOUNT, /**< The purple_account was changed. */ + PURPLE_CONVERSATION_UPDATE_TYPING, /**< The typing state was updated. */ + PURPLE_CONVERSATION_UPDATE_UNSEEN, /**< The unseen state was updated. */ + PURPLE_CONVERSATION_UPDATE_LOGGING, /**< Logging for this conversation was + enabled or disabled. */ + PURPLE_CONVERSATION_UPDATE_TOPIC, /**< The topic for a chat was updated. */ /* * XXX These need to go when we implement a more generic core/UI event * system. */ - PURPLE_CONV_ACCOUNT_ONLINE, /**< One of the user's accounts went online. */ - PURPLE_CONV_ACCOUNT_OFFLINE, /**< One of the user's accounts went offline. */ - PURPLE_CONV_UPDATE_AWAY, /**< The other user went away. */ - PURPLE_CONV_UPDATE_ICON, /**< The other user's buddy icon changed. */ - PURPLE_CONV_UPDATE_TITLE, - PURPLE_CONV_UPDATE_CHATLEFT, + PURPLE_CONVERSATION_ACCOUNT_ONLINE, /**< One of the user's accounts went online. */ + PURPLE_CONVERSATION_ACCOUNT_OFFLINE, /**< One of the user's accounts went offline. */ + PURPLE_CONVERSATION_UPDATE_AWAY, /**< The other user went away. */ + PURPLE_CONVERSATION_UPDATE_ICON, /**< The other user's buddy icon changed. */ + PURPLE_CONVERSATION_UPDATE_TITLE, + PURPLE_CONVERSATION_UPDATE_CHATLEFT, - PURPLE_CONV_UPDATE_FEATURES /**< The features for a chat have changed */ + PURPLE_CONVERSATION_UPDATE_FEATURES /**< The features for a chat have changed */ -} PurpleConvUpdateType; - -/** - * The typing state of a user. - */ -typedef enum -{ - PURPLE_NOT_TYPING = 0, /**< Not typing. */ - PURPLE_TYPING, /**< Currently typing. */ - PURPLE_TYPED /**< Stopped typing momentarily. */ - -} PurpleTypingState; +} PurpleConversationUpdateType; /** * Flags applicable to a message. Most will have send, recv or system. */ -typedef enum +typedef enum /*< flags >*/ { PURPLE_MESSAGE_SEND = 0x0001, /**< Outgoing message. */ PURPLE_MESSAGE_RECV = 0x0002, /**< Incoming message. */ PURPLE_MESSAGE_SYSTEM = 0x0004, /**< System message. */ PURPLE_MESSAGE_AUTO_RESP = 0x0008, /**< Auto response. */ PURPLE_MESSAGE_ACTIVE_ONLY = 0x0010, /**< Hint to the UI that this - message should not be - shown in conversations - which are only open for - internal UI purposes - (e.g. for contact-aware - conversations). */ + message should not be + shown in conversations + which are only open for + internal UI purposes + (e.g. for contact-aware + conversations). */ PURPLE_MESSAGE_NICK = 0x0020, /**< Contains your nick. */ PURPLE_MESSAGE_NO_LOG = 0x0040, /**< Do not log. */ PURPLE_MESSAGE_WHISPER = 0x0080, /**< Whispered message. */ PURPLE_MESSAGE_ERROR = 0x0200, /**< Error message. */ PURPLE_MESSAGE_DELAYED = 0x0400, /**< Delayed message. */ PURPLE_MESSAGE_RAW = 0x0800, /**< "Raw" message - don't - apply formatting */ + apply formatting */ PURPLE_MESSAGE_IMAGES = 0x1000, /**< Message contains images */ PURPLE_MESSAGE_NOTIFY = 0x2000, /**< Message is a notification */ PURPLE_MESSAGE_NO_LINKIFY = 0x4000, /**< Message should not be auto- - linkified */ + linkified */ PURPLE_MESSAGE_INVISIBLE = 0x8000 /**< Message should not be displayed */ } PurpleMessageFlags; +#include <glib.h> +#include <glib-object.h> + +/**************************************************************************/ +/** PurpleConversation */ +/**************************************************************************/ /** - * Flags applicable to users in Chats. + * A core representation of a conversation between two or more people. + * + * The conversation can be an IM or a chat. + * + * @note When a conversation is destroyed with the last g_object_unref(), the + * specified conversation is removed from the parent window. If this + * conversation is the only one contained in the parent window, that + * window is also destroyed. */ -typedef enum +struct _PurpleConversation { - PURPLE_CBFLAGS_NONE = 0x0000, /**< No flags */ - PURPLE_CBFLAGS_VOICE = 0x0001, /**< Voiced user or "Participant" */ - PURPLE_CBFLAGS_HALFOP = 0x0002, /**< Half-op */ - PURPLE_CBFLAGS_OP = 0x0004, /**< Channel Op or Moderator */ - PURPLE_CBFLAGS_FOUNDER = 0x0008, /**< Channel Founder */ - PURPLE_CBFLAGS_TYPING = 0x0010, /**< Currently typing */ - PURPLE_CBFLAGS_AWAY = 0x0020 /**< Currently away. */ + /*< private >*/ + GObject gparent; -} PurpleConvChatBuddyFlags; + /** The UI data associated with this conversation. This is a convenience + * field provided to the UIs -- it is not used by the libpurple core. + */ + gpointer ui_data; +}; + +/** Base class for all #PurpleConversation's */ +struct _PurpleConversationClass { + /*< private >*/ + GObjectClass parent_class; + + /** Writes a message to a chat or IM conversation. + * @see purple_conversation_write_message() + */ + void (*write_message)(PurpleConversation *conv, const char *who, + const char *message, PurpleMessageFlags flags, time_t mtime); + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; #include "account.h" #include "buddyicon.h" #include "log.h" -#include "server.h" +/**************************************************************************/ +/** PurpleConversationUiOps */ +/**************************************************************************/ /** * Conversation operations and events. * @@ -166,16 +177,16 @@ struct _PurpleConversationUiOps void (*destroy_conversation)(PurpleConversation *conv); /** Write a message to a chat. If this field is @c NULL, libpurple will * fall back to using #write_conv. - * @see purple_conv_chat_write() + * @see purple_chat_conversation_write() */ - void (*write_chat)(PurpleConversation *conv, const char *who, - const char *message, PurpleMessageFlags flags, - time_t mtime); + void (*write_chat)(PurpleChatConversation *chat, const char *who, + const char *message, PurpleMessageFlags flags, + time_t mtime); /** Write a message to an IM conversation. If this field is @c NULL, * libpurple will fall back to using #write_conv. - * @see purple_conv_im_write() + * @see purple_im_conversation_write() */ - void (*write_im)(PurpleConversation *conv, const char *who, + void (*write_im)(PurpleIMConversation *im, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime); /** Write a message to a conversation. This is used rather than the @@ -194,30 +205,31 @@ struct _PurpleConversationUiOps time_t mtime); /** Add @a cbuddies to a chat. - * @param cbuddies A @c GList of #PurpleConvChatBuddy structs. + * @param cbuddies A @c GList of #PurpleChatUser structs. * @param new_arrivals Whether join notices should be shown. * (Join notices are actually written to the - * conversation by #purple_conv_chat_add_users().) + * conversation by + * #purple_chat_conversation_add_users().) */ - void (*chat_add_users)(PurpleConversation *conv, + void (*chat_add_users)(PurpleChatConversation *chat, GList *cbuddies, gboolean new_arrivals); /** Rename the user in this chat named @a old_name to @a new_name. (The * rename message is written to the conversation by libpurple.) * @param new_alias @a new_name's new alias, if they have one. - * @see purple_conv_chat_add_users() + * @see purple_chat_conversation_add_users() */ - void (*chat_rename_user)(PurpleConversation *conv, const char *old_name, + void (*chat_rename_user)(PurpleChatConversation *chat, const char *old_name, const char *new_name, const char *new_alias); /** Remove @a users from a chat. * @param users A @c GList of <tt>const char *</tt>s. - * @see purple_conv_chat_rename_user() + * @see purple_chat_conversation_rename_user() */ - void (*chat_remove_users)(PurpleConversation *conv, GList *users); + void (*chat_remove_users)(PurpleChatConversation *chat, GList *users); /** Called when a user's flags are changed. - * @see purple_conv_chat_user_set_flags() + * @see purple_chat_user_set_flags() */ - void (*chat_update_user)(PurpleConversation *conv, const char *user); + void (*chat_update_user)(PurpleChatUser *cb); /** Present this conversation to the user; for example, by displaying * the IM dialog. @@ -231,7 +243,8 @@ struct _PurpleConversationUiOps gboolean (*has_focus)(PurpleConversation *conv); /* Custom Smileys */ - gboolean (*custom_smiley_add)(PurpleConversation *conv, const char *smile, gboolean remote); + gboolean (*custom_smiley_add)(PurpleConversation *conv, const char *smile, + gboolean remote); void (*custom_smiley_write)(PurpleConversation *conv, const char *smile, const guchar *data, gsize size); void (*custom_smiley_close)(PurpleConversation *conv, const char *smile); @@ -257,31 +270,9 @@ G_BEGIN_DECLS /*@{*/ /** - * Creates a new conversation of the specified type. - * - * @param type The type of conversation. - * @param account The account opening the conversation window on the purple - * user's end. - * @param name The name of the conversation. For PURPLE_CONV_TYPE_IM, - * this is the name of the buddy. - * - * @return The new conversation. - */ -PurpleConversation *purple_conversation_new(PurpleConversationType type, - PurpleAccount *account, - const char *name); - -/** - * Destroys the specified conversation and removes it from the parent - * window. - * - * If this conversation is the only one contained in the parent window, - * that window is also destroyed. - * - * @param conv The conversation to destroy. + * Returns the GType for the Conversation object. */ -void purple_conversation_destroy(PurpleConversation *conv); - +GType purple_conversation_get_type(void); /** * Present a conversation to the user. This allows core code to initiate a @@ -290,16 +281,6 @@ void purple_conversation_destroy(PurpleConversation *conv); */ void purple_conversation_present(PurpleConversation *conv); - -/** - * Returns the specified conversation's type. - * - * @param conv The conversation. - * - * @return The conversation's type. - */ -PurpleConversationType purple_conversation_get_type(const PurpleConversation *conv); - /** * Sets the specified conversation's UI operations structure. * @@ -310,21 +291,13 @@ void purple_conversation_set_ui_ops(PurpleConversation *conv, PurpleConversationUiOps *ops); /** - * Sets the default conversation UI operations structure. - * - * @param ops The UI conversation operations structure. - */ -void purple_conversations_set_ui_ops(PurpleConversationUiOps *ops); - -/** * Returns the specified conversation's UI operations structure. * * @param conv The conversation. * * @return The operations structure. */ -PurpleConversationUiOps *purple_conversation_get_ui_ops( - const PurpleConversation *conv); +PurpleConversationUiOps *purple_conversation_get_ui_ops(const PurpleConversation *conv); /** * Sets the specified conversation's purple_account. @@ -405,46 +378,6 @@ void purple_conversation_set_name(PurpleConversation *conv, const char *name); const char *purple_conversation_get_name(const PurpleConversation *conv); /** - * Get an attribute of a chat buddy - * - * @param cb The chat buddy. - * @param key The key of the attribute. - * - * @return The value of the attribute key. - */ -const char *purple_conv_chat_cb_get_attribute(PurpleConvChatBuddy *cb, const char *key); - -/** - * Get the keys of all atributes of a chat buddy - * - * @param cb The chat buddy. - * - * @return A list of the attributes of a chat buddy. - */ -GList *purple_conv_chat_cb_get_attribute_keys(PurpleConvChatBuddy *cb); - -/** - * Set an attribute of a chat buddy - * - * @param chat The chat. - * @param cb The chat buddy. - * @param key The key of the attribute. - * @param value The value of the attribute. - */ -void purple_conv_chat_cb_set_attribute(PurpleConvChat *chat, PurpleConvChatBuddy *cb, const char *key, const char *value); - -/** - * Set attributes of a chat buddy - * - * @param chat The chat. - * @param cb The chat buddy. - * @param keys A GList of the keys. - * @param values A GList of the values. - */ -void -purple_conv_chat_cb_set_attributes(PurpleConvChat *chat, PurpleConvChatBuddy *cb, GList *keys, GList *values); - -/** * Enables or disables logging for this conversation. * * @param conv The conversation. @@ -473,110 +406,61 @@ gboolean purple_conversation_is_logging(const PurpleConversation *conv); void purple_conversation_close_logs(PurpleConversation *conv); /** - * Returns the specified conversation's IM-specific data. - * - * If the conversation type is not PURPLE_CONV_TYPE_IM, this will return @c NULL. - * - * @param conv The conversation. - * - * @return The IM-specific data. - */ -PurpleConvIm *purple_conversation_get_im_data(const PurpleConversation *conv); - -#define PURPLE_CONV_IM(c) (purple_conversation_get_im_data(c)) - -/** - * Returns the specified conversation's chat-specific data. - * - * If the conversation type is not PURPLE_CONV_TYPE_CHAT, this will return @c NULL. - * - * @param conv The conversation. - * - * @return The chat-specific data. - */ -PurpleConvChat *purple_conversation_get_chat_data(const PurpleConversation *conv); - -#define PURPLE_CONV_CHAT(c) (purple_conversation_get_chat_data(c)) - -/** - * Sets extra data for a conversation. - * - * @param conv The conversation. - * @param key The unique key. - * @param data The data to assign. - */ -void purple_conversation_set_data(PurpleConversation *conv, const char *key, - gpointer data); - -/** - * Returns extra data in a conversation. + * Writes to a conversation window. * - * @param conv The conversation. - * @param key The unqiue key. + * This function should not be used to write IM or chat messages. Use + * purple_conversation_write_message() instead. This function will + * most likely call this anyway, but it may do it's own formatting, + * sound playback, etc. depending on whether the conversation is a chat or an + * IM. * - * @return The data associated with the key. - */ -gpointer purple_conversation_get_data(PurpleConversation *conv, const char *key); - -/** - * Returns a list of all conversations. + * This can be used to write generic messages, such as "so and so closed + * the conversation window." * - * This list includes both IMs and chats. + * @param conv The conversation. + * @param who The user who sent the message. + * @param message The message. + * @param flags The message flags. + * @param mtime The time the message was sent. * - * @constreturn A GList of all conversations. + * @see purple_conversation_write_message() */ -GList *purple_get_conversations(void); +void purple_conversation_write(PurpleConversation *conv, const char *who, + const char *message, PurpleMessageFlags flags, + time_t mtime); /** - * Returns a list of all IMs. + * Writes to a chat or an IM. * - * @constreturn A GList of all IMs. + * @param conv The conversation. + * @param who The user who sent the message. + * @param message The message to write. + * @param flags The message flags. + * @param mtime The time the message was sent. */ -GList *purple_get_ims(void); +void purple_conversation_write_message(PurpleConversation *conv, + const char *who, const char *message, + PurpleMessageFlags flags, time_t mtime); /** - * Returns a list of all chats. + * Sends a message to this conversation. This function calls + * purple_conversation_send_with_flags() with no additional flags. * - * @constreturn A GList of all chats. + * @param conv The conversation. + * @param message The message to send. */ -GList *purple_get_chats(void); +void purple_conversation_send(PurpleConversation *conv, const char *message); /** - * Finds a conversation with the specified type, name, and Purple account. - * - * @param type The type of the conversation. - * @param name The name of the conversation. - * @param account The purple_account associated with the conversation. - * - * @return The conversation if found, or @c NULL otherwise. - */ -PurpleConversation *purple_find_conversation_with_account( - PurpleConversationType type, const char *name, - const PurpleAccount *account); - -/** - * Writes to a conversation window. - * - * This function should not be used to write IM or chat messages. Use - * purple_conv_im_write() and purple_conv_chat_write() instead. Those functions will - * most likely call this anyway, but they may do their own formatting, - * sound playback, etc. - * - * This can be used to write generic messages, such as "so and so closed - * the conversation window." + * Sends a message to this conversation with specified flags. * * @param conv The conversation. - * @param who The user who sent the message. - * @param message The message. - * @param flags The message flags. - * @param mtime The time the message was sent. - * - * @see purple_conv_im_write() - * @see purple_conv_chat_write() + * @param message The message to send. + * @param flags The PurpleMessageFlags flags to use in addition to + * PURPLE_MESSAGE_SEND. */ -void purple_conversation_write(PurpleConversation *conv, const char *who, - const char *message, PurpleMessageFlags flags, - time_t mtime); +void purple_conversation_send_with_flags(PurpleConversation *conv, const char *message, + PurpleMessageFlags flags); /** Set the features as supported for the given conversation. @@ -609,21 +493,14 @@ gboolean purple_conversation_has_focus(PurpleConversation *conv); * @param conv The conversation. * @param type The update type. */ -void purple_conversation_update(PurpleConversation *conv, PurpleConvUpdateType type); - -/** - * Calls a function on each conversation. - * - * @param func The function. - */ -void purple_conversation_foreach(void (*func)(PurpleConversation *conv)); +void purple_conversation_update(PurpleConversation *conv, PurpleConversationUpdateType type); /** * Retrieve the message history of a conversation. * * @param conv The conversation * - * @return A GList of PurpleConvMessage's. The must not modify the list or the data within. + * @return A GList of PurpleConversationMessage's. The must not modify the list or the data within. * The list contains the newest message at the beginning, and the oldest message at * the end. */ @@ -637,60 +514,6 @@ GList *purple_conversation_get_message_history(PurpleConversation *conv); void purple_conversation_clear_message_history(PurpleConversation *conv); /** - * Get the sender from a PurpleConvMessage - * - * @param msg A PurpleConvMessage - * - * @return The name of the sender of the message - */ -const char *purple_conversation_message_get_sender(const PurpleConvMessage *msg); - -/** - * Get the message from a PurpleConvMessage - * - * @param msg A PurpleConvMessage - * - * @return The name of the sender of the message - */ -const char *purple_conversation_message_get_message(const PurpleConvMessage *msg); - -/** - * Get the message-flags of a PurpleConvMessage - * - * @param msg A PurpleConvMessage - * - * @return The message flags - */ -PurpleMessageFlags purple_conversation_message_get_flags(const PurpleConvMessage *msg); - -/** - * Get the timestamp of a PurpleConvMessage - * - * @param msg A PurpleConvMessage - * - * @return The timestamp of the message - */ -time_t purple_conversation_message_get_timestamp(const PurpleConvMessage *msg); - -/** - * Get the alias from a PurpleConvMessage - * - * @param msg A PurpleConvMessage - * - * @return The alias of the sender of the message - */ -const char *purple_conversation_message_get_alias(const PurpleConvMessage *msg); - -/** - * Get the conversation associated with the PurpleConvMessage - * - * @param msg A PurpleConvMessage - * - * @return The conversation - */ -PurpleConversation *purple_conversation_message_get_conv(const PurpleConvMessage *msg); - -/** * Set the UI data associated with this conversation. * * @param conv The conversation. @@ -709,175 +532,6 @@ void purple_conversation_set_ui_data(PurpleConversation *conv, gpointer ui_data) */ gpointer purple_conversation_get_ui_data(const PurpleConversation *conv); -/*@}*/ - - -/**************************************************************************/ -/** @name IM Conversation API */ -/**************************************************************************/ -/*@{*/ - -/** - * Gets an IM's parent conversation. - * - * @param im The IM. - * - * @return The parent conversation. - */ -PurpleConversation *purple_conv_im_get_conversation(const PurpleConvIm *im); - -/** - * Sets the IM's buddy icon. - * - * This should only be called from within Purple. You probably want to - * call purple_buddy_icon_set_data(). - * - * @param im The IM. - * @param icon The buddy icon. - * - * @see purple_buddy_icon_set_data() - */ -void purple_conv_im_set_icon(PurpleConvIm *im, PurpleBuddyIcon *icon); - -/** - * Returns the IM's buddy icon. - * - * @param im The IM. - * - * @return The buddy icon. - */ -PurpleBuddyIcon *purple_conv_im_get_icon(const PurpleConvIm *im); - -/** - * Sets the IM's typing state. - * - * @param im The IM. - * @param state The typing state. - */ -void purple_conv_im_set_typing_state(PurpleConvIm *im, PurpleTypingState state); - -/** - * Returns the IM's typing state. - * - * @param im The IM. - * - * @return The IM's typing state. - */ -PurpleTypingState purple_conv_im_get_typing_state(const PurpleConvIm *im); - -/** - * Starts the IM's typing timeout. - * - * @param im The IM. - * @param timeout The timeout. - */ -void purple_conv_im_start_typing_timeout(PurpleConvIm *im, int timeout); - -/** - * Stops the IM's typing timeout. - * - * @param im The IM. - */ -void purple_conv_im_stop_typing_timeout(PurpleConvIm *im); - -/** - * Returns the IM's typing timeout. - * - * @param im The IM. - * - * @return The timeout. - */ -guint purple_conv_im_get_typing_timeout(const PurpleConvIm *im); - -/** - * Sets the quiet-time when no PURPLE_TYPING messages will be sent. - * Few protocols need this (maybe only MSN). If the user is still - * typing after this quiet-period, then another PURPLE_TYPING message - * will be sent. - * - * @param im The IM. - * @param val The number of seconds to wait before allowing another - * PURPLE_TYPING message to be sent to the user. Or 0 to - * not send another PURPLE_TYPING message. - */ -void purple_conv_im_set_type_again(PurpleConvIm *im, unsigned int val); - -/** - * Returns the time after which another PURPLE_TYPING message should be sent. - * - * @param im The IM. - * - * @return The time in seconds since the epoch. Or 0 if no additional - * PURPLE_TYPING message should be sent. - */ -time_t purple_conv_im_get_type_again(const PurpleConvIm *im); - -/** - * Starts the IM's type again timeout. - * - * @param im The IM. - */ -void purple_conv_im_start_send_typed_timeout(PurpleConvIm *im); - -/** - * Stops the IM's type again timeout. - * - * @param im The IM. - */ -void purple_conv_im_stop_send_typed_timeout(PurpleConvIm *im); - -/** - * Returns the IM's type again timeout interval. - * - * @param im The IM. - * - * @return The type again timeout interval. - */ -guint purple_conv_im_get_send_typed_timeout(const PurpleConvIm *im); - -/** - * Updates the visual typing notification for an IM conversation. - * - * @param im The IM. - */ -void purple_conv_im_update_typing(PurpleConvIm *im); - -/** - * Writes to an IM. - * - * @param im The IM. - * @param who The user who sent the message. - * @param message The message to write. - * @param flags The message flags. - * @param mtime The time the message was sent. - */ -void purple_conv_im_write(PurpleConvIm *im, const char *who, - const char *message, PurpleMessageFlags flags, - time_t mtime); - -/** - * Presents an IM-error to the user - * - * This is a helper function to find a conversation, write an error to it, and - * raise the window. If a conversation with this user doesn't already exist, - * the function will return FALSE and the calling function can attempt to present - * the error another way (purple_notify_error, most likely) - * - * @param who The user this error is about - * @param account The account this error is on - * @param what The error - * @return TRUE if the error was presented, else FALSE - */ -gboolean purple_conv_present_error(const char *who, PurpleAccount *account, const char *what); - -/** - * Sends a message to this IM conversation. - * - * @param im The IM. - * @param message The message to send. - */ -void purple_conv_im_send(PurpleConvIm *im, const char *message); - /** * Sends a message to a conversation after confirming with * the user. @@ -890,21 +544,12 @@ void purple_conv_im_send(PurpleConvIm *im, const char *message); * @param conv The conversation. * @param message The message to send. */ -void purple_conv_send_confirm(PurpleConversation *conv, const char *message); - -/** - * Sends a message to this IM conversation with specified flags. - * - * @param im The IM. - * @param message The message to send. - * @param flags The PurpleMessageFlags flags to use in addition to PURPLE_MESSAGE_SEND. - */ -void purple_conv_im_send_with_flags(PurpleConvIm *im, const char *message, PurpleMessageFlags flags); +void purple_conversation_send_confirm(PurpleConversation *conv, const char *message); /** * Adds a smiley to the conversation's smiley tree. If this returns - * @c TRUE you should call purple_conv_custom_smiley_write() one or more - * times, and then purple_conv_custom_smiley_close(). If this returns + * @c TRUE you should call purple_conversation_custom_smiley_write() one or more + * times, and then purple_conversation_custom_smiley_close(). If this returns * @c FALSE, either the conv or smile were invalid, or the icon was * found in the cache. In either case, calling write or close would * be an error. @@ -915,16 +560,15 @@ void purple_conv_im_send_with_flags(PurpleConvIm *im, const char *message, Purpl * @param chksum The checksum, as a NUL terminated base64 string. * @param remote @c TRUE if the custom smiley is set by the remote user (buddy). * @return @c TRUE if an icon is expected, else FALSE. Note that - * it is an error to never call purple_conv_custom_smiley_close if + * it is an error to never call purple_conversation_custom_smiley_close if * this function returns @c TRUE, but an error to call it if * @c FALSE is returned. */ -gboolean purple_conv_custom_smiley_add(PurpleConversation *conv, const char *smile, +gboolean purple_conversation_custom_smiley_add(PurpleConversation *conv, const char *smile, const char *cksum_type, const char *chksum, gboolean remote); - /** * Updates the image associated with the current smiley. * @@ -934,469 +578,134 @@ gboolean purple_conv_custom_smiley_add(PurpleConversation *conv, const char *smi * @param size The length of the data. */ -void purple_conv_custom_smiley_write(PurpleConversation *conv, +void purple_conversation_custom_smiley_write(PurpleConversation *conv, const char *smile, const guchar *data, gsize size); /** * Close the custom smiley, all data has been written with - * purple_conv_custom_smiley_write, and it is no longer valid + * purple_conversation_custom_smiley_write, and it is no longer valid * to call that function on that smiley. * * @param conv The purple conversation associated with the smiley. * @param smile The text associated with the smiley */ -void purple_conv_custom_smiley_close(PurpleConversation *conv, const char *smile); - -/*@}*/ - - -/**************************************************************************/ -/** @name Chat Conversation API */ -/**************************************************************************/ -/*@{*/ - -/** - * Gets a chat's parent conversation. - * - * @param chat The chat. - * - * @return The parent conversation. - */ -PurpleConversation *purple_conv_chat_get_conversation(const PurpleConvChat *chat); - -/** - * Returns a list of users in the chat room. The members of the list - * are PurpleConvChatBuddy objects. - * - * @param chat The chat. - * - * @constreturn The list of users. - */ -GList *purple_conv_chat_get_users(const PurpleConvChat *chat); - -/** - * Ignores a user in a chat room. - * - * @param chat The chat. - * @param name The name of the user. - */ -void purple_conv_chat_ignore(PurpleConvChat *chat, const char *name); - -/** - * Unignores a user in a chat room. - * - * @param chat The chat. - * @param name The name of the user. - */ -void purple_conv_chat_unignore(PurpleConvChat *chat, const char *name); - -/** - * Sets the list of ignored users in the chat room. - * - * @param chat The chat. - * @param ignored The list of ignored users. - * - * @return The list passed. - */ -GList *purple_conv_chat_set_ignored(PurpleConvChat *chat, GList *ignored); - -/** - * Returns the list of ignored users in the chat room. - * - * @param chat The chat. - * - * @constreturn The list of ignored users. - */ -GList *purple_conv_chat_get_ignored(const PurpleConvChat *chat); - -/** - * Returns the actual name of the specified ignored user, if it exists in - * the ignore list. - * - * If the user found contains a prefix, such as '+' or '\@', this is also - * returned. The username passed to the function does not have to have this - * formatting. - * - * @param chat The chat. - * @param user The user to check in the ignore list. - * - * @return The ignored user if found, complete with prefixes, or @c NULL - * if not found. - */ -const char *purple_conv_chat_get_ignored_user(const PurpleConvChat *chat, - const char *user); - -/** - * Returns @c TRUE if the specified user is ignored. - * - * @param chat The chat. - * @param user The user. - * - * @return @c TRUE if the user is in the ignore list; @c FALSE otherwise. - */ -gboolean purple_conv_chat_is_user_ignored(const PurpleConvChat *chat, - const char *user); - -/** - * Sets the chat room's topic. - * - * @param chat The chat. - * @param who The user that set the topic. - * @param topic The topic. - */ -void purple_conv_chat_set_topic(PurpleConvChat *chat, const char *who, - const char *topic); - -/** - * Returns the chat room's topic. - * - * @param chat The chat. - * - * @return The chat's topic. - */ -const char *purple_conv_chat_get_topic(const PurpleConvChat *chat); - -/** - * Sets the chat room's ID. - * - * @param chat The chat. - * @param id The ID. - */ -void purple_conv_chat_set_id(PurpleConvChat *chat, int id); - -/** - * Returns the chat room's ID. - * - * @param chat The chat. - * - * @return The ID. - */ -int purple_conv_chat_get_id(const PurpleConvChat *chat); - -/** - * Writes to a chat. - * - * @param chat The chat. - * @param who The user who sent the message. - * @param message The message to write. - * @param flags The flags. - * @param mtime The time the message was sent. - */ -void purple_conv_chat_write(PurpleConvChat *chat, const char *who, - const char *message, PurpleMessageFlags flags, - time_t mtime); - -/** - * Sends a message to this chat conversation. - * - * @param chat The chat. - * @param message The message to send. - */ -void purple_conv_chat_send(PurpleConvChat *chat, const char *message); - -/** - * Sends a message to this chat conversation with specified flags. - * - * @param chat The chat. - * @param message The message to send. - * @param flags The PurpleMessageFlags flags to use. - */ -void purple_conv_chat_send_with_flags(PurpleConvChat *chat, const char *message, PurpleMessageFlags flags); - -/** - * Adds a user to a chat. - * - * @param chat The chat. - * @param user The user to add. - * @param extra_msg An extra message to display with the join message. - * @param flags The users flags - * @param new_arrival Decides whether or not to show a join notice. - */ -void purple_conv_chat_add_user(PurpleConvChat *chat, const char *user, - const char *extra_msg, PurpleConvChatBuddyFlags flags, - gboolean new_arrival); - -/** - * Adds a list of users to a chat. - * - * The data is copied from @a users, @a extra_msgs, and @a flags, so it is up to - * the caller to free this list after calling this function. - * - * @param chat The chat. - * @param users The list of users to add. - * @param extra_msgs An extra message to display with the join message for each - * user. This list may be shorter than @a users, in which - * case, the users after the end of extra_msgs will not have - * an extra message. By extension, this means that extra_msgs - * can simply be @c NULL and none of the users will have an - * extra message. - * @param flags The list of flags for each user. - * @param new_arrivals Decides whether or not to show join notices. - */ -void purple_conv_chat_add_users(PurpleConvChat *chat, GList *users, GList *extra_msgs, - GList *flags, gboolean new_arrivals); - -/** - * Renames a user in a chat. - * - * @param chat The chat. - * @param old_user The old username. - * @param new_user The new username. - */ -void purple_conv_chat_rename_user(PurpleConvChat *chat, const char *old_user, - const char *new_user); - -/** - * Removes a user from a chat, optionally with a reason. - * - * It is up to the developer to free this list after calling this function. - * - * @param chat The chat. - * @param user The user that is being removed. - * @param reason The optional reason given for the removal. Can be @c NULL. - */ -void purple_conv_chat_remove_user(PurpleConvChat *chat, const char *user, - const char *reason); - -/** - * Removes a list of users from a chat, optionally with a single reason. - * - * @param chat The chat. - * @param users The users that are being removed. - * @param reason The optional reason given for the removal. Can be @c NULL. - */ -void purple_conv_chat_remove_users(PurpleConvChat *chat, GList *users, - const char *reason); - -/** - * Finds a user in a chat - * - * @param chat The chat. - * @param user The user to look for. - * - * @return TRUE if the user is in the chat, FALSE if not - */ -gboolean purple_conv_chat_find_user(PurpleConvChat *chat, const char *user); - -/** - * Set a users flags in a chat - * - * @param chat The chat. - * @param user The user to update. - * @param flags The new flags. - */ -void purple_conv_chat_user_set_flags(PurpleConvChat *chat, const char *user, - PurpleConvChatBuddyFlags flags); - -/** - * Get the flags for a user in a chat - * - * @param chat The chat. - * @param user The user to find the flags for - * - * @return The flags for the user - */ -PurpleConvChatBuddyFlags purple_conv_chat_user_get_flags(PurpleConvChat *chat, - const char *user); - -/** - * Clears all users from a chat. - * - * @param chat The chat. - */ -void purple_conv_chat_clear_users(PurpleConvChat *chat); +void purple_conversation_custom_smiley_close(PurpleConversation *conv, const char *smile); /** - * Sets your nickname (used for hilighting) for a chat. + * Retrieves the extended menu items for the conversation. * - * @param chat The chat. - * @param nick The nick. - */ -void purple_conv_chat_set_nick(PurpleConvChat *chat, const char *nick); - -/** - * Gets your nickname (used for hilighting) for a chat. + * @param conv The conversation. * - * @param chat The chat. - * @return The nick. + * @return A list of PurpleMenuAction items, harvested by the + * chat-extended-menu signal. The list and the menuaction + * items should be freed by the caller. */ -const char *purple_conv_chat_get_nick(PurpleConvChat *chat); +GList * purple_conversation_get_extended_menu(PurpleConversation *conv); /** - * Finds a chat with the specified chat ID. - * - * @param gc The purple_connection. - * @param id The chat ID. + * Perform a command in a conversation. Similar to @see purple_cmd_do_command * - * @return The chat conversation. - */ -PurpleConversation *purple_find_chat(const PurpleConnection *gc, int id); - -/** - * Lets the core know we left a chat, without destroying it. - * Called from serv_got_chat_left(). + * @param conv The conversation. + * @param cmdline The entire command including the arguments. + * @param markup @c NULL, or the formatted command line. + * @param error If the command failed errormsg is filled in with the appropriate error + * message, if not @c NULL. It must be freed by the caller with g_free(). * - * @param chat The chat. + * @return @c TRUE if the command was executed successfully, @c FALSE otherwise. */ -void purple_conv_chat_left(PurpleConvChat *chat); +gboolean purple_conversation_do_command(PurpleConversation *conv, + const gchar *cmdline, const gchar *markup, gchar **error); -/** - * Invite a user to a chat. - * The user will be prompted to enter the user's name or a message if one is - * not given. - * - * @param chat The chat. - * @param user The user to invite to the chat. - * @param message The message to send with the invitation. - * @param confirm Prompt before sending the invitation. The user is always - * prompted if either \a user or \a message is @c NULL. - */ -void purple_conv_chat_invite_user(PurpleConvChat *chat, const char *user, - const char *message, gboolean confirm); +/*@}*/ -/** - * Returns true if we're no longer in this chat, - * and just left the window open. - * - * @param chat The chat. - * - * @return @c TRUE if we left the chat already, @c FALSE if - * we're still there. - */ -gboolean purple_conv_chat_has_left(PurpleConvChat *chat); +/**************************************************************************/ +/** @name Conversation Helper API */ +/**************************************************************************/ +/*@{*/ /** - * Creates a new chat buddy + * Presents an IM-error to the user * - * @param name The name. - * @param alias The alias. - * @param flags The flags. + * This is a helper function to find a conversation, write an error to it, and + * raise the window. If a conversation with this user doesn't already exist, + * the function will return FALSE and the calling function can attempt to present + * the error another way (purple_notify_error, most likely) * - * @return The new chat buddy + * @param who The user this error is about + * @param account The account this error is on + * @param what The error + * @return TRUE if the error was presented, else FALSE */ -PurpleConvChatBuddy *purple_conv_chat_cb_new(const char *name, const char *alias, - PurpleConvChatBuddyFlags flags); +gboolean purple_conversation_present_error(const char *who, PurpleAccount *account, const char *what); -/** - * Find a chat buddy in a chat - * - * @param chat The chat. - * @param name The name of the chat buddy to find. - */ -PurpleConvChatBuddy *purple_conv_chat_cb_find(PurpleConvChat *chat, const char *name); +/*@}*/ -/** - * Set the UI data associated with this chat buddy. - * - * @param cb The chat buddy - * @param ui_data A pointer to associate with this chat buddy. - */ -void purple_conv_chat_cb_set_ui_data(PurpleConvChatBuddy *cb, gpointer ui_data); +/**************************************************************************/ +/** @name Conversation Message API */ +/**************************************************************************/ +/*@{*/ /** - * Get the UI data associated with this chat buddy. - * - * @param cb The chat buddy. - * - * @return The UI data associated with this chat buddy. This is a - * convenience field provided to the UIs--it is not - * used by the libpurple core. + * Returns the GType for the PurpleConversationMessage boxed structure. */ -gpointer purple_conv_chat_cb_get_ui_data(const PurpleConvChatBuddy *conv); +GType purple_conversation_message_get_type(void); /** - * Get the alias of a chat buddy + * Get the sender from a PurpleConversationMessage * - * @param cb The chat buddy. + * @param msg A PurpleConversationMessage * - * @return The alias of the chat buddy. + * @return The name of the sender of the message */ -const char *purple_conv_chat_cb_get_alias(const PurpleConvChatBuddy *cb); +const char *purple_conversation_message_get_sender(const PurpleConversationMessage *msg); /** - * Get the name of a chat buddy + * Get the message from a PurpleConversationMessage * - * @param cb The chat buddy. + * @param msg A PurpleConversationMessage * - * @return The name of the chat buddy. + * @return The name of the sender of the message */ -const char *purple_conv_chat_cb_get_name(const PurpleConvChatBuddy *cb); +const char *purple_conversation_message_get_message(const PurpleConversationMessage *msg); /** - * Get the flags of a chat buddy. + * Get the message-flags of a PurpleConversationMessage * - * @param cb The chat buddy. + * @param msg A PurpleConversationMessage * - * @return The flags of the chat buddy. + * @return The message flags */ -PurpleConvChatBuddyFlags purple_conv_chat_cb_get_flags(const PurpleConvChatBuddy *cb); +PurpleMessageFlags purple_conversation_message_get_flags(const PurpleConversationMessage *msg); /** - * Indicates if this chat buddy is on the buddy list. + * Get the timestamp of a PurpleConversationMessage * - * @param cb The chat buddy. + * @param msg A PurpleConversationMessage * - * @return TRUE if the chat buddy is on the buddy list. + * @return The timestamp of the message */ -gboolean purple_conv_chat_cb_is_buddy(const PurpleConvChatBuddy *cb); +time_t purple_conversation_message_get_timestamp(const PurpleConversationMessage *msg); /** - * Destroys a chat buddy + * Get the alias from a PurpleConversationMessage * - * @param cb The chat buddy to destroy - */ -void purple_conv_chat_cb_destroy(PurpleConvChatBuddy *cb); - -/** - * Retrieves the extended menu items for the conversation. + * @param msg A PurpleConversationMessage * - * @param conv The conversation. - * - * @return A list of PurpleMenuAction items, harvested by the - * chat-extended-menu signal. The list and the menuaction - * items should be freed by the caller. + * @return The alias of the sender of the message */ -GList * purple_conversation_get_extended_menu(PurpleConversation *conv); +const char *purple_conversation_message_get_alias(const PurpleConversationMessage *msg); /** - * Perform a command in a conversation. Similar to @see purple_cmd_do_command + * Get the conversation associated with the PurpleConversationMessage * - * @param conv The conversation. - * @param cmdline The entire command including the arguments. - * @param markup @c NULL, or the formatted command line. - * @param error If the command failed errormsg is filled in with the appropriate error - * message, if not @c NULL. It must be freed by the caller with g_free(). - * - * @return @c TRUE if the command was executed successfully, @c FALSE otherwise. - */ -gboolean purple_conversation_do_command(PurpleConversation *conv, const gchar *cmdline, const gchar *markup, gchar **error); - -/*@}*/ - -/**************************************************************************/ -/** @name Conversations Subsystem */ -/**************************************************************************/ -/*@{*/ - -/** - * Returns the conversation subsystem handle. + * @param msg A PurpleConversationMessage * - * @return The conversation subsystem handle. - */ -void *purple_conversations_get_handle(void); - -/** - * Initializes the conversation subsystem. - */ -void purple_conversations_init(void); - -/** - * Uninitializes the conversation subsystem. + * @return The conversation */ -void purple_conversations_uninit(void); +PurpleConversation *purple_conversation_message_get_conversation(const PurpleConversationMessage *msg); /*@}*/ diff --git a/libpurple/conversations.c b/libpurple/conversations.c new file mode 100644 index 0000000000..0a3ded060e --- /dev/null +++ b/libpurple/conversations.c @@ -0,0 +1,478 @@ +/* + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#include "internal.h" +#include "conversations.h" + +static GList *conversations = NULL; +static GList *ims = NULL; +static GList *chats = NULL; +static PurpleConversationUiOps *default_ops = NULL; + +/** + * A hash table used for efficient lookups of conversations by name. + * struct _purple_hconv => PurpleConversation* + */ +static GHashTable *conversation_cache = NULL; + +struct _purple_hconv { + gboolean im; + char *name; + const PurpleAccount *account; +}; + +static guint +_purple_conversations_hconv_hash(struct _purple_hconv *hc) +{ + return g_str_hash(hc->name) ^ hc->im ^ g_direct_hash(hc->account); +} + +static guint +_purple_conversations_hconv_equal(struct _purple_hconv *hc1, struct _purple_hconv *hc2) +{ + return (hc1->im == hc2->im && + hc1->account == hc2->account && + g_str_equal(hc1->name, hc2->name)); +} + +static void +_purple_conversations_hconv_free_key(struct _purple_hconv *hc) +{ + g_free(hc->name); + g_free(hc); +} + +void +purple_conversations_add(PurpleConversation *conv) +{ + PurpleAccount *account; + struct _purple_hconv *hc; + + g_return_if_fail(conv != NULL); + + if (g_list_find(conversations, conv) != NULL) + return; + + conversations = g_list_prepend(conversations, conv); + + if (PURPLE_IS_IM_CONVERSATION(conv)) + ims = g_list_prepend(ims, conv); + else + chats = g_list_prepend(chats, conv); + + account = purple_conversation_get_account(conv); + + hc = g_new(struct _purple_hconv, 1); + hc->name = g_strdup(purple_normalize(account, + purple_conversation_get_name(conv))); + hc->account = account; + hc->im = PURPLE_IS_IM_CONVERSATION(conv); + + g_hash_table_insert(conversation_cache, hc, conv); +} + +void +purple_conversations_remove(PurpleConversation *conv) +{ + PurpleAccount *account; + struct _purple_hconv hc; + + g_return_if_fail(conv != NULL); + + conversations = g_list_remove(conversations, conv); + + if (PURPLE_IS_IM_CONVERSATION(conv)) + ims = g_list_remove(ims, conv); + else + chats = g_list_remove(chats, conv); + + account = purple_conversation_get_account(conv); + + hc.name = (gchar *)purple_normalize(account, + purple_conversation_get_name(conv)); + hc.account = account; + hc.im = PURPLE_IS_IM_CONVERSATION(conv); + + g_hash_table_remove(conversation_cache, &hc); +} + +void +purple_conversations_update_cache(PurpleConversation *conv, const char *name, + PurpleAccount *account) +{ + PurpleAccount *old_account; + struct _purple_hconv *hc; + + g_return_if_fail(conv != NULL); + g_return_if_fail(account != NULL || name != NULL); + + old_account = purple_conversation_get_account(conv); + + hc = g_new(struct _purple_hconv, 1); + hc->im = PURPLE_IS_IM_CONVERSATION(conv); + hc->account = old_account; + hc->name = (gchar *)purple_normalize(old_account, + purple_conversation_get_name(conv)); + + g_hash_table_remove(conversation_cache, hc); + + if (account) + hc->account = account; + if (name) + hc->name = g_strdup(purple_normalize(account, name)); + + g_hash_table_insert(conversation_cache, hc, conv); +} + +GList * +purple_conversations_get_all(void) +{ + return conversations; +} + +GList * +purple_conversations_get_ims(void) +{ + return ims; +} + +GList * +purple_conversations_get_chats(void) +{ + return chats; +} + +PurpleConversation * +purple_conversations_find_with_account(const char *name, + const PurpleAccount *account) +{ + PurpleConversation *c = NULL; + struct _purple_hconv hc; + + g_return_val_if_fail(name != NULL, NULL); + + hc.name = (gchar *)purple_normalize(account, name); + hc.account = account; + + hc.im = TRUE; + c = g_hash_table_lookup(conversation_cache, &hc); + if (!c) { + hc.im = FALSE; + c = g_hash_table_lookup(conversation_cache, &hc); + } + + return c; +} + +PurpleIMConversation * +purple_conversations_find_im_with_account(const char *name, + const PurpleAccount *account) +{ + PurpleIMConversation *im = NULL; + struct _purple_hconv hc; + + g_return_val_if_fail(name != NULL, NULL); + + hc.name = (gchar *)purple_normalize(account, name); + hc.account = account; + hc.im = TRUE; + + im = g_hash_table_lookup(conversation_cache, &hc); + + return im; +} + +PurpleChatConversation * +purple_conversations_find_chat_with_account(const char *name, + const PurpleAccount *account) +{ + PurpleChatConversation *c = NULL; + struct _purple_hconv hc; + + g_return_val_if_fail(name != NULL, NULL); + + hc.name = (gchar *)purple_normalize(account, name); + hc.account = account; + hc.im = FALSE; + + c = g_hash_table_lookup(conversation_cache, &hc); + + return c; +} + +PurpleChatConversation * +purple_conversations_find_chat(const PurpleConnection *gc, int id) +{ + GList *l; + PurpleChatConversation *chat; + + for (l = purple_conversations_get_chats(); l != NULL; l = l->next) { + chat = (PurpleChatConversation *)l->data; + + if (purple_chat_conversation_get_id(chat) == id && + purple_conversation_get_connection(PURPLE_CONVERSATION(chat)) == gc) + return chat; + } + + return NULL; +} + +void +purple_conversations_set_ui_ops(PurpleConversationUiOps *ops) +{ + default_ops = ops; +} + +PurpleConversationUiOps * +purple_conversations_get_ui_ops(void) +{ + return default_ops; +} + +void * +purple_conversations_get_handle(void) +{ + static int handle; + + return &handle; +} + +void +purple_conversations_init(void) +{ + void *handle = purple_conversations_get_handle(); + + conversation_cache = g_hash_table_new_full((GHashFunc)_purple_conversations_hconv_hash, + (GEqualFunc)_purple_conversations_hconv_equal, + (GDestroyNotify)_purple_conversations_hconv_free_key, NULL); + + /********************************************************************** + * Register preferences + **********************************************************************/ + + /* Conversations */ + purple_prefs_add_none("/purple/conversations"); + + /* Conversations -> Chat */ + purple_prefs_add_none("/purple/conversations/chat"); + purple_prefs_add_bool("/purple/conversations/chat/show_nick_change", TRUE); + + /* Conversations -> IM */ + purple_prefs_add_none("/purple/conversations/im"); + purple_prefs_add_bool("/purple/conversations/im/send_typing", TRUE); + + + /********************************************************************** + * Register signals + **********************************************************************/ + purple_signal_register(handle, "writing-im-msg", + purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_UINT, + G_TYPE_BOOLEAN, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_POINTER, /* pointer to a string */ + PURPLE_TYPE_CONVERSATION, G_TYPE_UINT); + + purple_signal_register(handle, "wrote-im-msg", + purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, + G_TYPE_NONE, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_STRING, PURPLE_TYPE_CONVERSATION, G_TYPE_UINT); + + purple_signal_register(handle, "sent-attention", + purple_marshal_VOID__POINTER_POINTER_POINTER_UINT, + G_TYPE_NONE, 4, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + PURPLE_TYPE_CONVERSATION, G_TYPE_UINT); + + purple_signal_register(handle, "got-attention", + purple_marshal_VOID__POINTER_POINTER_POINTER_UINT, + G_TYPE_NONE, 4, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + PURPLE_TYPE_CONVERSATION, G_TYPE_UINT); + + purple_signal_register(handle, "sending-im-msg", + purple_marshal_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_POINTER); /* pointer to a string */ + + purple_signal_register(handle, "sent-im-msg", + purple_marshal_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_STRING); + + purple_signal_register(handle, "receiving-im-msg", + purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, + G_TYPE_BOOLEAN, 5, PURPLE_TYPE_ACCOUNT, + G_TYPE_POINTER, /* pointer to a string */ + G_TYPE_POINTER, /* pointer to a string */ + PURPLE_TYPE_CONVERSATION, + G_TYPE_POINTER); /* pointer to a string */ + + purple_signal_register(handle, "received-im-msg", + purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, + G_TYPE_NONE, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_STRING, PURPLE_TYPE_CONVERSATION, G_TYPE_UINT); + + purple_signal_register(handle, "blocked-im-msg", + purple_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT, + G_TYPE_NONE, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT); + + purple_signal_register(handle, "writing-chat-msg", + purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_UINT, + G_TYPE_BOOLEAN, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_POINTER, /* pointer to a string */ + PURPLE_TYPE_CONVERSATION, G_TYPE_UINT); + + purple_signal_register(handle, "wrote-chat-msg", + purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, + G_TYPE_NONE, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_STRING, PURPLE_TYPE_CONVERSATION, G_TYPE_UINT); + + purple_signal_register(handle, "sending-chat-msg", + purple_marshal_VOID__POINTER_POINTER_UINT, G_TYPE_NONE, + 3, PURPLE_TYPE_ACCOUNT, + G_TYPE_POINTER, /* pointer to a string */ + G_TYPE_UINT); + + purple_signal_register(handle, "sent-chat-msg", + purple_marshal_VOID__POINTER_POINTER_UINT, G_TYPE_NONE, + 3, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, G_TYPE_UINT); + + purple_signal_register(handle, "receiving-chat-msg", + purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, + G_TYPE_BOOLEAN, 5, PURPLE_TYPE_ACCOUNT, + G_TYPE_POINTER, /* pointer to a string */ + G_TYPE_POINTER, /* pointer to a string */ + PURPLE_TYPE_CONVERSATION, + G_TYPE_POINTER); /* pointer to an unsigned int */ + + purple_signal_register(handle, "received-chat-msg", + purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, + G_TYPE_NONE, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_STRING, PURPLE_TYPE_CONVERSATION, G_TYPE_UINT); + + purple_signal_register(handle, "conversation-created", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_CONVERSATION); + + purple_signal_register(handle, "conversation-updated", + purple_marshal_VOID__POINTER_UINT, G_TYPE_NONE, 2, + PURPLE_TYPE_CONVERSATION, G_TYPE_UINT); + + purple_signal_register(handle, "deleting-conversation", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_CONVERSATION); + + purple_signal_register(handle, "buddy-typing", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_ACCOUNT, G_TYPE_STRING); + + purple_signal_register(handle, "buddy-typed", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_ACCOUNT, G_TYPE_STRING); + + purple_signal_register(handle, "buddy-typing-stopped", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_ACCOUNT, G_TYPE_STRING); + + purple_signal_register(handle, "chat-user-joining", + purple_marshal_BOOLEAN__POINTER_POINTER_UINT, + G_TYPE_BOOLEAN, 3, PURPLE_TYPE_CONVERSATION, + G_TYPE_STRING, G_TYPE_UINT); + + purple_signal_register(handle, "chat-user-joined", + purple_marshal_VOID__POINTER_POINTER_UINT_UINT, + G_TYPE_NONE, 4, PURPLE_TYPE_CONVERSATION, + G_TYPE_STRING, G_TYPE_UINT, G_TYPE_BOOLEAN); + + purple_signal_register(handle, "chat-user-flags", + purple_marshal_VOID__POINTER_UINT_UINT, G_TYPE_NONE, 3, + PURPLE_TYPE_CHAT_USER, G_TYPE_UINT, G_TYPE_UINT); + + purple_signal_register(handle, "chat-user-leaving", + purple_marshal_BOOLEAN__POINTER_POINTER_POINTER, + G_TYPE_BOOLEAN, 3, PURPLE_TYPE_CONVERSATION, + G_TYPE_STRING, G_TYPE_STRING); + + purple_signal_register(handle, "chat-user-left", + purple_marshal_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, PURPLE_TYPE_CONVERSATION, + G_TYPE_STRING, G_TYPE_STRING); + + purple_signal_register(handle, "deleting-chat-user", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_CHAT_USER); + + purple_signal_register(handle, "chat-inviting-user", + purple_marshal_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, PURPLE_TYPE_CONVERSATION, + G_TYPE_STRING, + G_TYPE_POINTER); /* pointer to a string */ + + purple_signal_register(handle, "chat-invited-user", + purple_marshal_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, PURPLE_TYPE_CONVERSATION, + G_TYPE_STRING, G_TYPE_STRING); + + purple_signal_register(handle, "chat-invited", + purple_marshal_INT__POINTER_POINTER_POINTER_POINTER_POINTER, + G_TYPE_INT, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); + + purple_signal_register(handle, "chat-invite-blocked", + purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_POINTER, + G_TYPE_NONE, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER); /* (GHashTable *) */ + + purple_signal_register(handle, "chat-joined", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_CONVERSATION); + + purple_signal_register(handle, "chat-join-failed", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_CONNECTION, G_TYPE_POINTER); + + purple_signal_register(handle, "chat-left", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_CONVERSATION); + + purple_signal_register(handle, "chat-topic-changed", + purple_marshal_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, PURPLE_TYPE_CONVERSATION, + G_TYPE_STRING, G_TYPE_STRING); + + purple_signal_register(handle, "cleared-message-history", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_CONVERSATION); + + purple_signal_register(handle, "conversation-extended-menu", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_CONVERSATION, + G_TYPE_POINTER); /* (GList **) */ +} + +void +purple_conversations_uninit(void) +{ + while (conversations) + g_object_unref(G_OBJECT(conversations->data)); + + g_hash_table_destroy(conversation_cache); + purple_signals_unregister_by_instance(purple_conversations_get_handle()); +} diff --git a/libpurple/conversations.h b/libpurple/conversations.h new file mode 100644 index 0000000000..395e88bda1 --- /dev/null +++ b/libpurple/conversations.h @@ -0,0 +1,167 @@ +/** + * @file conversations.h Conversations subsystem API + * @ingroup core + * @see @ref conversation-signals + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef _PURPLE_CONVERSATIONS_H_ +#define _PURPLE_CONVERSATIONS_H_ + +#include "conversationtypes.h" +#include "server.h" + +G_BEGIN_DECLS + +/**************************************************************************/ +/** @name Conversations Subsystem */ +/**************************************************************************/ +/*@{*/ + +/** + * Adds a conversation to the list of conversations. + * + * @param conv The conversation. + */ +void purple_conversations_add(PurpleConversation *conv); + +/** + * Removes a conversation from the list of conversations. + * + * @param conv The conversation. + */ +void purple_conversations_remove(PurpleConversation *conv); + +/** + * Updates the conversation cache to use a new conversation name and/or + * account. This function only updates the conversation cache. It is the + * caller's responsibility to actually update the conversation. + * + * @param conv The conversation. + * @param name The new name. If no change, use @c NULL. + * @param account The new account. If no change, use @c NULL. + */ +void purple_conversations_update_cache(PurpleConversation *conv, + const char *name, PurpleAccount *account); + +/** + * Returns a list of all conversations. + * + * This list includes both IMs and chats. + * + * @constreturn A GList of all conversations. + */ +GList *purple_conversations_get_all(void); + +/** + * Returns a list of all IMs. + * + * @constreturn A GList of all IMs. + */ +GList *purple_conversations_get_ims(void); + +/** + * Returns a list of all chats. + * + * @constreturn A GList of all chats. + */ +GList *purple_conversations_get_chats(void); + +/** + * Finds a conversation of any type with the specified name and Purple account. + * + * @param name The name of the conversation. + * @param account The purple_account associated with the conversation. + * + * @return The conversation if found, or @c NULL otherwise. + */ +PurpleConversation *purple_conversations_find_with_account(const char *name, + const PurpleAccount *account); + +/** + * Finds an IM with the specified name and Purple account. + * + * @param name The name of the conversation. + * @param account The purple_account associated with the conversation. + * + * @return The conversation if found, or @c NULL otherwise. + */ +PurpleIMConversation *purple_conversations_find_im_with_account(const char *name, + const PurpleAccount *account); + +/** + * Finds a chat with the specified name and Purple account. + * + * @param name The name of the conversation. + * @param account The purple_account associated with the conversation. + * + * @return The conversation if found, or @c NULL otherwise. + */ +PurpleChatConversation *purple_conversations_find_chat_with_account(const char *name, + const PurpleAccount *account); + +/** + * Finds a chat with the specified chat ID. + * + * @param gc The purple_connection. + * @param id The chat ID. + * + * @return The chat conversation. + */ +PurpleChatConversation *purple_conversations_find_chat(const PurpleConnection *gc, int id); + +/** + * Sets the default conversation UI operations structure. + * + * @param ops The UI conversation operations structure. + */ +void purple_conversations_set_ui_ops(PurpleConversationUiOps *ops); + +/** + * Gets the default conversation UI operations structure. + * + * @return The UI conversation operations structure. + */ +PurpleConversationUiOps *purple_conversations_get_ui_ops(void); + +/** + * Returns the conversation subsystem handle. + * + * @return The conversation subsystem handle. + */ +void *purple_conversations_get_handle(void); + +/** + * Initializes the conversation subsystem. + */ +void purple_conversations_init(void); + +/** + * Uninitializes the conversation subsystem. + */ +void purple_conversations_uninit(void); + +/*@}*/ + +G_END_DECLS + +#endif /* _PURPLE_CONVERSATIONS_H_ */ diff --git a/libpurple/conversationtypes.c b/libpurple/conversationtypes.c new file mode 100644 index 0000000000..2291b57fe3 --- /dev/null +++ b/libpurple/conversationtypes.c @@ -0,0 +1,1999 @@ +/* + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#include "internal.h" +#include "conversationtypes.h" +#include "dbus-maybe.h" +#include "debug.h" +#include "enums.h" + +#define SEND_TYPED_TIMEOUT_SECONDS 5 + +#define PURPLE_CHAT_CONVERSATION_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_CHAT_CONVERSATION, PurpleChatConversationPrivate)) + +/** @copydoc _PurpleChatConversationPrivate */ +typedef struct _PurpleChatConversationPrivate PurpleChatConversationPrivate; + +#define PURPLE_IM_CONVERSATION_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_IM_CONVERSATION, PurpleIMConversationPrivate)) + +/** @copydoc _PurpleIMConversationPrivate */ +typedef struct _PurpleIMConversationPrivate PurpleIMConversationPrivate; + +#define PURPLE_CHAT_USER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_CHAT_USER, PurpleChatUserPrivate)) + +/** @copydoc _PurpleChatUserPrivate */ +typedef struct _PurpleChatUserPrivate PurpleChatUserPrivate; + +/** + * Data specific to Chats. + */ +struct _PurpleChatConversationPrivate +{ + GList *in_room; /**< The users in the room. + @deprecated Will be removed in 3.0.0 TODO */ + GList *ignored; /**< Ignored users. */ + char *who; /**< The person who set the topic. */ + char *topic; /**< The topic. */ + int id; /**< The chat ID. */ + char *nick; /**< Your nick in this chat. */ + gboolean left; /**< We left the chat and kept the window open */ + GHashTable *users; /**< Hash table of the users in the room. */ +}; + +/* Chat Property enums */ +enum { + CHAT_PROP_0, + CHAT_PROP_TOPIC_WHO, + CHAT_PROP_TOPIC, + CHAT_PROP_ID, + CHAT_PROP_NICK, + CHAT_PROP_LEFT, + CHAT_PROP_LAST +}; + +/** + * Data specific to Instant Messages. + */ +struct _PurpleIMConversationPrivate +{ + PurpleIMTypingState typing_state; /**< The current typing state. */ + guint typing_timeout; /**< The typing timer handle. */ + time_t type_again; /**< The type again time. */ + guint send_typed_timeout; /**< The type again timer handle. */ + PurpleBuddyIcon *icon; /**< The buddy icon. */ +}; + +/* IM Property enums */ +enum { + IM_PROP_0, + IM_PROP_TYPING_STATE, + IM_PROP_ICON, + IM_PROP_LAST +}; + +/** + * Data for "Chat Buddies" + */ +struct _PurpleChatUserPrivate +{ + PurpleChatConversation *chat; /**< The chat */ + char *name; /**< The chat participant's name in the + chat. */ + char *alias; /**< The chat participant's alias, if known; + @a NULL otherwise. */ + char *alias_key; /**< A string by which this user will be + sorted, or @c NULL if the user should be + sorted by its @c name. + (This is currently always @c NULL. */ + gboolean buddy; /**< @a TRUE if this chat participant is on + the buddy list; @a FALSE otherwise. */ + PurpleChatUserFlags flags; /**< A bitwise OR of flags for this + participant, such as whether they + are a channel operator. */ +}; + +/* Chat User Property enums */ +enum { + CU_PROP_0, + CU_PROP_CHAT, + CU_PROP_NAME, + CU_PROP_ALIAS, + CU_PROP_BUDDY, + CU_PROP_FLAGS, + CU_PROP_LAST +}; + +static PurpleConversationClass *parent_class; +static GObjectClass *cb_parent_class; + +static int purple_chat_user_compare(PurpleChatUser *a, + PurpleChatUser *b); + +/************************************************************************** + * IM Conversation API + **************************************************************************/ +static gboolean +reset_typing_cb(gpointer data) +{ + PurpleIMConversation *im = (PurpleIMConversation *)data; + + purple_im_conversation_set_typing_state(im, PURPLE_IM_NOT_TYPING); + purple_im_conversation_stop_typing_timeout(im); + + return FALSE; +} + +static gboolean +send_typed_cb(gpointer data) +{ + PurpleIMConversation *im = (PurpleIMConversation *)data; + PurpleConnection *gc; + const char *name; + + g_return_val_if_fail(im != NULL, FALSE); + + gc = purple_conversation_get_connection(PURPLE_CONVERSATION(im)); + name = purple_conversation_get_name(PURPLE_CONVERSATION(im)); + + if (gc != NULL && name != NULL) { + /* We set this to 1 so that PURPLE_IM_TYPING will be sent + * if the Purple user types anything else. + */ + purple_im_conversation_set_type_again(im, 1); + + serv_send_typing(gc, name, PURPLE_IM_TYPED); + + purple_debug(PURPLE_DEBUG_MISC, "conversation", "typed...\n"); + } + + return FALSE; +} + +void +purple_im_conversation_set_icon(PurpleIMConversation *im, PurpleBuddyIcon *icon) +{ + PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im); + + g_return_if_fail(priv != NULL); + + if (priv->icon != icon) + { + purple_buddy_icon_unref(priv->icon); + + priv->icon = (icon == NULL ? NULL : purple_buddy_icon_ref(icon)); + } + + purple_conversation_update(PURPLE_CONVERSATION(im), + PURPLE_CONVERSATION_UPDATE_ICON); +} + +PurpleBuddyIcon * +purple_im_conversation_get_icon(const PurpleIMConversation *im) +{ + PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->icon; +} + +void +purple_im_conversation_set_typing_state(PurpleIMConversation *im, PurpleIMTypingState state) +{ + PurpleAccount *account; + const char *name; + PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im); + + g_return_if_fail(priv != NULL); + + name = purple_conversation_get_name(PURPLE_CONVERSATION(im)); + account = purple_conversation_get_account(PURPLE_CONVERSATION(im)); + + if (priv->typing_state != state) + { + priv->typing_state = state; + + switch (state) + { + case PURPLE_IM_TYPING: + purple_signal_emit(purple_conversations_get_handle(), + "buddy-typing", account, name); + break; + case PURPLE_IM_TYPED: + purple_signal_emit(purple_conversations_get_handle(), + "buddy-typed", account, name); + break; + case PURPLE_IM_NOT_TYPING: + purple_signal_emit(purple_conversations_get_handle(), + "buddy-typing-stopped", account, name); + break; + } + + purple_im_conversation_update_typing(im); + } +} + +PurpleIMTypingState +purple_im_conversation_get_typing_state(const PurpleIMConversation *im) +{ + PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im); + + g_return_val_if_fail(priv != NULL, 0); + + return priv->typing_state; +} + +void +purple_im_conversation_start_typing_timeout(PurpleIMConversation *im, int timeout) +{ + PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im); + + g_return_if_fail(priv != NULL); + + if (priv->typing_timeout > 0) + purple_im_conversation_stop_typing_timeout(im); + + priv->typing_timeout = purple_timeout_add_seconds(timeout, reset_typing_cb, im); +} + +void +purple_im_conversation_stop_typing_timeout(PurpleIMConversation *im) +{ + PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im); + + g_return_if_fail(priv != NULL); + + if (priv->typing_timeout == 0) + return; + + purple_timeout_remove(priv->typing_timeout); + priv->typing_timeout = 0; +} + +guint +purple_im_conversation_get_typing_timeout(const PurpleIMConversation *im) +{ + PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im); + + g_return_val_if_fail(priv != NULL, 0); + + return priv->typing_timeout; +} + +void +purple_im_conversation_set_type_again(PurpleIMConversation *im, unsigned int val) +{ + PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im); + + g_return_if_fail(priv != NULL); + + if (val == 0) + priv->type_again = 0; + else + priv->type_again = time(NULL) + val; +} + +time_t +purple_im_conversation_get_type_again(const PurpleIMConversation *im) +{ + PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im); + + g_return_val_if_fail(priv != NULL, 0); + + return priv->type_again; +} + +void +purple_im_conversation_start_send_typed_timeout(PurpleIMConversation *im) +{ + PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im); + + g_return_if_fail(priv != NULL); + + priv->send_typed_timeout = purple_timeout_add_seconds(SEND_TYPED_TIMEOUT_SECONDS, + send_typed_cb, im); +} + +void +purple_im_conversation_stop_send_typed_timeout(PurpleIMConversation *im) +{ + PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im); + + g_return_if_fail(priv != NULL); + + if (priv->send_typed_timeout == 0) + return; + + purple_timeout_remove(priv->send_typed_timeout); + priv->send_typed_timeout = 0; +} + +guint +purple_im_conversation_get_send_typed_timeout(const PurpleIMConversation *im) +{ + PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im); + + g_return_val_if_fail(priv != NULL, 0); + + return priv->send_typed_timeout; +} + +void +purple_im_conversation_update_typing(PurpleIMConversation *im) +{ + g_return_if_fail(im != NULL); + + purple_conversation_update(PURPLE_CONVERSATION(im), + PURPLE_CONVERSATION_UPDATE_TYPING); +} + +static void +im_conversation_write_message(PurpleConversation *conv, const char *who, const char *message, + PurpleMessageFlags flags, time_t mtime) +{ + PurpleConversationUiOps *ops; + + g_return_if_fail(conv != NULL); + g_return_if_fail(message != NULL); + + ops = purple_conversation_get_ui_ops(conv); + + if ((flags & PURPLE_MESSAGE_RECV) == PURPLE_MESSAGE_RECV) { + purple_im_conversation_set_typing_state(PURPLE_IM_CONVERSATION(conv), + PURPLE_IM_NOT_TYPING); + } + + /* Pass this on to either the ops structure or the default write func. */ + if (ops != NULL && ops->write_im != NULL) + ops->write_im(PURPLE_IM_CONVERSATION(conv), who, message, flags, mtime); + else + purple_conversation_write(conv, who, message, flags, mtime); +} + +/************************************************************************** + * GObject code for IMs + **************************************************************************/ + +/* GObject Property names */ +#define IM_PROP_TYPING_STATE_S "typing-state" +#define IM_PROP_ICON_S "icon" + +/* Set method for GObject properties */ +static void +purple_im_conversation_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(obj); + + switch (param_id) { + case IM_PROP_TYPING_STATE: + purple_im_conversation_set_typing_state(im, g_value_get_enum(value)); + break; + case IM_PROP_ICON: + purple_im_conversation_set_icon(im, g_value_get_pointer(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_im_conversation_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(obj); + + switch (param_id) { + case IM_PROP_TYPING_STATE: + g_value_set_enum(value, purple_im_conversation_get_typing_state(im)); + break; + case IM_PROP_ICON: + g_value_set_pointer(value, purple_im_conversation_get_icon(im)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Called when done constructing */ +static void +purple_im_conversation_constructed(GObject *object) +{ + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(object); + PurpleAccount *account; + PurpleBuddyIcon *icon; + gchar *name; + + G_OBJECT_CLASS(parent_class)->constructed(object); + + g_object_get(object, + "account", &account, + "name", &name, + NULL); + + if ((icon = purple_buddy_icons_find(account, name))) + { + purple_im_conversation_set_icon(im, icon); + /* purple_im_conversation_set_icon refs the icon. */ + purple_buddy_icon_unref(icon); + } + + if (purple_prefs_get_bool("/purple/logging/log_ims")) + purple_conversation_set_logging(PURPLE_CONVERSATION(im), TRUE); + + g_free(name); +} + +/* GObject dispose function */ +static void +purple_im_conversation_dispose(GObject *object) +{ + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(object); + PurpleConnection *gc = purple_conversation_get_connection(PURPLE_CONVERSATION(im)); + PurplePluginProtocolInfo *prpl_info = NULL; + const char *name = purple_conversation_get_name(PURPLE_CONVERSATION(im)); + + if (gc != NULL) + { + /* Still connected */ + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + + if (purple_prefs_get_bool("/purple/conversations/im/send_typing")) + serv_send_typing(gc, name, PURPLE_IM_NOT_TYPING); + + if (gc && prpl_info->convo_closed != NULL) + prpl_info->convo_closed(gc, name); + } + + purple_im_conversation_stop_typing_timeout(im); + purple_im_conversation_stop_send_typed_timeout(im); + + G_OBJECT_CLASS(parent_class)->dispose(object); +} + +/* GObject finalize function */ +static void +purple_im_conversation_finalize(GObject *object) +{ + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(object); + PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(im); + + purple_buddy_icon_unref(priv->icon); + priv->icon = NULL; + + G_OBJECT_CLASS(parent_class)->finalize(object); +} + +/* Class initializer function */ +static void purple_im_conversation_class_init(PurpleIMConversationClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleConversationClass *conv_class = PURPLE_CONVERSATION_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->dispose = purple_im_conversation_dispose; + obj_class->finalize = purple_im_conversation_finalize; + obj_class->constructed = purple_im_conversation_constructed; + + /* Setup properties */ + obj_class->get_property = purple_im_conversation_get_property; + obj_class->set_property = purple_im_conversation_set_property; + + conv_class->write_message = im_conversation_write_message; + + g_object_class_install_property(obj_class, IM_PROP_TYPING_STATE, + g_param_spec_enum(IM_PROP_TYPING_STATE_S, _("Typing state"), + _("Status of the user's typing of a message."), + PURPLE_TYPE_IM_TYPING_STATE, PURPLE_IM_NOT_TYPING, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, IM_PROP_ICON, + g_param_spec_pointer(IM_PROP_ICON_S, _("Buddy icon"), + _("The buddy icon for the IM."), + G_PARAM_READWRITE) + ); + + g_type_class_add_private(klass, sizeof(PurpleIMConversationPrivate)); +} + +GType +purple_im_conversation_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleIMConversationClass), + NULL, + NULL, + (GClassInitFunc)purple_im_conversation_class_init, + NULL, + NULL, + sizeof(PurpleIMConversation), + 0, + NULL, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_CONVERSATION, + "PurpleIMConversation", + &info, 0); + } + + return type; +} + +PurpleIMConversation * +purple_im_conversation_new(PurpleAccount *account, const char *name) +{ + PurpleIMConversation *im; + PurpleConnection *gc; + + g_return_val_if_fail(account != NULL, NULL); + g_return_val_if_fail(name != NULL, NULL); + + /* Check if this conversation already exists. */ + if ((im = purple_conversations_find_im_with_account(name, account)) != NULL) + return im; + + gc = purple_account_get_connection(account); + g_return_val_if_fail(gc != NULL, NULL); + + im = g_object_new(PURPLE_TYPE_IM_CONVERSATION, + "account", account, + "name", name, + "title", name, + NULL); + + return im; +} + +/************************************************************************** + * Chat Conversation API + **************************************************************************/ +static guint +_purple_conversation_user_hash(gconstpointer data) +{ + const gchar *name = data; + gchar *collated; + guint hash; + + collated = g_utf8_collate_key(name, -1); + hash = g_str_hash(collated); + g_free(collated); + return hash; +} + +static gboolean +_purple_conversation_user_equal(gconstpointer a, gconstpointer b) +{ + return !g_utf8_collate(a, b); +} + +GList * +purple_chat_conversation_get_users(const PurpleChatConversation *chat) +{ + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->in_room; +} + +void +purple_chat_conversation_ignore(PurpleChatConversation *chat, const char *name) +{ + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_if_fail(priv != NULL); + g_return_if_fail(name != NULL); + + /* Make sure the user isn't already ignored. */ + if (purple_chat_conversation_is_ignored_user(chat, name)) + return; + + purple_chat_conversation_set_ignored(chat, + g_list_append(priv->ignored, g_strdup(name))); +} + +void +purple_chat_conversation_unignore(PurpleChatConversation *chat, const char *name) +{ + GList *item; + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_if_fail(priv != NULL); + g_return_if_fail(name != NULL); + + /* Make sure the user is actually ignored. */ + if (!purple_chat_conversation_is_ignored_user(chat, name)) + return; + + item = g_list_find(purple_chat_conversation_get_ignored(chat), + purple_chat_conversation_get_ignored_user(chat, name)); + + purple_chat_conversation_set_ignored(chat, + g_list_remove_link(priv->ignored, item)); + + g_free(item->data); + g_list_free_1(item); +} + +GList * +purple_chat_conversation_set_ignored(PurpleChatConversation *chat, GList *ignored) +{ + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_val_if_fail(priv != NULL, NULL); + + priv->ignored = ignored; + return ignored; +} + +GList * +purple_chat_conversation_get_ignored(const PurpleChatConversation *chat) +{ + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->ignored; +} + +const char * +purple_chat_conversation_get_ignored_user(const PurpleChatConversation *chat, const char *user) +{ + GList *ignored; + + g_return_val_if_fail(chat != NULL, NULL); + g_return_val_if_fail(user != NULL, NULL); + + for (ignored = purple_chat_conversation_get_ignored(chat); + ignored != NULL; + ignored = ignored->next) { + + const char *ign = (const char *)ignored->data; + + if (!purple_utf8_strcasecmp(user, ign) || + ((*ign == '+' || *ign == '%') && !purple_utf8_strcasecmp(user, ign + 1))) + return ign; + + if (*ign == '@') { + ign++; + + if ((*ign == '+' && !purple_utf8_strcasecmp(user, ign + 1)) || + (*ign != '+' && !purple_utf8_strcasecmp(user, ign))) + return ign; + } + } + + return NULL; +} + +gboolean +purple_chat_conversation_is_ignored_user(const PurpleChatConversation *chat, const char *user) +{ + g_return_val_if_fail(chat != NULL, FALSE); + g_return_val_if_fail(user != NULL, FALSE); + + return (purple_chat_conversation_get_ignored_user(chat, user) != NULL); +} + +void +purple_chat_conversation_set_topic(PurpleChatConversation *chat, const char *who, const char *topic) +{ + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_if_fail(priv != NULL); + + g_free(priv->who); + g_free(priv->topic); + + priv->who = g_strdup(who); + priv->topic = g_strdup(topic); + + purple_conversation_update(PURPLE_CONVERSATION(chat), + PURPLE_CONVERSATION_UPDATE_TOPIC); + + purple_signal_emit(purple_conversations_get_handle(), "chat-topic-changed", + chat, priv->who, priv->topic); +} + +const char * +purple_chat_conversation_get_topic(const PurpleChatConversation *chat) +{ + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->topic; +} + +const char * +purple_chat_conversation_get_topic_who(const PurpleChatConversation *chat) +{ + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->who; +} + +void +purple_chat_conversation_set_id(PurpleChatConversation *chat, int id) +{ + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_if_fail(priv != NULL); + + priv->id = id; +} + +int +purple_chat_conversation_get_id(const PurpleChatConversation *chat) +{ + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_val_if_fail(priv != NULL, -1); + + return priv->id; +} + +static void +chat_conversation_write_message(PurpleConversation *conv, const char *who, const char *message, + PurpleMessageFlags flags, time_t mtime) +{ + PurpleAccount *account; + PurpleConversationUiOps *ops; + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv); + + g_return_if_fail(priv != NULL); + g_return_if_fail(who != NULL); + g_return_if_fail(message != NULL); + + account = purple_conversation_get_account(conv); + + /* Don't display this if the person who wrote it is ignored. */ + if (purple_chat_conversation_is_ignored_user(PURPLE_CHAT_CONVERSATION(conv), who)) + return; + + if (!(flags & PURPLE_MESSAGE_WHISPER)) { + const char *str; + + str = purple_normalize(account, who); + + if (purple_strequal(str, priv->nick)) { + flags |= PURPLE_MESSAGE_SEND; + } else { + flags |= PURPLE_MESSAGE_RECV; + + if (purple_utf8_has_word(message, priv->nick)) + flags |= PURPLE_MESSAGE_NICK; + } + } + + ops = purple_conversation_get_ui_ops(conv); + + /* Pass this on to either the ops structure or the default write func. */ + if (ops != NULL && ops->write_chat != NULL) + ops->write_chat(PURPLE_CHAT_CONVERSATION(conv), who, message, flags, mtime); + else + purple_conversation_write(conv, who, message, flags, mtime); +} + +void +purple_chat_conversation_add_user(PurpleChatConversation *chat, const char *user, + const char *extra_msg, PurpleChatUserFlags flags, + gboolean new_arrival) +{ + GList *users = g_list_append(NULL, (char *)user); + GList *extra_msgs = g_list_append(NULL, (char *)extra_msg); + GList *flags2 = g_list_append(NULL, GINT_TO_POINTER(flags)); + + purple_chat_conversation_add_users(chat, users, extra_msgs, flags2, new_arrival); + + g_list_free(users); + g_list_free(extra_msgs); + g_list_free(flags2); +} + +void +purple_chat_conversation_add_users(PurpleChatConversation *chat, GList *users, GList *extra_msgs, + GList *flags, gboolean new_arrivals) +{ + PurpleConversation *conv; + PurpleConversationUiOps *ops; + PurpleChatUser *chatuser; + PurpleChatConversationPrivate *priv; + PurpleAccount *account; + PurpleConnection *gc; + PurplePluginProtocolInfo *prpl_info; + GList *ul, *fl; + GList *cbuddies = NULL; + + priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_if_fail(priv != NULL); + g_return_if_fail(users != NULL); + + conv = PURPLE_CONVERSATION(chat); + ops = purple_conversation_get_ui_ops(conv); + + account = purple_conversation_get_account(conv); + gc = purple_conversation_get_connection(conv); + g_return_if_fail(gc != NULL); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + g_return_if_fail(prpl_info != NULL); + + ul = users; + fl = flags; + while ((ul != NULL) && (fl != NULL)) { + const char *user = (const char *)ul->data; + const char *alias = user; + gboolean quiet; + PurpleChatUserFlags flag = GPOINTER_TO_INT(fl->data); + const char *extra_msg = (extra_msgs ? extra_msgs->data : NULL); + + if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + if (purple_strequal(priv->nick, purple_normalize(account, user))) { + const char *alias2 = purple_account_get_private_alias(account); + if (alias2 != NULL) + alias = alias2; + else + { + const char *display_name = purple_connection_get_display_name(gc); + if (display_name != NULL) + alias = display_name; + } + } else { + PurpleBuddy *buddy; + if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), user)) != NULL) + alias = purple_buddy_get_contact_alias(buddy); + } + } + + quiet = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_conversations_get_handle(), + "chat-user-joining", chat, user, flag)) || + purple_chat_conversation_is_ignored_user(chat, user); + + chatuser = purple_chat_user_new(chat, user, alias, flag); + purple_chat_user_set_buddy(chatuser, purple_blist_find_buddy(account, user) != NULL); + + priv->in_room = g_list_prepend(priv->in_room, chatuser); + g_hash_table_replace(priv->users, + g_strdup(purple_chat_user_get_name(chatuser)), chatuser); + + cbuddies = g_list_prepend(cbuddies, chatuser); + + if (!quiet && new_arrivals) { + char *alias_esc = g_markup_escape_text(alias, -1); + char *tmp; + + if (extra_msg == NULL) + tmp = g_strdup_printf(_("%s entered the room."), alias_esc); + else { + char *extra_msg_esc = g_markup_escape_text(extra_msg, -1); + tmp = g_strdup_printf(_("%s [<I>%s</I>] entered the room."), + alias_esc, extra_msg_esc); + g_free(extra_msg_esc); + } + g_free(alias_esc); + + purple_conversation_write(conv, NULL, tmp, + PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, + time(NULL)); + g_free(tmp); + } + + purple_signal_emit(purple_conversations_get_handle(), + "chat-user-joined", chat, user, flag, new_arrivals); + ul = ul->next; + fl = fl->next; + if (extra_msgs != NULL) + extra_msgs = extra_msgs->next; + } + + cbuddies = g_list_sort(cbuddies, (GCompareFunc)purple_chat_user_compare); + + if (ops != NULL && ops->chat_add_users != NULL) + ops->chat_add_users(chat, cbuddies, new_arrivals); + + g_list_free(cbuddies); +} + +void +purple_chat_conversation_rename_user(PurpleChatConversation *chat, const char *old_user, + const char *new_user) +{ + PurpleConversation *conv; + PurpleConversationUiOps *ops; + PurpleAccount *account; + PurpleConnection *gc; + PurplePluginProtocolInfo *prpl_info; + PurpleChatUser *cb; + PurpleChatUserFlags flags; + PurpleChatConversationPrivate *priv; + const char *new_alias = new_user; + char tmp[BUF_LONG]; + gboolean is_me = FALSE; + + priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_if_fail(priv != NULL); + g_return_if_fail(old_user != NULL); + g_return_if_fail(new_user != NULL); + + conv = PURPLE_CONVERSATION(chat); + ops = purple_conversation_get_ui_ops(conv); + account = purple_conversation_get_account(conv); + + gc = purple_conversation_get_connection(conv); + g_return_if_fail(gc != NULL); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + g_return_if_fail(prpl_info != NULL); + + if (purple_strequal(priv->nick, purple_normalize(account, old_user))) { + const char *alias; + + /* Note this for later. */ + is_me = TRUE; + + if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + alias = purple_account_get_private_alias(account); + if (alias != NULL) + new_alias = alias; + else + { + const char *display_name = purple_connection_get_display_name(gc); + if (display_name != NULL) + new_alias = display_name; + } + } + } else if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + PurpleBuddy *buddy; + if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), new_user)) != NULL) + new_alias = purple_buddy_get_contact_alias(buddy); + } + + flags = purple_chat_user_get_flags(purple_chat_conversation_find_user(chat, old_user)); + cb = purple_chat_user_new(chat, new_user, new_alias, flags); + purple_chat_user_set_buddy(cb, purple_blist_find_buddy(account, new_user) != NULL); + + priv->in_room = g_list_prepend(priv->in_room, cb); + g_hash_table_replace(priv->users, + g_strdup(purple_chat_user_get_name(cb)), cb); + + if (ops != NULL && ops->chat_rename_user != NULL) + ops->chat_rename_user(chat, old_user, new_user, new_alias); + + cb = purple_chat_conversation_find_user(chat, old_user); + + if (cb) { + priv->in_room = g_list_remove(priv->in_room, cb); + g_hash_table_remove(priv->users, purple_chat_user_get_name(cb)); + g_object_unref(cb); + } + + if (purple_chat_conversation_is_ignored_user(chat, old_user)) { + purple_chat_conversation_unignore(chat, old_user); + purple_chat_conversation_ignore(chat, new_user); + } + else if (purple_chat_conversation_is_ignored_user(chat, new_user)) + purple_chat_conversation_unignore(chat, new_user); + + if (is_me) + purple_chat_conversation_set_nick(chat, new_user); + + if (purple_prefs_get_bool("/purple/conversations/chat/show_nick_change") && + !purple_chat_conversation_is_ignored_user(chat, new_user)) { + + if (is_me) { + char *escaped = g_markup_escape_text(new_user, -1); + g_snprintf(tmp, sizeof(tmp), + _("You are now known as %s"), escaped); + g_free(escaped); + } else { + const char *old_alias = old_user; + const char *new_alias = new_user; + char *escaped; + char *escaped2; + + if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + PurpleBuddy *buddy; + + if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), old_user)) != NULL) + old_alias = purple_buddy_get_contact_alias(buddy); + if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), new_user)) != NULL) + new_alias = purple_buddy_get_contact_alias(buddy); + } + + escaped = g_markup_escape_text(old_alias, -1); + escaped2 = g_markup_escape_text(new_alias, -1); + g_snprintf(tmp, sizeof(tmp), + _("%s is now known as %s"), escaped, escaped2); + g_free(escaped); + g_free(escaped2); + } + + purple_conversation_write(conv, NULL, tmp, + PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, + time(NULL)); + } +} + +void +purple_chat_conversation_remove_user(PurpleChatConversation *chat, const char *user, const char *reason) +{ + GList *users = g_list_append(NULL, (char *)user); + + purple_chat_conversation_remove_users(chat, users, reason); + + g_list_free(users); +} + +void +purple_chat_conversation_remove_users(PurpleChatConversation *chat, GList *users, const char *reason) +{ + PurpleConversation *conv; + PurpleConnection *gc; + PurplePluginProtocolInfo *prpl_info; + PurpleConversationUiOps *ops; + PurpleChatUser *cb; + PurpleChatConversationPrivate *priv; + GList *l; + gboolean quiet; + + priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_if_fail(priv != NULL); + g_return_if_fail(users != NULL); + + conv = PURPLE_CONVERSATION(chat); + + gc = purple_conversation_get_connection(conv); + g_return_if_fail(gc != NULL); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + g_return_if_fail(prpl_info != NULL); + + ops = purple_conversation_get_ui_ops(conv); + + for (l = users; l != NULL; l = l->next) { + const char *user = (const char *)l->data; + quiet = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_conversations_get_handle(), + "chat-user-leaving", chat, user, reason)) | + purple_chat_conversation_is_ignored_user(chat, user); + + cb = purple_chat_conversation_find_user(chat, user); + + if (cb) { + priv->in_room = g_list_remove(priv->in_room, cb); + g_hash_table_remove(priv->users, purple_chat_user_get_name(cb)); + g_object_unref(cb); + } + + /* NOTE: Don't remove them from ignored in case they re-enter. */ + + if (!quiet) { + const char *alias = user; + char *alias_esc; + char *tmp; + + if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + PurpleBuddy *buddy; + + if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), user)) != NULL) + alias = purple_buddy_get_contact_alias(buddy); + } + + alias_esc = g_markup_escape_text(alias, -1); + + if (reason == NULL || !*reason) + tmp = g_strdup_printf(_("%s left the room."), alias_esc); + else { + char *reason_esc = g_markup_escape_text(reason, -1); + tmp = g_strdup_printf(_("%s left the room (%s)."), + alias_esc, reason_esc); + g_free(reason_esc); + } + g_free(alias_esc); + + purple_conversation_write(conv, NULL, tmp, + PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, + time(NULL)); + g_free(tmp); + } + + purple_signal_emit(purple_conversations_get_handle(), "chat-user-left", + conv, user, reason); + } + + if (ops != NULL && ops->chat_remove_users != NULL) + ops->chat_remove_users(chat, users); +} + +void +purple_chat_conversation_clear_users(PurpleChatConversation *chat) +{ + PurpleConversationUiOps *ops; + GList *users; + GList *l; + GList *names = NULL; + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_if_fail(priv != NULL); + + ops = purple_conversation_get_ui_ops(PURPLE_CONVERSATION(chat)); + users = priv->in_room; + + if (ops != NULL && ops->chat_remove_users != NULL) { + for (l = users; l; l = l->next) { + PurpleChatUser *cb = l->data; + names = g_list_prepend(names, + (gchar *) purple_chat_user_get_name(cb)); + } + ops->chat_remove_users(chat, names); + g_list_free(names); + } + + for (l = users; l; l = l->next) + { + PurpleChatUser *cb = l->data; + const char *name = purple_chat_user_get_name(cb); + + purple_signal_emit(purple_conversations_get_handle(), + "chat-user-leaving", chat, name, NULL); + purple_signal_emit(purple_conversations_get_handle(), + "chat-user-left", chat, name, NULL); + + g_object_unref(cb); + } + + g_hash_table_remove_all(priv->users); + + g_list_free(users); + priv->in_room = NULL; +} + +void purple_chat_conversation_set_nick(PurpleChatConversation *chat, const char *nick) { + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_if_fail(priv != NULL); + + g_free(priv->nick); + priv->nick = g_strdup(purple_normalize( + purple_conversation_get_account(PURPLE_CONVERSATION(chat)), nick)); +} + +const char *purple_chat_conversation_get_nick(PurpleChatConversation *chat) { + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->nick; +} + +static void +invite_user_to_chat(gpointer data, PurpleRequestFields *fields) +{ + PurpleConversation *conv; + PurpleChatConversationPrivate *priv; + const char *user, *message; + + conv = data; + priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv); + user = purple_request_fields_get_string(fields, "screenname"); + message = purple_request_fields_get_string(fields, "message"); + + serv_chat_invite(purple_conversation_get_connection(conv), priv->id, message, user); +} + +void purple_chat_conversation_invite_user(PurpleChatConversation *chat, const char *user, + const char *message, gboolean confirm) +{ + PurpleAccount *account; + PurpleRequestFields *fields; + PurpleRequestFieldGroup *group; + PurpleRequestField *field; + + g_return_if_fail(chat != NULL); + + if (!user || !*user || !message || !*message) + confirm = TRUE; + + account = purple_conversation_get_account(PURPLE_CONVERSATION(chat)); + + if (!confirm) { + serv_chat_invite(purple_account_get_connection(account), + purple_chat_conversation_get_id(chat), message, user); + return; + } + + fields = purple_request_fields_new(); + group = purple_request_field_group_new(_("Invite to chat")); + purple_request_fields_add_group(fields, group); + + field = purple_request_field_string_new("screenname", _("Buddy"), user, FALSE); + purple_request_field_group_add_field(group, field); + purple_request_field_set_required(field, TRUE); + purple_request_field_set_type_hint(field, "screenname"); + + field = purple_request_field_string_new("message", _("Message"), message, FALSE); + purple_request_field_group_add_field(group, field); + + purple_request_fields(chat, _("Invite to chat"), NULL, + _("Please enter the name of the user you wish to invite, " + "along with an optional invite message."), + fields, + _("Invite"), G_CALLBACK(invite_user_to_chat), + _("Cancel"), NULL, + account, user, PURPLE_CONVERSATION(chat), + chat); +} + +gboolean +purple_chat_conversation_has_user(PurpleChatConversation *chat, const char *user) +{ + g_return_val_if_fail(chat != NULL, FALSE); + g_return_val_if_fail(user != NULL, FALSE); + + return (purple_chat_conversation_find_user(chat, user) != NULL); +} + +void +purple_chat_conversation_leave(PurpleChatConversation *chat) +{ + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_if_fail(priv != NULL); + + priv->left = TRUE; + purple_conversation_update(PURPLE_CONVERSATION(chat), PURPLE_CONVERSATION_UPDATE_CHATLEFT); +} + +gboolean +purple_chat_conversation_has_left(PurpleChatConversation *chat) +{ + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_val_if_fail(priv != NULL, TRUE); + + return priv->left; +} + +static void +chat_conversation_cleanup_for_rejoin(PurpleChatConversation *chat) +{ + const char *disp; + PurpleAccount *account; + PurpleConnection *gc; + PurpleConversation *conv = PURPLE_CONVERSATION(chat); + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + account = purple_conversation_get_account(conv); + + purple_conversation_close_logs(conv); + purple_conversation_set_logging(conv, TRUE); + + gc = purple_account_get_connection(account); + + if ((disp = purple_connection_get_display_name(gc)) != NULL) + purple_chat_conversation_set_nick(chat, disp); + else + { + purple_chat_conversation_set_nick(chat, + purple_account_get_username(account)); + } + + purple_chat_conversation_clear_users(chat); + purple_chat_conversation_set_topic(chat, NULL, NULL); + priv->left = FALSE; + + purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_CHATLEFT); +} + +PurpleChatUser * +purple_chat_conversation_find_user(PurpleChatConversation *chat, const char *name) +{ + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_return_val_if_fail(priv != NULL, NULL); + g_return_val_if_fail(name != NULL, NULL); + + return g_hash_table_lookup(priv->users, name); +} + +/************************************************************************** + * GObject code for chats + **************************************************************************/ + +/* GObject Property names */ +#define CHAT_PROP_TOPIC_WHO_S "topic-who" +#define CHAT_PROP_TOPIC_S "topic" +#define CHAT_PROP_ID_S "chat-id" +#define CHAT_PROP_NICK_S "nick" +#define CHAT_PROP_LEFT_S "left" + +/* Set method for GObject properties */ +static void +purple_chat_conversation_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(obj); + + switch (param_id) { + case CHAT_PROP_ID: + purple_chat_conversation_set_id(chat, g_value_get_int(value)); + break; + case CHAT_PROP_NICK: + purple_chat_conversation_set_nick(chat, g_value_get_string(value)); + break; + case CHAT_PROP_LEFT: + { + gboolean left = g_value_get_boolean(value); + if (left == TRUE) + purple_chat_conversation_leave(chat); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_chat_conversation_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(obj); + + switch (param_id) { + case CHAT_PROP_TOPIC_WHO: + g_value_set_string(value, purple_chat_conversation_get_topic_who(chat)); + break; + case CHAT_PROP_TOPIC: + g_value_set_string(value, purple_chat_conversation_get_topic(chat)); + break; + case CHAT_PROP_ID: + g_value_set_int(value, purple_chat_conversation_get_id(chat)); + break; + case CHAT_PROP_NICK: + g_value_set_string(value, purple_chat_conversation_get_nick(chat)); + break; + case CHAT_PROP_LEFT: + g_value_set_boolean(value, purple_chat_conversation_has_left(chat)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* GObject initialization function */ +static void purple_chat_conversation_init(GTypeInstance *instance, gpointer klass) +{ + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(instance); + + priv->users = g_hash_table_new_full(_purple_conversation_user_hash, + _purple_conversation_user_equal, g_free, NULL); +} + +/* Called when done constructing */ +static void +purple_chat_conversation_constructed(GObject *object) +{ + PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(object); + PurpleAccount *account; + const char *disp; + + G_OBJECT_CLASS(parent_class)->constructed(object); + + g_object_get(object, "account", &account, NULL); + + if ((disp = purple_connection_get_display_name(purple_account_get_connection(account)))) + purple_chat_conversation_set_nick(chat, disp); + else + purple_chat_conversation_set_nick(chat, + purple_account_get_username(account)); + + if (purple_prefs_get_bool("/purple/logging/log_chats")) + purple_conversation_set_logging(PURPLE_CONVERSATION(chat), TRUE); +} + +/* GObject dispose function */ +static void +purple_chat_conversation_dispose(GObject *object) +{ + PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(object); + PurpleConnection *gc = purple_conversation_get_connection(PURPLE_CONVERSATION(chat)); + + if (gc != NULL) + { + /* Still connected */ + int chat_id = purple_chat_conversation_get_id(chat); +#if 0 + /* + * This is unfortunately necessary, because calling + * serv_chat_leave() calls this purple_conversation_destroy(), + * which leads to two calls here.. We can't just return after + * this, because then it'll return on the next pass. So, since + * serv_got_chat_left(), which is eventually called from the + * prpl that serv_chat_leave() calls, removes this conversation + * from the gc's buddy_chats list, we're going to check to see + * if this exists in the list. If so, we want to return after + * calling this, because it'll be called again. If not, fall + * through, because it'll have already been removed, and we'd + * be on the 2nd pass. + * + * Long paragraph. <-- Short sentence. + * + * -- ChipX86 + */ + + if (gc && g_slist_find(gc->buddy_chats, conv) != NULL) { + serv_chat_leave(gc, chat_id); + + return; + } +#endif + /* + * Instead of all of that, lets just close the window when + * the user tells us to, and let the prpl deal with the + * internals on it's own time. Don't do this if the prpl already + * knows it left the chat. + */ + if (!purple_chat_conversation_has_left(chat)) + serv_chat_leave(gc, chat_id); + + /* + * If they didn't call serv_got_chat_left by now, it's too late. + * So we better do it for them before we destroy the thing. + */ + if (!purple_chat_conversation_has_left(chat)) + serv_got_chat_left(gc, chat_id); + } + + G_OBJECT_CLASS(parent_class)->dispose(object); +} + +/* GObject finalize function */ +static void +purple_chat_conversation_finalize(GObject *object) +{ + PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(object); + PurpleChatConversationPrivate *priv = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(chat); + + g_hash_table_destroy(priv->users); + priv->users = NULL; + + g_list_foreach(priv->in_room, (GFunc)g_object_unref, NULL); + g_list_free(priv->in_room); + priv->in_room = NULL; + + g_list_foreach(priv->ignored, (GFunc)g_free, NULL); + g_list_free(priv->ignored); + priv->ignored = NULL; + + g_free(priv->who); + g_free(priv->topic); + g_free(priv->nick); + + priv->who = NULL; + priv->topic = NULL; + priv->nick = NULL; + + G_OBJECT_CLASS(parent_class)->finalize(object); +} + +/* Class initializer function */ +static void purple_chat_conversation_class_init(PurpleChatConversationClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleConversationClass *conv_class = PURPLE_CONVERSATION_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->dispose = purple_chat_conversation_dispose; + obj_class->finalize = purple_chat_conversation_finalize; + obj_class->constructed = purple_chat_conversation_constructed; + + /* Setup properties */ + obj_class->get_property = purple_chat_conversation_get_property; + obj_class->set_property = purple_chat_conversation_set_property; + + conv_class->write_message = chat_conversation_write_message; + + g_object_class_install_property(obj_class, CHAT_PROP_TOPIC_WHO, + g_param_spec_string(CHAT_PROP_TOPIC_WHO_S, _("Who set topic"), + _("Who set the chat topic."), NULL, + G_PARAM_READABLE) + ); + + g_object_class_install_property(obj_class, CHAT_PROP_TOPIC, + g_param_spec_string(CHAT_PROP_TOPIC_S, _("Topic"), + _("Topic of the chat."), NULL, + G_PARAM_READABLE) + ); + + g_object_class_install_property(obj_class, CHAT_PROP_ID, + g_param_spec_int(CHAT_PROP_ID_S, _("Chat ID"), + _("The ID of the chat."), G_MININT, G_MAXINT, 0, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, CHAT_PROP_NICK, + g_param_spec_string(CHAT_PROP_NICK_S, _("Nickname"), + _("The nickname of the user in a chat."), NULL, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, CHAT_PROP_LEFT, + g_param_spec_boolean(CHAT_PROP_LEFT_S, _("Left the chat"), + _("Whether the user has left the chat."), FALSE, + G_PARAM_READWRITE) + ); + + g_type_class_add_private(klass, sizeof(PurpleChatConversationPrivate)); +} + +GType +purple_chat_conversation_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleChatConversationClass), + NULL, + NULL, + (GClassInitFunc)purple_chat_conversation_class_init, + NULL, + NULL, + sizeof(PurpleChatConversation), + 0, + (GInstanceInitFunc)purple_chat_conversation_init, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_CONVERSATION, + "PurpleChatConversation", + &info, 0); + } + + return type; +} + +PurpleChatConversation * +purple_chat_conversation_new(PurpleAccount *account, const char *name) +{ + PurpleChatConversation *chat; + PurpleConnection *gc; + + g_return_val_if_fail(account != NULL, NULL); + g_return_val_if_fail(name != NULL, NULL); + + /* Check if this conversation already exists. */ + if ((chat = purple_conversations_find_chat_with_account(name, account)) != NULL) + { + if (!purple_chat_conversation_has_left(chat)) { + purple_debug_warning("conversation", "Trying to create multiple " + "chats (%s) with the same name is deprecated and will be " + "removed in libpurple 3.0.0", name); + } else { + /* + * This hack is necessary because some prpls (MSN) have unnamed chats + * that all use the same name. A PurpleConversation for one of those + * is only ever re-used if the user has left, so calls to + * purple_conversation_new need to fall-through to creating a new + * chat. + * TODO 3.0.0: Remove this workaround and mandate unique names. + */ + + chat_conversation_cleanup_for_rejoin(chat); + return chat; + } + } + + gc = purple_account_get_connection(account); + g_return_val_if_fail(gc != NULL, NULL); + + chat = g_object_new(PURPLE_TYPE_CHAT_CONVERSATION, + "account", account, + "name", name, + "title", name, + NULL); + + return chat; +} + +/************************************************************************** + * Chat Conversation User API + **************************************************************************/ +static int +purple_chat_user_compare(PurpleChatUser *a, PurpleChatUser *b) +{ + PurpleChatUserFlags f1 = 0, f2 = 0; + PurpleChatUserPrivate *priva, *privb; + char *user1 = NULL, *user2 = NULL; + gint ret = 0; + + priva = PURPLE_CHAT_USER_GET_PRIVATE(a); + privb = PURPLE_CHAT_USER_GET_PRIVATE(b); + + if (priva) { + f1 = priva->flags; + if (priva->alias_key) + user1 = priva->alias_key; + else if (priva->name) + user1 = priva->name; + } + + if (privb) { + f2 = privb->flags; + if (privb->alias_key) + user2 = privb->alias_key; + else if (privb->name) + user2 = privb->name; + } + + if (user1 == NULL || user2 == NULL) { + if (!(user1 == NULL && user2 == NULL)) + ret = (user1 == NULL) ? -1: 1; + } else if (f1 != f2) { + /* sort more important users first */ + ret = (f1 > f2) ? -1 : 1; + } else if (priva->buddy != privb->buddy) { + ret = priva->buddy ? -1 : 1; + } else { + ret = purple_utf8_strcasecmp(user1, user2); + } + + return ret; +} + +const char * +purple_chat_user_get_alias(const PurpleChatUser *cb) +{ + PurpleChatUserPrivate *priv; + priv = PURPLE_CHAT_USER_GET_PRIVATE(cb); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->alias; +} + +const char * +purple_chat_user_get_name(const PurpleChatUser *cb) +{ + PurpleChatUserPrivate *priv; + priv = PURPLE_CHAT_USER_GET_PRIVATE(cb); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->name; +} + +void +purple_chat_user_set_flags(PurpleChatUser *cb, + PurpleChatUserFlags flags) +{ + PurpleConversationUiOps *ops; + PurpleChatUserFlags oldflags; + PurpleChatUserPrivate *priv; + priv = PURPLE_CHAT_USER_GET_PRIVATE(cb); + + g_return_if_fail(priv != NULL); + + if (flags == priv->flags) + return; + + oldflags = priv->flags; + priv->flags = flags; + + ops = purple_conversation_get_ui_ops(PURPLE_CONVERSATION(priv->chat)); + + if (ops != NULL && ops->chat_update_user != NULL) + ops->chat_update_user(cb); + + purple_signal_emit(purple_conversations_get_handle(), + "chat-user-flags", cb, oldflags, flags); +} + +PurpleChatUserFlags +purple_chat_user_get_flags(const PurpleChatUser *cb) +{ + PurpleChatUserPrivate *priv; + priv = PURPLE_CHAT_USER_GET_PRIVATE(cb); + + g_return_val_if_fail(priv != NULL, PURPLE_CHAT_USER_NONE); + + return priv->flags; +} + +void +purple_chat_user_set_ui_data(PurpleChatUser *cb, gpointer ui_data) +{ + g_return_if_fail(cb != NULL); + + cb->ui_data = ui_data; +} + +gpointer +purple_chat_user_get_ui_data(const PurpleChatUser *cb) +{ + g_return_val_if_fail(cb != NULL, NULL); + + return cb->ui_data; +} + +void +purple_chat_user_set_chat(PurpleChatUser *cb, + PurpleChatConversation *chat) +{ + PurpleChatUserPrivate *priv; + priv = PURPLE_CHAT_USER_GET_PRIVATE(cb); + + g_return_if_fail(priv != NULL); + + priv->chat = chat; +} + +PurpleChatConversation * +purple_chat_user_get_chat(const PurpleChatUser *cb) +{ + PurpleChatUserPrivate *priv; + priv = PURPLE_CHAT_USER_GET_PRIVATE(cb); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->chat; +} + +void +purple_chat_user_set_buddy(const PurpleChatUser *cb, + gboolean buddy) +{ + PurpleChatUserPrivate *priv; + priv = PURPLE_CHAT_USER_GET_PRIVATE(cb); + + g_return_if_fail(priv != NULL); + + priv->buddy = buddy; +} + +gboolean +purple_chat_user_is_buddy(const PurpleChatUser *cb) +{ + PurpleChatUserPrivate *priv; + priv = PURPLE_CHAT_USER_GET_PRIVATE(cb); + + g_return_val_if_fail(priv != NULL, FALSE); + + return priv->buddy; +} + +/************************************************************************** + * GObject code for chat user + **************************************************************************/ + +/* GObject Property names */ +#define CU_PROP_CHAT_S "chat" +#define CU_PROP_NAME_S "name" +#define CU_PROP_ALIAS_S "alias" +#define CU_PROP_BUDDY_S "buddy" +#define CU_PROP_FLAGS_S "flags" + +/* Set method for GObject properties */ +static void +purple_chat_user_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleChatUser *cb = PURPLE_CHAT_USER(obj); + PurpleChatUserPrivate *priv = PURPLE_CHAT_USER_GET_PRIVATE(cb); + + switch (param_id) { + case CU_PROP_CHAT: + priv->chat = g_value_get_object(value); + break; + case CU_PROP_NAME: + g_free(priv->name); + priv->name = g_strdup(g_value_get_string(value)); + break; + case CU_PROP_ALIAS: + g_free(priv->alias); + priv->alias = g_strdup(g_value_get_string(value)); + break; + case CU_PROP_BUDDY: + priv->buddy = g_value_get_boolean(value); + break; + case CU_PROP_FLAGS: + priv->flags = g_value_get_flags(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_chat_user_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleChatUser *cb = PURPLE_CHAT_USER(obj); + + switch (param_id) { + case CU_PROP_CHAT: + g_value_set_object(value, purple_chat_user_get_chat(cb)); + break; + case CU_PROP_NAME: + g_value_set_string(value, purple_chat_user_get_name(cb)); + break; + case CU_PROP_ALIAS: + g_value_set_string(value, purple_chat_user_get_alias(cb)); + break; + case CU_PROP_BUDDY: + g_value_set_boolean(value, purple_chat_user_is_buddy(cb)); + break; + case CU_PROP_FLAGS: + g_value_set_flags(value, purple_chat_user_get_flags(cb)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* GObject initialization function */ +static void +purple_chat_user_init(GTypeInstance *instance, gpointer klass) +{ + PURPLE_DBUS_REGISTER_POINTER(PURPLE_CHAT_USER(instance), PurpleChatUser); +} + +/* GObject dispose function */ +static void +purple_chat_user_dispose(GObject *object) +{ + PurpleChatUser *cb = PURPLE_CHAT_USER(object); + + purple_signal_emit(purple_conversations_get_handle(), + "deleting-chat-user", cb); + PURPLE_DBUS_UNREGISTER_POINTER(cb); + + cb_parent_class->dispose(object); +} + +/* GObject finalize function */ +static void +purple_chat_user_finalize(GObject *object) +{ + PurpleChatUserPrivate *priv; + priv = PURPLE_CHAT_USER_GET_PRIVATE(object); + + g_free(priv->alias); + g_free(priv->alias_key); + g_free(priv->name); + + cb_parent_class->finalize(object); +} + +/* Class initializer function */ +static void purple_chat_user_class_init(PurpleChatUserClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + cb_parent_class = g_type_class_peek_parent(klass); + + obj_class->dispose = purple_chat_user_dispose; + obj_class->finalize = purple_chat_user_finalize; + + /* Setup properties */ + obj_class->get_property = purple_chat_user_get_property; + obj_class->set_property = purple_chat_user_set_property; + + g_object_class_install_property(obj_class, CU_PROP_CHAT, + g_param_spec_object(CU_PROP_CHAT_S, _("Chat"), + _("The chat the buddy belongs to."), PURPLE_TYPE_CHAT_CONVERSATION, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_object_class_install_property(obj_class, CU_PROP_NAME, + g_param_spec_string(CU_PROP_NAME_S, _("Name"), + _("Name of the chat user."), NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_object_class_install_property(obj_class, CU_PROP_ALIAS, + g_param_spec_string(CU_PROP_ALIAS_S, _("Alias"), + _("Alias of the chat user."), NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_object_class_install_property(obj_class, CU_PROP_BUDDY, + g_param_spec_boolean(CU_PROP_BUDDY_S, _("Is buddy"), + _("Whether the chat user is in the buddy list."), FALSE, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, CU_PROP_FLAGS, + g_param_spec_flags(CU_PROP_FLAGS_S, _("Buddy flags"), + _("The flags for the chat user."), + PURPLE_TYPE_CHAT_USER_FLAGS, PURPLE_CHAT_USER_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_type_class_add_private(klass, sizeof(PurpleChatUserPrivate)); +} + +GType +purple_chat_user_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleChatUserClass), + NULL, + NULL, + (GClassInitFunc)purple_chat_user_class_init, + NULL, + NULL, + sizeof(PurpleChatUser), + 0, + (GInstanceInitFunc)purple_chat_user_init, + NULL, + }; + + type = g_type_register_static(G_TYPE_OBJECT, + "PurpleChatUser", + &info, 0); + } + + return type; +} + +PurpleChatUser * +purple_chat_user_new(PurpleChatConversation *chat, const char *name, + const char *alias, PurpleChatUserFlags flags) +{ + PurpleChatUser *cb; + + g_return_val_if_fail(chat != NULL, NULL); + g_return_val_if_fail(name != NULL, NULL); + + cb = g_object_new(PURPLE_TYPE_CHAT_USER, + CU_PROP_CHAT_S, chat, + CU_PROP_NAME_S, name, + CU_PROP_ALIAS_S, alias, + CU_PROP_FLAGS_S, flags, + NULL); + + return cb; +} diff --git a/libpurple/conversationtypes.h b/libpurple/conversationtypes.h new file mode 100644 index 0000000000..050d8cc375 --- /dev/null +++ b/libpurple/conversationtypes.h @@ -0,0 +1,707 @@ +/** + * @file conversationtypes.h Chat and IM Conversation API + * @ingroup core + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef _PURPLE_CONVERSATION_TYPES_H_ +#define _PURPLE_CONVERSATION_TYPES_H_ + +/**************************************************************************/ +/** Data Structures */ +/**************************************************************************/ + +#define PURPLE_TYPE_IM_CONVERSATION (purple_im_conversation_get_type()) +#define PURPLE_IM_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_IM_CONVERSATION, PurpleIMConversation)) +#define PURPLE_IM_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_IM_CONVERSATION, PurpleIMConversationClass)) +#define PURPLE_IS_IM_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_IM_CONVERSATION)) +#define PURPLE_IS_IM_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_IM_CONVERSATION)) +#define PURPLE_IM_CONVERSATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_IM_CONVERSATION, PurpleIMConversationClass)) + +/** @copydoc _PurpleIMConversation */ +typedef struct _PurpleIMConversation PurpleIMConversation; +/** @copydoc _PurpleIMConversationClass */ +typedef struct _PurpleIMConversationClass PurpleIMConversationClass; + +#define PURPLE_TYPE_CHAT_CONVERSATION (purple_chat_conversation_get_type()) +#define PURPLE_CHAT_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_CHAT_CONVERSATION, PurpleChatConversation)) +#define PURPLE_CHAT_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_CHAT_CONVERSATION, PurpleChatConversationClass)) +#define PURPLE_IS_CHAT_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_CHAT_CONVERSATION)) +#define PURPLE_IS_CHAT_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_CHAT_CONVERSATION)) +#define PURPLE_CHAT_CONVERSATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_CHAT_CONVERSATION, PurpleChatConversationClass)) + +/** @copydoc _PurpleChatConversation */ +typedef struct _PurpleChatConversation PurpleChatConversation; +/** @copydoc _PurpleChatConversationClass */ +typedef struct _PurpleChatConversationClass PurpleChatConversationClass; + +#define PURPLE_TYPE_CHAT_USER (purple_chat_user_get_type()) +#define PURPLE_CHAT_USER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_CHAT_USER, PurpleChatUser)) +#define PURPLE_CHAT_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_CHAT_USER, PurpleChatUserClass)) +#define PURPLE_IS_CHAT_USER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_CHAT_USER)) +#define PURPLE_IS_CHAT_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_CHAT_USER)) +#define PURPLE_CHAT_USER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_CHAT_USER, PurpleChatUserClass)) + +/** @copydoc _PurpleChatUser */ +typedef struct _PurpleChatUser PurpleChatUser; +/** @copydoc _PurpleChatUserClass */ +typedef struct _PurpleChatUserClass PurpleChatUserClass; + +/** + * The typing state of a user. + */ +typedef enum +{ + PURPLE_IM_NOT_TYPING = 0, /**< Not typing. */ + PURPLE_IM_TYPING, /**< Currently typing. */ + PURPLE_IM_TYPED /**< Stopped typing momentarily. */ + +} PurpleIMTypingState; + +/** + * Flags applicable to users in Chats. + */ +typedef enum /*< flags >*/ +{ + PURPLE_CHAT_USER_NONE = 0x0000, /**< No flags */ + PURPLE_CHAT_USER_VOICE = 0x0001, /**< Voiced user or "Participant" */ + PURPLE_CHAT_USER_HALFOP = 0x0002, /**< Half-op */ + PURPLE_CHAT_USER_OP = 0x0004, /**< Channel Op or Moderator */ + PURPLE_CHAT_USER_FOUNDER = 0x0008, /**< Channel Founder */ + PURPLE_CHAT_USER_TYPING = 0x0010, /**< Currently typing */ + PURPLE_CHAT_USER_AWAY = 0x0020 /**< Currently away. */ + +} PurpleChatUserFlags; + +#include "conversation.h" + +/**************************************************************************/ +/** PurpleIMConversation */ +/**************************************************************************/ +/** Structure representing an IM conversation instance. */ +struct _PurpleIMConversation +{ + /*< private >*/ + PurpleConversation parent_object; +}; + +/** Base class for all #PurpleIMConversation's */ +struct _PurpleIMConversationClass { + /*< private >*/ + PurpleConversationClass parent_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/**************************************************************************/ +/** PurpleChatConversation */ +/**************************************************************************/ +/** Structure representing a chat conversation instance. */ +struct _PurpleChatConversation +{ + /*< private >*/ + PurpleConversation parent_object; +}; + +/** Base class for all #PurpleChatConversation's */ +struct _PurpleChatConversationClass { + /*< private >*/ + PurpleConversationClass parent_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/**************************************************************************/ +/** PurpleChatUser */ +/**************************************************************************/ +/** Structure representing a chat user instance. */ +struct _PurpleChatUser +{ + /*< private >*/ + GObject gparent; + + /** The UI data associated with this chat user. This is a convenience + * field provided to the UIs -- it is not used by the libpurple core. + */ + gpointer ui_data; +}; + +/** Base class for all #PurpleChatUser's */ +struct _PurpleChatUserClass { + /*< private >*/ + GObjectClass parent_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +/**************************************************************************/ +/** @name IM Conversation API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the IMConversation object. + */ +GType purple_im_conversation_get_type(void); + +/** + * Creates a new IM conversation. + * + * @param account The account opening the conversation window on the purple + * user's end. + * @param name Name of the buddy. + * + * @return The new conversation. + */ +PurpleIMConversation *purple_im_conversation_new(PurpleAccount *account, + const char *name); + +/** + * Sets the IM's buddy icon. + * + * This should only be called from within Purple. You probably want to + * call purple_buddy_icon_set_data(). + * + * @param im The IM. + * @param icon The buddy icon. + * + * @see purple_buddy_icon_set_data() + */ +void purple_im_conversation_set_icon(PurpleIMConversation *im, PurpleBuddyIcon *icon); + +/** + * Returns the IM's buddy icon. + * + * @param im The IM. + * + * @return The buddy icon. + */ +PurpleBuddyIcon *purple_im_conversation_get_icon(const PurpleIMConversation *im); + +/** + * Sets the IM's typing state. + * + * @param im The IM. + * @param state The typing state. + */ +void purple_im_conversation_set_typing_state(PurpleIMConversation *im, PurpleIMTypingState state); + +/** + * Returns the IM's typing state. + * + * @param im The IM. + * + * @return The IM's typing state. + */ +PurpleIMTypingState purple_im_conversation_get_typing_state(const PurpleIMConversation *im); + +/** + * Starts the IM's typing timeout. + * + * @param im The IM. + * @param timeout The timeout. + */ +void purple_im_conversation_start_typing_timeout(PurpleIMConversation *im, int timeout); + +/** + * Stops the IM's typing timeout. + * + * @param im The IM. + */ +void purple_im_conversation_stop_typing_timeout(PurpleIMConversation *im); + +/** + * Returns the IM's typing timeout. + * + * @param im The IM. + * + * @return The timeout. + */ +guint purple_im_conversation_get_typing_timeout(const PurpleIMConversation *im); + +/** + * Sets the quiet-time when no PURPLE_IM_TYPING messages will be sent. + * Few protocols need this (maybe only MSN). If the user is still + * typing after this quiet-period, then another PURPLE_IM_TYPING message + * will be sent. + * + * @param im The IM. + * @param val The number of seconds to wait before allowing another + * PURPLE_IM_TYPING message to be sent to the user. Or 0 to + * not send another PURPLE_IM_TYPING message. + */ +void purple_im_conversation_set_type_again(PurpleIMConversation *im, unsigned int val); + +/** + * Returns the time after which another PURPLE_IM_TYPING message should be sent. + * + * @param im The IM. + * + * @return The time in seconds since the epoch. Or 0 if no additional + * PURPLE_IM_TYPING message should be sent. + */ +time_t purple_im_conversation_get_type_again(const PurpleIMConversation *im); + +/** + * Starts the IM's type again timeout. + * + * @param im The IM. + */ +void purple_im_conversation_start_send_typed_timeout(PurpleIMConversation *im); + +/** + * Stops the IM's type again timeout. + * + * @param im The IM. + */ +void purple_im_conversation_stop_send_typed_timeout(PurpleIMConversation *im); + +/** + * Returns the IM's type again timeout interval. + * + * @param im The IM. + * + * @return The type again timeout interval. + */ +guint purple_im_conversation_get_send_typed_timeout(const PurpleIMConversation *im); + +/** + * Updates the visual typing notification for an IM conversation. + * + * @param im The IM. + */ +void purple_im_conversation_update_typing(PurpleIMConversation *im); + +/*@}*/ + +/**************************************************************************/ +/** @name Chat Conversation API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the ChatConversation object. + */ +GType purple_chat_conversation_get_type(void); + +/** + * Creates a new chat conversation. + * + * @param account The account opening the conversation window on the purple + * user's end. + * @param name The name of the conversation. + * + * @return The new conversation. + */ +PurpleChatConversation *purple_chat_conversation_new(PurpleAccount *account, + const char *name); + +/** + * Returns a list of users in the chat room. The members of the list + * are PurpleChatUser objects. + * + * @param chat The chat. + * + * @constreturn The list of users. + */ +GList *purple_chat_conversation_get_users(const PurpleChatConversation *chat); + +/** + * Ignores a user in a chat room. + * + * @param chat The chat. + * @param name The name of the user. + */ +void purple_chat_conversation_ignore(PurpleChatConversation *chat, const char *name); + +/** + * Unignores a user in a chat room. + * + * @param chat The chat. + * @param name The name of the user. + */ +void purple_chat_conversation_unignore(PurpleChatConversation *chat, const char *name); + +/** + * Sets the list of ignored users in the chat room. + * + * @param chat The chat. + * @param ignored The list of ignored users. + * + * @return The list passed. + */ +GList *purple_chat_conversation_set_ignored(PurpleChatConversation *chat, GList *ignored); + +/** + * Returns the list of ignored users in the chat room. + * + * @param chat The chat. + * + * @constreturn The list of ignored users. + */ +GList *purple_chat_conversation_get_ignored(const PurpleChatConversation *chat); + +/** + * Returns the actual name of the specified ignored user, if it exists in + * the ignore list. + * + * If the user found contains a prefix, such as '+' or '\@', this is also + * returned. The username passed to the function does not have to have this + * formatting. + * + * @param chat The chat. + * @param user The user to check in the ignore list. + * + * @return The ignored user if found, complete with prefixes, or @c NULL + * if not found. + */ +const char *purple_chat_conversation_get_ignored_user(const PurpleChatConversation *chat, + const char *user); + +/** + * Returns @c TRUE if the specified user is ignored. + * + * @param chat The chat. + * @param user The user. + * + * @return @c TRUE if the user is in the ignore list; @c FALSE otherwise. + */ +gboolean purple_chat_conversation_is_ignored_user(const PurpleChatConversation *chat, + const char *user); + +/** + * Sets the chat room's topic. + * + * @param chat The chat. + * @param who The user that set the topic. + * @param topic The topic. + */ +void purple_chat_conversation_set_topic(PurpleChatConversation *chat, const char *who, + const char *topic); + +/** + * Returns the chat room's topic. + * + * @param chat The chat. + * + * @return The chat's topic. + */ +const char *purple_chat_conversation_get_topic(const PurpleChatConversation *chat); + +/** + * Returns who set the chat room's topic. + * + * @param chat The chat. + * + * @return Who set the topic. + */ +const char *purple_chat_conversation_get_topic_who(const PurpleChatConversation *chat); + +/** + * Sets the chat room's ID. + * + * @param chat The chat. + * @param id The ID. + */ +void purple_chat_conversation_set_id(PurpleChatConversation *chat, int id); + +/** + * Returns the chat room's ID. + * + * @param chat The chat. + * + * @return The ID. + */ +int purple_chat_conversation_get_id(const PurpleChatConversation *chat); + +/** + * Adds a user to a chat. + * + * @param chat The chat. + * @param user The user to add. + * @param extra_msg An extra message to display with the join message. + * @param flags The users flags + * @param new_arrival Decides whether or not to show a join notice. + */ +void purple_chat_conversation_add_user(PurpleChatConversation *chat, const char *user, + const char *extra_msg, PurpleChatUserFlags flags, + gboolean new_arrival); + +/** + * Adds a list of users to a chat. + * + * The data is copied from @a users, @a extra_msgs, and @a flags, so it is up to + * the caller to free this list after calling this function. + * + * @param chat The chat. + * @param users The list of users to add. + * @param extra_msgs An extra message to display with the join message for each + * user. This list may be shorter than @a users, in which + * case, the users after the end of extra_msgs will not have + * an extra message. By extension, this means that extra_msgs + * can simply be @c NULL and none of the users will have an + * extra message. + * @param flags The list of flags for each user. + * @param new_arrivals Decides whether or not to show join notices. + */ +void purple_chat_conversation_add_users(PurpleChatConversation *chat, + GList *users, GList *extra_msgs, GList *flags, gboolean new_arrivals); + +/** + * Renames a user in a chat. + * + * @param chat The chat. + * @param old_user The old username. + * @param new_user The new username. + */ +void purple_chat_conversation_rename_user(PurpleChatConversation *chat, + const char *old_user, const char *new_user); + +/** + * Removes a user from a chat, optionally with a reason. + * + * It is up to the developer to free this list after calling this function. + * + * @param chat The chat. + * @param user The user that is being removed. + * @param reason The optional reason given for the removal. Can be @c NULL. + */ +void purple_chat_conversation_remove_user(PurpleChatConversation *chat, + const char *user, const char *reason); + +/** + * Removes a list of users from a chat, optionally with a single reason. + * + * @param chat The chat. + * @param users The users that are being removed. + * @param reason The optional reason given for the removal. Can be @c NULL. + */ +void purple_chat_conversation_remove_users(PurpleChatConversation *chat, + GList *users, const char *reason); + +/** + * Checks if a user is in a chat + * + * @param chat The chat. + * @param user The user to look for. + * + * @return TRUE if the user is in the chat, FALSE if not + */ +gboolean purple_chat_conversation_has_user(PurpleChatConversation *chat, + const char *user); + +/** + * Clears all users from a chat. + * + * @param chat The chat. + */ +void purple_chat_conversation_clear_users(PurpleChatConversation *chat); + +/** + * Sets your nickname (used for hilighting) for a chat. + * + * @param chat The chat. + * @param nick The nick. + */ +void purple_chat_conversation_set_nick(PurpleChatConversation *chat, + const char *nick); + +/** + * Gets your nickname (used for hilighting) for a chat. + * + * @param chat The chat. + * @return The nick. + */ +const char *purple_chat_conversation_get_nick(PurpleChatConversation *chat); + +/** + * Lets the core know we left a chat, without destroying it. + * Called from serv_got_chat_left(). + * + * @param chat The chat. + */ +void purple_chat_conversation_leave(PurpleChatConversation *chat); + +/** + * Find a chat user in a chat + * + * @param chat The chat. + * @param name The name of the chat user to find. + */ +PurpleChatUser *purple_chat_conversation_find_user(PurpleChatConversation *chat, + const char *name); + +/** + * Invite a user to a chat. + * The user will be prompted to enter the user's name or a message if one is + * not given. + * + * @param chat The chat. + * @param user The user to invite to the chat. + * @param message The message to send with the invitation. + * @param confirm Prompt before sending the invitation. The user is always + * prompted if either \a user or \a message is @c NULL. + */ +void purple_chat_conversation_invite_user(PurpleChatConversation *chat, + const char *user, const char *message, gboolean confirm); + +/** + * Returns true if we're no longer in this chat, + * and just left the window open. + * + * @param chat The chat. + * + * @return @c TRUE if we left the chat already, @c FALSE if + * we're still there. + */ +gboolean purple_chat_conversation_has_left(PurpleChatConversation *chat); + +/*@}*/ + +/**************************************************************************/ +/** @name Chat Conversation User API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the ChatConversationBuddy object. + */ +GType purple_chat_user_get_type(void); + +/** + * Set the chat conversation associated with this chat user. + * + * @param cb The chat user + * @param chat The chat conversation that the buddy belongs to. + */ +void purple_chat_user_set_chat(PurpleChatUser *cb, + PurpleChatConversation *chat); + +/** + * Get the chat conversation associated with this chat user. + * + * @param cb The chat user. + * + * @return The chat conversation that the buddy belongs to. + */ +PurpleChatConversation *purple_chat_user_get_chat(const PurpleChatUser *cb); + +/** + * Creates a new chat user + * + * @param chat The chat that the buddy belongs to. + * @param name The name. + * @param alias The alias. + * @param flags The flags. + * + * @return The new chat user + */ +PurpleChatUser *purple_chat_user_new(PurpleChatConversation *chat, + const char *name, const char *alias, PurpleChatUserFlags flags); + +/** + * Set the UI data associated with this chat user. + * + * @param cb The chat user + * @param ui_data A pointer to associate with this chat user. + */ +void purple_chat_user_set_ui_data(PurpleChatUser *cb, gpointer ui_data); + +/** + * Get the UI data associated with this chat user. + * + * @param cb The chat user. + * + * @return The UI data associated with this chat user. This is a + * convenience field provided to the UIs--it is not + * used by the libpurple core. + */ +gpointer purple_chat_user_get_ui_data(const PurpleChatUser *cb); + +/** + * Get the alias of a chat user + * + * @param cb The chat user. + * + * @return The alias of the chat user. + */ +const char *purple_chat_user_get_alias(const PurpleChatUser *cb); + +/** + * Get the name of a chat user + * + * @param cb The chat user. + * + * @return The name of the chat user. + */ +const char *purple_chat_user_get_name(const PurpleChatUser *cb); + +/** + * Set the flags of a chat user. + * + * @param cb The chat user. + * @param flags The new flags. + */ +void purple_chat_user_set_flags(PurpleChatUser *cb, PurpleChatUserFlags flags); + +/** + * Get the flags of a chat user. + * + * @param cb The chat user. + * + * @return The flags of the chat user. + */ +PurpleChatUserFlags purple_chat_user_get_flags(const PurpleChatUser *cb); + +/** + * Sets if this chat user is on the buddy list. + * + * @param cb The chat user. + * @param buddy TRUE if the chat user is on the buddy list. + */ +void purple_chat_user_set_buddy(const PurpleChatUser *cb, gboolean buddy); + +/** + * Indicates if this chat user is on the buddy list. + * + * @param cb The chat user. + * + * @return TRUE if the chat user is on the buddy list. + */ +gboolean purple_chat_user_is_buddy(const PurpleChatUser *cb); + +/*@}*/ + +G_END_DECLS + +#endif /* _PURPLE_CONVERSATION_TYPES_H_ */ diff --git a/libpurple/core.c b/libpurple/core.c index 3aa93a8572..0666624f10 100644 --- a/libpurple/core.c +++ b/libpurple/core.c @@ -43,7 +43,6 @@ #include "plugin.h" #include "pounce.h" #include "prefs.h" -#include "privacy.h" #include "proxy.h" #include "savedstatuses.h" #include "signals.h" @@ -135,13 +134,15 @@ purple_core_init(const char *ui) purple_signal_register(core, "uri-handler", purple_marshal_BOOLEAN__POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 3, - purple_value_new(PURPLE_TYPE_STRING), /* Protocol */ - purple_value_new(PURPLE_TYPE_STRING), /* Command */ - purple_value_new(PURPLE_TYPE_BOXED, "GHashTable *")); /* Parameters */ + G_TYPE_BOOLEAN, 3, + G_TYPE_STRING, /* Protocol */ + G_TYPE_STRING, /* Command */ + G_TYPE_POINTER); /* Parameters (GHashTable *) */ - purple_signal_register(core, "quitting", purple_marshal_VOID, NULL, 0); - purple_signal_register(core, "core-initialized", purple_marshal_VOID, NULL, 0); + purple_signal_register(core, "quitting", purple_marshal_VOID, G_TYPE_NONE, + 0); + purple_signal_register(core, "core-initialized", purple_marshal_VOID, + G_TYPE_NONE, 0); purple_core_print_version(); @@ -164,7 +165,6 @@ purple_core_init(const char *ui) purple_dbus_init(); #endif - purple_ciphers_init(); purple_cmds_init(); /* Since plugins get probed so early we should probably initialize their @@ -186,7 +186,7 @@ purple_core_init(const char *ui) /* Accounts use status, buddy icons and connection signals, so * initialize these before accounts */ - purple_status_init(); + purple_statuses_init(); purple_buddy_icons_init(); purple_connections_init(); @@ -198,7 +198,6 @@ purple_core_init(const char *ui) purple_blist_init(); purple_log_init(); purple_network_init(); - purple_privacy_init(); purple_pounces_init(); purple_proxy_init(); purple_dnsquery_init(); @@ -265,13 +264,12 @@ purple_core_quit(void) purple_idle_uninit(); purple_pounces_uninit(); purple_blist_uninit(); - purple_ciphers_uninit(); purple_notify_uninit(); purple_conversations_uninit(); purple_connections_uninit(); purple_buddy_icons_uninit(); purple_savedstatuses_uninit(); - purple_status_uninit(); + purple_statuses_uninit(); purple_accounts_uninit(); purple_keyring_uninit(); /* after accounts */ purple_sound_uninit(); diff --git a/libpurple/dbus-analyze-functions.py b/libpurple/dbus-analyze-functions.py index caa07e1187..59191fda4b 100644 --- a/libpurple/dbus-analyze-functions.py +++ b/libpurple/dbus-analyze-functions.py @@ -22,10 +22,10 @@ excluded = [\ # functions with untranslatable types are skipped, but this script # assumes that all non-pointer type names beginning with "Purple" # are enums, which is not true in this case. - "purple_conv_placement_add_fnc", - "purple_conv_placement_get_fnc", - "purple_conv_placement_get_current_func", - "purple_conv_placement_set_current_func", + "purple_conversation_placement_add_fnc", + "purple_conversation_placement_get_fnc", + "purple_conversation_placement_get_current_func", + "purple_conversation_placement_set_current_func", # Similar to the above: "purple_account_set_register_callback", @@ -70,11 +70,11 @@ constlists = [ "purple_account_option_get_list", "purple_connections_get_all", "purple_connections_get_connecting", - "purple_get_conversations", - "purple_get_ims", - "purple_get_chats", - "purple_conv_chat_get_users", - "purple_conv_chat_get_ignored", + "purple_conversations_get_all", + "purple_conversations_get_ims", + "purple_conversations_get_chats", + "purple_chat_conversation_get_users", + "purple_chat_conversation_get_ignored", "purple_mime_document_get_fields", "purple_mime_document_get_parts", "purple_mime_part_get_fields", diff --git a/libpurple/dbus-define-api.h b/libpurple/dbus-define-api.h index 7916ec744f..17bcd422ed 100644 --- a/libpurple/dbus-define-api.h +++ b/libpurple/dbus-define-api.h @@ -5,21 +5,10 @@ provides type information for the dbus-analyze-functions.py program, which makes these macros callable by DBUS. */ -/* blist.h */ -gboolean PURPLE_BLIST_NODE_IS_CHAT(PurpleBlistNode *node); -gboolean PURPLE_BLIST_NODE_IS_BUDDY(PurpleBlistNode *node); -gboolean PURPLE_BLIST_NODE_IS_CONTACT(PurpleBlistNode *node); -gboolean PURPLE_BLIST_NODE_IS_GROUP(PurpleBlistNode *node); +/* buddylist.h */ gboolean PURPLE_BUDDY_IS_ONLINE(PurpleBuddy *buddy); -gboolean PURPLE_BLIST_NODE_HAS_FLAG(PurpleBlistNode *node, int flags); -gboolean PURPLE_BLIST_NODE_SHOULD_SAVE(PurpleBlistNode *node); /* connection.h */ gboolean PURPLE_CONNECTION_IS_CONNECTED(PurpleConnection *connection); gboolean PURPLE_CONNECTION_IS_VALID(PurpleConnection *connection); -/* conversation.h */ -PurpleConvIm *PURPLE_CONV_IM(const PurpleConversation *conversation); -PurpleConvIm *PURPLE_CONV_CHAT(const PurpleConversation *conversation); - - diff --git a/libpurple/dbus-server.c b/libpurple/dbus-server.c index 63b8b82f5b..6c42592d8a 100644 --- a/libpurple/dbus-server.c +++ b/libpurple/dbus-server.c @@ -36,7 +36,7 @@ #include <string.h> #include "account.h" -#include "blist.h" +#include "buddylist.h" #include "conversation.h" #include "dbus-purple.h" #include "dbus-server.h" @@ -47,7 +47,6 @@ #include "savedstatuses.h" #include "smiley.h" #include "util.h" -#include "value.h" #include "xmlnode.h" @@ -628,13 +627,11 @@ purple_dbus_dispatch_init(void) purple_signal_register(purple_dbus_get_handle(), "dbus-method-called", purple_marshal_BOOLEAN__POINTER_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 2, - purple_value_new(PURPLE_TYPE_POINTER), - purple_value_new(PURPLE_TYPE_POINTER)); + G_TYPE_BOOLEAN, 2, G_TYPE_POINTER, G_TYPE_POINTER); purple_signal_register(purple_dbus_get_handle(), "dbus-introspect", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new_outgoing(PURPLE_TYPE_POINTER)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + G_TYPE_POINTER); /* pointer to a pointer */ PURPLE_DBUS_REGISTER_BINDINGS(purple_dbus_get_handle()); @@ -677,7 +674,7 @@ purple_dbus_convert_signal_name(const char *purple_name) static gboolean purple_dbus_message_append_purple_values(DBusMessageIter *iter, - int number, PurpleValue **purple_values, va_list data) + int number, GType *types, va_list data) { int i; gboolean error = FALSE; @@ -693,37 +690,36 @@ purple_dbus_message_append_purple_values(DBusMessageIter *iter, gboolean xboolean; gpointer ptr = NULL; gpointer val; - +#if 0 if (purple_value_is_outgoing(purple_values[i])) { ptr = my_arg(gpointer); g_return_val_if_fail(ptr, TRUE); } - - switch (purple_value_get_type(purple_values[i])) +#endif + switch (types[i]) { - case PURPLE_TYPE_INT: - case PURPLE_TYPE_ENUM: + case G_TYPE_INT: xint = my_arg(gint); dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &xint); break; - case PURPLE_TYPE_UINT: + case G_TYPE_UINT: xuint = my_arg(guint); dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &xuint); break; - case PURPLE_TYPE_INT64: + case G_TYPE_INT64: xint64 = my_arg(gint64); dbus_message_iter_append_basic(iter, DBUS_TYPE_INT64, &xint64); break; - case PURPLE_TYPE_UINT64: + case G_TYPE_UINT64: xuint64 = my_arg(guint64); dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64, &xuint64); break; - case PURPLE_TYPE_BOOLEAN: + case G_TYPE_BOOLEAN: xboolean = my_arg(gboolean); dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &xboolean); break; - case PURPLE_TYPE_STRING: + case G_TYPE_STRING: str = null_to_empty(my_arg(char*)); if (!g_utf8_validate(str, -1, NULL)) { gchar *tmp; @@ -735,19 +731,27 @@ purple_dbus_message_append_purple_values(DBusMessageIter *iter, dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &str); } break; - case PURPLE_TYPE_SUBTYPE: /* registered pointers only! */ - case PURPLE_TYPE_POINTER: - case PURPLE_TYPE_OBJECT: - case PURPLE_TYPE_BOXED: - val = my_arg(gpointer); - id = purple_dbus_pointer_to_id(val); - if (id == 0 && val != NULL) - error = TRUE; /* Some error happened. */ - dbus_message_iter_append_basic(iter, - (sizeof(id) == sizeof(dbus_int32_t)) ? DBUS_TYPE_INT32 : DBUS_TYPE_INT64, &id); - break; - default: /* no conversion implemented */ - g_return_val_if_reached(TRUE); + default: + if (G_TYPE_IS_OBJECT(types[i]) || + G_TYPE_IS_BOXED(types[i]) || + types[i] == G_TYPE_POINTER ) + { + val = my_arg(gpointer); + id = purple_dbus_pointer_to_id(val); + if (id == 0 && val != NULL) + error = TRUE; /* Some error happened. */ + dbus_message_iter_append_basic(iter, + (sizeof(id) == sizeof(dbus_int32_t)) ? DBUS_TYPE_INT32 : DBUS_TYPE_INT64, &id); + } + else if (G_TYPE_IS_ENUM(types[i])) + { + xint = my_arg(gint); + dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &xint); + } + else /* no conversion implemented */ + { + g_return_val_if_reached(TRUE); + } } } return error; @@ -757,7 +761,7 @@ purple_dbus_message_append_purple_values(DBusMessageIter *iter, void purple_dbus_signal_emit_purple(const char *name, int num_values, - PurpleValue **values, va_list vargs) + GType *types, va_list vargs) { DBusMessage *signal; DBusMessageIter iter; @@ -784,7 +788,7 @@ purple_dbus_signal_emit_purple(const char *name, int num_values, signal = dbus_message_new_signal(DBUS_PATH_PURPLE, DBUS_INTERFACE_PURPLE, newname); dbus_message_iter_init_append(signal, &iter); - if (purple_dbus_message_append_purple_values(&iter, num_values, values, vargs)) + if (purple_dbus_message_append_purple_values(&iter, num_values, types, vargs)) if (purple_debug_is_verbose()) purple_debug_warning("dbus", "The signal \"%s\" caused some dbus error." diff --git a/libpurple/dbus-server.h b/libpurple/dbus-server.h index 5810dab8c7..4425dc66e0 100644 --- a/libpurple/dbus-server.h +++ b/libpurple/dbus-server.h @@ -29,7 +29,6 @@ #define _PURPLE_DBUS_SERVER_H_ #include "dbus-purple.h" -#include "value.h" G_BEGIN_DECLS @@ -141,12 +140,11 @@ void purple_dbus_unregister_pointer(gpointer node); @param name The name of the signal ("bla-bla-blaa") @param num_values The number of parameters. - @param values Array of pointers to #PurpleValue objects representing - the types of the parameters. + @param types Array of GTypes representing the types of the parameters. @param vargs A va_list containing the actual parameters. */ void purple_dbus_signal_emit_purple(const char *name, int num_values, - PurpleValue **values, va_list vargs); + GType *types, va_list vargs); /** * Returns whether Purple's D-BUS subsystem is up and running. If it's diff --git a/libpurple/dbus-useful.c b/libpurple/dbus-useful.c index 4a685fc88f..99d456d4f3 100644 --- a/libpurple/dbus-useful.c +++ b/libpurple/dbus-useful.c @@ -2,6 +2,7 @@ #include <glib.h> #include "dbus-useful.h" +#include "accounts.h" #include "conversation.h" #include "util.h" diff --git a/libpurple/enums.c.template b/libpurple/enums.c.template new file mode 100644 index 0000000000..dd05073b96 --- /dev/null +++ b/libpurple/enums.c.template @@ -0,0 +1,64 @@ +/*** BEGIN file-header ***/ +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#if HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include "enums.h" + +/*** END file-header ***/ +/*** BEGIN file-production ***/ + +/* enumerations from "@filename@" */ +#include "@filename@" + +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type(void) { + static volatile gsize g_define_type_id__volatile = 0; + + if(g_once_init_enter(&g_define_type_id__volatile)) { + static const G@Type@Value values [] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + + GType g_define_type_id = + g_@type@_register_static(g_intern_static_string("@EnumName@"), values); + g_once_init_leave(&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} + +/*** END value-tail ***/ + +/*** BEGIN file-tail ***/ +/*** END file-tail ***/ diff --git a/libpurple/enums.h.template b/libpurple/enums.h.template new file mode 100644 index 0000000000..a29b432b41 --- /dev/null +++ b/libpurple/enums.h.template @@ -0,0 +1,45 @@ +/*** BEGIN file-header ***/ +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef PURPLE_ENUM_H +#define PURPLE_ENUM_H + +#include <glib-object.h> + +G_BEGIN_DECLS +/*** END file-header ***/ + +/*** BEGIN file-production ***/ + +/* enumerations from "@filename@" */ +/*** END file-production ***/ +/*** BEGIN value-header ***/ +GType @enum_name@_get_type(void) G_GNUC_CONST; +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) +/*** END value-header ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* PURPLE_ENUM_H */ + +/*** END file-tail ***/ + diff --git a/libpurple/ft.c b/libpurple/ft.c index 695400837f..22b81c8338 100644 --- a/libpurple/ft.c +++ b/libpurple/ft.c @@ -278,7 +278,7 @@ static void purple_xfer_conversation_write_internal(PurpleXfer *xfer, const char *message, gboolean is_error, gboolean print_thumbnail) { - PurpleConversation *conv = NULL; + PurpleIMConversation *im = NULL; PurpleMessageFlags flags = PURPLE_MESSAGE_SYSTEM; char *escaped; gconstpointer thumbnail_data; @@ -289,10 +289,10 @@ purple_xfer_conversation_write_internal(PurpleXfer *xfer, thumbnail_data = purple_xfer_get_thumbnail(xfer, &size); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, xfer->who, + im = purple_conversations_find_im_with_account(xfer->who, purple_xfer_get_account(xfer)); - if (conv == NULL) + if (im == NULL) return; escaped = g_markup_escape_text(message, -1); @@ -308,12 +308,13 @@ purple_xfer_conversation_write_internal(PurpleXfer *xfer, message_with_img = g_strdup_printf("<img src='" PURPLE_STORED_IMAGE_PROTOCOL "%d'> %s", id, escaped); - purple_conversation_write(conv, NULL, message_with_img, flags, - time(NULL)); + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, + message_with_img, flags, time(NULL)); purple_imgstore_unref_by_id(id); g_free(message_with_img); } else { - purple_conversation_write(conv, NULL, escaped, flags, time(NULL)); + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, escaped, flags, + time(NULL)); } g_free(escaped); } @@ -498,7 +499,7 @@ purple_xfer_ask_recv(PurpleXfer *xfer) /* If we have already accepted the request, ask the destination file name directly */ if (purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_ACCEPTED) { - PurpleBuddy *buddy = purple_find_buddy(xfer->account, xfer->who); + PurpleBuddy *buddy = purple_blist_find_buddy(xfer->account, xfer->who); if (purple_xfer_get_filename(xfer) != NULL) { @@ -558,7 +559,7 @@ static void purple_xfer_ask_accept(PurpleXfer *xfer) { char *buf, *buf2 = NULL; - PurpleBuddy *buddy = purple_find_buddy(xfer->account, xfer->who); + PurpleBuddy *buddy = purple_blist_find_buddy(xfer->account, xfer->who); buf = g_strdup_printf(_("Accept file transfer request from %s?"), buddy ? purple_buddy_get_alias(buddy) : xfer->who); @@ -598,7 +599,7 @@ purple_xfer_request(PurpleXfer *xfer) purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_ACCEPTED) { gchar* message = NULL; - PurpleBuddy *buddy = purple_find_buddy(xfer->account, xfer->who); + PurpleBuddy *buddy = purple_blist_find_buddy(xfer->account, xfer->who); message = g_strdup_printf(_("%s is offering to send file %s"), buddy ? purple_buddy_get_alias(buddy) : xfer->who, purple_xfer_get_filename(xfer)); @@ -643,7 +644,7 @@ purple_xfer_request_accepted(PurpleXfer *xfer, const char *filename) return; } - buddy = purple_find_buddy(account, xfer->who); + buddy = purple_blist_find_buddy(account, xfer->who); if (type == PURPLE_XFER_SEND) { /* Sending a file */ @@ -901,7 +902,7 @@ purple_xfer_set_completed(PurpleXfer *xfer, gboolean completed) if (completed == TRUE) { char *msg = NULL; - PurpleConversation *conv; + PurpleIMConversation *im; purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_DONE); @@ -924,11 +925,12 @@ purple_xfer_set_completed(PurpleXfer *xfer, gboolean completed) else msg = g_strdup(_("File transfer complete")); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, xfer->who, + im = purple_conversations_find_im_with_account(xfer->who, purple_xfer_get_account(xfer)); - if (conv != NULL) - purple_conversation_write(conv, NULL, msg, PURPLE_MESSAGE_SYSTEM, time(NULL)); + if (im != NULL) + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, msg, + PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(msg); } @@ -1670,7 +1672,7 @@ purple_xfer_cancel_remote(PurpleXfer *xfer) xfer->end_time = time(NULL); account = purple_xfer_get_account(xfer); - buddy = purple_find_buddy(account, xfer->who); + buddy = purple_blist_find_buddy(account, xfer->who); if (purple_xfer_get_filename(xfer) != NULL) { @@ -1730,7 +1732,7 @@ purple_xfer_error(PurpleXferType type, PurpleAccount *account, const char *who, if (account) { PurpleBuddy *buddy; - buddy = purple_find_buddy(account, who); + buddy = purple_blist_find_buddy(account, who); if (buddy) who = purple_buddy_get_alias(buddy); } @@ -1834,6 +1836,33 @@ gpointer purple_xfer_get_ui_data(const PurpleXfer *xfer) return xfer->ui_data; } +static PurpleXfer * +purple_xfer_copy(PurpleXfer *xfer) +{ + PurpleXfer *xfer_copy; + + g_return_val_if_fail(xfer != NULL, NULL); + + xfer_copy = g_new(PurpleXfer, 1); + *xfer_copy = *xfer; + + return xfer_copy; +} + +GType +purple_xfer_get_g_type(void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static("PurpleXfer", + (GBoxedCopyFunc)purple_xfer_copy, + (GBoxedFreeFunc)g_free); + } + + return type; +} + /************************************************************************** * File Transfer Subsystem API @@ -1854,41 +1883,32 @@ purple_xfers_init(void) { /* register signals */ purple_signal_register(handle, "file-recv-accept", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_XFER)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_XFER); purple_signal_register(handle, "file-send-accept", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_XFER)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_XFER); purple_signal_register(handle, "file-recv-start", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_XFER)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_XFER); purple_signal_register(handle, "file-send-start", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_XFER)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_XFER); purple_signal_register(handle, "file-send-cancel", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_XFER)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_XFER); purple_signal_register(handle, "file-recv-cancel", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_XFER)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_XFER); purple_signal_register(handle, "file-send-complete", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_XFER)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_XFER); purple_signal_register(handle, "file-recv-complete", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_XFER)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_XFER); purple_signal_register(handle, "file-recv-request", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_XFER)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_XFER); } void diff --git a/libpurple/ft.h b/libpurple/ft.h index 1de8469e50..b48a3a9bbf 100644 --- a/libpurple/ft.h +++ b/libpurple/ft.h @@ -27,6 +27,8 @@ #ifndef _PURPLE_FT_H_ #define _PURPLE_FT_H_ +#define PURPLE_TYPE_XFER (purple_xfer_get_g_type()) + /**************************************************************************/ /** Data Structures */ /**************************************************************************/ @@ -192,6 +194,13 @@ G_BEGIN_DECLS /*@{*/ /** + * Returns the GType for the PurpleXfer boxed structure. + * TODO Boxing of PurpleXfer is a temporary solution to having a GType for + * file transfers. This should rather be a GObject instead of a GBoxed. + */ +GType purple_xfer_get_g_type(void); + +/** * Creates a new file transfer handle. * This is called by prpls. * The handle starts with a ref count of 1, and this reference diff --git a/libpurple/hash.c b/libpurple/hash.c new file mode 100644 index 0000000000..8858707c27 --- /dev/null +++ b/libpurple/hash.c @@ -0,0 +1,268 @@ +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#include "internal.h" +#include "hash.h" +#include "debug.h" + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_hash_class_init(PurpleHashClass *klass) { + klass->reset = NULL; + klass->reset_state = NULL; + klass->append = NULL; + klass->digest = NULL; + klass->get_digest_size = NULL; + klass->get_block_size = NULL; + klass->get_name = NULL; +} + +/****************************************************************************** + * PurpleHash API + *****************************************************************************/ +const gchar * +purple_hash_get_name(PurpleHash *hash) { + PurpleHashClass *klass = NULL; + + g_return_val_if_fail(hash, NULL); + g_return_val_if_fail(PURPLE_IS_HASH(hash), NULL); + + klass = PURPLE_HASH_GET_CLASS(hash); + g_return_val_if_fail(klass->get_name, NULL); + + return klass->get_name(hash); +} + +GType +purple_hash_get_type(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleHashClass), + NULL, + NULL, + (GClassInitFunc)purple_hash_class_init, + NULL, + NULL, + sizeof(PurpleHash), + 0, + NULL, + NULL + }; + + type = g_type_register_static(G_TYPE_OBJECT, + "PurpleHash", + &info, G_TYPE_FLAG_ABSTRACT); + } + + return type; +} + +/** + * purple_hash_reset: + * @hash: The hash to reset + * + * Resets a hash to it's default value + * + * @note If you have set an IV you will have to set it after resetting + */ +void +purple_hash_reset(PurpleHash *hash) { + PurpleHashClass *klass = NULL; + + g_return_if_fail(PURPLE_IS_HASH(hash)); + + klass = PURPLE_HASH_GET_CLASS(hash); + + if(klass && klass->reset) + klass->reset(hash); + else + purple_debug_warning("hash", "the %s hash does not implement the " + "reset method\n", + klass->get_name ? klass->get_name(hash) : ""); +} + +/** + * Resets a hash state to it's default value, but doesn't touch stateless + * configuration. + * + * That means, IV and digest context will be wiped out, but keys, ops or salt + * will remain untouched. + */ +void +purple_hash_reset_state(PurpleHash *hash) { + PurpleHashClass *klass = NULL; + + g_return_if_fail(PURPLE_IS_HASH(hash)); + + klass = PURPLE_HASH_GET_CLASS(hash); + + if(klass && klass->reset_state) + klass->reset_state(hash); + else + purple_debug_warning("hash", "the %s hash does not implement the " + "reset_state method\n", + klass->get_name ? klass->get_name(hash) : ""); +} + +/** + * purple_hash_append: + * @hash: The hash to append data to + * @data: The data to append + * @len: The length of the data + * + * Appends data to the hash + */ +void +purple_hash_append(PurpleHash *hash, const guchar *data, + size_t len) +{ + PurpleHashClass *klass = NULL; + + g_return_if_fail(PURPLE_IS_HASH(hash)); + + klass = PURPLE_HASH_GET_CLASS(hash); + + if(klass && klass->append) + klass->append(hash, data, len); + else + purple_debug_warning("hash", "the %s hash does not implement the " + "append method\n", + klass->get_name ? klass->get_name(hash) : ""); +} + +/** + * purple_hash_digest: + * @hash: The hash to digest + * @in_len: The length of the buffer + * @digest: The return buffer for the digest + * @out_len: The length of the returned value + * + * Digests a hash + * + * Return Value: TRUE if the digest was successful, FALSE otherwise. + */ +gboolean +purple_hash_digest(PurpleHash *hash, guchar digest[], size_t len) +{ + PurpleHashClass *klass = NULL; + + g_return_val_if_fail(PURPLE_IS_HASH(hash), FALSE); + + klass = PURPLE_HASH_GET_CLASS(hash); + + if(klass && klass->digest) + return klass->digest(hash, digest, len); + else + purple_debug_warning("hash", "the %s hash does not implement the " + "digest method\n", + klass->get_name ? klass->get_name(hash) : ""); + + return FALSE; +} + +/** + * purple_hash_digest_to_str: + * @hash: The hash to get a digest from + * @in_len: The length of the buffer + * @digest_s: The return buffer for the string digest + * @out_len: The length of the returned value + * + * Converts a guchar digest into a hex string + * + * Return Value: TRUE if the digest was successful, FALSE otherwise. + */ +gboolean +purple_hash_digest_to_str(PurpleHash *hash, gchar digest_s[], size_t len) +{ + /* 8k is a bit excessive, will tweak later. */ + guchar digest[BUF_LEN * 4]; + gint n = 0; + size_t digest_size; + + g_return_val_if_fail(hash, FALSE); + g_return_val_if_fail(digest_s, FALSE); + + digest_size = purple_hash_get_digest_size(hash); + + g_return_val_if_fail(digest_size <= BUF_LEN * 4, FALSE); + + if(!purple_hash_digest(hash, digest, sizeof(digest))) + return FALSE; + + /* Every digest byte occupies 2 chars + the NUL at the end. */ + g_return_val_if_fail(digest_size * 2 + 1 <= len, FALSE); + + for(n = 0; n < digest_size; n++) + sprintf(digest_s + (n * 2), "%02x", digest[n]); + + digest_s[n * 2] = '\0'; + + return TRUE; +} + +size_t +purple_hash_get_digest_size(PurpleHash *hash) +{ + PurpleHashClass *klass = NULL; + + g_return_val_if_fail(PURPLE_IS_HASH(hash), FALSE); + + klass = PURPLE_HASH_GET_CLASS(hash); + + if(klass && klass->get_digest_size) + return klass->get_digest_size(hash); + else + purple_debug_warning("hash", "the %s hash does not implement the " + "get_digest_size method\n", + klass->get_name ? klass->get_name(hash) : ""); + + return FALSE; +} + +/** + * purple_hash_get_block_size: + * @hash: The hash whose block size to get + * + * Gets the block size of a hash + * + * Return Value: The block size of the hash + */ +size_t +purple_hash_get_block_size(PurpleHash *hash) +{ + PurpleHashClass *klass = NULL; + + g_return_val_if_fail(PURPLE_IS_HASH(hash), -1); + + klass = PURPLE_HASH_GET_CLASS(hash); + + if(klass && klass->get_block_size) + return klass->get_block_size(hash); + else + purple_debug_warning("hash", "the %s hash does not implement the " + "get_block_size method\n", + klass->get_name ? klass->get_name(hash) : ""); + + return -1; +} diff --git a/libpurple/hash.h b/libpurple/hash.h new file mode 100644 index 0000000000..640ebfbfab --- /dev/null +++ b/libpurple/hash.h @@ -0,0 +1,181 @@ +/** + * @file hash.h Purple Hash API + * @ingroup core + * @see @ref hash-signals + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef PURPLE_HASH_H +#define PURPLE_HASH_H + +#include <glib.h> +#include <glib-object.h> +#include <string.h> + +#include "internal.h" + +#define PURPLE_TYPE_HASH (purple_hash_get_type()) +#define PURPLE_HASH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_HASH, PurpleHash)) +#define PURPLE_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_HASH, PurpleHashClass)) +#define PURPLE_IS_HASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_HASH)) +#define PURPLE_IS_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_HASH)) +#define PURPLE_HASH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_HASH, PurpleHashClass)) + +typedef struct _PurpleHash PurpleHash; +typedef struct _PurpleHashClass PurpleHashClass; + +/** + * PurpleHash: + * + * Purple Hash is an opaque data structure and should not be used directly. + */ +struct _PurpleHash { + /*< private >*/ + GObject gparent; +}; + +/** + * PurpleHashClass: + * + * The base class for all #PurpleHash's. + */ +struct _PurpleHashClass { + /*< private >*/ + GObjectClass parent_class; + + /** The reset function */ + void (*reset)(PurpleHash *hash); + + /** The reset state function */ + void (*reset_state)(PurpleHash *hash); + + /** The append data function */ + void (*append)(PurpleHash *hash, const guchar *data, size_t len); + + /** The digest function */ + gboolean (*digest)(PurpleHash *hash, guchar digest[], size_t len); + + /** The get digest size function */ + size_t (*get_digest_size)(PurpleHash *hash); + + /** The get block size function */ + size_t (*get_block_size)(PurpleHash *hash); + + /** The get hash name function */ + const gchar* (*get_name)(PurpleHash *hash); + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +/*****************************************************************************/ +/** @name PurpleHash API */ +/*****************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the Hash object. + */ +GType purple_hash_get_type(void); + +/** + * Gets a hash's name + * + * @param hash The hash + * + * @return The hash's name + */ +const gchar *purple_hash_get_name(PurpleHash *hash); + +/** + * Resets a hash to it's default value + * @note If you have set an IV you will have to set it after resetting + * + * @param hash The hash + */ +void purple_hash_reset(PurpleHash *hash); + +/** + * Resets a hash state to it's default value, but doesn't touch stateless + * configuration. + * + * That means, IV and digest will be wiped out, but keys, ops or salt + * will remain untouched. + * + * @param hash The hash + */ +void purple_hash_reset_state(PurpleHash *hash); + +/** + * Appends data to the hash context + * + * @param hash The hash + * @param data The data to append + * @param len The length of the data + */ +void purple_hash_append(PurpleHash *hash, const guchar *data, size_t len); + +/** + * Digests a hash context + * + * @param hash The hash + * @param digest The return buffer for the digest + * @param len The length of the buffer + */ +gboolean purple_hash_digest(PurpleHash *hash, guchar digest[], size_t len); + +/** + * Converts a guchar digest into a hex string + * + * @param hash The hash + * @param digest_s The return buffer for the string digest + * @param len The length of the buffer + */ +gboolean purple_hash_digest_to_str(PurpleHash *hash, gchar digest_s[], size_t len); + +/** + * Gets the digest size of a hash + * + * @param hash The hash whose digest size to get + * + * @return The digest size of the hash + */ +size_t purple_hash_get_digest_size(PurpleHash *hash); + +/** + * Gets the block size of a hash + * + * @param hash The hash whose block size to get + * + * @return The block size of the hash + */ +size_t purple_hash_get_block_size(PurpleHash *hash); + +/*@}*/ + +G_END_DECLS + +#endif /* PURPLE_HASH_H */ diff --git a/libpurple/imgstore.c b/libpurple/imgstore.c index ec03c54ff0..d608ee55dc 100644 --- a/libpurple/imgstore.c +++ b/libpurple/imgstore.c @@ -214,10 +214,8 @@ purple_imgstore_init() void *handle = purple_imgstore_get_handle(); purple_signal_register(handle, "image-deleting", - purple_marshal_VOID__POINTER, NULL, - 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_STORED_IMAGE)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, + 1, PURPLE_TYPE_STORED_IMAGE); imgstore = g_hash_table_new(g_int_hash, g_int_equal); } @@ -229,3 +227,30 @@ purple_imgstore_uninit() purple_signals_unregister_by_instance(purple_imgstore_get_handle()); } + +static PurpleStoredImage * +purple_imgstore_copy(PurpleStoredImage *img) +{ + PurpleStoredImage *img_copy; + + g_return_val_if_fail(img != NULL, NULL); + + img_copy = g_new(PurpleStoredImage, 1); + *img_copy = *img; + + return img_copy; +} + +GType +purple_imgstore_get_type(void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static("PurpleStoredImage", + (GBoxedCopyFunc)purple_imgstore_copy, + (GBoxedFreeFunc)g_free); + } + + return type; +} diff --git a/libpurple/imgstore.h b/libpurple/imgstore.h index 4782ba2cd2..6c640db9c8 100644 --- a/libpurple/imgstore.h +++ b/libpurple/imgstore.h @@ -37,9 +37,18 @@ */ typedef struct _PurpleStoredImage PurpleStoredImage; +#define PURPLE_TYPE_STORED_IMAGE (purple_imgstore_get_type()) + G_BEGIN_DECLS /** + * Returns the GType for the PurpleStoredImage boxed structure. + * TODO Boxing of PurpleStoredImage is a temporary solution to having a GType + * for stored images. This should rather be a GObject instead of a GBoxed. + */ +GType purple_imgstore_get_type(void); + +/** * Create a new PurpleStoredImage. * * The image is not added to the image store and no ID is assigned. If you diff --git a/libpurple/internal.h b/libpurple/internal.h index a7b9d1f35f..2a4c0a65b4 100644 --- a/libpurple/internal.h +++ b/libpurple/internal.h @@ -156,7 +156,7 @@ /* INTERNAL FUNCTIONS */ -#include "account.h" +#include "accounts.h" #include "connection.h" /* This is for the accounts code to notify the buddy icon code that @@ -203,14 +203,36 @@ void _purple_connection_new(PurpleAccount *account, gboolean regist, void _purple_connection_new_unregister(PurpleAccount *account, const char *password, PurpleAccountUnregistrationCb cb, void *user_data); /** - * Disconnects and destroys a PurpleConnection. + * Checks if a connection is disconnecting, and should not attempt to reconnect. * - * @note This function should only be called by purple_account_disconnect() - * in account.c. If you're trying to sign off an account, use that - * function instead. + * @note This function should only be called by purple_account_set_enabled() + * in account.c. + * + * @param gc The connection to check + */ +gboolean _purple_connection_wants_to_die(const PurpleConnection *gc); + +/** + * Adds a chat to the active chats list of a connection + * + * @note This function should only be called by serv_got_joined_chat() + * in server.c. + * + * @param gc The connection + * @param chat The chat conversation to add + */ +void _purple_connection_add_active_chat(PurpleConnection *gc, + PurpleChatConversation *chat); +/** + * Removes a chat from the active chats list of a connection + * + * @note This function should only be called by serv_got_chat_left() + * in server.c. * - * @param gc The purple connection to destroy. + * @param gc The connection + * @param chat The chat conversation to remove */ -void _purple_connection_destroy(PurpleConnection *gc); +void _purple_connection_remove_active_chat(PurpleConnection *gc, + PurpleChatConversation *chat); #endif /* _PURPLE_INTERNAL_H_ */ diff --git a/libpurple/keyring.c b/libpurple/keyring.c index 5ab9b425a8..abcf0639a0 100644 --- a/libpurple/keyring.c +++ b/libpurple/keyring.c @@ -1245,12 +1245,9 @@ purple_keyring_init(void) * @param keyring_id The keyring ID. * @param keyring The keyring. */ - purple_signal_register(purple_keyring_get_handle(), - "keyring-register", - purple_marshal_VOID__POINTER_POINTER, - NULL, 2, - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_BOXED, "PurpleKeyring *")); + purple_signal_register(purple_keyring_get_handle(), "keyring-register", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, G_TYPE_STRING, + PURPLE_TYPE_KEYRING); /* void keyring_unregister(const char *keyring_id, * PurpleKeyring * keyring); @@ -1260,12 +1257,9 @@ purple_keyring_init(void) * @param keyring_id The keyring ID. * @param keyring The keyring. */ - purple_signal_register(purple_keyring_get_handle(), - "keyring-unregister", - purple_marshal_VOID__POINTER_POINTER, - NULL, 2, - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_BOXED, "PurpleKeyring *")); + purple_signal_register(purple_keyring_get_handle(), "keyring-unregister", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, G_TYPE_STRING, + PURPLE_TYPE_KEYRING); /* void password_migration(PurpleAccount* account); * @@ -1274,11 +1268,8 @@ purple_keyring_init(void) * * @param account The account. */ - purple_signal_register(purple_keyring_get_handle(), - "password-migration", - purple_marshal_VOID__POINTER, - NULL, 1, - purple_value_new(PURPLE_TYPE_BOXED, "PurpleAccount *")); + purple_signal_register(purple_keyring_get_handle(), "password-migration", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, PURPLE_TYPE_ACCOUNT); touse = purple_prefs_get_string("/purple/keyring/active"); if (touse == NULL) { @@ -1356,3 +1347,33 @@ purple_keyring_get_handle(void) return &handle; } + +static PurpleKeyring * +purple_keyring_copy(PurpleKeyring *keyring) +{ + PurpleKeyring *keyring_copy; + + g_return_val_if_fail(keyring != NULL, NULL); + + keyring_copy = purple_keyring_new(); + *keyring_copy = *keyring; + + keyring_copy->name = g_strdup(keyring->name); + keyring_copy->id = g_strdup(keyring->id); + + return keyring_copy; +} + +GType +purple_keyring_get_type(void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static("PurpleKeyring", + (GBoxedCopyFunc)purple_keyring_copy, + (GBoxedFreeFunc)purple_keyring_free); + } + + return type; +} diff --git a/libpurple/keyring.h b/libpurple/keyring.h index 9bed5fe5e6..059a282cba 100644 --- a/libpurple/keyring.h +++ b/libpurple/keyring.h @@ -30,6 +30,8 @@ #include "account.h" #include "request.h" +#define PURPLE_TYPE_KEYRING (purple_keyring_get_type()) + /** * Default keyring ID. */ @@ -358,6 +360,11 @@ purple_keyring_apply_settings(void *notify_handle, PurpleRequestFields *fields); /*@{*/ /** + * Returns the GType for the PurpleKeyring boxed structure. + */ +GType purple_keyring_get_type(void); + +/** * Creates a new keyring wrapper. */ PurpleKeyring * diff --git a/libpurple/log.c b/libpurple/log.c index 523676e501..76bb7e74b8 100644 --- a/libpurple/log.c +++ b/libpurple/log.c @@ -700,17 +700,16 @@ void purple_log_init(void) #else #error Unknown size of time_t #endif - purple_value_new(PURPLE_TYPE_STRING), 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_LOG), + G_TYPE_STRING, 3, + PURPLE_TYPE_LOG, #if SIZEOF_TIME_T == 4 - purple_value_new(PURPLE_TYPE_INT), + G_TYPE_INT, #elif SIZEOF_TIME_T == 8 - purple_value_new(PURPLE_TYPE_INT64), + G_TYPE_INT64, #else # error Unknown size of time_t #endif - purple_value_new(PURPLE_TYPE_BOOLEAN)); + G_TYPE_BOOLEAN); purple_prefs_connect_callback(NULL, "/purple/logging/format", logger_pref_cb, NULL); @@ -745,6 +744,33 @@ purple_log_uninit(void) g_hash_table_destroy(logsize_users_decayed); } +static PurpleLog * +purple_log_copy(PurpleLog *log) +{ + PurpleLog *log_copy; + + g_return_val_if_fail(log != NULL, NULL); + + log_copy = g_new(PurpleLog, 1); + *log_copy = *log; + + return log_copy; +} + +GType +purple_log_get_type(void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static("PurpleLog", + (GBoxedCopyFunc)purple_log_copy, + (GBoxedFreeFunc)g_free); + } + + return type; +} + /**************************************************************************** * LOGGERS ****************************************************************** ****************************************************************************/ @@ -1150,7 +1176,7 @@ static void log_get_log_sets_common(GHashTable *sets) /* Determine if this (account, name) combination exists as a buddy. */ if (account != NULL && *name != '\0') - set->buddy = (purple_find_buddy(account, name) != NULL); + set->buddy = (purple_blist_find_buddy(account, name) != NULL); else set->buddy = FALSE; @@ -2025,14 +2051,14 @@ static void old_logger_get_log_sets(PurpleLogSetCallback cb, GHashTable *sets) !found && gnode != NULL; gnode = purple_blist_node_get_sibling_next(gnode)) { - if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) + if (!PURPLE_IS_GROUP(gnode)) continue; for (cnode = purple_blist_node_get_first_child(gnode); !found && cnode != NULL; cnode = purple_blist_node_get_sibling_next(cnode)) { - if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) + if (!PURPLE_IS_CONTACT(cnode)) continue; for (bnode = purple_blist_node_get_first_child(cnode); diff --git a/libpurple/log.h b/libpurple/log.h index 1e12844d5a..71939ecc9a 100644 --- a/libpurple/log.h +++ b/libpurple/log.h @@ -29,6 +29,7 @@ #include <stdio.h> +#define PURPLE_TYPE_LOG (purple_log_get_type()) /******************************************************** * DATA STRUCTURES ************************************** @@ -189,6 +190,13 @@ G_BEGIN_DECLS /*@{*/ /** + * Returns the GType for the PurpleLog boxed structure. + * TODO Boxing of PurpleLog is a temporary solution to having a GType for + * logs. This should rather be a GObject instead of a GBoxed. + */ +GType purple_log_get_type(void); + +/** * Creates a new log * * @param type The type of log this is. diff --git a/libpurple/media.c b/libpurple/media.c index d8bba699cf..fd6a981fff 100644 --- a/libpurple/media.c +++ b/libpurple/media.c @@ -44,23 +44,6 @@ typedef struct _PurpleMediaSession PurpleMediaSession; /** @copydoc _PurpleMediaStream */ typedef struct _PurpleMediaStream PurpleMediaStream; -/** @copydoc _PurpleMediaClass */ -typedef struct _PurpleMediaClass PurpleMediaClass; -/** @copydoc _PurpleMediaPrivate */ -typedef struct _PurpleMediaPrivate PurpleMediaPrivate; - -/** The media class */ -struct _PurpleMediaClass -{ - GObjectClass parent_class; /**< The parent class. */ -}; - -/** The media class's private data */ -struct _PurpleMedia -{ - GObject parent; /**< The parent of this object. */ - PurpleMediaPrivate *priv; /**< The private data of this object. */ -}; struct _PurpleMediaSession { @@ -215,9 +198,8 @@ purple_media_class_init (PurpleMediaClass *klass) G_PARAM_READABLE)); g_object_class_install_property(gobject_class, PROP_ACCOUNT, - g_param_spec_pointer("account", - "PurpleAccount", - "The account this media session is on.", + g_param_spec_object("account", "PurpleAccount", + "The account this media session is on.", PURPLE_TYPE_ACCOUNT, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); g_object_class_install_property(gobject_class, PROP_CONFERENCE_TYPE, @@ -377,7 +359,7 @@ purple_media_set_property (GObject *object, guint prop_id, const GValue *value, media->priv->manager = g_value_dup_object(value); break; case PROP_ACCOUNT: - media->priv->account = g_value_get_pointer(value); + media->priv->account = g_value_get_object(value); break; case PROP_CONFERENCE_TYPE: media->priv->conference_type = @@ -438,7 +420,7 @@ purple_media_get_property (GObject *object, guint prop_id, GValue *value, GParam g_value_set_object(value, media->priv->backend); break; case PROP_ACCOUNT: - g_value_set_pointer(value, media->priv->account); + g_value_set_object(value, media->priv->account); break; case PROP_CONFERENCE_TYPE: g_value_set_string(value, diff --git a/libpurple/media.h b/libpurple/media.h index b55ed14f69..243f49691e 100644 --- a/libpurple/media.h +++ b/libpurple/media.h @@ -41,12 +41,39 @@ #define PURPLE_IS_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_MEDIA)) #define PURPLE_MEDIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MEDIA, PurpleMediaClass)) -/** An opaque structure representing a media call. */ +/** A structure representing a media call. */ typedef struct _PurpleMedia PurpleMedia; #include "signals.h" #include "util.h" +#ifdef USE_VV + +/** @copydoc _PurpleMediaClass */ +typedef struct _PurpleMediaClass PurpleMediaClass; +/** @copydoc _PurpleMediaPrivate */ +typedef struct _PurpleMediaPrivate PurpleMediaPrivate; + +/** The media instance */ +struct _PurpleMedia +{ + GObject parent; /**< The parent of this object. */ + PurpleMediaPrivate *priv; /**< The private data of this object. */ +}; + +/** The media class */ +struct _PurpleMediaClass +{ + GObjectClass parent_class; /**< The parent class. */ + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); +}; + +#endif + G_BEGIN_DECLS /** diff --git a/libpurple/network.c b/libpurple/network.c index 4ed7711977..4cae6ad676 100644 --- a/libpurple/network.c +++ b/libpurple/network.c @@ -1221,7 +1221,7 @@ purple_network_init(void) #endif purple_signal_register(purple_network_get_handle(), "network-configuration-changed", - purple_marshal_VOID, NULL, 0); + purple_marshal_VOID, G_TYPE_NONE, 0); purple_pmp_init(); purple_upnp_init(); diff --git a/libpurple/notify.c b/libpurple/notify.c index 7d94b5da2e..c513e96a95 100644 --- a/libpurple/notify.c +++ b/libpurple/notify.c @@ -453,7 +453,7 @@ purple_notify_user_info_entry_new(const char *label, const char *value) return user_info_entry; } -static void +void purple_notify_user_info_entry_destroy(PurpleNotifyUserInfoEntry *user_info_entry) { g_return_if_fail(user_info_entry != NULL); @@ -692,6 +692,42 @@ purple_notify_user_info_remove_last_item(PurpleNotifyUserInfo *user_info) purple_notify_user_info_entry_destroy(entry); } +static PurpleNotifyUserInfo * +purple_notify_user_info_copy(PurpleNotifyUserInfo *user_info) +{ + PurpleNotifyUserInfo *user_info_copy; + GList *l; + + g_return_val_if_fail(user_info != NULL, NULL); + + user_info_copy = purple_notify_user_info_new(); + + for (l = user_info->entries.head; l != NULL; l = l->next) { + PurpleNotifyUserInfoEntry *new_entry, *user_info_entry = l->data; + + new_entry = purple_notify_user_info_entry_new(user_info_entry->label, + user_info_entry->value); + new_entry->type = user_info_entry->type; + g_queue_push_tail(&user_info_copy->entries, new_entry); + } + + return user_info_copy; +} + +GType +purple_notify_user_info_get_type(void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static("PurpleNotifyUserInfo", + (GBoxedCopyFunc)purple_notify_user_info_copy, + (GBoxedFreeFunc)purple_notify_user_info_destroy); + } + + return type; +} + void * purple_notify_uri(void *handle, const char *uri) { @@ -804,30 +840,22 @@ purple_notify_init(void) gpointer handle = purple_notify_get_handle(); purple_signal_register(handle, "displaying-email-notification", - purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER, NULL, 4, - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); + purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER, + G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING); purple_signal_register(handle, "displaying-emails-notification", - purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, NULL, 5, - purple_value_new(PURPLE_TYPE_POINTER), - purple_value_new(PURPLE_TYPE_POINTER), - purple_value_new(PURPLE_TYPE_POINTER), - purple_value_new(PURPLE_TYPE_POINTER), - purple_value_new(PURPLE_TYPE_UINT)); + purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, + G_TYPE_NONE, 5, G_TYPE_POINTER, G_TYPE_POINTER, + G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_UINT); purple_signal_register(handle, "displaying-emails-clear", - purple_marshal_VOID, NULL, 0); + purple_marshal_VOID, G_TYPE_NONE, 0); purple_signal_register(handle, "displaying-userinfo", - purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_USERINFO)); + purple_marshal_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + PURPLE_TYPE_NOTIFY_USER_INFO); } void diff --git a/libpurple/notify.h b/libpurple/notify.h index ea7ab2b7c5..0c8ebc2f18 100644 --- a/libpurple/notify.h +++ b/libpurple/notify.h @@ -32,7 +32,10 @@ #include <glib.h> typedef struct _PurpleNotifyUserInfoEntry PurpleNotifyUserInfoEntry; + +#define PURPLE_TYPE_NOTIFY_USER_INFO (purple_notify_user_info_get_type()) typedef struct _PurpleNotifyUserInfo PurpleNotifyUserInfo; + /** @copydoc _PurpleNotifySearchColumn */ typedef struct _PurpleNotifySearchColumn PurpleNotifySearchColumn; @@ -422,6 +425,11 @@ void *purple_notify_userinfo(PurpleConnection *gc, const char *who, gpointer user_data); /** + * Returns the GType for the PurpleNotifyUserInfo boxed structure. + */ +GType purple_notify_user_info_get_type(void); + +/** * Create a new PurpleNotifyUserInfo which is suitable for passing to * purple_notify_userinfo() * @@ -501,21 +509,14 @@ void purple_notify_user_info_prepend_pair_html(PurpleNotifyUserInfo *user_info, */ void purple_notify_user_info_prepend_pair_plaintext(PurpleNotifyUserInfo *user_info, const char *label, const char *value); -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_NOTIFY_C_) /** * Remove a PurpleNotifyUserInfoEntry from a PurpleNotifyUserInfo object * without freeing the entry. * * @param user_info The PurpleNotifyUserInfo * @param user_info_entry The PurpleNotifyUserInfoEntry - * - * @deprecated Nothing is using this function and it should be removed - * in 3.0.0. Or, if we decide we want to keep it in 3.0.0 - * then we should make purple_notify_user_info_entry_destroy - * public so that entries can be free'd after they're removed. */ void purple_notify_user_info_remove_entry(PurpleNotifyUserInfo *user_info, PurpleNotifyUserInfoEntry *user_info_entry); -#endif /** * Create a new PurpleNotifyUserInfoEntry @@ -541,6 +542,13 @@ void purple_notify_user_info_remove_entry(PurpleNotifyUserInfo *user_info, Purpl PurpleNotifyUserInfoEntry *purple_notify_user_info_entry_new(const char *label, const char *value); /** + * Destroy a PurpleNotifyUserInfoEntry + * + * @param user_info_entry The PurpleNotifyUserInfoEntry + */ +void purple_notify_user_info_entry_destroy(PurpleNotifyUserInfoEntry *user_info_entry); + +/** * Add a section break. A UI might display this as a horizontal line. * * @param user_info The PurpleNotifyUserInfo diff --git a/libpurple/ntlm.c b/libpurple/ntlm.c index 82a865c9b4..0934d92a33 100644 --- a/libpurple/ntlm.c +++ b/libpurple/ntlm.c @@ -28,8 +28,11 @@ #include "util.h" #include "ntlm.h" -#include "cipher.h" #include "debug.h" + +#include "ciphers/descipher.h" +#include "ciphers/md4hash.h" + #include <string.h> #define NTLM_NEGOTIATE_NTLM2_KEY 0x00080000 @@ -191,13 +194,11 @@ static void des_ecb_encrypt(const guint8 *plaintext, guint8 *result, const guint8 *key) { PurpleCipher *cipher; - PurpleCipherContext *context; - cipher = purple_ciphers_find_cipher("des"); - context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_set_key(context, key, 8); - purple_cipher_context_encrypt(context, plaintext, 8, result, 8); - purple_cipher_context_destroy(context); + cipher = purple_des_cipher_new(); + purple_cipher_set_key(cipher, key, 8); + purple_cipher_encrypt(cipher, plaintext, 8, result, 8); + g_object_unref(cipher); } /* @@ -273,8 +274,7 @@ purple_ntlm_gen_type3(const gchar *username, const gchar *passw, const gchar *ho unsigned char magic[] = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }; unsigned char nt_hpw[21]; char nt_pw[128]; - PurpleCipher *cipher; - PurpleCipherContext *context; + PurpleHash *hash; char *tmp; int idx; gchar *ucs2le; @@ -375,11 +375,10 @@ purple_ntlm_gen_type3(const gchar *username, const gchar *passw, const gchar *ho nt_pw[2 * idx + 1] = 0; } - cipher = purple_ciphers_find_cipher("md4"); - context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, (guint8 *)nt_pw, 2 * lennt); - purple_cipher_context_digest(context, nt_hpw, sizeof(nt_hpw)); - purple_cipher_context_destroy(context); + hash = purple_md4_hash_new(); + purple_hash_append(hash, (guint8 *)nt_pw, 2 * lennt); + purple_hash_digest(hash, nt_hpw, sizeof(nt_hpw)); + g_object_unref(hash); memset(nt_hpw + 16, 0, 5); calc_resp(nt_hpw, nonce, nt_resp); diff --git a/libpurple/plugin.c b/libpurple/plugin.c index 1f92c4b34a..40739d518e 100644 --- a/libpurple/plugin.c +++ b/libpurple/plugin.c @@ -49,8 +49,8 @@ typedef struct PurpleSignalMarshalFunc marshal; int num_params; - PurpleValue **params; - PurpleValue *ret_value; + GType *param_types; + GType ret_type; } PurplePluginIpcCommand; @@ -962,26 +962,15 @@ static void destroy_ipc_info(void *data) { PurplePluginIpcCommand *ipc_command = (PurplePluginIpcCommand *)data; - int i; - - if (ipc_command->params != NULL) - { - for (i = 0; i < ipc_command->num_params; i++) - purple_value_destroy(ipc_command->params[i]); - - g_free(ipc_command->params); - } - - if (ipc_command->ret_value != NULL) - purple_value_destroy(ipc_command->ret_value); + g_free(ipc_command->param_types); g_free(ipc_command); } gboolean purple_plugin_ipc_register(PurplePlugin *plugin, const char *command, PurpleCallback func, PurpleSignalMarshalFunc marshal, - PurpleValue *ret_value, int num_params, ...) + GType ret_type, int num_params, ...) { PurplePluginIpcInfo *ipc_info; PurplePluginIpcCommand *ipc_command; @@ -1004,19 +993,19 @@ purple_plugin_ipc_register(PurplePlugin *plugin, const char *command, ipc_command->func = func; ipc_command->marshal = marshal; ipc_command->num_params = num_params; - ipc_command->ret_value = ret_value; + ipc_command->ret_type = ret_type; if (num_params > 0) { va_list args; int i; - ipc_command->params = g_new0(PurpleValue *, num_params); + ipc_command->param_types = g_new0(GType, num_params); va_start(args, num_params); for (i = 0; i < num_params; i++) - ipc_command->params[i] = va_arg(args, PurpleValue *); + ipc_command->param_types[i] = va_arg(args, GType); va_end(args); } @@ -1079,9 +1068,9 @@ purple_plugin_ipc_unregister_all(PurplePlugin *plugin) } gboolean -purple_plugin_ipc_get_params(PurplePlugin *plugin, const char *command, - PurpleValue **ret_value, int *num_params, - PurpleValue ***params) +purple_plugin_ipc_get_types(PurplePlugin *plugin, const char *command, + GType *ret_type, int *num_params, + GType **param_types) { PurplePluginIpcInfo *ipc_info; PurplePluginIpcCommand *ipc_command; @@ -1105,11 +1094,11 @@ purple_plugin_ipc_get_params(PurplePlugin *plugin, const char *command, if (num_params != NULL) *num_params = ipc_command->num_params; - if (params != NULL) - *params = ipc_command->params; + if (param_types != NULL) + *param_types = ipc_command->param_types; - if (ret_value != NULL) - *ret_value = ipc_command->ret_value; + if (ret_type != NULL) + *ret_type = ipc_command->ret_type; return TRUE; } @@ -1170,14 +1159,10 @@ purple_plugins_init(void) { purple_signal_register(handle, "plugin-load", purple_marshal_VOID__POINTER, - NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_PLUGIN)); + G_TYPE_NONE, 1, PURPLE_TYPE_PLUGIN); purple_signal_register(handle, "plugin-unload", purple_marshal_VOID__POINTER, - NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_PLUGIN)); + G_TYPE_NONE, 1, PURPLE_TYPE_PLUGIN); } void @@ -1612,3 +1597,30 @@ purple_plugin_action_free(PurplePluginAction *action) g_free(action->label); g_free(action); } + +static PurplePlugin * +purple_plugin_copy(PurplePlugin *plugin) +{ + PurplePlugin *plugin_copy; + + g_return_val_if_fail(plugin != NULL, NULL); + + plugin_copy = g_new(PurplePlugin, 1); + *plugin_copy = *plugin; + + return plugin_copy; +} + +GType +purple_plugin_get_type(void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static("PurplePlugin", + (GBoxedCopyFunc)purple_plugin_copy, + (GBoxedFreeFunc)g_free); + } + + return type; +} diff --git a/libpurple/plugin.h b/libpurple/plugin.h index d4b543cadd..6e9b2f5ec4 100644 --- a/libpurple/plugin.h +++ b/libpurple/plugin.h @@ -32,7 +32,9 @@ #include <glib.h> #include <gmodule.h> #include "signals.h" -#include "value.h" + +/** Returns the GType for the PurplePlugin boxed structure */ +#define PURPLE_TYPE_PLUGIN (purple_plugin_get_type()) /** @copydoc _PurplePlugin */ typedef struct _PurplePlugin PurplePlugin; @@ -247,6 +249,13 @@ G_BEGIN_DECLS /*@{*/ /** + * Returns the GType for the PurplePlugin boxed structure. + * TODO Boxing of PurplePlugin is a temporary solution to having a GType for + * plugins. This should rather be a GObject instead of a GBoxed. + */ +GType purple_plugin_get_type(void); + +/** * Creates a new plugin structure. * * @param native Whether or not the plugin is native. @@ -437,7 +446,7 @@ const gchar *purple_plugin_get_homepage(const PurplePlugin *plugin); * @param command The name of the command. * @param func The function to execute. * @param marshal The marshalling function. - * @param ret_value The return value type. + * @param ret_type The return type. * @param num_params The number of parameters. * @param ... The parameter types. * @@ -447,7 +456,7 @@ const gchar *purple_plugin_get_homepage(const PurplePlugin *plugin); gboolean purple_plugin_ipc_register(PurplePlugin *plugin, const char *command, PurpleCallback func, PurpleSignalMarshalFunc marshal, - PurpleValue *ret_value, int num_params, ...); + GType ret_type, int num_params, ...); /** * Unregisters an IPC command in a plugin. @@ -467,17 +476,17 @@ void purple_plugin_ipc_unregister_all(PurplePlugin *plugin); /** * Returns a list of value types used for an IPC command. * - * @param plugin The plugin. - * @param command The name of the command. - * @param ret_value The returned return value. - * @param num_params The returned number of parameters. - * @param params The returned list of parameters. + * @param plugin The plugin. + * @param command The name of the command. + * @param ret_type The returned return type. + * @param num_params The returned number of parameters. + * @param param_types The returned list of parameter types. * * @return TRUE if the command was found, or FALSE otherwise. */ -gboolean purple_plugin_ipc_get_params(PurplePlugin *plugin, const char *command, - PurpleValue **ret_value, int *num_params, - PurpleValue ***params); +gboolean purple_plugin_ipc_get_types(PurplePlugin *plugin, const char *command, + GType *ret_type, int *num_params, + GType **param_types); /** * Executes an IPC command. diff --git a/libpurple/plugins/autoaccept.c b/libpurple/plugins/autoaccept.c index 82b9278912..835574b84b 100644 --- a/libpurple/plugins/autoaccept.c +++ b/libpurple/plugins/autoaccept.c @@ -34,7 +34,7 @@ #include <plugin.h> #include <version.h> -#include <blist.h> +#include <buddylist.h> #include <conversation.h> #include <ft.h> #include <request.h> @@ -73,7 +73,7 @@ static void auto_accept_complete_cb(PurpleXfer *xfer, PurpleXfer *my) { if (xfer == my && purple_prefs_get_bool(PREF_NOTIFY) && - !purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_xfer_get_remote_user(xfer), purple_xfer_get_account(xfer))) + !purple_conversations_find_im_with_account(purple_xfer_get_remote_user(xfer), purple_xfer_get_account(xfer))) { char *message = g_strdup_printf(_("Autoaccepted file transfer of \"%s\" from \"%s\" completed."), purple_xfer_get_filename(xfer), purple_xfer_get_remote_user(xfer)); @@ -94,13 +94,13 @@ file_recv_request_cb(PurpleXfer *xfer, gpointer handle) int accept_setting; account = purple_xfer_get_account(xfer); - node = PURPLE_BLIST_NODE(purple_find_buddy(account, purple_xfer_get_remote_user(xfer))); + node = PURPLE_BLIST_NODE(purple_blist_find_buddy(account, purple_xfer_get_remote_user(xfer))); /* If person is on buddy list, use the buddy setting; otherwise, use the stranger setting. */ if (node) { node = purple_blist_node_get_parent(node); - g_return_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(node)); + g_return_if_fail(PURPLE_IS_CONTACT(node)); accept_setting = purple_blist_node_get_int(node, "autoaccept"); } else { accept_setting = purple_prefs_get_int(PREF_STRANGER); @@ -182,9 +182,9 @@ file_recv_request_cb(PurpleXfer *xfer, gpointer handle) static void save_cb(PurpleBlistNode *node, int choice) { - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (PURPLE_IS_BUDDY(node)) node = purple_blist_node_get_parent(node); - g_return_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(node)); + g_return_if_fail(PURPLE_IS_CONTACT(node)); purple_blist_node_set_int(node, "autoaccept", choice); } @@ -193,12 +193,12 @@ set_auto_accept_settings(PurpleBlistNode *node, gpointer plugin) { char *message; - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (PURPLE_IS_BUDDY(node)) node = purple_blist_node_get_parent(node); - g_return_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(node)); + g_return_if_fail(PURPLE_IS_CONTACT(node)); message = g_strdup_printf(_("When a file-transfer request arrives from %s"), - purple_contact_get_alias((PurpleContact *)node)); + purple_contact_get_alias(PURPLE_CONTACT(node))); purple_request_choice(plugin, _("Set Autoaccept Setting"), message, NULL, purple_blist_node_get_int(node, "autoaccept"), _("_Save"), G_CALLBACK(save_cb), @@ -208,7 +208,7 @@ set_auto_accept_settings(PurpleBlistNode *node, gpointer plugin) _("Ask"), FT_ASK, _("Auto Accept"), FT_ACCEPT, _("Auto Reject"), FT_REJECT, - NULL, purple_contact_get_alias((PurpleContact *)node), NULL, + NULL, purple_contact_get_alias(PURPLE_CONTACT(node)), NULL, NULL); g_free(message); } @@ -218,8 +218,8 @@ context_menu(PurpleBlistNode *node, GList **menu, gpointer plugin) { PurpleMenuAction *action; - if (!PURPLE_BLIST_NODE_IS_BUDDY(node) && !PURPLE_BLIST_NODE_IS_CONTACT(node) && - !(purple_blist_node_get_flags(node) & PURPLE_BLIST_NODE_FLAG_NO_SAVE)) + if (!PURPLE_IS_BUDDY(node) && !PURPLE_IS_CONTACT(node) && + !purple_blist_node_is_transient(node)) return; action = purple_menu_action_new(_("Autoaccept File Transfers..."), diff --git a/libpurple/plugins/buddynote.c b/libpurple/plugins/buddynote.c index e7d676215a..a44a82c2d9 100644 --- a/libpurple/plugins/buddynote.c +++ b/libpurple/plugins/buddynote.c @@ -58,7 +58,7 @@ buddynote_extended_menu_cb(PurpleBlistNode *node, GList **m) { PurpleMenuAction *bna = NULL; - if (purple_blist_node_get_flags(node) & PURPLE_BLIST_NODE_FLAG_NO_SAVE) + if (purple_blist_node_is_transient(node)) return; *m = g_list_append(*m, bna); diff --git a/libpurple/plugins/ciphertest.c b/libpurple/plugins/ciphertest.c index 4fb9771b92..dc516ba824 100644 --- a/libpurple/plugins/ciphertest.c +++ b/libpurple/plugins/ciphertest.c @@ -32,10 +32,16 @@ #include <glib.h> #include <string.h> -#include "cipher.h" #include "debug.h" #include "plugin.h" #include "version.h" +#include "util.h" + +#include "ciphers/aescipher.h" +#include "ciphers/md5hash.h" +#include "ciphers/pbkdf2cipher.h" +#include "ciphers/sha1hash.h" +#include "ciphers/sha256hash.h" struct test { const gchar *question; @@ -62,14 +68,13 @@ struct test md5_tests[8] = { static void cipher_test_md5(void) { - PurpleCipher *cipher; - PurpleCipherContext *context; + PurpleHash *hash; gchar digest[33]; gboolean ret; gint i = 0; - cipher = purple_ciphers_find_cipher("md5"); - if(!cipher) { + hash = purple_md5_hash_new(); + if(!hash) { purple_debug_info("cipher-test", "could not find md5 cipher, not testing\n"); return; @@ -77,16 +82,14 @@ cipher_test_md5(void) { purple_debug_info("cipher-test", "Running md5 tests\n"); - context = purple_cipher_context_new(cipher, NULL); - while(md5_tests[i].answer) { purple_debug_info("cipher-test", "Test %02d:\n", i); purple_debug_info("cipher-test", "Testing '%s'\n", md5_tests[i].question); - purple_cipher_context_append(context, (guchar *)md5_tests[i].question, + purple_hash_append(hash, (guchar *)md5_tests[i].question, strlen(md5_tests[i].question)); - ret = purple_cipher_context_digest_to_str(context, digest, sizeof(digest)); + ret = purple_hash_digest_to_str(hash, digest, sizeof(digest)); if(!ret) { purple_debug_info("cipher-test", "failed\n"); @@ -96,11 +99,11 @@ cipher_test_md5(void) { md5_tests[i].answer); } - purple_cipher_context_reset(context, NULL); + purple_hash_reset(hash); i++; } - purple_cipher_context_destroy(context); + g_object_unref(hash); purple_debug_info("cipher-test", "md5 tests completed\n\n"); } @@ -118,14 +121,13 @@ struct test sha1_tests[5] = { static void cipher_test_sha1(void) { - PurpleCipher *cipher; - PurpleCipherContext *context; + PurpleHash *hash; gchar digest[41]; gint i = 0; gboolean ret; - cipher = purple_ciphers_find_cipher("sha1"); - if(!cipher) { + hash = purple_sha1_hash_new(); + if(!hash) { purple_debug_info("cipher-test", "could not find sha1 cipher, not testing\n"); return; @@ -133,8 +135,6 @@ cipher_test_sha1(void) { purple_debug_info("cipher-test", "Running sha1 tests\n"); - context = purple_cipher_context_new(cipher, NULL); - while(sha1_tests[i].answer) { purple_debug_info("cipher-test", "Test %02d:\n", i); purple_debug_info("cipher-test", "Testing '%s'\n", @@ -142,7 +142,7 @@ cipher_test_sha1(void) { sha1_tests[i].question : "'a'x1000, 1000 times"); if(sha1_tests[i].question) { - purple_cipher_context_append(context, (guchar *)sha1_tests[i].question, + purple_hash_append(hash, (guchar *)sha1_tests[i].question, strlen(sha1_tests[i].question)); } else { gint j; @@ -151,10 +151,10 @@ cipher_test_sha1(void) { memset(buff, 'a', 1000); for(j = 0; j < 1000; j++) - purple_cipher_context_append(context, buff, 1000); + purple_hash_append(hash, buff, 1000); } - ret = purple_cipher_context_digest_to_str(context, digest, sizeof(digest)); + ret = purple_hash_digest_to_str(hash, digest, sizeof(digest)); if(!ret) { purple_debug_info("cipher-test", "failed\n"); @@ -164,11 +164,11 @@ cipher_test_sha1(void) { sha1_tests[i].answer); } - purple_cipher_context_reset(context, NULL); + purple_hash_reset(hash); i++; } - purple_cipher_context_destroy(context); + g_object_unref(hash); purple_debug_info("cipher-test", "sha1 tests completed\n\n"); } @@ -192,7 +192,7 @@ cipher_test_digest(void) purple_debug_info("cipher-test", "Running HTTP Digest tests\n"); - session_key = purple_cipher_http_digest_calculate_session_key( + session_key = purple_http_digest_calculate_session_key( algorithm, username, realm, password, nonce, client_nonce); @@ -208,7 +208,7 @@ cipher_test_digest(void) purple_debug_info("cipher-test", "\tsession_key: Got: %s\n", session_key); purple_debug_info("cipher-test", "\tsession_key: Wanted: %s\n", "939e7578ed9e3c518a452acee763bce9"); - response = purple_cipher_http_digest_calculate_response( + response = purple_http_digest_calculate_response( algorithm, method, digest_uri, qop, entity, nonce, nonce_count, client_nonce, session_key); @@ -362,14 +362,13 @@ cipher_pbkdf2_nss_sha1(const gchar *passphrase, const gchar *salt, static void cipher_test_pbkdf2(void) { - PurpleCipherContext *context; + PurpleCipher *cipher; + PurpleHash *hash; int i = 0; gboolean fail = FALSE; purple_debug_info("cipher-test", "Running PBKDF2 tests\n"); - context = purple_cipher_context_new_by_name("pbkdf2", NULL); - while (!fail && pbkdf2_tests[i].answer) { pbkdf2_test *test = &pbkdf2_tests[i]; gchar digest[2 * 32 + 1 + 10]; @@ -384,18 +383,28 @@ cipher_test_pbkdf2(void) test->passphrase, test->salt, test->hash, test->iter_count); - purple_cipher_context_set_option(context, "hash", (gpointer)test->hash); - purple_cipher_context_set_option(context, "iter_count", GUINT_TO_POINTER(test->iter_count)); - purple_cipher_context_set_option(context, "out_len", GUINT_TO_POINTER(test->out_len)); - purple_cipher_context_set_salt(context, (const guchar*)test->salt, test->salt ? strlen(test->salt): 0); - purple_cipher_context_set_key(context, (const guchar*)test->passphrase, strlen(test->passphrase)); + if (!strcmp(test->hash, "sha1")) + hash = purple_sha1_hash_new(); + else if (!strcmp(test->hash, "sha256")) + hash = purple_sha256_hash_new(); + else + hash = NULL; + + cipher = purple_pbkdf2_cipher_new(hash); + + g_object_set(G_OBJECT(cipher), "iter_count", GUINT_TO_POINTER(test->iter_count), NULL); + g_object_set(G_OBJECT(cipher), "out_len", GUINT_TO_POINTER(test->out_len), NULL); + purple_cipher_set_salt(cipher, (const guchar*)test->salt, test->salt ? strlen(test->salt): 0); + purple_cipher_set_key(cipher, (const guchar*)test->passphrase, strlen(test->passphrase)); - ret = purple_cipher_context_digest_to_str(context, digest, sizeof(digest)); - purple_cipher_context_reset(context, NULL); + ret = purple_cipher_digest_to_str(cipher, digest, sizeof(digest)); + purple_cipher_reset(cipher); if (!ret) { purple_debug_info("cipher-test", "\tfailed\n"); fail = TRUE; + g_object_unref(cipher); + g_object_unref(hash); continue; } @@ -431,9 +440,10 @@ cipher_test_pbkdf2(void) purple_debug_info("cipher-test", "\twrong answer\n"); fail = TRUE; } - } - purple_cipher_context_destroy(context); + g_object_unref(cipher); + g_object_unref(hash); + } if (fail) purple_debug_info("cipher-test", "PBKDF2 tests FAILED\n\n"); @@ -466,14 +476,14 @@ aes_test aes_tests[] = { static void cipher_test_aes(void) { - PurpleCipherContext *context; + PurpleCipher *cipher; int i = 0; gboolean fail = FALSE; purple_debug_info("cipher-test", "Running AES tests\n"); - context = purple_cipher_context_new_by_name("aes", NULL); - if (context == NULL) { + cipher = purple_aes_cipher_new(); + if (cipher == NULL) { purple_debug_error("cipher-test", "AES cipher not found\n"); fail = TRUE; } @@ -482,7 +492,7 @@ cipher_test_aes(void) aes_test *test = &aes_tests[i]; gsize key_size; guchar *key; - guchar cipher[1024], decipher[1024]; + guchar cipher_s[1024], decipher_s[1024]; ssize_t cipher_len, decipher_len; gchar *cipher_b16, *deciphered; @@ -493,38 +503,38 @@ cipher_test_aes(void) i++; - purple_cipher_context_reset(context, NULL); + purple_cipher_reset(cipher); if (test->iv) { gsize iv_size; guchar *iv = purple_base16_decode(test->iv, &iv_size); g_assert(iv != NULL); - purple_cipher_context_set_iv(context, iv, iv_size); + purple_cipher_set_iv(cipher, iv, iv_size); g_free(iv); } key = purple_base16_decode(test->key, &key_size); g_assert(key != NULL); - purple_cipher_context_set_key(context, key, key_size); + purple_cipher_set_key(cipher, key, key_size); g_free(key); - if (purple_cipher_context_get_key_size(context) != key_size) { + if (purple_cipher_get_key_size(cipher) != key_size) { purple_debug_info("cipher-test", "\tinvalid key size\n"); fail = TRUE; continue; } - cipher_len = purple_cipher_context_encrypt(context, + cipher_len = purple_cipher_encrypt(cipher, (const guchar*)(test->plaintext ? test->plaintext : ""), test->plaintext ? (strlen(test->plaintext) + 1) : 0, - cipher, sizeof(cipher)); + cipher_s, sizeof(cipher_s)); if (cipher_len < 0) { purple_debug_info("cipher-test", "\tencryption failed\n"); fail = TRUE; continue; } - cipher_b16 = purple_base16_encode(cipher, cipher_len); + cipher_b16 = purple_base16_encode(cipher_s, cipher_len); purple_debug_info("cipher-test", "\tGot: %s\n", cipher_b16); purple_debug_info("cipher-test", "\tWanted: %s\n", test->cipher); @@ -538,15 +548,15 @@ cipher_test_aes(void) } g_free(cipher_b16); - decipher_len = purple_cipher_context_decrypt(context, - cipher, cipher_len, decipher, sizeof(decipher)); + decipher_len = purple_cipher_decrypt(cipher, + cipher_s, cipher_len, decipher_s, sizeof(decipher_s)); if (decipher_len < 0) { purple_debug_info("cipher-test", "\tdecryption failed\n"); fail = TRUE; continue; } - deciphered = (decipher_len > 0) ? (gchar*)decipher : NULL; + deciphered = (decipher_len > 0) ? (gchar*)decipher_s : NULL; if (g_strcmp0(deciphered, test->plaintext) != 0) { purple_debug_info("cipher-test", @@ -558,8 +568,8 @@ cipher_test_aes(void) purple_debug_info("cipher-test", "\tTest OK\n"); } - if (context != NULL) - purple_cipher_context_destroy(context); + if (cipher != NULL) + g_object_unref(cipher); if (fail) purple_debug_info("cipher-test", "AES tests FAILED\n\n"); diff --git a/libpurple/plugins/dbus-example.c b/libpurple/plugins/dbus-example.c index cf9f255382..01a7978a00 100644 --- a/libpurple/plugins/dbus-example.c +++ b/libpurple/plugins/dbus-example.c @@ -37,7 +37,7 @@ #include "internal.h" -#include "blist.h" +#include "buddylist.h" #include "notify.h" #include "plugin.h" #include "version.h" diff --git a/libpurple/plugins/idle.c b/libpurple/plugins/idle.c index 5d320992eb..b7ed73003e 100644 --- a/libpurple/plugins/idle.c +++ b/libpurple/plugins/idle.c @@ -28,6 +28,7 @@ #include "debug.h" #include "notify.h" #include "plugin.h" +#include "presence.h" #include "request.h" #include "server.h" #include "status.h" diff --git a/libpurple/plugins/joinpart.c b/libpurple/plugins/joinpart.c index 1e55b05228..4dd836b1ff 100644 --- a/libpurple/plugins/joinpart.c +++ b/libpurple/plugins/joinpart.c @@ -79,22 +79,22 @@ static void joinpart_key_destroy(struct joinpart_key *key) static gboolean should_hide_notice(PurpleConversation *conv, const char *name, GHashTable *users) { - PurpleConvChat *chat; + PurpleChatConversation *chat; guint threshold; struct joinpart_key key; time_t *last_said; g_return_val_if_fail(conv != NULL, FALSE); - g_return_val_if_fail(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT, FALSE); + g_return_val_if_fail(PURPLE_IS_CHAT_CONVERSATION(conv), FALSE); /* If the room is small, don't bother. */ - chat = PURPLE_CONV_CHAT(conv); + chat = PURPLE_CHAT_CONVERSATION(conv); threshold = purple_prefs_get_int(THRESHOLD_PREF); - if (g_list_length(purple_conv_chat_get_users(chat)) < threshold) + if (g_list_length(purple_chat_conversation_get_users(chat)) < threshold) return FALSE; if (!purple_prefs_get_bool(HIDE_BUDDIES_PREF) && - purple_find_buddy(purple_conversation_get_account(conv), name)) + purple_blist_find_buddy(purple_conversation_get_account(conv), name)) return FALSE; /* Only show the notice if the user has spoken recently. */ @@ -111,14 +111,14 @@ static gboolean should_hide_notice(PurpleConversation *conv, const char *name, return TRUE; } -static gboolean chat_buddy_leaving_cb(PurpleConversation *conv, const char *name, +static gboolean chat_user_leaving_cb(PurpleConversation *conv, const char *name, const char *reason, GHashTable *users) { return should_hide_notice(conv, name, users); } -static gboolean chat_buddy_joining_cb(PurpleConversation *conv, const char *name, - PurpleConvChatBuddyFlags flags, +static gboolean chat_user_joining_cb(PurpleConversation *conv, const char *name, + PurpleChatUserFlags flags, GHashTable *users) { return should_hide_notice(conv, name, users); @@ -186,10 +186,10 @@ static gboolean plugin_load(PurplePlugin *plugin) g_free); conv_handle = purple_conversations_get_handle(); - purple_signal_connect(conv_handle, "chat-buddy-joining", plugin, - PURPLE_CALLBACK(chat_buddy_joining_cb), users); - purple_signal_connect(conv_handle, "chat-buddy-leaving", plugin, - PURPLE_CALLBACK(chat_buddy_leaving_cb), users); + purple_signal_connect(conv_handle, "chat-user-joining", plugin, + PURPLE_CALLBACK(chat_user_joining_cb), users); + purple_signal_connect(conv_handle, "chat-user-leaving", plugin, + PURPLE_CALLBACK(chat_user_leaving_cb), users); purple_signal_connect(conv_handle, "received-chat-msg", plugin, PURPLE_CALLBACK(received_chat_msg_cb), users); diff --git a/libpurple/plugins/keyrings/internalkeyring.c b/libpurple/plugins/keyrings/internalkeyring.c index f2e9f5d236..46b092f414 100644 --- a/libpurple/plugins/keyrings/internalkeyring.c +++ b/libpurple/plugins/keyrings/internalkeyring.c @@ -26,12 +26,15 @@ #include "internal.h" #include "account.h" -#include "cipher.h" #include "debug.h" #include "keyring.h" #include "plugin.h" #include "version.h" +#include "ciphers/aescipher.h" +#include "ciphers/pbkdf2cipher.h" +#include "ciphers/sha256hash.h" + #define INTKEYRING_NAME N_("Internal keyring") #define INTKEYRING_DESCRIPTION N_("This plugin provides the default password " \ "storage behaviour for libpurple.") @@ -147,30 +150,31 @@ intkeyring_buff_from_base64(const gchar *base64) static intkeyring_buff_t * intkeyring_derive_key(const gchar *passphrase, intkeyring_buff_t *salt) { - PurpleCipherContext *context; + PurpleCipher *cipher; + PurpleHash *hash; gboolean succ; intkeyring_buff_t *ret; g_return_val_if_fail(passphrase != NULL, NULL); - context = purple_cipher_context_new_by_name("pbkdf2", NULL); - g_return_val_if_fail(context != NULL, NULL); + hash = purple_sha256_hash_new(); + cipher = purple_pbkdf2_cipher_new(hash); - purple_cipher_context_set_option(context, "hash", "sha256"); - purple_cipher_context_set_option(context, "iter_count", + g_object_set(G_OBJECT(cipher), "iter_count", GUINT_TO_POINTER(purple_prefs_get_int(INTKEYRING_PREFS - "pbkdf2_iterations"))); - purple_cipher_context_set_option(context, "out_len", GUINT_TO_POINTER( - INTKEYRING_KEY_LEN)); - purple_cipher_context_set_salt(context, salt->data, salt->len); - purple_cipher_context_set_key(context, (const guchar*)passphrase, + "pbkdf2_iterations")), NULL); + g_object_set(G_OBJECT(cipher), "out_len", GUINT_TO_POINTER( + INTKEYRING_KEY_LEN), NULL); + purple_cipher_set_salt(cipher, salt->data, salt->len); + purple_cipher_set_key(cipher, (const guchar*)passphrase, strlen(passphrase)); ret = intkeyring_buff_new(g_new(guchar, INTKEYRING_KEY_LEN), INTKEYRING_KEY_LEN); - succ = purple_cipher_context_digest(context, ret->data, ret->len); + succ = purple_cipher_digest(cipher, ret->data, ret->len); - purple_cipher_context_destroy(context); + g_object_unref(cipher); + g_object_unref(hash); if (!succ) { intkeyring_buff_free(ret); @@ -229,7 +233,7 @@ intkeyring_gen_salt(size_t len) static gchar * intkeyring_encrypt(intkeyring_buff_t *key, const gchar *str) { - PurpleCipherContext *context; + PurpleCipher *cipher; intkeyring_buff_t *iv; guchar plaintext[INTKEYRING_ENCRYPT_BUFF_LEN]; size_t plaintext_len, text_len, verify_len; @@ -248,30 +252,30 @@ intkeyring_encrypt(intkeyring_buff_t *key, const gchar *str) g_return_val_if_fail(plaintext_len + verify_len <= sizeof(plaintext), NULL); - context = purple_cipher_context_new_by_name("aes", NULL); - g_return_val_if_fail(context != NULL, NULL); + cipher = purple_aes_cipher_new(); + g_return_val_if_fail(cipher != NULL, NULL); memset(plaintext, 0, plaintext_len); memcpy(plaintext, str, text_len); memcpy(plaintext + plaintext_len, INTKEYRING_VERIFY_STR, verify_len); plaintext_len += verify_len; - iv = intkeyring_gen_salt(purple_cipher_context_get_block_size(context)); - purple_cipher_context_set_iv(context, iv->data, iv->len); - purple_cipher_context_set_key(context, key->data, key->len); - purple_cipher_context_set_batch_mode(context, + iv = intkeyring_gen_salt(purple_cipher_get_block_size(cipher)); + purple_cipher_set_iv(cipher, iv->data, iv->len); + purple_cipher_set_key(cipher, key->data, key->len); + purple_cipher_set_batch_mode(cipher, PURPLE_CIPHER_BATCH_MODE_CBC); memcpy(encrypted_raw, iv->data, iv->len); - encrypted_size = purple_cipher_context_encrypt(context, + encrypted_size = purple_cipher_encrypt(cipher, plaintext, plaintext_len, encrypted_raw + iv->len, sizeof(encrypted_raw) - iv->len); encrypted_size += iv->len; memset(plaintext, 0, plaintext_len); intkeyring_buff_free(iv); - purple_cipher_context_destroy(context); + g_object_unref(cipher); if (encrypted_size < 0) return NULL; @@ -283,7 +287,7 @@ intkeyring_encrypt(intkeyring_buff_t *key, const gchar *str) static gchar * intkeyring_decrypt(intkeyring_buff_t *key, const gchar *str) { - PurpleCipherContext *context; + PurpleCipher *cipher; guchar *encrypted_raw; gsize encrypted_size; size_t iv_len, verify_len, text_len; @@ -295,29 +299,29 @@ intkeyring_decrypt(intkeyring_buff_t *key, const gchar *str) g_return_val_if_fail(key != NULL, NULL); g_return_val_if_fail(str != NULL, NULL); - context = purple_cipher_context_new_by_name("aes", NULL); - g_return_val_if_fail(context != NULL, NULL); + cipher = purple_aes_cipher_new(); + g_return_val_if_fail(cipher != NULL, NULL); encrypted_raw = purple_base64_decode(str, &encrypted_size); g_return_val_if_fail(encrypted_raw != NULL, NULL); - iv_len = purple_cipher_context_get_block_size(context); + iv_len = purple_cipher_get_block_size(cipher); if (encrypted_size < iv_len) { g_free(encrypted_raw); return NULL; } - purple_cipher_context_set_iv(context, encrypted_raw, iv_len); - purple_cipher_context_set_key(context, key->data, key->len); - purple_cipher_context_set_batch_mode(context, + purple_cipher_set_iv(cipher, encrypted_raw, iv_len); + purple_cipher_set_key(cipher, key->data, key->len); + purple_cipher_set_batch_mode(cipher, PURPLE_CIPHER_BATCH_MODE_CBC); - plaintext_len = purple_cipher_context_decrypt(context, + plaintext_len = purple_cipher_decrypt(cipher, encrypted_raw + iv_len, encrypted_size - iv_len, plaintext, sizeof(plaintext)); g_free(encrypted_raw); - purple_cipher_context_destroy(context); + g_object_unref(cipher); verify_len = strlen(INTKEYRING_VERIFY_STR); /* Don't remove the len > 0 check! */ diff --git a/libpurple/plugins/log_reader.c b/libpurple/plugins/log_reader.c index 39f52c7c82..3c73b6537d 100644 --- a/libpurple/plugins/log_reader.c +++ b/libpurple/plugins/log_reader.c @@ -644,7 +644,7 @@ static GList *msn_logger_list(PurpleLogType type, const char *sn, PurpleAccount if (!logdir || !*logdir) return NULL; - buddy = purple_find_buddy(account, sn); + buddy = purple_blist_find_buddy(account, sn); if ((username = g_strdup(purple_account_get_string( account, "log_reader_msn_log_folder", NULL)))) { @@ -662,7 +662,7 @@ static GList *msn_logger_list(PurpleLogType type, const char *sn, PurpleAccount } if (buddy) { - savedfilename = purple_blist_node_get_string((PurpleBlistNode *)buddy, + savedfilename = purple_blist_node_get_string(PURPLE_BLIST_NODE(buddy), "log_reader_msn_log_filename"); } @@ -824,7 +824,7 @@ static GList *msn_logger_list(PurpleLogType type, const char *sn, PurpleAccount * detected for both buddies. */ if (buddy && logfile) { - PurpleBlistNode *node = (PurpleBlistNode *)buddy; + PurpleBlistNode *node = PURPLE_BLIST_NODE(buddy); purple_blist_node_set_string(node, "log_reader_msn_log_filename", logfile); g_free(logfile); } @@ -979,14 +979,14 @@ static char * msn_logger_read (PurpleLog *log, PurpleLogReadFlags *flags) int friendly_name_length = strlen(friendly_name); const char *alias; int alias_length; - PurpleBuddy *buddy = purple_find_buddy(log->account, log->name); + PurpleBuddy *buddy = purple_blist_find_buddy(log->account, log->name); gboolean from_name_matches; gboolean to_name_matches; if (buddy) their_name = purple_buddy_get_alias(buddy); - alias = purple_account_get_alias(log->account); + alias = purple_account_get_private_alias(log->account); if (alias) { alias_length = strlen(alias); } else { @@ -1111,8 +1111,8 @@ static char * msn_logger_read (PurpleLog *log, PurpleLogReadFlags *flags) text = g_string_append(text, "<b>"); if (name_guessed == NAME_GUESS_ME) { - if (purple_account_get_alias(log->account)) - text = g_string_append(text, purple_account_get_alias(log->account)); + if (purple_account_get_private_alias(log->account)) + text = g_string_append(text, purple_account_get_private_alias(log->account)); else text = g_string_append(text, purple_account_get_username(log->account)); } @@ -1434,7 +1434,7 @@ static char * trillian_logger_read (PurpleLog *log, PurpleLogReadFlags *flags) } /* Load miscellaneous data. */ - buddy = purple_find_buddy(log->account, log->name); + buddy = purple_blist_find_buddy(log->account, log->name); escaped = g_markup_escape_text(read, -1); g_free(read); @@ -1663,7 +1663,7 @@ static char * trillian_logger_read (PurpleLog *log, PurpleLogReadFlags *flags) const char *acct_name; line2++; line = line2; - acct_name = purple_account_get_alias(log->account); + acct_name = purple_account_get_private_alias(log->account); if (!acct_name) acct_name = purple_account_get_username(log->account); @@ -1964,7 +1964,7 @@ static char *qip_logger_read(PurpleLog *log, PurpleLogReadFlags *flags) contents = g_markup_escape_text(utf8_string, -1); g_free(utf8_string); - buddy = purple_find_buddy(log->account, log->name); + buddy = purple_blist_find_buddy(log->account, log->name); /* Apply formatting... */ formatted = g_string_sized_new(data->length + 2); @@ -2032,7 +2032,7 @@ static char *qip_logger_read(PurpleLog *log, PurpleLogReadFlags *flags) } } else { const char *acct_name; - acct_name = purple_account_get_alias(log->account); + acct_name = purple_account_get_private_alias(log->account); if (!acct_name) acct_name = purple_account_get_username(log->account); diff --git a/libpurple/plugins/mono/loader/blist-glue.c b/libpurple/plugins/mono/loader/blist-glue.c index a424914036..303e77da0a 100644 --- a/libpurple/plugins/mono/loader/blist-glue.c +++ b/libpurple/plugins/mono/loader/blist-glue.c @@ -1,5 +1,5 @@ #include <string.h> -#include "blist.h" +#include "buddylist.h" #include "mono-helper.h" #include "mono-glue.h" @@ -14,7 +14,7 @@ MonoObject* purple_blist_build_buddy_object(void* data) { MonoObject *obj = NULL; - PurpleBuddy *buddy = (PurpleBuddy*)data; + PurpleBuddy *buddy = PURPLE_BUDDY(data); obj = ml_create_api_object("Buddy"); g_return_val_if_fail(obj != NULL, NULL); diff --git a/libpurple/plugins/mono/loader/mono-helper.c b/libpurple/plugins/mono/loader/mono-helper.c index 4404544409..bd7d3b7fc0 100644 --- a/libpurple/plugins/mono/loader/mono-helper.c +++ b/libpurple/plugins/mono/loader/mono-helper.c @@ -14,7 +14,6 @@ #include <string.h> #include "mono-helper.h" #include "mono-glue.h" -#include "value.h" #include "debug.h" static gboolean _runtime_active = FALSE; diff --git a/libpurple/plugins/mono/loader/mono-helper.h b/libpurple/plugins/mono/loader/mono-helper.h index 1d454388d5..6fd0dc8902 100644 --- a/libpurple/plugins/mono/loader/mono-helper.h +++ b/libpurple/plugins/mono/loader/mono-helper.h @@ -8,7 +8,6 @@ #include <mono/metadata/debug-helpers.h> #include <mono/metadata/tokentype.h> #include "plugin.h" -#include "value.h" #include "debug.h" typedef struct { diff --git a/libpurple/plugins/mono/loader/signal-glue.c b/libpurple/plugins/mono/loader/signal-glue.c index c6b4be01c6..cb65642419 100644 --- a/libpurple/plugins/mono/loader/signal-glue.c +++ b/libpurple/plugins/mono/loader/signal-glue.c @@ -1,9 +1,8 @@ #include "mono-glue.h" #include "mono-helper.h" #include "debug.h" -#include "blist.h" +#include "buddylist.h" #include "signals.h" -#include "value.h" typedef struct { MonoObject *func; diff --git a/libpurple/plugins/newline.c b/libpurple/plugins/newline.c index 25ba535140..1dfdc77596 100644 --- a/libpurple/plugins/newline.c +++ b/libpurple/plugins/newline.c @@ -31,9 +31,9 @@ static gboolean addnewline_msg_cb(PurpleAccount *account, char *sender, char **message, PurpleConversation *conv, int *flags, void *data) { - if (((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) && + if ((PURPLE_IS_IM_CONVERSATION(conv) && !purple_prefs_get_bool("/plugins/core/newline/im")) || - ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) && + (PURPLE_IS_CHAT_CONVERSATION(conv) && !purple_prefs_get_bool("/plugins/core/newline/chat"))) return FALSE; diff --git a/libpurple/plugins/offlinemsg.c b/libpurple/plugins/offlinemsg.c index 1803f82430..56dfe66cad 100644 --- a/libpurple/plugins/offlinemsg.c +++ b/libpurple/plugins/offlinemsg.c @@ -29,7 +29,7 @@ /* Purple headers */ #include <version.h> -#include <blist.h> +#include <buddylist.h> #include <conversation.h> #include <core.h> #include <debug.h> @@ -67,9 +67,9 @@ discard_data(OfflineMsg *offline) static void cancel_poune(OfflineMsg *offline) { - purple_conversation_set_data(offline->conv, "plugin_pack:offlinemsg", + g_object_set_data(G_OBJECT(offline->conv), "plugin_pack:offlinemsg", GINT_TO_POINTER(OFFLINE_MSG_NO)); - purple_conv_im_send_with_flags(PURPLE_CONV_IM(offline->conv), offline->message, 0); + purple_conversation_send_with_flags(offline->conv, offline->message, 0); discard_data(offline); } @@ -97,15 +97,15 @@ record_pounce(OfflineMsg *offline) g_free(temp); conv = offline->conv; - if (!purple_conversation_get_data(conv, "plugin_pack:offlinemsg")) + if (!g_object_get_data(G_OBJECT(conv), "plugin_pack:offlinemsg")) purple_conversation_write(conv, NULL, _("The rest of the messages will be saved " "as pounces. You can edit/delete the pounce from the `Buddy " "Pounce' dialog."), PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conversation_set_data(conv, "plugin_pack:offlinemsg", + g_object_set_data(G_OBJECT(conv), "plugin_pack:offlinemsg", GINT_TO_POINTER(OFFLINE_MSG_YES)); - purple_conv_im_write(PURPLE_CONV_IM(conv), offline->who, offline->message, + purple_conversation_write_message(conv, offline->who, offline->message, PURPLE_MESSAGE_SEND, time(NULL)); discard_data(offline); @@ -123,7 +123,7 @@ sending_msg_cb(PurpleAccount *account, const char *who, char **message, gpointer **message == '\0') return; - buddy = purple_find_buddy(account, who); + buddy = purple_blist_find_buddy(account, who); if (!buddy) return; @@ -137,13 +137,12 @@ sending_msg_cb(PurpleAccount *account, const char *who, char **message, gpointer return; } - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - who, account); + conv = PURPLE_CONVERSATION(purple_conversations_find_im_with_account(who, account)); if (!conv) return; - setting = GPOINTER_TO_INT(purple_conversation_get_data(conv, "plugin_pack:offlinemsg")); + setting = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "plugin_pack:offlinemsg")); if (setting == OFFLINE_MSG_NO) return; diff --git a/libpurple/plugins/perl/common/Account.xs b/libpurple/plugins/perl/common/Account.xs index b83f4e9089..ea9b5b56cf 100644 --- a/libpurple/plugins/perl/common/Account.xs +++ b/libpurple/plugins/perl/common/Account.xs @@ -1,6 +1,57 @@ #include "module.h" #include "../perl-handlers.h" +MODULE = Purple::Account PACKAGE = Purple::Accounts PREFIX = purple_accounts_ +PROTOTYPES: ENABLE + +void +purple_accounts_add(account) + Purple::Account account + +void +purple_accounts_remove(account) + Purple::Account account + +void +purple_accounts_delete(account) + Purple::Account account + +void +purple_accounts_reorder(account, new_index) + Purple::Account account + size_t new_index + +void +purple_accounts_get_all() +PREINIT: + GList *l; +PPCODE: + for (l = purple_accounts_get_all(); l != NULL; l = l->next) { + XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Account"))); + } + +void +purple_accounts_get_all_active() +PREINIT: + GList *list, *iter; +PPCODE: + list = purple_accounts_get_all_active(); + for (iter = list; iter != NULL; iter = iter->next) { + XPUSHs(sv_2mortal(purple_perl_bless_object(iter->data, "Purple::Account"))); + } + g_list_free(list); + +void +purple_accounts_restore_current_statuses() + +Purple::Account +purple_accounts_find(name, protocol) + const char * name + const char * protocol + +Purple::Handle +purple_accounts_get_handle() + MODULE = Purple::Account PACKAGE = Purple::Account PREFIX = purple_account_ PROTOTYPES: ENABLE @@ -16,10 +67,6 @@ purple_account_new(class, username, protocol_id) username, protocol_id void -purple_account_destroy(account) - Purple::Account account - -void purple_account_connect(account) Purple::Account account @@ -54,7 +101,7 @@ CODE: purple_perl_account_set_password(account, password, func, data); void -purple_account_set_alias(account, alias) +purple_account_set_private_alias(account, alias) Purple::Account account const char * alias @@ -144,7 +191,7 @@ CODE: purple_perl_account_get_password(account, func, data); const char * -purple_account_get_alias(account) +purple_account_get_private_alias(account) Purple::Account account const char * @@ -273,53 +320,34 @@ purple_account_remove_group(account, group) Purple::Account account Purple::BuddyList::Group group -MODULE = Purple::Account PACKAGE = Purple::Accounts PREFIX = purple_accounts_ +MODULE = Purple::Account PACKAGE = Purple::Account::Privacy PREFIX = purple_account_privacy_ PROTOTYPES: ENABLE -void -purple_accounts_add(account) - Purple::Account account - -void -purple_accounts_remove(account) - Purple::Account account - -void -purple_accounts_delete(account) - Purple::Account account - -void -purple_accounts_reorder(account, new_index) - Purple::Account account - size_t new_index - -void -purple_accounts_get_all() -PREINIT: - GList *l; -PPCODE: - for (l = purple_accounts_get_all(); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Account"))); - } +gboolean +purple_account_privacy_permit_add(account, name, local_only) + Purple::Account account + const char * name + gboolean local_only -void -purple_accounts_get_all_active() -PREINIT: - GList *list, *iter; -PPCODE: - list = purple_accounts_get_all_active(); - for (iter = list; iter != NULL; iter = iter->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(iter->data, "Purple::Account"))); - } - g_list_free(list); +gboolean +purple_account_privacy_permit_remove(account, name, local_only) + Purple::Account account + const char * name + gboolean local_only -void -purple_accounts_restore_current_statuses() +gboolean +purple_account_privacy_deny_add(account, name, local_only) + Purple::Account account + const char * name + gboolean local_only -Purple::Account -purple_accounts_find(name, protocol) - const char * name - const char * protocol +gboolean +purple_account_privacy_deny_remove(account, name, local_only) + Purple::Account account + const char * name + gboolean local_only -Purple::Handle -purple_accounts_get_handle() +gboolean +purple_account_privacy_check(account, who) + Purple::Account account + const char * who diff --git a/libpurple/plugins/perl/common/BuddyList.xs b/libpurple/plugins/perl/common/BuddyList.xs index 394496b118..518dd3a2bf 100644 --- a/libpurple/plugins/perl/common/BuddyList.xs +++ b/libpurple/plugins/perl/common/BuddyList.xs @@ -10,57 +10,6 @@ chat_components_foreach(gpointer key, gpointer value, gpointer user_data) purple_debug_error("perl", "hv_store failed\n"); } -MODULE = Purple::BuddyList PACKAGE = Purple PREFIX = purple_ -PROTOTYPES: ENABLE - -BOOT: -{ - HV *stash = gv_stashpv("Purple::BuddyList::Node", 1); - - static const constiv *civ, const_iv[] = { -#define const_iv(name) {#name, (IV)PURPLE_BLIST_##name##_NODE} - const_iv(GROUP), - const_iv(CONTACT), - const_iv(BUDDY), - const_iv(CHAT), - const_iv(OTHER), -#undef const_iv -#define const_iv(name) {#name, (IV)PURPLE_BLIST_NODE_FLAG_##name} - const_iv(NO_SAVE), - }; - - for (civ = const_iv + sizeof(const_iv) / sizeof(const_iv[0]); civ-- > const_iv; ) - newCONSTSUB(stash, (char *)civ->name, newSViv(civ->iv)); -} - -Purple::BuddyList -purple_get_blist() - -MODULE = Purple::BuddyList PACKAGE = Purple::Find PREFIX = purple_find_ -PROTOTYPES: ENABLE - -Purple::BuddyList::Buddy -purple_find_buddy(account, name) - Purple::Account account - const char * name - -void -purple_find_buddies(account, name) - Purple::Account account - const char * name -PREINIT: - GSList *l, *ll; -PPCODE: - ll = purple_find_buddies(account, name); - for (l = ll; l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::BuddyList::Buddy"))); - } - g_slist_free(ll); - -Purple::BuddyList::Group -purple_find_group(name) - const char *name - MODULE = Purple::BuddyList PACKAGE = Purple::Find PREFIX = purple_ PROTOTYPES: ENABLE @@ -92,6 +41,11 @@ void purple_contact_invalidate_priority_buddy(contact) Purple::BuddyList::Contact contact +void +purple_contact_merge(source, node) + Purple::BuddyList::Contact source + Purple::BuddyList::Node node + MODULE = Purple::BuddyList PACKAGE = Purple::BuddyList::Group PREFIX = purple_group_ PROTOTYPES: ENABLE @@ -116,6 +70,11 @@ purple_group_on_account(group, account) Purple::BuddyList::Group group Purple::Account account +void +purple_group_set_name(group, name) + Purple::BuddyList::Group group + const char * name + const char * purple_group_get_name(group) Purple::BuddyList::Group group @@ -123,6 +82,31 @@ purple_group_get_name(group) MODULE = Purple::BuddyList PACKAGE = Purple::BuddyList PREFIX = purple_blist_ PROTOTYPES: ENABLE +Purple::BuddyList +purple_blist_get_buddy_list() + +Purple::BuddyList::Buddy +purple_blist_find_buddy(account, name) + Purple::Account account + const char * name + +void +purple_blist_find_buddies(account, name) + Purple::Account account + const char * name +PREINIT: + GSList *l, *ll; +PPCODE: + ll = purple_blist_find_buddies(account, name); + for (l = ll; l != NULL; l = l->next) { + XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::BuddyList::Buddy"))); + } + g_slist_free(ll); + +Purple::BuddyList::Group +purple_blist_find_group(name) + const char *name + void purple_blist_add_contact(contact, group, node) Purple::BuddyList::Contact contact @@ -130,11 +114,6 @@ purple_blist_add_contact(contact, group, node) Purple::BuddyList::Node node void -purple_blist_merge_contact(source, node) - Purple::BuddyList::Contact source - Purple::BuddyList::Node node - -void purple_blist_add_group(group, node) Purple::BuddyList::Group group Purple::BuddyList::Node node @@ -177,43 +156,10 @@ void purple_blist_show() void -purple_blist_destroy(); - -void purple_blist_set_visible(show) gboolean show void -purple_blist_update_buddy_status(buddy, old_status) - Purple::BuddyList::Buddy buddy - Purple::Status old_status - -void -purple_blist_rename_buddy(buddy, name) - Purple::BuddyList::Buddy buddy - const char * name - -void -purple_blist_alias_buddy(buddy, alias) - Purple::BuddyList::Buddy buddy - const char * alias - -void -purple_blist_server_alias_buddy(buddy, alias) - Purple::BuddyList::Buddy buddy - const char * alias - -void -purple_blist_alias_chat(chat, alias) - Purple::BuddyList::Chat chat - const char * alias - -void -purple_blist_rename_group(group, name) - Purple::BuddyList::Group group - const char * name - -void purple_blist_add_account(account) Purple::Account account @@ -221,15 +167,6 @@ void purple_blist_remove_account(account) Purple::Account account -int -purple_blist_get_group_size(group, offline) - Purple::BuddyList::Group group - gboolean offline - -int -purple_blist_get_group_online_count(group) - Purple::BuddyList::Group group - void purple_blist_schedule_save() @@ -287,27 +224,63 @@ purple_blist_node_get_string(node, key) const char * key void +purple_blist_node_set_transient(node, transient) + Purple::BuddyList::Node node + gboolean transient + +gboolean +purple_blist_node_is_transient(node); + Purple::BuddyList::Node node + +void purple_blist_node_remove_setting(node, key) Purple::BuddyList::Node node const char * key +MODULE = Purple::BuddyList PACKAGE = Purple::BuddyList::CountingNode PREFIX = purple_counting_node_ +PROTOTYPES: ENABLE + +int +purple_counting_node_get_total_size(counter); + Purple::BuddyList::CountingNode counter + +int +purple_counting_node_get_current_size(counter); + Purple::BuddyList::CountingNode counter + +int +purple_counting_node_get_online_count(counter); + Purple::BuddyList::CountingNode counter + void -purple_blist_node_set_flags(node, flags) - Purple::BuddyList::Node node - Purple::BuddyList::NodeFlags flags +purple_counting_node_change_total_size(counter, delta); + Purple::BuddyList::CountingNode counter + int delta -Purple::BuddyList::NodeFlags -purple_blist_node_get_flags(node) - Purple::BuddyList::Node node +void +purple_counting_node_change_current_size(counter, delta); + Purple::BuddyList::CountingNode counter + int delta -Purple::BuddyList::NodeType -purple_blist_node_get_type(node) - Purple::BuddyList::Node node +void +purple_counting_node_change_online_count(counter, delta); + Purple::BuddyList::CountingNode counter + int delta -Purple::BuddyList::Node -purple_blist_node_next(node, offline) - Purple::BuddyList::Node node - gboolean offline +void +purple_counting_node_set_total_size(counter, totalsize); + Purple::BuddyList::CountingNode counter + int totalsize + +void +purple_counting_node_set_current_size(counter, currentsize); + Purple::BuddyList::CountingNode counter + int currentsize + +void +purple_counting_node_set_online_count(counter, onlinecount); + Purple::BuddyList::CountingNode counter + int onlinecount MODULE = Purple::BuddyList PACKAGE = Purple::BuddyList::Chat PREFIX = purple_chat_ PROTOTYPES: ENABLE @@ -316,10 +289,19 @@ Purple::BuddyList::Group purple_chat_get_group(chat) Purple::BuddyList::Chat chat +void +purple_chat_set_alias(chat, alias) + Purple::BuddyList::Chat chat + const char * alias + const char * purple_chat_get_name(chat) Purple::BuddyList::Chat chat +const char * +purple_chat_get_name_only(chat) + Purple::BuddyList::Chat chat + HV * purple_chat_get_components(chat) Purple::BuddyList::Chat chat @@ -370,6 +352,26 @@ purple_buddy_new(account, name, alias) const char *name const char *alias +void +purple_buddy_update_status(buddy, old_status) + Purple::BuddyList::Buddy buddy + Purple::Status old_status + +void +purple_buddy_set_name(buddy, name) + Purple::BuddyList::Buddy buddy + const char * name + +void +purple_buddy_set_local_alias(buddy, alias) + Purple::BuddyList::Buddy buddy + const char * alias + +void +purple_buddy_set_server_alias(buddy, alias) + Purple::BuddyList::Buddy buddy + const char * alias + const char * purple_buddy_get_server_alias(buddy) Purple::BuddyList::Buddy buddy diff --git a/libpurple/plugins/perl/common/Cipher.xs b/libpurple/plugins/perl/common/Cipher.xs index 2dd723fcd7..2612090ada 100644 --- a/libpurple/plugins/perl/common/Cipher.xs +++ b/libpurple/plugins/perl/common/Cipher.xs @@ -6,7 +6,6 @@ PROTOTYPES: ENABLE BOOT: { HV *stash = gv_stashpv("Purple::Cipher::BatchMode", 1); - HV *cipher_caps = gv_stashpv("Purple::Cipher::Caps", 1); static const constiv *civ, const_iv[] = { #define const_iv(name) {#name, (IV)PURPLE_CIPHER_BATCH_MODE_##name} @@ -15,74 +14,16 @@ BOOT: #undef const_iv }; - static const constiv bm_const_iv[] = { -#define const_iv(name) {#name, (IV)PURPLE_CIPHER_CAPS_##name} - const_iv(SET_OPT), - const_iv(GET_OPT), - const_iv(INIT), - const_iv(RESET), - const_iv(UNINIT), - const_iv(SET_IV), - const_iv(APPEND), - const_iv(DIGEST), - const_iv(GET_DIGEST_SIZE), - const_iv(ENCRYPT), - const_iv(DECRYPT), - const_iv(SET_SALT), - const_iv(GET_SALT_SIZE), - const_iv(SET_KEY), - const_iv(GET_KEY_SIZE), - const_iv(SET_BATCH_MODE), - const_iv(GET_BATCH_MODE), - const_iv(GET_BLOCK_SIZE), - const_iv(UNKNOWN), -#undef const_iv - }; - for (civ = const_iv + sizeof(const_iv) / sizeof(const_iv[0]); civ-- > const_iv; ) newCONSTSUB(stash, (char *)civ->name, newSViv(civ->iv)); - - for (civ = bm_const_iv + sizeof(bm_const_iv) / sizeof(bm_const_iv[0]); civ-- > bm_const_iv; ) - newCONSTSUB(cipher_caps, (char *)civ->name, newSViv(civ->iv)); } const gchar * purple_cipher_get_name(cipher) Purple::Cipher cipher -guint -purple_cipher_get_capabilities(cipher) - Purple::Cipher cipher - -gboolean -purple_cipher_digest_region(name, data_sv, data_len, digest) - const gchar *name - SV *data_sv - size_t data_len - SV *digest - PREINIT: - guchar *buff = NULL; - guchar *data = NULL; - ssize_t digest_len; - size_t max_digest_len = 100; - CODE: - data = (guchar *)SvPV(data_sv, data_len); - SvUPGRADE(digest, SVt_PV); - buff = (guchar *)SvGROW(digest, max_digest_len); - digest_len = purple_cipher_digest_region(name, data, data_len, buff, max_digest_len); - if(digest_len == -1) { - SvSetSV_nosteal(digest, &PL_sv_undef); - RETVAL = 0; - } else { - SvCUR_set(digest, digest_len); - SvPOK_only(digest); - RETVAL = 1; - } - OUTPUT: - RETVAL - gchar_own* -purple_cipher_http_digest_calculate_response(algorithm, method, digest_uri, qop, entity, nonce, nonce_count, client_nonce, session_key) +purple_http_digest_calculate_response(algorithm, method, digest_uri, qop, entity, nonce, nonce_count, client_nonce, session_key) const gchar* algorithm const gchar* method const gchar* digest_uri @@ -94,7 +35,7 @@ purple_cipher_http_digest_calculate_response(algorithm, method, digest_uri, qop, const gchar* session_key gchar_own* -purple_cipher_http_digest_calculate_session_key(algorithm, username, realm, password, nonce, client_nonce) +purple_http_digest_calculate_session_key(algorithm, username, realm, password, nonce, client_nonce) const gchar* algorithm const gchar* username const gchar* realm @@ -102,89 +43,30 @@ purple_cipher_http_digest_calculate_session_key(algorithm, username, realm, pass const gchar* nonce const gchar* client_nonce -MODULE = Purple::Cipher PACKAGE = Purple::Ciphers PREFIX = purple_ciphers_ -PROTOTYPES: ENABLE - -Purple::Cipher -purple_ciphers_find_cipher(name) - gchar * name - -Purple::Cipher -purple_ciphers_register_cipher(name, ops) - gchar * name - Purple::Cipher::Ops ops - -gboolean -purple_ciphers_unregister_cipher(cipher) - Purple::Cipher cipher - void -purple_ciphers_get_ciphers() -PREINIT: - GList *l; -PPCODE: - for (l = purple_ciphers_get_ciphers(); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Cipher"))); - } - -Purple::Handle -purple_ciphers_get_handle() - -MODULE = Purple::Cipher PACKAGE = Purple::Cipher::Context PREFIX = purple_cipher_context_ -PROTOTYPES: ENABLE - -void -purple_cipher_context_set_option(context, name, value) - Purple::Cipher::Context context - gchar *name - gpointer value - -gpointer -purple_cipher_context_get_option(context, name) - Purple::Cipher::Context context - gchar *name - -Purple::Cipher::Context -purple_cipher_context_new(klass, cipher, extra = NULL) +purple_cipher_reset(cipher) Purple::Cipher cipher - void *extra - C_ARGS: cipher, extra - -Purple::Cipher::Context -purple_cipher_context_new_by_name(klass, name, extra = NULL) - gchar *name - void *extra - C_ARGS: name, extra - -void -purple_cipher_context_reset(context, extra = NULL) - Purple::Cipher::Context context - gpointer extra - -void -purple_cipher_context_destroy(context) - Purple::Cipher::Context context void -purple_cipher_context_set_iv(Purple::Cipher::Context context, guchar *iv, size_t length(iv)) +purple_cipher_set_iv(Purple::Cipher cipher, guchar *iv, size_t length(iv)) PROTOTYPE: $$ void -purple_cipher_context_append(Purple::Cipher::Context context, guchar *data, size_t length(data)) +purple_cipher_append(Purple::Cipher cipher, guchar *data, size_t length(data)) PROTOTYPE: $$ gboolean -purple_cipher_context_digest(context, digest) - Purple::Cipher::Context context +purple_cipher_digest(cipher, digest) + Purple::Cipher cipher SV *digest PREINIT: guchar *buff = NULL; size_t digest_size; CODE: - digest_size = purple_cipher_context_get_digest_size(context); + digest_size = purple_cipher_get_digest_size(cipher); SvUPGRADE(digest, SVt_PV); buff = (guchar *)SvGROW(digest, digest_size); - if (purple_cipher_context_digest(context, buff, digest_size)) { + if (purple_cipher_digest(cipher, buff, digest_size)) { SvCUR_set(digest, digest_size); SvPOK_only(digest); RETVAL = 1; @@ -196,18 +78,18 @@ purple_cipher_context_digest(context, digest) RETVAL gboolean -purple_cipher_context_digest_to_str(context, digest_s) - Purple::Cipher::Context context +purple_cipher_digest_to_str(cipher, digest_s) + Purple::Cipher cipher SV *digest_s PREINIT: gchar *buff = NULL; size_t digest_size, str_len; CODE: - digest_size = purple_cipher_context_get_digest_size(context); + digest_size = purple_cipher_get_digest_size(cipher); str_len = 2 * digest_size; SvUPGRADE(digest_s, SVt_PV); buff = SvGROW(digest_s, str_len + 1); - if (purple_cipher_context_digest_to_str(context, buff, str_len + 1)) { + if (purple_cipher_digest_to_str(cipher, buff, str_len + 1)) { SvCUR_set(digest_s, str_len); SvPOK_only(digest_s); RETVAL = 1; @@ -219,8 +101,8 @@ purple_cipher_context_digest_to_str(context, digest_s) RETVAL gboolean -purple_cipher_context_encrypt(context, input, output) - Purple::Cipher::Context context +purple_cipher_encrypt(cipher, input, output) + Purple::Cipher cipher SV *input SV *output PREINIT: @@ -230,10 +112,10 @@ purple_cipher_context_encrypt(context, input, output) guchar *data = NULL; CODE: data = (guchar *)SvPV(input, input_len); - output_len = input_len + purple_cipher_context_get_block_size(context); + output_len = input_len + purple_cipher_get_block_size(cipher); SvUPGRADE(output, SVt_PV); buff = (guchar *)SvGROW(output, output_len); - ret = purple_cipher_context_encrypt(context, data, input_len, buff, output_len); + ret = purple_cipher_encrypt(cipher, data, input_len, buff, output_len); if (ret >= 0) { RETVAL = 1; SvPOK_only(output); @@ -246,8 +128,8 @@ purple_cipher_context_encrypt(context, input, output) RETVAL gboolean -purple_cipher_context_decrypt(context, input, output) - Purple::Cipher::Context context +purple_cipher_decrypt(cipher, input, output) + Purple::Cipher cipher SV *input SV *output PREINIT: @@ -257,10 +139,10 @@ purple_cipher_context_decrypt(context, input, output) guchar *data = NULL; CODE: data = (guchar *)SvPV(input, input_len); - output_len = input_len + purple_cipher_context_get_block_size(context); + output_len = input_len + purple_cipher_get_block_size(cipher); SvUPGRADE(output, SVt_PV); buff = (guchar *)SvGROW(output, output_len); - ret = purple_cipher_context_decrypt(context, data, input_len, buff, output_len); + ret = purple_cipher_decrypt(cipher, data, input_len, buff, output_len); if (ret >= 0) { RETVAL = 1; SvPOK_only(output); @@ -273,44 +155,68 @@ purple_cipher_context_decrypt(context, input, output) RETVAL void -purple_cipher_context_set_salt(context, salt, len) - Purple::Cipher::Context context +purple_cipher_set_salt(cipher, salt, len) + Purple::Cipher cipher guchar *salt size_t len -size_t -purple_cipher_context_get_salt_size(context) - Purple::Cipher::Context context - void -purple_cipher_context_set_key(context, key, len) - Purple::Cipher::Context context +purple_cipher_set_key(cipher, key, len) + Purple::Cipher cipher guchar *key size_t len size_t -purple_cipher_context_get_key_size(context) - Purple::Cipher::Context context - -void -purple_cipher_context_set_data(context, data) - Purple::Cipher::Context context - gpointer data - -gpointer -purple_cipher_context_get_data(context) - Purple::Cipher::Context context +purple_cipher_get_key_size(cipher) + Purple::Cipher cipher Purple::Cipher::BatchMode -purple_cipher_context_get_batch_mode(context) - Purple::Cipher::Context context +purple_cipher_get_batch_mode(cipher) + Purple::Cipher cipher size_t -purple_cipher_context_get_block_size(context) - Purple::Cipher::Context context +purple_cipher_get_block_size(cipher) + Purple::Cipher cipher void -purple_cipher_context_set_batch_mode(context, mode) - Purple::Cipher::Context context +purple_cipher_set_batch_mode(cipher, mode) + Purple::Cipher cipher Purple::Cipher::BatchMode mode +MODULE = Purple::Cipher PACKAGE = Purple::AESCipher PREFIX = purple_aes_cipher_ +PROTOTYPES: ENABLE + +Purple::Cipher +purple_aes_cipher_new() + +MODULE = Purple::Cipher PACKAGE = Purple::DES3Cipher PREFIX = purple_des3_cipher_ +PROTOTYPES: ENABLE + +Purple::Cipher +purple_des3_cipher_new() + +MODULE = Purple::Cipher PACKAGE = Purple::DESCipher PREFIX = purple_des_cipher_ +PROTOTYPES: ENABLE + +Purple::Cipher +purple_des_cipher_new() + +MODULE = Purple::Cipher PACKAGE = Purple::HMACCipher PREFIX = purple_hmac_cipher_ +PROTOTYPES: ENABLE + +Purple::Cipher +purple_hmac_cipher_new(hash) + Purple::Hash hash + +MODULE = Purple::Cipher PACKAGE = Purple::PBKDF2Cipher PREFIX = purple_pbkdf2_cipher_ +PROTOTYPES: ENABLE + +Purple::Cipher +purple_pbkdf2_cipher_new(hash) + Purple::Hash hash + +MODULE = Purple::Cipher PACKAGE = Purple::RC4Cipher PREFIX = purple_rc4_cipher_ +PROTOTYPES: ENABLE + +Purple::Cipher +purple_rc4_cipher_new() diff --git a/libpurple/plugins/perl/common/Connection.xs b/libpurple/plugins/perl/common/Connection.xs index dc0c2660e1..446913fff0 100644 --- a/libpurple/plugins/perl/common/Connection.xs +++ b/libpurple/plugins/perl/common/Connection.xs @@ -8,7 +8,7 @@ BOOT: HV *stash = gv_stashpv("Purple::Connection::State", 1); static const constiv *civ, const_iv[] = { -#define const_iv(name) {#name, (IV)PURPLE_##name} +#define const_iv(name) {#name, (IV)PURPLE_CONNECTION_##name} const_iv(DISCONNECTED), const_iv(CONNECTED), const_iv(CONNECTING), @@ -26,6 +26,16 @@ const char * purple_connection_get_password(gc) Purple::Connection gc +void +purple_connection_get_active_chats(gc) + Purple::Connection gc +PREINIT: + GSList *l; +PPCODE: + for (l = purple_connection_get_active_chats(gc); l != NULL; l = l->next) { + XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ChatConversation"))); + } + const char * purple_connection_get_display_name(gc) Purple::Connection gc diff --git a/libpurple/plugins/perl/common/Conversation.xs b/libpurple/plugins/perl/common/Conversation.xs index 3263aafc4c..dfa101cb60 100644 --- a/libpurple/plugins/perl/common/Conversation.xs +++ b/libpurple/plugins/perl/common/Conversation.xs @@ -5,23 +5,14 @@ PROTOTYPES: ENABLE BOOT: { - HV *type_stash = gv_stashpv("Purple::Conversation::Type", 1); - HV *update_stash = gv_stashpv("Purple::Conversation::Update::Type", 1); - HV *typing_stash = gv_stashpv("Purple::Conversation::TypingState", 1); - HV *flags_stash = gv_stashpv("Purple::Conversation::Flags", 1); - HV *cbflags_stash = gv_stashpv("Purple::Conversation::ChatBuddy::Flags", 1); - - static const constiv *civ, type_const_iv[] = { -#define const_iv(name) {#name, (IV)PURPLE_CONV_TYPE_##name} - const_iv(UNKNOWN), - const_iv(IM), - const_iv(CHAT), - const_iv(MISC), - const_iv(ANY), - }; - static const constiv update_const_iv[] = { + HV *update_stash = gv_stashpv("Purple::Conversation::UpdateType", 1); + HV *typing_stash = gv_stashpv("Purple::IMTypingState", 1); + HV *flags_stash = gv_stashpv("Purple::MessageFlags", 1); + HV *cbflags_stash = gv_stashpv("Purple::ChatUser::Flags", 1); + + static const constiv *civ, update_const_iv[] = { #undef const_iv -#define const_iv(name) {#name, (IV)PURPLE_CONV_UPDATE_##name} +#define const_iv(name) {#name, (IV)PURPLE_CONVERSATION_UPDATE_##name} const_iv(ADD), const_iv(REMOVE), const_iv(ACCOUNT), @@ -41,7 +32,7 @@ BOOT: }; static const constiv typing_const_iv[] = { #undef const_iv -#define const_iv(name) {#name, (IV)PURPLE_##name} +#define const_iv(name) {#name, (IV)PURPLE_IM_##name} const_iv(NOT_TYPING), const_iv(TYPING), const_iv(TYPED), @@ -66,7 +57,7 @@ BOOT: }; static const constiv cbflags_const_iv[] = { #undef const_iv -#define const_iv(name) {#name, (IV)PURPLE_CBFLAGS_##name} +#define const_iv(name) {#name, (IV)PURPLE_CHAT_USER_##name} const_iv(NONE), const_iv(VOICE), const_iv(HALFOP), @@ -75,9 +66,6 @@ BOOT: const_iv(TYPING), }; - for (civ = type_const_iv + sizeof(type_const_iv) / sizeof(type_const_iv[0]); civ-- > type_const_iv; ) - newCONSTSUB(type_stash, (char *)civ->name, newSViv(civ->iv)); - for (civ = update_const_iv + sizeof(update_const_iv) / sizeof(update_const_iv[0]); civ-- > update_const_iv; ) newCONSTSUB(update_stash, (char *)civ->name, newSViv(civ->iv)); @@ -91,56 +79,76 @@ BOOT: newCONSTSUB(cbflags_stash, (char *)civ->name, newSViv(civ->iv)); } +MODULE = Purple::Conversation PACKAGE = Purple::Conversations PREFIX = purple_conversations_ +PROTOTYPES: ENABLE + +void +purple_conversations_add(conv) + Purple::Conversation conv + +void +purple_conversations_remove(conv) + Purple::Conversation conv + +void +purple_conversations_update_cache(conv, name, account) + Purple::Conversation conv + const char * name + Purple::Account account + +Purple::Handle +purple_conversations_get_handle() + +Purple::ChatConversation +purple_conversations_find_chat(gc, id) + Purple::Connection gc + int id + void -purple_get_ims() +purple_conversations_get_ims() PREINIT: GList *l; PPCODE: - for (l = purple_get_ims(); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation"))); + for (l = purple_conversations_get_ims(); l != NULL; l = l->next) { + XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::IMConversation"))); } void -purple_get_conversations() +purple_conversations_get_all() PREINIT: GList *l; PPCODE: - for (l = purple_get_conversations(); l != NULL; l = l->next) { + for (l = purple_conversations_get_all(); l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation"))); } void -purple_get_chats() +purple_conversations_get_chats() PREINIT: GList *l; PPCODE: - for (l = purple_get_chats(); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation"))); + for (l = purple_conversations_get_chats(); l != NULL; l = l->next) { + XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ChatConversation"))); } Purple::Conversation -purple_find_conversation_with_account(type, name, account) - Purple::ConversationType type +purple_conversations_find_with_account(name, account) const char *name Purple::Account account -MODULE = Purple::Conversation PACKAGE = Purple::Conversations PREFIX = purple_conversations_ -PROTOTYPES: ENABLE +Purple::ChatConversation +purple_conversations_find_chat_with_account(name, account) + const char *name + Purple::Account account -Purple::Handle -purple_conversations_get_handle() +Purple::IMConversation +purple_conversations_find_im_with_account(name, account) + const char *name + Purple::Account account MODULE = Purple::Conversation PACKAGE = Purple::Conversation PREFIX = purple_conversation_ PROTOTYPES: ENABLE -void -purple_conversation_destroy(conv) - Purple::Conversation conv - -Purple::ConversationType -purple_conversation_get_type(conv) - Purple::Conversation conv - Purple::Account purple_conversation_get_account(conv) Purple::Conversation conv @@ -180,19 +188,6 @@ gboolean purple_conversation_is_logging(conv) Purple::Conversation conv -Purple::Conversation::IM -purple_conversation_get_im_data(conv) - Purple::Conversation conv - -Purple::Conversation::Chat -purple_conversation_get_chat_data(conv) - Purple::Conversation conv - -gpointer -purple_conversation_get_data(conv, key) - Purple::Conversation conv - const char * key - Purple::ConnectionFlags purple_conversation_get_features(conv) Purple::Conversation conv @@ -204,15 +199,7 @@ purple_conversation_has_focus(conv) void purple_conversation_update(conv, type) Purple::Conversation conv - Purple::ConvUpdateType type - -Purple::Conversation -purple_conversation_new(class, type, account, name) - Purple::ConversationType type - Purple::Account account - const char *name - C_ARGS: - type, account, name + Purple::Conversation::UpdateType type void purple_conversation_set_account(conv, account); @@ -227,6 +214,25 @@ purple_conversation_write(conv, who, message, flags, mtime) Purple::MessageFlags flags time_t mtime +void +purple_conversation_write_message(conv, who, message, flags, mtime) + Purple::Conversation conv + const char *who + const char *message + Purple::MessageFlags flags + time_t mtime + +void +purple_conversation_send(conv, message) + Purple::Conversation conv + const char *message + +void +purple_conversation_send_with_flags(conv, message, flags) + Purple::Conversation conv + const char *message + Purple::MessageFlags flags + gboolean purple_conversation_do_command(conv, cmdline, markup, error) Purple::Conversation conv @@ -234,132 +240,122 @@ purple_conversation_do_command(conv, cmdline, markup, error) const char *markup char **error -MODULE = Purple::Conversation PACKAGE = Purple::Conversation::IM PREFIX = purple_conv_im_ +MODULE = Purple::Conversation PACKAGE = Purple::IMConversation PREFIX = purple_im_conversation_ PROTOTYPES: ENABLE -Purple::Conversation -purple_conv_im_get_conversation(im) - Purple::Conversation::IM im +Purple::IMConversation +purple_im_conversation_new(class, account, name) + Purple::Account account + const char *name + C_ARGS: + account, name void -purple_conv_im_set_icon(im, icon) - Purple::Conversation::IM im +purple_im_conversation_set_icon(im, icon) + Purple::IMConversation im Purple::Buddy::Icon icon Purple::Buddy::Icon -purple_conv_im_get_icon(im) - Purple::Conversation::IM im +purple_im_conversation_get_icon(im) + Purple::IMConversation im void -purple_conv_im_set_typing_state(im, state) - Purple::Conversation::IM im - Purple::TypingState state +purple_im_conversation_set_typing_state(im, state) + Purple::IMConversation im + Purple::IMTypingState state -Purple::TypingState -purple_conv_im_get_typing_state(im) - Purple::Conversation::IM im +Purple::IMTypingState +purple_im_conversation_get_typing_state(im) + Purple::IMConversation im void -purple_conv_im_start_typing_timeout(im, timeout) - Purple::Conversation::IM im +purple_im_conversation_start_typing_timeout(im, timeout) + Purple::IMConversation im int timeout void -purple_conv_im_stop_typing_timeout(im) - Purple::Conversation::IM im +purple_im_conversation_stop_typing_timeout(im) + Purple::IMConversation im guint -purple_conv_im_get_typing_timeout(im) - Purple::Conversation::IM im +purple_im_conversation_get_typing_timeout(im) + Purple::IMConversation im void -purple_conv_im_set_type_again(im, val) - Purple::Conversation::IM im +purple_im_conversation_set_type_again(im, val) + Purple::IMConversation im time_t val time_t -purple_conv_im_get_type_again(im) - Purple::Conversation::IM im +purple_im_conversation_get_type_again(im) + Purple::IMConversation im void -purple_conv_im_start_send_typed_timeout(im) - Purple::Conversation::IM im +purple_im_conversation_start_send_typed_timeout(im) + Purple::IMConversation im void -purple_conv_im_stop_send_typed_timeout(im) - Purple::Conversation::IM im +purple_im_conversation_stop_send_typed_timeout(im) + Purple::IMConversation im guint -purple_conv_im_get_send_typed_timeout(im) - Purple::Conversation::IM im - -void -purple_conv_im_update_typing(im) - Purple::Conversation::IM im +purple_im_conversation_get_send_typed_timeout(im) + Purple::IMConversation im void -purple_conv_im_send(im, message) - Purple::Conversation::IM im - const char *message +purple_im_conversation_update_typing(im) + Purple::IMConversation im -void -purple_conv_im_send_with_flags(im, message, flags) - Purple::Conversation::IM im - const char *message - Purple::MessageFlags flags - -void -purple_conv_im_write(im, who, message, flags, mtime) - Purple::Conversation::IM im - const char *who - const char *message - Purple::MessageFlags flags - time_t mtime - -MODULE = Purple::Conversation PACKAGE = Purple::Conversation PREFIX = purple_conv_ +MODULE = Purple::Conversation PACKAGE = Purple::Conversation::Helper PREFIX = purple_conversation_helper_ PROTOTYPES: ENABLE gboolean -purple_conv_present_error(who, account, what) +purple_conversation_present_error(who, account, what) const char *who Purple::Account account const char *what +MODULE = Purple::Conversation PACKAGE = Purple::Conversation PREFIX = purple_conversation_ +PROTOTYPES: ENABLE + void -purple_conv_custom_smiley_close(conv, smile) +purple_conversation_custom_smiley_close(conv, smile) Purple::Conversation conv const char *smile -MODULE = Purple::Conversation PACKAGE = Purple::Conversation::Chat PREFIX = purple_conv_chat_ +MODULE = Purple::Conversation PACKAGE = Purple::ChatConversation PREFIX = purple_chat_conversation_ PROTOTYPES: ENABLE -Purple::Conversation -purple_conv_chat_get_conversation(chat) - Purple::Conversation::Chat chat +Purple::ChatConversation +purple_chat_conversation_new(class, account, name) + Purple::Account account + const char *name + C_ARGS: + account, name void -purple_conv_chat_get_users(chat) - Purple::Conversation::Chat chat +purple_chat_conversation_get_users(chat) + Purple::ChatConversation chat PREINIT: GList *l; PPCODE: - for (l = purple_conv_chat_get_users(chat); l != NULL; l = l->next) { + for (l = purple_chat_conversation_get_users(chat); l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry"))); } void -purple_conv_chat_ignore(chat, name) - Purple::Conversation::Chat chat +purple_chat_conversation_ignore(chat, name) + Purple::ChatConversation chat const char *name void -purple_conv_chat_unignore(chat, name) - Purple::Conversation::Chat chat +purple_chat_conversation_unignore(chat, name) + Purple::ChatConversation chat const char *name void -purple_conv_chat_set_ignored(chat, ignored) - Purple::Conversation::Chat chat +purple_chat_conversation_set_ignored(chat, ignored) + Purple::ChatConversation chat SV * ignored PREINIT: GList *l, *t_GL; @@ -371,55 +367,36 @@ PPCODE: for (i = 0; i <= t_len; i++) t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(ignored), i, 0))); - for (l = purple_conv_chat_set_ignored(chat, t_GL); l != NULL; l = l->next) { + for (l = purple_chat_conversation_set_ignored(chat, t_GL); l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry"))); } void -purple_conv_chat_get_ignored(chat) - Purple::Conversation::Chat chat +purple_chat_conversation_get_ignored(chat) + Purple::ChatConversation chat PREINIT: GList *l; PPCODE: - for (l = purple_conv_chat_get_ignored(chat); l != NULL; l = l->next) { + for (l = purple_chat_conversation_get_ignored(chat); l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry"))); } const char * -purple_conv_chat_get_topic(chat) - Purple::Conversation::Chat chat +purple_chat_conversation_get_topic(chat) + Purple::ChatConversation chat void -purple_conv_chat_set_id(chat, id) - Purple::Conversation::Chat chat +purple_chat_conversation_set_id(chat, id) + Purple::ChatConversation chat int id int -purple_conv_chat_get_id(chat) - Purple::Conversation::Chat chat - -void -purple_conv_chat_send(chat, message) - Purple::Conversation::Chat chat - const char * message - -void -purple_conv_chat_send_with_flags(chat, message, flags) - Purple::Conversation::Chat chat - const char * message - Purple::MessageFlags flags +purple_chat_conversation_get_id(chat) + Purple::ChatConversation chat void -purple_conv_chat_write(chat, who, message, flags, mtime) - Purple::Conversation::Chat chat - const char *who - const char *message - Purple::MessageFlags flags - time_t mtime - -void -purple_conv_chat_add_users(chat, users, extra_msgs, flags, new_arrivals) - Purple::Conversation::Chat chat +purple_chat_conversation_add_users(chat, users, extra_msgs, flags, new_arrivals) + Purple::ChatConversation chat SV * users SV * extra_msgs SV * flags @@ -446,48 +423,39 @@ PPCODE: for (i = 0; i <= t_len; i++) t_GL_extra_msgs = g_list_append(t_GL_extra_msgs, SvPVutf8_nolen(*av_fetch((AV *)SvRV(extra_msgs), i, 0))); - purple_conv_chat_add_users(chat, t_GL_users, t_GL_extra_msgs, t_GL_flags, new_arrivals); + purple_chat_conversation_add_users(chat, t_GL_users, t_GL_extra_msgs, t_GL_flags, new_arrivals); g_list_free(t_GL_users); g_list_free(t_GL_extra_msgs); g_list_free(t_GL_flags); gboolean -purple_conv_chat_find_user(chat, user) - Purple::Conversation::Chat chat +purple_chat_conversation_has_user(chat, user) + Purple::ChatConversation chat const char * user -void purple_conv_chat_clear_users(chat) - Purple::Conversation::Chat chat +void purple_chat_conversation_clear_users(chat) + Purple::ChatConversation chat -void purple_conv_chat_set_nick(chat, nick) - Purple::Conversation::Chat chat +void purple_chat_conversation_set_nick(chat, nick) + Purple::ChatConversation chat const char * nick const char * -purple_conv_chat_get_nick(chat) - Purple::Conversation::Chat chat +purple_chat_conversation_get_nick(chat) + Purple::ChatConversation chat -Purple::Conversation -purple_find_chat(gc, id) - Purple::Connection gc - int id +void purple_chat_conversation_leave(chat) + Purple::ChatConversation chat -void purple_conv_chat_left(chat) - Purple::Conversation::Chat chat +gboolean purple_chat_conversation_has_left(chat) + Purple::ChatConversation chat -gboolean purple_conv_chat_has_left(chat) - Purple::Conversation::Chat chat - -Purple::Conversation::ChatBuddy -purple_conv_chat_cb_find(chat, name) - Purple::Conversation::Chat chat +Purple::ChatUser +purple_chat_conversation_find_user(chat, name) + Purple::ChatConversation chat const char *name const char * -purple_conv_chat_cb_get_name(cb) - Purple::Conversation::ChatBuddy cb - -void -purple_conv_chat_cb_destroy(cb); - Purple::Conversation::ChatBuddy cb +purple_chat_user_get_name(cb) + Purple::ChatUser cb diff --git a/libpurple/plugins/perl/common/Hash.xs b/libpurple/plugins/perl/common/Hash.xs new file mode 100644 index 0000000000..33e53b36cf --- /dev/null +++ b/libpurple/plugins/perl/common/Hash.xs @@ -0,0 +1,110 @@ +#include "module.h" + +MODULE = Purple::Hash PACKAGE = Purple::Hash PREFIX = purple_hash_ +PROTOTYPES: ENABLE + +const gchar * +purple_hash_get_name(hash) + Purple::Hash hash + +gchar_own* +purple_http_digest_calculate_response(algorithm, method, digest_uri, qop, entity, nonce, nonce_count, client_nonce, session_key) + const gchar* algorithm + const gchar* method + const gchar* digest_uri + const gchar* qop + const gchar* entity + const gchar* nonce + const gchar* nonce_count + const gchar* client_nonce + const gchar* session_key + +gchar_own* +purple_http_digest_calculate_session_key(algorithm, username, realm, password, nonce, client_nonce) + const gchar* algorithm + const gchar* username + const gchar* realm + const gchar* password + const gchar* nonce + const gchar* client_nonce + +void +purple_hash_reset(hash) + Purple::Hash hash + +void +purple_hash_append(Purple::Hash hash, guchar *data, size_t length(data)) + PROTOTYPE: $$ + +gboolean +purple_hash_digest(hash, digest) + Purple::Hash hash + SV *digest + PREINIT: + guchar *buff = NULL; + size_t digest_size; + CODE: + digest_size = purple_hash_get_digest_size(hash); + SvUPGRADE(digest, SVt_PV); + buff = (guchar *)SvGROW(digest, digest_size); + if (purple_hash_digest(hash, buff, digest_size)) { + SvCUR_set(digest, digest_size); + SvPOK_only(digest); + RETVAL = 1; + } else { + SvSetSV_nosteal(digest, &PL_sv_undef); + RETVAL = 0; + } + OUTPUT: + RETVAL + +gboolean +purple_hash_digest_to_str(hash, digest_s) + Purple::Hash hash + SV *digest_s + PREINIT: + gchar *buff = NULL; + size_t digest_size, str_len; + CODE: + digest_size = purple_hash_get_digest_size(hash); + str_len = 2 * digest_size; + SvUPGRADE(digest_s, SVt_PV); + buff = SvGROW(digest_s, str_len + 1); + if (purple_hash_digest_to_str(hash, buff, str_len + 1)) { + SvCUR_set(digest_s, str_len); + SvPOK_only(digest_s); + RETVAL = 1; + } else { + SvSetSV_nosteal(digest_s, &PL_sv_undef); + RETVAL = 0; + } + OUTPUT: + RETVAL + +size_t +purple_hash_get_block_size(hash) + Purple::Hash hash + +MODULE = Purple::Hash PACKAGE = Purple::MD4Hash PREFIX = purple_md4_hash_ +PROTOTYPES: ENABLE + +Purple::Hash +purple_md4_hash_new() + +MODULE = Purple::Hash PACKAGE = Purple::MD5Hash PREFIX = purple_md5_hash_ +PROTOTYPES: ENABLE + +Purple::Hash +purple_md5_hash_new() + +MODULE = Purple::Hash PACKAGE = Purple::SHA1Hash PREFIX = purple_sha1_hash_ +PROTOTYPES: ENABLE + +Purple::Hash +purple_sha1_hash_new() + +MODULE = Purple::Hash PACKAGE = Purple::SHA256Hash PREFIX = purple_sha256_hash_ +PROTOTYPES: ENABLE + +Purple::Hash +purple_sha256_hash_new() diff --git a/libpurple/plugins/perl/common/MANIFEST b/libpurple/plugins/perl/common/MANIFEST index 75e701224a..645f9d533e 100644 --- a/libpurple/plugins/perl/common/MANIFEST +++ b/libpurple/plugins/perl/common/MANIFEST @@ -8,6 +8,7 @@ Connection.xs Conversation.xs Debug.xs FT.xs +Hash.xs ImgStore.xs Log.xs Makefile.PL @@ -17,7 +18,7 @@ Plugin.xs PluginPref.xs Pounce.xs Prefs.xs -Privacy.xs +Presence.xs Proxy.xs Prpl.xs Purple.pm diff --git a/libpurple/plugins/perl/common/Makefile.mingw b/libpurple/plugins/perl/common/Makefile.mingw index 75fd54804e..9afa26dbc3 100644 --- a/libpurple/plugins/perl/common/Makefile.mingw +++ b/libpurple/plugins/perl/common/Makefile.mingw @@ -48,6 +48,7 @@ XS_FILES = Account.xs \ Core.xs \ Debug.xs \ FT.xs \ + Hash.xs \ Idle.xs \ Purple.xs \ ImgStore.xs \ @@ -58,7 +59,7 @@ XS_FILES = Account.xs \ PluginPref.xs \ Pounce.xs \ Prefs.xs \ - Privacy.xs \ + Presence.xs \ Proxy.xs \ Prpl.xs \ Request.xs \ diff --git a/libpurple/plugins/perl/common/Presence.xs b/libpurple/plugins/perl/common/Presence.xs new file mode 100644 index 0000000000..8f8bf5530e --- /dev/null +++ b/libpurple/plugins/perl/common/Presence.xs @@ -0,0 +1,102 @@ +#include "module.h" + +MODULE = Purple::Presence PACKAGE = Purple::Presence PREFIX = purple_presence_ +PROTOTYPES: ENABLE + +Purple::Status +purple_presence_get_active_status(presence) + Purple::Presence presence + +time_t +purple_presence_get_idle_time(presence) + Purple::Presence presence + +time_t +purple_presence_get_login_time(presence) + Purple::Presence presence + +Purple::Status +purple_presence_get_status(presence, status_id) + Purple::Presence presence + const char *status_id + +void +purple_presence_get_statuses(presence) + Purple::Presence presence +PREINIT: + GList *l; +PPCODE: + for (l = purple_presence_get_statuses(presence); l != NULL; l = l->next) { + XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Status"))); + } + +gboolean +purple_presence_is_available(presence) + Purple::Presence presence + +gboolean +purple_presence_is_idle(presence) + Purple::Presence presence + +gboolean +purple_presence_is_online(presence) + Purple::Presence presence + +gboolean +purple_presence_is_status_active(presence, status_id) + Purple::Presence presence + const char *status_id + +gboolean +purple_presence_is_status_primitive_active(presence, primitive) + Purple::Presence presence + Purple::StatusPrimitive primitive + +void +purple_presence_set_idle(presence, idle, idle_time) + Purple::Presence presence + gboolean idle + time_t idle_time + +void +purple_presence_set_login_time(presence, login_time) + Purple::Presence presence + time_t login_time + +void +purple_presence_set_status_active(presence, status_id, active) + Purple::Presence presence + const char *status_id + gboolean active + +void +purple_presence_switch_status(presence, status_id) + Purple::Presence presence + const char *status_id + +MODULE = Purple::Presence PACKAGE = Purple::AccountPresence PREFIX = purple_account_presence_ +PROTOTYPES: ENABLE + +Purple::Account +purple_account_presence_get_account(presence) + Purple::AccountPresence presence + +Purple::AccountPresence +purple_account_presence_new(account) + Purple::Account account + +MODULE = Purple::Presence PACKAGE = Purple::BuddyPresence PREFIX = purple_buddy_presence_ +PROTOTYPES: ENABLE + +gint +purple_buddy_presence_compare(presence1, presence2) + Purple::BuddyPresence presence1 + Purple::BuddyPresence presence2 + +Purple::BuddyList::Buddy +purple_buddy_presence_get_buddy(presence) + Purple::BuddyPresence presence + +Purple::BuddyPresence +purple_buddy_presence_new(buddy) + Purple::BuddyList::Buddy buddy diff --git a/libpurple/plugins/perl/common/Privacy.xs b/libpurple/plugins/perl/common/Privacy.xs deleted file mode 100644 index dbb63a594d..0000000000 --- a/libpurple/plugins/perl/common/Privacy.xs +++ /dev/null @@ -1,33 +0,0 @@ -#include "module.h" - -MODULE = Purple::Privacy PACKAGE = Purple::Privacy PREFIX = purple_privacy_ -PROTOTYPES: ENABLE - -gboolean -purple_privacy_permit_add(account, name, local_only) - Purple::Account account - const char * name - gboolean local_only - -gboolean -purple_privacy_permit_remove(account, name, local_only) - Purple::Account account - const char * name - gboolean local_only - -gboolean -purple_privacy_deny_add(account, name, local_only) - Purple::Account account - const char * name - gboolean local_only - -gboolean -purple_privacy_deny_remove(account, name, local_only) - Purple::Account account - const char * name - gboolean local_only - -gboolean -purple_privacy_check(account, who) - Purple::Account account - const char * who diff --git a/libpurple/plugins/perl/common/Prpl.xs b/libpurple/plugins/perl/common/Prpl.xs index 765ce5d41a..3e13133d21 100644 --- a/libpurple/plugins/perl/common/Prpl.xs +++ b/libpurple/plugins/perl/common/Prpl.xs @@ -65,7 +65,7 @@ CODE: if (!gc) RETVAL = 0; else { - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info && prpl_info->send_raw != NULL) { RETVAL = prpl_info->send_raw(gc, str, strlen(str)); } else { diff --git a/libpurple/plugins/perl/common/Server.xs b/libpurple/plugins/perl/common/Server.xs index 13e2aefcbf..a354029619 100644 --- a/libpurple/plugins/perl/common/Server.xs +++ b/libpurple/plugins/perl/common/Server.xs @@ -104,7 +104,7 @@ serv_got_im(gc, who, msg, imflags, mtime) Purple::MessageFlags imflags time_t mtime -Purple::Conversation +Purple::ChatConversation serv_got_joined_chat(gc, id, name) Purple::Connection gc int id @@ -115,7 +115,7 @@ serv_got_typing(gc, name, timeout, state) Purple::Connection gc const char *name int timeout - Purple::TypingState state + Purple::IMTypingState state void serv_got_typing_stopped(gc, name) @@ -203,7 +203,7 @@ int serv_send_typing(con, a, state) Purple::Connection con const char * a - Purple::TypingState state + Purple::IMTypingState state void serv_set_info(con, a) diff --git a/libpurple/plugins/perl/common/Status.xs b/libpurple/plugins/perl/common/Status.xs index 8965870ade..8c50ace626 100644 --- a/libpurple/plugins/perl/common/Status.xs +++ b/libpurple/plugins/perl/common/Status.xs @@ -39,22 +39,14 @@ purple_status_set_active_with_attrs(status, active, args) */ -MODULE = Purple::Status PACKAGE = Purple::Presence PREFIX = purple_presence_ +MODULE = Purple::Status PACKAGE = Purple::Primitive PREFIX = purple_primitive_ PROTOTYPES: ENABLE BOOT: { - HV *context_stash = gv_stashpv("Purple::Presence::Context", 1); HV *primitive_stash = gv_stashpv("Purple::Status::Primitive", 1); - static const constiv *civ, context_const_iv[] = { -#define const_iv(name) {#name, (IV)PURPLE_PRESENCE_CONTEXT_##name} - const_iv(UNSET), - const_iv(ACCOUNT), - const_iv(CONV), - const_iv(BUDDY), - }; - static const constiv primitive_const_iv[] = { + static const constiv *civ, primitive_const_iv[] = { #undef const_iv #define const_iv(name) {#name, (IV)PURPLE_STATUS_##name} const_iv(UNSET), @@ -67,128 +59,10 @@ BOOT: const_iv(MOBILE), }; - for (civ = context_const_iv + sizeof(context_const_iv) / sizeof(context_const_iv[0]); civ-- > context_const_iv; ) - newCONSTSUB(context_stash, (char *)civ->name, newSViv(civ->iv)); - for (civ = primitive_const_iv + sizeof(primitive_const_iv) / sizeof(primitive_const_iv[0]); civ-- > primitive_const_iv; ) newCONSTSUB(primitive_stash, (char *)civ->name, newSViv(civ->iv)); } -gint -purple_presence_compare(presence1, presence2) - Purple::Presence presence1 - Purple::Presence presence2 - -void -purple_presence_destroy(presence) - Purple::Presence presence - -Purple::Account -purple_presence_get_account(presence) - Purple::Presence presence - -Purple::Status -purple_presence_get_active_status(presence) - Purple::Presence presence - -const char * -purple_presence_get_chat_user(presence) - Purple::Presence presence - -Purple::PresenceContext -purple_presence_get_context(presence) - Purple::Presence presence - -Purple::Conversation -purple_presence_get_conversation(presence) - Purple::Presence presence - -time_t -purple_presence_get_idle_time(presence) - Purple::Presence presence - -time_t -purple_presence_get_login_time(presence) - Purple::Presence presence - -Purple::Status -purple_presence_get_status(presence, status_id) - Purple::Presence presence - const char *status_id - -void -purple_presence_get_statuses(presence) - Purple::Presence presence -PREINIT: - GList *l; -PPCODE: - for (l = purple_presence_get_statuses(presence); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Status"))); - } - -gboolean -purple_presence_is_available(presence) - Purple::Presence presence - -gboolean -purple_presence_is_idle(presence) - Purple::Presence presence - -gboolean -purple_presence_is_online(presence) - Purple::Presence presence - -gboolean -purple_presence_is_status_active(presence, status_id) - Purple::Presence presence - const char *status_id - -gboolean -purple_presence_is_status_primitive_active(presence, primitive) - Purple::Presence presence - Purple::StatusPrimitive primitive - -Purple::Presence -purple_presence_new(context) - Purple::PresenceContext context - -Purple::Presence -purple_presence_new_for_account(account) - Purple::Account account - -Purple::Presence -purple_presence_new_for_buddy(buddy) - Purple::BuddyList::Buddy buddy - -Purple::Presence -purple_presence_new_for_conv(conv) - Purple::Conversation conv - -void -purple_presence_set_idle(presence, idle, idle_time) - Purple::Presence presence - gboolean idle - time_t idle_time - -void -purple_presence_set_login_time(presence, login_time) - Purple::Presence presence - time_t login_time - -void -purple_presence_set_status_active(presence, status_id, active) - Purple::Presence presence - const char *status_id - gboolean active - -void -purple_presence_switch_status(presence, status_id) - Purple::Presence presence - const char *status_id - -MODULE = Purple::Status PACKAGE = Purple::Primitive PREFIX = purple_primitive_ -PROTOTYPES: ENABLE - const char * purple_primitive_get_id_from_type(type) Purple::StatusPrimitive type @@ -201,30 +75,30 @@ Purple::StatusPrimitive purple_primitive_get_type_from_id(id) const char *id -MODULE = Purple::Status PACKAGE = Purple::StatusAttr PREFIX = purple_status_attr_ +MODULE = Purple::Status PACKAGE = Purple::StatusAttr PREFIX = purple_status_attribute_ PROTOTYPES: ENABLE void -purple_status_attr_destroy(attr) +purple_status_attribute_destroy(attr) Purple::StatusAttr attr const char * -purple_status_attr_get_id(attr) +purple_status_attribute_get_id(attr) Purple::StatusAttr attr const char * -purple_status_attr_get_name(attr) +purple_status_attribute_get_name(attr) Purple::StatusAttr attr -Purple::Value -purple_status_attr_get_value(attr) +GValue * +purple_status_attribute_get_value(attr) Purple::StatusAttr attr Purple::StatusAttr -purple_status_attr_new(id, name, value_type) +purple_status_attribute_new(id, name, value_type) const char *id const char *name - Purple::Value value_type + GValue *value_type MODULE = Purple::Status PACKAGE = Purple::Status PREFIX = purple_status_ PROTOTYPES: ENABLE @@ -234,10 +108,6 @@ purple_status_compare(status1, status2) Purple::Status status1 Purple::Status status2 -void -purple_status_destroy(status) - Purple::Status status - gboolean purple_status_get_attr_boolean(status, id) Purple::Status status @@ -253,13 +123,13 @@ purple_status_get_attr_string(status, id) Purple::Status status const char *id -Purple::Value +GValue * purple_status_get_attr_value(status, id) Purple::Status status const char *id Purple::Handle -purple_status_get_handle() +purple_statuses_get_handle() const char * purple_status_get_id(status) @@ -274,7 +144,7 @@ purple_status_get_presence(status) Purple::Status status Purple::StatusType -purple_status_get_type(status) +purple_status_get_status_type(status) Purple::Status status gboolean diff --git a/libpurple/plugins/perl/common/module.h b/libpurple/plugins/perl/common/module.h index f16aa48084..9c4627c339 100644 --- a/libpurple/plugins/perl/common/module.h +++ b/libpurple/plugins/perl/common/module.h @@ -19,15 +19,26 @@ typedef struct group *Purple__Group; #include "../perl-common.h" -#include "account.h" +#include "accounts.h" #include "accountopt.h" -#include "blist.h" +#include "buddylist.h" #include "buddyicon.h" #include "certificate.h" #include "cipher.h" +#include "ciphers/aescipher.h" +#include "ciphers/des3cipher.h" +#include "ciphers/descipher.h" +#include "ciphers/hmaccipher.h" +#include "ciphers/pbkdf2cipher.h" +#include "ciphers/rc4cipher.h" +#include "hash.h" +#include "ciphers/md4hash.h" +#include "ciphers/md5hash.h" +#include "ciphers/sha1hash.h" +#include "ciphers/sha256hash.h" #include "cmds.h" #include "connection.h" -#include "conversation.h" +#include "conversations.h" #include "core.h" #include "debug.h" #include "desktopitem.h" @@ -48,7 +59,7 @@ typedef struct group *Purple__Group; #include "pluginpref.h" #include "pounce.h" #include "prefs.h" -#include "privacy.h" +#include "presence.h" #include "prpl.h" #include "proxy.h" #include "request.h" @@ -63,7 +74,6 @@ typedef struct group *Purple__Group; #include "stringref.h" /* Ewww. perl has it's own util.h which is in the include path :( */ #include "libpurple/util.h" -#include "value.h" #include "whiteboard.h" #include "xmlnode.h" @@ -71,11 +81,11 @@ typedef struct group *Purple__Group; typedef PurpleAccount * Purple__Account; typedef PurpleAccountOption * Purple__Account__Option; typedef PurpleAccountUserSplit * Purple__Account__UserSplit; +typedef PurpleAccountPrivacyType Purple__Account__PrivacyType; -/* blist.h */ +/* buddylist.h */ typedef PurpleBlistNode * Purple__BuddyList__Node; -typedef PurpleBlistNodeFlags Purple__BuddyList__NodeFlags; -typedef PurpleBlistNodeType Purple__BuddyList__NodeType; +typedef PurpleCountingNode * Purple__BuddyList__CountingNode; typedef PurpleBuddyList * Purple__BuddyList; typedef PurpleBuddy * Purple__BuddyList__Buddy; typedef PurpleChat * Purple__BuddyList__Chat; @@ -95,9 +105,6 @@ typedef PurpleCertificateVerificationStatus Purple__Certificate__VerificationSta /* cipher.h */ typedef PurpleCipher * Purple__Cipher; -typedef PurpleCipherCaps Purple__CipherCaps; -typedef PurpleCipherContext * Purple__Cipher__Context; -typedef PurpleCipherOps * Purple__Cipher__Ops; typedef PurpleCipherBatchMode Purple__Cipher__BatchMode; /* cmds.h */ @@ -111,16 +118,15 @@ typedef PurpleConnection * Purple__Connection; typedef PurpleConnectionFlags Purple__ConnectionFlags; typedef PurpleConnectionState Purple__ConnectionState; -/* conversation.h */ -typedef PurpleConversationType Purple__ConversationType; -typedef PurpleConvUpdateType Purple__ConvUpdateType; -typedef PurpleTypingState Purple__TypingState; -typedef PurpleMessageFlags Purple__MessageFlags; -typedef PurpleConvChatBuddyFlags Purple__ConvChatBuddyFlags; +/* conversations.h */ +typedef PurpleMessageFlags Purple__MessageFlags; typedef PurpleConversation * Purple__Conversation; -typedef PurpleConvIm * Purple__Conversation__IM; -typedef PurpleConvChat * Purple__Conversation__Chat; -typedef PurpleConvChatBuddy * Purple__Conversation__ChatBuddy; +typedef PurpleConversationUpdateType Purple__Conversation__UpdateType; +typedef PurpleIMConversation * Purple__IMConversation; +typedef PurpleIMTypingState Purple__IMTypingState; +typedef PurpleChatConversation * Purple__ChatConversation; +typedef PurpleChatUser * Purple__ChatUser; +typedef PurpleChatUserFlags Purple__ChatUser__Flags; /* core.h */ @@ -168,6 +174,9 @@ typedef GtkTextView * Purple__GTK__TextView; /* gtkconn.h */ #endif +/* hash.h */ +typedef PurpleHash * Purple__Hash; + /* imgstore.h */ typedef PurpleStoredImage * Purple__StoredImage; @@ -215,8 +224,10 @@ typedef PurplePounceEvent Purple__PounceEvent; /* prefs.h */ typedef PurplePrefType Purple__PrefType; -/* privacy.h */ -typedef PurplePrivacyType Purple__PrivacyType; +/* presence.h */ +typedef PurplePresence * Purple__Presence; +typedef PurpleAccountPresence * Purple__AccountPresence; +typedef PurpleBuddyPresence * Purple__BuddyPresence; /* proxy.h */ typedef PurpleProxyInfo * Purple__ProxyInfo; @@ -259,10 +270,8 @@ typedef PurpleSslErrorType Purple__SslErrorType; typedef PurpleSslOps * Purple__Ssl__Ops; /* status.h */ -typedef PurplePresence * Purple__Presence; -typedef PurplePresenceContext Purple__PresenceContext; typedef PurpleStatus * Purple__Status; -typedef PurpleStatusAttr * Purple__StatusAttr; +typedef PurpleStatusAttribute * Purple__StatusAttr; typedef PurpleStatusPrimitive Purple__StatusPrimitive; typedef PurpleStatusType * Purple__StatusType; @@ -273,9 +282,6 @@ typedef PurpleStringref * Purple__Stringref; typedef PurpleInfoFieldFormatCallback Purple__Util__InfoFieldFormatCallback; typedef PurpleMenuAction * Purple__Menu__Action; -/* value.h */ -typedef PurpleValue * Purple__Value; - /* whiteboard.h */ typedef PurpleWhiteboard * Purple__Whiteboard; diff --git a/libpurple/plugins/perl/common/typemap b/libpurple/plugins/perl/common/typemap index 6f698a220a..5cad01ffc5 100644 --- a/libpurple/plugins/perl/common/typemap +++ b/libpurple/plugins/perl/common/typemap @@ -38,10 +38,13 @@ xmlnode * T_PTR const xmlnode * T_PTR gssize T_IV const void * T_PTR +GValue * T_PTR +GType T_IV Purple::Account T_PurpleObj Purple::Account::Option T_PurpleObj Purple::Account::UserSplit T_PurpleObj +Purple::Account::PrivacyType T_IV Purple::Buddy::Icon T_PurpleObj Purple::Buddy::Icon::Spec T_PurpleObj @@ -51,22 +54,15 @@ Purple::BuddyList::Chat T_PurpleObj Purple::BuddyList::Contact T_PurpleObj Purple::BuddyList::Group T_PurpleObj Purple::BuddyList::Node T_PurpleObj -Purple::BuddyList::NodeFlags T_IV -Purple::BuddyList::NodeType T_IV +Purple::BuddyList::CountingNode T_PurpleObj Purple::Cipher T_PurpleObj -Purple::CipherCaps T_IV -Purple::Cipher::Ops T_PurpleObj -Purple::Cipher::Context T_PurpleObj +Purple::Hash T_PurpleObj Purple::Cmd::Flag T_IV Purple::Cmd::Id T_IV Purple::Cmd::Priority T_IV Purple::Cmd::Ret T_IV Purple::Connection T_PurpleObj -Purple::Conversation T_PurpleObj -Purple::Conversation::Chat T_PurpleObj -Purple::Conversation::ChatBuddy T_PurpleObj -Purple::Conversation::IM T_PurpleObj Purple::Core T_PurpleObj Purple::Desktop::Item T_PurpleObj @@ -111,8 +107,6 @@ Purple::PluginPrefType T_IV Purple::PluginPref::Frame T_PurpleObj Purple::Pounce T_PurpleObj Purple::PounceEvent T_IV -Purple::Presence T_PurpleObj -Purple::PrivacyType T_IV Purple::ProtocolOptions T_IV Purple::ProxyInfo T_PurpleObj Purple::ProxyType T_IV @@ -141,7 +135,8 @@ Purple::Ssl::Connection T_PurpleObj Purple::Ssl::Ops T_PurpleObj Purple::Presence T_PurpleObj -Purple::PresenceContext T_IV +Purple::AccountPresence T_PurpleObj +Purple::BuddyPresence T_PurpleObj Purple::Smiley T_PurpleObj Purple::Status T_PurpleObj Purple::StatusAttr T_PurpleObj @@ -154,7 +149,6 @@ Purple::String::Format::Type T_IV Purple::Stringref T_PurpleObj Purple::Util::FetchUrlData T_PTR Purple::Util::InfoFieldFormatCallback T_PTR -Purple::Value T_PurpleObj Purple::Xfer T_PurpleObj Purple::XferType T_IV @@ -181,12 +175,15 @@ Purple::Cipher::BatchMode T_IV /* debug.h */ Purple::DebugLevel T_IV -/* conversation.h */ -Purple::ConvChatBuddyFlags T_IV -Purple::ConvUpdateType T_IV -Purple::ConversationType T_IV +/* conversations.h */ +Purple::Conversation T_PurpleObj +Purple::ChatConversation T_PurpleObj +Purple::ChatUser T_PurpleObj +Purple::IMConversation T_PurpleObj +Purple::ChatUser::Flags T_IV +Purple::Conversation::UpdateType T_IV Purple::MessageFlags T_IV -Purple::TypingState T_IV +Purple::IMTypingState T_IV Purple::UnseenState T_IV /* connection.h */ diff --git a/libpurple/plugins/perl/perl-common.c b/libpurple/plugins/perl/perl-common.c index 520a8c420a..aa890fa52e 100644 --- a/libpurple/plugins/perl/perl-common.c +++ b/libpurple/plugins/perl/perl-common.c @@ -1,8 +1,9 @@ -#include "debug.h" -#include "value.h" - #include "perl-common.h" +#include "cipher.h" +#include "debug.h" +#include "savedstatuses.h" + extern PerlInterpreter *my_perl; static GHashTable *object_stashes = NULL; @@ -379,102 +380,76 @@ purple_perl_sv_from_value(const PurpleValue *value, va_list list) #endif void * -purple_perl_data_from_sv(PurpleValue *value, SV *sv) +purple_perl_data_from_sv(GType type, SV *sv) { - - switch (purple_value_get_type(value)) { - case PURPLE_TYPE_BOOLEAN: return (void *)SvIV(sv); - case PURPLE_TYPE_INT: return (void *)SvIV(sv); - case PURPLE_TYPE_UINT: return (void *)SvUV(sv); - case PURPLE_TYPE_LONG: return (void *)SvIV(sv); - case PURPLE_TYPE_ULONG: return (void *)SvUV(sv); - case PURPLE_TYPE_INT64: return (void *)SvIV(sv); - case PURPLE_TYPE_UINT64: return (void *)SvUV(sv); - case PURPLE_TYPE_STRING: return g_strdup(SvPVutf8_nolen(sv)); - case PURPLE_TYPE_POINTER: return (void *)SvIV(sv); - case PURPLE_TYPE_BOXED: return (void *)SvIV(sv); - - default: - return NULL; + switch (type) { + case G_TYPE_BOOLEAN: return (void *)SvIV(sv); + case G_TYPE_INT: return (void *)SvIV(sv); + case G_TYPE_UINT: return (void *)SvUV(sv); + case G_TYPE_LONG: return (void *)SvIV(sv); + case G_TYPE_ULONG: return (void *)SvUV(sv); + case G_TYPE_INT64: return (void *)SvIV(sv); + case G_TYPE_UINT64: return (void *)SvUV(sv); + case G_TYPE_STRING: return g_strdup(SvPVutf8_nolen(sv)); + case G_TYPE_POINTER: return (void *)SvIV(sv); } return NULL; } static SV * -purple_perl_sv_from_subtype(const PurpleValue *value, void *arg) +purple_perl_sv_from_purple_type(GType type, void *arg) { const char *stash = "Purple"; /* ? */ - switch (purple_value_get_subtype(value)) { - case PURPLE_SUBTYPE_ACCOUNT: - stash = "Purple::Account"; - break; - case PURPLE_SUBTYPE_BLIST: - stash = "Purple::BuddyList"; - break; - case PURPLE_SUBTYPE_BLIST_BUDDY: - stash = "Purple::BuddyList::Buddy"; - break; - case PURPLE_SUBTYPE_BLIST_GROUP: - stash = "Purple::BuddyList::Group"; - break; - case PURPLE_SUBTYPE_BLIST_CHAT: - stash = "Purple::BuddyList::Chat"; - break; - case PURPLE_SUBTYPE_BUDDY_ICON: - stash = "Purple::Buddy::Icon"; - break; - case PURPLE_SUBTYPE_CONNECTION: - stash = "Purple::Connection"; - break; - case PURPLE_SUBTYPE_CONVERSATION: - stash = "Purple::Conversation"; - break; - case PURPLE_SUBTYPE_PLUGIN: - stash = "Purple::Plugin"; - break; - case PURPLE_SUBTYPE_BLIST_NODE: - stash = "Purple::BuddyList::Node"; - break; - case PURPLE_SUBTYPE_CIPHER: - stash = "Purple::Cipher"; - break; - case PURPLE_SUBTYPE_STATUS: - stash = "Purple::Status"; - break; - case PURPLE_SUBTYPE_SAVEDSTATUS: - stash = "Purple::SavedStatus"; - break; - case PURPLE_SUBTYPE_LOG: - stash = "Purple::Log"; - break; - case PURPLE_SUBTYPE_XFER: - stash = "Purple::Xfer"; - break; - case PURPLE_SUBTYPE_XMLNODE: - stash = "Purple::XMLNode"; - break; - case PURPLE_SUBTYPE_USERINFO: - stash = "Purple::NotifyUserInfo"; - break; - case PURPLE_SUBTYPE_STORED_IMAGE: - stash = "Purple::StoredImage"; - break; - case PURPLE_SUBTYPE_CERTIFICATEPOOL: - stash = "Purple::Certificate::Pool"; - break; - case PURPLE_SUBTYPE_UNKNOWN: - stash = "Purple::Unknown"; - break; - } + if (type == PURPLE_TYPE_ACCOUNT) + stash = "Purple::Account"; + else if (type == PURPLE_TYPE_CONTACT) + stash = "Purple::BuddyList::Contact"; + else if (type == PURPLE_TYPE_BUDDY) + stash = "Purple::BuddyList::Buddy"; + else if (type == PURPLE_TYPE_GROUP) + stash = "Purple::BuddyList::Group"; + else if (type == PURPLE_TYPE_CHAT) + stash = "Purple::BuddyList::Chat"; + else if (type == PURPLE_TYPE_BUDDY_ICON) + stash = "Purple::Buddy::Icon"; + else if (type == PURPLE_TYPE_CONNECTION) + stash = "Purple::Connection"; + else if (type == PURPLE_TYPE_CONVERSATION) + stash = "Purple::Conversation"; + else if (type == PURPLE_TYPE_PLUGIN) + stash = "Purple::Plugin"; + else if (type == PURPLE_TYPE_BLIST_NODE) + stash = "Purple::BuddyList::Node"; + else if (type == PURPLE_TYPE_CIPHER) + stash = "Purple::Cipher"; + else if (type == PURPLE_TYPE_STATUS) + stash = "Purple::Status"; + else if (type == PURPLE_TYPE_SAVEDSTATUS) + stash = "Purple::SavedStatus"; + else if (type == PURPLE_TYPE_LOG) + stash = "Purple::Log"; + else if (type == PURPLE_TYPE_XFER) + stash = "Purple::Xfer"; + else if (type == PURPLE_TYPE_XMLNODE) + stash = "Purple::XMLNode"; + else if (type == PURPLE_TYPE_NOTIFY_USER_INFO) + stash = "Purple::NotifyUserInfo"; + else if (type == PURPLE_TYPE_STORED_IMAGE) + stash = "Purple::StoredImage"; + else if (type == PURPLE_TYPE_CERTIFICATE_POOL) + stash = "Purple::Certificate::Pool"; + else + stash = "Purple::Unknown"; return sv_2mortal(purple_perl_bless_object(arg, stash)); } SV * -purple_perl_sv_from_vargs(const PurpleValue *value, va_list *args, void ***copy_arg) +purple_perl_sv_from_vargs(GType type, va_list *args, void ***copy_arg) { +#if 0 if (purple_value_is_outgoing(value)) { switch (purple_value_get_type(value)) { case PURPLE_TYPE_SUBTYPE: @@ -552,80 +527,60 @@ purple_perl_sv_from_vargs(const PurpleValue *value, va_list *args, void ***copy_ return NULL; } } else { - switch (purple_value_get_type(value)) { - case PURPLE_TYPE_SUBTYPE: - if ((*copy_arg = va_arg(*args, void *)) == NULL) - return &PL_sv_undef; - - return purple_perl_sv_from_subtype(value, *copy_arg); +#endif + switch (type) { + case G_TYPE_BOOLEAN: + *copy_arg = GINT_TO_POINTER( va_arg(*args, gboolean) ); - case PURPLE_TYPE_BOOLEAN: - *copy_arg = GINT_TO_POINTER( va_arg(*args, gboolean) ); + return newSViv((gboolean)GPOINTER_TO_INT(*copy_arg)); - return newSViv((gboolean)GPOINTER_TO_INT(*copy_arg)); + case G_TYPE_INT: + *copy_arg = GINT_TO_POINTER( va_arg(*args, int) ); - case PURPLE_TYPE_INT: - *copy_arg = GINT_TO_POINTER( va_arg(*args, int) ); + return newSViv(GPOINTER_TO_INT(*copy_arg)); - return newSViv(GPOINTER_TO_INT(*copy_arg)); + case G_TYPE_UINT: + *copy_arg = GUINT_TO_POINTER(va_arg(*args, unsigned int)); - case PURPLE_TYPE_UINT: - *copy_arg = GUINT_TO_POINTER(va_arg(*args, unsigned int)); + return newSVuv(GPOINTER_TO_UINT(*copy_arg)); - return newSVuv(GPOINTER_TO_UINT(*copy_arg)); + case G_TYPE_LONG: + *copy_arg = (void *)va_arg(*args, long); - case PURPLE_TYPE_LONG: - *copy_arg = (void *)va_arg(*args, long); + return newSViv((long)*copy_arg); - return newSViv((long)*copy_arg); + case G_TYPE_ULONG: + *copy_arg = (void *)va_arg(*args, unsigned long); - case PURPLE_TYPE_ULONG: - *copy_arg = (void *)va_arg(*args, unsigned long); + return newSVuv((unsigned long)*copy_arg); - return newSVuv((unsigned long)*copy_arg); + case G_TYPE_INT64: + *copy_arg = (void *)va_arg(*args, gint64); - case PURPLE_TYPE_INT64: -#if 0 - /* XXX This yells and complains. */ - *copy_arg = va_arg(*args, gint64); + return newSViv((gint64)*copy_arg); - return newSViv(*copy_arg); -#endif - break; + case G_TYPE_UINT64: + *copy_arg = (void *)va_arg(*args, guint64); - case PURPLE_TYPE_UINT64: - /* XXX This also yells and complains. */ -#if 0 - *copy_arg = (void *)va_arg(*args, guint64); + return newSVuv((guint64)*copy_arg); - return newSVuv(*copy_arg); -#endif - break; + case G_TYPE_STRING: + if ((*copy_arg = (void *)va_arg(*args, char *)) == NULL) + return &PL_sv_undef; - case PURPLE_TYPE_STRING: - if ((*copy_arg = (void *)va_arg(*args, char *)) == NULL) - return &PL_sv_undef; + return newSVGChar((char *)*copy_arg); - return newSVGChar((char *)*copy_arg); + case G_TYPE_POINTER: + if ((*copy_arg = (void *)va_arg(*args, void *)) == NULL) + return &PL_sv_undef; - case PURPLE_TYPE_POINTER: - if ((*copy_arg = (void *)va_arg(*args, void *)) == NULL) - return &PL_sv_undef; - - return newSViv((IV)*copy_arg); - - case PURPLE_TYPE_BOXED: - /* Uh.. I dunno. Try this? */ - if ((*copy_arg = (void *)va_arg(*args, void *)) == NULL) - return &PL_sv_undef; + return newSViv((IV)*copy_arg); - return sv_2mortal(purple_perl_bless_object(*copy_arg, - purple_value_get_specific_type(value))); + default: + if ((*copy_arg = va_arg(*args, void *)) == NULL) + return &PL_sv_undef; - default: - /* If this happens, things are going to get screwed up... */ - return NULL; - } + return purple_perl_sv_from_purple_type(type, *copy_arg); } return NULL; diff --git a/libpurple/plugins/perl/perl-common.h b/libpurple/plugins/perl/perl-common.h index 677e3bcaba..cda580c054 100644 --- a/libpurple/plugins/perl/perl-common.h +++ b/libpurple/plugins/perl/perl-common.h @@ -21,7 +21,6 @@ #undef _WIN32DEP_H_ #endif #include "plugin.h" -#include "value.h" #define is_hvref(o) \ ((o) && SvROK(o) && SvRV(o) && (SvTYPE(SvRV(o)) == SVt_PVHV)) @@ -68,8 +67,7 @@ gboolean purple_perl_value_from_sv(PurpleValue *value, SV *sv); SV *purple_perl_sv_from_value(const PurpleValue *value); #endif -void *purple_perl_data_from_sv(PurpleValue *value, SV *sv); -SV *purple_perl_sv_from_vargs(const PurpleValue *value, va_list *args, - void ***copy_arg); +void *purple_perl_data_from_sv(GType type, SV *sv); +SV *purple_perl_sv_from_vargs(GType type, va_list *args, void ***copy_arg); SV *purple_perl_sv_from_fun(PurplePlugin *plugin, SV *callback); #endif /* _PURPLE_PERL_COMMON_H_ */ diff --git a/libpurple/plugins/perl/perl-handlers.c b/libpurple/plugins/perl/perl-handlers.c index 1e8eb5830d..d87f63cfc7 100644 --- a/libpurple/plugins/perl/perl-handlers.c +++ b/libpurple/plugins/perl/perl-handlers.c @@ -285,7 +285,7 @@ perl_signal_cb(va_list args, void *data) int i; int count; int value_count; - PurpleValue *ret_value, **values; + GType ret_type, *value_types; SV **sv_args; DATATYPE **copy_args; @@ -296,14 +296,14 @@ perl_signal_cb(va_list args, void *data) SAVETMPS; PUSHMARK(sp); - purple_signal_get_values(handler->instance, handler->signal, - &ret_value, &value_count, &values); + purple_signal_get_types(handler->instance, handler->signal, + &ret_type, &value_count, &value_types); sv_args = g_new(SV *, value_count); copy_args = g_new(void **, value_count); for (i = 0; i < value_count; i++) { - sv_args[i] = purple_perl_sv_from_vargs(values[i], + sv_args[i] = purple_perl_sv_from_vargs(value_types[i], #ifdef VA_COPY_AS_ARRAY (va_list*)args, #else @@ -318,7 +318,7 @@ perl_signal_cb(va_list args, void *data) PUTBACK; - if (ret_value != NULL) { + if (ret_type != G_TYPE_NONE) { count = call_sv(handler->callback, G_EVAL | G_SCALAR); SPAGAIN; @@ -326,7 +326,7 @@ perl_signal_cb(va_list args, void *data) if (count != 1) croak("Uh oh! call_sv returned %i != 1", i); else - ret_val = purple_perl_data_from_sv(ret_value, POPs); + ret_val = purple_perl_data_from_sv(ret_type, POPs); } else { call_sv(handler->callback, G_EVAL | G_SCALAR); @@ -339,6 +339,7 @@ perl_signal_cb(va_list args, void *data) SvPVutf8_nolen(ERRSV)); } +#if 0 /* See if any parameters changed. */ for (i = 0; i < value_count; i++) { if (purple_value_is_outgoing(values[i])) { @@ -401,6 +402,7 @@ perl_signal_cb(va_list args, void *data) #endif } } +#endif PUTBACK; FREETMPS; diff --git a/libpurple/plugins/psychic.c b/libpurple/plugins/psychic.c index 787bfd1654..c79cd0ca21 100644 --- a/libpurple/plugins/psychic.c +++ b/libpurple/plugins/psychic.c @@ -3,13 +3,12 @@ #include "internal.h" #include "account.h" -#include "blist.h" +#include "buddylist.h" #include "conversation.h" #include "debug.h" #include "signals.h" #include "status.h" #include "version.h" -#include "privacy.h" #include "plugin.h" #include "pluginpref.h" @@ -34,7 +33,7 @@ static void buddy_typing_cb(PurpleAccount *acct, const char *name, void *data) { - PurpleConversation *gconv; + PurpleIMConversation *im; if(purple_prefs_get_bool(PREF_STATUS) && ! purple_status_is_available(purple_account_get_active_status(acct))) { @@ -43,23 +42,23 @@ buddy_typing_cb(PurpleAccount *acct, const char *name, void *data) { } if(purple_prefs_get_bool(PREF_BUDDIES) && - ! purple_find_buddy(acct, name)) { + ! purple_blist_find_buddy(acct, name)) { purple_debug_info("psychic", "not in blist, doing nothing\n"); return; } - if(FALSE == purple_privacy_check(acct, name)) { + if(FALSE == purple_account_privacy_check(acct, name)) { purple_debug_info("psychic", "user %s is blocked\n", name); return; } - gconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, acct); - if(! gconv) { + im = purple_conversations_find_im_with_account(name, acct); + if(! im) { purple_debug_info("psychic", "no previous conversation exists\n"); - gconv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, name); + im = purple_im_conversation_new(acct, name); if(purple_prefs_get_bool(PREF_RAISE)) { - purple_conversation_present(gconv); + purple_conversation_present(PURPLE_CONVERSATION(im)); } if(purple_prefs_get_bool(PREF_NOTICE)) { @@ -68,14 +67,14 @@ buddy_typing_cb(PurpleAccount *acct, const char *name, void *data) { translate it literally. If you can't find a fitting cultural reference in your language, consider translating something like this instead: "You feel a new message coming." */ - purple_conversation_write(gconv, NULL, + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, _("You feel a disturbance in the force..."), PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG | PURPLE_MESSAGE_ACTIVE_ONLY, time(NULL)); } /* Necessary because we may be creating a new conversation window. */ - purple_conv_im_set_typing_state(PURPLE_CONV_IM(gconv), PURPLE_TYPING); + purple_im_conversation_set_typing_state(im, PURPLE_IM_TYPING); } } diff --git a/libpurple/plugins/signals-test.c b/libpurple/plugins/signals-test.c index 840b260d11..19ba8afa00 100644 --- a/libpurple/plugins/signals-test.c +++ b/libpurple/plugins/signals-test.c @@ -24,7 +24,6 @@ #include <stdio.h> -#include "cipher.h" #include "connection.h" #include "conversation.h" #include "core.h" @@ -74,7 +73,7 @@ account_alias_changed(PurpleAccount *account, const char *old, gpointer data) { purple_debug_misc("signals test", "account-alias-changed (%s, %s, %s)\n", purple_account_get_username(account), - old, purple_account_get_alias(account)); + old, purple_account_get_private_alias(account)); } static int @@ -149,12 +148,12 @@ static void blist_node_added_cb(PurpleBlistNode *bnode, void *data) { const char *name; - if (PURPLE_BLIST_NODE_IS_GROUP(bnode)) + if (PURPLE_IS_GROUP(bnode)) name = purple_group_get_name(PURPLE_GROUP(bnode)); - else if (PURPLE_BLIST_NODE_IS_CONTACT(bnode)) + else if (PURPLE_IS_CONTACT(bnode)) /* Close enough */ name = purple_contact_get_alias(PURPLE_CONTACT(bnode)); - else if (PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + else if (PURPLE_IS_BUDDY(bnode)) name = purple_buddy_get_name(PURPLE_BUDDY(bnode)); else name = "(unknown)"; @@ -167,12 +166,12 @@ static void blist_node_removed_cb(PurpleBlistNode *bnode, void *data) { const char *name; - if (PURPLE_BLIST_NODE_IS_GROUP(bnode)) + if (PURPLE_IS_GROUP(bnode)) name = purple_group_get_name(PURPLE_GROUP(bnode)); - else if (PURPLE_BLIST_NODE_IS_CONTACT(bnode)) + else if (PURPLE_IS_CONTACT(bnode)) /* Close enough */ name = purple_contact_get_alias(PURPLE_CONTACT(bnode)); - else if (PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + else if (PURPLE_IS_BUDDY(bnode)) name = purple_buddy_get_name(PURPLE_BUDDY(bnode)); else name = "(unknown)"; @@ -184,62 +183,54 @@ blist_node_removed_cb(PurpleBlistNode *bnode, void *data) static void blist_node_aliased(PurpleBlistNode *node, const char *old_alias) { - PurpleContact *p = (PurpleContact *)node; - PurpleBuddy *b = (PurpleBuddy *)node; - PurpleChat *c = (PurpleChat *)node; - PurpleGroup *g = (PurpleGroup *)node; + PurpleContact *p = PURPLE_CONTACT(node); + PurpleBuddy *b = PURPLE_BUDDY(node); + PurpleChat *c = PURPLE_CHAT(node); + PurpleGroup *g = PURPLE_GROUP(node); - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if (PURPLE_IS_CONTACT(node)) { purple_debug_misc("signals test", "blist-node-aliased (Contact: %s, %s)\n", purple_contact_get_alias(p), old_alias); - } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + } else if (PURPLE_IS_BUDDY(node)) { purple_debug_misc("signals test", "blist-node-aliased (Buddy: %s, %s)\n", purple_buddy_get_name(b), old_alias); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { purple_debug_misc("signals test", "blist-node-aliased (Chat: %s, %s)\n", purple_chat_get_name(c), old_alias); - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { purple_debug_misc("signals test", "blist-node-aliased (Group: %s, %s)\n", purple_group_get_name(g), old_alias); - } else { - purple_debug_misc("signals test", - "blist-node-aliased (UNKNOWN: %d, %s)\n", - purple_blist_node_get_type(node), old_alias); } } static void blist_node_extended_menu_cb(PurpleBlistNode *node, void *data) { - PurpleContact *p = (PurpleContact *)node; - PurpleBuddy *b = (PurpleBuddy *)node; - PurpleChat *c = (PurpleChat *)node; - PurpleGroup *g = (PurpleGroup *)node; + PurpleContact *p = PURPLE_CONTACT(node); + PurpleBuddy *b = PURPLE_BUDDY(node); + PurpleChat *c = PURPLE_CHAT(node); + PurpleGroup *g = PURPLE_GROUP(node); - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if (PURPLE_IS_CONTACT(node)) { purple_debug_misc("signals test", "blist-node-extended-menu (Contact: %s)\n", purple_contact_get_alias(p)); - } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + } else if (PURPLE_IS_BUDDY(node)) { purple_debug_misc("signals test", "blist-node-extended-menu (Buddy: %s)\n", purple_buddy_get_name(b)); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { purple_debug_misc("signals test", "blist-node-extended-menu (Chat: %s)\n", purple_chat_get_name(c)); - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { purple_debug_misc("signals test", "blist-node-extended-menu (Group: %s)\n", purple_group_get_name(g)); - } else { - purple_debug_misc("signals test", - "blist-node-extended-menu (UNKNOWN: %d)\n", - purple_blist_node_get_type(node)); } } @@ -429,46 +420,48 @@ buddy_typing_stopped_cb(PurpleAccount *account, const char *name, void *data) } static gboolean -chat_buddy_joining_cb(PurpleConversation *conv, const char *user, - PurpleConvChatBuddyFlags flags, void *data) +chat_user_joining_cb(PurpleConversation *conv, const char *user, + PurpleChatUserFlags flags, void *data) { - purple_debug_misc("signals test", "chat-buddy-joining (%s, %s, %d)\n", + purple_debug_misc("signals test", "chat-user-joining (%s, %s, %d)\n", purple_conversation_get_name(conv), user, flags); return FALSE; } static void -chat_buddy_joined_cb(PurpleConversation *conv, const char *user, - PurpleConvChatBuddyFlags flags, gboolean new_arrival, void *data) +chat_user_joined_cb(PurpleConversation *conv, const char *user, + PurpleChatUserFlags flags, gboolean new_arrival, void *data) { - purple_debug_misc("signals test", "chat-buddy-joined (%s, %s, %d, %d)\n", + purple_debug_misc("signals test", "chat-user-joined (%s, %s, %d, %d)\n", purple_conversation_get_name(conv), user, flags, new_arrival); } static void -chat_buddy_flags_cb(PurpleConversation *conv, const char *user, - PurpleConvChatBuddyFlags oldflags, PurpleConvChatBuddyFlags newflags, void *data) +chat_user_flags_cb(PurpleChatUser *cb, PurpleChatUserFlags oldflags, + PurpleChatUserFlags newflags, void *data) { - purple_debug_misc("signals test", "chat-buddy-flags (%s, %s, %d, %d)\n", - purple_conversation_get_name(conv), user, oldflags, newflags); + purple_debug_misc("signals test", "chat-user-flags (%s, %s, %d, %d)\n", + purple_conversation_get_name(PURPLE_CONVERSATION( + purple_chat_user_get_chat(cb))), + purple_chat_user_get_name(cb), oldflags, newflags); } static gboolean -chat_buddy_leaving_cb(PurpleConversation *conv, const char *user, +chat_user_leaving_cb(PurpleConversation *conv, const char *user, const char *reason, void *data) { - purple_debug_misc("signals test", "chat-buddy-leaving (%s, %s, %s)\n", + purple_debug_misc("signals test", "chat-user-leaving (%s, %s, %s)\n", purple_conversation_get_name(conv), user, reason); return FALSE; } static void -chat_buddy_left_cb(PurpleConversation *conv, const char *user, +chat_user_left_cb(PurpleConversation *conv, const char *user, const char *reason, void *data) { - purple_debug_misc("signals test", "chat-buddy-left (%s, %s, %s)\n", + purple_debug_misc("signals test", "chat-user-left (%s, %s, %s)\n", purple_conversation_get_name(conv), user, reason); } @@ -524,21 +517,6 @@ chat_topic_changed_cb(PurpleConversation *conv, const char *who, (who) ? who : "unknown"); } /************************************************************************** - * Ciphers signal callbacks - **************************************************************************/ -static void -cipher_added_cb(PurpleCipher *cipher, void *data) { - purple_debug_misc("signals test", "cipher %s added\n", - purple_cipher_get_name(cipher)); -} - -static void -cipher_removed_cb(PurpleCipher *cipher, void *data) { - purple_debug_misc("signals test", "cipher %s removed\n", - purple_cipher_get_name(cipher)); -} - -/************************************************************************** * Core signal callbacks **************************************************************************/ static void @@ -719,7 +697,6 @@ plugin_load(PurplePlugin *plugin) void *conn_handle = purple_connections_get_handle(); void *conv_handle = purple_conversations_get_handle(); void *accounts_handle = purple_accounts_get_handle(); - void *ciphers_handle = purple_ciphers_get_handle(); void *ft_handle = purple_xfers_get_handle(); void *sound_handle = purple_sounds_get_handle(); void *notify_handle = purple_notify_get_handle(); @@ -808,16 +785,16 @@ plugin_load(PurplePlugin *plugin) plugin, PURPLE_CALLBACK(buddy_typing_cb), NULL); purple_signal_connect(conv_handle, "buddy-typing-stopped", plugin, PURPLE_CALLBACK(buddy_typing_stopped_cb), NULL); - purple_signal_connect(conv_handle, "chat-buddy-joining", - plugin, PURPLE_CALLBACK(chat_buddy_joining_cb), NULL); - purple_signal_connect(conv_handle, "chat-buddy-joined", - plugin, PURPLE_CALLBACK(chat_buddy_joined_cb), NULL); - purple_signal_connect(conv_handle, "chat-buddy-flags", - plugin, PURPLE_CALLBACK(chat_buddy_flags_cb), NULL); - purple_signal_connect(conv_handle, "chat-buddy-leaving", - plugin, PURPLE_CALLBACK(chat_buddy_leaving_cb), NULL); - purple_signal_connect(conv_handle, "chat-buddy-left", - plugin, PURPLE_CALLBACK(chat_buddy_left_cb), NULL); + purple_signal_connect(conv_handle, "chat-user-joining", + plugin, PURPLE_CALLBACK(chat_user_joining_cb), NULL); + purple_signal_connect(conv_handle, "chat-user-joined", + plugin, PURPLE_CALLBACK(chat_user_joined_cb), NULL); + purple_signal_connect(conv_handle, "chat-user-flags", + plugin, PURPLE_CALLBACK(chat_user_flags_cb), NULL); + purple_signal_connect(conv_handle, "chat-user-leaving", + plugin, PURPLE_CALLBACK(chat_user_leaving_cb), NULL); + purple_signal_connect(conv_handle, "chat-user-left", + plugin, PURPLE_CALLBACK(chat_user_left_cb), NULL); purple_signal_connect(conv_handle, "chat-inviting-user", plugin, PURPLE_CALLBACK(chat_inviting_user_cb), NULL); purple_signal_connect(conv_handle, "chat-invited-user", @@ -831,12 +808,6 @@ plugin_load(PurplePlugin *plugin) purple_signal_connect(conv_handle, "chat-topic-changed", plugin, PURPLE_CALLBACK(chat_topic_changed_cb), NULL); - /* Ciphers signals */ - purple_signal_connect(ciphers_handle, "cipher-added", - plugin, PURPLE_CALLBACK(cipher_added_cb), NULL); - purple_signal_connect(ciphers_handle, "cipher-removed", - plugin, PURPLE_CALLBACK(cipher_removed_cb), NULL); - /* Core signals */ purple_signal_connect(core_handle, "quitting", plugin, PURPLE_CALLBACK(quitting_cb), NULL); diff --git a/libpurple/plugins/statenotify.c b/libpurple/plugins/statenotify.c index ca74854e90..92ead65679 100644 --- a/libpurple/plugins/statenotify.c +++ b/libpurple/plugins/statenotify.c @@ -1,6 +1,6 @@ #include "internal.h" -#include "blist.h" +#include "buddylist.h" #include "conversation.h" #include "debug.h" #include "signals.h" @@ -16,7 +16,7 @@ static void write_status(PurpleBuddy *buddy, const char *message) { PurpleAccount *account = NULL; - PurpleConversation *conv; + PurpleIMConversation *im; const char *who; char buf[256]; char *escaped; @@ -25,15 +25,13 @@ write_status(PurpleBuddy *buddy, const char *message) account = purple_buddy_get_account(buddy); buddy_name = purple_buddy_get_name(buddy); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - buddy_name, account); + im = purple_conversations_find_im_with_account(buddy_name, account); - if (conv == NULL) + if (im == NULL) return; - g_return_if_fail(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM); /* Prevent duplicate notifications for buddies in multiple groups */ - if (buddy != purple_find_buddy(account, buddy_name)) + if (buddy != purple_blist_find_buddy(account, buddy_name)) return; who = purple_buddy_get_alias(buddy); @@ -42,7 +40,9 @@ write_status(PurpleBuddy *buddy, const char *message) g_snprintf(buf, sizeof(buf), message, escaped); g_free(escaped); - purple_conv_im_write(PURPLE_CONV_IM(conv), NULL, buf, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_ACTIVE_ONLY | PURPLE_MESSAGE_NO_LINKIFY, time(NULL)); + purple_conversation_write_message(PURPLE_CONVERSATION(im), NULL, buf, + PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_ACTIVE_ONLY | PURPLE_MESSAGE_NO_LINKIFY, + time(NULL)); } static void diff --git a/libpurple/plugins/tcl/tcl_cmds.c b/libpurple/plugins/tcl/tcl_cmds.c index 04ed4a3b7c..4a95b4883e 100644 --- a/libpurple/plugins/tcl/tcl_cmds.c +++ b/libpurple/plugins/tcl/tcl_cmds.c @@ -29,10 +29,11 @@ #include "account.h" #include "server.h" #include "notify.h" -#include "blist.h" +#include "buddylist.h" #include "savedstatuses.h" #include "debug.h" #include "prefs.h" +#include "presence.h" #include "core.h" #include "tcl_purple.h" @@ -70,7 +71,7 @@ static PurpleConversation *tcl_validate_conversation(Tcl_Obj *obj, Tcl_Interp *i if (convo == NULL) return NULL; - for (cur = purple_get_conversations(); cur != NULL; cur = g_list_next(cur)) { + for (cur = purple_conversations_get_all(); cur != NULL; cur = g_list_next(cur)) { if (convo == cur->data) return convo; } @@ -118,7 +119,7 @@ int tcl_cmd_account(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CO PurpleAccount *account; PurpleStatus *status; PurpleStatusType *status_type; - PurpleValue *value; + GValue *value; char *attr_id; int error; int b, i; @@ -139,7 +140,7 @@ int tcl_cmd_account(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CO } if ((account = tcl_validate_account(objv[2], interp)) == NULL) return TCL_ERROR; - alias = purple_account_get_alias(account); + alias = purple_account_get_private_alias(account); Tcl_SetObjResult(interp, Tcl_NewStringObj(alias ? (char *)alias : "", -1)); break; case CMD_ACCOUNT_CONNECT: @@ -292,27 +293,27 @@ int tcl_cmd_account(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CO Tcl_SetObjResult(interp, Tcl_NewStringObj("invalid attribute for account", -1)); return TCL_ERROR; } - switch (purple_value_get_type(value)) { - case PURPLE_TYPE_BOOLEAN: + switch (G_VALUE_TYPE(value)) { + case G_TYPE_BOOLEAN: error = Tcl_GetBooleanFromObj(interp, objv[i + 1], &b); if (error != TCL_OK) return error; l = g_list_append(l, attr_id); l = g_list_append(l, GINT_TO_POINTER(b)); break; - case PURPLE_TYPE_INT: + case G_TYPE_INT: error = Tcl_GetIntFromObj(interp, objv[i + 1], &b); if (error != TCL_OK) return error; l = g_list_append(l, attr_id); l = g_list_append(l, GINT_TO_POINTER(b)); break; - case PURPLE_TYPE_STRING: + case G_TYPE_STRING: l = g_list_append(l, attr_id); l = g_list_append(l, Tcl_GetString(objv[i + 1])); break; default: - Tcl_SetObjResult(interp, Tcl_NewStringObj("unknown PurpleValue type", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj("unknown GValue type", -1)); return TCL_ERROR; } } @@ -401,7 +402,7 @@ static PurpleBlistNode *tcl_list_to_buddy(Tcl_Interp *interp, int count, Tcl_Obj return NULL; if (!strcmp(type, "buddy")) { - node = PURPLE_BLIST_NODE(purple_find_buddy(account, name)); + node = PURPLE_BLIST_NODE(purple_blist_find_buddy(account, name)); } else if (!strcmp(type, "group")) { node = PURPLE_BLIST_NODE(purple_blist_find_chat(account, name)); } @@ -414,7 +415,6 @@ int tcl_cmd_buddy(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONS Tcl_Obj *list, *tclgroup, *tclgrouplist, *tclcontact, *tclcontactlist, *tclbud, **elems, *result; const char *cmds[] = { "alias", "handle", "info", "list", NULL }; enum { CMD_BUDDY_ALIAS, CMD_BUDDY_HANDLE, CMD_BUDDY_INFO, CMD_BUDDY_LIST } cmd; - PurpleBlistNodeType type; PurpleBlistNode *node, *gnode, *bnode; PurpleAccount *account; PurpleBuddy *bud; @@ -438,13 +438,12 @@ int tcl_cmd_buddy(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONS return error; if ((node = tcl_list_to_buddy(interp, count, elems)) == NULL) return TCL_ERROR; - type = purple_blist_node_get_type(node); - if (type == PURPLE_BLIST_CHAT_NODE) + if (PURPLE_IS_CHAT(node)) Tcl_SetObjResult(interp, - Tcl_NewStringObj(purple_chat_get_name((PurpleChat *)node), -1)); - else if (type == PURPLE_BLIST_BUDDY_NODE) + Tcl_NewStringObj(purple_chat_get_name(PURPLE_CHAT(node)), -1)); + else if (PURPLE_IS_BUDDY(node)) Tcl_SetObjResult(interp, - Tcl_NewStringObj((char *)purple_buddy_get_alias((PurpleBuddy *)node), -1)); + Tcl_NewStringObj((char *)purple_buddy_get_alias(PURPLE_BUDDY(node)), -1)); return TCL_OK; break; case CMD_BUDDY_HANDLE: @@ -499,14 +498,12 @@ int tcl_cmd_buddy(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONS tclgroup = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(interp, tclgroup, Tcl_NewStringObj("group", -1)); Tcl_ListObjAppendElement(interp, tclgroup, - Tcl_NewStringObj(purple_group_get_name((PurpleGroup *)gnode), -1)); + Tcl_NewStringObj(purple_group_get_name(PURPLE_GROUP(gnode)), -1)); tclgrouplist = Tcl_NewListObj(0, NULL); for (node = purple_blist_node_get_first_child(gnode); node != NULL; node = purple_blist_node_get_sibling_next(node)) { PurpleAccount *account; - type = purple_blist_node_get_type(node); - switch (type) { - case PURPLE_BLIST_CONTACT_NODE: + if (PURPLE_IS_CONTACT(node)) { tclcontact = Tcl_NewListObj(0, NULL); Tcl_IncrRefCount(tclcontact); Tcl_ListObjAppendElement(interp, tclcontact, Tcl_NewStringObj("contact", -1)); @@ -514,9 +511,9 @@ int tcl_cmd_buddy(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONS Tcl_IncrRefCount(tclcontactlist); count = 0; for (bnode = purple_blist_node_get_first_child(node); bnode != NULL; bnode = purple_blist_node_get_sibling_next(bnode)) { - if (purple_blist_node_get_type(bnode) != PURPLE_BLIST_BUDDY_NODE) + if (!PURPLE_IS_BUDDY(bnode)) continue; - bud = (PurpleBuddy *)bnode; + bud = PURPLE_BUDDY(bnode); account = purple_buddy_get_account(bud); if (!all && !purple_account_is_connected(account)) continue; @@ -533,9 +530,8 @@ int tcl_cmd_buddy(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONS } Tcl_DecrRefCount(tclcontact); Tcl_DecrRefCount(tclcontactlist); - break; - case PURPLE_BLIST_CHAT_NODE: - cnode = (PurpleChat *)node; + } else if (PURPLE_IS_CHAT(node)) { + cnode = PURPLE_CHAT(node); account = purple_chat_get_account(cnode); if (!all && !purple_account_is_connected(account)) continue; @@ -544,9 +540,8 @@ int tcl_cmd_buddy(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONS Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj(purple_chat_get_name(cnode), -1)); Tcl_ListObjAppendElement(interp, tclbud, purple_tcl_ref_new(PurpleTclRefAccount, account)); Tcl_ListObjAppendElement(interp, tclgrouplist, tclbud); - break; - default: - purple_debug(PURPLE_DEBUG_WARNING, "tcl", "Unexpected buddy type %d", type); + } else { + purple_debug(PURPLE_DEBUG_WARNING, "tcl", "Unexpected buddy type %s", G_OBJECT_TYPE_NAME(node)); continue; } } @@ -748,13 +743,13 @@ int tcl_cmd_connection(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj if ((gc = tcl_validate_gc(objv[2], interp)) == NULL) return TCL_ERROR; switch (purple_connection_get_state(gc)) { - case PURPLE_DISCONNECTED: + case PURPLE_CONNECTION_DISCONNECTED: Tcl_SetObjResult(interp, Tcl_NewStringObj("disconnected", -1)); break; - case PURPLE_CONNECTED: + case PURPLE_CONNECTION_CONNECTED: Tcl_SetObjResult(interp, Tcl_NewStringObj("connected", -1)); break; - case PURPLE_CONNECTING: + case PURPLE_CONNECTION_CONNECTING: Tcl_SetObjResult(interp, Tcl_NewStringObj("connecting", -1)); break; } @@ -775,7 +770,7 @@ int tcl_cmd_conversation(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Ob enum { CMD_CONV_NEW_CHAT, CMD_CONV_NEW_IM } newopt; PurpleConversation *convo; PurpleAccount *account; - PurpleConversationType type; + gboolean is_chat = FALSE; GList *cur; char *opt, *from, *what; int error, argsused, flags = 0; @@ -797,8 +792,7 @@ int tcl_cmd_conversation(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Ob account = NULL; if ((account = tcl_validate_account(objv[2], interp)) == NULL) return TCL_ERROR; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, - Tcl_GetString(objv[3]), + convo = purple_conversations_find_with_account(Tcl_GetString(objv[3]), account); Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefConversation, convo)); break; @@ -813,7 +807,7 @@ int tcl_cmd_conversation(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Ob break; case CMD_CONV_LIST: list = Tcl_NewListObj(0, NULL); - for (cur = purple_get_conversations(); cur != NULL; cur = g_list_next(cur)) { + for (cur = purple_conversations_get_all(); cur != NULL; cur = g_list_next(cur)) { elem = purple_tcl_ref_new(PurpleTclRefConversation, cur->data); Tcl_ListObjAppendElement(interp, list, elem); } @@ -825,7 +819,7 @@ int tcl_cmd_conversation(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Ob return TCL_ERROR; } argsused = 2; - type = PURPLE_CONV_TYPE_IM; + is_chat = FALSE; while (argsused < objc) { opt = Tcl_GetString(objv[argsused]); if (*opt == '-') { @@ -835,10 +829,10 @@ int tcl_cmd_conversation(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Ob argsused++; switch (newopt) { case CMD_CONV_NEW_CHAT: - type = PURPLE_CONV_TYPE_CHAT; + is_chat = TRUE; break; case CMD_CONV_NEW_IM: - type = PURPLE_CONV_TYPE_IM; + is_chat = FALSE; break; } } else { @@ -851,7 +845,10 @@ int tcl_cmd_conversation(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Ob } if ((account = tcl_validate_account(objv[argsused++], interp)) == NULL) return TCL_ERROR; - convo = purple_conversation_new(type, account, Tcl_GetString(objv[argsused])); + if (is_chat) + convo = PURPLE_CONVERSATION(purple_chat_conversation_new(account, Tcl_GetString(objv[argsused]))); + else + convo = PURPLE_CONVERSATION(purple_im_conversation_new(account, Tcl_GetString(objv[argsused]))); Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefConversation, convo)); break; case CMD_CONV_WRITE: @@ -877,11 +874,7 @@ int tcl_cmd_conversation(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Ob flags = PURPLE_MESSAGE_SYSTEM; break; } - if (purple_conversation_get_type(convo) == PURPLE_CONV_TYPE_CHAT) - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), from, what, flags, time(NULL)); - else - purple_conv_im_write(PURPLE_CONV_IM(convo), from, what, flags, time(NULL)); - break; + purple_conversation_write_message(convo, from, what, flags, time(NULL)); case CMD_CONV_NAME: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "conversation"); @@ -912,10 +905,7 @@ int tcl_cmd_conversation(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Ob if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL) return TCL_ERROR; what = Tcl_GetString(objv[3]); - if (purple_conversation_get_type(convo) == PURPLE_CONV_TYPE_CHAT) - purple_conv_chat_send(PURPLE_CONV_CHAT(convo), what); - else - purple_conv_im_send(PURPLE_CONV_IM(convo), what); + purple_conversation_send(convo, what); break; } @@ -1179,12 +1169,11 @@ int tcl_cmd_prefs(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONS int tcl_cmd_presence(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { const char *cmds[] = { "account", "active_status", "available", - "chat_user", "context", "conversation", "idle", - "login", "online", "status", "statuses", NULL }; + "idle", "type", "login", "online", "status", + "statuses", NULL }; enum { CMD_PRESENCE_ACCOUNT, CMD_PRESENCE_ACTIVE_STATUS, - CMD_PRESENCE_AVAILABLE, CMD_PRESENCE_CHAT_USER, - CMD_PRESENCE_CONTEXT, CMD_PRESENCE_CONVERSATION, - CMD_PRESENCE_IDLE, CMD_PRESENCE_LOGIN, CMD_PRESENCE_ONLINE, + CMD_PRESENCE_AVAILABLE, CMD_PRESENCE_IDLE, CMD_PRESENCE_TYPE, + CMD_PRESENCE_LOGIN, CMD_PRESENCE_ONLINE, CMD_PRESENCE_STATUS, CMD_PRESENCE_STATUSES } cmd; Tcl_Obj *result; Tcl_Obj *list, *elem; @@ -1209,7 +1198,7 @@ int tcl_cmd_presence(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *C if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefAccount, - purple_presence_get_account(presence))); + purple_account_presence_get_account(PURPLE_ACCOUNT_PRESENCE(presence)))); break; case CMD_PRESENCE_ACTIVE_STATUS: if (objc != 3 && objc != 4 && objc != 5) { @@ -1260,47 +1249,17 @@ int tcl_cmd_presence(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *C Tcl_SetObjResult(interp, Tcl_NewBooleanObj(purple_presence_is_available(presence))); break; - case CMD_PRESENCE_CHAT_USER: - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "presence"); - return TCL_ERROR; - } - if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL) - return TCL_ERROR; - Tcl_SetObjResult(interp, - Tcl_NewStringObj(purple_presence_get_chat_user(presence), -1)); - break; - case CMD_PRESENCE_CONTEXT: + case CMD_PRESENCE_TYPE: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "presence"); return TCL_ERROR; } if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL) return TCL_ERROR; - switch (purple_presence_get_context(presence)) { - case PURPLE_PRESENCE_CONTEXT_UNSET: - Tcl_SetObjResult(interp, Tcl_NewStringObj("unset", -1)); - break; - case PURPLE_PRESENCE_CONTEXT_ACCOUNT: + if (PURPLE_IS_ACCOUNT_PRESENCE(presence)) Tcl_SetObjResult(interp, Tcl_NewStringObj("account", -1)); - break; - case PURPLE_PRESENCE_CONTEXT_CONV: - Tcl_SetObjResult(interp, Tcl_NewStringObj("conversation", -1)); - break; - case PURPLE_PRESENCE_CONTEXT_BUDDY: + else if (PURPLE_IS_BUDDY_PRESENCE(presence)) Tcl_SetObjResult(interp, Tcl_NewStringObj("buddy", -1)); - break; - } - break; - case CMD_PRESENCE_CONVERSATION: - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "presence"); - return TCL_ERROR; - } - if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL) - return TCL_ERROR; - Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefConversation, - purple_presence_get_conversation(presence))); break; case CMD_PRESENCE_IDLE: if (objc < 3 || objc > 5) { @@ -1512,7 +1471,7 @@ int tcl_cmd_signal(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CON int tcl_cmd_status(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { const char *cmds[] = { "attr", "type", NULL }; - enum { CMD_STATUS_ATTR, CMD_STATUS_TYPE } cmd; + enum { CMD_STATUS_ATTRIBUTE, CMD_STATUS_TYPE } cmd; PurpleStatus *status; PurpleStatusType *status_type; int error; @@ -1532,7 +1491,7 @@ int tcl_cmd_status(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CON return error; switch (cmd) { - case CMD_STATUS_ATTR: + case CMD_STATUS_ATTRIBUTE: # if (0) /* #if !(defined PURPLE_DISABLE_DEPRECATED) */ if (objc != 4 && objc != 5) { @@ -1589,7 +1548,7 @@ int tcl_cmd_status(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CON } if ((status = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatus)) == NULL) return TCL_ERROR; - status_type = purple_status_get_type(status); + status_type = purple_status_get_status_type(status); Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefStatusType, status_type)); break; @@ -1601,8 +1560,8 @@ int tcl_cmd_status(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CON int tcl_cmd_status_attr(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { const char *cmds[] = { "id", "name", NULL }; - enum { CMD_STATUS_ATTR_ID, CMD_STATUS_ATTR_NAME } cmd; - PurpleStatusAttr *attr; + enum { CMD_STATUS_ATTRIBUTE_ID, CMD_STATUS_ATTRIBUTE_NAME } cmd; + PurpleStatusAttribute *attr; int error; if (objc < 2) { @@ -1614,7 +1573,7 @@ int tcl_cmd_status_attr(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj return error; switch (cmd) { - case CMD_STATUS_ATTR_ID: + case CMD_STATUS_ATTRIBUTE_ID: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "attr"); return TCL_ERROR; @@ -1622,9 +1581,9 @@ int tcl_cmd_status_attr(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj if ((attr = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusAttr)) == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, - Tcl_NewStringObj(purple_status_attr_get_id(attr), -1)); + Tcl_NewStringObj(purple_status_attribute_get_id(attr), -1)); break; - case CMD_STATUS_ATTR_NAME: + case CMD_STATUS_ATTRIBUTE_NAME: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "attr"); return TCL_ERROR; @@ -1632,7 +1591,7 @@ int tcl_cmd_status_attr(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj if ((attr = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusAttr)) == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, - Tcl_NewStringObj(purple_status_attr_get_name(attr), -1)); + Tcl_NewStringObj(purple_status_attribute_get_name(attr), -1)); break; } diff --git a/libpurple/plugins/tcl/tcl_purple.h b/libpurple/plugins/tcl/tcl_purple.h index ad3092eaea..6662d11aee 100644 --- a/libpurple/plugins/tcl/tcl_purple.h +++ b/libpurple/plugins/tcl/tcl_purple.h @@ -28,7 +28,6 @@ #include "internal.h" #include "cmds.h" #include "plugin.h" -#include "value.h" #include "stringref.h" struct tcl_signal_handler { @@ -41,9 +40,9 @@ struct tcl_signal_handler { Tcl_Obj *args; Tcl_Obj *proc; - PurpleValue *returntype; + GType returntype; int nargs; - PurpleValue **argtypes; + GType *argtypes; }; struct tcl_cmd_handler { diff --git a/libpurple/plugins/tcl/tcl_signals.c b/libpurple/plugins/tcl/tcl_signals.c index fb81ea3d5c..56f658604c 100644 --- a/libpurple/plugins/tcl/tcl_signals.c +++ b/libpurple/plugins/tcl/tcl_signals.c @@ -29,7 +29,6 @@ #include "conversation.h" #include "signals.h" #include "debug.h" -#include "value.h" #include "core.h" static GList *tcl_callbacks; @@ -74,7 +73,7 @@ gboolean tcl_signal_connect(struct tcl_signal_handler *handler) { GString *proc; - purple_signal_get_values(handler->instance, + purple_signal_get_types(handler->instance, Tcl_GetString(handler->signal), &handler->returntype, &handler->nargs, &handler->argtypes); @@ -136,24 +135,22 @@ void tcl_signal_disconnect(void *instance, const char *signal, Tcl_Interp *inter tcl_callbacks = g_list_remove_all(tcl_callbacks, NULL); } -static PurpleStringref *ref_type(PurpleSubType type) +static PurpleStringref *ref_purple_type(GType type) { - switch (type) { - case PURPLE_SUBTYPE_ACCOUNT: + if (type == PURPLE_TYPE_ACCOUNT) return PurpleTclRefAccount; - case PURPLE_SUBTYPE_CONNECTION: + else if (type == PURPLE_TYPE_CONNECTION) return PurpleTclRefConnection; - case PURPLE_SUBTYPE_CONVERSATION: + else if (type == PURPLE_TYPE_CONVERSATION) return PurpleTclRefConversation; - case PURPLE_SUBTYPE_PLUGIN: + else if (type == PURPLE_TYPE_PLUGIN) return PurpleTclRefPlugin; - case PURPLE_SUBTYPE_STATUS: + else if (type == PURPLE_TYPE_STATUS) return PurpleTclRefStatus; - case PURPLE_SUBTYPE_XFER: + else if (type == PURPLE_TYPE_XFER) return PurpleTclRefXfer; - default: + else return NULL; - } } static void *tcl_signal_callback(va_list args, struct tcl_signal_handler *handler) @@ -179,58 +176,57 @@ static void *tcl_signal_callback(va_list args, struct tcl_signal_handler *handle Tcl_ListObjAppendElement(handler->interp, cmd, arg); for (i = 0; i < handler->nargs; i++) { +#if 0 if (purple_value_is_outgoing(handler->argtypes[i])) g_string_printf(name, "%s::arg%d", Tcl_GetString(handler->namespace), i); - - switch(purple_value_get_type(handler->argtypes[i])) { - case PURPLE_TYPE_UNKNOWN: /* What? I guess just pass the word ... */ - /* treat this as a pointer, but complain first */ - purple_debug(PURPLE_DEBUG_ERROR, "tcl", "unknown PurpleValue type %d\n", - purple_value_get_type(handler->argtypes[i])); - case PURPLE_TYPE_POINTER: - case PURPLE_TYPE_OBJECT: - case PURPLE_TYPE_BOXED: +#endif + switch(handler->argtypes[i]) { + case G_TYPE_POINTER: +#if 0 + case G_TYPE_OBJECT: + case G_TYPE_BOXED: /* These are all "pointer" types to us */ if (purple_value_is_outgoing(handler->argtypes[i])) purple_debug_error("tcl", "pointer types do not currently support outgoing arguments\n"); +#endif arg = purple_tcl_ref_new(PurpleTclRefPointer, va_arg(args, void *)); break; - case PURPLE_TYPE_BOOLEAN: + case G_TYPE_BOOLEAN: +#if 0 if (purple_value_is_outgoing(handler->argtypes[i])) { vals[i] = va_arg(args, gboolean *); Tcl_LinkVar(handler->interp, name->str, (char *)&vals[i], TCL_LINK_BOOLEAN); arg = Tcl_NewStringObj(name->str, -1); - } else { - arg = Tcl_NewBooleanObj(va_arg(args, gboolean)); - } + } else +#endif + arg = Tcl_NewBooleanObj(va_arg(args, gboolean)); break; - case PURPLE_TYPE_CHAR: - case PURPLE_TYPE_UCHAR: - case PURPLE_TYPE_SHORT: - case PURPLE_TYPE_USHORT: - case PURPLE_TYPE_INT: - case PURPLE_TYPE_UINT: - case PURPLE_TYPE_LONG: - case PURPLE_TYPE_ULONG: - case PURPLE_TYPE_ENUM: + case G_TYPE_CHAR: + case G_TYPE_UCHAR: + case G_TYPE_INT: + case G_TYPE_UINT: + case G_TYPE_LONG: + case G_TYPE_ULONG: /* I should really cast these individually to * preserve as much information as possible ... * but heh */ +#if 0 if (purple_value_is_outgoing(handler->argtypes[i])) { vals[i] = va_arg(args, int *); Tcl_LinkVar(handler->interp, name->str, vals[i], TCL_LINK_INT); arg = Tcl_NewStringObj(name->str, -1); - } else { - arg = Tcl_NewIntObj(va_arg(args, int)); - } + } else +#endif + arg = Tcl_NewIntObj(va_arg(args, int)); break; - case PURPLE_TYPE_INT64: - case PURPLE_TYPE_UINT64: + case G_TYPE_INT64: + case G_TYPE_UINT64: /* Tcl < 8.4 doesn't have wide ints, so we have ugly * ifdefs in here */ +#if 0 if (purple_value_is_outgoing(handler->argtypes[i])) { vals[i] = (void *)va_arg(args, gint64 *); #if (TCL_MAJOR_VERSION >= 8 && TCL_MINOR_VERSION >= 4) @@ -245,14 +241,15 @@ static void *tcl_signal_callback(va_list args, struct tcl_signal_handler *handle #endif /* Tcl >= 8.4 */ arg = Tcl_NewStringObj(name->str, -1); } else { - #if (TCL_MAJOR_VERSION >= 8 && TCL_MINOR_VERSION >= 4) - arg = Tcl_NewWideIntObj(va_arg(args, gint64)); - #else - arg = Tcl_NewIntObj((int)va_arg(args, int)); - #endif /* Tcl >= 8.4 */ - } +#endif + #if (TCL_MAJOR_VERSION >= 8 && TCL_MINOR_VERSION >= 4) + arg = Tcl_NewWideIntObj(va_arg(args, gint64)); + #else + arg = Tcl_NewIntObj((int)va_arg(args, int)); + #endif /* Tcl >= 8.4 */ break; - case PURPLE_TYPE_STRING: + case G_TYPE_STRING: +#if 0 if (purple_value_is_outgoing(handler->argtypes[i])) { strs[i] = va_arg(args, char **); if (strs[i] == NULL || *strs[i] == NULL) { @@ -266,70 +263,77 @@ static void *tcl_signal_callback(va_list args, struct tcl_signal_handler *handle Tcl_LinkVar(handler->interp, name->str, (char *)&vals[i], TCL_LINK_STRING); arg = Tcl_NewStringObj(name->str, -1); - } else { - arg = Tcl_NewStringObj(va_arg(args, char *), -1); - } + } else +#endif + arg = Tcl_NewStringObj(va_arg(args, char *), -1); break; - case PURPLE_TYPE_SUBTYPE: - switch (purple_value_get_subtype(handler->argtypes[i])) { - case PURPLE_SUBTYPE_UNKNOWN: - purple_debug(PURPLE_DEBUG_ERROR, "tcl", "subtype unknown\n"); - case PURPLE_SUBTYPE_ACCOUNT: - case PURPLE_SUBTYPE_CONNECTION: - case PURPLE_SUBTYPE_CONVERSATION: - case PURPLE_SUBTYPE_STATUS: - case PURPLE_SUBTYPE_PLUGIN: - case PURPLE_SUBTYPE_XFER: + default: + if (handler->argtypes[i] == PURPLE_TYPE_ACCOUNT || + handler->argtypes[i] == PURPLE_TYPE_CONNECTION || + handler->argtypes[i] == PURPLE_TYPE_CONVERSATION || + handler->argtypes[i] == PURPLE_TYPE_STATUS || + handler->argtypes[i] == PURPLE_TYPE_PLUGIN || + handler->argtypes[i] == PURPLE_TYPE_XFER ) + { +#if 0 if (purple_value_is_outgoing(handler->argtypes[i])) purple_debug_error("tcl", "pointer subtypes do not currently support outgoing arguments\n"); - arg = purple_tcl_ref_new(ref_type(purple_value_get_subtype(handler->argtypes[i])), va_arg(args, void *)); - break; - case PURPLE_SUBTYPE_BLIST: - case PURPLE_SUBTYPE_BLIST_BUDDY: - case PURPLE_SUBTYPE_BLIST_GROUP: - case PURPLE_SUBTYPE_BLIST_CHAT: +#endif + arg = purple_tcl_ref_new(ref_purple_type(handler->argtypes[i]), va_arg(args, void *)); + } + else + if (handler->argtypes[i] == PURPLE_TYPE_CONTACT || + handler->argtypes[i] == PURPLE_TYPE_BUDDY || + handler->argtypes[i] == PURPLE_TYPE_GROUP || + handler->argtypes[i] == PURPLE_TYPE_CHAT ) + { /* We're going to switch again for code-deduping */ +#if 0 if (purple_value_is_outgoing(handler->argtypes[i])) node = *va_arg(args, PurpleBlistNode **); else - node = va_arg(args, PurpleBlistNode *); - switch (purple_blist_node_get_type(node)) { - case PURPLE_BLIST_GROUP_NODE: +#endif + node = va_arg(args, PurpleBlistNode *); + + if (PURPLE_IS_GROUP(node)) { arg = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(handler->interp, arg, Tcl_NewStringObj("group", -1)); Tcl_ListObjAppendElement(handler->interp, arg, - Tcl_NewStringObj(purple_group_get_name((PurpleGroup *)node), -1)); - break; - case PURPLE_BLIST_CONTACT_NODE: + Tcl_NewStringObj(purple_group_get_name(PURPLE_GROUP(node)), -1)); + } else if (PURPLE_IS_CONTACT(node)) { /* g_string_printf(val, "contact {%s}", Contact Name? ); */ arg = Tcl_NewStringObj("contact", -1); - break; - case PURPLE_BLIST_BUDDY_NODE: + } else if (PURPLE_IS_BUDDY(node)) { arg = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(handler->interp, arg, Tcl_NewStringObj("buddy", -1)); Tcl_ListObjAppendElement(handler->interp, arg, - Tcl_NewStringObj(purple_buddy_get_name((PurpleBuddy *)node), -1)); + Tcl_NewStringObj(purple_buddy_get_name(PURPLE_BUDDY(node)), -1)); Tcl_ListObjAppendElement(handler->interp, arg, purple_tcl_ref_new(PurpleTclRefAccount, - purple_buddy_get_account((PurpleBuddy *)node))); - break; - case PURPLE_BLIST_CHAT_NODE: + purple_buddy_get_account(PURPLE_BUDDY(node)))); + } else if (PURPLE_IS_CHAT(node)) { arg = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(handler->interp, arg, Tcl_NewStringObj("chat", -1)); Tcl_ListObjAppendElement(handler->interp, arg, - Tcl_NewStringObj(purple_chat_get_name((PurpleChat *)node), -1)); + Tcl_NewStringObj(purple_chat_get_name(PURPLE_CHAT(node)), -1)); Tcl_ListObjAppendElement(handler->interp, arg, purple_tcl_ref_new(PurpleTclRefAccount, - purple_chat_get_account((PurpleChat *)node))); - break; - case PURPLE_BLIST_OTHER_NODE: - arg = Tcl_NewStringObj("other", -1); - break; + purple_chat_get_account(PURPLE_CHAT(node)))); } - break; + } + else if (G_TYPE_IS_ENUM(handler->argtypes[i])) + { + arg = Tcl_NewIntObj(va_arg(args, int)); + } + else + { + /* What? I guess just pass the word ... */ + /* treat this as a pointer, but complain first */ + purple_debug(PURPLE_DEBUG_ERROR, "tcl", "unknown GType %lu\n", + handler->argtypes[i]); } } Tcl_ListObjAppendElement(handler->interp, cmd, arg); @@ -343,7 +347,7 @@ static void *tcl_signal_callback(va_list args, struct tcl_signal_handler *handle result = Tcl_GetObjResult(handler->interp); /* handle return values -- strings and words only */ if (handler->returntype) { - if (purple_value_get_type(handler->returntype) == PURPLE_TYPE_STRING) { + if (handler->returntype == G_TYPE_STRING) { retval = (void *)g_strdup(Tcl_GetString(result)); } else { if (Tcl_GetIntFromObj(handler->interp, result, (int *)&retval) != TCL_OK) { @@ -359,14 +363,14 @@ static void *tcl_signal_callback(va_list args, struct tcl_signal_handler *handle for (i = 0; i < handler->nargs; i++) { g_string_printf(name, "%s::arg%d", Tcl_GetString(handler->namespace), i); +#if 0 if (purple_value_is_outgoing(handler->argtypes[i]) - && purple_value_get_type(handler->argtypes[i]) != PURPLE_TYPE_SUBTYPE) + && purple_value_get_type(handler->argtypes[i]) != G_TYPE_SUBTYPE) Tcl_UnlinkVar(handler->interp, name->str); - /* We basically only have to deal with strings on the * way out */ - switch (purple_value_get_type(handler->argtypes[i])) { - case PURPLE_TYPE_STRING: + switch (handler->argtypes[i]) { + case G_TYPE_STRING: if (purple_value_is_outgoing(handler->argtypes[i])) { if (vals[i] != NULL && *(char **)vals[i] != NULL) { g_free(*strs[i]); @@ -379,6 +383,7 @@ static void *tcl_signal_callback(va_list args, struct tcl_signal_handler *handle /* nothing */ ; } +#endif } g_string_free(name, TRUE); diff --git a/libpurple/pounce.c b/libpurple/pounce.c index 641ebb525f..ca9940c226 100644 --- a/libpurple/pounce.c +++ b/libpurple/pounce.c @@ -1126,18 +1126,18 @@ buddy_idle_changed_cb(PurpleBuddy *buddy, gboolean old_idle, gboolean idle) static void buddy_typing_cb(PurpleAccount *account, const char *name, void *data) { - PurpleConversation *conv; + PurpleIMConversation *im; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, account); - if (conv != NULL) + im = purple_conversations_find_im_with_account(name, account); + if (im != NULL) { - PurpleTypingState state; + PurpleIMTypingState state; PurplePounceEvent event; - state = purple_conv_im_get_typing_state(PURPLE_CONV_IM(conv)); - if (state == PURPLE_TYPED) + state = purple_im_conversation_get_typing_state(im); + if (state == PURPLE_IM_TYPED) event = PURPLE_POUNCE_TYPED; - else if (state == PURPLE_NOT_TYPING) + else if (state == PURPLE_IM_NOT_TYPING) event = PURPLE_POUNCE_TYPING_STOPPED; else event = PURPLE_POUNCE_TYPING; diff --git a/libpurple/presence.c b/libpurple/presence.c new file mode 100644 index 0000000000..4c36647ce7 --- /dev/null +++ b/libpurple/presence.c @@ -0,0 +1,996 @@ +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#include "internal.h" +#include "debug.h" +#include "dbus-maybe.h" +#include "presence.h" + +#define PURPLE_PRESENCE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_PRESENCE, PurplePresencePrivate)) + +/** @copydoc _PurplePresencePrivate */ +typedef struct _PurplePresencePrivate PurplePresencePrivate; + +#define PURPLE_ACCOUNT_PRESENCE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_ACCOUNT_PRESENCE, PurpleAccountPresencePrivate)) + +/** @copydoc _PurpleAccountPresencePrivate */ +typedef struct _PurpleAccountPresencePrivate PurpleAccountPresencePrivate; + +#define PURPLE_BUDDY_PRESENCE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_BUDDY_PRESENCE, PurpleBuddyPresencePrivate)) + +/** @copydoc _PurpleBuddyPresencePrivate */ +typedef struct _PurpleBuddyPresencePrivate PurpleBuddyPresencePrivate; + +/** Private data for a presence */ +struct _PurplePresencePrivate +{ + gboolean idle; + time_t idle_time; + time_t login_time; + + GList *statuses; + GHashTable *status_table; + + PurpleStatus *active_status; +}; + +/* Presence property enums */ +enum +{ + PRES_PROP_0, + PRES_PROP_IDLE, + PRES_PROP_IDLE_TIME, + PRES_PROP_LOGIN_TIME, + PRES_PROP_STATUSES, + PRES_PROP_ACTIVE_STATUS, + PRES_PROP_LAST +}; + +/** Private data for an account presence */ +struct _PurpleAccountPresencePrivate +{ + PurpleAccount *account; +}; + +/* Account presence property enums */ +enum +{ + ACPRES_PROP_0, + ACPRES_PROP_ACCOUNT, + ACPRES_PROP_LAST +}; + +/** Private data for a buddy presence */ +struct _PurpleBuddyPresencePrivate +{ + PurpleBuddy *buddy; +}; + +/* Buddy presence property enums */ +enum +{ + BUDPRES_PROP_0, + BUDPRES_PROP_BUDDY, + BUDPRES_PROP_LAST +}; + +static GObjectClass *parent_class; +static PurplePresenceClass *presence_class; + +int *_purple_get_primitive_scores(void); + +/************************************************************************** +* PurplePresence API +**************************************************************************/ + +void +purple_presence_set_status_active(PurplePresence *presence, const char *status_id, + gboolean active) +{ + PurpleStatus *status; + + g_return_if_fail(presence != NULL); + g_return_if_fail(status_id != NULL); + + status = purple_presence_get_status(presence, status_id); + + g_return_if_fail(status != NULL); + /* TODO: Should we do the following? */ + /* g_return_if_fail(active == status->active); */ + + if (purple_status_is_exclusive(status)) + { + if (!active) + { + purple_debug_warning("status", + "Attempted to set a non-independent status " + "(%s) inactive. Only independent statuses " + "can be specifically marked inactive.", + status_id); + return; + } + } + + purple_status_set_active(status, active); +} + +void +purple_presence_switch_status(PurplePresence *presence, const char *status_id) +{ + purple_presence_set_status_active(presence, status_id, TRUE); +} + +void +purple_presence_set_idle(PurplePresence *presence, gboolean idle, time_t idle_time) +{ + gboolean old_idle; + PurplePresencePrivate *priv = PURPLE_PRESENCE_GET_PRIVATE(presence); + PurplePresenceClass *klass = PURPLE_PRESENCE_GET_CLASS(presence); + + g_return_if_fail(priv != NULL); + + if (priv->idle == idle && priv->idle_time == idle_time) + return; + + old_idle = priv->idle; + priv->idle = idle; + priv->idle_time = (idle ? idle_time : 0); + + if (klass->update_idle) + klass->update_idle(presence, old_idle); +} + +void +purple_presence_set_login_time(PurplePresence *presence, time_t login_time) +{ + PurplePresencePrivate *priv = PURPLE_PRESENCE_GET_PRIVATE(presence); + + g_return_if_fail(priv != NULL); + + if (priv->login_time == login_time) + return; + + priv->login_time = login_time; +} + +GList * +purple_presence_get_statuses(const PurplePresence *presence) +{ + PurplePresencePrivate *priv = PURPLE_PRESENCE_GET_PRIVATE(presence); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->statuses; +} + +PurpleStatus * +purple_presence_get_status(const PurplePresence *presence, const char *status_id) +{ + PurpleStatus *status; + PurplePresencePrivate *priv = PURPLE_PRESENCE_GET_PRIVATE(presence); + GList *l = NULL; + + g_return_val_if_fail(priv != NULL, NULL); + g_return_val_if_fail(status_id != NULL, NULL); + + /* What's the purpose of this hash table? */ + status = (PurpleStatus *)g_hash_table_lookup(priv->status_table, + status_id); + + if (status == NULL) { + for (l = purple_presence_get_statuses(presence); + l != NULL && status == NULL; l = l->next) + { + PurpleStatus *temp_status = l->data; + + if (purple_strequal(status_id, purple_status_get_id(temp_status))) + status = temp_status; + } + + if (status != NULL) + g_hash_table_insert(priv->status_table, + g_strdup(purple_status_get_id(status)), status); + } + + return status; +} + +PurpleStatus * +purple_presence_get_active_status(const PurplePresence *presence) +{ + PurplePresencePrivate *priv = PURPLE_PRESENCE_GET_PRIVATE(presence); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->active_status; +} + +gboolean +purple_presence_is_available(const PurplePresence *presence) +{ + PurpleStatus *status; + + g_return_val_if_fail(presence != NULL, FALSE); + + status = purple_presence_get_active_status(presence); + + return ((status != NULL && purple_status_is_available(status)) && + !purple_presence_is_idle(presence)); +} + +gboolean +purple_presence_is_online(const PurplePresence *presence) +{ + PurpleStatus *status; + + g_return_val_if_fail(presence != NULL, FALSE); + + if ((status = purple_presence_get_active_status(presence)) == NULL) + return FALSE; + + return purple_status_is_online(status); +} + +gboolean +purple_presence_is_status_active(const PurplePresence *presence, + const char *status_id) +{ + PurpleStatus *status; + + g_return_val_if_fail(presence != NULL, FALSE); + g_return_val_if_fail(status_id != NULL, FALSE); + + status = purple_presence_get_status(presence, status_id); + + return (status != NULL && purple_status_is_active(status)); +} + +gboolean +purple_presence_is_status_primitive_active(const PurplePresence *presence, + PurpleStatusPrimitive primitive) +{ + GList *l; + + g_return_val_if_fail(presence != NULL, FALSE); + g_return_val_if_fail(primitive != PURPLE_STATUS_UNSET, FALSE); + + for (l = purple_presence_get_statuses(presence); + l != NULL; l = l->next) + { + PurpleStatus *temp_status = l->data; + PurpleStatusType *type = purple_status_get_status_type(temp_status); + + if (purple_status_type_get_primitive(type) == primitive && + purple_status_is_active(temp_status)) + return TRUE; + } + return FALSE; +} + +gboolean +purple_presence_is_idle(const PurplePresence *presence) +{ + PurplePresencePrivate *priv = PURPLE_PRESENCE_GET_PRIVATE(presence); + + g_return_val_if_fail(priv != NULL, FALSE); + + return purple_presence_is_online(presence) && priv->idle; +} + +time_t +purple_presence_get_idle_time(const PurplePresence *presence) +{ + PurplePresencePrivate *priv = PURPLE_PRESENCE_GET_PRIVATE(presence); + + g_return_val_if_fail(priv != NULL, 0); + + return priv->idle_time; +} + +time_t +purple_presence_get_login_time(const PurplePresence *presence) +{ + PurplePresencePrivate *priv = PURPLE_PRESENCE_GET_PRIVATE(presence); + + g_return_val_if_fail(priv != NULL, 0); + + return purple_presence_is_online(presence) ? priv->login_time : 0; +} + +/************************************************************************** + * GObject code for PurplePresence + **************************************************************************/ + +/* GObject Property names */ +#define PRES_PROP_IDLE_S "idle" +#define PRES_PROP_IDLE_TIME_S "idle-time" +#define PRES_PROP_LOGIN_TIME_S "login-time" +#define PRES_PROP_STATUSES_S "statuses" +#define PRES_PROP_ACTIVE_STATUS_S "active-status" + +/* Set method for GObject properties */ +static void +purple_presence_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurplePresence *presence = PURPLE_PRESENCE(obj); + PurplePresencePrivate *priv = PURPLE_PRESENCE_GET_PRIVATE(presence); + + switch (param_id) { + case PRES_PROP_IDLE: + purple_presence_set_idle(presence, g_value_get_boolean(value), 0); + break; + case PRES_PROP_IDLE_TIME: +#if SIZEOF_TIME_T == 4 + purple_presence_set_idle(presence, TRUE, g_value_get_int(value)); +#elif SIZEOF_TIME_T == 8 + purple_presence_set_idle(presence, TRUE, g_value_get_int64(value)); +#else +#error Unknown size of time_t +#endif + break; + case PRES_PROP_LOGIN_TIME: +#if SIZEOF_TIME_T == 4 + purple_presence_set_login_time(presence, g_value_get_int(value)); +#elif SIZEOF_TIME_T == 8 + purple_presence_set_login_time(presence, g_value_get_int64(value)); +#else +#error Unknown size of time_t +#endif + break; + case PRES_PROP_ACTIVE_STATUS: + priv->active_status = g_value_get_object(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_presence_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurplePresence *presence = PURPLE_PRESENCE(obj); + + switch (param_id) { + case PRES_PROP_IDLE: + g_value_set_boolean(value, purple_presence_is_idle(presence)); + break; + case PRES_PROP_IDLE_TIME: +#if SIZEOF_TIME_T == 4 + g_value_set_int(value, purple_presence_get_idle_time(presence)); +#elif SIZEOF_TIME_T == 8 + g_value_set_int64(value, purple_presence_get_idle_time(presence)); +#else +#error Unknown size of time_t +#endif + break; + case PRES_PROP_LOGIN_TIME: +#if SIZEOF_TIME_T == 4 + g_value_set_int(value, purple_presence_get_login_time(presence)); +#elif SIZEOF_TIME_T == 8 + g_value_set_int64(value, purple_presence_get_login_time(presence)); +#else +#error Unknown size of time_t +#endif + break; + case PRES_PROP_STATUSES: + g_value_set_pointer(value, purple_presence_get_statuses(presence)); + break; + case PRES_PROP_ACTIVE_STATUS: + g_value_set_object(value, purple_presence_get_active_status(presence)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* GObject initialization function */ +static void +purple_presence_init(GTypeInstance *instance, gpointer klass) +{ + PURPLE_DBUS_REGISTER_POINTER(PURPLE_PRESENCE(instance), PurplePresence); + + PURPLE_PRESENCE_GET_PRIVATE(instance)->status_table = + g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); +} + +/* GObject dispose function */ +static void +purple_presence_dispose(GObject *object) +{ + PURPLE_DBUS_UNREGISTER_POINTER(object); + + g_list_foreach(PURPLE_PRESENCE_GET_PRIVATE(object)->statuses, + (GFunc)g_object_unref, NULL); + + parent_class->dispose(object); +} + +/* GObject finalize function */ +static void +purple_presence_finalize(GObject *object) +{ + PurplePresencePrivate *priv = PURPLE_PRESENCE_GET_PRIVATE(object); + + g_list_free(priv->statuses); + g_hash_table_destroy(priv->status_table); + + parent_class->finalize(object); +} + +/* Class initializer function */ +static void purple_presence_class_init(PurplePresenceClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->dispose = purple_presence_dispose; + obj_class->finalize = purple_presence_finalize; + + /* Setup properties */ + obj_class->get_property = purple_presence_get_property; + obj_class->set_property = purple_presence_set_property; + + g_object_class_install_property(obj_class, PRES_PROP_IDLE, + g_param_spec_boolean(PRES_PROP_IDLE_S, _("Idle"), + _("Whether the presence is in idle state."), FALSE, + G_PARAM_READWRITE) + ); + + + g_object_class_install_property(obj_class, PRES_PROP_IDLE_TIME, +#if SIZEOF_TIME_T == 4 + g_param_spec_int +#elif SIZEOF_TIME_T == 8 + g_param_spec_int64 +#else +#error Unknown size of time_t +#endif + (PRES_PROP_IDLE_TIME_S, _("Idle time"), + _("The idle time of the presence"), +#if SIZEOF_TIME_T == 4 + G_MININT, G_MAXINT, 0, +#elif SIZEOF_TIME_T == 8 + G_MININT64, G_MAXINT64, 0, +#else +#error Unknown size of time_t +#endif + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PRES_PROP_LOGIN_TIME, +#if SIZEOF_TIME_T == 4 + g_param_spec_int +#elif SIZEOF_TIME_T == 8 + g_param_spec_int64 +#else +#error Unknown size of time_t +#endif + (PRES_PROP_LOGIN_TIME_S, _("Login time"), + _("The login time of the presence."), +#if SIZEOF_TIME_T == 4 + G_MININT, G_MAXINT, 0, +#elif SIZEOF_TIME_T == 8 + G_MININT64, G_MAXINT64, 0, +#else +#error Unknown size of time_t +#endif + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PRES_PROP_STATUSES, + g_param_spec_pointer(PRES_PROP_STATUSES_S, _("Statuses"), + _("The list of statuses in the presence."), + G_PARAM_READABLE) + ); + + g_object_class_install_property(obj_class, PRES_PROP_ACTIVE_STATUS, + g_param_spec_object(PRES_PROP_ACTIVE_STATUS_S, _("Active status"), + _("The active status for the presence."), PURPLE_TYPE_STATUS, + G_PARAM_READWRITE) + ); + + g_type_class_add_private(klass, sizeof(PurplePresencePrivate)); +} + +GType +purple_presence_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurplePresenceClass), + NULL, + NULL, + (GClassInitFunc)purple_presence_class_init, + NULL, + NULL, + sizeof(PurplePresence), + 0, + (GInstanceInitFunc)purple_presence_init, + NULL, + }; + + type = g_type_register_static(G_TYPE_OBJECT, "PurplePresence", + &info, G_TYPE_FLAG_ABSTRACT); + } + + return type; +} + +/************************************************************************** +* PurpleAccountPresence API +**************************************************************************/ +static void +purple_account_presence_update_idle(PurplePresence *presence, gboolean old_idle) +{ + PurpleAccount *account; + PurpleConnection *gc = NULL; + PurplePlugin *prpl = NULL; + PurplePluginProtocolInfo *prpl_info = NULL; + gboolean idle = purple_presence_is_idle(presence); + time_t idle_time = purple_presence_get_idle_time(presence); + time_t current_time = time(NULL); + + account = purple_account_presence_get_account(PURPLE_ACCOUNT_PRESENCE(presence)); + + if (purple_prefs_get_bool("/purple/logging/log_system")) + { + PurpleLog *log = purple_account_get_log(account, FALSE); + + if (log != NULL) + { + char *msg, *tmp; + + if (idle) + tmp = g_strdup_printf(_("+++ %s became idle"), purple_account_get_username(account)); + else + tmp = g_strdup_printf(_("+++ %s became unidle"), purple_account_get_username(account)); + + msg = g_markup_escape_text(tmp, -1); + g_free(tmp); + purple_log_write(log, PURPLE_MESSAGE_SYSTEM, + purple_account_get_username(account), + (idle ? idle_time : current_time), msg); + g_free(msg); + } + } + + gc = purple_account_get_connection(account); + + if(gc) + prpl = purple_connection_get_prpl(gc); + + if(PURPLE_CONNECTION_IS_CONNECTED(gc) && prpl != NULL) + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + + if (prpl_info && prpl_info->set_idle) + prpl_info->set_idle(gc, (idle ? (current_time - idle_time) : 0)); +} + +PurpleAccount * +purple_account_presence_get_account(const PurpleAccountPresence *presence) +{ + PurpleAccountPresencePrivate *priv = PURPLE_ACCOUNT_PRESENCE_GET_PRIVATE(presence); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->account; +} + +static int +purple_buddy_presence_compute_score(const PurpleBuddyPresence *buddy_presence) +{ + GList *l; + int score = 0; + PurplePresence *presence = PURPLE_PRESENCE(buddy_presence); + PurpleBuddy *b = purple_buddy_presence_get_buddy(buddy_presence); + int *primitive_scores = _purple_get_primitive_scores(); + int offline_score = purple_prefs_get_int("/purple/status/scores/offline_msg"); + int idle_score = purple_prefs_get_int("/purple/status/scores/idle"); + + for (l = purple_presence_get_statuses(presence); l != NULL; l = l->next) { + PurpleStatus *status = (PurpleStatus *)l->data; + PurpleStatusType *type = purple_status_get_status_type(status); + + if (purple_status_is_active(status)) { + score += primitive_scores[purple_status_type_get_primitive(type)]; + if (!purple_status_is_online(status)) { + if (b && purple_account_supports_offline_message(purple_buddy_get_account(b), b)) + score += offline_score; + } + } + } + score += purple_account_get_int(purple_buddy_get_account(b), "score", 0); + if (purple_presence_is_idle(presence)) + score += idle_score; + return score; +} + +gint +purple_buddy_presence_compare(const PurpleBuddyPresence *buddy_presence1, + const PurpleBuddyPresence *buddy_presence2) +{ + PurplePresence *presence1 = PURPLE_PRESENCE(buddy_presence1); + PurplePresence *presence2 = PURPLE_PRESENCE(buddy_presence2); + time_t idle_time_1, idle_time_2; + int score1 = 0, score2 = 0; + int idle_time_score = purple_prefs_get_int("/purple/status/scores/idle_time"); + + if (presence1 == presence2) + return 0; + else if (presence1 == NULL) + return 1; + else if (presence2 == NULL) + return -1; + + if (purple_presence_is_online(presence1) && + !purple_presence_is_online(presence2)) + return -1; + else if (purple_presence_is_online(presence2) && + !purple_presence_is_online(presence1)) + return 1; + + /* Compute the score of the first set of statuses. */ + score1 = purple_buddy_presence_compute_score(buddy_presence1); + + /* Compute the score of the second set of statuses. */ + score2 = purple_buddy_presence_compute_score(buddy_presence2); + + idle_time_1 = time(NULL) - purple_presence_get_idle_time(presence1); + idle_time_2 = time(NULL) - purple_presence_get_idle_time(presence2); + + if (idle_time_1 > idle_time_2) + score1 += idle_time_score; + else if (idle_time_1 < idle_time_2) + score2 += idle_time_score; + + if (score1 < score2) + return 1; + else if (score1 > score2) + return -1; + + return 0; +} + +/************************************************************************** + * GObject code for PurpleAccountPresence + **************************************************************************/ + +/* GObject Property names */ +#define ACPRES_PROP_ACCOUNT_S "account" + +/* Set method for GObject properties */ +static void +purple_account_presence_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleAccountPresence *account_presence = PURPLE_ACCOUNT_PRESENCE(obj); + PurpleAccountPresencePrivate *priv = + PURPLE_ACCOUNT_PRESENCE_GET_PRIVATE(account_presence); + + switch (param_id) { + case ACPRES_PROP_ACCOUNT: + priv->account = g_value_get_object(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_account_presence_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleAccountPresence *account_presence = PURPLE_ACCOUNT_PRESENCE(obj); + + switch (param_id) { + case ACPRES_PROP_ACCOUNT: + g_value_set_object(value, + purple_account_presence_get_account(account_presence)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Called when done constructing */ +static void +purple_account_presence_constructed(GObject *object) +{ + PurplePresence *presence = PURPLE_PRESENCE(object); + PurpleAccountPresencePrivate *priv = PURPLE_ACCOUNT_PRESENCE_GET_PRIVATE(presence); + + G_OBJECT_CLASS(presence_class)->constructed(object); + + PURPLE_PRESENCE_GET_PRIVATE(presence)->statuses = + purple_prpl_get_statuses(priv->account, presence); +} + +/* Class initializer function */ +static void purple_account_presence_class_init(PurpleAccountPresenceClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + PURPLE_PRESENCE_CLASS(klass)->update_idle = purple_account_presence_update_idle; + + presence_class = g_type_class_peek_parent(klass); + + obj_class->constructed = purple_account_presence_constructed; + + /* Setup properties */ + obj_class->get_property = purple_account_presence_get_property; + obj_class->set_property = purple_account_presence_set_property; + + g_object_class_install_property(obj_class, ACPRES_PROP_ACCOUNT, + g_param_spec_object(ACPRES_PROP_ACCOUNT_S, _("Account"), + _("The account that this presence is of."), PURPLE_TYPE_ACCOUNT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY) + ); + + g_type_class_add_private(klass, sizeof(PurpleAccountPresencePrivate)); +} + +GType +purple_account_presence_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleAccountPresenceClass), + NULL, + NULL, + (GClassInitFunc)purple_account_presence_class_init, + NULL, + NULL, + sizeof(PurpleAccountPresence), + 0, + NULL, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_PRESENCE, + "PurpleAccountPresence", + &info, 0); + } + + return type; +} + +PurpleAccountPresence * +purple_account_presence_new(PurpleAccount *account) +{ + g_return_val_if_fail(account != NULL, NULL); + + return g_object_new(PURPLE_TYPE_ACCOUNT_PRESENCE, + ACPRES_PROP_ACCOUNT_S, account, + NULL); +} + +/************************************************************************** +* PurpleBuddyPresence API +**************************************************************************/ +static void +purple_buddy_presence_update_idle(PurplePresence *presence, gboolean old_idle) +{ + PurpleBuddy *buddy = purple_buddy_presence_get_buddy(PURPLE_BUDDY_PRESENCE(presence)); + time_t current_time = time(NULL); + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + PurpleAccount *account = purple_buddy_get_account(buddy); + gboolean idle = purple_presence_is_idle(presence); + + if (!old_idle && idle) + { + if (purple_prefs_get_bool("/purple/logging/log_system")) + { + PurpleLog *log = purple_account_get_log(account, FALSE); + + if (log != NULL) + { + char *tmp, *tmp2; + tmp = g_strdup_printf(_("%s became idle"), + purple_buddy_get_alias(buddy)); + tmp2 = g_markup_escape_text(tmp, -1); + g_free(tmp); + + purple_log_write(log, PURPLE_MESSAGE_SYSTEM, + purple_buddy_get_alias(buddy), current_time, tmp2); + g_free(tmp2); + } + } + } + else if (old_idle && !idle) + { + if (purple_prefs_get_bool("/purple/logging/log_system")) + { + PurpleLog *log = purple_account_get_log(account, FALSE); + + if (log != NULL) + { + char *tmp, *tmp2; + tmp = g_strdup_printf(_("%s became unidle"), + purple_buddy_get_alias(buddy)); + tmp2 = g_markup_escape_text(tmp, -1); + g_free(tmp); + + purple_log_write(log, PURPLE_MESSAGE_SYSTEM, + purple_buddy_get_alias(buddy), current_time, tmp2); + g_free(tmp2); + } + } + } + + if (old_idle != idle) + purple_signal_emit(purple_blist_get_handle(), "buddy-idle-changed", buddy, + old_idle, idle); + + purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy)); + + /* Should this be done here? It'd perhaps make more sense to + * connect to buddy-[un]idle signals and update from there + */ + + if (ops != NULL && ops->update != NULL) + ops->update(purple_blist_get_buddy_list(), (PurpleBlistNode *)buddy); +} + +PurpleBuddy * +purple_buddy_presence_get_buddy(const PurpleBuddyPresence *presence) +{ + PurpleBuddyPresencePrivate *priv = PURPLE_BUDDY_PRESENCE_GET_PRIVATE(presence); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->buddy; +} + +/************************************************************************** + * GObject code for PurpleBuddyPresence + **************************************************************************/ + +/* GObject Property names */ +#define BUDPRES_PROP_BUDDY_S "buddy" + +/* Set method for GObject properties */ +static void +purple_buddy_presence_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleBuddyPresence *buddy_presence = PURPLE_BUDDY_PRESENCE(obj); + PurpleBuddyPresencePrivate *priv = + PURPLE_BUDDY_PRESENCE_GET_PRIVATE(buddy_presence); + + switch (param_id) { + case BUDPRES_PROP_BUDDY: + priv->buddy = g_value_get_object(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_buddy_presence_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleBuddyPresence *buddy_presence = PURPLE_BUDDY_PRESENCE(obj); + + switch (param_id) { + case BUDPRES_PROP_BUDDY: + g_value_set_object(value, + purple_buddy_presence_get_buddy(buddy_presence)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Called when done constructing */ +static void +purple_buddy_presence_constructed(GObject *object) +{ + PurplePresence *presence = PURPLE_PRESENCE(object); + PurpleBuddyPresencePrivate *priv = PURPLE_BUDDY_PRESENCE_GET_PRIVATE(presence); + PurpleAccount *account; + + G_OBJECT_CLASS(presence_class)->constructed(object); + + account = purple_buddy_get_account(priv->buddy); + PURPLE_PRESENCE_GET_PRIVATE(presence)->statuses = + purple_prpl_get_statuses(account, presence); +} + +/* Class initializer function */ +static void purple_buddy_presence_class_init(PurpleBuddyPresenceClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + PURPLE_PRESENCE_CLASS(klass)->update_idle = purple_buddy_presence_update_idle; + + presence_class = g_type_class_peek_parent(klass); + + obj_class->constructed = purple_buddy_presence_constructed; + + /* Setup properties */ + obj_class->get_property = purple_buddy_presence_get_property; + obj_class->set_property = purple_buddy_presence_set_property; + + g_object_class_install_property(obj_class, BUDPRES_PROP_BUDDY, + g_param_spec_object(BUDPRES_PROP_BUDDY_S, _("Buddy"), + _("The buddy that this presence is of."), PURPLE_TYPE_BUDDY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY) + ); + + g_type_class_add_private(klass, sizeof(PurpleBuddyPresencePrivate)); +} + +GType +purple_buddy_presence_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleBuddyPresenceClass), + NULL, + NULL, + (GClassInitFunc)purple_buddy_presence_class_init, + NULL, + NULL, + sizeof(PurpleBuddyPresence), + 0, + NULL, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_PRESENCE, + "PurpleBuddyPresence", + &info, 0); + } + + return type; +} + +PurpleBuddyPresence * +purple_buddy_presence_new(PurpleBuddy *buddy) +{ + g_return_val_if_fail(buddy != NULL, NULL); + + return g_object_new(PURPLE_TYPE_BUDDY_PRESENCE, + BUDPRES_PROP_BUDDY_S, buddy, + NULL); +} diff --git a/libpurple/presence.h b/libpurple/presence.h new file mode 100644 index 0000000000..465a76f802 --- /dev/null +++ b/libpurple/presence.h @@ -0,0 +1,387 @@ +/** + * @file presence.h Presence, account presence and buddy presence API + * @ingroup core + */ +/* + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef _PURPLE_PRESENCE_H_ +#define _PURPLE_PRESENCE_H_ + +#define PURPLE_TYPE_PRESENCE (purple_presence_get_type()) +#define PURPLE_PRESENCE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_PRESENCE, PurplePresence)) +#define PURPLE_PRESENCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_PRESENCE, PurplePresenceClass)) +#define PURPLE_IS_PRESENCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_PRESENCE)) +#define PURPLE_IS_PRESENCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_PRESENCE)) +#define PURPLE_PRESENCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_PRESENCE, PurplePresenceClass)) + +/** @copydoc _PurplePresence */ +typedef struct _PurplePresence PurplePresence; +/** @copydoc _PurplePresenceClass */ +typedef struct _PurplePresenceClass PurplePresenceClass; + +#define PURPLE_TYPE_ACCOUNT_PRESENCE (purple_account_presence_get_type()) +#define PURPLE_ACCOUNT_PRESENCE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_ACCOUNT_PRESENCE, PurpleAccountPresence)) +#define PURPLE_ACCOUNT_PRESENCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_ACCOUNT_PRESENCE, PurpleAccountPresenceClass)) +#define PURPLE_IS_ACCOUNT_PRESENCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_ACCOUNT_PRESENCE)) +#define PURPLE_IS_ACCOUNT_PRESENCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_ACCOUNT_PRESENCE)) +#define PURPLE_ACCOUNT_PRESENCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_ACCOUNT_PRESENCE, PurpleAccountPresenceClass)) + +/** @copydoc _PurpleAccountPresence */ +typedef struct _PurpleAccountPresence PurpleAccountPresence; +/** @copydoc _PurpleAccountPresenceClass */ +typedef struct _PurpleAccountPresenceClass PurpleAccountPresenceClass; + +#define PURPLE_TYPE_BUDDY_PRESENCE (purple_buddy_presence_get_type()) +#define PURPLE_BUDDY_PRESENCE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_BUDDY_PRESENCE, PurpleBuddyPresence)) +#define PURPLE_BUDDY_PRESENCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_BUDDY_PRESENCE, PurpleBuddyPresenceClass)) +#define PURPLE_IS_BUDDY_PRESENCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_BUDDY_PRESENCE)) +#define PURPLE_IS_BUDDY_PRESENCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_BUDDY_PRESENCE)) +#define PURPLE_BUDDY_PRESENCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_BUDDY_PRESENCE, PurpleBuddyPresenceClass)) + +/** @copydoc _PurpleBuddyPresence */ +typedef struct _PurpleBuddyPresence PurpleBuddyPresence; +/** @copydoc _PurpleBuddyPresenceClass */ +typedef struct _PurpleBuddyPresenceClass PurpleBuddyPresenceClass; + +#include "account.h" +#include "buddylist.h" +#include "status.h" + +/** + * A PurplePresence is like a collection of PurpleStatuses (plus some + * other random info). For any buddy, or for any one of your accounts, + * or for any person with which you're chatting, you may know various + * amounts of information. This information is all contained in + * one PurplePresence. If one of your buddies is away and idle, + * then the presence contains the PurpleStatus for their awayness, + * and it contains their current idle time. PurplePresences are + * never saved to disk. The information they contain is only relevant + * for the current PurpleSession. + * + * @note When a presence is destroyed with the last g_object_unref(), all + * statuses added to this list will be destroyed along with the presence. + */ +struct _PurplePresence +{ + /*< private >*/ + GObject gparent; +}; + +/** Base class for all #PurplePresence's */ +struct _PurplePresenceClass { + /*< private >*/ + GObjectClass parent_class; + + /** + * Updates the logs and the UI when the idle state or time of the presence + * changes. + */ + void (*update_idle)(PurplePresence *presence, gboolean old_idle); + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/** + * A presence for an account + */ +struct _PurpleAccountPresence +{ + /*< private >*/ + PurplePresence parent; +}; + +/** Base class for all #PurpleAccountPresence's */ +struct _PurpleAccountPresenceClass { + /*< private >*/ + PurplePresenceClass parent_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/** + * A presence for a buddy + */ +struct _PurpleBuddyPresence +{ + /*< private >*/ + PurplePresence parent; +}; + +/** Base class for all #PurpleBuddyPresence's */ +struct _PurpleBuddyPresenceClass { + /*< private >*/ + PurplePresenceClass parent_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +/**************************************************************************/ +/** @name PurpleAccountPresence API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the PurpleAccountPresence object. + */ +GType purple_account_presence_get_type(void); + +/** + * Creates a presence for an account. + * + * @param account The account to associate with the presence. + * + * @return The new presence. + */ +PurpleAccountPresence *purple_account_presence_new(PurpleAccount *account); + +/** + * Returns an account presence's account. + * + * @param presence The presence. + * + * @return The presence's account. + */ +PurpleAccount *purple_account_presence_get_account(const PurpleAccountPresence *presence); + +/*@}*/ + +/**************************************************************************/ +/** @name PurpleBuddyPresence API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the PurpleBuddyPresence object. + */ +GType purple_buddy_presence_get_type(void); + +/** + * Creates a presence for a buddy. + * + * @param buddy The buddy to associate with the presence. + * + * @return The new presence. + */ +PurpleBuddyPresence *purple_buddy_presence_new(PurpleBuddy *buddy); + +/** + * Returns the buddy presence's buddy. + * + * @param presence The presence. + * + * @return The presence's buddy. + */ +PurpleBuddy *purple_buddy_presence_get_buddy(const PurpleBuddyPresence *presence); + +/** + * Compares two buddy presences for availability. + * + * @param buddy_presence1 The first presence. + * @param buddy_presence2 The second presence. + * + * @return -1 if @a buddy_presence1 is more available than @a buddy_presence2. + * 0 if @a buddy_presence1 is equal to @a buddy_presence2. + * 1 if @a buddy_presence1 is less available than @a buddy_presence2. + */ +gint purple_buddy_presence_compare(const PurpleBuddyPresence *buddy_presence1, + const PurpleBuddyPresence *buddy_presence2); + +/*@}*/ + +/**************************************************************************/ +/** @name PurplePresence API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the PurplePresence object. + */ +GType purple_presence_get_type(void); + +/** + * Sets the active state of a status in a presence. + * + * Only independent statuses can be set unactive. Normal statuses can only + * be set active, so if you wish to disable a status, set another + * non-independent status to active, or use purple_presence_switch_status(). + * + * @param presence The presence. + * @param status_id The ID of the status. + * @param active The active state. + */ +void purple_presence_set_status_active(PurplePresence *presence, + const char *status_id, gboolean active); + +/** + * Switches the active status in a presence. + * + * This is similar to purple_presence_set_status_active(), except it won't + * activate independent statuses. + * + * @param presence The presence. + * @param status_id The status ID to switch to. + */ +void purple_presence_switch_status(PurplePresence *presence, + const char *status_id); + +/** + * Sets the idle state and time on a presence. + * + * @param presence The presence. + * @param idle The idle state. + * @param idle_time The idle time, if @a idle is TRUE. This + * is the time at which the user became idle, + * in seconds since the epoch. If this value is + * unknown then 0 should be used. + */ +void purple_presence_set_idle(PurplePresence *presence, gboolean idle, + time_t idle_time); + +/** + * Sets the login time on a presence. + * + * @param presence The presence. + * @param login_time The login time. + */ +void purple_presence_set_login_time(PurplePresence *presence, time_t login_time); + +/** + * Returns all the statuses in a presence. + * + * @param presence The presence. + * + * @constreturn The statuses. + */ +GList *purple_presence_get_statuses(const PurplePresence *presence); + +/** + * Returns the status with the specified ID from a presence. + * + * @param presence The presence. + * @param status_id The ID of the status. + * + * @return The status if found, or NULL. + */ +PurpleStatus *purple_presence_get_status(const PurplePresence *presence, + const char *status_id); + +/** + * Returns the active exclusive status from a presence. + * + * @param presence The presence. + * + * @return The active exclusive status. + */ +PurpleStatus *purple_presence_get_active_status(const PurplePresence *presence); + +/** + * Returns whether or not a presence is available. + * + * Available presences are online and possibly invisible, but not away or idle. + * + * @param presence The presence. + * + * @return TRUE if the presence is available, or FALSE otherwise. + */ +gboolean purple_presence_is_available(const PurplePresence *presence); + +/** + * Returns whether or not a presence is online. + * + * @param presence The presence. + * + * @return TRUE if the presence is online, or FALSE otherwise. + */ +gboolean purple_presence_is_online(const PurplePresence *presence); + +/** + * Returns whether or not a status in a presence is active. + * + * A status is active if itself or any of its sub-statuses are active. + * + * @param presence The presence. + * @param status_id The ID of the status. + * + * @return TRUE if the status is active, or FALSE. + */ +gboolean purple_presence_is_status_active(const PurplePresence *presence, + const char *status_id); + +/** + * Returns whether or not a status with the specified primitive type + * in a presence is active. + * + * A status is active if itself or any of its sub-statuses are active. + * + * @param presence The presence. + * @param primitive The status primitive. + * + * @return TRUE if the status is active, or FALSE. + */ +gboolean purple_presence_is_status_primitive_active( + const PurplePresence *presence, PurpleStatusPrimitive primitive); + +/** + * Returns whether or not a presence is idle. + * + * @param presence The presence. + * + * @return TRUE if the presence is idle, or FALSE otherwise. + * If the presence is offline (purple_presence_is_online() + * returns FALSE) then FALSE is returned. + */ +gboolean purple_presence_is_idle(const PurplePresence *presence); + +/** + * Returns the presence's idle time. + * + * @param presence The presence. + * + * @return The presence's idle time. + */ +time_t purple_presence_get_idle_time(const PurplePresence *presence); + +/** + * Returns the presence's login time. + * + * @param presence The presence. + * + * @return The presence's login time. + */ +time_t purple_presence_get_login_time(const PurplePresence *presence); + +/*@}*/ + +G_END_DECLS + +#endif /* _PURPLE_PRESENCE_H_ */ diff --git a/libpurple/privacy.c b/libpurple/privacy.c deleted file mode 100644 index 9f9d28838f..0000000000 --- a/libpurple/privacy.c +++ /dev/null @@ -1,411 +0,0 @@ -/** - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "internal.h" - -#include "account.h" -#include "privacy.h" -#include "server.h" -#include "util.h" - -static PurplePrivacyUiOps *privacy_ops = NULL; - -gboolean -purple_privacy_permit_add(PurpleAccount *account, const char *who, - gboolean local_only) -{ - GSList *l; - char *name; - PurpleBuddy *buddy; - PurpleBlistUiOps *blist_ops; - - g_return_val_if_fail(account != NULL, FALSE); - g_return_val_if_fail(who != NULL, FALSE); - - name = g_strdup(purple_normalize(account, who)); - - for (l = account->permit; l != NULL; l = l->next) { - if (g_str_equal(name, l->data)) - /* This buddy already exists */ - break; - } - - if (l != NULL) - { - /* This buddy already exists, so bail out */ - g_free(name); - return FALSE; - } - - account->permit = g_slist_append(account->permit, name); - - if (!local_only && purple_account_is_connected(account)) - serv_add_permit(purple_account_get_connection(account), who); - - if (privacy_ops != NULL && privacy_ops->permit_added != NULL) - privacy_ops->permit_added(account, who); - - blist_ops = purple_blist_get_ui_ops(); - if (blist_ops != NULL && blist_ops->save_account != NULL) - blist_ops->save_account(account); - - /* This lets the UI know a buddy has had its privacy setting changed */ - buddy = purple_find_buddy(account, name); - if (buddy != NULL) { - purple_signal_emit(purple_blist_get_handle(), - "buddy-privacy-changed", buddy); - } - return TRUE; -} - -gboolean -purple_privacy_permit_remove(PurpleAccount *account, const char *who, - gboolean local_only) -{ - GSList *l; - const char *name; - PurpleBuddy *buddy; - char *del; - PurpleBlistUiOps *blist_ops; - - g_return_val_if_fail(account != NULL, FALSE); - g_return_val_if_fail(who != NULL, FALSE); - - name = purple_normalize(account, who); - - for (l = account->permit; l != NULL; l = l->next) { - if (g_str_equal(name, l->data)) - /* We found the buddy we were looking for */ - break; - } - - if (l == NULL) - /* We didn't find the buddy we were looking for, so bail out */ - return FALSE; - - /* We should not free l->data just yet. There can be occasions where - * l->data == who. In such cases, freeing l->data here can cause crashes - * later when who is used. */ - del = l->data; - account->permit = g_slist_delete_link(account->permit, l); - - if (!local_only && purple_account_is_connected(account)) - serv_rem_permit(purple_account_get_connection(account), who); - - if (privacy_ops != NULL && privacy_ops->permit_removed != NULL) - privacy_ops->permit_removed(account, who); - - blist_ops = purple_blist_get_ui_ops(); - if (blist_ops != NULL && blist_ops->save_account != NULL) - blist_ops->save_account(account); - - buddy = purple_find_buddy(account, name); - if (buddy != NULL) { - purple_signal_emit(purple_blist_get_handle(), - "buddy-privacy-changed", buddy); - } - g_free(del); - return TRUE; -} - -gboolean -purple_privacy_deny_add(PurpleAccount *account, const char *who, - gboolean local_only) -{ - GSList *l; - char *name; - PurpleBuddy *buddy; - PurpleBlistUiOps *blist_ops; - - g_return_val_if_fail(account != NULL, FALSE); - g_return_val_if_fail(who != NULL, FALSE); - - name = g_strdup(purple_normalize(account, who)); - - for (l = account->deny; l != NULL; l = l->next) { - if (g_str_equal(name, l->data)) - /* This buddy already exists */ - break; - } - - if (l != NULL) - { - /* This buddy already exists, so bail out */ - g_free(name); - return FALSE; - } - - account->deny = g_slist_append(account->deny, name); - - if (!local_only && purple_account_is_connected(account)) - serv_add_deny(purple_account_get_connection(account), who); - - if (privacy_ops != NULL && privacy_ops->deny_added != NULL) - privacy_ops->deny_added(account, who); - - blist_ops = purple_blist_get_ui_ops(); - if (blist_ops != NULL && blist_ops->save_account != NULL) - blist_ops->save_account(account); - - buddy = purple_find_buddy(account, name); - if (buddy != NULL) { - purple_signal_emit(purple_blist_get_handle(), - "buddy-privacy-changed", buddy); - } - return TRUE; -} - -gboolean -purple_privacy_deny_remove(PurpleAccount *account, const char *who, - gboolean local_only) -{ - GSList *l; - const char *normalized; - char *name; - PurpleBuddy *buddy; - PurpleBlistUiOps *blist_ops; - - g_return_val_if_fail(account != NULL, FALSE); - g_return_val_if_fail(who != NULL, FALSE); - - normalized = purple_normalize(account, who); - - for (l = account->deny; l != NULL; l = l->next) { - if (g_str_equal(normalized, l->data)) - /* We found the buddy we were looking for */ - break; - } - - if (l == NULL) - /* We didn't find the buddy we were looking for, so bail out */ - return FALSE; - - buddy = purple_find_buddy(account, normalized); - - name = l->data; - account->deny = g_slist_delete_link(account->deny, l); - - if (!local_only && purple_account_is_connected(account)) - serv_rem_deny(purple_account_get_connection(account), name); - - if (privacy_ops != NULL && privacy_ops->deny_removed != NULL) - privacy_ops->deny_removed(account, who); - - if (buddy != NULL) { - purple_signal_emit(purple_blist_get_handle(), - "buddy-privacy-changed", buddy); - } - - g_free(name); - - blist_ops = purple_blist_get_ui_ops(); - if (blist_ops != NULL && blist_ops->save_account != NULL) - blist_ops->save_account(account); - - return TRUE; -} - -/** - * This makes sure your permit list contains all buddies from your - * buddy list and ONLY buddies from your buddy list. - */ -static void -add_all_buddies_to_permit_list(PurpleAccount *account, gboolean local) -{ - GSList *list; - - /* Remove anyone in the permit list who is not in the buddylist */ - for (list = account->permit; list != NULL; ) { - char *person = list->data; - list = list->next; - if (!purple_find_buddy(account, person)) - purple_privacy_permit_remove(account, person, local); - } - - /* Now make sure everyone in the buddylist is in the permit list */ - list = purple_find_buddies(account, NULL); - while (list != NULL) - { - PurpleBuddy *buddy = list->data; - const gchar *name = purple_buddy_get_name(buddy); - - if (!g_slist_find_custom(account->permit, name, (GCompareFunc)g_utf8_collate)) - purple_privacy_permit_add(account, name, local); - list = g_slist_delete_link(list, list); - } -} - -/* - * TODO: All callers of this function pass in FALSE for local and - * restore and I don't understand when you would ever want to - * use TRUE for either of them. I think both parameters could - * safely be removed in the next major version bump. - */ -void -purple_privacy_allow(PurpleAccount *account, const char *who, gboolean local, - gboolean restore) -{ - GSList *list; - PurplePrivacyType type = purple_account_get_privacy_type(account); - - switch (type) { - case PURPLE_PRIVACY_ALLOW_ALL: - return; - case PURPLE_PRIVACY_ALLOW_USERS: - purple_privacy_permit_add(account, who, local); - break; - case PURPLE_PRIVACY_DENY_USERS: - purple_privacy_deny_remove(account, who, local); - break; - case PURPLE_PRIVACY_DENY_ALL: - if (!restore) { - /* Empty the allow-list. */ - const char *norm = purple_normalize(account, who); - for (list = account->permit; list != NULL;) { - char *person = list->data; - list = list->next; - if (!purple_strequal(norm, person)) - purple_privacy_permit_remove(account, person, local); - } - } - purple_privacy_permit_add(account, who, local); - purple_account_set_privacy_type(account, PURPLE_PRIVACY_ALLOW_USERS); - break; - case PURPLE_PRIVACY_ALLOW_BUDDYLIST: - if (!purple_find_buddy(account, who)) { - add_all_buddies_to_permit_list(account, local); - purple_privacy_permit_add(account, who, local); - purple_account_set_privacy_type(account, PURPLE_PRIVACY_ALLOW_USERS); - } - break; - default: - g_return_if_reached(); - } - - /* Notify the server if the privacy setting was changed */ - if (type != purple_account_get_privacy_type(account) && purple_account_is_connected(account)) - serv_set_permit_deny(purple_account_get_connection(account)); -} - -/* - * TODO: All callers of this function pass in FALSE for local and - * restore and I don't understand when you would ever want to - * use TRUE for either of them. I think both parameters could - * safely be removed in the next major version bump. - */ -void -purple_privacy_deny(PurpleAccount *account, const char *who, gboolean local, - gboolean restore) -{ - GSList *list; - PurplePrivacyType type = purple_account_get_privacy_type(account); - - switch (type) { - case PURPLE_PRIVACY_ALLOW_ALL: - if (!restore) { - /* Empty the deny-list. */ - const char *norm = purple_normalize(account, who); - for (list = account->deny; list != NULL; ) { - char *person = list->data; - list = list->next; - if (!purple_strequal(norm, person)) - purple_privacy_deny_remove(account, person, local); - } - } - purple_privacy_deny_add(account, who, local); - purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS); - break; - case PURPLE_PRIVACY_ALLOW_USERS: - purple_privacy_permit_remove(account, who, local); - break; - case PURPLE_PRIVACY_DENY_USERS: - purple_privacy_deny_add(account, who, local); - break; - case PURPLE_PRIVACY_DENY_ALL: - break; - case PURPLE_PRIVACY_ALLOW_BUDDYLIST: - if (purple_find_buddy(account, who)) { - add_all_buddies_to_permit_list(account, local); - purple_privacy_permit_remove(account, who, local); - purple_account_set_privacy_type(account, PURPLE_PRIVACY_ALLOW_USERS); - } - break; - default: - g_return_if_reached(); - } - - /* Notify the server if the privacy setting was changed */ - if (type != purple_account_get_privacy_type(account) && purple_account_is_connected(account)) - serv_set_permit_deny(purple_account_get_connection(account)); -} - -gboolean -purple_privacy_check(PurpleAccount *account, const char *who) -{ - GSList *list; - - switch (purple_account_get_privacy_type(account)) { - case PURPLE_PRIVACY_ALLOW_ALL: - return TRUE; - - case PURPLE_PRIVACY_DENY_ALL: - return FALSE; - - case PURPLE_PRIVACY_ALLOW_USERS: - who = purple_normalize(account, who); - for (list=account->permit; list!=NULL; list=list->next) { - if (g_str_equal(who, list->data)) - return TRUE; - } - return FALSE; - - case PURPLE_PRIVACY_DENY_USERS: - who = purple_normalize(account, who); - for (list=account->deny; list!=NULL; list=list->next) { - if (g_str_equal(who, list->data)) - return FALSE; - } - return TRUE; - - case PURPLE_PRIVACY_ALLOW_BUDDYLIST: - return (purple_find_buddy(account, who) != NULL); - - default: - g_return_val_if_reached(TRUE); - } -} - -void -purple_privacy_set_ui_ops(PurplePrivacyUiOps *ops) -{ - privacy_ops = ops; -} - -PurplePrivacyUiOps * -purple_privacy_get_ui_ops(void) -{ - return privacy_ops; -} - -void -purple_privacy_init(void) -{ -} diff --git a/libpurple/privacy.h b/libpurple/privacy.h deleted file mode 100644 index 19ef9d6494..0000000000 --- a/libpurple/privacy.h +++ /dev/null @@ -1,190 +0,0 @@ -/** - * @file privacy.h Privacy API - * @ingroup core - */ - -/* purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _PURPLE_PRIVACY_H_ -#define _PURPLE_PRIVACY_H_ - -/** - * Privacy data types. - */ -typedef enum -{ - PURPLE_PRIVACY_ALLOW_ALL = 1, - PURPLE_PRIVACY_DENY_ALL, - PURPLE_PRIVACY_ALLOW_USERS, - PURPLE_PRIVACY_DENY_USERS, - PURPLE_PRIVACY_ALLOW_BUDDYLIST -} PurplePrivacyType; - -#include "account.h" - -/** - * Privacy core/UI operations. - */ -typedef struct -{ - void (*permit_added)(PurpleAccount *account, const char *name); - void (*permit_removed)(PurpleAccount *account, const char *name); - void (*deny_added)(PurpleAccount *account, const char *name); - void (*deny_removed)(PurpleAccount *account, const char *name); - - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -} PurplePrivacyUiOps; - -G_BEGIN_DECLS - -/** - * Adds a user to the account's permit list. - * - * @param account The account. - * @param name The name of the user to add to the list. - * @param local_only If TRUE, only the local list is updated, and not - * the server. - * - * @return TRUE if the user was added successfully, or @c FALSE otherwise. - */ -gboolean purple_privacy_permit_add(PurpleAccount *account, const char *name, - gboolean local_only); - -/** - * Removes a user from the account's permit list. - * - * @param account The account. - * @param name The name of the user to add to the list. - * @param local_only If TRUE, only the local list is updated, and not - * the server. - * - * @return TRUE if the user was removed successfully, or @c FALSE otherwise. - */ -gboolean purple_privacy_permit_remove(PurpleAccount *account, const char *name, - gboolean local_only); - -/** - * Adds a user to the account's deny list. - * - * @param account The account. - * @param name The name of the user to add to the list. - * @param local_only If TRUE, only the local list is updated, and not - * the server. - * - * @return TRUE if the user was added successfully, or @c FALSE otherwise. - */ -gboolean purple_privacy_deny_add(PurpleAccount *account, const char *name, - gboolean local_only); - -/** - * Removes a user from the account's deny list. - * - * @param account The account. - * @param name The name of the user to add to the list. - * @param local_only If TRUE, only the local list is updated, and not - * the server. - * - * @return TRUE if the user was removed successfully, or @c FALSE otherwise. - */ -gboolean purple_privacy_deny_remove(PurpleAccount *account, const char *name, - gboolean local_only); - -/** - * Allow a user to send messages. If current privacy setting for the account is: - * PURPLE_PRIVACY_ALLOW_USERS: The user is added to the allow-list. - * PURPLE_PRIVACY_DENY_USERS : The user is removed from the deny-list. - * PURPLE_PRIVACY_ALLOW_ALL : No changes made. - * PURPLE_PRIVACY_DENY_ALL : The privacy setting is changed to - * PURPLE_PRIVACY_ALLOW_USERS and the user - * is added to the allow-list. - * PURPLE_PRIVACY_ALLOW_BUDDYLIST: No changes made if the user is already in - * the buddy-list. Otherwise the setting is - * changed to PURPLE_PRIVACY_ALLOW_USERS, all the - * buddies are added to the allow-list, and the - * user is also added to the allow-list. - * - * @param account The account. - * @param who The name of the user. - * @param local Whether the change is local-only. - * @param restore Should the previous allow/deny list be restored if the - * privacy setting is changed. - */ -void purple_privacy_allow(PurpleAccount *account, const char *who, gboolean local, - gboolean restore); - -/** - * Block messages from a user. If current privacy setting for the account is: - * PURPLE_PRIVACY_ALLOW_USERS: The user is removed from the allow-list. - * PURPLE_PRIVACY_DENY_USERS : The user is added to the deny-list. - * PURPLE_PRIVACY_DENY_ALL : No changes made. - * PURPLE_PRIVACY_ALLOW_ALL : The privacy setting is changed to - * PURPLE_PRIVACY_DENY_USERS and the user is - * added to the deny-list. - * PURPLE_PRIVACY_ALLOW_BUDDYLIST: If the user is not in the buddy-list, - * then no changes made. Otherwise, the setting - * is changed to PURPLE_PRIVACY_ALLOW_USERS, all - * the buddies are added to the allow-list, and - * this user is removed from the list. - * - * @param account The account. - * @param who The name of the user. - * @param local Whether the change is local-only. - * @param restore Should the previous allow/deny list be restored if the - * privacy setting is changed. - */ -void purple_privacy_deny(PurpleAccount *account, const char *who, gboolean local, - gboolean restore); - -/** - * Check the privacy-setting for a user. - * - * @param account The account. - * @param who The name of the user. - * - * @return @c FALSE if the specified account's privacy settings block the user or @c TRUE otherwise. The meaning of "block" is protocol-dependent and generally relates to status and/or sending of messages. - */ -gboolean purple_privacy_check(PurpleAccount *account, const char *who); - -/** - * Sets the UI operations structure for the privacy subsystem. - * - * @param ops The UI operations structure. - */ -void purple_privacy_set_ui_ops(PurplePrivacyUiOps *ops); - -/** - * Returns the UI operations structure for the privacy subsystem. - * - * @return The UI operations structure. - */ -PurplePrivacyUiOps *purple_privacy_get_ui_ops(void); - -/** - * Initializes the privacy subsystem. - */ -void purple_privacy_init(void); - -G_END_DECLS - -#endif /* _PURPLE_PRIVACY_H_ */ diff --git a/libpurple/protocols/bonjour/bonjour.c b/libpurple/protocols/bonjour/bonjour.c index 5dc85c47db..d0ceef8bab 100644 --- a/libpurple/protocols/bonjour/bonjour.c +++ b/libpurple/protocols/bonjour/bonjour.c @@ -68,11 +68,11 @@ bonjour_removeallfromlocal(PurpleConnection *conn, PurpleGroup *bonjour_group) /* Go through and remove all buddies that belong to this account */ for (cnode = purple_blist_node_get_first_child((PurpleBlistNode *) bonjour_group); cnode; cnode = cnodenext) { cnodenext = purple_blist_node_get_sibling_next(cnode); - if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) + if (!PURPLE_IS_CONTACT(cnode)) continue; for (bnode = purple_blist_node_get_first_child(cnode); bnode; bnode = bnodenext) { bnodenext = purple_blist_node_get_sibling_next(bnode); - if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + if (!PURPLE_IS_BUDDY(bnode)) continue; buddy = (PurpleBuddy *) bnode; if (purple_buddy_get_account(buddy) != account) @@ -103,7 +103,7 @@ bonjour_login(PurpleAccount *account) } #endif /* _WIN32 */ - purple_connection_set_flags(gc, PURPLE_CONNECTION_HTML); + purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_HTML); bd = g_new0(BonjourData, 1); purple_connection_set_protocol_data(gc, bd); @@ -152,7 +152,7 @@ bonjour_login(PurpleAccount *account) bonjour_dns_sd_update_buddy_icon(bd->dns_sd_data); /* Show the buddy list by telling Purple we have already connected */ - purple_connection_set_state(gc, PURPLE_CONNECTED); + purple_connection_set_state(gc, PURPLE_CONNECTION_CONNECTED); } static void @@ -161,7 +161,7 @@ bonjour_close(PurpleConnection *connection) PurpleGroup *bonjour_group; BonjourData *bd = purple_connection_get_protocol_data(connection); - bonjour_group = purple_find_group(BONJOUR_GROUP_NAME); + bonjour_group = purple_blist_find_group(BONJOUR_GROUP_NAME); /* Remove all the bonjour buddies */ bonjour_removeallfromlocal(connection, bonjour_group); @@ -289,14 +289,14 @@ bonjour_status_types(PurpleAccount *account) BONJOUR_STATUS_ID_AVAILABLE, NULL, TRUE, TRUE, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_append(status_types, type); type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, BONJOUR_STATUS_ID_AWAY, NULL, TRUE, TRUE, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_append(status_types, type); type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, @@ -310,7 +310,7 @@ bonjour_status_types(PurpleAccount *account) static void bonjour_convo_closed(PurpleConnection *connection, const char *who) { - PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(connection), who); + PurpleBuddy *buddy = purple_blist_find_buddy(purple_connection_get_account(connection), who); BonjourBuddy *bb; if (buddy == NULL || (bb = purple_buddy_get_protocol_data(buddy)) == NULL) @@ -421,26 +421,24 @@ bonjour_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboole } static void -bonjour_do_group_change(PurpleBuddy *buddy, const char *new_group) { - PurpleBlistNodeFlags oldflags; - +bonjour_do_group_change(PurpleBuddy *buddy, const char *new_group) +{ if (buddy == NULL) return; - oldflags = purple_blist_node_get_flags((PurpleBlistNode *)buddy); - /* If we're moving them out of the bonjour group, make them persistent */ if (purple_strequal(new_group, BONJOUR_GROUP_NAME)) - purple_blist_node_set_flags((PurpleBlistNode *)buddy, oldflags | PURPLE_BLIST_NODE_FLAG_NO_SAVE); + purple_blist_node_set_transient(PURPLE_BLIST_NODE(buddy), TRUE); else - purple_blist_node_set_flags((PurpleBlistNode *)buddy, oldflags ^ PURPLE_BLIST_NODE_FLAG_NO_SAVE); + purple_blist_node_set_transient(PURPLE_BLIST_NODE(buddy), + !purple_blist_node_is_transient(PURPLE_BLIST_NODE(buddy))); } static void bonjour_group_buddy(PurpleConnection *connection, const char *who, const char *old_group, const char *new_group) { - PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(connection), who); + PurpleBuddy *buddy = purple_blist_find_buddy(purple_connection_get_account(connection), who); bonjour_do_group_change(buddy, new_group); @@ -465,7 +463,7 @@ bonjour_rename_group(PurpleConnection *connection, const char *old_name, PurpleG static gboolean bonjour_can_receive_file(PurpleConnection *connection, const char *who) { - PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(connection), who); + PurpleBuddy *buddy = purple_blist_find_buddy(purple_connection_get_account(connection), who); return (buddy != NULL && purple_buddy_get_protocol_data(buddy) != NULL); } diff --git a/libpurple/protocols/bonjour/bonjour_ft.c b/libpurple/protocols/bonjour/bonjour_ft.c index 6e704facc4..870e8700ce 100644 --- a/libpurple/protocols/bonjour/bonjour_ft.c +++ b/libpurple/protocols/bonjour/bonjour_ft.c @@ -28,7 +28,7 @@ #include "buddy.h" #include "bonjour.h" #include "bonjour_ft.h" -#include "cipher.h" +#include "ciphers/sha1hash.h" static void bonjour_bytestreams_init(PurpleXfer *xfer); @@ -408,7 +408,7 @@ bonjour_xfer_init(PurpleXfer *xfer) purple_debug_info("bonjour", "Bonjour-xfer-init.\n"); - buddy = purple_find_buddy(purple_xfer_get_account(xfer), purple_xfer_get_remote_user(xfer)); + buddy = purple_blist_find_buddy(purple_xfer_get_account(xfer), purple_xfer_get_remote_user(xfer)); /* this buddy is offline. */ if (buddy == NULL || (bb = purple_buddy_get_protocol_data(buddy)) == NULL) return; @@ -1018,6 +1018,7 @@ bonjour_bytestreams_connect(PurpleXfer *xfer) { PurpleBuddy *pb; PurpleAccount *account = NULL; + PurpleHash *hash; XepXfer *xf; char dstaddr[41]; const gchar *name = NULL; @@ -1039,8 +1040,12 @@ bonjour_bytestreams_connect(PurpleXfer *xfer) account = purple_buddy_get_account(pb); p = g_strdup_printf("%s%s%s", xf->sid, name, bonjour_get_jid(account)); - purple_cipher_digest_region("sha1", (guchar *)p, strlen(p), hashval, - sizeof(hashval)); + + hash = purple_sha1_hash_new(); + purple_hash_append(hash, (guchar *)p, strlen(p)); + purple_hash_digest(hash, hashval, sizeof(hashval)); + g_object_unref(G_OBJECT(hash)); + g_free(p); memset(dstaddr, 0, 41); diff --git a/libpurple/protocols/bonjour/buddy.c b/libpurple/protocols/bonjour/buddy.c index 890a7e1b09..36eb17caca 100644 --- a/libpurple/protocols/bonjour/buddy.c +++ b/libpurple/protocols/bonjour/buddy.c @@ -20,7 +20,7 @@ #include "internal.h" #include "buddy.h" #include "account.h" -#include "blist.h" +#include "buddylist.h" #include "bonjour.h" #include "mdns_interface.h" #include "debug.h" @@ -141,7 +141,7 @@ bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy, PurpleBuddy *buddy) */ /* Make sure the Bonjour group exists in our buddy list */ - group = purple_find_group(BONJOUR_GROUP_NAME); /* Use the buddy's domain, instead? */ + group = purple_blist_find_group(BONJOUR_GROUP_NAME); /* Use the buddy's domain, instead? */ if (group == NULL) { group = purple_group_new(BONJOUR_GROUP_NAME); purple_blist_add_group(group, NULL); @@ -149,11 +149,11 @@ bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy, PurpleBuddy *buddy) /* Make sure the buddy exists in our buddy list */ if (buddy == NULL) - buddy = purple_find_buddy(account, bonjour_buddy->name); + buddy = purple_blist_find_buddy(account, bonjour_buddy->name); if (buddy == NULL) { buddy = purple_buddy_new(account, bonjour_buddy->name, NULL); - purple_blist_node_set_flags((PurpleBlistNode *)buddy, PURPLE_BLIST_NODE_FLAG_NO_SAVE); + purple_blist_node_set_transient(PURPLE_BLIST_NODE(buddy), TRUE); purple_blist_add_buddy(buddy, NULL, group, NULL); } @@ -207,14 +207,14 @@ bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy, PurpleBuddy *buddy) * If the buddy is being saved, mark as offline, otherwise delete */ void bonjour_buddy_signed_off(PurpleBuddy *pb) { - if (PURPLE_BLIST_NODE_SHOULD_SAVE(pb)) { + if (purple_blist_node_is_transient(PURPLE_BLIST_NODE(pb))) { + purple_account_remove_buddy(purple_buddy_get_account(pb), pb, NULL); + purple_blist_remove_buddy(pb); + } else { purple_prpl_got_user_status(purple_buddy_get_account(pb), purple_buddy_get_name(pb), "offline", NULL); bonjour_buddy_delete(purple_buddy_get_protocol_data(pb)); purple_buddy_set_protocol_data(pb, NULL); - } else { - purple_account_remove_buddy(purple_buddy_get_account(pb), pb, NULL); - purple_blist_remove_buddy(pb); } } diff --git a/libpurple/protocols/bonjour/jabber.c b/libpurple/protocols/bonjour/jabber.c index a600b6d023..241abf16be 100644 --- a/libpurple/protocols/bonjour/jabber.c +++ b/libpurple/protocols/bonjour/jabber.c @@ -52,7 +52,7 @@ #include "network.h" #include "eventloop.h" #include "connection.h" -#include "blist.h" +#include "buddylist.h" #include "xmlnode.h" #include "debug.h" #include "notify.h" @@ -89,7 +89,7 @@ bonjour_jabber_conv_new(PurpleBuddy *pb, PurpleAccount *account, const char *ip) BonjourJabberConversation *bconv = g_new0(BonjourJabberConversation, 1); bconv->socket = -1; - bconv->tx_buf = purple_circ_buffer_new(512); + bconv->tx_buf = purple_circular_buffer_new(512); bconv->tx_handler = 0; bconv->rx_handler = 0; bconv->pb = pb; @@ -280,7 +280,7 @@ _send_data_write_cb(gpointer data, gint source, PurpleInputCondition cond) BonjourJabberConversation *bconv = bb->conversation; int ret, writelen; - writelen = purple_circ_buffer_get_max_read(bconv->tx_buf); + writelen = purple_circular_buffer_get_max_read(bconv->tx_buf); if (writelen == 0) { purple_input_remove(bconv->tx_handler); @@ -288,7 +288,7 @@ _send_data_write_cb(gpointer data, gint source, PurpleInputCondition cond) return; } - ret = send(bconv->socket, bconv->tx_buf->outptr, writelen, 0); + ret = send(bconv->socket, purple_circular_buffer_get_output(bconv->tx_buf), writelen, 0); if (ret < 0 && errno == EAGAIN) return; @@ -302,7 +302,7 @@ _send_data_write_cb(gpointer data, gint source, PurpleInputCondition cond) account = purple_buddy_get_account(pb); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, account); + conv = PURPLE_CONVERSATION(purple_conversations_find_im_with_account(bb->name, account)); if (conv != NULL) purple_conversation_write(conv, NULL, _("Unable to send message."), @@ -313,7 +313,7 @@ _send_data_write_cb(gpointer data, gint source, PurpleInputCondition cond) return; } - purple_circ_buffer_mark_read(bconv->tx_buf, ret); + purple_circular_buffer_mark_read(bconv->tx_buf, ret); } static gint @@ -329,7 +329,7 @@ _send_data(PurpleBuddy *pb, char *message) || bconv->connect_data != NULL || bconv->sent_stream_start != FULLY_SENT || !bconv->recv_stream_start - || purple_circ_buffer_get_max_read(bconv->tx_buf) > 0) { + || purple_circular_buffer_get_max_read(bconv->tx_buf) > 0) { ret = -1; errno = EAGAIN; } else { @@ -348,7 +348,7 @@ _send_data(PurpleBuddy *pb, char *message) account = purple_buddy_get_account(pb); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, account); + conv = PURPLE_CONVERSATION(purple_conversations_find_im_with_account(bb->name, account)); if (conv != NULL) purple_conversation_write(conv, NULL, _("Unable to send message."), @@ -364,7 +364,7 @@ _send_data(PurpleBuddy *pb, char *message) if (bconv->sent_stream_start == FULLY_SENT && bconv->recv_stream_start && bconv->tx_handler == 0) bconv->tx_handler = purple_input_add(bconv->socket, PURPLE_INPUT_WRITE, _send_data_write_cb, pb); - purple_circ_buffer_append(bconv->tx_buf, message + ret, len - ret); + purple_circular_buffer_append(bconv->tx_buf, message + ret, len - ret); } return ret; @@ -396,7 +396,7 @@ static void bonjour_jabber_stream_ended(BonjourJabberConversation *bconv) { #if 0 if(bconv->pb != NULL) { PurpleConversation *conv; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bconv->pb->name, bconv->pb->account); + conv = purple_conversations_find_im_with_account(bconv->pb->name, bconv->pb->account); if (conv != NULL) { char *tmp = g_strdup_printf(_("%s has closed the conversation."), bconv->pb->name); purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); @@ -485,7 +485,7 @@ _start_stream(gpointer data, gint source, PurpleInputCondition condition) purple_debug_error("bonjour", "Error starting stream with buddy %s at %s error: %s\n", bname ? bname : "(unknown)", bconv->ip, err ? err : "(null)"); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bname, bconv->account); + conv = PURPLE_CONVERSATION(purple_conversations_find_im_with_account(bname, bconv->account)); if (conv != NULL) purple_conversation_write(conv, NULL, _("Unable to send the message, the conversation couldn't be started."), @@ -550,7 +550,7 @@ static gboolean bonjour_jabber_send_stream_init(BonjourJabberConversation *bconv if (bconv->pb) { PurpleConversation *conv; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bname, bconv->account); + conv = PURPLE_CONVERSATION(purple_conversations_find_im_with_account(bname, bconv->account)); if (conv != NULL) purple_conversation_write(conv, NULL, _("Unable to send the message, the conversation couldn't be started."), @@ -595,7 +595,7 @@ void bonjour_jabber_stream_started(BonjourJabberConversation *bconv) { if (bconv->pb) { PurpleConversation *conv; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bname, bconv->account); + conv = PURPLE_CONVERSATION(purple_conversations_find_im_with_account(bname, bconv->account)); if (conv != NULL) purple_conversation_write(conv, NULL, _("Unable to send the message, the conversation couldn't be started."), @@ -616,7 +616,7 @@ void bonjour_jabber_stream_started(BonjourJabberConversation *bconv) { /* If the stream has been completely started and we know who we're talking to, we can start doing stuff. */ /* I don't think the circ_buffer can actually contain anything without a buddy being associated, but lets be explicit. */ if (bconv->sent_stream_start == FULLY_SENT && bconv->recv_stream_start - && bconv->pb && purple_circ_buffer_get_max_read(bconv->tx_buf) > 0) { + && bconv->pb && purple_circular_buffer_get_max_read(bconv->tx_buf) > 0) { /* Watch for when we can write the buffered messages */ bconv->tx_handler = purple_input_add(bconv->socket, PURPLE_INPUT_WRITE, _send_data_write_cb, bconv->pb); @@ -680,7 +680,7 @@ _server_socket_handler(gpointer data, int server_socket, PurpleInputCondition co mbba = g_new0(struct _match_buddies_by_address_t, 1); mbba->address = address_text; - buddies = purple_find_buddies(jdata->account, NULL); + buddies = purple_blist_find_buddies(jdata->account, NULL); g_slist_foreach(buddies, _match_buddies_by_address, mbba); g_slist_free(buddies); @@ -872,7 +872,7 @@ _connected_to_buddy(gpointer data, gint source, const gchar *error) purple_debug_error("bonjour", "No more addresses for buddy %s. Aborting", purple_buddy_get_name(pb)); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, account); + conv = PURPLE_CONVERSATION(purple_conversations_find_im_with_account(bb->name, account)); if (conv != NULL) purple_conversation_write(conv, NULL, _("Unable to send the message, the conversation couldn't be started."), @@ -893,7 +893,7 @@ _connected_to_buddy(gpointer data, gint source, const gchar *error) account = purple_buddy_get_account(pb); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, account); + conv = PURPLE_CONVERSATION(purple_conversations_find_im_with_account(bb->name, account)); if (conv != NULL) purple_conversation_write(conv, NULL, _("Unable to send the message, the conversation couldn't be started."), @@ -919,7 +919,7 @@ bonjour_jabber_conv_match_by_name(BonjourJabberConversation *bconv) { g_return_if_fail(bconv->ip != NULL); g_return_if_fail(bconv->pb == NULL); - pb = purple_find_buddy(bconv->account, bconv->buddy_name); + pb = purple_blist_find_buddy(bconv->account, bconv->buddy_name); if (pb && (bb = purple_buddy_get_protocol_data(pb))) { const char *ip; GSList *tmp = bb->ips; @@ -975,7 +975,7 @@ bonjour_jabber_conv_match_by_ip(BonjourJabberConversation *bconv) { mbba = g_new0(struct _match_buddies_by_address_t, 1); mbba->address = bconv->ip; - buddies = purple_find_buddies(jdata->account, NULL); + buddies = purple_blist_find_buddies(jdata->account, NULL); g_slist_foreach(buddies, _match_buddies_by_address, mbba); g_slist_free(buddies); @@ -1024,7 +1024,7 @@ _find_or_start_conversation(BonjourJabber *jdata, const gchar *to) g_return_val_if_fail(jdata != NULL, NULL); g_return_val_if_fail(to != NULL, NULL); - pb = purple_find_buddy(jdata->account, to); + pb = purple_blist_find_buddy(jdata->account, to); if (pb == NULL || (bb = purple_buddy_get_protocol_data(pb)) == NULL) /* You can not send a message to an offline buddy */ return NULL; @@ -1189,7 +1189,7 @@ bonjour_jabber_close_conversation(BonjourJabberConversation *bconv) purple_input_remove(bconv->tx_handler); /* Free all the data related to the conversation */ - purple_circ_buffer_destroy(bconv->tx_buf); + g_object_unref(G_OBJECT(bconv->tx_buf)); if (bconv->connect_data != NULL) purple_proxy_connect_cancel(bconv->connect_data); if (bconv->stream_data != NULL) { @@ -1227,12 +1227,12 @@ bonjour_jabber_stop(BonjourJabber *jdata) if (!purple_account_is_disconnected(jdata->account)) { GSList *buddies, *l; - buddies = purple_find_buddies(jdata->account, NULL); + buddies = purple_blist_find_buddies(jdata->account, NULL); for (l = buddies; l; l = l->next) { BonjourBuddy *bb = purple_buddy_get_protocol_data((PurpleBuddy*) l->data); if (bb && bb->conversation) { /* Any ongoing connection attempt is cancelled - * by _purple_connection_destroy */ + * when a connection is destroyed */ bb->conversation->connect_data = NULL; bonjour_jabber_close_conversation(bb->conversation); bb->conversation = NULL; @@ -1303,7 +1303,7 @@ check_if_blocked(PurpleBuddy *pb) acc = purple_buddy_get_account(pb); - for(l = acc->deny; l != NULL; l = l->next) { + for(l = purple_account_privacy_get_denied(acc); l != NULL; l = l->next) { const gchar *name = purple_buddy_get_name(pb); const gchar *username = bonjour_get_jid(acc); diff --git a/libpurple/protocols/bonjour/jabber.h b/libpurple/protocols/bonjour/jabber.h index 4096497008..e0a1d0a2cd 100644 --- a/libpurple/protocols/bonjour/jabber.h +++ b/libpurple/protocols/bonjour/jabber.h @@ -31,7 +31,7 @@ #include "xmlnode.h" #include "account.h" -#include "circbuffer.h" +#include "circularbuffer.h" typedef struct _BonjourJabber { @@ -50,7 +50,7 @@ typedef struct _BonjourJabberConversation guint rx_handler; guint tx_handler; guint close_timeout; - PurpleCircBuffer *tx_buf; + PurpleCircularBuffer *tx_buf; int sent_stream_start; /* 0 = Unsent, 1 = Partial, 2 = Complete */ gboolean recv_stream_start; PurpleProxyConnectData *connect_data; diff --git a/libpurple/protocols/bonjour/mdns_avahi.c b/libpurple/protocols/bonjour/mdns_avahi.c index 07dc63e161..b921ce7acf 100644 --- a/libpurple/protocols/bonjour/mdns_avahi.c +++ b/libpurple/protocols/bonjour/mdns_avahi.c @@ -122,7 +122,7 @@ _resolver_callback(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtoco g_return_if_fail(r != NULL); - pb = purple_find_buddy(account, name); + pb = purple_blist_find_buddy(account, name); bb = (pb != NULL) ? purple_buddy_get_protocol_data(pb) : NULL; switch (event) { @@ -266,7 +266,7 @@ _browser_callback(AvahiServiceBrowser *b, AvahiIfIndex interface, break; case AVAHI_BROWSER_REMOVE: purple_debug_info("bonjour", "_browser_callback - Remove service\n"); - pb = purple_find_buddy(account, name); + pb = purple_blist_find_buddy(account, name); if (pb != NULL) { BonjourBuddy *bb = purple_buddy_get_protocol_data(pb); AvahiBuddyImplData *b_impl; diff --git a/libpurple/protocols/bonjour/mdns_win32.c b/libpurple/protocols/bonjour/mdns_win32.c index d7ee2e8e86..7cade1986b 100644 --- a/libpurple/protocols/bonjour/mdns_win32.c +++ b/libpurple/protocols/bonjour/mdns_win32.c @@ -176,7 +176,7 @@ _mdns_resolve_host_callback(DNSServiceRef sdRef, DNSServiceFlags flags, g_free(args->resolver_query); args->resolver_query = NULL; - if ((pb = purple_find_buddy(args->account, args->res_data->name))) { + if ((pb = purple_blist_find_buddy(args->account, args->res_data->name))) { if (purple_buddy_get_protocol_data(pb) != args->bb) { purple_debug_error("bonjour", "Found purple buddy for %s not matching bonjour buddy record.", args->res_data->name); @@ -293,7 +293,7 @@ _mdns_service_resolve_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint3 if (idata->resolvers == NULL) { PurpleBuddy *pb; /* See if this is now attached to a PurpleBuddy */ - if ((pb = purple_find_buddy(args->account, args->bb->name))) + if ((pb = purple_blist_find_buddy(args->account, args->bb->name))) bonjour_buddy_signed_off(pb); else { /* Remove from the pending list */ @@ -347,7 +347,7 @@ _mdns_service_browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32 Win32BuddyImplData *idata; /* Is there an existing buddy? */ - if ((pb = purple_find_buddy(account, serviceName))) + if ((pb = purple_blist_find_buddy(account, serviceName))) bb = purple_buddy_get_protocol_data(pb); /* Is there a pending buddy? */ else { @@ -403,7 +403,7 @@ _mdns_service_browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32 serviceName, interfaceIndex, regtype ? regtype : "", replyDomain ? replyDomain : ""); - pb = purple_find_buddy(account, serviceName); + pb = purple_blist_find_buddy(account, serviceName); if (pb != NULL) { GSList *l; /* There may be multiple presences, we should only get rid of this one */ diff --git a/libpurple/protocols/gg/Makefile.am b/libpurple/protocols/gg/Makefile.am index ecfcd72ca8..6c1904bedd 100644 --- a/libpurple/protocols/gg/Makefile.am +++ b/libpurple/protocols/gg/Makefile.am @@ -55,8 +55,8 @@ GGSOURCES = \ utils.c \ confer.h \ confer.c \ - buddylist.h \ - buddylist.c \ + blist.h \ + blist.c \ gg.h \ gg.c \ resolver-purple.h \ diff --git a/libpurple/protocols/gg/avatar.c b/libpurple/protocols/gg/avatar.c index 07a26ccde5..763fa51c87 100644 --- a/libpurple/protocols/gg/avatar.c +++ b/libpurple/protocols/gg/avatar.c @@ -191,7 +191,7 @@ static gboolean ggp_avatar_buddy_update_next(PurpleConnection *gc) pending_update = pending_update_it->data; avdata->pending_updates = g_list_remove(avdata->pending_updates, pending_update); - buddy = purple_find_buddy(account, ggp_uin_to_str(pending_update->uin)); + buddy = purple_blist_find_buddy(account, ggp_uin_to_str(pending_update->uin)); if (!buddy) { @@ -286,7 +286,7 @@ static void ggp_avatar_buddy_update_received(PurpleHttpConnection *http_conn, } account = purple_connection_get_account(gc); - buddy = purple_find_buddy(account, ggp_uin_to_str(pending_update->uin)); + buddy = purple_blist_find_buddy(account, ggp_uin_to_str(pending_update->uin)); if (!buddy) { diff --git a/libpurple/protocols/gg/buddylist.c b/libpurple/protocols/gg/blist.c index eaeb40305e..72d9e98f12 100644 --- a/libpurple/protocols/gg/buddylist.c +++ b/libpurple/protocols/gg/blist.c @@ -26,7 +26,7 @@ #include "gg.h" #include "utils.h" -#include "buddylist.h" +#include "blist.h" #define F_FIRSTNAME 0 #define F_LASTNAME 1 @@ -48,13 +48,13 @@ void ggp_buddylist_send(PurpleConnection *gc) int i = 0, ret = 0; int size; - buddies = purple_find_buddies(account, NULL); + buddies = purple_blist_find_buddies(account, NULL); size = g_slist_length(buddies); userlist = g_new(uin_t, size); types = g_new(gchar, size); - for (buddies = purple_find_buddies(account, NULL); buddies; + for (buddies = purple_blist_find_buddies(account, NULL); buddies; buddies = g_slist_delete_link(buddies, buddies), ++i) { PurpleBuddy *buddy = buddies->data; @@ -118,7 +118,7 @@ void ggp_buddylist_load(PurpleConnection *gc, char *buddylist) purple_debug_info("gg", "got buddy: name=%s; show=%s\n", name, show); - if (purple_find_buddy(purple_connection_get_account(gc), name)) { + if (purple_blist_find_buddy(purple_connection_get_account(gc), name)) { g_strfreev(data_tbl); continue; } @@ -139,7 +139,7 @@ void ggp_buddylist_load(PurpleConnection *gc, char *buddylist) buddy = purple_buddy_new(purple_connection_get_account(gc), name, strlen(show) ? show : NULL); - if (!(group = purple_find_group(g))) { + if (!(group = purple_blist_find_group(g))) { group = purple_group_new(g); purple_blist_add_group(group, NULL); } @@ -163,7 +163,7 @@ char *ggp_buddylist_dump(PurpleAccount *account) GString *buddylist = g_string_sized_new(1024); char *ptr; - for (buddies = purple_find_buddies(account, NULL); buddies; + for (buddies = purple_blist_find_buddies(account, NULL); buddies; buddies = g_slist_delete_link(buddies, buddies)) { PurpleBuddy *buddy = buddies->data; PurpleGroup *group = purple_buddy_get_group(buddy); @@ -189,7 +189,7 @@ char *ggp_buddylist_dump(PurpleAccount *account) const char * ggp_buddylist_get_buddy_name(PurpleConnection *gc, const uin_t uin) { const char *uin_s = ggp_uin_to_str(uin); - PurpleBuddy *buddy = purple_find_buddy( + PurpleBuddy *buddy = purple_blist_find_buddy( purple_connection_get_account(gc), uin_s); if (buddy != NULL) diff --git a/libpurple/protocols/gg/buddylist.h b/libpurple/protocols/gg/blist.h index 70fdf41692..ca07212328 100644 --- a/libpurple/protocols/gg/buddylist.h +++ b/libpurple/protocols/gg/blist.h @@ -1,5 +1,5 @@ /** - * @file buddylist.h + * @file blist.h * * purple * diff --git a/libpurple/protocols/gg/confer.c b/libpurple/protocols/gg/confer.c index 25406af301..12007ded23 100644 --- a/libpurple/protocols/gg/confer.c +++ b/libpurple/protocols/gg/confer.c @@ -27,12 +27,12 @@ #include "confer.h" /* PurpleConversation *ggp_confer_find_by_name(PurpleConnection *gc, const gchar *name) {{{ */ -PurpleConversation *ggp_confer_find_by_name(PurpleConnection *gc, const gchar *name) +PurpleChatConversation *ggp_confer_find_by_name(PurpleConnection *gc, const gchar *name) { g_return_val_if_fail(gc != NULL, NULL); g_return_val_if_fail(name != NULL, NULL); - return purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, name, + return purple_conversations_find_chat_with_account(name, purple_connection_get_account(gc)); } /* }}} */ @@ -41,7 +41,7 @@ PurpleConversation *ggp_confer_find_by_name(PurpleConnection *gc, const gchar *n void ggp_confer_participants_add_uin(PurpleConnection *gc, const gchar *chat_name, const uin_t uin) { - PurpleConversation *conv; + PurpleChatConversation *conv; GGPInfo *info = purple_connection_get_protocol_data(gc); GGPChat *chat; GList *l; @@ -59,8 +59,8 @@ void ggp_confer_participants_add_uin(PurpleConnection *gc, const gchar *chat_nam str_uin = g_strdup_printf("%lu", (unsigned long int)uin); conv = ggp_confer_find_by_name(gc, chat_name); - purple_conv_chat_add_user(PURPLE_CONV_CHAT(conv), str_uin, NULL, - PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(conv, str_uin, NULL, + PURPLE_CHAT_USER_NONE, TRUE); g_free(str_uin); } @@ -85,7 +85,7 @@ void ggp_confer_participants_add(PurpleConnection *gc, const gchar *chat_name, continue; for (i = 0; i < count; i++) { - PurpleConversation *conv; + PurpleChatConversation *conv; if (g_list_find(chat->participants, GINT_TO_POINTER(recipients[i])) != NULL) { @@ -97,9 +97,8 @@ void ggp_confer_participants_add(PurpleConnection *gc, const gchar *chat_name, str_uin = g_strdup_printf("%lu", (unsigned long int)recipients[i]); conv = ggp_confer_find_by_name(gc, chat_name); - purple_conv_chat_add_user(PURPLE_CONV_CHAT(conv), - str_uin, NULL, - PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(conv, str_uin, NULL, + PURPLE_CHAT_USER_NONE, TRUE); g_free(str_uin); } break; diff --git a/libpurple/protocols/gg/confer.h b/libpurple/protocols/gg/confer.h index 37e93df128..003b22d77c 100644 --- a/libpurple/protocols/gg/confer.h +++ b/libpurple/protocols/gg/confer.h @@ -34,7 +34,7 @@ * * @return PurpleConversation or NULL if not found. */ -PurpleConversation * +PurpleChatConversation * ggp_confer_find_by_name(PurpleConnection *gc, const gchar *name); /** diff --git a/libpurple/protocols/gg/gg.c b/libpurple/protocols/gg/gg.c index 98087588d5..93fffdba00 100644 --- a/libpurple/protocols/gg/gg.c +++ b/libpurple/protocols/gg/gg.c @@ -31,7 +31,7 @@ #include "plugin.h" #include "version.h" #include "notify.h" -#include "blist.h" +#include "buddylist.h" #include "accountopt.h" #include "debug.h" #include "util.h" @@ -41,7 +41,7 @@ #include "gg.h" #include "confer.h" #include "search.h" -#include "buddylist.h" +#include "blist.h" #include "utils.h" #include "resolver-purple.h" #include "account.h" @@ -273,7 +273,7 @@ static void ggp_rem_deny(PurpleConnection *gc, const char *who) void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event_msg *ev, gboolean multilogon) { GGPInfo *info = purple_connection_get_protocol_data(gc); - PurpleConversation *conv; + PurpleChatConversation *chat; gchar *from; gchar *msg; gchar *tmp; @@ -415,13 +415,12 @@ void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event_msg *e purple_debug_warning("gg", "ggp_recv_message_handler: conference multilogon messages are not yet handled\n"); } else if (multilogon) { PurpleAccount *account = purple_connection_get_account(gc); - PurpleConversation *conv; + PurpleIMConversation *im; const gchar *who = ggp_uin_to_str(ev->sender); // not really sender - conv = purple_find_conversation_with_account( - PURPLE_CONV_TYPE_IM, who, account); - if (conv == NULL) - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, who); - purple_conversation_write(conv, purple_account_get_username(account), msg, PURPLE_MESSAGE_SEND, mtime); + im = purple_conversations_find_im_with_account(who, account); + if (im == NULL) + im = purple_im_conversation_new(account, who); + purple_conversation_write(PURPLE_CONVERSATION(im), purple_account_get_username(account), msg, PURPLE_MESSAGE_SEND, mtime); } else if (ev->recipients_count == 0) { serv_got_im(gc, from, msg, 0, mtime); } else { @@ -443,8 +442,8 @@ void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event_msg *e ev->recipients, ev->recipients_count); } - conv = ggp_confer_find_by_name(gc, chat_name); - chat_id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)); + chat = ggp_confer_find_by_name(gc, chat_name); + chat_id = purple_chat_conversation_get_id(chat); serv_got_chat_in(gc, chat_id, ggp_buddylist_get_buddy_name(gc, ev->sender), @@ -459,7 +458,7 @@ static void ggp_typing_notification_handler(PurpleConnection *gc, uin_t uin, int from = g_strdup_printf("%u", uin); if (length) - serv_got_typing(gc, from, 0, PURPLE_TYPING); + serv_got_typing(gc, from, 0, PURPLE_IM_TYPING); else serv_got_typing_stopped(gc, from); g_free(from); @@ -689,7 +688,7 @@ static void ggp_async_login_handler(gpointer _gc, gint fd, PurpleInputCondition ggp_callback_recv, gc); purple_connection_update_progress(gc, _("Connected"), 1, 2); - purple_connection_set_state(gc, PURPLE_CONNECTED); + purple_connection_set_state(gc, PURPLE_CONNECTION_CONNECTED); ggp_buddylist_send(gc); ggp_roster_request_update(gc); @@ -837,7 +836,7 @@ static GList *ggp_blist_node_menu(PurpleBlistNode *node) PurpleConnection *gc; GGPInfo *info; - if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (!PURPLE_IS_BUDDY(node)) return NULL; account = purple_buddy_get_account((PurpleBuddy *) node); @@ -1027,7 +1026,7 @@ static int ggp_send_im(PurpleConnection *gc, const char *who, const char *msg, GData *attribs; const char *start, *end = NULL, *last; ggp_buddy_data *buddy_data = ggp_buddy_get_data( - purple_find_buddy(purple_connection_get_account(gc), who)); + purple_blist_find_buddy(purple_connection_get_account(gc), who)); if (msg == NULL || *msg == '\0') { return 0; @@ -1084,11 +1083,10 @@ static int ggp_send_im(PurpleConnection *gc, const char *who, const char *msg, } else if (prepare_result == GGP_IMAGE_PREPARE_TOO_BIG) { - PurpleConversation *conv = - purple_find_conversation_with_account( - PURPLE_CONV_TYPE_IM, who, + PurpleIMConversation *im = + purple_conversations_find_im_with_account(who, purple_connection_get_account(gc)); - purple_conversation_write(conv, "", + purple_conversation_write(PURPLE_CONVERSATION(im), "", _("Image is too large, please try " "smaller one."), PURPLE_MESSAGE_ERROR, time(NULL)); @@ -1141,17 +1139,17 @@ static int ggp_send_im(PurpleConnection *gc, const char *who, const char *msg, return ret; } -static unsigned int ggp_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state) +static unsigned int ggp_send_typing(PurpleConnection *gc, const char *name, PurpleIMTypingState state) { GGPInfo *info = purple_connection_get_protocol_data(gc); int dummy_length; // we don't send real length of typed message - if (state == PURPLE_TYPED) // not supported + if (state == PURPLE_IM_TYPED) // not supported return 1; - if (state == PURPLE_TYPING) + if (state == PURPLE_IM_TYPING) dummy_length = (int)g_random_int(); - else // PURPLE_NOT_TYPING + else // PURPLE_IM_NOT_TYPING dummy_length = 0; gg_typing_notification( @@ -1193,7 +1191,7 @@ static void ggp_join_chat(PurpleConnection *gc, GHashTable *data) GGPChat *chat; char *chat_name; GList *l; - PurpleConversation *conv; + PurpleChatConversation *conv; PurpleAccount *account = purple_connection_get_account(gc); chat_name = g_hash_table_lookup(data, "name"); @@ -1215,9 +1213,8 @@ static void ggp_join_chat(PurpleConnection *gc, GHashTable *data) ggp_confer_add_new(gc, chat_name); conv = serv_got_joined_chat(gc, info->chats_count, chat_name); - purple_conv_chat_add_user(PURPLE_CONV_CHAT(conv), - purple_account_get_username(account), NULL, - PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(conv, purple_account_get_username(account), + NULL, PURPLE_CHAT_USER_NONE, TRUE); } static char *ggp_get_chat_name(GHashTable *data) { @@ -1226,7 +1223,7 @@ static char *ggp_get_chat_name(GHashTable *data) { static int ggp_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags) { - PurpleConversation *conv; + PurpleChatConversation *conv; GGPInfo *info = purple_connection_get_protocol_data(gc); GGPChat *chat = NULL; GList *l; @@ -1235,13 +1232,14 @@ static int ggp_chat_send(PurpleConnection *gc, int id, const char *message, Purp uin_t *uins; int count = 0; - if ((conv = purple_find_chat(gc, id)) == NULL) + if ((conv = purple_conversations_find_chat(gc, id)) == NULL) return -EINVAL; for (l = info->chats; l != NULL; l = l->next) { chat = l->data; - if (g_utf8_collate(chat->name, purple_conversation_get_name(conv)) == 0) { + if (g_utf8_collate(chat->name, purple_conversation_get_name( + PURPLE_CONVERSATION(conv))) == 0) { break; } diff --git a/libpurple/protocols/gg/image.c b/libpurple/protocols/gg/image.c index 20b26b6be7..f8d3afeb46 100644 --- a/libpurple/protocols/gg/image.c +++ b/libpurple/protocols/gg/image.c @@ -290,9 +290,8 @@ void ggp_image_send(PurpleConnection *gc, purple_imgstore_get_size(image)); purple_imgstore_unref(image); - conv = purple_find_conversation_with_account( - PURPLE_CONV_TYPE_IM, pending_image->conv_name, - purple_connection_get_account(gc)); + conv = PURPLE_CONVERSATION(purple_conversations_find_im_with_account( + pending_image->conv_name, purple_connection_get_account(gc))); if (conv != NULL) purple_conversation_write(conv, "", _("Image delivered."), PURPLE_MESSAGE_NO_LOG | PURPLE_MESSAGE_NOTIFY, diff --git a/libpurple/protocols/gg/oauth/oauth.c b/libpurple/protocols/gg/oauth/oauth.c index 3fc3a570c7..7440593e75 100644 --- a/libpurple/protocols/gg/oauth/oauth.c +++ b/libpurple/protocols/gg/oauth/oauth.c @@ -26,7 +26,8 @@ #include "oauth.h" #include "oauth-parameter.h" -#include <cipher.h> +#include "ciphers/hmaccipher.h" +#include "ciphers/sha1hash.h" char *gg_oauth_static_nonce; /* dla unit testów */ char *gg_oauth_static_timestamp; /* dla unit testów */ @@ -48,15 +49,19 @@ static void gg_oauth_generate_nonce(char *buf, int len) static gchar *gg_hmac_sha1(const char *key, const char *message) { - PurpleCipherContext *context; + PurpleCipher *cipher; + PurpleHash *hash; guchar digest[20]; - - context = purple_cipher_context_new_by_name("hmac", NULL); - purple_cipher_context_set_option(context, "hash", "sha1"); - purple_cipher_context_set_key(context, (guchar *)key, strlen(key)); - purple_cipher_context_append(context, (guchar *)message, strlen(message)); - purple_cipher_context_digest(context, digest, sizeof(digest)); - purple_cipher_context_destroy(context); + + hash = purple_sha1_hash_new(); + cipher = purple_hmac_cipher_new(hash); + + purple_cipher_set_key(cipher, (guchar *)key, strlen(key)); + purple_cipher_append(cipher, (guchar *)message, strlen(message)); + purple_cipher_digest(cipher, digest, sizeof(digest)); + + g_object_unref(cipher); + g_object_unref(hash); return purple_base64_encode(digest, sizeof(digest)); } diff --git a/libpurple/protocols/gg/pubdir-prpl.c b/libpurple/protocols/gg/pubdir-prpl.c index 35ecf4b6a6..1065f27a4e 100644 --- a/libpurple/protocols/gg/pubdir-prpl.c +++ b/libpurple/protocols/gg/pubdir-prpl.c @@ -389,7 +389,7 @@ static void ggp_pubdir_get_info_prpl_got(PurpleConnection *gc, g_assert(uin == record->uin); g_assert(records_count == 1); - buddy = purple_find_buddy(purple_connection_get_account(gc), + buddy = purple_blist_find_buddy(purple_connection_get_account(gc), ggp_uin_to_str(uin)); if (buddy) { @@ -778,8 +778,8 @@ static void ggp_pubdir_search_results_add(PurpleConnection *gc, GList *row, static void ggp_pubdir_search_results_im(PurpleConnection *gc, GList *row, gpointer _form) { - purple_conversation_present(purple_conversation_new(PURPLE_CONV_TYPE_IM, - purple_connection_get_account(gc), g_list_nth_data(row, 0))); + purple_conversation_present(PURPLE_CONVERSATION(purple_im_conversation_new( + purple_connection_get_account(gc), g_list_nth_data(row, 0)))); } static void ggp_pubdir_search_results_info(PurpleConnection *gc, GList *row, diff --git a/libpurple/protocols/gg/purplew.c b/libpurple/protocols/gg/purplew.c index fa96294509..9f134299ae 100644 --- a/libpurple/protocols/gg/purplew.c +++ b/libpurple/protocols/gg/purplew.c @@ -103,16 +103,16 @@ GList * ggp_purplew_group_get_buddies(PurpleGroup *group, PurpleAccount *account gnode = PURPLE_BLIST_NODE(group); for (cnode = gnode->child; cnode; cnode = cnode->next) { - if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) + if (!PURPLE_IS_CONTACT(cnode)) continue; for (bnode = cnode->child; bnode; bnode = bnode->next) { PurpleBuddy *buddy; - if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + if (!PURPLE_IS_BUDDY(bnode)) continue; buddy = PURPLE_BUDDY(bnode); - if (account == NULL || buddy->account == account) + if (account == NULL || purple_buddy_get_account(buddy) == account) buddies = g_list_append(buddies, buddy); } } @@ -130,7 +130,7 @@ GList * ggp_purplew_account_get_groups(PurpleAccount *account, gboolean exclusiv GSList *accounts; gboolean have_specified = FALSE, have_others = FALSE; - if (!PURPLE_BLIST_NODE_IS_GROUP(bnode)) + if (!PURPLE_IS_GROUP(bnode)) continue; group = PURPLE_GROUP(bnode); diff --git a/libpurple/protocols/gg/roster.c b/libpurple/protocols/gg/roster.c index 27777014a2..6bf4abdb02 100644 --- a/libpurple/protocols/gg/roster.c +++ b/libpurple/protocols/gg/roster.c @@ -361,7 +361,7 @@ void ggp_roster_alias_buddy(PurpleConnection *gc, const char *who, purple_debug_misc("gg", "ggp_roster_alias_buddy(\"%s\", \"%s\")\n", who, alias); - buddy = purple_find_buddy(purple_connection_get_account(gc), who); + buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who); g_return_if_fail(buddy != NULL); ggp_roster_set_synchronized(gc, buddy, FALSE); @@ -382,7 +382,7 @@ void ggp_roster_group_buddy(PurpleConnection *gc, const char *who, "who=\"%s\", group=\"%s\" -> \"%s\")\n", who, old_group, new_group); - // purple_find_buddy(..., who) is not accessible at this moment + // purple_blist_find_buddy(..., who) is not accessible at this moment change->type = GGP_ROSTER_CHANGE_CONTACT_UPDATE; change->data.uin = ggp_str_to_uin(who); rdata->pending_updates = g_list_append(rdata->pending_updates, change); @@ -538,7 +538,7 @@ static gboolean ggp_roster_reply_list_read_buddy(PurpleConnection *gc, } if (group_name) { - group = purple_find_group(group_name); + group = purple_blist_find_group(group_name); if (!group) { group = purple_group_new(group_name); @@ -547,7 +547,7 @@ static gboolean ggp_roster_reply_list_read_buddy(PurpleConnection *gc, } // add buddy, if doesn't exists - buddy = purple_find_buddy(account, ggp_uin_to_str(uin)); + buddy = purple_blist_find_buddy(account, ggp_uin_to_str(uin)); g_hash_table_remove(remove_buddies, GINT_TO_POINTER(uin)); if (!buddy) { @@ -587,7 +587,7 @@ static gboolean ggp_roster_reply_list_read_buddy(PurpleConnection *gc, purple_buddy_get_alias(buddy), alias, currentGroup, group, group_name); if (alias_changed) - purple_blist_alias_buddy(buddy, alias); + purple_buddy_set_local_alias(buddy, alias); if (currentGroup != group) purple_blist_add_buddy(buddy, NULL, group, NULL); @@ -666,7 +666,7 @@ static void ggp_roster_reply_list(PurpleConnection *gc, uint32_t version, // we will: // - remove synchronized ones, if not found in list at server // - upload not synchronized ones - local_buddies = purple_find_buddies(account, NULL); + local_buddies = purple_blist_find_buddies(account, NULL); remove_buddies = g_hash_table_new(g_direct_hash, g_direct_equal); while (local_buddies) { @@ -733,7 +733,7 @@ static void ggp_roster_reply_list(PurpleConnection *gc, uint32_t version, { PurpleGroup *group = it->data; it = g_list_next(it); - if (purple_blist_get_group_size(group, TRUE) != 0) + if (purple_counting_node_get_total_size(PURPLE_COUNTING_NODE(group)) != 0) continue; purple_debug_info("gg", "ggp_roster_reply_list: " "removing group %s\n", purple_group_get_name(group)); @@ -829,7 +829,7 @@ static gboolean ggp_roster_send_update_contact_update(PurpleConnection *gc, g_return_val_if_fail(change->type == GGP_ROSTER_CHANGE_CONTACT_UPDATE, FALSE); - buddy = purple_find_buddy(account, ggp_uin_to_str(uin)); + buddy = purple_blist_find_buddy(account, ggp_uin_to_str(uin)); if (!buddy) return TRUE; buddy_node = g_hash_table_lookup(content->contact_nodes, @@ -897,7 +897,7 @@ static gboolean ggp_roster_send_update_contact_remove(PurpleConnection *gc, g_return_val_if_fail(change->type == GGP_ROSTER_CHANGE_CONTACT_REMOVE, FALSE); - buddy = purple_find_buddy(account, ggp_uin_to_str(uin)); + buddy = purple_blist_find_buddy(account, ggp_uin_to_str(uin)); if (buddy) { purple_debug_info("gg", "ggp_roster_send_update_contact_remove:" @@ -940,7 +940,7 @@ static gboolean ggp_roster_send_update_group_rename(PurpleConnection *gc, { PurpleGroup *group; GList *group_buddies; - group = purple_find_group(new_name); + group = purple_blist_find_group(new_name); if (!group) return TRUE; purple_debug_info("gg", "ggp_roster_send_update_group_rename: " @@ -1058,7 +1058,7 @@ static void ggp_roster_reply_ack(PurpleConnection *gc, uint32_t version) if (change->type != GGP_ROSTER_CHANGE_CONTACT_UPDATE) continue; - buddy = purple_find_buddy(account, + buddy = purple_blist_find_buddy(account, ggp_uin_to_str(change->data.uin)); if (buddy) ggp_roster_set_synchronized(gc, buddy, TRUE); @@ -1076,7 +1076,7 @@ static void ggp_roster_reply_ack(PurpleConnection *gc, uint32_t version) if (change->type != GGP_ROSTER_CHANGE_CONTACT_UPDATE) continue; - buddy = purple_find_buddy(account, + buddy = purple_blist_find_buddy(account, ggp_uin_to_str(change->data.uin)); if (buddy && ggp_roster_is_synchronized(buddy)) ggp_roster_set_synchronized(gc, buddy, FALSE); diff --git a/libpurple/protocols/gg/status.c b/libpurple/protocols/gg/status.c index afedd2b70d..af5ead7800 100644 --- a/libpurple/protocols/gg/status.c +++ b/libpurple/protocols/gg/status.c @@ -90,32 +90,32 @@ GList * ggp_status_types(PurpleAccount *account) types = g_list_append(types, purple_status_type_new_with_attrs( PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL)); + purple_g_value_new(G_TYPE_STRING), NULL)); types = g_list_append(types, purple_status_type_new_with_attrs( PURPLE_STATUS_AVAILABLE, "freeforchat", _("Chatty"), TRUE, TRUE, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL)); + purple_g_value_new(G_TYPE_STRING), NULL)); types = g_list_append(types, purple_status_type_new_with_attrs( PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL)); + purple_g_value_new(G_TYPE_STRING), NULL)); types = g_list_append(types, purple_status_type_new_with_attrs( PURPLE_STATUS_UNAVAILABLE, NULL, NULL, TRUE, TRUE, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL)); + purple_g_value_new(G_TYPE_STRING), NULL)); types = g_list_append(types, purple_status_type_new_with_attrs( PURPLE_STATUS_INVISIBLE, NULL, NULL, TRUE, TRUE, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL)); + purple_g_value_new(G_TYPE_STRING), NULL)); types = g_list_append(types, purple_status_type_new_with_attrs( PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE, TRUE, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL)); + purple_g_value_new(G_TYPE_STRING), NULL)); return types; } @@ -403,7 +403,7 @@ void ggp_status_got_others_buddy(PurpleConnection *gc, uin_t uin, int status, const char *descr) { PurpleAccount *account = purple_connection_get_account(gc); - PurpleBuddy *buddy = purple_find_buddy(account, ggp_uin_to_str(uin)); + PurpleBuddy *buddy = purple_blist_find_buddy(account, ggp_uin_to_str(uin)); const gchar *purple_status = ggp_status_to_purplestatus(status); gchar *status_message = NULL; gboolean is_own; diff --git a/libpurple/protocols/irc/cmds.c b/libpurple/protocols/irc/cmds.c index 5a704a243f..be88b8519f 100644 --- a/libpurple/protocols/irc/cmds.c +++ b/libpurple/protocols/irc/cmds.c @@ -34,17 +34,14 @@ static void irc_do_mode(struct irc_conn *irc, const char *target, const char *si int irc_cmd_default(struct irc_conn *irc, const char *cmd, const char *target, const char **args) { - PurpleConversation *convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, target, irc->account); + PurpleConversation *convo = purple_conversations_find_with_account(target, irc->account); char *buf; if (!convo) return 1; buf = g_strdup_printf(_("Unknown command: %s"), cmd); - if (purple_conversation_get_type(convo) == PURPLE_CONV_TYPE_IM) - purple_conv_im_write(PURPLE_CONV_IM(convo), "", buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); - else - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "", buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); + purple_conversation_write_message(convo, "", buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); g_free(buf); return 1; @@ -132,19 +129,19 @@ int irc_cmd_ctcp_action(struct irc_conn *irc, const char *cmd, const char *targe g_free(newargs[1]); g_free(newargs); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, target, irc->account); + convo = purple_conversations_find_with_account(target, irc->account); if (convo) { escaped = g_markup_escape_text(args[0], -1); action = g_strdup_printf("/me %s", escaped); g_free(escaped); if (action[strlen(action) - 1] == '\n') action[strlen(action) - 1] = '\0'; - if (purple_conversation_get_type(convo) == PURPLE_CONV_TYPE_CHAT) - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), + if (PURPLE_IS_CHAT_CONVERSATION(convo)) + serv_got_chat_in(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(convo)), purple_connection_get_display_name(gc), PURPLE_MESSAGE_SEND, action, time(NULL)); else - purple_conv_im_write(PURPLE_CONV_IM(convo), purple_connection_get_display_name(gc), + purple_conversation_write_message(convo, purple_connection_get_display_name(gc), action, PURPLE_MESSAGE_SEND, time(NULL)); g_free(action); } @@ -200,13 +197,11 @@ int irc_cmd_join(struct irc_conn *irc, const char *cmd, const char *target, cons int irc_cmd_kick(struct irc_conn *irc, const char *cmd, const char *target, const char **args) { char *buf; - PurpleConversation *convo; if (!args || !args[0]) return 0; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, target, irc->account); - if (!convo) + if (!purple_conversations_find_chat_with_account(target, irc->account)) return 0; if (args[1]) @@ -446,20 +441,21 @@ int irc_cmd_quote(struct irc_conn *irc, const char *cmd, const char *target, con int irc_cmd_query(struct irc_conn *irc, const char *cmd, const char *target, const char **args) { - PurpleConversation *convo; + PurpleIMConversation *im; PurpleConnection *gc; if (!args || !args[0]) return 0; - convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, irc->account, args[0]); - purple_conversation_present(convo); + im = purple_im_conversation_new(irc->account, args[0]); + purple_conversation_present(PURPLE_CONVERSATION(im)); if (args[1]) { gc = purple_account_get_connection(irc->account); irc_cmd_privmsg(irc, cmd, target, args); - purple_conv_im_write(PURPLE_CONV_IM(convo), purple_connection_get_display_name(gc), - args[1], PURPLE_MESSAGE_SEND, time(NULL)); + purple_conversation_write_message(PURPLE_CONVERSATION(im), + purple_connection_get_display_name(gc), args[1], + PURPLE_MESSAGE_SEND, time(NULL)); } return 0; @@ -517,17 +513,17 @@ int irc_cmd_topic(struct irc_conn *irc, const char *cmd, const char *target, con { char *buf; const char *topic; - PurpleConversation *convo; + PurpleChatConversation *chat; if (!args) return 0; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, target, irc->account); - if (!convo) + chat = purple_conversations_find_chat_with_account(target, irc->account); + if (!chat) return 0; if (!args[0]) { - topic = purple_conv_chat_get_topic (PURPLE_CONV_CHAT(convo)); + topic = purple_chat_conversation_get_topic (chat); if (topic) { char *tmp, *tmp2; @@ -538,7 +534,8 @@ int irc_cmd_topic(struct irc_conn *irc, const char *cmd, const char *target, con g_free(tmp2); } else buf = g_strdup(_("No topic is set")); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), target, buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); + purple_conversation_write_message(PURPLE_CONVERSATION(chat), target, buf, + PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); g_free(buf); return 0; diff --git a/libpurple/protocols/irc/irc.c b/libpurple/protocols/irc/irc.c index dd287a0b6b..3f56dde06f 100644 --- a/libpurple/protocols/irc/irc.c +++ b/libpurple/protocols/irc/irc.c @@ -26,7 +26,7 @@ #include "internal.h" #include "accountopt.h" -#include "blist.h" +#include "buddylist.h" #include "conversation.h" #include "debug.h" #include "notify.h" @@ -111,8 +111,9 @@ irc_send_cb(gpointer data, gint source, PurpleInputCondition cond) { struct irc_conn *irc = data; int ret, writelen; + const gchar *buffer = NULL; - writelen = purple_circ_buffer_get_max_read(irc->outbuf); + writelen = purple_circular_buffer_get_max_read(irc->outbuf); if (writelen == 0) { purple_input_remove(irc->writeh); @@ -120,7 +121,9 @@ irc_send_cb(gpointer data, gint source, PurpleInputCondition cond) return; } - ret = do_send(irc, irc->outbuf->outptr, writelen); + buffer = purple_circular_buffer_get_output(irc->outbuf); + + ret = do_send(irc, buffer, writelen); if (ret < 0 && errno == EAGAIN) return; @@ -134,7 +137,7 @@ irc_send_cb(gpointer data, gint source, PurpleInputCondition cond) return; } - purple_circ_buffer_mark_read(irc->outbuf, ret); + purple_circular_buffer_mark_read(irc->outbuf, ret); #if 0 /* We *could* try to write more if we wrote it all */ @@ -183,7 +186,7 @@ int irc_send_len(struct irc_conn *irc, const char *buf, int buflen) irc->writeh = purple_input_add( irc->gsc ? irc->gsc->fd : irc->fd, PURPLE_INPUT_WRITE, irc_send_cb, irc); - purple_circ_buffer_append(irc->outbuf, tosend + ret, + purple_circular_buffer_append(irc->outbuf, tosend + ret, buflen - ret); } g_free(tosend); @@ -271,7 +274,7 @@ static GList *irc_status_types(PurpleAccount *account) type = purple_status_type_new_with_attrs( PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, type); @@ -332,7 +335,7 @@ static void irc_login(PurpleAccount *account) const char *username = purple_account_get_username(account); gc = purple_account_get_connection(account); - purple_connection_set_flags(gc, PURPLE_CONNECTION_NO_NEWLINES); + purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_NO_NEWLINES); if (strpbrk(username, " \t\v\r\n") != NULL) { purple_connection_error (gc, @@ -345,7 +348,7 @@ static void irc_login(PurpleAccount *account) purple_connection_set_protocol_data(gc, irc); irc->fd = -1; irc->account = account; - irc->outbuf = purple_circ_buffer_new(512); + irc->outbuf = purple_circular_buffer_new(512); userparts = g_strsplit(username, "@", 2); purple_connection_set_display_name(gc, userparts[0]); @@ -533,7 +536,7 @@ static void irc_close(PurpleConnection *gc) if (irc->writeh) purple_input_remove(irc->writeh); - purple_circ_buffer_destroy(irc->outbuf); + g_object_unref(G_OBJECT(irc->outbuf)); g_free(irc->mode_chars); g_free(irc->reqnick); @@ -758,7 +761,7 @@ static char *irc_get_chat_name(GHashTable *data) { static void irc_chat_invite(PurpleConnection *gc, int id, const char *message, const char *name) { struct irc_conn *irc = purple_connection_get_protocol_data(gc); - PurpleConversation *convo = purple_find_chat(gc, id); + PurpleConversation *convo = PURPLE_CONVERSATION(purple_conversations_find_chat(gc, id)); const char *args[2]; if (!convo) { @@ -774,7 +777,7 @@ static void irc_chat_invite(PurpleConnection *gc, int id, const char *message, c static void irc_chat_leave (PurpleConnection *gc, int id) { struct irc_conn *irc = purple_connection_get_protocol_data(gc); - PurpleConversation *convo = purple_find_chat(gc, id); + PurpleConversation *convo = PURPLE_CONVERSATION(purple_conversations_find_chat(gc, id)); const char *args[2]; if (!convo) @@ -789,7 +792,7 @@ static void irc_chat_leave (PurpleConnection *gc, int id) static int irc_chat_send(PurpleConnection *gc, int id, const char *what, PurpleMessageFlags flags) { struct irc_conn *irc = purple_connection_get_protocol_data(gc); - PurpleConversation *convo = purple_find_chat(gc, id); + PurpleConversation *convo = PURPLE_CONVERSATION(purple_conversations_find_chat(gc, id)); const char *args[2]; char *tmp; @@ -843,7 +846,8 @@ static void irc_chat_set_topic(PurpleConnection *gc, int id, const char *topic) struct irc_conn *irc; irc = purple_connection_get_protocol_data(gc); - name = purple_conversation_get_name(purple_find_chat(gc, id)); + name = purple_conversation_get_name(PURPLE_CONVERSATION( + purple_conversations_find_chat(gc, id))); if (name == NULL) return; @@ -990,13 +994,13 @@ static PurplePluginProtocolInfo prpl_info = static gboolean load_plugin (PurplePlugin *plugin) { purple_signal_register(plugin, "irc-sending-text", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), - purple_value_new_outgoing(PURPLE_TYPE_STRING)); + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_CONNECTION, + G_TYPE_POINTER); /* pointer to a string */ purple_signal_register(plugin, "irc-receiving-text", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), - purple_value_new_outgoing(PURPLE_TYPE_STRING)); + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_CONNECTION, + G_TYPE_POINTER); /* pointer to a string */ return TRUE; } diff --git a/libpurple/protocols/irc/irc.h b/libpurple/protocols/irc/irc.h index 3f25002473..43780b7cb0 100644 --- a/libpurple/protocols/irc/irc.h +++ b/libpurple/protocols/irc/irc.h @@ -29,7 +29,7 @@ #include <sasl/sasl.h> #endif -#include "circbuffer.h" +#include "circularbuffer.h" #include "ft.h" #include "roomlist.h" #include "sslconn.h" @@ -89,7 +89,7 @@ struct irc_conn { gboolean quitting; - PurpleCircBuffer *outbuf; + PurpleCircularBuffer *outbuf; guint writeh; time_t recv_time; diff --git a/libpurple/protocols/irc/msgs.c b/libpurple/protocols/irc/msgs.c index d6e11cb51a..d81a1564a1 100644 --- a/libpurple/protocols/irc/msgs.c +++ b/libpurple/protocols/irc/msgs.c @@ -23,7 +23,7 @@ #include "internal.h" #include "conversation.h" -#include "blist.h" +#include "buddylist.h" #include "notify.h" #include "util.h" #include "debug.h" @@ -38,7 +38,7 @@ static char *irc_mask_nick(const char *mask); static char *irc_mask_userhost(const char *mask); -static void irc_chat_remove_buddy(PurpleConversation *convo, char *data[2]); +static void irc_chat_remove_buddy(PurpleChatConversation *chat, char *data[2]); static void irc_buddy_status(char *name, struct irc_buddy *ib, struct irc_conn *irc); static void irc_connected(struct irc_conn *irc, const char *nick); @@ -68,7 +68,7 @@ static char *irc_mask_userhost(const char *mask) return g_strdup(strchr(mask, '!') + 1); } -static void irc_chat_remove_buddy(PurpleConversation *convo, char *data[2]) +static void irc_chat_remove_buddy(PurpleChatConversation *chat, char *data[2]) { char *message, *stripped; @@ -76,8 +76,8 @@ static void irc_chat_remove_buddy(PurpleConversation *convo, char *data[2]) message = g_strdup_printf("quit: %s", stripped); g_free(stripped); - if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(convo), data[0])) - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), data[0], message); + if (purple_chat_conversation_has_user(chat, data[0])) + purple_chat_conversation_remove_user(chat, data[0], message); g_free(message); } @@ -94,18 +94,18 @@ static void irc_connected(struct irc_conn *irc, const char *nick) return; purple_connection_set_display_name(gc, nick); - purple_connection_set_state(gc, PURPLE_CONNECTED); + purple_connection_set_state(gc, PURPLE_CONNECTION_CONNECTED); account = purple_connection_get_account(gc); /* If we're away then set our away message */ status = purple_account_get_active_status(irc->account); - if (purple_status_type_get_primitive(purple_status_get_type(status)) != PURPLE_STATUS_AVAILABLE) { + if (purple_status_type_get_primitive(purple_status_get_status_type(status)) != PURPLE_STATUS_AVAILABLE) { PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); prpl_info->set_status(irc->account, status); } /* this used to be in the core, but it's not now */ - for (buddies = purple_find_buddies(account, NULL); buddies; + for (buddies = purple_blist_find_buddies(account, NULL); buddies; buddies = g_slist_delete_link(buddies, buddies)) { PurpleBuddy *b = buddies->data; @@ -161,9 +161,7 @@ void irc_msg_default(struct irc_conn *irc, const char *name, const char *from, c g_free(tmp); /* Check for an existing conversation */ - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, - convname, - irc->account); + convo = purple_conversations_find_with_account(convname, irc->account); g_free(convname); if (convo == NULL) { @@ -267,13 +265,12 @@ void irc_msg_badmode(struct irc_conn *irc, const char *name, const char *from, c void irc_msg_ban(struct irc_conn *irc, const char *name, const char *from, char **args) { - PurpleConversation *convo; + PurpleChatConversation *chat; if (!args || !args[0] || !args[1]) return; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - args[1], irc->account); + chat = purple_conversations_find_chat_with_account(args[1], irc->account); if (!strcmp(name, "367")) { char *msg = NULL; @@ -291,8 +288,8 @@ void irc_msg_ban(struct irc_conn *irc, const char *name, const char *from, char } else { msg = g_strdup_printf(_("Ban on %s"), args[2]); } - if (convo) { - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "", msg, + if (chat) { + purple_conversation_write_message(PURPLE_CONVERSATION(chat), "", msg, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); } else { @@ -300,10 +297,10 @@ void irc_msg_ban(struct irc_conn *irc, const char *name, const char *from, char } g_free(msg); } else if (!strcmp(name, "368")) { - if (!convo) + if (!chat) return; /* End of ban list */ - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "", + purple_conversation_write_message(PURPLE_CONVERSATION(chat), "", _("End of ban list"), PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); @@ -325,20 +322,20 @@ void irc_msg_banned(struct irc_conn *irc, const char *name, const char *from, ch void irc_msg_banfull(struct irc_conn *irc, const char *name, const char *from, char **args) { - PurpleConversation *convo; + PurpleChatConversation *chat; char *buf, *nick; if (!args || !args[0] || !args[1] || !args[2]) return; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[1], irc->account); - if (!convo) + chat = purple_conversations_find_chat_with_account(args[1], irc->account); + if (!chat) return; nick = g_markup_escape_text(args[2], -1); buf = g_strdup_printf(_("Cannot ban %s: banlist is full"), nick); g_free(nick); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "", buf, + purple_conversation_write_message(PURPLE_CONVERSATION(chat), "", buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); g_free(buf); @@ -346,19 +343,19 @@ void irc_msg_banfull(struct irc_conn *irc, const char *name, const char *from, c void irc_msg_chanmode(struct irc_conn *irc, const char *name, const char *from, char **args) { - PurpleConversation *convo; + PurpleChatConversation *chat; char *buf, *escaped; if (!args || !args[1] || !args[2]) return; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[1], irc->account); - if (!convo) /* XXX punt on channels we are not in for now */ + chat = purple_conversations_find_chat_with_account(args[1], irc->account); + if (!chat) /* XXX punt on channels we are not in for now */ return; escaped = (args[3] != NULL) ? g_markup_escape_text(args[3], -1) : NULL; buf = g_strdup_printf("mode for %s: %s %s", args[1], args[2], escaped ? escaped : ""); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "", buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write_message(PURPLE_CONVERSATION(chat), "", buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(escaped); g_free(buf); @@ -476,14 +473,12 @@ void irc_msg_endwhois(struct irc_conn *irc, const char *name, const char *from, void irc_msg_who(struct irc_conn *irc, const char *name, const char *from, char **args) { if (!strcmp(name, "352")) { - PurpleConversation *conv; - PurpleConvChat *chat; - PurpleConvChatBuddy *cb; + PurpleChatConversation *chat; + PurpleChatUser *cb; char *cur, *userhost, *realname; - PurpleConvChatBuddyFlags flags; - GList *keys = NULL, *values = NULL; + PurpleChatUserFlags flags; if (!args || !args[0] || !args[1] || !args[2] || !args[3] || !args[4] || !args[5] || !args[6] || !args[7]) { @@ -492,19 +487,17 @@ void irc_msg_who(struct irc_conn *irc, const char *name, const char *from, char return; } - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[1], irc->account); - if (!conv) { + chat = purple_conversations_find_chat_with_account(args[1], irc->account); + if (!chat) { purple_debug(PURPLE_DEBUG_ERROR, "irc","Got a WHO response for %s, which doesn't exist\n", args[1]); return; } - cb = purple_conv_chat_cb_find(PURPLE_CONV_CHAT(conv), args[5]); + cb = purple_chat_conversation_find_user(chat, args[5]); if (!cb) { purple_debug(PURPLE_DEBUG_ERROR, "irc", "Got a WHO response for %s who isn't a buddy.\n", args[5]); return; } - - chat = PURPLE_CONV_CHAT(conv); userhost = g_strdup_printf("%s@%s", args[2], args[3]); @@ -518,30 +511,19 @@ void irc_msg_who(struct irc_conn *irc, const char *name, const char *from, char } realname = g_strdup(cur); - keys = g_list_prepend(keys, "userhost"); - values = g_list_prepend(values, userhost); - - keys = g_list_prepend(keys, "realname"); - values = g_list_prepend(values, realname); - - purple_conv_chat_cb_set_attributes(chat, cb, keys, values); - - g_list_free(keys); - g_list_free(values); + g_object_set_data_full(G_OBJECT(cb), "userhost", userhost, (GDestroyNotify)g_free); + g_object_set_data_full(G_OBJECT(cb), "realname", realname, (GDestroyNotify)g_free); - g_free(userhost); - g_free(realname); - - flags = purple_conv_chat_cb_get_flags(cb); + flags = purple_chat_user_get_flags(cb); /* FIXME: I'm not sure this is really a good idea, now * that we no longer do periodic WHO. It seems to me * like it's more likely to be confusing than not. * Comments? */ - if (args[6][0] == 'G' && !(flags & PURPLE_CBFLAGS_AWAY)) { - purple_conv_chat_user_set_flags(chat, purple_conv_chat_cb_get_name(cb), flags | PURPLE_CBFLAGS_AWAY); - } else if(args[6][0] == 'H' && (flags & PURPLE_CBFLAGS_AWAY)) { - purple_conv_chat_user_set_flags(chat, purple_conv_chat_cb_get_name(cb), flags & ~PURPLE_CBFLAGS_AWAY); + if (args[6][0] == 'G' && !(flags & PURPLE_CHAT_USER_AWAY)) { + purple_chat_user_set_flags(cb, flags | PURPLE_CHAT_USER_AWAY); + } else if(args[6][0] == 'H' && (flags & PURPLE_CHAT_USER_AWAY)) { + purple_chat_user_set_flags(cb, flags & ~PURPLE_CHAT_USER_AWAY); } } } @@ -588,7 +570,7 @@ void irc_msg_list(struct irc_conn *irc, const char *name, const char *from, char void irc_msg_topic(struct irc_conn *irc, const char *name, const char *from, char **args) { char *chan, *topic, *msg, *nick, *tmp, *tmp2; - PurpleConversation *convo; + PurpleChatConversation *chat; if (!strcmp(name, "topic")) { if (!args[0] || !args[1]) @@ -602,8 +584,8 @@ void irc_msg_topic(struct irc_conn *irc, const char *name, const char *from, cha topic = irc_mirc2txt (args[2]); } - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, chan, irc->account); - if (!convo) { + chat = purple_conversations_find_chat_with_account(chan, irc->account); + if (!chat) { purple_debug(PURPLE_DEBUG_ERROR, "irc", "Got a topic for %s, which doesn't exist\n", chan); g_free(topic); return; @@ -614,28 +596,30 @@ void irc_msg_topic(struct irc_conn *irc, const char *name, const char *from, cha tmp2 = purple_markup_linkify(tmp); g_free(tmp); if (!strcmp(name, "topic")) { - const char *current_topic = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(convo)); + const char *current_topic = purple_chat_conversation_get_topic(chat); if (!(current_topic != NULL && strcmp(tmp2, current_topic) == 0)) { char *nick_esc; nick = irc_mask_nick(from); nick_esc = g_markup_escape_text(nick, -1); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), nick, topic); + purple_chat_conversation_set_topic(chat, nick, topic); if (*tmp2) msg = g_strdup_printf(_("%s has changed the topic to: %s"), nick_esc, tmp2); else msg = g_strdup_printf(_("%s has cleared the topic."), nick_esc); g_free(nick_esc); g_free(nick); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), from, msg, PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write_message(PURPLE_CONVERSATION(chat), from, + msg, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(msg); } } else { char *chan_esc = g_markup_escape_text(chan, -1); msg = g_strdup_printf(_("The topic for %s is: %s"), chan_esc, tmp2); g_free(chan_esc); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, topic); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "", msg, PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_chat_conversation_set_topic(chat, NULL, topic); + purple_conversation_write_message(PURPLE_CONVERSATION(chat), "", msg, + PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(msg); } g_free(tmp2); @@ -644,7 +628,7 @@ void irc_msg_topic(struct irc_conn *irc, const char *name, const char *from, cha void irc_msg_topicinfo(struct irc_conn *irc, const char *name, const char *from, char **args) { - PurpleConversation *convo; + PurpleChatConversation *chat; struct tm *tm; time_t t; char *msg, *timestamp, *datestamp; @@ -652,8 +636,8 @@ void irc_msg_topicinfo(struct irc_conn *irc, const char *name, const char *from, if (!args || !args[1] || !args[2] || !args[3]) return; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[1], irc->account); - if (!convo) { + chat = purple_conversations_find_chat_with_account(args[1], irc->account); + if (!chat) { purple_debug(PURPLE_DEBUG_ERROR, "irc", "Got topic info for %s, which doesn't exist\n", args[1]); return; } @@ -668,7 +652,8 @@ void irc_msg_topicinfo(struct irc_conn *irc, const char *name, const char *from, timestamp = g_strdup(purple_time_format(tm)); datestamp = g_strdup(purple_date_format_short(tm)); msg = g_strdup_printf(_("Topic for %s set by %s at %s on %s"), args[1], args[2], timestamp, datestamp); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "", msg, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, time(NULL)); + purple_conversation_write_message(PURPLE_CONVERSATION(chat), "", msg, + PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, time(NULL)); g_free(timestamp); g_free(datestamp); g_free(msg); @@ -693,7 +678,7 @@ void irc_msg_names(struct irc_conn *irc, const char *name, const char *from, cha PurpleConversation *convo; if (!strcmp(name, "366")) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, args[1], irc->account); + convo = purple_conversations_find_with_account(args[1], irc->account); if (!convo) { purple_debug(PURPLE_DEBUG_ERROR, "irc", "Got a NAMES list for %s, which doesn't exist\n", args[1]); g_string_free(irc->names, TRUE); @@ -703,35 +688,32 @@ void irc_msg_names(struct irc_conn *irc, const char *name, const char *from, cha names = cur = g_string_free(irc->names, FALSE); irc->names = NULL; - if (purple_conversation_get_data(convo, IRC_NAMES_FLAG)) { + if (g_object_get_data(G_OBJECT(convo), IRC_NAMES_FLAG)) { msg = g_strdup_printf(_("Users on %s: %s"), args[1], names ? names : ""); - if (purple_conversation_get_type(convo) == PURPLE_CONV_TYPE_CHAT) - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "", msg, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); - else - purple_conv_im_write(PURPLE_CONV_IM(convo), "", msg, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); + purple_conversation_write_message(convo, "", msg, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); g_free(msg); } else if (cur != NULL) { GList *users = NULL; GList *flags = NULL; while (*cur) { - PurpleConvChatBuddyFlags f = PURPLE_CBFLAGS_NONE; + PurpleChatUserFlags f = PURPLE_CHAT_USER_NONE; end = strchr(cur, ' '); if (!end) end = cur + strlen(cur); if (*cur == '@') { - f = PURPLE_CBFLAGS_OP; + f = PURPLE_CHAT_USER_OP; cur++; } else if (*cur == '%') { - f = PURPLE_CBFLAGS_HALFOP; + f = PURPLE_CHAT_USER_HALFOP; cur++; } else if(*cur == '+') { - f = PURPLE_CBFLAGS_VOICE; + f = PURPLE_CHAT_USER_VOICE; cur++; } else if(irc->mode_chars && strchr(irc->mode_chars, *cur)) { if (*cur == '~') - f = PURPLE_CBFLAGS_FOUNDER; + f = PURPLE_CHAT_USER_FOUNDER; cur++; } tmp = g_strndup(cur, end - cur); @@ -745,7 +727,7 @@ void irc_msg_names(struct irc_conn *irc, const char *name, const char *from, cha if (users != NULL) { GList *l; - purple_conv_chat_add_users(PURPLE_CONV_CHAT(convo), users, NULL, flags, FALSE); + purple_chat_conversation_add_users(PURPLE_CHAT_CONVERSATION(convo), users, NULL, flags, FALSE); for (l = users; l != NULL; l = l->next) g_free(l->data); @@ -754,7 +736,7 @@ void irc_msg_names(struct irc_conn *irc, const char *name, const char *from, cha g_list_free(flags); } - purple_conversation_set_data(convo, IRC_NAMES_FLAG, + g_object_set_data(G_OBJECT(convo), IRC_NAMES_FLAG, GINT_TO_POINTER(TRUE)); } g_free(names); @@ -837,14 +819,12 @@ void irc_msg_nonick(struct irc_conn *irc, const char *name, const char *from, ch PurpleConnection *gc; PurpleConversation *convo; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, args[1], irc->account); + convo = purple_conversations_find_with_account(args[1], irc->account); if (convo) { - if (purple_conversation_get_type(convo) == PURPLE_CONV_TYPE_CHAT) /* does this happen? */ - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), args[1], _("no such channel"), - PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); - else - purple_conv_im_write(PURPLE_CONV_IM(convo), args[1], _("User is not logged in"), - PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); + purple_conversation_write_message(convo, args[1], + PURPLE_IS_IM_CONVERSATION(convo) ? _("User is not logged in") : _("no such channel"), + PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); + } else { if ((gc = purple_account_get_connection(irc->account)) == NULL) return; @@ -860,11 +840,12 @@ void irc_msg_nonick(struct irc_conn *irc, const char *name, const char *from, ch void irc_msg_nosend(struct irc_conn *irc, const char *name, const char *from, char **args) { PurpleConnection *gc; - PurpleConversation *convo; + PurpleChatConversation *chat; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[1], irc->account); - if (convo) { - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), args[1], args[2], PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); + chat = purple_conversations_find_chat_with_account(args[1], irc->account); + if (chat) { + purple_conversation_write_message(PURPLE_CONVERSATION(chat), args[1], args[2], + PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); } else { if ((gc = purple_account_get_connection(irc->account)) == NULL) return; @@ -874,28 +855,29 @@ void irc_msg_nosend(struct irc_conn *irc, const char *name, const char *from, ch void irc_msg_notinchan(struct irc_conn *irc, const char *name, const char *from, char **args) { - PurpleConversation *convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[1], irc->account); + PurpleChatConversation *chat = purple_conversations_find_chat_with_account(args[1], irc->account); purple_debug(PURPLE_DEBUG_INFO, "irc", "We're apparently not in %s, but tried to use it\n", args[1]); - if (convo) { - /*g_slist_remove(irc->gc->buddy_chats, convo); - purple_conversation_set_account(convo, NULL);*/ - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), args[1], args[2], PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); + if (chat) { + /*g_slist_remove(irc->gc->buddy_chats, chat); + purple_conversation_set_account(chat, NULL);*/ + purple_conversation_write_message(PURPLE_CONVERSATION(chat), args[1], args[2], + PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); } } void irc_msg_notop(struct irc_conn *irc, const char *name, const char *from, char **args) { - PurpleConversation *convo; + PurpleChatConversation *chat; if (!args || !args[1] || !args[2]) return; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[1], irc->account); - if (!convo) + chat = purple_conversations_find_chat_with_account(args[1], irc->account); + if (!chat) return; - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "", args[2], PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write_message(PURPLE_CONVERSATION(chat), "", args[2], PURPLE_MESSAGE_SYSTEM, time(NULL)); } void irc_msg_invite(struct irc_conn *irc, const char *name, const char *from, char **args) @@ -957,7 +939,7 @@ void irc_msg_ison(struct irc_conn *irc, const char *name, const char *from, char static void irc_buddy_status(char *name, struct irc_buddy *ib, struct irc_conn *irc) { PurpleConnection *gc = purple_account_get_connection(irc->account); - PurpleBuddy *buddy = purple_find_buddy(irc->account, name); + PurpleBuddy *buddy = purple_blist_find_buddy(irc->account, name); if (!gc || !buddy) return; @@ -974,9 +956,8 @@ static void irc_buddy_status(char *name, struct irc_buddy *ib, struct irc_conn * void irc_msg_join(struct irc_conn *irc, const char *name, const char *from, char **args) { PurpleConnection *gc = purple_account_get_connection(irc->account); - PurpleConversation *convo; - PurpleConvChat *chat; - PurpleConvChatBuddy *cb; + PurpleChatConversation *chat; + PurpleChatUser *cb; char *nick = irc_mask_nick(from), *userhost, *buf; struct irc_buddy *ib; @@ -991,15 +972,13 @@ void irc_msg_join(struct irc_conn *irc, const char *name, const char *from, char /* We are joining a channel for the first time */ serv_got_joined_chat(gc, id++, args[0]); g_free(nick); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - args[0], - irc->account); + chat = purple_conversations_find_chat_with_account(args[0], irc->account); - if (convo == NULL) { + if (chat == NULL) { purple_debug_error("irc", "tried to join %s but couldn't\n", args[0]); return; } - purple_conversation_set_data(convo, IRC_NAMES_FLAG, + g_object_set_data(G_OBJECT(chat), IRC_NAMES_FLAG, GINT_TO_POINTER(FALSE)); // Get the real name and user host for all participants. @@ -1010,26 +989,25 @@ void irc_msg_join(struct irc_conn *irc, const char *name, const char *from, char /* Until purple_conversation_present does something that * one would expect in Pidgin, this call produces buggy * behavior both for the /join and auto-join cases. */ - /* purple_conversation_present(convo); */ + /* purple_conversation_present(chat); */ return; } - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[0], irc->account); - if (convo == NULL) { + chat = purple_conversations_find_chat_with_account(args[0], irc->account); + if (chat == NULL) { purple_debug(PURPLE_DEBUG_ERROR, "irc", "JOIN for %s failed\n", args[0]); g_free(nick); return; } userhost = irc_mask_userhost(from); - chat = PURPLE_CONV_CHAT(convo); - purple_conv_chat_add_user(chat, nick, userhost, PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(chat, nick, userhost, PURPLE_CHAT_USER_NONE, TRUE); - cb = purple_conv_chat_cb_find(chat, nick); + cb = purple_chat_conversation_find_user(chat, nick); if (cb) { - purple_conv_chat_cb_set_attribute(chat, cb, "userhost", userhost); + g_object_set_data_full(G_OBJECT(cb), "userhost", userhost, (GDestroyNotify)g_free); } if ((ib = g_hash_table_lookup(irc->buddies, nick)) != NULL) { @@ -1037,14 +1015,13 @@ void irc_msg_join(struct irc_conn *irc, const char *name, const char *from, char irc_buddy_status(nick, ib, irc); } - g_free(userhost); g_free(nick); } void irc_msg_kick(struct irc_conn *irc, const char *name, const char *from, char **args) { PurpleConnection *gc = purple_account_get_connection(irc->account); - PurpleConversation *convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[0], irc->account); + PurpleChatConversation *chat = purple_conversations_find_chat_with_account(args[0], irc->account); char *nick = irc_mask_nick(from), *buf; if (!gc) { @@ -1052,7 +1029,7 @@ void irc_msg_kick(struct irc_conn *irc, const char *name, const char *from, char return; } - if (!convo) { + if (!chat) { purple_debug(PURPLE_DEBUG_ERROR, "irc", "Received a KICK for unknown channel %s\n", args[0]); g_free(nick); return; @@ -1060,12 +1037,12 @@ void irc_msg_kick(struct irc_conn *irc, const char *name, const char *from, char if (!purple_utf8_strcasecmp(purple_connection_get_display_name(gc), args[1])) { buf = g_strdup_printf(_("You have been kicked by %s: (%s)"), nick, args[2]); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), args[0], buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write_message(PURPLE_CONVERSATION(chat), args[0], buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(buf); - serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo))); + serv_got_chat_left(gc, purple_chat_conversation_get_id(chat)); } else { buf = g_strdup_printf(_("Kicked by %s (%s)"), nick, args[2]); - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), args[1], buf); + purple_chat_conversation_remove_user(chat, args[1], buf); g_free(buf); } @@ -1075,24 +1052,25 @@ void irc_msg_kick(struct irc_conn *irc, const char *name, const char *from, char void irc_msg_mode(struct irc_conn *irc, const char *name, const char *from, char **args) { - PurpleConversation *convo; + PurpleChatConversation *chat; char *nick = irc_mask_nick(from), *buf; if (*args[0] == '#' || *args[0] == '&') { /* Channel */ char *escaped; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[0], irc->account); - if (!convo) { + chat = purple_conversations_find_chat_with_account(args[0], irc->account); + if (!chat) { purple_debug(PURPLE_DEBUG_ERROR, "irc", "MODE received for %s, which we are not in\n", args[0]); g_free(nick); return; } escaped = (args[2] != NULL) ? g_markup_escape_text(args[2], -1) : NULL; buf = g_strdup_printf(_("mode (%s %s) by %s"), args[1], escaped ? escaped : "", nick); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), args[0], buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write_message(PURPLE_CONVERSATION(chat), args[0], buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(escaped); g_free(buf); if(args[2]) { - PurpleConvChatBuddyFlags newflag, flags; + PurpleChatUser *cb; + PurpleChatUserFlags newflag, flags; char *mcur, *cur, *end, *user; gboolean add = FALSE; mcur = args[1]; @@ -1107,23 +1085,24 @@ void irc_msg_mode(struct irc_conn *irc, const char *name, const char *from, char if (!end) end = cur + strlen(cur); user = g_strndup(cur, end - cur); - flags = purple_conv_chat_user_get_flags(PURPLE_CONV_CHAT(convo), user); - newflag = PURPLE_CBFLAGS_NONE; + cb = purple_chat_conversation_find_user(chat, user); + flags = purple_chat_user_get_flags(cb); + newflag = PURPLE_CHAT_USER_NONE; if (*mcur == 'o') - newflag = PURPLE_CBFLAGS_OP; + newflag = PURPLE_CHAT_USER_OP; else if (*mcur =='h') - newflag = PURPLE_CBFLAGS_HALFOP; + newflag = PURPLE_CHAT_USER_HALFOP; else if (*mcur == 'v') - newflag = PURPLE_CBFLAGS_VOICE; + newflag = PURPLE_CHAT_USER_VOICE; else if(irc->mode_chars && strchr(irc->mode_chars, '~') && (*mcur == 'q')) - newflag = PURPLE_CBFLAGS_FOUNDER; + newflag = PURPLE_CHAT_USER_FOUNDER; if (newflag) { if (add) flags |= newflag; else flags &= ~newflag; - purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(convo), user, flags); + purple_chat_user_set_flags(cb, flags); } g_free(user); cur = end; @@ -1141,7 +1120,7 @@ void irc_msg_mode(struct irc_conn *irc, const char *name, const char *from, char void irc_msg_nick(struct irc_conn *irc, const char *name, const char *from, char **args) { PurpleConnection *gc = purple_account_get_connection(irc->account); - PurpleConversation *conv; + PurpleIMConversation *im; GSList *chats; char *nick = irc_mask_nick(from); @@ -1151,24 +1130,24 @@ void irc_msg_nick(struct irc_conn *irc, const char *name, const char *from, char g_free(nick); return; } - chats = gc->buddy_chats; + chats = purple_connection_get_active_chats(gc); if (!purple_utf8_strcasecmp(nick, purple_connection_get_display_name(gc))) { purple_connection_set_display_name(gc, args[0]); } while (chats) { - PurpleConvChat *chat = PURPLE_CONV_CHAT(chats->data); + PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(chats->data); /* This is ugly ... */ - if (purple_conv_chat_find_user(chat, nick)) - purple_conv_chat_rename_user(chat, nick, args[0]); + if (purple_chat_conversation_has_user(chat, nick)) + purple_chat_conversation_rename_user(chat, nick, args[0]); chats = chats->next; } - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, nick, + im = purple_conversations_find_im_with_account(nick, irc->account); - if (conv != NULL) - purple_conversation_set_name(conv, args[0]); + if (im != NULL) + purple_conversation_set_name(PURPLE_CONVERSATION(im), args[0]); g_free(nick); } @@ -1176,7 +1155,7 @@ void irc_msg_nick(struct irc_conn *irc, const char *name, const char *from, char void irc_msg_badnick(struct irc_conn *irc, const char *name, const char *from, char **args) { PurpleConnection *gc = purple_account_get_connection(irc->account); - if (purple_connection_get_state(gc) == PURPLE_CONNECTED) { + if (purple_connection_get_state(gc) == PURPLE_CONNECTION_CONNECTED) { purple_notify_error(gc, _("Invalid nickname"), _("Invalid nickname"), _("Your selected nickname was rejected by the server. It probably contains invalid characters.")); @@ -1196,7 +1175,7 @@ void irc_msg_nickused(struct irc_conn *irc, const char *name, const char *from, if (!args || !args[1]) return; - if (gc && purple_connection_get_state(gc) == PURPLE_CONNECTED) { + if (gc && purple_connection_get_state(gc) == PURPLE_CONNECTION_CONNECTED) { /* We only want to do the following dance if the connection has not been successfully completed. If it has, just notify the user that their /nick command didn't go. */ @@ -1253,7 +1232,7 @@ void irc_msg_nochangenick(struct irc_conn *irc, const char *name, const char *fr void irc_msg_part(struct irc_conn *irc, const char *name, const char *from, char **args) { PurpleConnection *gc = purple_account_get_connection(irc->account); - PurpleConversation *convo; + PurpleChatConversation *chat; char *nick, *msg, *channel; if (!args || !args[0] || !gc) @@ -1263,8 +1242,8 @@ void irc_msg_part(struct irc_conn *irc, const char *name, const char *from, char * that I can see. This catches that. */ channel = (args[0][0] == ':') ? &args[0][1] : args[0]; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, channel, irc->account); - if (!convo) { + chat = purple_conversations_find_chat_with_account(channel, irc->account); + if (!chat) { purple_debug(PURPLE_DEBUG_INFO, "irc", "Got a PART on %s, which doesn't exist -- probably closed\n", channel); return; } @@ -1276,12 +1255,12 @@ void irc_msg_part(struct irc_conn *irc, const char *name, const char *from, char (args[1] && *args[1]) ? ": " : "", (escaped && *escaped) ? escaped : ""); g_free(escaped); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel, msg, PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write_message(PURPLE_CONVERSATION(chat), channel, msg, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(msg); - serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo))); + serv_got_chat_left(gc, purple_chat_conversation_get_id(chat)); } else { msg = args[1] ? irc_mirc2txt(args[1]) : NULL; - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), nick, msg); + purple_chat_conversation_remove_user(chat, nick, msg); g_free(msg); } g_free(nick); @@ -1321,13 +1300,10 @@ void irc_msg_pong(struct irc_conn *irc, const char *name, const char *from, char msg = g_strdup_printf(_("PING reply -- Lag: %lu seconds"), time(NULL) - oldstamp); } - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, parts[0], irc->account); + convo = purple_conversations_find_with_account(parts[0], irc->account); g_strfreev(parts); if (convo) { - if (purple_conversation_get_type (convo) == PURPLE_CONV_TYPE_CHAT) - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "PONG", msg, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); - else - purple_conv_im_write(PURPLE_CONV_IM(convo), "PONG", msg, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); + purple_conversation_write_message(convo, "PONG", msg, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); } else { gc = purple_account_get_connection(irc->account); if (!gc) { @@ -1350,7 +1326,7 @@ void irc_msg_privmsg(struct irc_conn *irc, const char *name, const char *from, c static void irc_msg_handle_privmsg(struct irc_conn *irc, const char *name, const char *from, const char *to, const char *rawmsg, gboolean notice) { PurpleConnection *gc = purple_account_get_connection(irc->account); - PurpleConversation *convo; + PurpleChatConversation *chat; char *tmp; char *msg; char *nick; @@ -1380,9 +1356,9 @@ static void irc_msg_handle_privmsg(struct irc_conn *irc, const char *name, const if (!purple_utf8_strcasecmp(to, purple_connection_get_display_name(gc))) { serv_got_im(gc, nick, msg, 0, time(NULL)); } else { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, irc_nick_skip_mode(irc, to), irc->account); - if (convo) - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), nick, 0, msg, time(NULL)); + chat = purple_conversations_find_chat_with_account(irc_nick_skip_mode(irc, to), irc->account); + if (chat) + serv_got_chat_in(gc, purple_chat_conversation_get_id(chat), nick, 0, msg, time(NULL)); else purple_debug_error("irc", "Got a %s on %s, which does not exist\n", notice ? "NOTICE" : "PRIVMSG", to); @@ -1394,14 +1370,12 @@ static void irc_msg_handle_privmsg(struct irc_conn *irc, const char *name, const void irc_msg_regonly(struct irc_conn *irc, const char *name, const char *from, char **args) { PurpleConnection *gc = purple_account_get_connection(irc->account); - PurpleConversation *convo; char *msg; if (!args || !args[1] || !args[2] || !gc) return; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[1], irc->account); - if (convo) { + if (purple_conversations_find_chat_with_account(args[1], irc->account)) { /* This is a channel we're already in; for some reason, * freenode feels the need to notify us that in some * hypothetical other situation this might not have @@ -1426,7 +1400,8 @@ void irc_msg_quit(struct irc_conn *irc, const char *name, const char *from, char data[0] = irc_mask_nick(from); data[1] = args[0]; /* XXX this should have an API, I shouldn't grab this directly */ - g_slist_foreach(gc->buddy_chats, (GFunc)irc_chat_remove_buddy, data); + g_slist_foreach(purple_connection_get_active_chats(gc), + (GFunc)irc_chat_remove_buddy, data); if ((ib = g_hash_table_lookup(irc->buddies, data[0])) != NULL) { ib->new_online_status = FALSE; diff --git a/libpurple/protocols/jabber/adhoccommands.c b/libpurple/protocols/jabber/adhoccommands.c index 60dc73305d..23e8286047 100644 --- a/libpurple/protocols/jabber/adhoccommands.c +++ b/libpurple/protocols/jabber/adhoccommands.c @@ -224,7 +224,7 @@ jabber_adhoc_parse(JabberStream *js, const char *from, } void jabber_adhoc_execute_action(PurpleBlistNode *node, gpointer data) { - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (PURPLE_IS_BUDDY(node)) { JabberAdHocCommands *cmd = data; PurpleBuddy *buddy = (PurpleBuddy *) node; PurpleAccount *account = purple_buddy_get_account(buddy); diff --git a/libpurple/protocols/jabber/auth.c b/libpurple/protocols/jabber/auth.c index 7285108b11..df5bdeadc6 100644 --- a/libpurple/protocols/jabber/auth.c +++ b/libpurple/protocols/jabber/auth.c @@ -24,7 +24,6 @@ #include "account.h" #include "debug.h" -#include "cipher.h" #include "core.h" #include "conversation.h" #include "request.h" @@ -39,6 +38,9 @@ #include "iq.h" #include "notify.h" +#include "ciphers/hmaccipher.h" +#include "ciphers/md5hash.h" + static GSList *auth_mechs = NULL; static void auth_old_result_cb(JabberStream *js, const char *from, @@ -276,16 +278,18 @@ static void auth_old_cb(JabberStream *js, const char *from, */ const char *challenge; gchar digest[33]; - PurpleCipherContext *hmac; + PurpleCipher *hmac; + PurpleHash *md5; /* Calculate the MHAC-MD5 digest */ + md5 = purple_md5_hash_new(); + hmac = purple_hmac_cipher_new(md5); challenge = xmlnode_get_attrib(x, "challenge"); - hmac = purple_cipher_context_new_by_name("hmac", NULL); - purple_cipher_context_set_option(hmac, "hash", "md5"); - purple_cipher_context_set_key(hmac, (guchar *)pw, strlen(pw)); - purple_cipher_context_append(hmac, (guchar *)challenge, strlen(challenge)); - purple_cipher_context_digest_to_str(hmac, digest, 33); - purple_cipher_context_destroy(hmac); + purple_cipher_set_key(hmac, (guchar *)pw, strlen(pw)); + purple_cipher_append(hmac, (guchar *)challenge, strlen(challenge)); + purple_cipher_digest_to_str(hmac, digest, 33); + g_object_unref(hmac); + g_object_unref(md5); /* Create the response query */ iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth"); diff --git a/libpurple/protocols/jabber/auth_digest_md5.c b/libpurple/protocols/jabber/auth_digest_md5.c index 7d38db7b03..e729cea978 100644 --- a/libpurple/protocols/jabber/auth_digest_md5.c +++ b/libpurple/protocols/jabber/auth_digest_md5.c @@ -23,7 +23,7 @@ #include "internal.h" #include "debug.h" -#include "cipher.h" +#include "ciphers/md5hash.h" #include "util.h" #include "xmlnode.h" @@ -106,8 +106,7 @@ static char * generate_response_value(JabberID *jid, const char *passwd, const char *nonce, const char *cnonce, const char *a2, const char *realm) { - PurpleCipher *cipher; - PurpleCipherContext *context; + PurpleHash *hash; guchar result[16]; size_t a1len; @@ -122,35 +121,34 @@ generate_response_value(JabberID *jid, const char *passwd, const char *nonce, convpasswd = g_strdup(passwd); } - cipher = purple_ciphers_find_cipher("md5"); - context = purple_cipher_context_new(cipher, NULL); + hash = purple_md5_hash_new(); x = g_strdup_printf("%s:%s:%s", convnode, realm, convpasswd ? convpasswd : ""); - purple_cipher_context_append(context, (const guchar *)x, strlen(x)); - purple_cipher_context_digest(context, result, sizeof(result)); + purple_hash_append(hash, (const guchar *)x, strlen(x)); + purple_hash_digest(hash, result, sizeof(result)); a1 = g_strdup_printf("xxxxxxxxxxxxxxxx:%s:%s", nonce, cnonce); a1len = strlen(a1); g_memmove(a1, result, 16); - purple_cipher_context_reset(context, NULL); - purple_cipher_context_append(context, (const guchar *)a1, a1len); - purple_cipher_context_digest(context, result, sizeof(result)); + purple_hash_reset(hash); + purple_hash_append(hash, (const guchar *)a1, a1len); + purple_hash_digest(hash, result, sizeof(result)); ha1 = purple_base16_encode(result, 16); - purple_cipher_context_reset(context, NULL); - purple_cipher_context_append(context, (const guchar *)a2, strlen(a2)); - purple_cipher_context_digest(context, result, sizeof(result)); + purple_hash_reset(hash); + purple_hash_append(hash, (const guchar *)a2, strlen(a2)); + purple_hash_digest(hash, result, sizeof(result)); ha2 = purple_base16_encode(result, 16); kd = g_strdup_printf("%s:%s:00000001:%s:auth:%s", ha1, nonce, cnonce, ha2); - purple_cipher_context_reset(context, NULL); - purple_cipher_context_append(context, (const guchar *)kd, strlen(kd)); - purple_cipher_context_digest(context, result, sizeof(result)); - purple_cipher_context_destroy(context); + purple_hash_reset(hash); + purple_hash_append(hash, (const guchar *)kd, strlen(kd)); + purple_hash_digest(hash, result, sizeof(result)); + g_object_unref(hash); z = purple_base16_encode(result, 16); diff --git a/libpurple/protocols/jabber/auth_scram.c b/libpurple/protocols/jabber/auth_scram.c index 5fe6bf9539..8c92ed5978 100644 --- a/libpurple/protocols/jabber/auth_scram.c +++ b/libpurple/protocols/jabber/auth_scram.c @@ -25,11 +25,12 @@ #include "auth.h" #include "auth_scram.h" -#include "cipher.h" +#include "ciphers/hmaccipher.h" +#include "ciphers/sha1hash.h" #include "debug.h" static const JabberScramHash hashes[] = { - { "-SHA-1", "sha1", 20 }, + { "-SHA-1", purple_sha1_hash_new, 20 }, }; static const JabberScramHash *mech_to_hash(const char *mech) @@ -76,7 +77,8 @@ static const struct { guchar *jabber_scram_hi(const JabberScramHash *hash, const GString *str, GString *salt, guint iterations) { - PurpleCipherContext *context; + PurpleHash *hasher; + PurpleCipher *cipher; guchar *result; guint i; guchar *prev, *tmp; @@ -90,27 +92,28 @@ guchar *jabber_scram_hi(const JabberScramHash *hash, const GString *str, tmp = g_new0(guint8, hash->size); result = g_new0(guint8, hash->size); - context = purple_cipher_context_new_by_name("hmac", NULL); + hasher = hash->new_cipher(); + cipher = purple_hmac_cipher_new(hasher); + g_object_unref(G_OBJECT(hasher)); /* Append INT(1), a four-octet encoding of the integer 1, most significant * octet first. */ g_string_append_len(salt, "\0\0\0\1", 4); /* Compute U0 */ - purple_cipher_context_set_option(context, "hash", (gpointer)hash->name); - purple_cipher_context_set_key(context, (guchar *)str->str, str->len); - purple_cipher_context_append(context, (guchar *)salt->str, salt->len); - purple_cipher_context_digest(context, result, hash->size); + purple_cipher_set_key(cipher, (guchar *)str->str, str->len); + purple_cipher_append(cipher, (guchar *)salt->str, salt->len); + purple_cipher_digest(cipher, result, hash->size); memcpy(prev, result, hash->size); /* Compute U1...Ui */ for (i = 1; i < iterations; ++i) { guint j; - purple_cipher_context_set_option(context, "hash", (gpointer)hash->name); - purple_cipher_context_set_key(context, (guchar *)str->str, str->len); - purple_cipher_context_append(context, prev, hash->size); - purple_cipher_context_digest(context, tmp, hash->size); + purple_cipher_reset(cipher); + purple_cipher_set_key(cipher, (guchar *)str->str, str->len); + purple_cipher_append(cipher, prev, hash->size); + purple_cipher_digest(cipher, tmp, hash->size); for (j = 0; j < hash->size; ++j) result[j] ^= tmp[j]; @@ -118,7 +121,7 @@ guchar *jabber_scram_hi(const JabberScramHash *hash, const GString *str, memcpy(prev, tmp, hash->size); } - purple_cipher_context_destroy(context); + g_object_unref(G_OBJECT(cipher)); g_free(tmp); g_free(prev); return result; @@ -136,25 +139,27 @@ guchar *jabber_scram_hi(const JabberScramHash *hash, const GString *str, static void hmac(const JabberScramHash *hash, guchar *out, const guchar *key, const gchar *str) { - PurpleCipherContext *context; - - context = purple_cipher_context_new_by_name("hmac", NULL); - purple_cipher_context_set_option(context, "hash", (gpointer)hash->name); - purple_cipher_context_set_key(context, key, hash->size); - purple_cipher_context_append(context, (guchar *)str, strlen(str)); - purple_cipher_context_digest(context, out, hash->size); - purple_cipher_context_destroy(context); + PurpleHash *hasher; + PurpleCipher *cipher; + + hasher = hash->new_cipher(); + cipher = purple_hmac_cipher_new(hasher); + g_object_unref(G_OBJECT(hasher)); + purple_cipher_set_key(cipher, key, hash->size); + purple_cipher_append(cipher, (guchar *)str, strlen(str)); + purple_cipher_digest(cipher, out, hash->size); + g_object_unref(G_OBJECT(cipher)); } static void hash(const JabberScramHash *hash, guchar *out, const guchar *data) { - PurpleCipherContext *context; + PurpleHash *hasher; - context = purple_cipher_context_new_by_name(hash->name, NULL); - purple_cipher_context_append(context, data, hash->size); - purple_cipher_context_digest(context, out, hash->size); - purple_cipher_context_destroy(context); + hasher = hash->new_cipher(); + purple_hash_append(hasher, data, hash->size); + purple_hash_digest(hasher, out, hash->size); + g_object_unref(G_OBJECT(hasher)); } gboolean diff --git a/libpurple/protocols/jabber/auth_scram.h b/libpurple/protocols/jabber/auth_scram.h index e1f52d1cbe..84f1cb3e25 100644 --- a/libpurple/protocols/jabber/auth_scram.h +++ b/libpurple/protocols/jabber/auth_scram.h @@ -29,12 +29,14 @@ * DO NOT USE ANYTHING HERE OR YOU WILL BE SENT TO THE PIT OF DESPAIR. */ +#include "hash.h" + /* Per-connection state stored between messages. * This is stored in js->auth_data_mech. */ typedef struct { const char *mech_substr; - const char *name; + PurpleHash *(*new_cipher)(void); guint size; } JabberScramHash; diff --git a/libpurple/protocols/jabber/buddy.c b/libpurple/protocols/jabber/buddy.c index 9e22b41973..3a37315fcc 100644 --- a/libpurple/protocols/jabber/buddy.c +++ b/libpurple/protocols/jabber/buddy.c @@ -1225,7 +1225,7 @@ static void jabber_vcard_parse(JabberStream *js, const char *from, PurpleBuddy *b; /* If we found a serverside alias, set it and tell the core */ serv_got_alias(js->gc, bare_jid, serverside_alias); - b = purple_find_buddy(account, bare_jid); + b = purple_blist_find_buddy(account, bare_jid); if (b) { purple_blist_node_set_string((PurpleBlistNode*)b, "servernick", serverside_alias); } @@ -1698,7 +1698,7 @@ static void jabber_buddy_make_invisible(PurpleBlistNode *node, gpointer data) PurpleConnection *gc; JabberStream *js; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); @@ -1713,7 +1713,7 @@ static void jabber_buddy_make_visible(PurpleBlistNode *node, gpointer data) PurpleConnection *gc; JabberStream *js; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); @@ -1745,7 +1745,7 @@ jabber_buddy_cancel_presence_notification(PurpleBlistNode *node, const gchar *name; char *msg; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; name = purple_buddy_get_name(buddy); @@ -1766,7 +1766,7 @@ static void jabber_buddy_rerequest_auth(PurpleBlistNode *node, gpointer data) PurpleConnection *gc; JabberStream *js; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); @@ -1782,7 +1782,7 @@ static void jabber_buddy_unsubscribe(PurpleBlistNode *node, gpointer data) PurpleConnection *gc; JabberStream *js; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); @@ -1792,7 +1792,7 @@ static void jabber_buddy_unsubscribe(PurpleBlistNode *node, gpointer data) } static void jabber_buddy_login(PurpleBlistNode *node, gpointer data) { - if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if(PURPLE_IS_BUDDY(node)) { /* simply create a directed presence of the current status */ PurpleBuddy *buddy = (PurpleBuddy *) node; PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy)); @@ -1818,7 +1818,7 @@ static void jabber_buddy_login(PurpleBlistNode *node, gpointer data) { } static void jabber_buddy_logout(PurpleBlistNode *node, gpointer data) { - if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if(PURPLE_IS_BUDDY(node)) { /* simply create a directed unavailable presence */ PurpleBuddy *buddy = (PurpleBuddy *) node; PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy)); @@ -1932,7 +1932,7 @@ static GList *jabber_buddy_menu(PurpleBuddy *buddy) GList * jabber_blist_node_menu(PurpleBlistNode *node) { - if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if(PURPLE_IS_BUDDY(node)) { return jabber_buddy_menu((PurpleBuddy *) node); } else { return NULL; diff --git a/libpurple/protocols/jabber/caps.c b/libpurple/protocols/jabber/caps.c index 8b87a4d958..7e084681ee 100644 --- a/libpurple/protocols/jabber/caps.c +++ b/libpurple/protocols/jabber/caps.c @@ -25,12 +25,14 @@ #include "debug.h" #include "caps.h" -#include "cipher.h" #include "iq.h" #include "presence.h" #include "util.h" #include "xdata.h" +#include "ciphers/md5hash.h" +#include "ciphers/sha1hash.h" + #define JABBER_CAPS_FILENAME "xmpp-caps.xml" typedef struct _JabberDataFormField { @@ -455,16 +457,18 @@ jabber_caps_client_iqcb(JabberStream *js, const char *from, JabberIqType type, /* Only validate if these are v1.5 capabilities */ if (userdata->hash) { gchar *hash = NULL; + PurpleHash *hasher = NULL; /* * TODO: If you add *any* hash here, make sure the checksum buffer * size in jabber_caps_calculate_hash is large enough. The cipher API * doesn't seem to offer a "Get the hash size" function(?). */ if (g_str_equal(userdata->hash, "sha-1")) { - hash = jabber_caps_calculate_hash(info, "sha1"); + hasher = purple_sha1_hash_new(); } else if (g_str_equal(userdata->hash, "md5")) { - hash = jabber_caps_calculate_hash(info, "md5"); + hasher = purple_md5_hash_new(); } + hash = jabber_caps_calculate_hash(info, hasher); if (!hash || !g_str_equal(hash, userdata->ver)) { purple_debug_warning("jabber", "Could not validate caps info from " @@ -480,6 +484,7 @@ jabber_caps_client_iqcb(JabberStream *js, const char *from, JabberIqType type, } g_free(hash); + g_object_unref(hasher); } if (!userdata->hash && userdata->node_exts) { @@ -806,28 +811,33 @@ static GList* jabber_caps_xdata_get_fields(const xmlnode *x) } static void -append_escaped_string(PurpleCipherContext *context, const gchar *str) +append_escaped_string(PurpleHash *hash, const gchar *str) { + g_return_if_fail(hash != NULL); + g_object_ref(hash); + if (str && *str) { char *tmp = g_markup_escape_text(str, -1); - purple_cipher_context_append(context, (const guchar *)tmp, strlen(tmp)); + purple_hash_append(hash, (const guchar *)tmp, strlen(tmp)); g_free(tmp); } - purple_cipher_context_append(context, (const guchar *)"<", 1); + purple_hash_append(hash, (const guchar *)"<", 1); + g_object_unref(hash); } -gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, const char *hash) +gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, PurpleHash *hash) { GList *node; - PurpleCipherContext *context; guint8 checksum[20]; gsize checksum_size = 20; gboolean success; - if (!info || !(context = purple_cipher_context_new_by_name(hash, NULL))) + if (!info || !hash) return NULL; + g_object_ref(hash); + /* sort identities, features and x-data forms */ info->identities = g_list_sort(info->identities, jabber_identity_compare); info->features = g_list_sort(info->features, (GCompareFunc)strcmp); @@ -850,7 +860,7 @@ gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, const char *hash) tmp = g_strconcat(category, "/", type, "/", lang ? lang : "", "/", name ? name : "", "<", NULL); - purple_cipher_context_append(context, (const guchar *)tmp, strlen(tmp)); + purple_hash_append(hash, (const guchar *)tmp, strlen(tmp)); g_free(tmp); g_free(category); @@ -861,7 +871,7 @@ gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, const char *hash) /* concat features to the verification string */ for (node = info->features; node; node = node->next) { - append_escaped_string(context, node->data); + append_escaped_string(hash, node->data); } /* concat x-data forms to the verification string */ @@ -871,7 +881,7 @@ gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, const char *hash) GList *fields = jabber_caps_xdata_get_fields(data); /* append FORM_TYPE's field value to the verification string */ - append_escaped_string(context, formtype); + append_escaped_string(hash, formtype); g_free(formtype); while (fields) { @@ -879,10 +889,10 @@ gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, const char *hash) if (!g_str_equal(field->var, "FORM_TYPE")) { /* Append the "var" attribute */ - append_escaped_string(context, field->var); + append_escaped_string(hash, field->var); /* Append <value/> elements' cdata */ while (field->values) { - append_escaped_string(context, field->values->data); + append_escaped_string(hash, field->values->data); g_free(field->values->data); field->values = g_list_delete_link(field->values, field->values); @@ -900,16 +910,17 @@ gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, const char *hash) } /* generate hash */ - success = purple_cipher_context_digest(context, checksum, checksum_size); - checksum_size = purple_cipher_context_get_digest_size(context); + success = purple_hash_digest(hash, checksum, checksum_size); + checksum_size = purple_hash_get_digest_size(hash); - purple_cipher_context_destroy(context); + g_object_unref(hash); return (success ? purple_base64_encode(checksum, checksum_size) : NULL); } void jabber_caps_calculate_own_hash(JabberStream *js) { JabberCapsClientInfo info; + PurpleHash *hasher; GList *iter = 0; GList *features = 0; @@ -940,7 +951,9 @@ void jabber_caps_calculate_own_hash(JabberStream *js) { info.forms = NULL; g_free(js->caps_hash); - js->caps_hash = jabber_caps_calculate_hash(&info, "sha1"); + hasher = purple_sha1_hash_new(); + js->caps_hash = jabber_caps_calculate_hash(&info, hasher); + g_object_unref(hasher); g_list_free(info.identities); g_list_free(info.features); } diff --git a/libpurple/protocols/jabber/caps.h b/libpurple/protocols/jabber/caps.h index 897754f6d9..b428c577d2 100644 --- a/libpurple/protocols/jabber/caps.h +++ b/libpurple/protocols/jabber/caps.h @@ -27,6 +27,7 @@ typedef struct _JabberCapsClientInfo JabberCapsClientInfo; #include "jabber.h" +#include "hash.h" /* Implementation of XEP-0115 - Entity Capabilities */ @@ -98,7 +99,7 @@ void jabber_caps_get_info(JabberStream *js, const char *who, const char *node, * @param hash Hash cipher to be used. Either sha-1 or md5. * @return The base64 encoded SHA-1 hash; must be freed by caller */ -gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, const char *hash); +gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, PurpleHash *hash); /** * Calculate SHA1 hash for own featureset. diff --git a/libpurple/protocols/jabber/chat.c b/libpurple/protocols/jabber/chat.c index b4a3ec0e89..e9975e853a 100644 --- a/libpurple/protocols/jabber/chat.c +++ b/libpurple/protocols/jabber/chat.c @@ -138,16 +138,16 @@ JabberChat *jabber_chat_find_by_id(JabberStream *js, int id) return chat; } -JabberChat *jabber_chat_find_by_conv(PurpleConversation *conv) +JabberChat *jabber_chat_find_by_conv(PurpleChatConversation *conv) { - PurpleAccount *account = purple_conversation_get_account(conv); + PurpleAccount *account = purple_conversation_get_account(PURPLE_CONVERSATION(conv)); PurpleConnection *gc = purple_account_get_connection(account); JabberStream *js; int id; if (!gc) return NULL; js = purple_connection_get_protocol_data(gc); - id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)); + id = purple_chat_conversation_get_id(conv); return jabber_chat_find_by_id(js, id); } @@ -451,12 +451,12 @@ void jabber_chat_free(JabberChat *chat) g_free(chat); } -gboolean jabber_chat_find_buddy(PurpleConversation *conv, const char *name) +gboolean jabber_chat_find_buddy(PurpleChatConversation *conv, const char *name) { - return purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), name); + return purple_chat_conversation_has_user(conv, name); } -char *jabber_chat_buddy_real_name(PurpleConnection *gc, int id, const char *who) +char *jabber_chat_user_real_name(PurpleConnection *gc, int id, const char *who) { JabberStream *js = purple_connection_get_protocol_data(gc); JabberChat *chat; @@ -753,7 +753,7 @@ gboolean jabber_chat_change_nick(JabberChat *chat, const char *nick) int priority; if(!chat->muc) { - purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), "", + purple_conversation_write_message(PURPLE_CONVERSATION(chat->conv), "", _("Nick changing not supported in non-MUC chatrooms"), PURPLE_MESSAGE_SYSTEM, time(NULL)); return FALSE; @@ -1072,7 +1072,7 @@ jabber_chat_affiliation_list_cb(JabberStream *js, const char *from, buf = g_string_append_len(buf, _("No users found"), -1); } - purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), "", buf->str, + purple_conversation_write_message(PURPLE_CONVERSATION(chat->conv), "", buf->str, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG, time(NULL)); g_string_free(buf, TRUE); @@ -1167,7 +1167,7 @@ static void jabber_chat_role_list_cb(JabberStream *js, const char *from, buf = g_string_append_len(buf, _("No users found"), -1); } - purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), "", buf->str, + purple_conversation_write_message(PURPLE_CONVERSATION(chat->conv), "", buf->str, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG, time(NULL)); g_string_free(buf, TRUE); diff --git a/libpurple/protocols/jabber/chat.h b/libpurple/protocols/jabber/chat.h index 203b242734..71174e192b 100644 --- a/libpurple/protocols/jabber/chat.h +++ b/libpurple/protocols/jabber/chat.h @@ -45,7 +45,7 @@ typedef struct _JabberChat { char *handle; GHashTable *components; int id; - PurpleConversation *conv; + PurpleChatConversation *conv; gboolean muc; gboolean xhtml; PurpleRequestType config_dialog_type; @@ -77,14 +77,14 @@ void jabber_chat_join(PurpleConnection *gc, GHashTable *data); JabberChat *jabber_chat_find(JabberStream *js, const char *room, const char *server); JabberChat *jabber_chat_find_by_id(JabberStream *js, int id); -JabberChat *jabber_chat_find_by_conv(PurpleConversation *conv); +JabberChat *jabber_chat_find_by_conv(PurpleChatConversation *conv); void jabber_chat_destroy(JabberChat *chat); void jabber_chat_free(JabberChat *chat); -gboolean jabber_chat_find_buddy(PurpleConversation *conv, const char *name); +gboolean jabber_chat_find_buddy(PurpleChatConversation *conv, const char *name); void jabber_chat_invite(PurpleConnection *gc, int id, const char *message, const char *name); void jabber_chat_leave(PurpleConnection *gc, int id); -char *jabber_chat_buddy_real_name(PurpleConnection *gc, int id, const char *who); +char *jabber_chat_user_real_name(PurpleConnection *gc, int id, const char *who); void jabber_chat_request_room_configure(JabberChat *chat); void jabber_chat_create_instant_room(JabberChat *chat); void jabber_chat_register(JabberChat *chat); diff --git a/libpurple/protocols/jabber/disco.c b/libpurple/protocols/jabber/disco.c index 1b5a3deac1..82f0f03fa8 100644 --- a/libpurple/protocols/jabber/disco.c +++ b/libpurple/protocols/jabber/disco.c @@ -526,8 +526,8 @@ jabber_disco_server_info_result_cb(JabberStream *js, const char *from, js->pep = TRUE; purple_connection_set_flags(gc, purple_connection_get_flags(gc) - | PURPLE_CONNECTION_SUPPORT_MOODS - | PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES); + | PURPLE_CONNECTION_FLAG_SUPPORT_MOODS + | PURPLE_CONNECTION_FLAG_SUPPORT_MOOD_MESSAGES); } if (!category || strcmp(category, "server")) continue; diff --git a/libpurple/protocols/jabber/google/google.c b/libpurple/protocols/jabber/google/google.c index 55cb68cab5..ba79112c14 100644 --- a/libpurple/protocols/jabber/google/google.c +++ b/libpurple/protocols/jabber/google/google.c @@ -152,7 +152,7 @@ void google_buddy_node_chat(PurpleBlistNode *node, gpointer data) gchar *room; gchar *uuid = purple_uuid_random(); - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = PURPLE_BUDDY(node); gc = purple_account_get_connection(purple_buddy_get_account(buddy)); diff --git a/libpurple/protocols/jabber/google/google_roster.c b/libpurple/protocols/jabber/google/google_roster.c index b7714b8be6..dcab1a1e2c 100644 --- a/libpurple/protocols/jabber/google/google_roster.c +++ b/libpurple/protocols/jabber/google/google_roster.c @@ -28,7 +28,7 @@ void jabber_google_roster_outgoing(JabberStream *js, xmlnode *query, xmlnode *item) { PurpleAccount *account = purple_connection_get_account(js->gc); - GSList *list = account->deny; + GSList *list = purple_account_privacy_get_denied(account); const char *jid = xmlnode_get_attrib(item, "jid"); char *jid_norm = (char *)jabber_normalize(account, jid); @@ -64,12 +64,12 @@ gboolean jabber_google_roster_incoming(JabberStream *js, xmlnode *item) jid_norm = g_strdup(jabber_normalize(account, jid)); - on_block_list = NULL != g_slist_find_custom(account->deny, jid_norm, - (GCompareFunc)strcmp); + on_block_list = NULL != g_slist_find_custom(purple_account_privacy_get_denied(account), + jid_norm, (GCompareFunc)strcmp); if (grt && (*grt == 'H' || *grt == 'h')) { /* Hidden; don't show this buddy. */ - GSList *buddies = purple_find_buddies(account, jid_norm); + GSList *buddies = purple_blist_find_buddies(account, jid_norm); if (buddies) { purple_debug_info("jabber", "Removing %s from local buddy list\n", jid_norm); @@ -86,10 +86,10 @@ gboolean jabber_google_roster_incoming(JabberStream *js, xmlnode *item) if (!on_block_list && (grt && (*grt == 'B' || *grt == 'b'))) { purple_debug_info("jabber", "Blocking %s\n", jid_norm); - purple_privacy_deny_add(account, jid_norm, TRUE); + purple_account_privacy_deny_add(account, jid_norm, TRUE); } else if (on_block_list && (!grt || (*grt != 'B' && *grt != 'b' ))){ purple_debug_info("jabber", "Unblocking %s\n", jid_norm); - purple_privacy_deny_remove(account, jid_norm, TRUE); + purple_account_privacy_deny_remove(account, jid_norm, TRUE); } g_free(jid_norm); @@ -111,7 +111,7 @@ void jabber_google_roster_add_deny(JabberStream *js, const char *who) jb = jabber_buddy_find(js, who, TRUE); account = purple_connection_get_account(js->gc); - buddies = purple_find_buddies(account, who); + buddies = purple_blist_find_buddies(account, who); if(!buddies) return; @@ -132,7 +132,7 @@ void jabber_google_roster_add_deny(JabberStream *js, const char *who) buddies = g_slist_delete_link(buddies, buddies); } while (buddies); - balias = purple_buddy_get_local_buddy_alias(b); + balias = purple_buddy_get_local_alias(b); xmlnode_set_attrib(item, "jid", who); xmlnode_set_attrib(item, "name", balias ? balias : ""); xmlnode_set_attrib(item, "gr:t", "B"); @@ -169,7 +169,7 @@ void jabber_google_roster_rem_deny(JabberStream *js, const char *who) PurpleBuddy *b; const char *balias; - buddies = purple_find_buddies(purple_connection_get_account(js->gc), who); + buddies = purple_blist_find_buddies(purple_connection_get_account(js->gc), who); if(!buddies) return; @@ -190,7 +190,7 @@ void jabber_google_roster_rem_deny(JabberStream *js, const char *who) buddies = g_slist_delete_link(buddies, buddies); } while (buddies); - balias = purple_buddy_get_local_buddy_alias(b); + balias = purple_buddy_get_local_alias(b); xmlnode_set_attrib(item, "jid", who); xmlnode_set_attrib(item, "name", balias ? balias : ""); xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER); diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c index 85ee7984d2..f2ca99c993 100644 --- a/libpurple/protocols/jabber/jabber.c +++ b/libpurple/protocols/jabber/jabber.c @@ -24,7 +24,7 @@ #include "account.h" #include "accountopt.h" -#include "blist.h" +#include "buddylist.h" #include "core.h" #include "cmds.h" #include "connection.h" @@ -36,7 +36,6 @@ #include "message.h" #include "notify.h" #include "pluginpref.h" -#include "privacy.h" #include "proxy.h" #include "prpl.h" #include "request.h" @@ -392,8 +391,11 @@ static int jabber_do_send(JabberStream *js, const char *data, int len) static void jabber_send_cb(gpointer data, gint source, PurpleInputCondition cond) { JabberStream *js = data; + const gchar *output = NULL; int ret, writelen; - writelen = purple_circ_buffer_get_max_read(js->write_buffer); + + writelen = purple_circular_buffer_get_max_read(js->write_buffer); + output = purple_circular_buffer_get_output(js->write_buffer); if (writelen == 0) { purple_input_remove(js->writeh); @@ -401,7 +403,7 @@ static void jabber_send_cb(gpointer data, gint source, PurpleInputCondition cond return; } - ret = jabber_do_send(js, js->write_buffer->outptr, writelen); + ret = jabber_do_send(js, output, writelen); if (ret < 0 && errno == EAGAIN) return; @@ -414,7 +416,7 @@ static void jabber_send_cb(gpointer data, gint source, PurpleInputCondition cond return; } - purple_circ_buffer_mark_read(js->write_buffer, ret); + purple_circular_buffer_mark_read(js->write_buffer, ret); } static gboolean do_jabber_send_raw(JabberStream *js, const char *data, int len) @@ -457,7 +459,7 @@ static gboolean do_jabber_send_raw(JabberStream *js, const char *data, int len) js->writeh = purple_input_add( js->gsc ? js->gsc->fd : js->fd, PURPLE_INPUT_WRITE, jabber_send_cb, js); - purple_circ_buffer_append(js->write_buffer, + purple_circular_buffer_append(js->write_buffer, data + ret, len - ret); } @@ -993,7 +995,7 @@ jabber_stream_new(PurpleAccount *account) js->chats = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)jabber_chat_free); js->next_id = g_random_int(); - js->write_buffer = purple_circ_buffer_new(512); + js->write_buffer = purple_circular_buffer_new(512); js->old_length = 0; js->keepalive_timeout = 0; js->max_inactivity = DEFAULT_INACTIVITY_TIME; @@ -1083,7 +1085,7 @@ jabber_login(PurpleAccount *account) JabberStream *js; PurpleStoredImage *image; - purple_connection_set_flags(gc, PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY); + purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_HTML | PURPLE_CONNECTION_FLAG_ALLOW_CUSTOM_SMILEY); js = jabber_stream_new(account); if (js == NULL) return; @@ -1343,7 +1345,7 @@ void jabber_register_parse(JabberStream *js, const char *from, JabberIqType type if(js->registration) { /* get rid of the login thingy */ - purple_connection_set_state(js->gc, PURPLE_CONNECTED); + purple_connection_set_state(js->gc, PURPLE_CONNECTION_CONNECTED); } if(xmlnode_get_child(query, "registered")) { @@ -1372,9 +1374,10 @@ void jabber_register_parse(JabberStream *js, const char *from, JabberIqType type g_free(href); if(js->registration) { - js->gc->wants_to_die = TRUE; /* succeeded, but we have no login info */ purple_account_register_completed(account, TRUE); + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, + _("Registration completed successfully. Please reconnect to continue.")); jabber_connection_schedule_close(js); } return; @@ -1415,7 +1418,7 @@ void jabber_register_parse(JabberStream *js, const char *from, JabberIqType type if((node = xmlnode_get_child(query, "name"))) { if(js->registration) field = purple_request_field_string_new("name", _("Name"), - purple_account_get_alias(purple_connection_get_account(js->gc)), FALSE); + purple_account_get_private_alias(purple_connection_get_account(js->gc)), FALSE); else { char *data = xmlnode_get_data(node); field = purple_request_field_string_new("name", _("Name"), data, FALSE); @@ -1549,8 +1552,8 @@ void jabber_unregister_account(PurpleAccount *account, PurpleAccountUnregistrati PurpleConnection *gc = purple_account_get_connection(account); JabberStream *js; - if (purple_connection_get_state(gc) != PURPLE_CONNECTED) { - if (purple_connection_get_state(gc) != PURPLE_CONNECTING) + if (purple_connection_get_state(gc) != PURPLE_CONNECTION_CONNECTED) { + if (purple_connection_get_state(gc) != PURPLE_CONNECTION_CONNECTING) jabber_login(account); js = purple_connection_get_protocol_data(gc); js->unregistration = TRUE; @@ -1644,7 +1647,7 @@ void jabber_close(PurpleConnection *gc) g_free(js->caps_hash); if (js->write_buffer) - purple_circ_buffer_destroy(js->write_buffer); + g_object_unref(G_OBJECT(js->write_buffer)); if(js->writeh) purple_input_remove(js->writeh); if (js->auth_mech && js->auth_mech->dispose) @@ -1744,7 +1747,7 @@ void jabber_stream_set_state(JabberStream *js, JabberStreamState state) /* Start up the inactivity timer */ jabber_stream_restart_inactivity_timer(js); - purple_connection_set_state(js->gc, PURPLE_CONNECTED); + purple_connection_set_state(js->gc, PURPLE_CONNECTION_CONNECTED); break; } @@ -1776,6 +1779,7 @@ void jabber_blocklist_parse_push(JabberStream *js, const char *from, xmlnode *item; PurpleAccount *account; gboolean is_block; + GSList *deny; if (!jabber_is_own_account(js, from)) { xmlnode *error, *x; @@ -1801,8 +1805,8 @@ void jabber_blocklist_parse_push(JabberStream *js, const char *from, /* Unblock everyone */ purple_debug_info("jabber", "Received unblock push. Unblocking everyone.\n"); - while (account->deny != NULL) { - purple_privacy_deny_remove(account, account->deny->data, TRUE); + while ((deny = purple_account_privacy_get_denied(account)) != NULL) { + purple_account_privacy_deny_remove(account, deny->data, TRUE); } } else if (item == NULL) { /* An empty <block/> is bogus */ @@ -1824,9 +1828,9 @@ void jabber_blocklist_parse_push(JabberStream *js, const char *from, continue; if (is_block) - purple_privacy_deny_add(account, jid, TRUE); + purple_account_privacy_deny_add(account, jid, TRUE); else - purple_privacy_deny_remove(account, jid, TRUE); + purple_account_privacy_deny_remove(account, jid, TRUE); } } @@ -1841,6 +1845,7 @@ static void jabber_blocklist_parse(JabberStream *js, const char *from, { xmlnode *blocklist, *item; PurpleAccount *account; + GSList *deny; blocklist = xmlnode_get_child_with_namespace(packet, "blocklist", NS_SIMPLE_BLOCKING); @@ -1850,19 +1855,19 @@ static void jabber_blocklist_parse(JabberStream *js, const char *from, return; /* This is the only privacy method supported by XEP-0191 */ - purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_DENY_USERS); /* * TODO: When account->deny is something more than a hash table, this can * be re-written to find the set intersection and difference. */ - while (account->deny) - purple_privacy_deny_remove(account, account->deny->data, TRUE); + while ((deny = purple_account_privacy_get_denied(account))) + purple_account_privacy_deny_remove(account, deny->data, TRUE); item = xmlnode_get_child(blocklist, "item"); while (item != NULL) { const char *jid = xmlnode_get_attrib(item, "jid"); - purple_privacy_deny_add(account, jid, TRUE); + purple_account_privacy_deny_add(account, jid, TRUE); item = xmlnode_get_next_twin(item); } } @@ -2339,21 +2344,21 @@ GList *jabber_status_types(PurpleAccount *account) { PurpleStatusType *type; GList *types = NULL; - PurpleValue *priority_value; - PurpleValue *buzz_enabled; + GValue *priority_value; + GValue *buzz_enabled; - priority_value = purple_value_new(PURPLE_TYPE_INT); - purple_value_set_int(priority_value, 1); - buzz_enabled = purple_value_new(PURPLE_TYPE_BOOLEAN); - purple_value_set_boolean(buzz_enabled, TRUE); + priority_value = purple_g_value_new(G_TYPE_INT); + g_value_set_int(priority_value, 1); + buzz_enabled = purple_g_value_new(G_TYPE_BOOLEAN); + g_value_set_boolean(buzz_enabled, TRUE); type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_ONLINE), NULL, TRUE, TRUE, FALSE, "priority", _("Priority"), priority_value, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), - "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), - "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), + "mood", _("Mood"), purple_g_value_new(G_TYPE_STRING), + "moodtext", _("Mood Text"), purple_g_value_new(G_TYPE_STRING), + "nick", _("Nickname"), purple_g_value_new(G_TYPE_STRING), "buzz", _("Allow Buzz"), buzz_enabled, NULL); types = g_list_prepend(types, type); @@ -2361,69 +2366,69 @@ GList *jabber_status_types(PurpleAccount *account) type = purple_status_type_new_with_attrs(PURPLE_STATUS_MOOD, "mood", NULL, TRUE, TRUE, TRUE, - PURPLE_MOOD_NAME, _("Mood Name"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_MOOD_COMMENT, _("Mood Comment"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_MOOD_NAME, _("Mood Name"), purple_g_value_new(G_TYPE_STRING), + PURPLE_MOOD_COMMENT, _("Mood Comment"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_prepend(types, type); - priority_value = purple_value_new(PURPLE_TYPE_INT); - purple_value_set_int(priority_value, 1); - buzz_enabled = purple_value_new(PURPLE_TYPE_BOOLEAN); - purple_value_set_boolean(buzz_enabled, TRUE); + priority_value = purple_g_value_new(G_TYPE_INT); + g_value_set_int(priority_value, 1); + buzz_enabled = purple_g_value_new(G_TYPE_BOOLEAN); + g_value_set_boolean(buzz_enabled, TRUE); type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_CHAT), _("Chatty"), TRUE, TRUE, FALSE, "priority", _("Priority"), priority_value, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), - "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), - "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), + "mood", _("Mood"), purple_g_value_new(G_TYPE_STRING), + "moodtext", _("Mood Text"), purple_g_value_new(G_TYPE_STRING), + "nick", _("Nickname"), purple_g_value_new(G_TYPE_STRING), "buzz", _("Allow Buzz"), buzz_enabled, NULL); types = g_list_prepend(types, type); - priority_value = purple_value_new(PURPLE_TYPE_INT); - purple_value_set_int(priority_value, 0); - buzz_enabled = purple_value_new(PURPLE_TYPE_BOOLEAN); - purple_value_set_boolean(buzz_enabled, TRUE); + priority_value = purple_g_value_new(G_TYPE_INT); + g_value_set_int(priority_value, 0); + buzz_enabled = purple_g_value_new(G_TYPE_BOOLEAN); + g_value_set_boolean(buzz_enabled, TRUE); type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_AWAY), NULL, TRUE, TRUE, FALSE, "priority", _("Priority"), priority_value, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), - "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), - "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), + "mood", _("Mood"), purple_g_value_new(G_TYPE_STRING), + "moodtext", _("Mood Text"), purple_g_value_new(G_TYPE_STRING), + "nick", _("Nickname"), purple_g_value_new(G_TYPE_STRING), "buzz", _("Allow Buzz"), buzz_enabled, NULL); types = g_list_prepend(types, type); - priority_value = purple_value_new(PURPLE_TYPE_INT); - purple_value_set_int(priority_value, 0); - buzz_enabled = purple_value_new(PURPLE_TYPE_BOOLEAN); - purple_value_set_boolean(buzz_enabled, TRUE); + priority_value = purple_g_value_new(G_TYPE_INT); + g_value_set_int(priority_value, 0); + buzz_enabled = purple_g_value_new(G_TYPE_BOOLEAN); + g_value_set_boolean(buzz_enabled, TRUE); type = purple_status_type_new_with_attrs(PURPLE_STATUS_EXTENDED_AWAY, jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_XA), NULL, TRUE, TRUE, FALSE, "priority", _("Priority"), priority_value, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), - "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), - "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), + "mood", _("Mood"), purple_g_value_new(G_TYPE_STRING), + "moodtext", _("Mood Text"), purple_g_value_new(G_TYPE_STRING), + "nick", _("Nickname"), purple_g_value_new(G_TYPE_STRING), "buzz", _("Allow Buzz"), buzz_enabled, NULL); types = g_list_prepend(types, type); - priority_value = purple_value_new(PURPLE_TYPE_INT); - purple_value_set_int(priority_value, 0); + priority_value = purple_g_value_new(G_TYPE_INT); + g_value_set_int(priority_value, 0); type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE, jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_DND), _("Do Not Disturb"), TRUE, TRUE, FALSE, "priority", _("Priority"), priority_value, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING), - "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING), - "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), + "mood", _("Mood"), purple_g_value_new(G_TYPE_STRING), + "moodtext", _("Mood Text"), purple_g_value_new(G_TYPE_STRING), + "nick", _("Nickname"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_prepend(types, type); @@ -2435,21 +2440,21 @@ GList *jabber_status_types(PurpleAccount *account) type = purple_status_type_new_with_attrs(PURPLE_STATUS_OFFLINE, jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_UNAVAILABLE), NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_prepend(types, type); type = purple_status_type_new_with_attrs(PURPLE_STATUS_TUNE, "tune", NULL, FALSE, TRUE, TRUE, - PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT), - PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT), - PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_g_value_new(G_TYPE_STRING), + PURPLE_TUNE_TITLE, _("Tune Title"), purple_g_value_new(G_TYPE_STRING), + PURPLE_TUNE_ALBUM, _("Tune Album"), purple_g_value_new(G_TYPE_STRING), + PURPLE_TUNE_GENRE, _("Tune Genre"), purple_g_value_new(G_TYPE_STRING), + PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_g_value_new(G_TYPE_STRING), + PURPLE_TUNE_TRACK, _("Tune Track"), purple_g_value_new(G_TYPE_STRING), + PURPLE_TUNE_TIME, _("Tune Time"), purple_g_value_new(G_TYPE_INT), + PURPLE_TUNE_YEAR, _("Tune Year"), purple_g_value_new(G_TYPE_INT), + PURPLE_TUNE_URL, _("Tune URL"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_prepend(types, type); @@ -2589,7 +2594,7 @@ PurpleChat *jabber_find_blist_chat(PurpleAccount *account, const char *name) PurpleChat *chat = (PurpleChat*)cnode; const char *room, *server; GHashTable *components; - if(!PURPLE_BLIST_NODE_IS_CHAT(cnode)) + if(!PURPLE_IS_CHAT(cnode)) continue; if (purple_chat_get_account(chat) != account) @@ -2803,7 +2808,7 @@ char *jabber_parse_error(JabberStream *js, static PurpleCmdRet jabber_cmd_chat_config(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - JabberChat *chat = jabber_chat_find_by_conv(conv); + JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv)); if (!chat) return PURPLE_CMD_RET_FAILED; @@ -2815,7 +2820,7 @@ static PurpleCmdRet jabber_cmd_chat_config(PurpleConversation *conv, static PurpleCmdRet jabber_cmd_chat_register(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - JabberChat *chat = jabber_chat_find_by_conv(conv); + JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv)); if (!chat) return PURPLE_CMD_RET_FAILED; @@ -2827,7 +2832,7 @@ static PurpleCmdRet jabber_cmd_chat_register(PurpleConversation *conv, static PurpleCmdRet jabber_cmd_chat_topic(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - JabberChat *chat = jabber_chat_find_by_conv(conv); + JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv)); if (!chat) return PURPLE_CMD_RET_FAILED; @@ -2835,7 +2840,7 @@ static PurpleCmdRet jabber_cmd_chat_topic(PurpleConversation *conv, if (args && args[0] && *args[0]) jabber_chat_change_topic(chat, args[0]); else { - const char *cur = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(conv)); + const char *cur = purple_chat_conversation_get_topic(PURPLE_CHAT_CONVERSATION(conv)); char *buf, *tmp, *tmp2; if (cur) { @@ -2846,7 +2851,7 @@ static PurpleCmdRet jabber_cmd_chat_topic(PurpleConversation *conv, g_free(tmp2); } else buf = g_strdup(_("No topic is set")); - purple_conv_chat_write(PURPLE_CONV_CHAT(conv), "", buf, + purple_conversation_write_message(conv, "", buf, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG, time(NULL)); g_free(buf); } @@ -2857,7 +2862,7 @@ static PurpleCmdRet jabber_cmd_chat_topic(PurpleConversation *conv, static PurpleCmdRet jabber_cmd_chat_nick(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - JabberChat *chat = jabber_chat_find_by_conv(conv); + JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv)); if(!chat || !args || !args[0]) return PURPLE_CMD_RET_FAILED; @@ -2876,7 +2881,7 @@ static PurpleCmdRet jabber_cmd_chat_nick(PurpleConversation *conv, static PurpleCmdRet jabber_cmd_chat_part(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - JabberChat *chat = jabber_chat_find_by_conv(conv); + JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv)); if (!chat) return PURPLE_CMD_RET_FAILED; @@ -2888,7 +2893,7 @@ static PurpleCmdRet jabber_cmd_chat_part(PurpleConversation *conv, static PurpleCmdRet jabber_cmd_chat_ban(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - JabberChat *chat = jabber_chat_find_by_conv(conv); + JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv)); if(!chat || !args || !args[0]) return PURPLE_CMD_RET_FAILED; @@ -2904,7 +2909,7 @@ static PurpleCmdRet jabber_cmd_chat_ban(PurpleConversation *conv, static PurpleCmdRet jabber_cmd_chat_affiliate(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - JabberChat *chat = jabber_chat_find_by_conv(conv); + JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv)); if (!chat || !args || !args[0]) return PURPLE_CMD_RET_FAILED; @@ -2940,7 +2945,7 @@ static PurpleCmdRet jabber_cmd_chat_affiliate(PurpleConversation *conv, static PurpleCmdRet jabber_cmd_chat_role(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - JabberChat *chat = jabber_chat_find_by_conv(conv); + JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv)); if (!chat || !args || !args[0]) return PURPLE_CMD_RET_FAILED; @@ -2979,7 +2984,7 @@ static PurpleCmdRet jabber_cmd_chat_invite(PurpleConversation *conv, return PURPLE_CMD_RET_FAILED; jabber_chat_invite(purple_conversation_get_connection(conv), - purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), args[1] ? args[1] : "", + purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)), args[1] ? args[1] : "", args[0]); return PURPLE_CMD_RET_OK; @@ -2988,7 +2993,7 @@ static PurpleCmdRet jabber_cmd_chat_invite(PurpleConversation *conv, static PurpleCmdRet jabber_cmd_chat_join(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - JabberChat *chat = jabber_chat_find_by_conv(conv); + JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv)); GHashTable *components; JabberID *jid = NULL; const char *room = NULL, *server = NULL, *handle = NULL; @@ -3035,7 +3040,7 @@ static PurpleCmdRet jabber_cmd_chat_join(PurpleConversation *conv, static PurpleCmdRet jabber_cmd_chat_kick(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - JabberChat *chat = jabber_chat_find_by_conv(conv); + JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv)); if(!chat || !args || !args[0]) return PURPLE_CMD_RET_FAILED; @@ -3051,7 +3056,7 @@ static PurpleCmdRet jabber_cmd_chat_kick(PurpleConversation *conv, static PurpleCmdRet jabber_cmd_chat_msg(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - JabberChat *chat = jabber_chat_find_by_conv(conv); + JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv)); char *who; if (!chat) @@ -3091,7 +3096,7 @@ static gboolean _jabber_send_buzz(JabberStream *js, const char *username, char * JabberBuddyResource *jbr; PurpleConnection *gc = js->gc; PurpleBuddy *buddy = - purple_find_buddy(purple_connection_get_account(gc), username); + purple_blist_find_buddy(purple_connection_get_account(gc), username); const gchar *alias = buddy ? purple_buddy_get_contact_alias(buddy) : username; @@ -3151,7 +3156,7 @@ static PurpleCmdRet jabber_cmd_buzz(PurpleConversation *conv, if (!args || !args[0]) { /* use the buddy from conversation, if it's a one-to-one conversation */ - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + if (PURPLE_IS_IM_CONVERSATION(conv)) { who = purple_conversation_get_name(conv); } else { return PURPLE_CMD_RET_FAILED; @@ -3160,7 +3165,7 @@ static PurpleCmdRet jabber_cmd_buzz(PurpleConversation *conv, who = args[0]; } - buddy = purple_find_buddy(account, who); + buddy = purple_blist_find_buddy(account, who); if (buddy != NULL) alias = purple_buddy_get_contact_alias(buddy); else @@ -3194,7 +3199,7 @@ gboolean jabber_send_attention(PurpleConnection *gc, const char *username, guint if (!_jabber_send_buzz(js, username, &error)) { PurpleAccount *account = purple_connection_get_account(gc); PurpleConversation *conv = - purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, username, account); + purple_conversations_find_with_account(username, account); purple_debug_error("jabber", "jabber_send_attention: jabber_cmd_buzz failed with error: %s\n", error ? error : "(NULL)"); if (conv) { @@ -3938,41 +3943,38 @@ void jabber_plugin_init(PurplePlugin *plugin) /* IPC functions */ purple_plugin_ipc_register(plugin, "contact_has_feature", PURPLE_CALLBACK(jabber_ipc_contact_has_feature), purple_marshal_BOOLEAN__POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); + G_TYPE_BOOLEAN, 3, + PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, G_TYPE_STRING); purple_plugin_ipc_register(plugin, "add_feature", PURPLE_CALLBACK(jabber_ipc_add_feature), purple_marshal_VOID__POINTER, - NULL, 1, - purple_value_new(PURPLE_TYPE_STRING)); + G_TYPE_NONE, 1, G_TYPE_STRING); purple_plugin_ipc_register(plugin, "register_namespace_watcher", PURPLE_CALLBACK(jabber_iq_signal_register), purple_marshal_VOID__POINTER_POINTER, - NULL, 2, - purple_value_new(PURPLE_TYPE_STRING), /* node */ - purple_value_new(PURPLE_TYPE_STRING)); /* namespace */ + G_TYPE_NONE, 2, + G_TYPE_STRING, /* node */ + G_TYPE_STRING); /* namespace */ purple_plugin_ipc_register(plugin, "unregister_namespace_watcher", PURPLE_CALLBACK(jabber_iq_signal_unregister), purple_marshal_VOID__POINTER_POINTER, - NULL, 2, - purple_value_new(PURPLE_TYPE_STRING), /* node */ - purple_value_new(PURPLE_TYPE_STRING)); /* namespace */ + G_TYPE_NONE, 2, + G_TYPE_STRING, /* node */ + G_TYPE_STRING); /* namespace */ purple_signal_register(plugin, "jabber-register-namespace-watcher", purple_marshal_VOID__POINTER_POINTER, - NULL, 2, - purple_value_new(PURPLE_TYPE_STRING), /* node */ - purple_value_new(PURPLE_TYPE_STRING)); /* namespace */ + G_TYPE_NONE, 2, + G_TYPE_STRING, /* node */ + G_TYPE_STRING); /* namespace */ purple_signal_register(plugin, "jabber-unregister-namespace-watcher", purple_marshal_VOID__POINTER_POINTER, - NULL, 2, - purple_value_new(PURPLE_TYPE_STRING), /* node */ - purple_value_new(PURPLE_TYPE_STRING)); /* namespace */ + G_TYPE_NONE, 2, + G_TYPE_STRING, /* node */ + G_TYPE_STRING); /* namespace */ purple_signal_connect(plugin, "jabber-register-namespace-watcher", plugin, PURPLE_CALLBACK(jabber_iq_signal_register), NULL); @@ -3981,14 +3983,14 @@ void jabber_plugin_init(PurplePlugin *plugin) purple_signal_register(plugin, "jabber-receiving-xmlnode", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), - purple_value_new_outgoing(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_XMLNODE)); + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_CONNECTION, + G_TYPE_POINTER); /* modifiable xmlnode */ purple_signal_register(plugin, "jabber-sending-xmlnode", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), - purple_value_new_outgoing(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_XMLNODE)); + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_CONNECTION, + G_TYPE_POINTER); /* modifiable xmlnode */ /* * Do not remove this or the plugin will fail. Completely. You have been @@ -3999,45 +4001,45 @@ void jabber_plugin_init(PurplePlugin *plugin) NULL, PURPLE_SIGNAL_PRIORITY_HIGHEST); purple_signal_register(plugin, "jabber-sending-text", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), - purple_value_new_outgoing(PURPLE_TYPE_STRING)); + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_CONNECTION, + G_TYPE_POINTER); /* pointer to a string */ purple_signal_register(plugin, "jabber-receiving-message", purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 6, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), - purple_value_new(PURPLE_TYPE_STRING), /* type */ - purple_value_new(PURPLE_TYPE_STRING), /* id */ - purple_value_new(PURPLE_TYPE_STRING), /* from */ - purple_value_new(PURPLE_TYPE_STRING), /* to */ - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_XMLNODE)); + G_TYPE_BOOLEAN, 6, + PURPLE_TYPE_CONNECTION, + G_TYPE_STRING, /* type */ + G_TYPE_STRING, /* id */ + G_TYPE_STRING, /* from */ + G_TYPE_STRING, /* to */ + PURPLE_TYPE_XMLNODE); purple_signal_register(plugin, "jabber-receiving-iq", purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), - purple_value_new(PURPLE_TYPE_STRING), /* type */ - purple_value_new(PURPLE_TYPE_STRING), /* id */ - purple_value_new(PURPLE_TYPE_STRING), /* from */ - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_XMLNODE)); + G_TYPE_BOOLEAN, 5, + PURPLE_TYPE_CONNECTION, + G_TYPE_STRING, /* type */ + G_TYPE_STRING, /* id */ + G_TYPE_STRING, /* from */ + PURPLE_TYPE_XMLNODE); purple_signal_register(plugin, "jabber-watched-iq", purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), - purple_value_new(PURPLE_TYPE_STRING), /* type */ - purple_value_new(PURPLE_TYPE_STRING), /* id */ - purple_value_new(PURPLE_TYPE_STRING), /* from */ - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_XMLNODE)); /* child */ + G_TYPE_BOOLEAN, 5, + PURPLE_TYPE_CONNECTION, + G_TYPE_STRING, /* type */ + G_TYPE_STRING, /* id */ + G_TYPE_STRING, /* from */ + PURPLE_TYPE_XMLNODE); /* child */ purple_signal_register(plugin, "jabber-receiving-presence", purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 4, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONNECTION), - purple_value_new(PURPLE_TYPE_STRING), /* type */ - purple_value_new(PURPLE_TYPE_STRING), /* from */ - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_XMLNODE)); + G_TYPE_BOOLEAN, 4, + PURPLE_TYPE_CONNECTION, + G_TYPE_STRING, /* type */ + G_TYPE_STRING, /* from */ + PURPLE_TYPE_XMLNODE); } void jabber_plugin_uninit(PurplePlugin *plugin) diff --git a/libpurple/protocols/jabber/jabber.h b/libpurple/protocols/jabber/jabber.h index ffa3556db2..fac856e920 100644 --- a/libpurple/protocols/jabber/jabber.h +++ b/libpurple/protocols/jabber/jabber.h @@ -56,7 +56,7 @@ typedef struct _JabberStream JabberStream; #include <libxml/parser.h> #include <glib.h> -#include "circbuffer.h" +#include "circularbuffer.h" #include "connection.h" #include "dnsquery.h" #include "dnssrv.h" @@ -191,7 +191,7 @@ struct _JabberStream GSList *pending_buddy_info_requests; - PurpleCircBuffer *write_buffer; + PurpleCircularBuffer *write_buffer; guint writeh; gboolean reinit; diff --git a/libpurple/protocols/jabber/jutil.c b/libpurple/protocols/jabber/jutil.c index b02e220197..f3835515b3 100644 --- a/libpurple/protocols/jabber/jutil.c +++ b/libpurple/protocols/jabber/jutil.c @@ -22,7 +22,6 @@ */ #include "internal.h" #include "account.h" -#include "cipher.h" #include "conversation.h" #include "debug.h" #include "server.h" @@ -33,6 +32,10 @@ #include "presence.h" #include "jutil.h" +#include "ciphers/md4hash.h" +#include "ciphers/md5hash.h" +#include "ciphers/sha1hash.h" + #ifdef USE_IDN #include <idna.h> #include <stringprep.h> @@ -736,25 +739,31 @@ char * jabber_calculate_data_hash(gconstpointer data, size_t len, const gchar *hash_algo) { - PurpleCipherContext *context; + PurpleHash *hash = NULL; static gchar digest[129]; /* 512 bits hex + \0 */ - context = purple_cipher_context_new_by_name(hash_algo, NULL); - if (context == NULL) + /* FIXME: Check the source of this change and what we need here... */ + if (g_str_equal(hash_algo, "sha1")) + hash = purple_sha1_hash_new(); + else if (g_str_equal(hash_algo, "md4")) + hash = purple_md4_hash_new(); + else if (g_str_equal(hash_algo, "md5")) + hash = purple_md5_hash_new(); + if (hash == NULL) { purple_debug_error("jabber", "Could not find %s cipher\n", hash_algo); g_return_val_if_reached(NULL); } /* Hash the data */ - purple_cipher_context_append(context, data, len); - if (!purple_cipher_context_digest_to_str(context, digest, sizeof(digest))) + purple_hash_append(hash, data, len); + if (!purple_hash_digest_to_str(hash, digest, sizeof(digest))) { purple_debug_error("jabber", "Failed to get digest for %s cipher.\n", hash_algo); g_return_val_if_reached(NULL); } - purple_cipher_context_destroy(context); + g_object_unref(G_OBJECT(hash)); return g_strdup(digest); } diff --git a/libpurple/protocols/jabber/libfacebook.c b/libpurple/protocols/jabber/libfacebook.c index b426eac356..3e3f2299b7 100644 --- a/libpurple/protocols/jabber/libfacebook.c +++ b/libpurple/protocols/jabber/libfacebook.c @@ -112,7 +112,7 @@ static PurplePluginProtocolInfo prpl_info = jabber_normalize, /* normalize */ jabber_set_buddy_icon, /* set_buddy_icon */ NULL, /* remove_group */ - jabber_chat_buddy_real_name, /* get_cb_real_name */ + jabber_chat_user_real_name, /* get_cb_real_name */ jabber_chat_set_topic, /* set_chat_topic */ jabber_find_blist_chat, /* find_blist_chat */ jabber_roomlist_get_list, /* roomlist_get_list */ @@ -229,11 +229,11 @@ static gboolean xmpp_uri_handler(const char *proto, const char *user, GHashTable if (!params || g_hash_table_lookup_extended(params, "message", NULL, NULL)) { char *body = g_hash_table_lookup(params, "body"); if (user && *user) { - PurpleConversation *conv = - purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, user); - purple_conversation_present(conv); + PurpleIMConversation *im = + purple_im_conversation_new(acct, user); + purple_conversation_present(PURPLE_CONVERSATION(im)); if (body && *body) - purple_conv_send_confirm(conv, body); + purple_conversation_send_confirm(PURPLE_CONVERSATION(im), body); } } else if (g_hash_table_lookup_extended(params, "roster", NULL, NULL)) { char *name = g_hash_table_lookup(params, "name"); diff --git a/libpurple/protocols/jabber/libgtalk.c b/libpurple/protocols/jabber/libgtalk.c index d52d1842c2..b2e3c3253c 100644 --- a/libpurple/protocols/jabber/libgtalk.c +++ b/libpurple/protocols/jabber/libgtalk.c @@ -112,7 +112,7 @@ static PurplePluginProtocolInfo prpl_info = jabber_normalize, /* normalize */ jabber_set_buddy_icon, /* set_buddy_icon */ NULL, /* remove_group */ - jabber_chat_buddy_real_name, /* get_cb_real_name */ + jabber_chat_user_real_name, /* get_cb_real_name */ jabber_chat_set_topic, /* set_chat_topic */ jabber_find_blist_chat, /* find_blist_chat */ jabber_roomlist_get_list, /* roomlist_get_list */ @@ -229,11 +229,11 @@ static gboolean xmpp_uri_handler(const char *proto, const char *user, GHashTable if (!params || g_hash_table_lookup_extended(params, "message", NULL, NULL)) { char *body = g_hash_table_lookup(params, "body"); if (user && *user) { - PurpleConversation *conv = - purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, user); - purple_conversation_present(conv); + PurpleIMConversation *im = + purple_im_conversation_new(acct, user); + purple_conversation_present(PURPLE_CONVERSATION(im)); if (body && *body) - purple_conv_send_confirm(conv, body); + purple_conversation_send_confirm(PURPLE_CONVERSATION(im), body); } } else if (g_hash_table_lookup_extended(params, "roster", NULL, NULL)) { char *name = g_hash_table_lookup(params, "name"); diff --git a/libpurple/protocols/jabber/libxmpp.c b/libpurple/protocols/jabber/libxmpp.c index 53b7b9bd75..c76395640b 100644 --- a/libpurple/protocols/jabber/libxmpp.c +++ b/libpurple/protocols/jabber/libxmpp.c @@ -106,7 +106,7 @@ static PurplePluginProtocolInfo prpl_info = jabber_normalize, /* normalize */ jabber_set_buddy_icon, /* set_buddy_icon */ NULL, /* remove_group */ - jabber_chat_buddy_real_name, /* get_cb_real_name */ + jabber_chat_user_real_name, /* get_cb_real_name */ jabber_chat_set_topic, /* set_chat_topic */ jabber_find_blist_chat, /* find_blist_chat */ jabber_roomlist_get_list, /* roomlist_get_list */ @@ -223,11 +223,11 @@ static gboolean xmpp_uri_handler(const char *proto, const char *user, GHashTable if (!params || g_hash_table_lookup_extended(params, "message", NULL, NULL)) { char *body = g_hash_table_lookup(params, "body"); if (user && *user) { - PurpleConversation *conv = - purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, user); - purple_conversation_present(conv); + PurpleIMConversation *im = + purple_im_conversation_new(acct, user); + purple_conversation_present(PURPLE_CONVERSATION(im)); if (body && *body) - purple_conv_send_confirm(conv, body); + purple_conversation_send_confirm(PURPLE_CONVERSATION(im), body); } } else if (g_hash_table_lookup_extended(params, "roster", NULL, NULL)) { char *name = g_hash_table_lookup(params, "name"); diff --git a/libpurple/protocols/jabber/message.c b/libpurple/protocols/jabber/message.c index 4bf17f0b75..8c5ee0eb98 100644 --- a/libpurple/protocols/jabber/message.c +++ b/libpurple/protocols/jabber/message.c @@ -79,19 +79,19 @@ static void handle_chat(JabberMessage *jm) jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED; if(JM_STATE_COMPOSING == jm->chat_state) { - serv_got_typing(gc, jm->from, 0, PURPLE_TYPING); + serv_got_typing(gc, jm->from, 0, PURPLE_IM_TYPING); } else if(JM_STATE_PAUSED == jm->chat_state) { - serv_got_typing(gc, jm->from, 0, PURPLE_TYPED); + serv_got_typing(gc, jm->from, 0, PURPLE_IM_TYPED); } else if(JM_STATE_GONE == jm->chat_state) { - PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, + PurpleIMConversation *im = purple_conversations_find_im_with_account( jm->from, account); - if (conv && jid->node && jid->domain) { + if (im && jid->node && jid->domain) { char buf[256]; PurpleBuddy *buddy; g_snprintf(buf, sizeof(buf), "%s@%s", jid->node, jid->domain); - if ((buddy = purple_find_buddy(account, buf))) { + if ((buddy = purple_blist_find_buddy(account, buf))) { const char *who; char *escaped; @@ -105,7 +105,7 @@ static void handle_chat(JabberMessage *jm) /* At some point when we restructure PurpleConversation, * this should be able to be implemented by removing the * user from the conversation like we do with chats now. */ - purple_conversation_write(conv, "", buf, + purple_conversation_write(PURPLE_CONVERSATION(im), "", buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); } } @@ -122,18 +122,17 @@ static void handle_chat(JabberMessage *jm) * resource (i.e. bind/lock the conversation to this * resource). * - * This works because purple_conv_im_send gets the name + * This works because purple_im_conversation_send gets the name * from purple_conversation_get_name() */ - PurpleConversation *conv; + PurpleIMConversation *im; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - jm->from, account); - if (conv && !g_str_equal(jm->from, - purple_conversation_get_name(conv))) { + im = purple_conversations_find_im_with_account(jm->from, account); + if (im && !g_str_equal(jm->from, + purple_conversation_get_name(PURPLE_CONVERSATION(im)))) { purple_debug_info("jabber", "Binding conversation to %s\n", jm->from); - purple_conversation_set_name(conv, jm->from); + purple_conversation_set_name(PURPLE_CONVERSATION(im), jm->from); } } @@ -230,7 +229,7 @@ static void handle_groupchat(JabberMessage *jm) return; if(jm->subject) { - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(chat->conv), jid->resource, + purple_chat_conversation_set_topic(chat->conv, jid->resource, jm->subject); messageFlags |= PURPLE_MESSAGE_NO_LOG; if(!jm->xhtml && !jm->body) { @@ -241,7 +240,7 @@ static void handle_groupchat(JabberMessage *jm) msg = g_strdup_printf(_("%s has set the topic to: %s"), jid->resource, tmp2); else msg = g_strdup_printf(_("The topic is: %s"), tmp2); - purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), "", msg, messageFlags | PURPLE_MESSAGE_SYSTEM, jm->sent); + purple_conversation_write_message(PURPLE_CONVERSATION(chat->conv), "", msg, messageFlags | PURPLE_MESSAGE_SYSTEM, jm->sent); g_free(tmp); g_free(tmp2); g_free(msg); @@ -254,7 +253,7 @@ static void handle_groupchat(JabberMessage *jm) messageFlags | (jm->delayed ? PURPLE_MESSAGE_DELAYED : 0), jm->xhtml ? jm->xhtml : jm->body, jm->sent); else if(chat->muc) - purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), "", + purple_conversation_write_message(PURPLE_CONVERSATION(chat->conv), "", jm->xhtml ? jm->xhtml : jm->body, messageFlags | PURPLE_MESSAGE_SYSTEM, jm->sent); } @@ -310,7 +309,7 @@ static void handle_buzz(JabberMessage *jm) { account = purple_connection_get_account(jm->js->gc); - if (purple_find_buddy(account, jm->from) == NULL) + if (purple_blist_find_buddy(account, jm->from) == NULL) return; /* Do not accept buzzes from unknown people */ /* xmpp only has 1 attention type, so index is 0 */ @@ -487,13 +486,13 @@ static void jabber_message_request_data_cb(JabberData *data, gchar *alt, gpointer userdata) { - PurpleConversation *conv = (PurpleConversation *) userdata; + PurpleConversation *conv = PURPLE_CONVERSATION(userdata); if (data) { - purple_conv_custom_smiley_write(conv, alt, + purple_conversation_custom_smiley_write(conv, alt, jabber_data_get_data(data), jabber_data_get_size(data)); - purple_conv_custom_smiley_close(conv, alt); + purple_conversation_custom_smiley_close(conv, alt); } g_free(alt); @@ -619,19 +618,17 @@ void jabber_message_parse(JabberStream *js, xmlnode *packet) if (jid) { chat = jabber_chat_find(js, jid->node, jid->domain); if (chat) - conv = chat->conv; + conv = PURPLE_CONVERSATION(chat->conv); jabber_id_free(jid); } } else if (jm->type == JABBER_MESSAGE_NORMAL || jm->type == JABBER_MESSAGE_CHAT) { conv = - purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, - from, account); + purple_conversations_find_with_account(from, account); if (!conv) { /* we need to create the conversation here */ - conv = - purple_conversation_new(PURPLE_CONV_TYPE_IM, - account, from); + conv = PURPLE_CONVERSATION( + purple_im_conversation_new(account, from)); } } } @@ -662,7 +659,7 @@ void jabber_message_parse(JabberStream *js, xmlnode *packet) purple_debug_info("jabber", "about to add custom smiley %s to the conv\n", alt); - if (purple_conv_custom_smiley_add(conv, alt, "cid", cid, + if (purple_conversation_custom_smiley_add(conv, alt, "cid", cid, TRUE)) { const JabberData *data = jabber_data_find_remote_by_cid(js, from, cid); @@ -670,10 +667,10 @@ void jabber_message_parse(JabberStream *js, xmlnode *packet) if (data) { purple_debug_info("jabber", "data is already known\n"); - purple_conv_custom_smiley_write(conv, alt, + purple_conversation_custom_smiley_write(conv, alt, jabber_data_get_data(data), jabber_data_get_size(data)); - purple_conv_custom_smiley_close(conv, alt); + purple_conversation_custom_smiley_close(conv, alt); } else { /* we need to request the smiley (data) */ purple_debug_info("jabber", @@ -906,30 +903,24 @@ jabber_conv_support_custom_smileys(JabberStream *js, JabberBuddy *jb; JabberChat *chat; - switch (purple_conversation_get_type(conv)) { - case PURPLE_CONV_TYPE_IM: - jb = jabber_buddy_find(js, who, FALSE); - if (jb) { - return jabber_buddy_has_capability(jb, NS_BOB); - } else { - return FALSE; - } - break; - case PURPLE_CONV_TYPE_CHAT: - chat = jabber_chat_find_by_conv(conv); - if (chat) { - /* do not attempt to send custom smileys in a MUC with more than - 10 people, to avoid getting too many BoB requests */ - return jabber_chat_get_num_participants(chat) <= 10 && - jabber_chat_all_participants_have_capability(chat, - NS_BOB); - } else { - return FALSE; - } - break; - default: + if (PURPLE_IS_IM_CONVERSATION(conv)) { + jb = jabber_buddy_find(js, who, FALSE); + if (jb) { + return jabber_buddy_has_capability(jb, NS_BOB); + } else { return FALSE; - break; + } + } else { + chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv)); + if (chat) { + /* do not attempt to send custom smileys in a MUC with more than + 10 people, to avoid getting too many BoB requests */ + return jabber_chat_get_num_participants(chat) <= 10 && + jabber_chat_all_participants_have_capability(chat, + NS_BOB); + } else { + return FALSE; + } } } @@ -938,7 +929,7 @@ jabber_message_smileyfy_xhtml(JabberMessage *jm, const char *xhtml) { PurpleAccount *account = purple_connection_get_account(jm->js->gc); PurpleConversation *conv = - purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, jm->to, + purple_conversations_find_with_account(jm->to, account); if (jabber_conv_support_custom_smileys(jm->js, conv, jm->to)) { @@ -1248,7 +1239,7 @@ int jabber_message_send_chat(PurpleConnection *gc, int id, const char *msg, Purp return 1; } -unsigned int jabber_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state) +unsigned int jabber_send_typing(PurpleConnection *gc, const char *who, PurpleIMTypingState state) { JabberStream *js; JabberMessage *jm; @@ -1282,9 +1273,9 @@ unsigned int jabber_send_typing(PurpleConnection *gc, const char *who, PurpleTyp jm->to = g_strdup(who); jm->id = jabber_get_next_id(jm->js); - if(PURPLE_TYPING == state) + if(PURPLE_IM_TYPING == state) jm->chat_state = JM_STATE_COMPOSING; - else if(PURPLE_TYPED == state) + else if(PURPLE_IM_TYPED == state) jm->chat_state = JM_STATE_PAUSED; else jm->chat_state = JM_STATE_ACTIVE; diff --git a/libpurple/protocols/jabber/message.h b/libpurple/protocols/jabber/message.h index 555f8f94b7..ee943f0117 100644 --- a/libpurple/protocols/jabber/message.h +++ b/libpurple/protocols/jabber/message.h @@ -73,7 +73,7 @@ int jabber_message_send_im(PurpleConnection *gc, const char *who, const char *ms PurpleMessageFlags flags); int jabber_message_send_chat(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags); -unsigned int jabber_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state); +unsigned int jabber_send_typing(PurpleConnection *gc, const char *who, PurpleIMTypingState state); gboolean jabber_buzz_isenabled(JabberStream *js, const gchar *namespace); diff --git a/libpurple/protocols/jabber/parser.c b/libpurple/protocols/jabber/parser.c index d407c634fc..8141df13c6 100644 --- a/libpurple/protocols/jabber/parser.c +++ b/libpurple/protocols/jabber/parser.c @@ -308,7 +308,10 @@ void jabber_parser_process(JabberStream *js, const char *buf, int len) } if (js->protocol_version.major == 0 && js->protocol_version.minor == 9 && +#if 0 + /* FIXME Is this required here? */ !js->gc->disconnect_timeout && +#endif (js->state == JABBER_STREAM_INITIALIZING || js->state == JABBER_STREAM_INITIALIZING_ENCRYPTION)) { /* diff --git a/libpurple/protocols/jabber/presence.c b/libpurple/protocols/jabber/presence.c index 4421514a5b..5cc6633176 100644 --- a/libpurple/protocols/jabber/presence.c +++ b/libpurple/protocols/jabber/presence.c @@ -130,7 +130,7 @@ void jabber_presence_fake_to_self(JabberStream *js, PurpleStatus *status) * While we need to track the status of this resource, the core * only cares if we're on our own buddy list. */ - if (purple_find_buddy(account, username)) { + if (purple_blist_find_buddy(account, username)) { jbr = jabber_buddy_find_resource(jb, NULL); if (jbr) { purple_prpl_got_user_status(account, username, @@ -166,7 +166,7 @@ void jabber_set_status(PurpleAccount *account, PurpleStatus *status) js = purple_connection_get_protocol_data(gc); /* it's a mood update */ - if (purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_MOOD) { + if (purple_status_type_get_primitive(purple_status_get_status_type(status)) == PURPLE_STATUS_MOOD) { const char *mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME); const char *mood_text = @@ -540,7 +540,7 @@ static gboolean handle_presence_chat(JabberStream *js, JabberPresence *presence, xmlnode *packet) { static int i = 1; - PurpleConvChatBuddyFlags flags = PURPLE_CBFLAGS_NONE; + PurpleChatUserFlags flags = PURPLE_CHAT_USER_NONE; JabberChat *chat = presence->chat; if (presence->state == JABBER_BUDDY_STATE_ERROR) { @@ -600,7 +600,7 @@ handle_presence_chat(JabberStream *js, JabberPresence *presence, xmlnode *packet " you like to configure it, or" " accept the default settings?"), /* Default Action */ 1, - purple_connection_get_account(js->gc), NULL, chat->conv, + purple_connection_get_account(js->gc), NULL, PURPLE_CONVERSATION(chat->conv), chat, 2, _("_Configure Room"), G_CALLBACK(jabber_chat_request_room_configure), _("_Accept Defaults"), G_CALLBACK(jabber_chat_create_instant_room)); @@ -613,19 +613,19 @@ handle_presence_chat(JabberStream *js, JabberPresence *presence, xmlnode *packet } if (purple_strequal(affiliation, "owner")) - flags |= PURPLE_CBFLAGS_FOUNDER; + flags |= PURPLE_CHAT_USER_FOUNDER; if (role) { if (g_str_equal(role, "moderator")) - flags |= PURPLE_CBFLAGS_OP; + flags |= PURPLE_CHAT_USER_OP; else if (g_str_equal(role, "participant")) - flags |= PURPLE_CBFLAGS_VOICE; + flags |= PURPLE_CHAT_USER_VOICE; } if(!chat->conv) { char *room_jid = g_strdup_printf("%s@%s", presence->jid_from->node, presence->jid_from->domain); chat->id = i++; chat->conv = serv_got_joined_chat(js->gc, chat->id, room_jid); - purple_conv_chat_set_nick(PURPLE_CONV_CHAT(chat->conv), chat->handle); + purple_chat_conversation_set_nick(chat->conv, chat->handle); jabber_chat_disco_traffic(chat); g_free(room_jid); @@ -637,10 +637,10 @@ handle_presence_chat(JabberStream *js, JabberPresence *presence, xmlnode *packet jabber_chat_track_handle(chat, presence->jid_from->resource, jid, affiliation, role); if(!jabber_chat_find_buddy(chat->conv, presence->jid_from->resource)) - purple_conv_chat_add_user(PURPLE_CONV_CHAT(chat->conv), presence->jid_from->resource, + purple_chat_conversation_add_user(chat->conv, presence->jid_from->resource, jid, flags, chat->joined > 0 && ((!presence->delayed) || (presence->sent > chat->joined))); else - purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(chat->conv), presence->jid_from->resource, + purple_chat_user_set_flags(purple_chat_conversation_find_user(chat->conv, presence->jid_from->resource), flags); if (is_our_resource && chat->joined == 0) @@ -700,7 +700,7 @@ handle_presence_chat(JabberStream *js, JabberPresence *presence, xmlnode *packet chat->handle = g_strdup(nick); } - purple_conv_chat_rename_user(PURPLE_CONV_CHAT(chat->conv), + purple_chat_conversation_rename_user(chat->conv, presence->jid_from->resource, nick); jabber_chat_remove_handle(chat, @@ -783,13 +783,13 @@ handle_presence_chat(JabberStream *js, JabberPresence *presence, xmlnode *packet if(!nick_change) { if (is_our_resource) { if (kick) - purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), presence->jid_from->resource, + purple_conversation_write_message(PURPLE_CONVERSATION(chat->conv), presence->jid_from->resource, presence->status, PURPLE_MESSAGE_SYSTEM, time(NULL)); serv_got_chat_left(js->gc, chat->id); jabber_chat_destroy(chat); } else { - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(chat->conv), presence->jid_from->resource, + purple_chat_conversation_remove_user(chat->conv, presence->jid_from->resource, presence->status); jabber_chat_remove_handle(chat, presence->jid_from->resource); } @@ -806,24 +806,23 @@ handle_presence_contact(JabberStream *js, JabberPresence *presence) PurpleAccount *account; PurpleBuddy *b; char *buddy_name; - PurpleConversation *conv; + PurpleIMConversation *im; buddy_name = jabber_id_get_bare_jid(presence->jid_from); account = purple_connection_get_account(js->gc); - b = purple_find_buddy(account, buddy_name); + b = purple_blist_find_buddy(account, buddy_name); /* * Unbind/unlock from sending messages to a specific resource on * presence changes. This is locked to a specific resource when * receiving a message (in message.c). */ - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - buddy_name, account); - if (conv) { + im = purple_conversations_find_im_with_account(buddy_name, account); + if (im) { purple_debug_info("jabber", "Changed conversation binding from %s to %s\n", - purple_conversation_get_name(conv), buddy_name); - purple_conversation_set_name(conv, buddy_name); + purple_conversation_get_name(PURPLE_CONVERSATION(im)), buddy_name); + purple_conversation_set_name(PURPLE_CONVERSATION(im), buddy_name); } if (b == NULL) { @@ -958,7 +957,7 @@ void jabber_presence_parse(JabberStream *js, xmlnode *packet) xmlnode *nick; account = purple_connection_get_account(js->gc); - buddy = purple_find_buddy(account, presence.from); + buddy = purple_blist_find_buddy(account, presence.from); nick = xmlnode_get_child_with_namespace(packet, "nick", "http://jabber.org/protocol/nick"); if (nick) presence.nickname = xmlnode_get_data(nick); diff --git a/libpurple/protocols/jabber/roster.c b/libpurple/protocols/jabber/roster.c index 1dd565be35..8a4f4ccce9 100644 --- a/libpurple/protocols/jabber/roster.c +++ b/libpurple/protocols/jabber/roster.c @@ -96,7 +96,7 @@ static void remove_purple_buddies(JabberStream *js, const char *jid) { GSList *buddies, *l; - buddies = purple_find_buddies(purple_connection_get_account(js->gc), jid); + buddies = purple_blist_find_buddies(purple_connection_get_account(js->gc), jid); for(l = buddies; l; l = l->next) purple_blist_remove_buddy(l->data); @@ -110,7 +110,7 @@ static void add_purple_buddy_to_groups(JabberStream *js, const char *jid, GSList *buddies, *l; PurpleAccount *account = purple_connection_get_account(js->gc); - buddies = purple_find_buddies(purple_connection_get_account(js->gc), jid); + buddies = purple_blist_find_buddies(purple_connection_get_account(js->gc), jid); if(!groups) { if(!buddies) @@ -146,7 +146,7 @@ static void add_purple_buddy_to_groups(JabberStream *js, const char *jid, serv_got_alias(js->gc, jid, servernick); /* Alias from our roster retrieval */ - balias = purple_buddy_get_local_buddy_alias(b); + balias = purple_buddy_get_local_alias(b); if(alias && !purple_strequal(alias, balias)) purple_serv_got_private_alias(js->gc, jid, alias); g_free(l->data); @@ -169,7 +169,7 @@ static void add_purple_buddy_to_groups(JabberStream *js, const char *jid, } while(groups) { - PurpleGroup *g = purple_find_group(groups->data); + PurpleGroup *g = purple_blist_find_group(groups->data); PurpleBuddy *b = purple_buddy_new(account, jid, alias); if(!g) { @@ -178,7 +178,7 @@ static void add_purple_buddy_to_groups(JabberStream *js, const char *jid, } purple_blist_add_buddy(b, NULL, g, NULL); - purple_blist_alias_buddy(b, alias); + purple_buddy_set_local_alias(b, alias); g_free(groups->data); groups = g_slist_delete_link(groups, groups); @@ -304,7 +304,7 @@ static void jabber_roster_update(JabberStream *js, const char *name, if (js->currently_parsing_roster_push) return; - if(!(b = purple_find_buddy(purple_connection_get_account(js->gc), name))) + if(!(b = purple_blist_find_buddy(purple_connection_get_account(js->gc), name))) return; if (groups) { @@ -314,7 +314,7 @@ static void jabber_roster_update(JabberStream *js, const char *name, "groups]: groups: %s\n", name, tmp); g_free(tmp); } else { - GSList *buddies = purple_find_buddies(purple_connection_get_account(js->gc), name); + GSList *buddies = purple_blist_find_buddies(purple_connection_get_account(js->gc), name); char *tmp; if(!buddies) @@ -339,7 +339,7 @@ static void jabber_roster_update(JabberStream *js, const char *name, xmlnode_set_attrib(item, "jid", name); - balias = purple_buddy_get_local_buddy_alias(b); + balias = purple_buddy_get_local_alias(b); xmlnode_set_attrib(item, "name", balias ? balias : ""); for(l = groups; l; l = l->next) { @@ -378,7 +378,7 @@ void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, return; } - /* Adding a chat room or a chat buddy to the roster is *not* supported. */ + /* Adding a chat room or a chat user to the roster is *not* supported. */ if (jid->node && jabber_chat_find(js, jid->node, jid->domain) != NULL) { /* * This is the same thing Bonjour does. If it causes problems, move @@ -399,7 +399,7 @@ void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, * If the buddy name added contains a resource, strip that off and * rename the buddy. */ - purple_blist_rename_buddy(buddy, who); + purple_buddy_set_name(buddy, who); } jb = jabber_buddy_find(js, who, FALSE); @@ -423,10 +423,10 @@ void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, void jabber_roster_alias_change(PurpleConnection *gc, const char *name, const char *alias) { - PurpleBuddy *b = purple_find_buddy(purple_connection_get_account(gc), name); + PurpleBuddy *b = purple_blist_find_buddy(purple_connection_get_account(gc), name); if(b != NULL) { - purple_blist_alias_buddy(b, alias); + purple_buddy_set_local_alias(b, alias); purple_debug_info("jabber", "jabber_roster_alias_change(): Aliased %s to %s\n", name, alias ? alias : "(null)"); @@ -446,7 +446,7 @@ void jabber_roster_group_change(PurpleConnection *gc, const char *name, if(!old_group || !new_group || !strcmp(old_group, new_group)) return; - buddies = purple_find_buddies(purple_connection_get_account(gc), name); + buddies = purple_blist_find_buddies(purple_connection_get_account(gc), name); while(buddies) { b = buddies->data; g = purple_buddy_get_group(b); @@ -478,7 +478,7 @@ void jabber_roster_group_rename(PurpleConnection *gc, const char *old_name, void jabber_roster_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { const char *name = purple_buddy_get_name(buddy); - GSList *buddies = purple_find_buddies(purple_connection_get_account(gc), name); + GSList *buddies = purple_blist_find_buddies(purple_connection_get_account(gc), name); buddies = g_slist_remove(buddies, buddy); if(buddies != NULL) { diff --git a/libpurple/protocols/jabber/si.c b/libpurple/protocols/jabber/si.c index f36b28f060..dd039e6d63 100644 --- a/libpurple/protocols/jabber/si.c +++ b/libpurple/protocols/jabber/si.c @@ -24,7 +24,7 @@ #include "internal.h" -#include "blist.h" +#include "buddylist.h" #include "debug.h" #include "ft.h" #include "request.h" @@ -71,7 +71,7 @@ typedef struct _JabberSIXfer { JabberIBBSession *ibb_session; guint ibb_timeout_handle; - PurpleCircBuffer *ibb_buffer; + PurpleCircularBuffer *ibb_buffer; } JabberSIXfer; /* some forward declarations */ @@ -1011,7 +1011,7 @@ jabber_si_xfer_ibb_recv_data_cb(JabberIBBSession *sess, gpointer data, if (size <= purple_xfer_get_bytes_remaining(xfer)) { purple_debug_info("jabber", "about to write %" G_GSIZE_FORMAT " bytes from IBB stream\n", size); - purple_circ_buffer_append(jsx->ibb_buffer, data, size); + purple_circular_buffer_append(jsx->ibb_buffer, data, size); purple_xfer_prpl_ready(xfer); } else { /* trying to write past size of file transfers negotiated size, @@ -1028,15 +1028,15 @@ jabber_si_xfer_ibb_read(guchar **out_buffer, PurpleXfer *xfer) { JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); guchar *buffer; - gsize size; + gsize size = purple_circular_buffer_get_used(jsx->ibb_buffer); gsize tmp; - size = jsx->ibb_buffer->bufused; *out_buffer = buffer = g_malloc(size); - while ((tmp = purple_circ_buffer_get_max_read(jsx->ibb_buffer))) { - memcpy(buffer, jsx->ibb_buffer->outptr, tmp); + while ((tmp = purple_circular_buffer_get_max_read(jsx->ibb_buffer))) { + const gchar *output = purple_circular_buffer_get_output(jsx->ibb_buffer); + memcpy(buffer, output, tmp); buffer += tmp; - purple_circ_buffer_mark_read(jsx->ibb_buffer, tmp); + purple_circular_buffer_mark_read(jsx->ibb_buffer, tmp); } return size; @@ -1069,7 +1069,7 @@ jabber_si_xfer_ibb_open_cb(JabberStream *js, const char *who, const char *id, clients interpreting the block-size attribute as that (see also remark in ibb.c) */ jsx->ibb_buffer = - purple_circ_buffer_new(jabber_ibb_session_get_block_size(sess)); + purple_circular_buffer_new(jabber_ibb_session_get_block_size(sess)); /* set up read function */ purple_xfer_set_read_fnc(xfer, jabber_si_xfer_ibb_read); @@ -1157,7 +1157,7 @@ jabber_si_xfer_ibb_send_init(JabberStream *js, PurpleXfer *xfer) purple_xfer_set_write_fnc(xfer, jabber_si_xfer_ibb_write); jsx->ibb_buffer = - purple_circ_buffer_new(jabber_ibb_session_get_max_data_size(jsx->ibb_session)); + purple_circular_buffer_new(jabber_ibb_session_get_max_data_size(jsx->ibb_session)); /* open the IBB session */ jabber_ibb_session_open(jsx->ibb_session); @@ -1334,7 +1334,7 @@ static void jabber_si_xfer_free(PurpleXfer *xfer) } if (jsx->ibb_buffer) { - purple_circ_buffer_destroy(jsx->ibb_buffer); + g_object_unref(G_OBJECT(jsx->ibb_buffer)); } purple_debug_info("jabber", "jabber_si_xfer_free(): freeing jsx %p\n", jsx); diff --git a/libpurple/protocols/jabber/useravatar.c b/libpurple/protocols/jabber/useravatar.c index 914f257589..6f982bac13 100644 --- a/libpurple/protocols/jabber/useravatar.c +++ b/libpurple/protocols/jabber/useravatar.c @@ -325,7 +325,7 @@ do_buddy_avatar_update_data(JabberStream *js, const char *from, xmlnode *items) static void update_buddy_metadata(JabberStream *js, const char *from, xmlnode *items) { - PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(js->gc), from); + PurpleBuddy *buddy = purple_blist_find_buddy(purple_connection_get_account(js->gc), from); const char *checksum; xmlnode *item, *metadata; if(!buddy) diff --git a/libpurple/protocols/msn/contact.c b/libpurple/protocols/msn/contact.c index e5f18c230f..375b4a6855 100644 --- a/libpurple/protocols/msn/contact.c +++ b/libpurple/protocols/msn/contact.c @@ -616,7 +616,7 @@ msn_parse_addressbook_groups(MsnSession *session, xmlnode *node) msn_group_new(session->userlist, group_id, group_name); purple_debug_info("msn", "AB group_id: %s, name: %s\n", group_id, group_name ? group_name : "(null)"); - if ((purple_find_group(group_name)) == NULL) { + if ((purple_blist_find_group(group_name)) == NULL) { PurpleGroup *g = purple_group_new(group_name); purple_blist_add_group(g, NULL); } @@ -936,7 +936,7 @@ msn_parse_addressbook(MsnSession *session, xmlnode *node) MSN_INDIVIDUALS_GROUP_NAME); purple_debug_misc("msn", "AB group_id:%s name:%s\n", MSN_INDIVIDUALS_GROUP_ID, MSN_INDIVIDUALS_GROUP_NAME); - if ((purple_find_group(MSN_INDIVIDUALS_GROUP_NAME)) == NULL){ + if ((purple_blist_find_group(MSN_INDIVIDUALS_GROUP_NAME)) == NULL){ PurpleGroup *g = purple_group_new(MSN_INDIVIDUALS_GROUP_NAME); purple_blist_add_group(g, NULL); } @@ -944,7 +944,7 @@ msn_parse_addressbook(MsnSession *session, xmlnode *node) /* Add a "Non-IM Contacts" group */ msn_group_new(session->userlist, MSN_NON_IM_GROUP_ID, MSN_NON_IM_GROUP_NAME); purple_debug_misc("msn", "AB group_id:%s name:%s\n", MSN_NON_IM_GROUP_ID, MSN_NON_IM_GROUP_NAME); - if ((purple_find_group(MSN_NON_IM_GROUP_NAME)) == NULL) { + if ((purple_blist_find_group(MSN_NON_IM_GROUP_NAME)) == NULL) { PurpleGroup *g = purple_group_new(MSN_NON_IM_GROUP_NAME); purple_blist_add_group(g, NULL); } @@ -1067,7 +1067,7 @@ msn_add_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, purple_debug_error("msn", "Contact is from a federated domain, but don't know what to do yet!\n"); } else if (errorcode && !strcmp(errorcode, "InvalidPassportUser")) { - PurpleBuddy *buddy = purple_find_buddy(session->account, state->who); + PurpleBuddy *buddy = purple_blist_find_buddy(session->account, state->who); char *str = g_strdup_printf(_("Unable to add \"%s\"."), state->who); purple_notify_error(state->session, _("Buddy Add error"), str, _("The username specified does not exist.")); @@ -1163,7 +1163,7 @@ msn_add_contact_to_group_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, purple_debug_error("msn", "Contact is from a federated domain, but don't know what to do yet!\n"); } else if (errorcode && !strcmp(errorcode, "InvalidPassportUser")) { - PurpleBuddy *buddy = purple_find_buddy(session->account, state->who); + PurpleBuddy *buddy = purple_blist_find_buddy(session->account, state->who); char *str = g_strdup_printf(_("Unable to add \"%s\"."), state->who); purple_notify_error(session, _("Buddy Add error"), str, _("The username specified does not exist.")); @@ -1664,10 +1664,10 @@ msn_del_contact_from_list_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, msn_add_contact_to_list(session, new_state, state->who, MSN_LIST_RL); return; } else if (state->list_id == MSN_LIST_AL) { - purple_privacy_permit_remove(session->account, state->who, TRUE); + purple_account_privacy_permit_remove(session->account, state->who, TRUE); msn_add_contact_to_list(session, NULL, state->who, MSN_LIST_BL); } else if (state->list_id == MSN_LIST_BL) { - purple_privacy_deny_remove(session->account, state->who, TRUE); + purple_account_privacy_deny_remove(session->account, state->who, TRUE); msn_add_contact_to_list(session, NULL, state->who, MSN_LIST_AL); } @@ -1764,9 +1764,9 @@ msn_add_contact_to_list_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, if (state->action & MSN_DENIED_BUDDY) { msn_add_contact_to_list(state->session, NULL, state->who, MSN_LIST_BL); } else if (state->list_id == MSN_LIST_AL) { - purple_privacy_permit_add(state->session->account, state->who, TRUE); + purple_account_privacy_permit_add(state->session->account, state->who, TRUE); } else if (state->list_id == MSN_LIST_BL) { - purple_privacy_deny_add(state->session->account, state->who, TRUE); + purple_account_privacy_deny_add(state->session->account, state->who, TRUE); } } } diff --git a/libpurple/protocols/msn/directconn.c b/libpurple/protocols/msn/directconn.c index f68e973f06..a22f34d9b8 100644 --- a/libpurple/protocols/msn/directconn.c +++ b/libpurple/protocols/msn/directconn.c @@ -23,7 +23,7 @@ */ #include "internal.h" -#include "cipher.h" +#include "ciphers/sha1hash.h" #include "debug.h" #include "msn.h" @@ -44,11 +44,10 @@ msn_dc_calculate_nonce_hash(MsnDirectConnNonceType type, guchar digest[20]; if (type == DC_NONCE_SHA1) { - PurpleCipher *cipher = purple_ciphers_find_cipher("sha1"); - PurpleCipherContext *context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, nonce, nonce_len); - purple_cipher_context_digest(context, digest, sizeof(digest)); - purple_cipher_context_destroy(context); + PurpleHash *hash = purple_sha1_hash_new(); + purple_hash_append(hash, nonce, nonce_len); + purple_hash_digest(hash, digest, sizeof(digest)); + g_object_unref(hash); } else if (type == DC_NONCE_PLAIN) { memcpy(digest, nonce, nonce_len); } else { diff --git a/libpurple/protocols/msn/directconn.h b/libpurple/protocols/msn/directconn.h index 41a05d274e..ffffcc43e6 100644 --- a/libpurple/protocols/msn/directconn.h +++ b/libpurple/protocols/msn/directconn.h @@ -28,7 +28,7 @@ typedef struct _MsnDirectConn MsnDirectConn; #include "network.h" #include "proxy.h" -#include "circbuffer.h" +#include "circularbuffer.h" #include "slp.h" #include "slplink.h" diff --git a/libpurple/protocols/msn/error.c b/libpurple/protocols/msn/error.c index 18df67a8d5..df8bf1459e 100644 --- a/libpurple/protocols/msn/error.c +++ b/libpurple/protocols/msn/error.c @@ -290,12 +290,12 @@ msn_complete_sync_issue(MsnAddRemData *data) PurpleGroup *group = NULL; if (data->group != NULL) - group = purple_find_group(data->group); + group = purple_blist_find_group(data->group); if (group != NULL) - buddy = purple_find_buddy_in_group(data->session->account, data->who, group); + buddy = purple_blist_find_buddy_in_group(data->session->account, data->who, group); else - buddy = purple_find_buddy(data->session->account, data->who); + buddy = purple_blist_find_buddy(data->session->account, data->who); if (buddy != NULL) purple_blist_remove_buddy(buddy); diff --git a/libpurple/protocols/msn/msg.c b/libpurple/protocols/msn/msg.c index 755bf0b21d..0d3f65b5a6 100644 --- a/libpurple/protocols/msn/msg.c +++ b/libpurple/protocols/msn/msg.c @@ -705,7 +705,7 @@ msn_plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg) if (swboard->current_users > 1 || ((swboard->conv != NULL) && - purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) + PURPLE_IS_CHAT_CONVERSATION(swboard->conv))) { /* If current_users is always ok as it should then there is no need to * check if this is a chat. */ @@ -717,7 +717,7 @@ msn_plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg) time(NULL)); if (swboard->conv == NULL) { - swboard->conv = purple_find_chat(gc, swboard->chat_id); + swboard->conv = PURPLE_CONVERSATION(purple_conversations_find_chat(gc, swboard->chat_id)); swboard->flag |= MSN_SB_FLAG_IM; } } @@ -727,8 +727,8 @@ msn_plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg) serv_got_im(gc, passport, body_final, 0, time(NULL)); if (swboard->conv == NULL) { - swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - passport, purple_connection_get_account(gc)); + swboard->conv = PURPLE_CONVERSATION(purple_conversations_find_im_with_account( + passport, purple_connection_get_account(gc))); swboard->flag |= MSN_SB_FLAG_IM; } } @@ -758,12 +758,12 @@ msn_control_msg(MsnCmdProc *cmdproc, MsnMessage *msg) if (swboard->current_users == 1) { serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT, - PURPLE_TYPING); + PURPLE_IM_TYPING); } } else { serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT, - PURPLE_TYPING); + PURPLE_IM_TYPING); } } @@ -780,7 +780,7 @@ datacast_inform_user(MsnSwitchBoard *swboard, const char *who, account = swboard->session->account; pc = purple_account_get_connection(account); - if ((b = purple_find_buddy(account, who)) != NULL) + if ((b = purple_blist_find_buddy(account, who)) != NULL) username = g_markup_escape_text(purple_buddy_get_alias(b), -1); else username = g_markup_escape_text(who, -1); @@ -795,18 +795,19 @@ datacast_inform_user(MsnSwitchBoard *swboard, const char *who, if (swboard->conv == NULL) { if (chat) - swboard->conv = purple_find_chat(purple_account_get_connection(account), swboard->chat_id); + swboard->conv = PURPLE_CONVERSATION(purple_conversations_find_chat( + purple_account_get_connection(account), swboard->chat_id)); else { - swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - who, account); + swboard->conv = PURPLE_CONVERSATION(purple_conversations_find_im_with_account( + who, account)); if (swboard->conv == NULL) - swboard->conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, who); + swboard->conv = PURPLE_CONVERSATION(purple_im_conversation_new(account, who)); } } if (chat) serv_got_chat_in(pc, - purple_conv_chat_get_id(PURPLE_CONV_CHAT(swboard->conv)), + purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(swboard->conv)), who, PURPLE_MESSAGE_RECV|PURPLE_MESSAGE_SYSTEM, str, time(NULL)); else @@ -921,8 +922,8 @@ got_emoticon(MsnSlpCall *slpcall, instead of all at once, calling write multiple times and close once at the very end */ - purple_conv_custom_smiley_write(conv, slpcall->data_info, data, size); - purple_conv_custom_smiley_close(conv, slpcall->data_info ); + purple_conversation_custom_smiley_write(conv, slpcall->data_info, data, size); + purple_conversation_custom_smiley_close(conv, slpcall->data_info ); } if (purple_debug_is_verbose()) purple_debug_info("msn", "Got smiley: %s\n", slpcall->data_info); @@ -996,10 +997,10 @@ void msn_emoticon_msg(MsnCmdProc *cmdproc, MsnMessage *msg) * the conversation doesn't exist then we cannot associate the new * smiley with its GtkIMHtml widget. */ if (!conv) { - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, session->account, who); + conv = PURPLE_CONVERSATION(purple_im_conversation_new(session->account, who)); } - if (purple_conv_custom_smiley_add(conv, smile, "sha1", sha1, TRUE)) { + if (purple_conversation_custom_smiley_add(conv, smile, "sha1", sha1, TRUE)) { msn_slplink_request_object(slplink, smile, got_emoticon, NULL, obj); } @@ -1034,7 +1035,7 @@ msn_datacast_msg(MsnCmdProc *cmdproc, MsnMessage *msg) MsnSwitchBoard *swboard = cmdproc->data; if (swboard->current_users > 1 || ((swboard->conv != NULL) && - purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) + PURPLE_IS_CHAT_CONVERSATION(swboard->conv))) purple_prpl_got_attention_in_chat(gc, swboard->chat_id, user, MSN_NUDGE); else @@ -1140,21 +1141,20 @@ msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg) purple_debug_info("msn", "Computer call\n"); if (cmdproc->session) { - PurpleConversation *conv = NULL; + PurpleIMConversation *im = NULL; gchar *from = msg->remote_user; gchar *buf = NULL; if (from) - conv = purple_find_conversation_with_account( - PURPLE_CONV_TYPE_IM, from, - cmdproc->session->account); - if (conv) + im = purple_conversations_find_im_with_account( + from, cmdproc->session->account); + if (im) buf = g_strdup_printf( _("%s sent you a voice chat " "invite, which is not yet " "supported."), from); if (buf) { - purple_conversation_write(conv, NULL, buf, + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, buf, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NOTIFY, time(NULL)); diff --git a/libpurple/protocols/msn/msn.c b/libpurple/protocols/msn/msn.c index b15424f91b..1210ff3051 100644 --- a/libpurple/protocols/msn/msn.c +++ b/libpurple/protocols/msn/msn.c @@ -778,7 +778,7 @@ show_send_to_mobile_cb(PurpleBlistNode *node, gpointer ignored) PurpleAccount *account; const char *name; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; account = purple_buddy_get_account(buddy); @@ -814,8 +814,8 @@ msn_send_privacy(PurpleConnection *gc) session = purple_connection_get_protocol_data(gc); cmdproc = session->notification->cmdproc; - if (purple_account_get_privacy_type(account) == PURPLE_PRIVACY_ALLOW_ALL || - purple_account_get_privacy_type(account) == PURPLE_PRIVACY_DENY_USERS) + if (purple_account_get_privacy_type(account) == PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL || + purple_account_get_privacy_type(account) == PURPLE_ACCOUNT_PRIVACY_DENY_USERS) trans = msn_transaction_new(cmdproc, "BLP", "%s", "AL"); else trans = msn_transaction_new(cmdproc, "BLP", "%s", "BL"); @@ -835,7 +835,7 @@ initiate_chat_cb(PurpleBlistNode *node, gpointer data) const char *alias; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; account = purple_buddy_get_account(buddy); @@ -849,16 +849,17 @@ initiate_chat_cb(PurpleBlistNode *node, gpointer data) /* TODO: This might move somewhere else, after USR might be */ swboard->chat_id = msn_switchboard_get_chat_id(); - swboard->conv = serv_got_joined_chat(gc, swboard->chat_id, "MSN Chat"); + swboard->conv = PURPLE_CONVERSATION(serv_got_joined_chat(gc, + swboard->chat_id, "MSN Chat")); swboard->flag = MSN_SB_FLAG_IM; /* Local alias > Display name > Username */ - if ((alias = purple_account_get_alias(account)) == NULL) + if ((alias = purple_account_get_private_alias(account)) == NULL) if ((alias = purple_connection_get_display_name(gc)) == NULL) alias = purple_account_get_username(account); - purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), - alias, NULL, PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(PURPLE_CHAT_CONVERSATION(swboard->conv), + alias, NULL, PURPLE_CHAT_USER_NONE, TRUE); } static void @@ -1151,35 +1152,35 @@ msn_status_types(PurpleAccount *account) status = purple_status_type_new_with_attrs( PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, status); status = purple_status_type_new_with_attrs( PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, status); status = purple_status_type_new_with_attrs( PURPLE_STATUS_AWAY, "brb", _("Be Right Back"), TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, status); status = purple_status_type_new_with_attrs( PURPLE_STATUS_UNAVAILABLE, "busy", _("Busy"), TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, status); status = purple_status_type_new_with_attrs( PURPLE_STATUS_UNAVAILABLE, "phone", _("On the Phone"), TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, status); status = purple_status_type_new_with_attrs( PURPLE_STATUS_AWAY, "lunch", _("Out to Lunch"), TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, status); @@ -1197,11 +1198,11 @@ msn_status_types(PurpleAccount *account) status = purple_status_type_new_with_attrs(PURPLE_STATUS_TUNE, "tune", NULL, FALSE, TRUE, TRUE, - PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), - "game", _("Game Title"), purple_value_new(PURPLE_TYPE_STRING), - "office", _("Office Title"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_g_value_new(G_TYPE_STRING), + PURPLE_TUNE_ALBUM, _("Tune Album"), purple_g_value_new(G_TYPE_STRING), + PURPLE_TUNE_TITLE, _("Tune Title"), purple_g_value_new(G_TYPE_STRING), + "game", _("Game Title"), purple_g_value_new(G_TYPE_STRING), + "office", _("Office Title"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, status); @@ -1313,7 +1314,7 @@ msn_buddy_menu(PurpleBuddy *buddy) static GList * msn_blist_node_menu(PurpleBlistNode *node) { - if(PURPLE_BLIST_NODE_IS_BUDDY(node)) + if(PURPLE_IS_BUDDY(node)) { return msn_buddy_menu((PurpleBuddy *) node); } @@ -1356,8 +1357,8 @@ msn_login(PurpleAccount *account) purple_connection_set_protocol_data(gc, session); purple_connection_set_flags(gc, - PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_FORMATTING_WBFO | PURPLE_CONNECTION_NO_BGCOLOR | - PURPLE_CONNECTION_NO_FONTSIZE | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY); + PURPLE_CONNECTION_FLAG_HTML | PURPLE_CONNECTION_FLAG_FORMATTING_WBFO | PURPLE_CONNECTION_FLAG_NO_BGCOLOR | + PURPLE_CONNECTION_FLAG_NO_FONTSIZE | PURPLE_CONNECTION_FLAG_NO_URLDESC | PURPLE_CONNECTION_FLAG_ALLOW_CUSTOM_SMILEY); msn_session_set_login_step(session, MSN_LOGIN_STEP_START); @@ -1528,7 +1529,7 @@ msn_send_im(PurpleConnection *gc, const char *who, const char *message, PurpleMessageFlags flags) { PurpleAccount *account; - PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(gc), who); + PurpleBuddy *buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who); MsnSession *session; MsnSwitchBoard *swboard; MsnMessage *msg; @@ -1639,7 +1640,7 @@ msn_send_im(PurpleConnection *gc, const char *who, const char *message, } static unsigned int -msn_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state) +msn_send_typing(PurpleConnection *gc, const char *who, PurpleIMTypingState state) { PurpleAccount *account; MsnSession *session; @@ -1650,17 +1651,17 @@ msn_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state) session = purple_connection_get_protocol_data(gc); /* - * TODO: I feel like this should be "if (state != PURPLE_TYPING)" + * TODO: I feel like this should be "if (state != PURPLE_IM_TYPING)" * but this is how it was before, and I don't want to break * anything. --KingAnt */ - if (state == PURPLE_NOT_TYPING) + if (state == PURPLE_IM_NOT_TYPING) return 0; if (!g_ascii_strcasecmp(who, purple_account_get_username(account))) { /* We'll just fake it, since we're sending to ourself. */ - serv_got_typing(gc, who, MSN_TYPING_RECV_TIMEOUT, PURPLE_TYPING); + serv_got_typing(gc, who, MSN_TYPING_RECV_TIMEOUT, PURPLE_IM_TYPING); return MSN_TYPING_SEND_TIMEOUT; } @@ -1785,7 +1786,7 @@ msn_add_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group, cons if (!msn_email_is_valid(bname)) { gchar *buf; buf = g_strdup_printf(_("Unable to add the buddy %s because the username is invalid. Usernames must be valid email addresses."), bname); - if (!purple_conv_present_error(bname, account, buf)) + if (!purple_conversation_present_error(bname, account, buf)) purple_notify_error(pc, NULL, _("Unable to Add"), buf); g_free(buf); @@ -1796,7 +1797,7 @@ msn_add_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group, cons } /* Make sure name is normalized */ - purple_blist_rename_buddy(buddy, bname); + purple_buddy_set_name(buddy, bname); userlist = session->userlist; user = msn_userlist_find_user(userlist, bname); @@ -1970,7 +1971,7 @@ msn_chat_invite(PurpleConnection *gc, int id, const char *msg, swboard = msn_switchboard_new(session); msn_switchboard_request(swboard); swboard->chat_id = id; - swboard->conv = purple_find_chat(gc, id); + swboard->conv = PURPLE_CONVERSATION(purple_conversations_find_chat(gc, id)); } swboard->flag |= MSN_SB_FLAG_IM; @@ -2052,14 +2053,14 @@ msn_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFl while (smileys) { smile = (MsnEmoticon *)smileys->data; emoticons = msn_msg_emoticon_add(emoticons, smile); - if (purple_conv_custom_smiley_add(swboard->conv, smile->smile, + if (purple_conversation_custom_smiley_add(swboard->conv, smile->smile, "sha1", purple_smiley_get_checksum(smile->ps), FALSE)) { gconstpointer data; size_t len; data = purple_smiley_get_data(smile->ps, &len); - purple_conv_custom_smiley_write(swboard->conv, smile->smile, data, len); - purple_conv_custom_smiley_close(swboard->conv, smile->smile); + purple_conversation_custom_smiley_write(swboard->conv, smile->smile, data, len); + purple_conversation_custom_smiley_close(swboard->conv, smile->smile); } msn_emoticon_destroy(smile); smileys = g_slist_delete_link(smileys, smileys); @@ -2228,7 +2229,7 @@ msn_tooltip_extract_info_text(PurpleNotifyUserInfo *user_info, MsnGetInfoData *i { PurpleBuddy *b; - b = purple_find_buddy(purple_connection_get_account(info_data->gc), + b = purple_blist_find_buddy(purple_connection_get_account(info_data->gc), info_data->name); if (b) @@ -2236,7 +2237,7 @@ msn_tooltip_extract_info_text(PurpleNotifyUserInfo *user_info, MsnGetInfoData *i char *tmp; const char *alias; - alias = purple_buddy_get_local_buddy_alias(b); + alias = purple_buddy_get_local_alias(b); if (alias && alias[0]) { purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), alias); @@ -2688,7 +2689,7 @@ msn_got_info(PurpleHttpConnection *http_conn, char *p = strstr(url_buffer, "form id=\"SpacesSearch\" name=\"SpacesSearch\""); * Let's see how long this one holds out for ... */ char *p = strstr(url_buffer, "<form id=\"profile_form\" name=\"profile_form\" action=\"http://spaces.live.com/profile.aspx?cid=0\""); - PurpleBuddy *b = purple_find_buddy + PurpleBuddy *b = purple_blist_find_buddy (purple_connection_get_account(info_data->gc), info_data->name); purple_notify_user_info_add_pair_html(user_info, _("Error retrieving profile"), NULL); @@ -2859,11 +2860,11 @@ static gboolean msn_uri_handler(const char *proto, const char *cmd, GHashTable * if (!g_ascii_strcasecmp(cmd, "Chat")) { char *sname = g_hash_table_lookup(params, "contact"); if (sname) { - PurpleConversation *conv = purple_find_conversation_with_account( - PURPLE_CONV_TYPE_IM, sname, acct); - if (conv == NULL) - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, sname); - purple_conversation_present(conv); + PurpleIMConversation *im = purple_conversations_find_im_with_account( + sname, acct); + if (im == NULL) + im = purple_im_conversation_new(acct, sname); + purple_conversation_present(PURPLE_CONVERSATION(im)); } /*else **If pidgindialogs_im() was in the core, we could use it here. diff --git a/libpurple/protocols/msn/msnutils.c b/libpurple/protocols/msn/msnutils.c index 38a2ffd760..9904a3efd5 100644 --- a/libpurple/protocols/msn/msnutils.c +++ b/libpurple/protocols/msn/msnutils.c @@ -27,7 +27,7 @@ #include "msn.h" #include "msnutils.h" -#include "cipher.h" +#include "ciphers/md5hash.h" /************************************************************************** * Util @@ -542,8 +542,7 @@ msn_email_is_valid(const char *passport) void msn_handle_chl(char *input, char *output) { - PurpleCipher *cipher; - PurpleCipherContext *context; + PurpleHash *hash; const guchar productKey[] = MSNP15_WLM_PRODUCT_KEY; const guchar productID[] = MSNP15_WLM_PRODUCT_ID; const char hexChars[] = "0123456789abcdef"; @@ -560,13 +559,12 @@ msn_handle_chl(char *input, char *output) int i; /* Create the MD5 hash by using Purple MD5 algorithm */ - cipher = purple_ciphers_find_cipher("md5"); - context = purple_cipher_context_new(cipher, NULL); + hash = purple_md5_hash_new(); - purple_cipher_context_append(context, (guchar *)input, strlen(input)); - purple_cipher_context_append(context, productKey, sizeof(productKey) - 1); - purple_cipher_context_digest(context, md5Hash, sizeof(md5Hash)); - purple_cipher_context_destroy(context); + purple_hash_append(hash, (guchar *)input, strlen(input)); + purple_hash_append(hash, productKey, sizeof(productKey) - 1); + purple_hash_digest(hash, md5Hash, sizeof(md5Hash)); + g_object_unref(hash); /* Split it into four integers */ md5Parts = (unsigned int *)md5Hash; diff --git a/libpurple/protocols/msn/nexus.c b/libpurple/protocols/msn/nexus.c index 576fbf6c14..de61681fd8 100644 --- a/libpurple/protocols/msn/nexus.c +++ b/libpurple/protocols/msn/nexus.c @@ -23,7 +23,6 @@ */ #include "internal.h" -#include "cipher.h" #include "debug.h" #include "msnutils.h" @@ -31,6 +30,10 @@ #include "nexus.h" #include "notification.h" +#include "ciphers/des3cipher.h" +#include "ciphers/hmaccipher.h" +#include "ciphers/sha1hash.h" + /************************************************************************** * Valid Ticket Tokens **************************************************************************/ @@ -99,35 +102,37 @@ rps_create_key(const char *key, int key_len, const char *data, size_t data_len) const guchar magic[] = "WS-SecureConversation"; const int magic_len = sizeof(magic) - 1; - PurpleCipherContext *hmac; + PurpleCipher *hmac; + PurpleHash *hash; guchar hash1[20], hash2[20], hash3[20], hash4[20]; char *result; - hmac = purple_cipher_context_new_by_name("hmac", NULL); - purple_cipher_context_set_option(hmac, "hash", "sha1"); - purple_cipher_context_set_key(hmac, (guchar *)key, key_len); + hash = purple_sha1_hash_new(); + hmac = purple_hmac_cipher_new(hash); + purple_cipher_set_key(hmac, (guchar *)key, key_len); - purple_cipher_context_append(hmac, magic, magic_len); - purple_cipher_context_append(hmac, (guchar *)data, data_len); - purple_cipher_context_digest(hmac, hash1, sizeof(hash1)); + purple_cipher_append(hmac, magic, magic_len); + purple_cipher_append(hmac, (guchar *)data, data_len); + purple_cipher_digest(hmac, hash1, sizeof(hash1)); - purple_cipher_context_reset_state(hmac, NULL); - purple_cipher_context_append(hmac, hash1, 20); - purple_cipher_context_append(hmac, magic, magic_len); - purple_cipher_context_append(hmac, (guchar *)data, data_len); - purple_cipher_context_digest(hmac, hash2, sizeof(hash2)); + purple_cipher_reset_state(hmac); + purple_cipher_append(hmac, hash1, 20); + purple_cipher_append(hmac, magic, magic_len); + purple_cipher_append(hmac, (guchar *)data, data_len); + purple_cipher_digest(hmac, hash2, sizeof(hash2)); - purple_cipher_context_reset_state(hmac, NULL); - purple_cipher_context_append(hmac, hash1, 20); - purple_cipher_context_digest(hmac, hash3, sizeof(hash3)); + purple_cipher_reset_state(hmac); + purple_cipher_append(hmac, hash1, 20); + purple_cipher_digest(hmac, hash3, sizeof(hash3)); - purple_cipher_context_reset_state(hmac, NULL); - purple_cipher_context_append(hmac, hash3, sizeof(hash3)); - purple_cipher_context_append(hmac, magic, magic_len); - purple_cipher_context_append(hmac, (guchar *)data, data_len); - purple_cipher_context_digest(hmac, hash4, sizeof(hash4)); + purple_cipher_reset_state(hmac); + purple_cipher_append(hmac, hash3, sizeof(hash3)); + purple_cipher_append(hmac, magic, magic_len); + purple_cipher_append(hmac, (guchar *)data, data_len); + purple_cipher_digest(hmac, hash4, sizeof(hash4)); - purple_cipher_context_destroy(hmac); + g_object_unref(hmac); + g_object_unref(hash); result = g_malloc(24); memcpy(result, hash2, sizeof(hash2)); @@ -139,21 +144,21 @@ rps_create_key(const char *key, int key_len, const char *data, size_t data_len) static char * des3_cbc(const char *key, const char *iv, const char *data, int len, gboolean decrypt) { - PurpleCipherContext *des3; + PurpleCipher *des3; char *out; - des3 = purple_cipher_context_new_by_name("des3", NULL); - purple_cipher_context_set_key(des3, (guchar *)key, 24); - purple_cipher_context_set_batch_mode(des3, PURPLE_CIPHER_BATCH_MODE_CBC); - purple_cipher_context_set_iv(des3, (guchar *)iv, 8); + des3 = purple_des3_cipher_new(); + purple_cipher_set_key(des3, (guchar *)key, 24); + purple_cipher_set_batch_mode(des3, PURPLE_CIPHER_BATCH_MODE_CBC); + purple_cipher_set_iv(des3, (guchar *)iv, 8); out = g_malloc(len); if (decrypt) - purple_cipher_context_decrypt(des3, (guchar *)data, len, (guchar *)out, len); + purple_cipher_decrypt(des3, (guchar *)data, len, (guchar *)out, len); else - purple_cipher_context_encrypt(des3, (guchar *)data, len, (guchar *)out, len); + purple_cipher_encrypt(des3, (guchar *)data, len, (guchar *)out, len); - purple_cipher_context_destroy(des3); + g_object_unref(des3); return out; } @@ -168,7 +173,8 @@ msn_rps_encrypt(MsnNexus *nexus) char usr_key_base[MSN_USER_KEY_SIZE], *usr_key; const char magic1[] = "SESSION KEY HASH"; const char magic2[] = "SESSION KEY ENCRYPTION"; - PurpleCipherContext *hmac; + PurpleCipher *hmac; + PurpleHash *hasher; size_t len; guchar *hash; char *key1, *key2, *key3; @@ -199,12 +205,13 @@ msn_rps_encrypt(MsnNexus *nexus) key3 = rps_create_key(key1, key1_len, magic2, sizeof(magic2) - 1); len = strlen(nexus->nonce); - hmac = purple_cipher_context_new_by_name("hmac", NULL); - purple_cipher_context_set_option(hmac, "hash", "sha1"); - purple_cipher_context_set_key(hmac, (guchar *)key2, 24); - purple_cipher_context_append(hmac, (guchar *)nexus->nonce, len); - purple_cipher_context_digest(hmac, hash, 20); - purple_cipher_context_destroy(hmac); + hasher = purple_sha1_hash_new(); + hmac = purple_hmac_cipher_new(hasher); + purple_cipher_set_key(hmac, (guchar *)key2, 24); + purple_cipher_append(hmac, (guchar *)nexus->nonce, len); + purple_cipher_digest(hmac, hash, 20); + g_object_unref(hmac); + g_object_unref(hasher); /* We need to pad this to 72 bytes, apparently */ nonce_fixed = g_malloc(len + 8); @@ -507,8 +514,8 @@ msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data) MsnSession *session = nexus->session; MsnNexusUpdateData *ud; MsnNexusUpdateCallback *update; - PurpleCipherContext *sha1; - PurpleCipherContext *hmac; + PurpleHash *sha1; + PurpleCipher *hmac; char *key; @@ -558,7 +565,7 @@ msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data) ud->nexus = nexus; ud->id = id; - sha1 = purple_cipher_context_new_by_name("sha1", NULL); + sha1 = purple_sha1_hash_new(); domain = g_strdup_printf(MSN_SSO_RST_TEMPLATE, id, @@ -566,8 +573,8 @@ msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data) ticket_domains[id][SSO_VALID_TICKET_POLICY] != NULL ? ticket_domains[id][SSO_VALID_TICKET_POLICY] : nexus->policy); - purple_cipher_context_append(sha1, (guchar *)domain, strlen(domain)); - purple_cipher_context_digest(sha1, digest, 20); + purple_hash_append(sha1, (guchar *)domain, strlen(domain)); + purple_hash_digest(sha1, digest, 20); domain_b64 = purple_base64_encode(digest, 20); now = time(NULL); @@ -578,13 +585,13 @@ msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data) timestamp = g_strdup_printf(MSN_SSO_TIMESTAMP_TEMPLATE, now_str, purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", tm)); - purple_cipher_context_reset(sha1, NULL); - purple_cipher_context_append(sha1, (guchar *)timestamp, strlen(timestamp)); - purple_cipher_context_digest(sha1, digest, 20); + purple_hash_reset(sha1); + purple_hash_append(sha1, (guchar *)timestamp, strlen(timestamp)); + purple_hash_digest(sha1, digest, 20); timestamp_b64 = purple_base64_encode(digest, 20); g_free(now_str); - purple_cipher_context_destroy(sha1); + purple_hash_reset(sha1); signedinfo = g_strdup_printf(MSN_SSO_SIGNEDINFO_TEMPLATE, id, @@ -596,12 +603,14 @@ msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data) nonce_b64 = purple_base64_encode((guchar *)&nonce, sizeof(nonce)); key = rps_create_key(nexus->secret, 24, (char *)nonce, sizeof(nonce)); - hmac = purple_cipher_context_new_by_name("hmac", NULL); - purple_cipher_context_set_option(hmac, "hash", "sha1"); - purple_cipher_context_set_key(hmac, (guchar *)key, 24); - purple_cipher_context_append(hmac, (guchar *)signedinfo, strlen(signedinfo)); - purple_cipher_context_digest(hmac, signature, 20); - purple_cipher_context_destroy(hmac); + hmac = purple_hmac_cipher_new(sha1); + purple_cipher_set_key(hmac, (guchar *)key, 24); + purple_cipher_append(hmac, (guchar *)signedinfo, strlen(signedinfo)); + purple_cipher_digest(hmac, signature, 20); + + g_object_unref(hmac); + g_object_unref(sha1); + signature_b64 = purple_base64_encode(signature, 20); request = g_strdup_printf(MSN_SSO_TOKEN_UPDATE_TEMPLATE, diff --git a/libpurple/protocols/msn/notification.c b/libpurple/protocols/msn/notification.c index 969e6af088..37c99c9373 100644 --- a/libpurple/protocols/msn/notification.c +++ b/libpurple/protocols/msn/notification.c @@ -23,7 +23,7 @@ */ #include "internal.h" -#include "cipher.h" +#include "ciphers/md5hash.h" #include "core.h" #include "debug.h" @@ -1202,8 +1202,7 @@ ipg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len) if (id && strcmp(id, "1")) { PurpleConversation *conv - = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, - who, purple_connection_get_account(gc)); + = purple_conversations_find_with_account(who, purple_connection_get_account(gc)); if (conv != NULL) { const char *error; if (!strcmp(id, "407")) @@ -1394,7 +1393,7 @@ url_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) PurpleAccount *account; const char *rru; const char *url; - PurpleCipherContext *cipher; + PurpleHash *hash; gchar creds[33]; char *buf; @@ -1415,10 +1414,10 @@ url_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) tmp_timestamp, purple_connection_get_password(gc)); - cipher = purple_cipher_context_new_by_name("md5", NULL); - purple_cipher_context_append(cipher, (const guchar *)buf, strlen(buf)); - purple_cipher_context_digest_to_str(cipher, creds, sizeof(creds)); - purple_cipher_context_destroy(cipher); + hash = purple_md5_hash_new(); + purple_hash_append(hash, (const guchar *)buf, strlen(buf)); + purple_hash_digest_to_str(hash, creds, sizeof(creds)); + g_object_unref(hash); g_free(buf); g_free(session->passport_info.mail_url); diff --git a/libpurple/protocols/msn/object.c b/libpurple/protocols/msn/object.c index 7952f82838..c20065c4c9 100644 --- a/libpurple/protocols/msn/object.c +++ b/libpurple/protocols/msn/object.c @@ -26,7 +26,7 @@ #include "object.h" #include "debug.h" /* Sha1 stuff */ -#include "cipher.h" +#include "ciphers/sha1hash.h" /* Base64 stuff */ #include "util.h" @@ -130,7 +130,7 @@ msn_object_new_from_image(PurpleStoredImage *img, const char *location, { MsnObject *msnobj; - PurpleCipherContext *ctx; + PurpleHash *hash; char *buf; gconstpointer data; size_t size; @@ -157,9 +157,9 @@ msn_object_new_from_image(PurpleStoredImage *img, const char *location, /* Compute the SHA1D field. */ memset(digest, 0, sizeof(digest)); - ctx = purple_cipher_context_new_by_name("sha1", NULL); - purple_cipher_context_append(ctx, data, size); - purple_cipher_context_digest(ctx, digest, sizeof(digest)); + hash = purple_sha1_hash_new(); + purple_hash_append(hash, data, size); + purple_hash_digest(hash, digest, sizeof(digest)); base64 = purple_base64_encode(digest, sizeof(digest)); msn_object_set_sha1d(msnobj, base64); @@ -179,10 +179,10 @@ msn_object_new_from_image(PurpleStoredImage *img, const char *location, memset(digest, 0, sizeof(digest)); - purple_cipher_context_reset(ctx, NULL); - purple_cipher_context_append(ctx, (const guchar *)buf, strlen(buf)); - purple_cipher_context_digest(ctx, digest, sizeof(digest)); - purple_cipher_context_destroy(ctx); + purple_hash_reset(hash); + purple_hash_append(hash, (const guchar *)buf, strlen(buf)); + purple_hash_digest(hash, digest, sizeof(digest)); + g_object_unref(hash); g_free(buf); base64 = purple_base64_encode(digest, sizeof(digest)); diff --git a/libpurple/protocols/msn/servconn.c b/libpurple/protocols/msn/servconn.c index 8a2eb3e463..8427a8564f 100644 --- a/libpurple/protocols/msn/servconn.c +++ b/libpurple/protocols/msn/servconn.c @@ -53,7 +53,7 @@ msn_servconn_new(MsnSession *session, MsnServConnType type) servconn->num = session->servconns_count++; - servconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN); + servconn->tx_buf = purple_circular_buffer_new(MSN_BUF_LEN); servconn->tx_handler = 0; servconn->timeout_sec = 0; servconn->timeout_handle = 0; @@ -84,7 +84,7 @@ msn_servconn_destroy(MsnServConn *servconn) g_free(servconn->host); - purple_circ_buffer_destroy(servconn->tx_buf); + g_object_unref(G_OBJECT(servconn->tx_buf)); if (servconn->tx_handler > 0) purple_input_remove(servconn->tx_handler); if (servconn->timeout_handle > 0) @@ -331,8 +331,10 @@ servconn_write_cb(gpointer data, gint source, PurpleInputCondition cond) MsnServConn *servconn = data; gssize ret; int writelen; + const gchar *output = NULL; - writelen = purple_circ_buffer_get_max_read(servconn->tx_buf); + writelen = purple_circular_buffer_get_max_read(servconn->tx_buf); + output = purple_circular_buffer_get_output(servconn->tx_buf); if (writelen == 0) { purple_input_remove(servconn->tx_handler); @@ -340,7 +342,7 @@ servconn_write_cb(gpointer data, gint source, PurpleInputCondition cond) return; } - ret = write(servconn->fd, servconn->tx_buf->outptr, writelen); + ret = write(servconn->fd, output, writelen); if (ret < 0 && errno == EAGAIN) return; @@ -349,7 +351,7 @@ servconn_write_cb(gpointer data, gint source, PurpleInputCondition cond) return; } - purple_circ_buffer_mark_read(servconn->tx_buf, ret); + purple_circular_buffer_mark_read(servconn->tx_buf, ret); servconn_timeout_renew(servconn); } @@ -391,7 +393,7 @@ msn_servconn_write(MsnServConn *servconn, const char *buf, size_t len) servconn->tx_handler = purple_input_add( servconn->fd, PURPLE_INPUT_WRITE, servconn_write_cb, servconn); - purple_circ_buffer_append(servconn->tx_buf, buf + ret, + purple_circular_buffer_append(servconn->tx_buf, buf + ret, len - ret); } } diff --git a/libpurple/protocols/msn/servconn.h b/libpurple/protocols/msn/servconn.h index 88e6d32133..833a457137 100644 --- a/libpurple/protocols/msn/servconn.h +++ b/libpurple/protocols/msn/servconn.h @@ -24,7 +24,7 @@ #ifndef MSN_SERVCONN_H #define MSN_SERVCONN_H -#include "circbuffer.h" +#include "circularbuffer.h" typedef struct _MsnServConn MsnServConn; @@ -87,7 +87,7 @@ struct _MsnServConn It's only set when we've received a command that has a payload. */ - PurpleCircBuffer *tx_buf; + PurpleCircularBuffer *tx_buf; guint tx_handler; guint timeout_sec; guint timeout_handle; diff --git a/libpurple/protocols/msn/session.c b/libpurple/protocols/msn/session.c index 01cac2ae20..76a016342d 100644 --- a/libpurple/protocols/msn/session.c +++ b/libpurple/protocols/msn/session.c @@ -174,21 +174,20 @@ msn_session_find_swboard(MsnSession *session, const char *username) return NULL; } -static PurpleConversation * -msn_session_get_conv(MsnSession *session,const char *passport) +static PurpleIMConversation * +msn_session_get_im(MsnSession *session,const char *passport) { PurpleAccount *account; - PurpleConversation * conv; + PurpleIMConversation * im; g_return_val_if_fail(session != NULL, NULL); account = session->account; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - passport, account); - if(conv == NULL){ - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, passport); + im = purple_conversations_find_im_with_account(passport, account); + if(im == NULL){ + im = purple_im_conversation_new(account, passport); } - return conv; + return im; } /* put Message to User Conversation @@ -198,10 +197,10 @@ msn_session_get_conv(MsnSession *session,const char *passport) void msn_session_report_user(MsnSession *session,const char *passport,const char *msg,PurpleMessageFlags flags) { - PurpleConversation * conv; + PurpleIMConversation * im; - if ((conv = msn_session_get_conv(session,passport)) != NULL){ - purple_conversation_write(conv, NULL, msg, flags, time(NULL)); + if ((im = msn_session_get_im(session,passport)) != NULL){ + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, msg, flags, time(NULL)); } } @@ -309,7 +308,7 @@ msn_session_sync_users(MsnSession *session) * being logged in. This no longer happens, so we manually iterate * over the whole buddy list to identify sync issues. */ - for (buddies = purple_find_buddies(session->account, NULL); buddies; + for (buddies = purple_blist_find_buddies(session->account, NULL); buddies; buddies = g_slist_delete_link(buddies, buddies)) { PurpleBuddy *buddy = buddies->data; const gchar *buddy_name = purple_buddy_get_name(buddy); @@ -483,7 +482,7 @@ msn_session_finish_login(MsnSession *session) purple_imgstore_unref(img); session->logged_in = TRUE; - purple_connection_set_state(gc, PURPLE_CONNECTED); + purple_connection_set_state(gc, PURPLE_CONNECTION_CONNECTED); /* Sync users */ msn_session_sync_users(session); diff --git a/libpurple/protocols/msn/slpcall.c b/libpurple/protocols/msn/slpcall.c index 2a98e80384..c1eb81aeb6 100644 --- a/libpurple/protocols/msn/slpcall.c +++ b/libpurple/protocols/msn/slpcall.c @@ -566,18 +566,17 @@ got_sessionreq(MsnSlpCall *slpcall, const char *branch, } else if (!strcmp(euf_guid, MSN_CAM_REQUEST_GUID)) { purple_debug_info("msn", "Cam request.\n"); if (slpcall->slplink && slpcall->slplink->session) { - PurpleConversation *conv; + PurpleIMConversation *im; gchar *from = slpcall->slplink->remote_user; - conv = purple_find_conversation_with_account( - PURPLE_CONV_TYPE_IM, from, - slpcall->slplink->session->account); - if (conv) { + im = purple_conversations_find_im_with_account( + from, slpcall->slplink->session->account); + if (im) { char *buf; buf = g_strdup_printf( _("%s requests to view your " "webcam, but this request is " "not yet supported."), from); - purple_conversation_write(conv, NULL, buf, + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, buf, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NOTIFY, time(NULL)); @@ -588,17 +587,16 @@ got_sessionreq(MsnSlpCall *slpcall, const char *branch, } else if (!strcmp(euf_guid, MSN_CAM_GUID)) { purple_debug_info("msn", "Cam invite.\n"); if (slpcall->slplink && slpcall->slplink->session) { - PurpleConversation *conv; + PurpleIMConversation *im; gchar *from = slpcall->slplink->remote_user; - conv = purple_find_conversation_with_account( - PURPLE_CONV_TYPE_IM, from, - slpcall->slplink->session->account); - if (conv) { + im = purple_conversations_find_im_with_account( + from, slpcall->slplink->session->account); + if (im) { char *buf; buf = g_strdup_printf( _("%s invited you to view his/her webcam, but " "this is not yet supported."), from); - purple_conversation_write(conv, NULL, buf, + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, buf, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NOTIFY, time(NULL)); diff --git a/libpurple/protocols/msn/switchboard.c b/libpurple/protocols/msn/switchboard.c index 74d684a1aa..efc939660a 100644 --- a/libpurple/protocols/msn/switchboard.c +++ b/libpurple/protocols/msn/switchboard.c @@ -288,18 +288,17 @@ msn_switchboard_add_user(MsnSwitchBoard *swboard, const char *user) return; } - if ((swboard->conv != NULL) && - (purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) + if ((swboard->conv != NULL) && (PURPLE_IS_CHAT_CONVERSATION(swboard->conv))) { - purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), msnuser->passport, NULL, - PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(PURPLE_CHAT_CONVERSATION(swboard->conv), + msnuser->passport, NULL, PURPLE_CHAT_USER_NONE, TRUE); msn_servconn_set_idle_timeout(swboard->servconn, 0); } else if (swboard->current_users > 1) { msn_servconn_set_idle_timeout(swboard->servconn, 0); if (swboard->conv == NULL || - purple_conversation_get_type(swboard->conv) != PURPLE_CONV_TYPE_CHAT) + PURPLE_IS_IM_CONVERSATION(swboard->conv)) { GList *l; @@ -312,9 +311,9 @@ msn_switchboard_add_user(MsnSwitchBoard *swboard, const char *user) swboard->chat_id = msn_switchboard_get_chat_id(); swboard->flag |= MSN_SB_FLAG_IM; - swboard->conv = serv_got_joined_chat(purple_account_get_connection(account), + swboard->conv = PURPLE_CONVERSATION(serv_got_joined_chat(purple_account_get_connection(account), swboard->chat_id, - "MSN Chat"); + "MSN Chat")); for (l = swboard->users; l != NULL; l = l->next) { @@ -322,13 +321,13 @@ msn_switchboard_add_user(MsnSwitchBoard *swboard, const char *user) tmp_user = ((MsnUser*)l->data)->passport; - purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), - tmp_user, NULL, PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(PURPLE_CHAT_CONVERSATION(swboard->conv), + tmp_user, NULL, PURPLE_CHAT_USER_NONE, TRUE); } - purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), + purple_chat_conversation_add_user(PURPLE_CHAT_CONVERSATION(swboard->conv), purple_account_get_username(account), - NULL, PURPLE_CBFLAGS_NONE, TRUE); + NULL, PURPLE_CHAT_USER_NONE, TRUE); g_free(swboard->im_user); swboard->im_user = NULL; @@ -336,8 +335,8 @@ msn_switchboard_add_user(MsnSwitchBoard *swboard, const char *user) } else if (swboard->conv == NULL) { - swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - msnuser->passport, account); + swboard->conv = PURPLE_CONVERSATION(purple_conversations_find_im_with_account( + msnuser->passport, account)); } else { @@ -359,8 +358,8 @@ msn_switchboard_get_conv(MsnSwitchBoard *swboard) account = swboard->session->account; - return (swboard->conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, - account, swboard->im_user)); + return (swboard->conv = PURPLE_CONVERSATION(purple_im_conversation_new( + account, swboard->im_user))); } static void @@ -618,11 +617,11 @@ bye_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) msn_switchboard_destroy(swboard); } else if ((swboard->current_users > 1) || - (purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) + PURPLE_IS_CHAT_CONVERSATION(swboard->conv)) { GList *passport; /* This is a switchboard used for a chat */ - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(swboard->conv), user, NULL); + purple_chat_conversation_remove_user(PURPLE_CHAT_CONVERSATION(swboard->conv), user, NULL); passport = g_list_find_custom(swboard->users, user, (GCompareFunc)strcmp); if (passport) @@ -833,7 +832,7 @@ msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport, if (swboard->current_users > 1 || ((swboard->conv != NULL) && - purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) + PURPLE_IS_CHAT_CONVERSATION(swboard->conv))) serv_got_chat_in(gc, swboard->chat_id, passport, 0, image_msg, time(NULL)); else diff --git a/libpurple/protocols/msn/user.c b/libpurple/protocols/msn/user.c index ab86b5974f..70ab08b8c9 100644 --- a/libpurple/protocols/msn/user.c +++ b/libpurple/protocols/msn/user.c @@ -369,7 +369,7 @@ msn_user_add_group_id(MsnUser *user, const char* group_id) purple_debug_info("msn", "User: group id:%s,name:%s,user:%s\n", group_id, group_name, passport); - g = purple_find_group(group_name); + g = purple_blist_find_group(group_name); if ((group_id == NULL) && (g == NULL)) { @@ -377,7 +377,7 @@ msn_user_add_group_id(MsnUser *user, const char* group_id) purple_blist_add_group(g, NULL); } - b = purple_find_buddy_in_group(account, passport, g); + b = purple_blist_find_buddy_in_group(account, passport, g); if (b == NULL) { b = purple_buddy_new(account, passport, NULL); @@ -393,7 +393,7 @@ msn_user_is_online(PurpleAccount *account, const char *name) { PurpleBuddy *buddy; - buddy = purple_find_buddy(account, name); + buddy = purple_blist_find_buddy(account, name); return PURPLE_BUDDY_IS_ONLINE(buddy); } @@ -530,7 +530,7 @@ buddy_icon_cached(PurpleConnection *gc, MsnObject *obj) account = purple_connection_get_account(gc); - buddy = purple_find_buddy(account, msn_object_get_creator(obj)); + buddy = purple_blist_find_buddy(account, msn_object_get_creator(obj)); if (buddy == NULL) return FALSE; diff --git a/libpurple/protocols/msn/userlist.c b/libpurple/protocols/msn/userlist.c index 769d6579bf..b7304c4acb 100644 --- a/libpurple/protocols/msn/userlist.c +++ b/libpurple/protocols/msn/userlist.c @@ -59,8 +59,8 @@ msn_accept_add_cb(const char *message, gpointer data) PurpleAccount *account = purple_connection_get_account(pa->gc); msn_userlist_add_buddy_to_list(userlist, pa->who, MSN_LIST_AL); - purple_privacy_deny_remove(account, pa->who, TRUE); - purple_privacy_permit_add(account, pa->who, TRUE); + purple_account_privacy_deny_remove(account, pa->who, TRUE); + purple_account_privacy_permit_add(account, pa->who, TRUE); msn_del_contact_from_list(session, NULL, pa->who, MSN_LIST_PL); } @@ -107,7 +107,7 @@ got_new_entry(PurpleConnection *gc, const char *passport, const char *friendly, acct = purple_connection_get_account(gc); purple_account_request_authorization(acct, passport, NULL, friendly, message, - purple_find_buddy(acct, passport) != NULL, + purple_blist_find_buddy(acct, passport) != NULL, msn_accept_add_cb, msn_cancel_add_cb, pa); } @@ -152,15 +152,15 @@ msn_got_lst_user(MsnSession *session, MsnUser *user, if (list_op & MSN_LIST_AL_OP) { /* These are users who are allowed to see our status. */ - purple_privacy_deny_remove(account, passport, TRUE); - purple_privacy_permit_add(account, passport, TRUE); + purple_account_privacy_deny_remove(account, passport, TRUE); + purple_account_privacy_permit_add(account, passport, TRUE); } if (list_op & MSN_LIST_BL_OP) { /* These are users who are not allowed to see our status. */ - purple_privacy_permit_remove(account, passport, TRUE); - purple_privacy_deny_add(account, passport, TRUE); + purple_account_privacy_permit_remove(account, passport, TRUE); + purple_account_privacy_deny_add(account, passport, TRUE); } if (list_op & MSN_LIST_RL_OP) @@ -733,7 +733,7 @@ msn_userlist_load(MsnSession *session) g_return_if_fail(gc != NULL); - for (l = purple_find_buddies(account, NULL); l != NULL; + for (l = purple_blist_find_buddies(account, NULL); l != NULL; l = g_slist_delete_link(l, l)) { PurpleBuddy *buddy = l->data; @@ -742,13 +742,13 @@ msn_userlist_load(MsnSession *session) purple_buddy_set_protocol_data(buddy, user); msn_user_set_op(user, MSN_LIST_FL_OP); } - for (l = session->account->permit; l != NULL; l = l->next) + for (l = purple_account_privacy_get_permitted(session->account); l != NULL; l = l->next) { user = msn_userlist_find_add_user(session->userlist, (char *)l->data,NULL); msn_user_set_op(user, MSN_LIST_AL_OP); } - for (l = session->account->deny; l != NULL; l = l->next) + for (l = purple_account_privacy_get_denied(session->account); l != NULL; l = l->next) { user = msn_userlist_find_add_user(session->userlist, (char *)l->data,NULL); diff --git a/libpurple/protocols/mxit/formcmds.c b/libpurple/protocols/mxit/formcmds.c index 3d3938d175..7defe9059a 100644 --- a/libpurple/protocols/mxit/formcmds.c +++ b/libpurple/protocols/mxit/formcmds.c @@ -227,11 +227,11 @@ static GHashTable* command_tokenize(char* cmd) */ static void command_clear(struct MXitSession* session, const char* from, GHashTable* hash) { - PurpleConversation *conv; + PurpleIMConversation *im; char* clearmsgscreen; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, session->acc); - if (conv == NULL) { + im = purple_conversations_find_im_with_account(from, session->acc); + if (im == NULL) { purple_debug_error(MXIT_PLUGIN_ID, _( "Conversation with '%s' not found\n" ), from); return; } @@ -239,7 +239,7 @@ static void command_clear(struct MXitSession* session, const char* from, GHashTa clearmsgscreen = g_hash_table_lookup(hash, "clearmsgscreen"); if ( (clearmsgscreen) && (strcmp(clearmsgscreen, "true") == 0) ) { /* this is a command to clear the chat screen */ - purple_conversation_clear_message_history(conv); + purple_conversation_clear_message_history(PURPLE_CONVERSATION(im)); } } diff --git a/libpurple/protocols/mxit/login.c b/libpurple/protocols/mxit/login.c index f5d2443ed2..546cb02fce 100644 --- a/libpurple/protocols/mxit/login.c +++ b/libpurple/protocols/mxit/login.c @@ -73,10 +73,10 @@ static struct MXitSession* mxit_create_object( PurpleAccount* account ) /* configure the connection (reference: "libpurple/connection.h") */ purple_connection_set_protocol_data( con, session ); purple_connection_set_flags( con, - PURPLE_CONNECTION_NO_BGCOLOR - | PURPLE_CONNECTION_NO_URLDESC - | PURPLE_CONNECTION_HTML - | PURPLE_CONNECTION_SUPPORT_MOODS + PURPLE_CONNECTION_FLAG_NO_BGCOLOR + | PURPLE_CONNECTION_FLAG_NO_URLDESC + | PURPLE_CONNECTION_FLAG_HTML + | PURPLE_CONNECTION_FLAG_SUPPORT_MOODS ); /* configure the session (reference: "libpurple/account.h") */ diff --git a/libpurple/protocols/mxit/multimx.c b/libpurple/protocols/mxit/multimx.c index 606fe40253..b259a14d57 100644 --- a/libpurple/protocols/mxit/multimx.c +++ b/libpurple/protocols/mxit/multimx.c @@ -179,11 +179,11 @@ static void room_remove(struct MXitSession* session, struct multimx* multimx) * @param convo The Conversation object * @param nickname The nickname of the user who joined the room */ -static void member_added(PurpleConversation* convo, const char* nickname) +static void member_added(PurpleChatConversation* chat, const char* nickname) { purple_debug_info(MXIT_PLUGIN_ID, "member_added: '%s'\n", nickname); - purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), nickname, NULL, PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(chat, nickname, NULL, PURPLE_CHAT_USER_NONE, TRUE); } @@ -193,11 +193,11 @@ static void member_added(PurpleConversation* convo, const char* nickname) * @param convo The Conversation object * @param nickname The nickname of the user who left the room */ -static void member_removed(PurpleConversation* convo, const char* nickname) +static void member_removed(PurpleChatConversation* chat, const char* nickname) { purple_debug_info(MXIT_PLUGIN_ID, "member_removed: '%s'\n", nickname); - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), nickname, NULL); + purple_chat_conversation_remove_user(chat, nickname, NULL); } @@ -207,11 +207,11 @@ static void member_removed(PurpleConversation* convo, const char* nickname) * @param convo The Conversation object * @param nickname The nickname of the user who was kicked */ -static void member_kicked(PurpleConversation* convo, const char* nickname) +static void member_kicked(PurpleChatConversation* chat, const char* nickname) { purple_debug_info(MXIT_PLUGIN_ID, "member_kicked: '%s'\n", nickname); - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), nickname, _("was kicked")); + purple_chat_conversation_remove_user(chat, nickname, _("was kicked")); } @@ -222,12 +222,12 @@ static void member_kicked(PurpleConversation* convo, const char* nickname) * @param session The MXit session object * @param multimx The MultiMX room object */ -static void you_kicked(PurpleConversation* convo, struct MXitSession* session, struct multimx* multimx) +static void you_kicked(PurpleChatConversation* chat, struct MXitSession* session, struct multimx* multimx) { purple_debug_info(MXIT_PLUGIN_ID, "you_kicked\n"); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "MXit", _("You have been kicked from this MultiMX."), PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_clear_users(PURPLE_CONV_CHAT(convo)); + purple_conversation_write_message(PURPLE_CONVERSATION(chat), "MXit", _("You have been kicked from this MultiMX."), PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_chat_conversation_clear_users(chat); serv_got_chat_left(session->con, multimx->chatid); } @@ -238,7 +238,7 @@ static void you_kicked(PurpleConversation* convo, struct MXitSession* session, s * @param convo The Conversation object * @param data The nicknames of the users in the room (separated by \n) */ -static void member_update(PurpleConversation* convo, char* data) +static void member_update(PurpleChatConversation* chat, char* data) { gchar** userlist; int i = 0; @@ -246,14 +246,14 @@ static void member_update(PurpleConversation* convo, char* data) purple_debug_info(MXIT_PLUGIN_ID, "member_update: '%s'\n", data); /* Clear list */ - purple_conv_chat_clear_users(PURPLE_CONV_CHAT(convo)); + purple_chat_conversation_clear_users(chat); /* Add each member */ data = g_strstrip(data); /* string leading & trailing whitespace */ userlist = g_strsplit(data, "\n", 0); /* tokenize string */ while (userlist[i] != NULL) { purple_debug_info(MXIT_PLUGIN_ID, "member_update - adding: '%s'\n", userlist[i]); - purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), userlist[i], NULL, PURPLE_CBFLAGS_NONE, FALSE); + purple_chat_conversation_add_user(chat, userlist[i], NULL, PURPLE_CHAT_USER_NONE, FALSE); i++; } g_strfreev(userlist); @@ -377,8 +377,8 @@ void multimx_message_received(struct RXMsgData* mx, char* msg, int msglen, short /* Must be a service message */ char* ofs; - PurpleConversation* convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, multimx->roomname, mx->session->acc); - if (convo == NULL) { + PurpleChatConversation* chat = purple_conversations_find_chat_with_account(multimx->roomname, mx->session->acc); + if (chat == NULL) { purple_debug_error(MXIT_PLUGIN_ID, "Conversation '%s' not found\n", multimx->roomname); return; } @@ -387,28 +387,28 @@ void multimx_message_received(struct RXMsgData* mx, char* msg, int msglen, short if ((ofs = strstr(msg, " has joined")) != NULL) { /* Somebody has joined */ *ofs = '\0'; - member_added(convo, msg); + member_added(chat, msg); mx->processed = TRUE; } else if ((ofs = strstr(msg, " has left")) != NULL) { /* Somebody has left */ *ofs = '\0'; - member_removed(convo, msg); + member_removed(chat, msg); mx->processed = TRUE; } else if ((ofs = strstr(msg, " has been kicked")) != NULL) { /* Somebody has been kicked */ *ofs = '\0'; - member_kicked(convo, msg); + member_kicked(chat, msg); mx->processed = TRUE; } else if (strcmp(msg, "You have been kicked.") == 0) { /* You have been kicked */ - you_kicked(convo, mx->session, multimx); + you_kicked(chat, mx->session, multimx); mx->processed = TRUE; } else if (g_str_has_prefix(msg, "The following users are in this MultiMx:") == TRUE) { - member_update(convo, msg + strlen("The following users are in this MultiMx:") + 1); + member_update(chat, msg + strlen("The following users are in this MultiMx:") + 1); mx->processed = TRUE; } else { @@ -544,7 +544,7 @@ void mxit_chat_invite(PurpleConnection *gc, int id, const char *msg, const char struct MXitSession* session = purple_connection_get_protocol_data(gc); struct multimx* multimx = NULL; PurpleBuddy* buddy; - PurpleConversation *convo; + PurpleChatConversation *chat; char* tmp; purple_debug_info(MXIT_PLUGIN_ID, "Groupchat invite to '%s'\n", username); @@ -559,22 +559,22 @@ void mxit_chat_invite(PurpleConnection *gc, int id, const char *msg, const char /* Send invite to MXit */ mxit_send_groupchat_invite(session, multimx->roomid, 1, &username); - /* Find the buddy information for this contact (reference: "libpurple/blist.h") */ - buddy = purple_find_buddy(session->acc, username); + /* Find the buddy information for this contact (reference: "libpurple/buddylist.h") */ + buddy = purple_blist_find_buddy(session->acc, username); if (!buddy) { purple_debug_warning(MXIT_PLUGIN_ID, "mxit_chat_invite: unable to find the buddy '%s'\n", username); return; } - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, multimx->roomname, session->acc); - if (convo == NULL) { + chat = purple_conversations_find_chat_with_account(multimx->roomname, session->acc); + if (chat == NULL) { purple_debug_error(MXIT_PLUGIN_ID, "Conversation '%s' not found\n", multimx->roomname); return; } /* Display system message in chat window */ tmp = g_strdup_printf("%s: %s", _("You have invited"), purple_buddy_get_alias(buddy)); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "MXit", tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write_message(PURPLE_CONVERSATION(chat), "MXit", tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(tmp); } @@ -638,7 +638,7 @@ int mxit_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMess if (multimx->nickname) nickname = multimx->nickname; else - nickname = purple_account_get_alias(purple_connection_get_account(gc)); /* local alias */ + nickname = purple_account_get_private_alias(purple_connection_get_account(gc)); /* local alias */ /* Display message in chat window */ serv_got_chat_in(gc, id, nickname, flags, message, time(NULL)); diff --git a/libpurple/protocols/mxit/mxit.c b/libpurple/protocols/mxit/mxit.c index 119b0b7648..d4ce14203b 100644 --- a/libpurple/protocols/mxit/mxit.c +++ b/libpurple/protocols/mxit/mxit.c @@ -180,7 +180,7 @@ static void mxit_cb_chat_created( PurpleConversation* conv, struct MXitSession* /* not our conversation */ return; } - else if ( purple_conversation_get_type( conv ) != PURPLE_CONV_TYPE_IM ) { + else if ( PURPLE_IS_CHAT_CONVERSATION( conv ) ) { /* wrong type of conversation */ return; } @@ -193,7 +193,7 @@ static void mxit_cb_chat_created( PurpleConversation* conv, struct MXitSession* purple_debug_info( MXIT_PLUGIN_ID, "Conversation started with '%s'\n", who ); /* find the buddy object */ - buddy = purple_find_buddy( session->acc, who ); + buddy = purple_blist_find_buddy( session->acc, who ); if ( !buddy ) return; @@ -426,7 +426,7 @@ static void mxit_set_status( PurpleAccount* account, PurpleStatus* status ) char* statusmsg2; /* Handle mood changes */ - if ( purple_status_type_get_primitive( purple_status_get_type( status ) ) == PURPLE_STATUS_MOOD ) { + if ( purple_status_type_get_primitive( purple_status_get_status_type( status ) ) == PURPLE_STATUS_MOOD ) { const char* moodid = purple_status_get_attr_string( status, PURPLE_MOOD_NAME ); int mood; @@ -564,8 +564,8 @@ static void mxit_get_info( PurpleConnection *gc, const char *who ) purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_info: '%s'\n", who ); - /* find the buddy information for this contact (reference: "libpurple/blist.h") */ - buddy = purple_find_buddy( session->acc, who ); + /* find the buddy information for this contact (reference: "libpurple/buddylist.h") */ + buddy = purple_blist_find_buddy( session->acc, who ); if ( buddy ) { /* user is in our contact-list, so it's not an invite */ contact = purple_buddy_get_protocol_data( buddy ); @@ -633,7 +633,7 @@ static GList* mxit_blist_menu( PurpleBlistNode *node ) GList* m = NULL; PurpleMenuAction* act; - if ( !PURPLE_BLIST_NODE_IS_BUDDY( node ) ) + if ( !PURPLE_IS_BUDDY( node ) ) return NULL; buddy = (PurpleBuddy *) node; @@ -669,7 +669,7 @@ static GHashTable *mxit_chat_info_defaults( PurpleConnection *gc, const char *ch * @param name The username of the contact * @param state The typing state to be reported. */ -static unsigned int mxit_send_typing( PurpleConnection *gc, const char *name, PurpleTypingState state ) +static unsigned int mxit_send_typing( PurpleConnection *gc, const char *name, PurpleIMTypingState state ) { PurpleAccount* account = purple_connection_get_account( gc ); struct MXitSession* session = purple_connection_get_protocol_data( gc ); @@ -677,8 +677,8 @@ static unsigned int mxit_send_typing( PurpleConnection *gc, const char *name, Pu struct contact* contact; gchar* messageId = NULL; - /* find the buddy information for this contact (reference: "libpurple/blist.h") */ - buddy = purple_find_buddy( account, name ); + /* find the buddy information for this contact (reference: "libpurple/buddylist.h") */ + buddy = purple_blist_find_buddy( account, name ); if ( !buddy ) { purple_debug_warning( MXIT_PLUGIN_ID, "mxit_send_typing: unable to find the buddy '%s'\n", name ); return 0; @@ -695,12 +695,12 @@ static unsigned int mxit_send_typing( PurpleConnection *gc, const char *name, Pu messageId = purple_uuid_random(); /* generate a unique message id */ switch ( state ) { - case PURPLE_TYPING : /* currently typing */ + case PURPLE_IM_TYPING : /* currently typing */ mxit_send_msgevent( session, name, messageId, CP_MSGEVENT_TYPING ); break; - case PURPLE_TYPED : /* stopped typing */ - case PURPLE_NOT_TYPING : /* not typing / erased all text */ + case PURPLE_IM_TYPED : /* stopped typing */ + case PURPLE_IM_NOT_TYPING : /* not typing / erased all text */ mxit_send_msgevent( session, name, messageId, CP_MSGEVENT_STOPPED ); break; diff --git a/libpurple/protocols/mxit/profile.c b/libpurple/protocols/mxit/profile.c index 0fc5b49788..8d7568480f 100644 --- a/libpurple/protocols/mxit/profile.c +++ b/libpurple/protocols/mxit/profile.c @@ -201,7 +201,7 @@ void mxit_show_profile( struct MXitSession* session, const char* username, struc PurpleBuddy* buddy; gchar* tmp = NULL; - buddy = purple_find_buddy( session->acc, username ); + buddy = purple_blist_find_buddy( session->acc, username ); if ( buddy ) { purple_notify_user_info_add_pair_plaintext( info, _( "Alias" ), purple_buddy_get_alias( buddy ) ); purple_notify_user_info_add_section_break( info ); diff --git a/libpurple/protocols/mxit/protocol.c b/libpurple/protocols/mxit/protocol.c index ba879d80e2..39d151ddef 100644 --- a/libpurple/protocols/mxit/protocol.c +++ b/libpurple/protocols/mxit/protocol.c @@ -1444,7 +1444,7 @@ static void mxit_parse_cmd_login( struct MXitSession* session, struct record** r /* we were not yet logged in so we need to complete the login sequence here */ session->flags |= MXIT_FLAG_LOGGEDIN; purple_connection_update_progress( session->con, _( "Successfully Logged In..." ), 3, 4 ); - purple_connection_set_state( session->con, PURPLE_CONNECTED ); + purple_connection_set_state( session->con, PURPLE_CONNECTION_CONNECTED ); /* save extra info if this is a HTTP connection */ if ( session->http ) { @@ -1535,7 +1535,7 @@ static void mxit_parse_cmd_message( struct MXitSession* session, struct record** const char* name; char msg[128]; - buddy = purple_find_buddy( session->acc, sender ); + buddy = purple_blist_find_buddy( session->acc, sender ); if ( buddy ) name = purple_buddy_get_alias( buddy ); else @@ -1938,7 +1938,7 @@ static void mxit_parse_cmd_extprofile( struct MXitSession* session, struct recor /* update the status message */ PurpleBuddy* buddy = NULL; - buddy = purple_find_buddy( session->acc, mxitId ); + buddy = purple_blist_find_buddy( session->acc, mxitId ); if ( buddy ) { contact = purple_buddy_get_protocol_data( buddy ); if ( contact ) { @@ -2068,7 +2068,7 @@ static void mxit_parse_cmd_msgevent( struct MXitSession* session, struct record* switch ( event ) { case CP_MSGEVENT_TYPING : /* user is typing */ case CP_MSGEVENT_ANGRY : /* user is typing angrily */ - serv_got_typing( session->con, records[0]->fields[0]->data, 0, PURPLE_TYPING ); + serv_got_typing( session->con, records[0]->fields[0]->data, 0, PURPLE_IM_TYPING ); break; case CP_MSGEVENT_STOPPED : /* user has stopped typing */ diff --git a/libpurple/protocols/mxit/roster.c b/libpurple/protocols/mxit/roster.c index 82281a7257..814b88d620 100644 --- a/libpurple/protocols/mxit/roster.c +++ b/libpurple/protocols/mxit/roster.c @@ -75,7 +75,7 @@ GList* mxit_status_types( PurpleAccount* account ) /* add mxit status (reference: "libpurple/status.h") */ type = purple_status_type_new_with_attrs( status->primitive, status->id, _( status->name ), TRUE, TRUE, FALSE, - "message", _( "Message" ), purple_value_new( PURPLE_TYPE_STRING ), + "message", _( "Message" ), purple_g_value_new( G_TYPE_STRING ), NULL ); statuslist = g_list_append( statuslist, type ); @@ -83,7 +83,7 @@ GList* mxit_status_types( PurpleAccount* account ) /* add Mood option */ type = purple_status_type_new_with_attrs( PURPLE_STATUS_MOOD, "mood", NULL, FALSE, TRUE, TRUE, - PURPLE_MOOD_NAME, _( "Mood Name" ), purple_value_new( PURPLE_TYPE_STRING ), + PURPLE_MOOD_NAME, _( "Mood Name" ), purple_g_value_new( G_TYPE_STRING ), NULL ); statuslist = g_list_append( statuslist, type ); @@ -377,17 +377,17 @@ void mxit_update_contact( struct MXitSession* session, struct contact* contact ) } /* find or create a group for this contact */ - group = purple_find_group( contact->groupname ); + group = purple_blist_find_group( contact->groupname ); if ( !group ) group = purple_group_new( contact->groupname ); /* see if the buddy is not in the group already */ - buddy = purple_find_buddy_in_group( session->acc, contact->username, group ); + buddy = purple_blist_find_buddy_in_group( session->acc, contact->username, group ); if ( !buddy ) { /* buddy not found in the group */ /* lets try finding him in all groups */ - buddy = purple_find_buddy( session->acc, contact->username ); + buddy = purple_blist_find_buddy( session->acc, contact->username ); if ( buddy ) { /* ok, so we found him in another group. to switch him between groups we must delete him and add him again. */ purple_blist_remove_buddy( buddy ); @@ -407,7 +407,7 @@ void mxit_update_contact( struct MXitSession* session, struct contact* contact ) gpointer data = NULL; /* now update the buddy's alias */ - purple_blist_alias_buddy( buddy, contact->alias ); + purple_buddy_set_local_alias( buddy, contact->alias ); /* replace the buddy's contact struct */ if ( ( data = purple_buddy_get_protocol_data( buddy ) ) ) @@ -458,8 +458,8 @@ void mxit_update_buddy_presence( struct MXitSession* session, const char* userna return; /* ignore packet */ } - /* find the buddy information for this contact (reference: "libpurple/blist.h") */ - buddy = purple_find_buddy( session->acc, username ); + /* find the buddy information for this contact (reference: "libpurple/buddylist.h") */ + buddy = purple_blist_find_buddy( session->acc, username ); if ( !buddy ) { purple_debug_warning( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: unable to find the buddy '%s'\n", username ); return; @@ -517,8 +517,8 @@ void mxit_update_buddy_avatar( struct MXitSession* session, const char* username purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_buddy_avatar: user='%s' avatar='%s'\n", username, avatarId ); - /* find the buddy information for this contact (reference: "libpurple/blist.h") */ - buddy = purple_find_buddy( session->acc, username ); + /* find the buddy information for this contact (reference: "libpurple/buddylist.h") */ + buddy = purple_blist_find_buddy( session->acc, username ); if ( !buddy ) { purple_debug_warning( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: unable to find the buddy '%s'\n", username ); return; @@ -558,7 +558,7 @@ void mxit_update_blist( struct MXitSession* session ) /* remove all buddies we did not receive a roster update for. * these contacts must have been removed from another client */ - list = purple_find_buddies( session->acc, NULL ); + list = purple_blist_find_buddies( session->acc, NULL ); for ( i = 0; i < g_slist_length( list ); i++ ) { buddy = g_slist_nth_data( list, i ); @@ -700,7 +700,7 @@ gboolean is_mxit_chatroom_contact( struct MXitSession* session, const char* user struct contact* contact = NULL; /* find the buddy */ - buddy = purple_find_buddy( session->acc, username ); + buddy = purple_blist_find_buddy( session->acc, username ); if ( !buddy ) { purple_debug_warning( MXIT_PLUGIN_ID, "is_mxit_chatroom_contact: unable to find the buddy '%s'\n", username ); return FALSE; @@ -738,7 +738,7 @@ void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* grou purple_debug_info( MXIT_PLUGIN_ID, "mxit_add_buddy '%s' (group='%s')\n", buddy_name, group_name ); - list = purple_find_buddies( session->acc, buddy_name ); + list = purple_blist_find_buddies( session->acc, buddy_name ); if ( g_slist_length( list ) == 1 ) { purple_debug_info( MXIT_PLUGIN_ID, "mxit_add_buddy (scenario 1) (list:%i)\n", g_slist_length( list ) ); /* @@ -773,7 +773,7 @@ void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* grou /* this is our REAL MXit buddy! */ /* now update the buddy's alias */ - purple_blist_alias_buddy( mxbuddy, buddy_alias ); + purple_buddy_set_local_alias( mxbuddy, buddy_alias ); /* now update the buddy's group */ // mxbuddy = mxit_update_buddy_group( session, mxbuddy, group ); @@ -831,7 +831,7 @@ void mxit_buddy_alias( PurpleConnection* gc, const char* who, const char* alias purple_debug_info( MXIT_PLUGIN_ID, "mxit_buddy_alias '%s' to '%s\n", who, alias ); /* find the buddy */ - buddy = purple_find_buddy( session->acc, who ); + buddy = purple_blist_find_buddy( session->acc, who ); if ( !buddy ) { purple_debug_warning( MXIT_PLUGIN_ID, "mxit_buddy_alias: unable to find the buddy '%s'\n", who ); return; @@ -864,7 +864,7 @@ void mxit_buddy_group( PurpleConnection* gc, const char* who, const char* old_gr purple_debug_info( MXIT_PLUGIN_ID, "mxit_buddy_group from '%s' to '%s'\n", old_group, new_group ); /* find the buddy */ - buddy = purple_find_buddy( session->acc, who ); + buddy = purple_blist_find_buddy( session->acc, who ); if ( !buddy ) { purple_debug_warning( MXIT_PLUGIN_ID, "mxit_buddy_group: unable to find the buddy '%s'\n", who ); return; diff --git a/libpurple/protocols/mxit/voicevideo.c b/libpurple/protocols/mxit/voicevideo.c index aa30dc31b6..a254044b85 100644 --- a/libpurple/protocols/mxit/voicevideo.c +++ b/libpurple/protocols/mxit/voicevideo.c @@ -75,8 +75,8 @@ PurpleMediaCaps mxit_media_caps(PurpleAccount *account, const char *who) if (!*session->voip_server) return PURPLE_MEDIA_CAPS_NONE; - /* find the buddy information for this contact (reference: "libpurple/blist.h") */ - buddy = purple_find_buddy(account, who); + /* find the buddy information for this contact (reference: "libpurple/buddylist.h") */ + buddy = purple_blist_find_buddy(account, who); if (!buddy) { purple_debug_warning(MXIT_PLUGIN_ID, "mxit_media_caps: unable to find the buddy '%s'\n", who); return PURPLE_MEDIA_CAPS_NONE; diff --git a/libpurple/protocols/myspace/myspace.c b/libpurple/protocols/myspace/myspace.c index 8ac44c247a..3b469e537c 100644 --- a/libpurple/protocols/myspace/myspace.c +++ b/libpurple/protocols/myspace/myspace.c @@ -36,8 +36,6 @@ #include "myspace.h" -#include "privacy.h" - static void msim_set_status(PurpleAccount *account, PurpleStatus *status); static void msim_set_idle(PurpleConnection *gc, int time); @@ -134,7 +132,7 @@ msim_postprocess_outgoing_cb(MsimSession *session, const MsimMessage *userinfo, gchar *msg; msg = g_strdup_printf(_("No such user: %s"), username); - if (!purple_conv_present_error(username, session->account, msg)) { + if (!purple_conversation_present_error(username, session->account, msg)) { purple_notify_error(NULL, NULL, _("User lookup"), msg); } @@ -200,7 +198,7 @@ msim_postprocess_outgoing(MsimSession *session, MsimMessage *msg, uid = atol(username); } else { /* Next, see if on buddy list and know uid. */ - buddy = purple_find_buddy(session->account, username); + buddy = purple_blist_find_buddy(session->account, username); if (buddy) { uid = purple_blist_node_get_int(PURPLE_BLIST_NODE(buddy), "UserID"); } else { @@ -291,7 +289,7 @@ msim_uid2username_from_blist(PurpleAccount *account, guint wanted_uid) GSList *buddies, *cur; const gchar *ret; - buddies = purple_find_buddies(account, NULL); + buddies = purple_blist_find_buddies(account, NULL); if (!buddies) { @@ -473,7 +471,7 @@ msim_status_types(PurpleAccount *acct) /* Attributes - each status can have a message. */ \ "message", \ _("Message"), \ - purple_value_new(PURPLE_TYPE_STRING), \ + purple_g_value_new(G_TYPE_STRING), \ NULL); \ \ \ @@ -494,8 +492,8 @@ msim_status_types(PurpleAccount *acct) TRUE, /* should be user_settable some day */ TRUE, /* independent */ - PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_g_value_new(G_TYPE_STRING), + PURPLE_TUNE_TITLE, _("Tune Title"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, status); @@ -530,9 +528,8 @@ static gchar * msim_compute_login_response(const gchar nonce[2 * NONCE_SIZE], const gchar *email, const gchar *password, guint *response_len) { - PurpleCipherContext *key_context; - PurpleCipher *sha1; - PurpleCipherContext *rc4; + PurpleHash *sha1; + PurpleCipher *rc4; guchar hash_pw[HASH_SIZE]; guchar key[HASH_SIZE]; @@ -581,8 +578,11 @@ msim_compute_login_response(const gchar nonce[2 * NONCE_SIZE], } /* Compute password hash */ - purple_cipher_digest_region("sha1", (guchar *)password_utf16le, - conv_bytes_written, hash_pw, sizeof(hash_pw)); + sha1 = purple_sha1_hash_new(); + purple_hash_append(sha1, (guchar *)password_utf16le, + conv_bytes_written); + purple_hash_digest(sha1, hash_pw, sizeof(hash_pw)); + purple_hash_reset(sha1); g_free(password_utf16le); #ifdef MSIM_DEBUG_LOGIN_CHALLENGE @@ -593,12 +593,10 @@ msim_compute_login_response(const gchar nonce[2 * NONCE_SIZE], #endif /* key = sha1(sha1(pw) + nonce2) */ - sha1 = purple_ciphers_find_cipher("sha1"); - key_context = purple_cipher_context_new(sha1, NULL); - purple_cipher_context_append(key_context, hash_pw, HASH_SIZE); - purple_cipher_context_append(key_context, (guchar *)(nonce + NONCE_SIZE), NONCE_SIZE); - purple_cipher_context_digest(key_context, key, sizeof(key)); - purple_cipher_context_destroy(key_context); + purple_hash_append(sha1, hash_pw, HASH_SIZE); + purple_hash_append(sha1, (guchar *)(nonce + NONCE_SIZE), NONCE_SIZE); + purple_hash_digest(sha1, key, sizeof(key)); + g_object_unref(sha1); #ifdef MSIM_DEBUG_LOGIN_CHALLENGE purple_debug_info("msim", "key = "); @@ -608,11 +606,11 @@ msim_compute_login_response(const gchar nonce[2 * NONCE_SIZE], purple_debug_info("msim", "\n"); #endif - rc4 = purple_cipher_context_new_by_name("rc4", NULL); + rc4 = purple_rc4_cipher_new(); /* Note: 'key' variable is 0x14 bytes (from SHA-1 hash), * but only first 0x10 used for the RC4 key. */ - purple_cipher_context_set_key(rc4, key, 0x10); + purple_cipher_set_key(rc4, key, 0x10); /* rc4 encrypt: * nonce1+email+IP list */ @@ -638,9 +636,9 @@ msim_compute_login_response(const gchar nonce[2 * NONCE_SIZE], data_out = g_new0(guchar, data->len); - data_out_len = purple_cipher_context_encrypt(rc4, + data_out_len = purple_cipher_encrypt(rc4, (const guchar *)data->str, data->len, data_out, data->len); - purple_cipher_context_destroy(rc4); + g_object_unref(rc4); if (data_out_len != data->len) { purple_debug_info("msim", "msim_compute_login_response: " @@ -1006,7 +1004,7 @@ msim_add_contact_from_server_cb(MsimSession *session, const MsimMessage *user_lo group_name = g_strdup(_("IM Friends")); purple_debug_info("myspace", "No GroupName specified, defaulting to '%s'.\n", group_name); } - group = purple_find_group(group_name); + group = purple_blist_find_group(group_name); if (!group) { group = purple_group_new(group_name); /* Add group to beginning. See #2752. */ @@ -1017,7 +1015,7 @@ msim_add_contact_from_server_cb(MsimSession *session, const MsimMessage *user_lo visibility = msim_msg_get_integer(contact_info, "Visibility"); if (visibility == 2) { /* This buddy is blocked (and therefore not on our buddy list */ - purple_privacy_deny_add(session->account, username, TRUE); + purple_account_privacy_deny_add(session->account, username, TRUE); msim_msg_free(contact_info); g_free(username); g_free(display_name); @@ -1025,7 +1023,7 @@ msim_add_contact_from_server_cb(MsimSession *session, const MsimMessage *user_lo } /* 2. Get or create buddy */ - buddy = purple_find_buddy(session->account, username); + buddy = purple_blist_find_buddy(session->account, username); if (!buddy) { purple_debug_info("msim_add_contact_from_server_cb", "creating new buddy: %s\n", username); @@ -1152,7 +1150,7 @@ msim_got_contact_list(MsimSession *session, const MsimMessage *reply, gpointer u * signedOn signal, so clients can now do anything with msimprpl, and * we're ready for it (session key, userid, username all setup). */ purple_connection_update_progress(session->gc, _("Connected"), 3, 4); - purple_connection_set_state(session->gc, PURPLE_CONNECTED); + purple_connection_set_state(session->gc, PURPLE_CONNECTION_CONNECTED); break; } @@ -1488,10 +1486,10 @@ msim_incoming_im(MsimSession *session, MsimMessage *msg, const gchar *username) gchar *msg_msim_markup, *msg_purple_markup; gchar *userid; time_t time_received; - PurpleConversation *conv; + PurpleIMConversation *im; /* I know this isn't really a string... but we need it to be one for - * purple_find_conversation_with_account(). */ + * purple_conversations_find_with_account(). */ userid = msim_msg_get_string(msg, "f"); purple_debug_info("msim_incoming_im", "UserID is %s", userid); @@ -1502,11 +1500,11 @@ msim_incoming_im(MsimSession *session, MsimMessage *msg, const gchar *username) return FALSE; } - /* See if a conversation with their UID already exists...*/ - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, userid, session->account); - if (conv) { - /* Since the conversation exists... We need to normalize it */ - purple_conversation_set_name(conv, username); + /* See if an IM with their UID already exists...*/ + im = purple_conversations_find_im_with_account(userid, session->account); + if (im) { + /* Since the IM exists... We need to normalize it */ + purple_conversation_set_name(PURPLE_CONVERSATION(im), username); } msg_msim_markup = msim_msg_get_string(msg, "msg"); @@ -1555,7 +1553,7 @@ msim_incoming_action_or_im(MsimSession *session, MsimMessage *msg) msg_text, username); if (g_str_equal(msg_text, "%typing%")) { - serv_got_typing(session->gc, username, 0, PURPLE_TYPING); + serv_got_typing(session->gc, username, 0, PURPLE_IM_TYPING); rc = TRUE; } else if (g_str_equal(msg_text, "%stoptyping%")) { serv_got_typing_stopped(session->gc, username); @@ -1613,7 +1611,7 @@ msim_incoming_media(MsimSession *session, MsimMessage *msg) /* Media messages are sent when the user opens a window to someone. * Tell libpurple they started typing and stopped typing, to inform the Psychic * Mode plugin so it too can open a window to the user. */ - serv_got_typing(session->gc, username, 0, PURPLE_TYPING); + serv_got_typing(session->gc, username, 0, PURPLE_IM_TYPING); serv_got_typing_stopped(session->gc, username); g_free(username); @@ -2177,6 +2175,7 @@ msim_login(PurpleAccount *acct) { PurpleConnection *gc; const gchar *host; + GSList *deny; int port; g_return_if_fail(acct != NULL); @@ -2186,15 +2185,15 @@ msim_login(PurpleAccount *acct) gc = purple_account_get_connection(acct); purple_connection_set_protocol_data(gc, msim_session_new(acct)); - purple_connection_set_flags(gc, PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_URLDESC); + purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_HTML | PURPLE_CONNECTION_FLAG_NO_URLDESC); /* * Lets wipe out our local list of blocked buddies. We'll get a * list of all blocked buddies from the server, and we shouldn't * have stuff in the local list that isn't on the server list. */ - while (acct->deny != NULL) - purple_privacy_deny_remove(acct, acct->deny->data, TRUE); + while ((deny = purple_account_privacy_get_denied(acct)) != NULL) + purple_account_privacy_deny_remove(acct, deny->data, TRUE); /* 1. connect to server */ purple_connection_update_progress(gc, _("Connecting"), @@ -2247,7 +2246,7 @@ msim_close(PurpleConnection *gc) * should call our buddy_free prpl callback so that we don't need to do * this... but it doesn't, so we do. */ - buddies = purple_find_buddies(purple_connection_get_account(gc), NULL); + buddies = purple_blist_find_buddies(purple_connection_get_account(gc), NULL); while (buddies != NULL) { msim_buddy_free(buddies->data); buddies = g_slist_delete_link(buddies, buddies); @@ -2325,13 +2324,13 @@ msim_send_im(PurpleConnection *gc, const gchar *who, const gchar *message, * * @param gc * @param name The buddy name to which our user is typing to - * @param state PURPLE_TYPING, PURPLE_TYPED, PURPLE_NOT_TYPING + * @param state PURPLE_IM_TYPING, PURPLE_IM_TYPED, PURPLE_IM_NOT_TYPING * * @return 0 */ static unsigned int msim_send_typing(PurpleConnection *gc, const gchar *name, - PurpleTypingState state) + PurpleIMTypingState state) { const gchar *typing_str; MsimSession *session; @@ -2342,12 +2341,12 @@ msim_send_typing(PurpleConnection *gc, const gchar *name, session = purple_connection_get_protocol_data(gc); switch (state) { - case PURPLE_TYPING: + case PURPLE_IM_TYPING: typing_str = "%typing%"; break; - case PURPLE_TYPED: - case PURPLE_NOT_TYPING: + case PURPLE_IM_TYPED: + case PURPLE_IM_NOT_TYPING: default: typing_str = "%stoptyping%"; break; @@ -2493,7 +2492,7 @@ msim_set_status(PurpleAccount *account, PurpleStatus *status) session = purple_connection_get_protocol_data(gc); - type = purple_status_get_type(status); + type = purple_status_get_status_type(status); pres = purple_status_get_presence(status); switch (purple_status_type_get_primitive(type)) { @@ -3089,16 +3088,6 @@ static PurplePluginProtocolInfo prpl_info = { static gboolean msim_load(PurplePlugin *plugin) { - /* If compiled to use RC4 from libpurple, check if it is really there. */ - if (!purple_ciphers_find_cipher("rc4")) { - purple_debug_error("msim", "rc4 not in libpurple, but it is required - not loading MySpaceIM plugin!\n"); - purple_notify_error(plugin, _("Missing Cipher"), - _("The RC4 cipher could not be found"), - _("Upgrade " - "to a libpurple with RC4 support (>= 2.0.1). MySpaceIM " - "plugin will not be loaded.")); - return FALSE; - } return TRUE; } @@ -3404,7 +3393,7 @@ msim_uri_handler_addContact_cb(MsimSession *session, MsimMessage *userinfo, gpoi static void msim_uri_handler_sendIM_cb(MsimSession *session, MsimMessage *userinfo, gpointer data) { - PurpleConversation *conv; + PurpleIMConversation *im; MsimMessage *body; gchar *username; @@ -3422,14 +3411,14 @@ msim_uri_handler_sendIM_cb(MsimSession *session, MsimMessage *userinfo, gpointer } - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, session->account); - if (!conv) { + im = purple_conversations_find_im_with_account(username, session->account); + if (!im) { purple_debug_info("msim_uri_handler", "creating new conversation for %s\n", username); - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, session->account, username); + im = purple_im_conversation_new(session->account, username); } /* Just open the window so the user can send an IM. */ - purple_conversation_present(conv); + purple_conversation_present(PURPLE_CONVERSATION(im)); g_free(username); } diff --git a/libpurple/protocols/myspace/myspace.h b/libpurple/protocols/myspace/myspace.h index 8f5c975708..fd9a149fd3 100644 --- a/libpurple/protocols/myspace/myspace.h +++ b/libpurple/protocols/myspace/myspace.h @@ -42,7 +42,6 @@ #include "plugin.h" #include "accountopt.h" #include "version.h" -#include "cipher.h" /* for SHA-1 */ #include "util.h" /* for base64 */ #include "debug.h" /* for purple_debug_info */ #include "request.h" /* For dialogs used in setting the username */ @@ -50,6 +49,10 @@ #include "core.h" #include "conversation.h" /* For late normalization */ +/* Ciphers */ +#include "ciphers/rc4cipher.h" +#include "ciphers/sha1hash.h" + /* MySpaceIM includes */ #include "persist.h" #include "message.h" diff --git a/libpurple/protocols/myspace/user.c b/libpurple/protocols/myspace/user.c index a0775a1af1..b5ee54d2b2 100644 --- a/libpurple/protocols/myspace/user.c +++ b/libpurple/protocols/myspace/user.c @@ -93,7 +93,7 @@ msim_find_user(MsimSession *session, const gchar *username) { PurpleBuddy *buddy; - buddy = purple_find_buddy(session->account, username); + buddy = purple_blist_find_buddy(session->account, username); if (!buddy) { return NULL; } diff --git a/libpurple/protocols/myspace/zap.c b/libpurple/protocols/myspace/zap.c index 653b4d9f34..09dcf49bd1 100644 --- a/libpurple/protocols/myspace/zap.c +++ b/libpurple/protocols/myspace/zap.c @@ -143,7 +143,7 @@ msim_send_attention(PurpleConnection *gc, const gchar *username, guint code) return FALSE; } - buddy = purple_find_buddy(session->account, username); + buddy = purple_blist_find_buddy(session->account, username); if (!buddy) { return FALSE; } @@ -163,12 +163,12 @@ msim_send_zap_from_menu(PurpleBlistNode *node, gpointer zap_num_ptr) MsimSession *session; guint zap; - if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (!PURPLE_IS_BUDDY(node)) { /* Only know about buddies for now. */ return; } - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *)node; @@ -191,7 +191,7 @@ msim_blist_node_menu(PurpleBlistNode *node) PurpleMenuAction *act; guint i; - if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (!PURPLE_IS_BUDDY(node)) { /* Only know about buddies for now. */ return NULL; } diff --git a/libpurple/protocols/novell/novell.c b/libpurple/protocols/novell/novell.c index d0148c0cdb..7c366b3670 100644 --- a/libpurple/protocols/novell/novell.c +++ b/libpurple/protocols/novell/novell.c @@ -29,7 +29,6 @@ #include "sslconn.h" #include "request.h" #include "network.h" -#include "privacy.h" #include "status.h" #include "version.h" @@ -102,16 +101,16 @@ _login_resp_cb(NMUser * user, NMERR_T ret_code, if (ret_code == NM_OK) { /* Set alias for user if not set (use Full Name) */ - alias = purple_account_get_alias(user->client_data); + alias = purple_account_get_private_alias(user->client_data); if (alias == NULL || *alias == '\0') { alias = nm_user_record_get_full_name(user->user_record); if (alias) - purple_account_set_alias(user->client_data, alias); + purple_account_set_private_alias(user->client_data, alias); } /* Tell Purple that we are connected */ - purple_connection_set_state(gc, PURPLE_CONNECTED); + purple_connection_set_state(gc, PURPLE_CONNECTION_CONNECTED); _sync_contact_list(user); @@ -165,7 +164,7 @@ _get_status_resp_cb(NMUser * user, NMERR_T ret_code, const char *name = nm_user_record_get_display_id(user_record); if (name) { - buddies = purple_find_buddies((PurpleAccount *) user->client_data, name); + buddies = purple_blist_find_buddies((PurpleAccount *) user->client_data, name); for (bnode = buddies; bnode; bnode = bnode->next) { buddy = (PurpleBuddy *) bnode->data; if (buddy) { @@ -217,9 +216,8 @@ _get_details_resp_send_msg(NMUser * user, NMERR_T ret_code, if (user_record) { /* Set the title for the conversation */ - /* XXX - Should this be PURPLE_CONV_TYPE_IM? */ - gconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, - nm_user_record_get_display_id(user_record), + /* XXX - Should this be find_im_with_account? */ + gconv = purple_conversations_find_with_account(nm_user_record_get_display_id(user_record), (PurpleAccount *) user->client_data); if (gconv) { @@ -289,12 +287,12 @@ _get_details_resp_setup_buddy(NMUser * user, NMERR_T ret_code, nm_contact_set_user_record(contact, user_record); /* Set the display id */ - purple_blist_rename_buddy(buddy, + purple_buddy_set_name(buddy, nm_user_record_get_display_id(user_record)); alias = purple_buddy_get_alias(buddy); if (alias == NULL || *alias == '\0' || (strcmp(alias, purple_buddy_get_name(buddy)) == 0)) { - purple_blist_alias_buddy(buddy, + purple_buddy_set_local_alias(buddy, nm_user_record_get_full_name(user_record)); /* Tell the server about the new display name */ @@ -351,7 +349,7 @@ _create_contact_resp_cb(NMUser * user, NMERR_T ret_code, folder_name = NM_ROOT_FOLDER_NAME; /* Re-add the buddy now that we got the okay from the server */ - if (folder_name && (group = purple_find_group(folder_name))) { + if (folder_name && (group = purple_blist_find_group(folder_name))) { const char *alias = nm_contact_get_display_name(tmp_contact); const char *display_id = nm_contact_get_display_id(new_contact); @@ -373,7 +371,7 @@ _create_contact_resp_cb(NMUser * user, NMERR_T ret_code, } /* Add it to the purple buddy list if it is not there */ - buddy = purple_find_buddy_in_group(user->client_data, display_id, group); + buddy = purple_blist_find_buddy_in_group(user->client_data, display_id, group); if (buddy == NULL) { buddy = purple_buddy_new(user->client_data, display_id, alias); purple_blist_add_buddy(buddy, NULL, group, NULL); @@ -654,7 +652,7 @@ static void _join_conf_resp_cb(NMUser * user, NMERR_T ret_code, gpointer resp_data, gpointer user_data) { - PurpleConversation *chat; + PurpleChatConversation *chat; PurpleConnection *gc; NMUserRecord *ur; NMConference *conference = user_data; @@ -678,8 +676,8 @@ _join_conf_resp_cb(NMUser * user, NMERR_T ret_code, ur = nm_conference_get_participant(conference, i); if (ur) { name = nm_user_record_get_display_id(ur); - purple_conv_chat_add_user(PURPLE_CONV_CHAT(chat), name, NULL, - PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(chat, name, NULL, + PURPLE_CHAT_USER_NONE, TRUE); } } } @@ -726,6 +724,7 @@ _get_details_resp_add_privacy_item(NMUser *user, NMERR_T ret_code, gpointer resp_data, gpointer user_data) { PurpleConnection *gc; + PurpleAccount *account; NMUserRecord *user_record = resp_data; char *err; gboolean allowed = GPOINTER_TO_INT(user_data); @@ -736,21 +735,22 @@ _get_details_resp_add_privacy_item(NMUser *user, NMERR_T ret_code, gc = purple_account_get_connection(user->client_data); display_id = nm_user_record_get_display_id(user_record); + account = purple_connection_get_account(gc); if (ret_code == NM_OK) { if (allowed) { - if (!g_slist_find_custom(purple_connection_get_account(gc)->permit, + if (!g_slist_find_custom(purple_account_privacy_get_denied(account), display_id, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_permit_add(purple_connection_get_account(gc), display_id, TRUE); + purple_account_privacy_permit_add(account, display_id, TRUE); } } else { - if (!g_slist_find_custom(purple_connection_get_account(gc)->permit, + if (!g_slist_find_custom(purple_account_privacy_get_denied(account), display_id, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_deny_add(purple_connection_get_account(gc), display_id, TRUE); + purple_account_privacy_deny_add(account, display_id, TRUE); } } @@ -770,6 +770,7 @@ _create_privacy_item_deny_resp_cb(NMUser *user, NMERR_T ret_code, gpointer resp_data, gpointer user_data) { PurpleConnection *gc; + PurpleAccount *account; NMUserRecord *user_record; char *who = user_data; char *err; @@ -780,6 +781,7 @@ _create_privacy_item_deny_resp_cb(NMUser *user, NMERR_T ret_code, return; gc = purple_account_get_connection(user->client_data); + account = purple_connection_get_account(gc); if (ret_code == NM_OK) { @@ -789,10 +791,10 @@ _create_privacy_item_deny_resp_cb(NMUser *user, NMERR_T ret_code, if (display_id) { - if (!g_slist_find_custom(purple_connection_get_account(gc)->deny, + if (!g_slist_find_custom(purple_account_privacy_get_denied(account), display_id, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_deny_add(purple_connection_get_account(gc), display_id, TRUE); + purple_account_privacy_deny_add(account, display_id, TRUE); } } else { @@ -821,6 +823,7 @@ _create_privacy_item_permit_resp_cb(NMUser *user, NMERR_T ret_code, gpointer resp_data, gpointer user_data) { PurpleConnection *gc; + PurpleAccount *account; NMUserRecord *user_record; char *who = user_data; char *err; @@ -831,6 +834,7 @@ _create_privacy_item_permit_resp_cb(NMUser *user, NMERR_T ret_code, return; gc = purple_account_get_connection(user->client_data); + account = purple_connection_get_account(gc); if (ret_code == NM_OK) { @@ -840,11 +844,11 @@ _create_privacy_item_permit_resp_cb(NMUser *user, NMERR_T ret_code, if (display_id) { - if (!g_slist_find_custom(purple_connection_get_account(gc)->permit, + if (!g_slist_find_custom(purple_account_privacy_get_permitted(account), display_id, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_permit_add(purple_connection_get_account(gc), display_id, TRUE); + purple_account_privacy_permit_add(account, display_id, TRUE); } } else { @@ -979,7 +983,7 @@ _get_details_resp_send_invite(NMUser *user, NMERR_T ret_code, for (cnode = user->conferences; cnode != NULL; cnode = cnode->next) { conference = cnode->data; if (conference && (chat = nm_conference_get_data(conference))) { - if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(chat)) == id) { + if (purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat)) == id) { rc = nm_send_conference_invite(user, conference, user_record, NULL, _sendinvite_resp_cb, NULL); _check_for_disconnect(user, rc); @@ -1236,19 +1240,19 @@ _remove_purple_buddies(NMUser *user) for (gnode = purple_blist_get_root(); gnode; gnode = purple_blist_node_get_sibling_next(gnode)) { - if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) + if (!PURPLE_IS_GROUP(gnode)) continue; group = (PurpleGroup *) gnode; gname = purple_group_get_name(group); for (cnode = purple_blist_node_get_first_child(gnode); cnode; cnode = purple_blist_node_get_sibling_next(cnode)) { - if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) + if (!PURPLE_IS_CONTACT(cnode)) continue; for (bnode = purple_blist_node_get_first_child(cnode); bnode; bnode = purple_blist_node_get_sibling_next(bnode)) { - if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + if (!PURPLE_IS_BUDDY(bnode)) continue; buddy = (PurpleBuddy *) bnode; if (purple_buddy_get_account(buddy) == user->client_data) { @@ -1294,7 +1298,7 @@ _add_contacts_to_purple_blist(NMUser * user, NMFolder * folder) } /* Does the Purple group exist already? */ - group = purple_find_group(fname); + group = purple_blist_find_group(fname); if (group == NULL) { group = purple_group_new(fname); purple_blist_add_group(group, NULL); @@ -1309,7 +1313,7 @@ _add_contacts_to_purple_blist(NMUser * user, NMFolder * folder) name = nm_contact_get_display_id(contact); if (name) { - buddy = purple_find_buddy_in_group(user->client_data, name, group); + buddy = purple_blist_find_buddy_in_group(user->client_data, name, group); if (buddy == NULL) { /* Add it to the purple buddy list */ buddy = purple_buddy_new(user->client_data, @@ -1386,6 +1390,7 @@ _sync_privacy_lists(NMUser *user) { GSList *node = NULL, *rem_list = NULL; PurpleConnection *gc; + PurpleAccount *account; const char *name, *dn; NMUserRecord *user_record; @@ -1396,18 +1401,20 @@ _sync_privacy_lists(NMUser *user) if (gc == NULL) return; + account = purple_connection_get_account(gc); + /* Set the Purple privacy setting */ if (user->default_deny) { if (user->allow_list == NULL) { - purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_DENY_ALL); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_DENY_ALL); } else { - purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_ALLOW_USERS); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS); } } else { if (user->deny_list == NULL) { - purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_ALLOW_ALL); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL); } else { - purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_DENY_USERS); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_DENY_USERS); } } @@ -1419,9 +1426,9 @@ _sync_privacy_lists(NMUser *user) else name =(char *)node->data; - if (!g_slist_find_custom(purple_connection_get_account(gc)->permit, + if (!g_slist_find_custom(purple_account_privacy_get_permitted(account), name, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_permit_add(purple_connection_get_account(gc), name , TRUE); + purple_account_privacy_permit_add(account, name , TRUE); } } @@ -1432,15 +1439,15 @@ _sync_privacy_lists(NMUser *user) else name =(char *)node->data; - if (!g_slist_find_custom(purple_connection_get_account(gc)->deny, + if (!g_slist_find_custom(purple_account_privacy_get_denied(account), name, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_deny_add(purple_connection_get_account(gc), name, TRUE); + purple_account_privacy_deny_add(account, name, TRUE); } } /* Remove stuff */ - for (node = purple_connection_get_account(gc)->permit; node; node = node->next) { + for (node = purple_account_privacy_get_permitted(account); node; node = node->next) { dn = nm_lookup_dn(user, (char *)node->data); if (dn != NULL && !g_slist_find_custom(user->allow_list, @@ -1451,13 +1458,13 @@ _sync_privacy_lists(NMUser *user) if (rem_list) { for (node = rem_list; node; node = node->next) { - purple_privacy_permit_remove(purple_connection_get_account(gc), (char *)node->data, TRUE); + purple_account_privacy_permit_remove(account, (char *)node->data, TRUE); } g_slist_free(rem_list); rem_list = NULL; } - for (node = purple_connection_get_account(gc)->deny; node; node = node->next) { + for (node = purple_account_privacy_get_denied(account); node; node = node->next) { dn = nm_lookup_dn(user, (char *)node->data); if (dn != NULL && !g_slist_find_custom(user->deny_list, @@ -1468,7 +1475,7 @@ _sync_privacy_lists(NMUser *user) if (rem_list) { for (node = rem_list; node; node = node->next) { - purple_privacy_deny_remove(purple_connection_get_account(gc), (char *)node->data, TRUE); + purple_account_privacy_deny_remove(account, (char *)node->data, TRUE); } g_slist_free(rem_list); } @@ -1615,11 +1622,11 @@ _initiate_conference_cb(PurpleBlistNode *node, gpointer ignored) NMUser *user; const char *conf_name; - PurpleConversation *chat = NULL; + PurpleChatConversation *chat = NULL; NMUserRecord *user_record; NMConference *conference; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); @@ -1767,7 +1774,7 @@ _evt_receive_message(NMUser * user, NMEvent * event) { NMUserRecord *user_record = NULL; NMContact *contact = NULL; - PurpleConversation *gconv; + PurpleIMConversation *im; NMConference *conference; PurpleMessageFlags flags; char *text = NULL; @@ -1777,7 +1784,7 @@ _evt_receive_message(NMUser * user, NMEvent * event) conference = nm_event_get_conference(event); if (conference) { - PurpleConversation *chat = nm_conference_get_data(conference); + PurpleChatConversation *chat = nm_conference_get_data(conference); /* Is this a single person 'conversation' or a conference? */ if (chat == NULL && nm_conference_get_participant_count(conference) == 1) { @@ -1794,16 +1801,16 @@ _evt_receive_message(NMUser * user, NMEvent * event) text, flags, nm_event_get_gmt(event)); - gconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, + im = purple_conversations_find_im_with_account( nm_user_record_get_display_id(user_record), (PurpleAccount *) user->client_data); - if (gconv) { + if (im) { contact = nm_find_contact(user, nm_event_get_source(event)); if (contact) { - purple_conversation_set_title( - gconv, nm_contact_get_display_name(contact)); + purple_conversation_set_title(PURPLE_CONVERSATION(im), + nm_contact_get_display_name(contact)); } else { @@ -1814,7 +1821,7 @@ _evt_receive_message(NMUser * user, NMEvent * event) if (name == NULL) name = nm_user_record_get_userid(user_record); - purple_conversation_set_title(gconv, name); + purple_conversation_set_title(PURPLE_CONVERSATION(im), name); } } @@ -1845,7 +1852,7 @@ _evt_receive_message(NMUser * user, NMEvent * event) } serv_got_chat_in(purple_account_get_connection(user->client_data), - purple_conv_chat_get_id(PURPLE_CONV_CHAT(chat)), + purple_chat_conversation_get_id(chat), name, 0, text, nm_event_get_gmt(event)); } } @@ -1857,7 +1864,7 @@ _evt_receive_message(NMUser * user, NMEvent * event) static void _evt_conference_left(NMUser * user, NMEvent * event) { - PurpleConversation *chat; + PurpleChatConversation *chat; NMConference *conference; conference = nm_event_get_conference(event); @@ -1868,7 +1875,7 @@ _evt_conference_left(NMUser * user, NMEvent * event) nm_event_get_source(event)); if (ur) - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(chat), + purple_chat_conversation_remove_user(chat, nm_user_record_get_display_id(ur), NULL); } @@ -1945,7 +1952,7 @@ _evt_conference_invite(NMUser * user, NMEvent * event) static void _evt_conference_joined(NMUser * user, NMEvent * event) { - PurpleConversation *chat = NULL; + PurpleChatConversation *chat = NULL; PurpleConnection *gc; NMConference *conference = NULL; NMUserRecord *ur = NULL; @@ -1970,8 +1977,8 @@ _evt_conference_joined(NMUser * user, NMEvent * event) nm_conference_set_data(conference, (gpointer) chat); name = nm_user_record_get_display_id(ur); - purple_conv_chat_add_user(PURPLE_CONV_CHAT(chat), name, NULL, - PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(chat, name, NULL, + PURPLE_CHAT_USER_NONE, TRUE); } } @@ -1981,9 +1988,9 @@ _evt_conference_joined(NMUser * user, NMEvent * event) ur = nm_find_user_record(user, nm_event_get_source(event)); if (ur) { name = nm_user_record_get_display_id(ur); - if (!purple_conv_chat_find_user(PURPLE_CONV_CHAT(chat), name)) { - purple_conv_chat_add_user(PURPLE_CONV_CHAT(chat), name, NULL, - PURPLE_CBFLAGS_NONE, TRUE); + if (!purple_chat_conversation_has_user(chat, name)) { + purple_chat_conversation_add_user(chat, name, NULL, + PURPLE_CHAT_USER_NONE, TRUE); } } } @@ -2008,7 +2015,7 @@ _evt_status_change(NMUser * user, NMEvent * event) /* Update status for buddy in all folders */ display_id = nm_user_record_get_display_id(user_record); - buddies = purple_find_buddies(user->client_data, display_id); + buddies = purple_blist_find_buddies(user->client_data, display_id); for (bnode = buddies; bnode; bnode = bnode->next) { buddy = (PurpleBuddy *) bnode->data; if (buddy) { @@ -2049,7 +2056,7 @@ _evt_user_typing(NMUser * user, NMEvent * event) user_record = nm_find_user_record(user, nm_event_get_source(event)); if (user_record) { serv_got_typing(gc, nm_user_record_get_display_id(user_record), - 30, PURPLE_TYPING); + 30, PURPLE_IM_TYPING); } } } @@ -2081,8 +2088,7 @@ _evt_undeliverable_status(NMUser * user, NMEvent * event) if (ur) { /* XXX - Should this be PURPLE_CONV_TYPE_IM? */ gconv = - purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, - nm_user_record_get_display_id(ur), + purple_conversations_find_with_account(nm_user_record_get_display_id(ur), user->client_data); if (gconv) { const char *name = nm_user_record_get_full_name(ur); @@ -2337,7 +2343,7 @@ novell_send_im(PurpleConnection * gc, const char *name, } static unsigned int -novell_send_typing(PurpleConnection * gc, const char *name, PurpleTypingState state) +novell_send_typing(PurpleConnection * gc, const char *name, PurpleIMTypingState state) { NMConference *conf = NULL; NMUser *user; @@ -2360,7 +2366,7 @@ novell_send_typing(PurpleConnection * gc, const char *name, PurpleTypingState st if (conf) { rc = nm_send_typing(user, conf, - ((state == PURPLE_TYPING) ? TRUE : FALSE), NULL); + ((state == PURPLE_IM_TYPING) ? TRUE : FALSE), NULL); _check_for_disconnect(user, rc); } @@ -2396,7 +2402,7 @@ novell_chat_leave(PurpleConnection * gc, int id) { NMConference *conference; NMUser *user; - PurpleConversation *chat; + PurpleChatConversation *chat; GSList *cnode; NMERR_T rc = NM_OK; @@ -2410,7 +2416,7 @@ novell_chat_leave(PurpleConnection * gc, int id) for (cnode = user->conferences; cnode != NULL; cnode = cnode->next) { conference = cnode->data; if (conference && (chat = nm_conference_get_data(conference))) { - if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(chat)) == id) { + if (purple_chat_conversation_get_id(chat) == id) { rc = nm_send_leave_conference(user, conference, NULL, NULL); _check_for_disconnect(user, rc); break; @@ -2427,7 +2433,7 @@ novell_chat_invite(PurpleConnection *gc, int id, { NMConference *conference; NMUser *user; - PurpleConversation *chat; + PurpleChatConversation *chat; GSList *cnode; NMERR_T rc = NM_OK; NMUserRecord *user_record = NULL; @@ -2449,7 +2455,7 @@ novell_chat_invite(PurpleConnection *gc, int id, for (cnode = user->conferences; cnode != NULL; cnode = cnode->next) { conference = cnode->data; if (conference && (chat = nm_conference_get_data(conference))) { - if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(chat)) == id) { + if (purple_chat_conversation_get_id(chat) == id) { rc = nm_send_conference_invite(user, conference, user_record, message, _sendinvite_resp_cb, NULL); _check_for_disconnect(user, rc); @@ -2463,7 +2469,7 @@ static int novell_chat_send(PurpleConnection * gc, int id, const char *text, PurpleMessageFlags flags) { NMConference *conference; - PurpleConversation *chat; + PurpleChatConversation *chat; GSList *cnode; NMMessage *message; NMUser *user; @@ -2485,7 +2491,7 @@ novell_chat_send(PurpleConnection * gc, int id, const char *text, PurpleMessageF for (cnode = user->conferences; cnode != NULL; cnode = cnode->next) { conference = cnode->data; if (conference && (chat = nm_conference_get_data(conference))) { - if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(chat)) == id) { + if (purple_chat_conversation_get_id(chat) == id) { nm_message_set_conference(message, conference); @@ -2502,7 +2508,7 @@ novell_chat_send(PurpleConnection * gc, int id, const char *text, PurpleMessageF if (!_check_for_disconnect(user, rc)) { /* Use the account alias if it is set */ - name = purple_account_get_alias(user->client_data); + name = purple_account_get_private_alias(user->client_data); if (name == NULL || *name == '\0') { /* If there is no account alias, try full name */ @@ -2525,11 +2531,12 @@ novell_chat_send(PurpleConnection * gc, int id, const char *text, PurpleMessageF /* The conference was not found, must be closed */ - chat = purple_find_chat(gc, id); + chat = purple_conversations_find_chat(gc, id); if (chat) { str = g_strdup(_("This conference has been closed." " No more messages can be sent.")); - purple_conversation_write(chat, NULL, str, PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write(PURPLE_CONVERSATION(chat), NULL, str, + PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(str); } @@ -2691,16 +2698,16 @@ novell_alias_buddy(PurpleConnection * gc, const char *name, const char *alias) if (*fname == '\0') { fname = NM_ROOT_FOLDER_NAME; } - group = purple_find_group(fname); + group = purple_blist_find_group(fname); } if (group) { const char *balias; - buddy = purple_find_buddy_in_group(user->client_data, + buddy = purple_blist_find_buddy_in_group(user->client_data, name, group); - balias = buddy ? purple_buddy_get_local_buddy_alias(buddy) : NULL; + balias = buddy ? purple_buddy_get_local_alias(buddy) : NULL; if (balias && strcmp(balias, alias)) - purple_blist_alias_buddy(buddy, alias); + purple_buddy_set_local_alias(buddy, alias); } /* Tell the server to alias the contact */ @@ -2793,7 +2800,7 @@ novell_rename_group(PurpleConnection * gc, const char *old_name, const char *gname = purple_group_get_name(group); /* Does new folder exist already? */ if (nm_find_folder(user, gname)) { - /* purple_blist_rename_group() adds the buddies + /* purple_group_set_name() adds the buddies * to the new group and removes the old group... * so there is nothing more to do here. */ @@ -2975,19 +2982,19 @@ novell_status_types(PurpleAccount *account) type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, NOVELL_STATUS_TYPE_AVAILABLE, NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_append(status_types, type); type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, NOVELL_STATUS_TYPE_AWAY, NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_append(status_types, type); type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE, NOVELL_STATUS_TYPE_BUSY, _("Busy"), TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_append(status_types, type); @@ -3017,7 +3024,7 @@ novell_set_status(PurpleAccount *account, PurpleStatus *status) connected = purple_account_is_connected(account); presence = purple_status_get_presence(status); - type = purple_status_get_type(status); + type = purple_status_get_status_type(status); primitive = purple_status_type_get_primitive(type); /* @@ -3086,7 +3093,7 @@ novell_add_permit(PurpleConnection *gc, const char *who) /* Remove first -- we will add it back in when we get * the okay from the server */ - purple_privacy_permit_remove(purple_connection_get_account(gc), who, TRUE); + purple_account_privacy_permit_remove(purple_connection_get_account(gc), who, TRUE); if (nm_user_is_privacy_locked(user)) { _show_privacy_locked_error(gc, user); @@ -3130,7 +3137,7 @@ novell_add_deny(PurpleConnection *gc, const char *who) /* Remove first -- we will add it back in when we get * the okay from the server */ - purple_privacy_deny_remove(purple_connection_get_account(gc), who, TRUE); + purple_account_privacy_deny_remove(purple_connection_get_account(gc), who, TRUE); if (nm_user_is_privacy_locked(user)) { _show_privacy_locked_error(gc, user); @@ -3228,10 +3235,13 @@ novell_set_permit_deny(PurpleConnection *gc) int i, j, num_contacts, num_folders; NMContact *contact; NMFolder *folder = NULL; + PurpleAccount *account; if (gc == NULL) return; + account = purple_connection_get_account(gc); + user = purple_connection_get_protocol_data(gc); if (user == NULL) return; @@ -3248,9 +3258,9 @@ novell_set_permit_deny(PurpleConnection *gc) return; } - switch (purple_account_get_privacy_type(purple_connection_get_account(gc))) { + switch (purple_account_get_privacy_type(account)) { - case PURPLE_PRIVACY_ALLOW_ALL: + case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL: rc = nm_send_set_privacy_default(user, FALSE, _set_privacy_default_resp_cb, NULL); _check_for_disconnect(user, rc); @@ -3270,7 +3280,7 @@ novell_set_permit_deny(PurpleConnection *gc) } break; - case PURPLE_PRIVACY_DENY_ALL: + case PURPLE_ACCOUNT_PRIVACY_DENY_ALL: rc = nm_send_set_privacy_default(user, TRUE, _set_privacy_default_resp_cb, NULL); _check_for_disconnect(user, rc); @@ -3290,7 +3300,7 @@ novell_set_permit_deny(PurpleConnection *gc) } break; - case PURPLE_PRIVACY_ALLOW_USERS: + case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: rc = nm_send_set_privacy_default(user, TRUE, _set_privacy_default_resp_cb, NULL); @@ -3304,14 +3314,14 @@ novell_set_permit_deny(PurpleConnection *gc) if (user_record) { name = nm_user_record_get_display_id(user_record); - if (!g_slist_find_custom(purple_connection_get_account(gc)->permit, + if (!g_slist_find_custom(purple_account_privacy_get_permitted(account), name, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_permit_add(purple_connection_get_account(gc), name , TRUE); + purple_account_privacy_permit_add(account, name , TRUE); } } } - for (node = purple_connection_get_account(gc)->permit; node; node = node->next) { + for (node = purple_account_privacy_get_permitted(account); node; node = node->next) { dn = nm_lookup_dn(user, (char *)node->data); if (dn) { @@ -3322,13 +3332,13 @@ novell_set_permit_deny(PurpleConnection *gc) g_strdup(dn)); } } else { - purple_privacy_permit_remove(purple_connection_get_account(gc), (char *)node->data, TRUE); + purple_account_privacy_permit_remove(account, (char *)node->data, TRUE); } } } break; - case PURPLE_PRIVACY_DENY_USERS: + case PURPLE_ACCOUNT_PRIVACY_DENY_USERS: /* set to default allow */ rc = nm_send_set_privacy_default(user, FALSE, @@ -3343,14 +3353,14 @@ novell_set_permit_deny(PurpleConnection *gc) if (user_record) { name = nm_user_record_get_display_id(user_record); - if (!g_slist_find_custom(purple_connection_get_account(gc)->deny, + if (!g_slist_find_custom(purple_account_privacy_get_denied(account), name, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_deny_add(purple_connection_get_account(gc), name , TRUE); + purple_account_privacy_deny_add(account, name , TRUE); } } } - for (node = purple_connection_get_account(gc)->deny; node; node = node->next) { + for (node = purple_account_privacy_get_denied(account); node; node = node->next) { name = NULL; dn = nm_lookup_dn(user, (char *)node->data); @@ -3365,14 +3375,14 @@ novell_set_permit_deny(PurpleConnection *gc) g_strdup(name)); } } else { - purple_privacy_deny_remove(purple_connection_get_account(gc), (char *)node->data, TRUE); + purple_account_privacy_deny_remove(account, (char *)node->data, TRUE); } } } break; - case PURPLE_PRIVACY_ALLOW_BUDDYLIST: + case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST: /* remove users from allow list that are not in buddy list */ copy = g_slist_copy(user->allow_list); @@ -3438,7 +3448,7 @@ novell_blist_node_menu(PurpleBlistNode *node) GList *list = NULL; PurpleMenuAction *act; - if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if(PURPLE_IS_BUDDY(node)) { act = purple_menu_action_new(_("Initiate _Chat"), PURPLE_CALLBACK(_initiate_conference_cb), NULL, NULL); diff --git a/libpurple/protocols/null/nullprpl.c b/libpurple/protocols/null/nullprpl.c index 8516f728ab..139ea20ffe 100644 --- a/libpurple/protocols/null/nullprpl.c +++ b/libpurple/protocols/null/nullprpl.c @@ -54,13 +54,12 @@ #include "account.h" #include "accountopt.h" -#include "blist.h" +#include "buddylist.h" #include "cmds.h" #include "conversation.h" #include "connection.h" #include "debug.h" #include "notify.h" -#include "privacy.h" #include "prpl.h" #include "roomlist.h" #include "status.h" @@ -104,7 +103,7 @@ typedef struct { static PurpleConnection *get_nullprpl_gc(const char *username) { PurpleAccount *acct = purple_accounts_find(username, NULLPRPL_ID); if (acct && purple_account_is_connected(acct)) - return acct->gc; + return purple_account_get_connection(acct); else return NULL; } @@ -125,12 +124,12 @@ static void foreach_nullprpl_gc(GcFunc fn, PurpleConnection *from, } -typedef void(*ChatFunc)(PurpleConvChat *from, PurpleConvChat *to, +typedef void(*ChatFunc)(PurpleChatConversation *from, PurpleChatConversation *to, int id, const char *room, gpointer userdata); typedef struct { ChatFunc fn; - PurpleConvChat *from_chat; + PurpleChatConversation *from_chat; gpointer userdata; } ChatFuncData; @@ -138,19 +137,18 @@ static void call_chat_func(gpointer data, gpointer userdata) { PurpleConnection *to = (PurpleConnection *)data; ChatFuncData *cfdata = (ChatFuncData *)userdata; - int id = purple_conv_chat_get_id(cfdata->from_chat); - PurpleConversation *conv = purple_find_chat(to, id); - if (conv) { - PurpleConvChat *chat = purple_conversation_get_chat_data(conv); - cfdata->fn(cfdata->from_chat, chat, id, purple_conversation_get_name(conv), cfdata->userdata); - } + int id = purple_chat_conversation_get_id(cfdata->from_chat); + PurpleChatConversation *chat = purple_conversations_find_chat(to, id); + if (chat) + cfdata->fn(cfdata->from_chat, chat, id, + purple_conversation_get_name(PURPLE_CONVERSATION(chat)), cfdata->userdata); } static void foreach_gc_in_chat(ChatFunc fn, PurpleConnection *from, int id, gpointer userdata) { - PurpleConversation *conv = purple_find_chat(from, id); + PurpleChatConversation *chat = purple_conversations_find_chat(from, id); ChatFuncData cfdata = { fn, - purple_conversation_get_chat_data(conv), + chat, userdata }; g_list_foreach(purple_connections_get_all(), call_chat_func, @@ -163,7 +161,7 @@ static void discover_status(PurpleConnection *from, PurpleConnection *to, const char *from_username = purple_account_get_username(purple_connection_get_account(from)); const char *to_username = purple_account_get_username(purple_connection_get_account(to)); - if (purple_find_buddy(purple_connection_get_account(from), to_username)) { + if (purple_blist_find_buddy(purple_connection_get_account(from), to_username)) { PurpleStatus *status = purple_account_get_active_status(purple_connection_get_account(to)); const char *status_id = purple_status_get_id(status); const char *message = purple_status_get_attr_string(status, "message"); @@ -225,9 +223,10 @@ static const char *nullprpl_list_icon(PurpleAccount *acct, PurpleBuddy *buddy) static char *nullprpl_status_text(PurpleBuddy *buddy) { purple_debug_info("nullprpl", "getting %s's status text for %s\n", - buddy->name, purple_account_get_username(buddy->account)); + purple_buddy_get_name(buddy), + purple_account_get_username(purple_buddy_get_account(buddy))); - if (purple_find_buddy(buddy->account, buddy->name)) { + if (purple_blist_find_buddy(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy))) { PurplePresence *presence = purple_buddy_get_presence(buddy); PurpleStatus *status = purple_presence_get_active_status(presence); const char *name = purple_status_get_name(status); @@ -239,11 +238,12 @@ static char *nullprpl_status_text(PurpleBuddy *buddy) { else text = g_strdup(name); - purple_debug_info("nullprpl", "%s's status text is %s\n", buddy->name, text); + purple_debug_info("nullprpl", "%s's status text is %s\n", + purple_buddy_get_name(buddy), text); return text; } else { - purple_debug_info("nullprpl", "...but %s is not logged in\n", buddy->name); + purple_debug_info("nullprpl", "...but %s is not logged in\n", purple_buddy_get_name(buddy)); return g_strdup("Not logged in"); } } @@ -251,7 +251,7 @@ static char *nullprpl_status_text(PurpleBuddy *buddy) { static void nullprpl_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *info, gboolean full) { - PurpleConnection *gc = get_nullprpl_gc(buddy->name); + PurpleConnection *gc = get_nullprpl_gc(purple_buddy_get_name(buddy)); if (gc) { /* they're logged in */ @@ -278,7 +278,7 @@ static void nullprpl_tooltip_text(PurpleBuddy *buddy, } purple_debug_info("nullprpl", "showing %s tooltip for %s\n", - (full) ? "full" : "short", buddy->name); + (full) ? "full" : "short", purple_buddy_get_name(buddy)); } static GList *nullprpl_status_types(PurpleAccount *acct) @@ -292,19 +292,19 @@ static GList *nullprpl_status_types(PurpleAccount *acct) type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, NULL_STATUS_ONLINE, NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_prepend(types, type); type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, NULL_STATUS_AWAY, NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_prepend(types, type); type = purple_status_type_new_with_attrs(PURPLE_STATUS_OFFLINE, NULL_STATUS_OFFLINE, NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_prepend(types, type); @@ -313,7 +313,7 @@ static GList *nullprpl_status_types(PurpleAccount *acct) static void blist_example_menu_item(PurpleBlistNode *node, gpointer userdata) { purple_debug_info("nullprpl", "example menu item clicked on user %s\n", - ((PurpleBuddy *)node)->name); + purple_buddy_get_name(PURPLE_BUDDY(node))); purple_notify_info(NULL, /* plugin handle or PurpleConnection */ _("Primary title"), @@ -324,7 +324,7 @@ static void blist_example_menu_item(PurpleBlistNode *node, gpointer userdata) { static GList *nullprpl_blist_node_menu(PurpleBlistNode *node) { purple_debug_info("nullprpl", "providing buddy list context menu item\n"); - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (PURPLE_IS_BUDDY(node)) { PurpleMenuAction *action = purple_menu_action_new( _("Nullprpl example menu item"), PURPLE_CALLBACK(blist_example_menu_item), @@ -375,7 +375,7 @@ static void nullprpl_login(PurpleAccount *acct) purple_connection_update_progress(gc, _("Connected"), 1, /* which connection step this is */ 2); /* total number of steps */ - purple_connection_set_state(gc, PURPLE_CONNECTED); + purple_connection_set_state(gc, PURPLE_CONNECTION_CONNECTED); /* tell purple about everyone on our buddy list who's connected */ foreach_nullprpl_gc(discover_status, gc, NULL); @@ -423,13 +423,14 @@ static int nullprpl_send_im(PurpleConnection *gc, const char *who, from_username, who, message); /* is the sender blocked by the recipient's privacy settings? */ - if (to_acct && !purple_privacy_check(to_acct, purple_account_get_username(purple_connection_get_account(gc)))) { + if (to_acct && + !purple_account_privacy_check(to_acct, purple_account_get_username(purple_connection_get_account(gc)))) { char *msg = g_strdup_printf( _("Your message was blocked by %s's privacy settings."), who); purple_debug_info("nullprpl", "discarding; %s is blocked by %s's privacy settings\n", from_username, who); - purple_conv_present_error(who, purple_connection_get_account(gc), msg); + purple_conversation_present_error(who, purple_connection_get_account(gc), msg); g_free(msg); return 0; } @@ -464,11 +465,11 @@ static void nullprpl_set_info(PurpleConnection *gc, const char *info) { purple_account_get_username(purple_connection_get_account(gc)), info); } -static const char *typing_state_to_string(PurpleTypingState typing) { +static const char *typing_state_to_string(PurpleIMTypingState typing) { switch (typing) { - case PURPLE_NOT_TYPING: return "is not typing"; - case PURPLE_TYPING: return "is typing"; - case PURPLE_TYPED: return "stopped typing momentarily"; + case PURPLE_IM_NOT_TYPING: return "is not typing"; + case PURPLE_IM_TYPING: return "is typing"; + case PURPLE_IM_TYPED: return "stopped typing momentarily"; default: return "unknown typing state"; } } @@ -476,19 +477,19 @@ static const char *typing_state_to_string(PurpleTypingState typing) { static void notify_typing(PurpleConnection *from, PurpleConnection *to, gpointer typing) { const char *from_username = purple_account_get_username(purple_connection_get_account(from)); - const char *action = typing_state_to_string((PurpleTypingState)typing); + const char *action = typing_state_to_string((PurpleIMTypingState)typing); purple_debug_info("nullprpl", "notifying %s that %s %s\n", purple_account_get_username(purple_connection_get_account(to)), from_username, action); serv_got_typing(to, from_username, 0, /* if non-zero, a timeout in seconds after which to - * reset the typing status to PURPLE_NOT_TYPING */ - (PurpleTypingState)typing); + * reset the typing status to PURPLE_IM_NOT_TYPING */ + (PurpleIMTypingState)typing); } static unsigned int nullprpl_send_typing(PurpleConnection *gc, const char *name, - PurpleTypingState typing) { + PurpleIMTypingState typing) { purple_debug_info("nullprpl", "%s %s\n", purple_account_get_username(purple_connection_get_account(gc)), typing_state_to_string(typing)); foreach_nullprpl_gc(notify_typing, gc, (gpointer)typing); @@ -551,9 +552,9 @@ static void nullprpl_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message) { const char *username = purple_account_get_username(purple_connection_get_account(gc)); - PurpleConnection *buddy_gc = get_nullprpl_gc(buddy->name); + PurpleConnection *buddy_gc = get_nullprpl_gc(purple_buddy_get_name(buddy)); - purple_debug_info("nullprpl", "adding %s to %s's buddy list\n", buddy->name, + purple_debug_info("nullprpl", "adding %s to %s's buddy list\n", purple_buddy_get_name(buddy), username); if (buddy_gc) { @@ -561,12 +562,12 @@ static void nullprpl_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, discover_status(gc, buddy_gc, NULL); - if (purple_find_buddy(buddy_acct, username)) { + if (purple_blist_find_buddy(buddy_acct, username)) { purple_debug_info("nullprpl", "%s is already on %s's buddy list\n", - username, buddy->name); + username, purple_buddy_get_name(buddy)); } else { purple_debug_info("nullprpl", "asking %s if they want to add %s\n", - buddy->name, username); + purple_buddy_get_name(buddy), username); purple_account_request_add(buddy_acct, username, NULL, /* local account id (rarely used) */ @@ -594,7 +595,8 @@ static void nullprpl_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { purple_debug_info("nullprpl", "removing %s from %s's buddy list\n", - buddy->name, purple_account_get_username(purple_connection_get_account(gc))); + purple_buddy_get_name(buddy), + purple_account_get_username(purple_connection_get_account(gc))); } static void nullprpl_remove_buddies(PurpleConnection *gc, GList *buddies, @@ -644,25 +646,25 @@ static void nullprpl_set_permit_deny(PurpleConnection *gc) { */ } -static void joined_chat(PurpleConvChat *from, PurpleConvChat *to, +static void joined_chat(PurpleChatConversation *from, PurpleChatConversation *to, int id, const char *room, gpointer userdata) { /* tell their chat window that we joined */ purple_debug_info("nullprpl", "%s sees that %s joined chat room %s\n", - purple_conv_chat_get_nick(to), purple_conv_chat_get_nick(from), room); - purple_conv_chat_add_user(to, - purple_conv_chat_get_nick(from), + purple_chat_conversation_get_nick(to), purple_chat_conversation_get_nick(from), room); + purple_chat_conversation_add_user(to, + purple_chat_conversation_get_nick(from), NULL, /* user-provided join message, IRC style */ - PURPLE_CBFLAGS_NONE, + PURPLE_CHAT_USER_NONE, TRUE); /* show a join message */ if (from != to) { /* add them to our chat window */ purple_debug_info("nullprpl", "%s sees that %s is in chat room %s\n", - purple_conv_chat_get_nick(from), purple_conv_chat_get_nick(to), room); - purple_conv_chat_add_user(from, - purple_conv_chat_get_nick(to), + purple_chat_conversation_get_nick(from), purple_chat_conversation_get_nick(to), room); + purple_chat_conversation_add_user(from, + purple_chat_conversation_get_nick(to), NULL, /* user-provided join message, IRC style */ - PURPLE_CBFLAGS_NONE, + PURPLE_CHAT_USER_NONE, FALSE); /* show a join message */ } } @@ -673,7 +675,7 @@ static void nullprpl_join_chat(PurpleConnection *gc, GHashTable *components) { int chat_id = g_str_hash(room); purple_debug_info("nullprpl", "%s is joining chat room %s\n", username, room); - if (!purple_find_chat(gc, chat_id)) { + if (!purple_conversations_find_chat(gc, chat_id)) { serv_got_joined_chat(gc, chat_id, room); /* tell everyone that we joined, and add them if they're already there */ @@ -720,15 +722,15 @@ static char *nullprpl_get_chat_name(GHashTable *components) { static void nullprpl_chat_invite(PurpleConnection *gc, int id, const char *message, const char *who) { const char *username = purple_account_get_username(purple_connection_get_account(gc)); - PurpleConversation *conv = purple_find_chat(gc, id); - const char *room = purple_conversation_get_name(conv); + PurpleChatConversation *chat = purple_conversations_find_chat(gc, id); + const char *room = purple_conversation_get_name(PURPLE_CONVERSATION(chat)); PurpleAccount *to_acct = purple_accounts_find(who, NULLPRPL_ID); purple_debug_info("nullprpl", "%s is inviting %s to join chat room %s\n", username, who, room); if (to_acct) { - PurpleConversation *to_conv = purple_find_chat(to_acct->gc, id); + PurpleChatConversation *to_conv = purple_conversations_find_chat(purple_account_get_connection(to_acct), id); if (to_conv) { char *tmp = g_strdup_printf("%s is already in chat room %s.", who, room); purple_debug_info("nullprpl", @@ -742,27 +744,28 @@ static void nullprpl_chat_invite(PurpleConnection *gc, int id, components = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); g_hash_table_replace(components, "room", g_strdup(room)); g_hash_table_replace(components, "invited_by", g_strdup(username)); - serv_got_chat_invite(to_acct->gc, room, username, message, components); + serv_got_chat_invite(purple_account_get_connection(to_acct), room, username, message, components); } } } -static void left_chat_room(PurpleConvChat *from, PurpleConvChat *to, +static void left_chat_room(PurpleChatConversation *from, PurpleChatConversation *to, int id, const char *room, gpointer userdata) { if (from != to) { /* tell their chat window that we left */ purple_debug_info("nullprpl", "%s sees that %s left chat room %s\n", - purple_conv_chat_get_nick(to), purple_conv_chat_get_nick(from), room); - purple_conv_chat_remove_user(to, - purple_conv_chat_get_nick(from), + purple_chat_conversation_get_nick(to), purple_chat_conversation_get_nick(from), room); + purple_chat_conversation_remove_user(to, + purple_chat_conversation_get_nick(from), NULL); /* user-provided message, IRC style */ } } static void nullprpl_chat_leave(PurpleConnection *gc, int id) { - PurpleConversation *conv = purple_find_chat(gc, id); + PurpleChatConversation *chat = purple_conversations_find_chat(gc, id); purple_debug_info("nullprpl", "%s is leaving chat room %s\n", - purple_account_get_username(purple_connection_get_account(gc)), purple_conversation_get_name(conv)); + purple_account_get_username(purple_connection_get_account(gc)), + purple_conversation_get_name(PURPLE_CONVERSATION(chat))); /* tell everyone that we left */ foreach_gc_in_chat(left_chat_room, gc, id, NULL); @@ -773,8 +776,7 @@ static PurpleCmdRet send_whisper(PurpleConversation *conv, const gchar *cmd, const char *to_username; const char *message; const char *from_username; - PurpleConvChat *chat; - PurpleConvChatBuddy *chat_buddy; + PurpleChatUser *chat_user; PurpleConnection *to; /* parse args */ @@ -791,13 +793,13 @@ static PurpleCmdRet send_whisper(PurpleConversation *conv, const gchar *cmd, from_username = purple_account_get_username(purple_conversation_get_account(conv)); purple_debug_info("nullprpl", "%s whispers to %s in chat room %s: %s\n", - from_username, to_username, purple_conversation_get_name(conv), message); + from_username, to_username, + purple_conversation_get_name(conv), message); - chat = purple_conversation_get_chat_data(conv); - chat_buddy = purple_conv_chat_cb_find(chat, to_username); + chat_user = purple_chat_conversation_find_user(PURPLE_CHAT_CONVERSATION(conv), to_username); to = get_nullprpl_gc(to_username); - if (!chat_buddy) { + if (!chat_user) { /* this will be freed by the caller */ *error = g_strdup_printf(_("%s is not logged in."), to_username); return PURPLE_CMD_RET_FAILED; @@ -807,13 +809,14 @@ static PurpleCmdRet send_whisper(PurpleConversation *conv, const gchar *cmd, } else { /* write the whisper in the sender's chat window */ char *message_to = g_strdup_printf("%s (to %s)", message, to_username); - purple_conv_chat_write(chat, from_username, message_to, - PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_WHISPER, - time(NULL)); + purple_conversation_write_message(conv, from_username, message_to, + PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_WHISPER, + time(NULL)); g_free(message_to); /* send the whisper */ - serv_chat_whisper(to, purple_conv_chat_get_id(chat), from_username, message); + serv_chat_whisper(to, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)), + from_username, message); return PURPLE_CMD_RET_OK; } @@ -822,37 +825,38 @@ static PurpleCmdRet send_whisper(PurpleConversation *conv, const gchar *cmd, static void nullprpl_chat_whisper(PurpleConnection *gc, int id, const char *who, const char *message) { const char *username = purple_account_get_username(purple_connection_get_account(gc)); - PurpleConversation *conv = purple_find_chat(gc, id); + PurpleChatConversation *chat = purple_conversations_find_chat(gc, id); purple_debug_info("nullprpl", "%s receives whisper from %s in chat room %s: %s\n", - username, who, purple_conversation_get_name(conv), message); + username, who, purple_conversation_get_name(PURPLE_CONVERSATION(chat)), + message); /* receive whisper on recipient's account */ serv_got_chat_in(gc, id, who, PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_WHISPER, message, time(NULL)); } -static void receive_chat_message(PurpleConvChat *from, PurpleConvChat *to, +static void receive_chat_message(PurpleChatConversation *from, PurpleChatConversation *to, int id, const char *room, gpointer userdata) { const char *message = (const char *)userdata; - PurpleConnection *to_gc = get_nullprpl_gc(purple_conv_chat_get_nick(to)); + PurpleConnection *to_gc = get_nullprpl_gc(purple_chat_conversation_get_nick(to)); purple_debug_info("nullprpl", "%s receives message from %s in chat room %s: %s\n", - purple_conv_chat_get_nick(to), purple_conv_chat_get_nick(from), room, message); - serv_got_chat_in(to_gc, id, purple_conv_chat_get_nick(from), PURPLE_MESSAGE_RECV, message, + purple_chat_conversation_get_nick(to), purple_chat_conversation_get_nick(from), room, message); + serv_got_chat_in(to_gc, id, purple_chat_conversation_get_nick(from), PURPLE_MESSAGE_RECV, message, time(NULL)); } static int nullprpl_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags) { const char *username = purple_account_get_username(purple_connection_get_account(gc)); - PurpleConversation *conv = purple_find_chat(gc, id); + PurpleChatConversation *chat = purple_conversations_find_chat(gc, id); - if (conv) { + if (chat) { purple_debug_info("nullprpl", "%s is sending message to chat room %s: %s\n", username, - purple_conversation_get_name(conv), message); + purple_conversation_get_name(PURPLE_CONVERSATION(chat)), message); /* send message to everyone in the chat room */ foreach_gc_in_chat(receive_chat_message, gc, id, (gpointer)message); @@ -872,10 +876,11 @@ static void nullprpl_register_user(PurpleAccount *acct) { } static void nullprpl_get_cb_info(PurpleConnection *gc, int id, const char *who) { - PurpleConversation *conv = purple_find_chat(gc, id); + PurpleChatConversation *chat = purple_conversations_find_chat(gc, id); purple_debug_info("nullprpl", "retrieving %s's info for %s in chat room %s\n", who, - purple_account_get_username(purple_connection_get_account(gc)), purple_conversation_get_name(conv)); + purple_account_get_username(purple_connection_get_account(gc)), + purple_conversation_get_name(PURPLE_CONVERSATION(chat))); nullprpl_get_info(gc, who); } @@ -896,7 +901,8 @@ static void nullprpl_group_buddy(PurpleConnection *gc, const char *who, static void nullprpl_rename_group(PurpleConnection *gc, const char *old_name, PurpleGroup *group, GList *moved_buddies) { purple_debug_info("nullprpl", "%s has renamed group %s to %s\n", - purple_account_get_username(purple_connection_get_account(gc)), old_name, group->name); + purple_account_get_username(purple_connection_get_account(gc)), old_name, + purple_group_get_name(group)); } static void nullprpl_convo_closed(PurpleConnection *gc, const char *who) { @@ -921,42 +927,43 @@ static void nullprpl_set_buddy_icon(PurpleConnection *gc, static void nullprpl_remove_group(PurpleConnection *gc, PurpleGroup *group) { purple_debug_info("nullprpl", "%s has removed group %s\n", - purple_account_get_username(purple_connection_get_account(gc)), group->name); + purple_account_get_username(purple_connection_get_account(gc)), + purple_group_get_name(group)); } -static void set_chat_topic_fn(PurpleConvChat *from, PurpleConvChat *to, +static void set_chat_topic_fn(PurpleChatConversation *from, PurpleChatConversation *to, int id, const char *room, gpointer userdata) { const char *topic = (const char *)userdata; - const char *username = purple_account_get_username(purple_conversation_get_account(purple_conv_chat_get_conversation(from))); + const char *username = purple_account_get_username(purple_conversation_get_account(PURPLE_CONVERSATION(from))); char *msg; - purple_conv_chat_set_topic(to, username, topic); + purple_chat_conversation_set_topic(to, username, topic); if (topic && *topic) msg = g_strdup_printf(_("%s sets topic to: %s"), username, topic); else msg = g_strdup_printf(_("%s clears topic"), username); - purple_conv_chat_write(to, username, msg, - PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG, - time(NULL)); + purple_conversation_write_message(PURPLE_CONVERSATION(to), username, msg, + PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG, + time(NULL)); g_free(msg); } static void nullprpl_set_chat_topic(PurpleConnection *gc, int id, const char *topic) { - PurpleConversation *conv = purple_find_chat(gc, id); - PurpleConvChat *chat = purple_conversation_get_chat_data(conv); + PurpleChatConversation *chat = purple_conversations_find_chat(gc, id); const char *last_topic; if (!chat) return; purple_debug_info("nullprpl", "%s sets topic of chat room '%s' to '%s'\n", - purple_account_get_username(purple_connection_get_account(gc)), purple_conversation_get_name(conv), topic); + purple_account_get_username(purple_connection_get_account(gc)), + purple_conversation_get_name(PURPLE_CONVERSATION(chat)), topic); - last_topic = purple_conv_chat_get_topic(chat); + last_topic = purple_chat_conversation_get_topic(chat); if ((!topic && !last_topic) || (topic && last_topic && !strcmp(topic, last_topic))) return; /* topic is unchanged, this is a noop */ @@ -991,11 +998,11 @@ static PurpleRoomlist *nullprpl_roomlist_get_list(PurpleConnection *gc) { /* add each chat room. the chat ids are cached in seen_ids so that each room * is only returned once, even if multiple users are in it. */ - for (chats = purple_get_chats(); chats; chats = g_list_next(chats)) { - PurpleConversation *conv = (PurpleConversation *)chats->data; + for (chats = purple_conversations_get_chats(); chats; chats = g_list_next(chats)) { + PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(chats->data); PurpleRoomlistRoom *room; - const char *name = purple_conversation_get_name(conv); - int id = purple_conv_chat_get_id(purple_conversation_get_chat_data(conv)); + const char *name = purple_conversation_get_name(PURPLE_CONVERSATION(chat)); + int id = purple_chat_conversation_get_id(chat); /* have we already added this room? */ if (g_list_find_custom(seen_ids, name, (GCompareFunc)strcmp)) @@ -1041,7 +1048,7 @@ static gboolean nullprpl_can_receive_file(PurpleConnection *gc, static gboolean nullprpl_offline_message(const PurpleBuddy *buddy) { purple_debug_info("nullprpl", "reporting that offline messages are supported for %s\n", - buddy->name); + purple_buddy_get_name(buddy)); return TRUE; } diff --git a/libpurple/protocols/oscar/authorization.c b/libpurple/protocols/oscar/authorization.c index e2c2e65623..22a43b65b4 100644 --- a/libpurple/protocols/oscar/authorization.c +++ b/libpurple/protocols/oscar/authorization.c @@ -37,7 +37,7 @@ oscar_auth_sendrequest(PurpleConnection *gc, const char *bname, const char *msg) od = purple_connection_get_protocol_data(gc); account = purple_connection_get_account(gc); - buddy = purple_find_buddy(account, bname); + buddy = purple_blist_find_buddy(account, bname); if (buddy != NULL) group = purple_buddy_get_group(buddy); else @@ -96,7 +96,7 @@ oscar_auth_sendrequest_menu(PurpleBlistNode *node, gpointer ignored) PurpleBuddy *buddy; PurpleConnection *gc; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); @@ -115,6 +115,6 @@ oscar_auth_recvrequest(PurpleConnection *gc, gchar *name, gchar *nick, gchar *re data->nick = nick; purple_account_request_authorization(account, data->name, NULL, data->nick, - reason, purple_find_buddy(account, data->name) != NULL, + reason, purple_blist_find_buddy(account, data->name) != NULL, oscar_auth_grant, oscar_auth_dontgrant, data); } diff --git a/libpurple/protocols/oscar/clientlogin.c b/libpurple/protocols/oscar/clientlogin.c index dbc0c28008..ffdd296c54 100644 --- a/libpurple/protocols/oscar/clientlogin.c +++ b/libpurple/protocols/oscar/clientlogin.c @@ -38,10 +38,11 @@ #include "oscar.h" #include "oscarcommon.h" - -#include "cipher.h" #include "core.h" +#include "ciphers/hmaccipher.h" +#include "ciphers/sha256hash.h" + #define AIM_LOGIN_HOST "api.screenname.aol.com" #define ICQ_LOGIN_HOST "api.login.icq.net" @@ -128,15 +129,17 @@ static gchar *generate_error_message(xmlnode *resp, const char *url) */ static gchar *hmac_sha256(const char *key, const char *message) { - PurpleCipherContext *context; + PurpleCipher *cipher; + PurpleHash *hash; guchar digest[32]; - context = purple_cipher_context_new_by_name("hmac", NULL); - purple_cipher_context_set_option(context, "hash", "sha256"); - purple_cipher_context_set_key(context, (guchar *)key, strlen(key)); - purple_cipher_context_append(context, (guchar *)message, strlen(message)); - purple_cipher_context_digest(context, digest, sizeof(digest)); - purple_cipher_context_destroy(context); + hash = purple_sha256_hash_new(); + cipher = purple_hmac_cipher_new(hash); + purple_cipher_set_key(cipher, (guchar *)key, strlen(key)); + purple_cipher_append(cipher, (guchar *)message, strlen(message)); + purple_cipher_digest(cipher, digest, sizeof(digest)); + g_object_unref(cipher); + g_object_unref(hash); return purple_base64_encode(digest, sizeof(digest)); } diff --git a/libpurple/protocols/oscar/family_auth.c b/libpurple/protocols/oscar/family_auth.c index b5d3762697..14657a4eda 100644 --- a/libpurple/protocols/oscar/family_auth.c +++ b/libpurple/protocols/oscar/family_auth.c @@ -31,7 +31,7 @@ #include <ctype.h> -#include "cipher.h" +#include "ciphers/md5hash.h" /* #define USE_XOR_FOR_ICQ */ @@ -75,14 +75,14 @@ aim_encode_password(const char *password, guint8 *encoded) static int aim_encode_password_md5(const char *password, size_t password_len, const char *key, guint8 *digest) { - PurpleCipherContext *context; + PurpleHash *hash; - context = purple_cipher_context_new_by_name("md5", NULL); - purple_cipher_context_append(context, (const guchar *)key, strlen(key)); - purple_cipher_context_append(context, (const guchar *)password, password_len); - purple_cipher_context_append(context, (const guchar *)AIM_MD5_STRING, strlen(AIM_MD5_STRING)); - purple_cipher_context_digest(context, 16, digest, NULL); - purple_cipher_context_destroy(context); + hash = purple_md5_hash_new(); + purple_hash_append(hash, (const guchar *)key, strlen(key)); + purple_hash_append(hash, (const guchar *)password, password_len); + purple_hash_append(hash, (const guchar *)AIM_MD5_STRING, strlen(AIM_MD5_STRING)); + purple_hash_digest(hash, 16, digest, NULL); + g_object_unref(hash); return 0; } @@ -90,23 +90,19 @@ aim_encode_password_md5(const char *password, size_t password_len, const char *k static int aim_encode_password_md5(const char *password, size_t password_len, const char *key, guint8 *digest) { - PurpleCipher *cipher; - PurpleCipherContext *context; + PurpleHash *hash; guchar passdigest[16]; - cipher = purple_ciphers_find_cipher("md5"); + hash = purple_md5_hash_new(); + purple_hash_append(hash, (const guchar *)password, password_len); + purple_hash_digest(hash, passdigest, sizeof(passdigest)); + purple_hash_reset(hash); - context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, (const guchar *)password, password_len); - purple_cipher_context_digest(context, passdigest, sizeof(passdigest)); - purple_cipher_context_destroy(context); - - context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, (const guchar *)key, strlen(key)); - purple_cipher_context_append(context, passdigest, 16); - purple_cipher_context_append(context, (const guchar *)AIM_MD5_STRING, strlen(AIM_MD5_STRING)); - purple_cipher_context_digest(context, digest, 16); - purple_cipher_context_destroy(context); + purple_hash_append(hash, (const guchar *)key, strlen(key)); + purple_hash_append(hash, passdigest, 16); + purple_hash_append(hash, (const guchar *)AIM_MD5_STRING, strlen(AIM_MD5_STRING)); + purple_hash_digest(hash, digest, 16); + g_object_unref(hash); return 0; } diff --git a/libpurple/protocols/oscar/family_buddy.c b/libpurple/protocols/oscar/family_buddy.c index a58232a058..3d38323032 100644 --- a/libpurple/protocols/oscar/family_buddy.c +++ b/libpurple/protocols/oscar/family_buddy.c @@ -113,7 +113,7 @@ buddychange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *f if (snac->subtype == SNAC_SUBTYPE_BUDDY_ONCOMING && userinfo.capabilities & OSCAR_CAPABILITY_XTRAZ) { PurpleAccount *account = purple_connection_get_account(od->gc); - PurpleBuddy *buddy = purple_find_buddy(account, userinfo.bn); + PurpleBuddy *buddy = purple_blist_find_buddy(account, userinfo.bn); if (buddy) { PurplePresence *presence = purple_buddy_get_presence(buddy); diff --git a/libpurple/protocols/oscar/family_icbm.c b/libpurple/protocols/oscar/family_icbm.c index d87d8af017..2c90f9c37f 100644 --- a/libpurple/protocols/oscar/family_icbm.c +++ b/libpurple/protocols/oscar/family_icbm.c @@ -174,7 +174,7 @@ error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, else buf = g_strdup_printf(_("Unable to send message: %s"), reason_str); - if (!purple_conv_present_error(bn, purple_connection_get_account(gc), buf)) { + if (!purple_conversation_present_error(bn, purple_connection_get_account(gc), buf)) { g_free(buf); if (errcode != 0 && errcode < errcodereasonlen) buf = g_strdup_printf(_("Unable to send message to %s: %s (%s)"), @@ -1723,7 +1723,7 @@ static int clientautoresp(OscarData *od, FlapConnection *conn, aim_module_t *mod if (*unescaped_xstatus) { purple_debug_misc("oscar", "X-Status reply: %s\n", unescaped_xstatus); account = purple_connection_get_account(od->gc); - buddy = purple_find_buddy(account, bn); + buddy = purple_blist_find_buddy(account, bn); presence = purple_buddy_get_presence(buddy); status = purple_presence_get_status(presence, "mood"); if (status) { diff --git a/libpurple/protocols/oscar/family_icq.c b/libpurple/protocols/oscar/family_icq.c index dac6b10b54..a78b2d75aa 100644 --- a/libpurple/protocols/oscar/family_icq.c +++ b/libpurple/protocols/oscar/family_icq.c @@ -424,7 +424,7 @@ gotalias(OscarData *od, struct aim_icq_info *info) gchar who[16]; g_snprintf(who, sizeof(who), "%u", info->uin); serv_got_alias(gc, who, utf8); - if ((b = purple_find_buddy(account, who))) { + if ((b = purple_blist_find_buddy(account, who))) { purple_blist_node_set_string((PurpleBlistNode*)b, "servernick", utf8); } } @@ -624,7 +624,7 @@ icqresponse(OscarData *od, aim_modsnac_t *snac, ByteStream *bs) PurpleStatus *status; account = purple_connection_get_account(od->gc); - buddy = purple_find_buddy(account, uin); + buddy = purple_blist_find_buddy(account, uin); presence = purple_buddy_get_presence(buddy); status = purple_presence_get_active_status(presence); diff --git a/libpurple/protocols/oscar/family_oservice.c b/libpurple/protocols/oscar/family_oservice.c index bb57b10061..bd11ee1b8a 100644 --- a/libpurple/protocols/oscar/family_oservice.c +++ b/libpurple/protocols/oscar/family_oservice.c @@ -25,7 +25,7 @@ #include "oscar.h" -#include "cipher.h" +#include "ciphers/md5hash.h" /* * Each time we make a FLAP connection to an oscar server the server gives diff --git a/libpurple/protocols/oscar/flap_connection.c b/libpurple/protocols/oscar/flap_connection.c index a592a4e753..9a7eaf98b8 100644 --- a/libpurple/protocols/oscar/flap_connection.c +++ b/libpurple/protocols/oscar/flap_connection.c @@ -336,7 +336,7 @@ flap_connection_new(OscarData *od, int type) conn = g_new0(FlapConnection, 1); conn->od = od; - conn->buffer_outgoing = purple_circ_buffer_new(0); + conn->buffer_outgoing = purple_circular_buffer_new(0); conn->fd = -1; conn->subtype = -1; conn->type = type; @@ -410,7 +410,7 @@ flap_connection_close(OscarData *od, FlapConnection *conn) g_free(conn->buffer_incoming.data.data); conn->buffer_incoming.data.data = NULL; - purple_circ_buffer_destroy(conn->buffer_outgoing); + g_object_unref(G_OBJECT(conn->buffer_outgoing)); conn->buffer_outgoing = NULL; } @@ -1020,9 +1020,11 @@ send_cb(gpointer data, gint source, PurpleInputCondition cond) { FlapConnection *conn; int writelen, ret; + const gchar *output = NULL; conn = data; - writelen = purple_circ_buffer_get_max_read(conn->buffer_outgoing); + writelen = purple_circular_buffer_get_max_read(conn->buffer_outgoing); + output = purple_circular_buffer_get_output(conn->buffer_outgoing); if (writelen == 0) { @@ -1032,10 +1034,9 @@ send_cb(gpointer data, gint source, PurpleInputCondition cond) } if (conn->gsc) - ret = purple_ssl_write(conn->gsc, conn->buffer_outgoing->outptr, - writelen); + ret = purple_ssl_write(conn->gsc, output, writelen); else - ret = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0); + ret = send(conn->fd, output, writelen, 0); if (ret <= 0) { if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) @@ -1057,7 +1058,7 @@ send_cb(gpointer data, gint source, PurpleInputCondition cond) return; } - purple_circ_buffer_mark_read(conn->buffer_outgoing, ret); + purple_circular_buffer_mark_read(conn->buffer_outgoing, ret); } static void @@ -1074,7 +1075,7 @@ flap_connection_send_byte_stream(ByteStream *bs, FlapConnection *conn, size_t co return; /* Add everything to our outgoing buffer */ - purple_circ_buffer_append(conn->buffer_outgoing, bs->data, count); + purple_circular_buffer_append(conn->buffer_outgoing, bs->data, count); /* If we haven't already started writing stuff, then start the cycle */ if (conn->watcher_outgoing == 0) diff --git a/libpurple/protocols/oscar/odc.c b/libpurple/protocols/oscar/odc.c index c276e38aa2..ced7c18313 100644 --- a/libpurple/protocols/oscar/odc.c +++ b/libpurple/protocols/oscar/odc.c @@ -60,11 +60,12 @@ peer_odc_close(PeerConnection *conn) if (tmp != NULL) { PurpleAccount *account; - PurpleConversation *conv; + PurpleIMConversation *im; account = purple_connection_get_account(conn->od->gc); - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn); - purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); + im = purple_im_conversation_new(account, conn->bn); + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, tmp, + PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(tmp); } @@ -149,16 +150,16 @@ peer_odc_send_cookie(PeerConnection *conn) * Send client-to-client typing notification over an established direct connection. */ void -peer_odc_send_typing(PeerConnection *conn, PurpleTypingState typing) +peer_odc_send_typing(PeerConnection *conn, PurpleIMTypingState typing) { OdcFrame frame; memset(&frame, 0, sizeof(OdcFrame)); frame.type = 0x0001; frame.subtype = 0x0006; - if (typing == PURPLE_TYPING) + if (typing == PURPLE_IM_TYPING) frame.flags = 0x0002 | 0x0008; - else if (typing == PURPLE_TYPED) + else if (typing == PURPLE_IM_TYPED) frame.flags = 0x0002 | 0x0004; else frame.flags = 0x0002; @@ -524,7 +525,7 @@ peer_odc_recv_frame(PeerConnection *conn, ByteStream *bs) */ PurpleAccount *account; - PurpleConversation *conv; + PurpleIMConversation *im; if (conn->flags & PEER_CONNECTION_FLAG_IS_INCOMING) { @@ -565,8 +566,8 @@ peer_odc_recv_frame(PeerConnection *conn, ByteStream *bs) /* Tell the local user that we are connected */ account = purple_connection_get_account(gc); - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn); - purple_conversation_write(conv, NULL, _("Direct IM established"), + im = purple_im_conversation_new(account, conn->bn); + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, _("Direct IM established"), PURPLE_MESSAGE_SYSTEM, time(NULL)); } @@ -584,11 +585,11 @@ peer_odc_recv_frame(PeerConnection *conn, ByteStream *bs) purple_debug_info("oscar", "ohmigod! %s has started typing " "(DirectIM). He's going to send you a message! " "*squeal*\n", conn->bn); - serv_got_typing(gc, conn->bn, 0, PURPLE_TYPING); + serv_got_typing(gc, conn->bn, 0, PURPLE_IM_TYPING); } else if (frame->flags & 0x0004) { - serv_got_typing(gc, conn->bn, 0, PURPLE_TYPED); + serv_got_typing(gc, conn->bn, 0, PURPLE_IM_TYPED); } else { @@ -601,7 +602,7 @@ peer_odc_recv_frame(PeerConnection *conn, ByteStream *bs) { gchar *tmp, *size1, *size2; PurpleAccount *account; - PurpleConversation *conv; + PurpleIMConversation *im; size1 = purple_str_size_to_units(frame->payload.len); size2 = purple_str_size_to_units(DIRECTIM_MAX_FILESIZE); @@ -610,8 +611,8 @@ peer_odc_recv_frame(PeerConnection *conn, ByteStream *bs) g_free(size2); account = purple_connection_get_account(conn->od->gc); - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn); - purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); + im = purple_im_conversation_new(account, conn->bn); + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(tmp); peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL); diff --git a/libpurple/protocols/oscar/oft.c b/libpurple/protocols/oscar/oft.c index 49cbcb06da..c3cf730000 100644 --- a/libpurple/protocols/oscar/oft.c +++ b/libpurple/protocols/oscar/oft.c @@ -360,7 +360,7 @@ start_transfer_when_done_sending_data(gpointer data) conn = data; - if (purple_circ_buffer_get_max_read(conn->buffer_outgoing) == 0) + if (purple_circular_buffer_get_max_read(conn->buffer_outgoing) == 0) { int fd = conn->fd; conn->sending_data_timer = 0; @@ -385,7 +385,7 @@ destroy_connection_when_done_sending_data(gpointer data) conn = data; - if (purple_circ_buffer_get_max_read(conn->buffer_outgoing) == 0) + if (purple_circular_buffer_get_max_read(conn->buffer_outgoing) == 0) { conn->sending_data_timer = 0; peer_connection_destroy(conn, conn->disconnect_reason, NULL); diff --git a/libpurple/protocols/oscar/oscar.c b/libpurple/protocols/oscar/oscar.c index 9a8ecda387..4eb7c9ad1e 100644 --- a/libpurple/protocols/oscar/oscar.c +++ b/libpurple/protocols/oscar/oscar.c @@ -33,7 +33,7 @@ #include "account.h" #include "accountopt.h" #include "buddyicon.h" -#include "cipher.h" +#include "ciphers/md5hash.h" #include "conversation.h" #include "core.h" #include "debug.h" @@ -41,7 +41,6 @@ #include "imgstore.h" #include "network.h" #include "notify.h" -#include "privacy.h" #include "prpl.h" #include "proxy.h" #include "request.h" @@ -97,10 +96,10 @@ static int purple_parse_misses (OscarData *, FlapConnection *, FlapFrame *, static int purple_parse_clientauto (OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_parse_motd (OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_chatnav_info (OscarData *, FlapConnection *, FlapFrame *, ...); -static int purple_conv_chat_join (OscarData *, FlapConnection *, FlapFrame *, ...); -static int purple_conv_chat_leave (OscarData *, FlapConnection *, FlapFrame *, ...); -static int purple_conv_chat_info_update (OscarData *, FlapConnection *, FlapFrame *, ...); -static int purple_conv_chat_incoming_msg(OscarData *, FlapConnection *, FlapFrame *, ...); +static int purple_chat_conversation_join (OscarData *, FlapConnection *, FlapFrame *, ...); +static int purple_chat_conversation_left (OscarData *, FlapConnection *, FlapFrame *, ...); +static int purple_chat_conversation_info_update (OscarData *, FlapConnection *, FlapFrame *, ...); +static int purple_chat_conversation_incoming_msg(OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_email_parseupdate(OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_icon_parseicon (OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_parse_searcherror(OscarData *, FlapConnection *, FlapFrame *, ...); @@ -243,7 +242,7 @@ find_oscar_chat_by_conn(PurpleConnection *gc, FlapConnection *conn) } static struct chat_connection * -find_oscar_chat_by_conv(PurpleConnection *gc, PurpleConversation *conv) +find_oscar_chat_by_conv(PurpleConnection *gc, PurpleChatConversation *conv) { OscarData *od = purple_connection_get_protocol_data(gc); GSList *cur; @@ -273,7 +272,7 @@ oscar_chat_kill(PurpleConnection *gc, struct chat_connection *cc) OscarData *od = purple_connection_get_protocol_data(gc); /* Notify the conversation window that we've left the chat */ - serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(cc->conv))); + serv_got_chat_left(gc, purple_chat_conversation_get_id(cc->conv)); /* Destroy the chat_connection */ od->oscar_chats = g_slist_remove(od->oscar_chats, cc); @@ -668,10 +667,10 @@ oscar_login(PurpleAccount *account) oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_ONCOMING, purple_parse_oncoming, 0); oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_OFFGOING, purple_parse_offgoing, 0); oscar_data_addhandler(od, SNAC_FAMILY_CHAT, 0x0001, purple_parse_genericerr, 0); - oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_USERJOIN, purple_conv_chat_join, 0); - oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_USERLEAVE, purple_conv_chat_leave, 0); - oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_ROOMINFOUPDATE, purple_conv_chat_info_update, 0); - oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_INCOMINGMSG, purple_conv_chat_incoming_msg, 0); + oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_USERJOIN, purple_chat_conversation_join, 0); + oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_USERLEAVE, purple_chat_conversation_left, 0); + oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_ROOMINFOUPDATE, purple_chat_conversation_info_update, 0); + oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_INCOMINGMSG, purple_chat_conversation_incoming_msg, 0); oscar_data_addhandler(od, SNAC_FAMILY_CHATNAV, 0x0001, purple_parse_genericerr, 0); oscar_data_addhandler(od, SNAC_FAMILY_CHATNAV, SNAC_SUBTYPE_CHATNAV_INFO, purple_chatnav_info, 0); oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_ERROR, purple_ssi_parseerr, 0); @@ -719,17 +718,17 @@ oscar_login(PurpleAccount *account) return; } - flags = PURPLE_CONNECTION_HTML; + flags = PURPLE_CONNECTION_FLAG_HTML; if (g_str_equal(purple_account_get_protocol_id(account), "prpl-icq")) { od->icq = TRUE; } else { - flags |= PURPLE_CONNECTION_AUTO_RESP; + flags |= PURPLE_CONNECTION_FLAG_AUTO_RESP; } /* Set this flag based on the protocol_id rather than the username, because that is what's tied to the get_moods prpl callback. */ if (g_str_equal(purple_account_get_protocol_id(account), "prpl-icq")) - flags |= PURPLE_CONNECTION_SUPPORT_MOODS; + flags |= PURPLE_CONNECTION_FLAG_SUPPORT_MOODS; purple_connection_set_flags(gc, flags); @@ -1176,7 +1175,7 @@ static int purple_parse_oncoming(OscarData *od, FlapConnection *conn, FlapFrame g_return_val_if_fail(info != NULL, 1); g_return_val_if_fail(info->bn != NULL, 1); - buddy = purple_find_buddy(account, info->bn); + buddy = purple_blist_find_buddy(account, info->bn); if (buddy) { previous_status = purple_presence_get_active_status(purple_buddy_get_presence(buddy)); } @@ -1305,7 +1304,7 @@ static int purple_parse_oncoming(OscarData *od, FlapConnection *conn, FlapFrame PurpleBuddy *b = NULL; b16 = purple_base16_encode(info->iconcsum, info->iconcsumlen); - b = purple_find_buddy(account, info->bn); + b = purple_blist_find_buddy(account, info->bn); if (b != NULL) saved_b16 = purple_buddy_icons_get_checksum_for_user(b); @@ -2035,7 +2034,7 @@ static int purple_parse_misses(OscarData *od, FlapConnection *conn, FlapFrame *f break; } - if (!purple_conv_present_error(userinfo->bn, account, buf)) + if (!purple_conversation_present_error(userinfo->bn, account, buf)) purple_notify_error(od->gc, NULL, buf, NULL); g_free(buf); @@ -2199,11 +2198,11 @@ static int purple_parse_mtn(OscarData *od, FlapConnection *conn, FlapFrame *fr, } break; case 0x0001: { /* Paused typing */ - serv_got_typing(gc, bn, 0, PURPLE_TYPED); + serv_got_typing(gc, bn, 0, PURPLE_IM_TYPED); } break; case 0x0002: { /* Typing */ - serv_got_typing(gc, bn, 0, PURPLE_TYPING); + serv_got_typing(gc, bn, 0, PURPLE_IM_TYPING); } break; case 0x000f: { /* Closed IM window */ @@ -2317,7 +2316,7 @@ static int purple_chatnav_info(OscarData *od, FlapConnection *conn, FlapFrame *f return 1; } -static int purple_conv_chat_join(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { +static int purple_chat_conversation_join(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; int count, i; aim_userinfo_t *info; @@ -2335,12 +2334,12 @@ static int purple_conv_chat_join(OscarData *od, FlapConnection *conn, FlapFrame return 1; for (i = 0; i < count; i++) - purple_conv_chat_add_user(PURPLE_CONV_CHAT(c->conv), info[i].bn, NULL, PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(c->conv, info[i].bn, NULL, PURPLE_CHAT_USER_NONE, TRUE); return 1; } -static int purple_conv_chat_leave(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { +static int purple_chat_conversation_left(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; int count, i; aim_userinfo_t *info; @@ -2358,12 +2357,12 @@ static int purple_conv_chat_leave(OscarData *od, FlapConnection *conn, FlapFrame return 1; for (i = 0; i < count; i++) - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c->conv), info[i].bn, NULL); + purple_chat_conversation_remove_user(c->conv, info[i].bn, NULL); return 1; } -static int purple_conv_chat_info_update(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { +static int purple_chat_conversation_info_update(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; guint16 maxmsglen, maxvisiblemsglen; PurpleConnection *gc = od->gc; @@ -2387,7 +2386,7 @@ static int purple_conv_chat_info_update(OscarData *od, FlapConnection *conn, Fla return 1; } -static int purple_conv_chat_incoming_msg(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { +static int purple_chat_conversation_incoming_msg(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { PurpleConnection *gc = od->gc; struct chat_connection *ccon = find_oscar_chat_by_conn(gc, conn); gchar *utf8; @@ -2556,14 +2555,14 @@ static int purple_connerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, .. if (conn->type == SNAC_FAMILY_CHAT) { struct chat_connection *cc; - PurpleConversation *conv = NULL; + PurpleChatConversation *chat = NULL; cc = find_oscar_chat_by_conn(gc, conn); if (cc != NULL) { - conv = purple_find_chat(gc, cc->id); + chat = purple_conversations_find_chat(gc, cc->id); - if (conv != NULL) + if (chat != NULL) { /* * TOOD: Have flap_connection_destroy_cb() send us the @@ -2573,7 +2572,8 @@ static int purple_connerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, .. gchar *buf; buf = g_strdup_printf(_("You have been disconnected from chat " "room %s."), cc->name); - purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_ERROR, time(NULL)); + purple_conversation_write(PURPLE_CONVERSATION(chat), NULL, buf, + PURPLE_MESSAGE_ERROR, time(NULL)); g_free(buf); } oscar_chat_kill(gc, cc); @@ -2753,7 +2753,7 @@ static int purple_bosrights(OscarData *od, FlapConnection *conn, FlapFrame *fr, /* Request offline messages for AIM and ICQ */ aim_im_reqofflinemsgs(od); - purple_connection_set_state(gc, PURPLE_CONNECTED); + purple_connection_set_state(gc, PURPLE_CONNECTION_CONNECTED); } return 1; @@ -2944,7 +2944,7 @@ oscar_keepalive(PurpleConnection *gc) } unsigned int -oscar_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state) +oscar_send_typing(PurpleConnection *gc, const char *name, PurpleIMTypingState state) { OscarData *od; PeerConnection *conn; @@ -2958,14 +2958,16 @@ oscar_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState stat } else { /* Don't send if this turkey is in our deny list */ + PurpleAccount *account = purple_connection_get_account(gc); GSList *list; - for (list=purple_connection_get_account(gc)->deny; (list && oscar_util_name_compare(name, list->data)); list=list->next); + + for (list=purple_account_privacy_get_denied(account); (list && oscar_util_name_compare(name, list->data)); list=list->next); if (!list) { - struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(purple_connection_get_account(gc), name)); + struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, name)); if (bi && bi->typingnot) { - if (state == PURPLE_TYPING) + if (state == PURPLE_IM_TYPING) aim_im_sendmtn(od, 0x0001, name, 0x0002); - else if (state == PURPLE_TYPED) + else if (state == PURPLE_IM_TYPED) aim_im_sendmtn(od, 0x0001, name, 0x0001); else aim_im_sendmtn(od, 0x0001, name, 0x0000); @@ -3106,19 +3108,19 @@ oscar_send_im(PurpleConnection *gc, const char *name, const char *message, Purpl } else { struct buddyinfo *bi; struct aim_sendimext_args args; - PurpleConversation *conv; + PurpleIMConversation *im; PurpleStoredImage *img; PurpleBuddy *buddy; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, account); + im = purple_conversations_find_im_with_account(name, account); if (strstr(tmp1, "<IMG ")) - purple_conversation_write(conv, "", + purple_conversation_write(PURPLE_CONVERSATION(im), "", _("Your IM Image was not sent. " "You must be Direct Connected to send IM Images."), PURPLE_MESSAGE_ERROR, time(NULL)); - buddy = purple_find_buddy(account, name); + buddy = purple_blist_find_buddy(account, name); bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, name)); if (!bi) { @@ -3332,7 +3334,7 @@ oscar_set_info_and_status(PurpleAccount *account, gboolean setinfo, const char * char *status_text = NULL; const char *itmsurl = NULL; - status_type = purple_status_get_type(status); + status_type = purple_status_get_status_type(status); primitive = purple_status_type_get_primitive(status_type); if (!setinfo) @@ -3439,12 +3441,12 @@ oscar_set_icq_permdeny(PurpleAccount *account) /* * For ICQ the permit/deny setting controls who can see you - * online. Mimicking the official client's behavior, we use PURPLE_PRIVACY_ALLOW_USERS - * when our status is "invisible" and PURPLE_PRIVACY_DENY_USERS otherwise. + * online. Mimicking the official client's behavior, we use PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS + * when our status is "invisible" and PURPLE_ACCOUNT_PRIVACY_DENY_USERS otherwise. * In the former case, we are visible only to buddies on our "permanently visible" list. * In the latter, we are invisible only to buddies on our "permanently invisible" list. */ - aim_ssi_setpermdeny(od, invisible ? PURPLE_PRIVACY_ALLOW_USERS : PURPLE_PRIVACY_DENY_USERS); + aim_ssi_setpermdeny(od, invisible ? PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS : PURPLE_ACCOUNT_PRIVACY_DENY_USERS); } void @@ -3467,7 +3469,7 @@ oscar_set_status(PurpleAccount *account, PurpleStatus *status) od = purple_connection_get_protocol_data(pc); /* There's no need to do the stuff below for mood updates. */ - if (purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_MOOD) { + if (purple_status_type_get_primitive(purple_status_get_status_type(status)) == PURPLE_STATUS_MOOD) { aim_locate_setcaps(od, purple_caps); return; } @@ -3496,7 +3498,7 @@ oscar_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, co if (!oscar_util_valid_name(bname)) { gchar *buf; buf = g_strdup_printf(_("Unable to add the buddy %s because the username is invalid. Usernames must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), bname); - if (!purple_conv_present_error(bname, account, buf)) + if (!purple_conversation_present_error(bname, account, buf)) purple_notify_error(gc, NULL, _("Unable to Add"), buf); g_free(buf); @@ -3708,7 +3710,7 @@ static int purple_ssi_parselist(OscarData *od, FlapConnection *conn, FlapFrame * /* Buddies */ cur = NULL; - for (buddies = purple_find_buddies(account, NULL); + for (buddies = purple_blist_find_buddies(account, NULL); buddies; buddies = g_slist_delete_link(buddies, buddies)) { @@ -3731,7 +3733,7 @@ static int purple_ssi_parselist(OscarData *od, FlapConnection *conn, FlapFrame * /* Store local alias on server */ alias = aim_ssi_getalias(&od->ssi.local, gname, bname); - balias = purple_buddy_get_local_buddy_alias(b); + balias = purple_buddy_get_local_alias(b); if (!alias && balias && *balias) aim_ssi_aliasbuddy(od, gname, bname, balias); g_free(alias); @@ -3749,27 +3751,27 @@ static int purple_ssi_parselist(OscarData *od, FlapConnection *conn, FlapFrame * /* Permit list (ICQ doesn't have one) */ if (!od->icq) { - next = account->permit; + next = purple_account_privacy_get_permitted(account); while (next != NULL) { cur = next; next = next->next; if (!aim_ssi_itemlist_finditem(&od->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) { purple_debug_info("oscar", "ssi: removing permit %s from local list\n", (const char *)cur->data); - purple_privacy_permit_remove(account, cur->data, TRUE); + purple_account_privacy_permit_remove(account, cur->data, TRUE); } } } /* Deny list */ - next = account->deny; + next = purple_account_privacy_get_denied(account); while (next != NULL) { cur = next; next = next->next; if (!aim_ssi_itemlist_finditem(&od->ssi.local, NULL, cur->data, deny_entry_type)) { purple_debug_info("oscar", "ssi: removing deny %s from local list\n", (const char *)cur->data); - purple_privacy_deny_remove(account, cur->data, TRUE); + purple_account_privacy_deny_remove(account, cur->data, TRUE); } } @@ -3810,7 +3812,7 @@ static int purple_ssi_parselist(OscarData *od, FlapConnection *conn, FlapFrame * gname = groupitem ? groupitem->name : NULL; gname_utf8 = oscar_utf8_try_convert(account, od, gname); - g = purple_find_group(gname_utf8 ? gname_utf8 : _("Buddies")); + g = purple_blist_find_group(gname_utf8 ? gname_utf8 : _("Buddies")); if (g == NULL) { g = purple_group_new(gname_utf8 ? gname_utf8 : _("Buddies")); purple_blist_add_group(g, NULL); @@ -3819,10 +3821,10 @@ static int purple_ssi_parselist(OscarData *od, FlapConnection *conn, FlapFrame * alias = aim_ssi_getalias_from_item(curitem); alias_utf8 = oscar_utf8_try_convert(account, od, alias); - b = purple_find_buddy_in_group(account, curitem->name, g); + b = purple_blist_find_buddy_in_group(account, curitem->name, g); if (b) { /* Get server stored alias */ - purple_blist_alias_buddy(b, alias_utf8); + purple_buddy_set_local_alias(b, alias_utf8); } else { b = purple_buddy_new(account, curitem->name, alias_utf8); @@ -3848,7 +3850,7 @@ static int purple_ssi_parselist(OscarData *od, FlapConnection *conn, FlapFrame * } break; case AIM_SSI_TYPE_GROUP: { /* Group */ - if (curitem->name != NULL && purple_find_group(curitem->name) == NULL) { + if (curitem->name != NULL && purple_blist_find_group(curitem->name) == NULL) { g = purple_group_new(curitem->name); purple_blist_add_group(g, NULL); } @@ -3856,11 +3858,11 @@ static int purple_ssi_parselist(OscarData *od, FlapConnection *conn, FlapFrame * case AIM_SSI_TYPE_PERMIT: { /* Permit buddy (unless we're on ICQ) */ if (!od->icq && curitem->name) { - for (cur = account->permit; (cur && oscar_util_name_compare(curitem->name, cur->data)); cur = cur->next); + for (cur = purple_account_privacy_get_permitted(account); (cur && oscar_util_name_compare(curitem->name, cur->data)); cur = cur->next); if (!cur) { purple_debug_info("oscar", "ssi: adding permit buddy %s to local list\n", curitem->name); - purple_privacy_permit_add(account, curitem->name, TRUE); + purple_account_privacy_permit_add(account, curitem->name, TRUE); } } } break; @@ -3868,11 +3870,11 @@ static int purple_ssi_parselist(OscarData *od, FlapConnection *conn, FlapFrame * case AIM_SSI_TYPE_ICQDENY: case AIM_SSI_TYPE_DENY: { /* Deny buddy */ if (curitem->type == deny_entry_type && curitem->name) { - for (cur = account->deny; (cur && oscar_util_name_compare(curitem->name, cur->data)); cur = cur->next); + for (cur = purple_account_privacy_get_denied(account); (cur && oscar_util_name_compare(curitem->name, cur->data)); cur = cur->next); if (!cur) { purple_debug_info("oscar", "ssi: adding deny buddy %s to local list\n", curitem->name); - purple_privacy_deny_add(account, curitem->name, TRUE); + purple_account_privacy_deny_add(account, curitem->name, TRUE); } } } break; @@ -3935,7 +3937,7 @@ static int purple_ssi_parselist(OscarData *od, FlapConnection *conn, FlapFrame * /* Request offline messages for AIM and ICQ */ aim_im_reqofflinemsgs(od); - purple_connection_set_state(gc, PURPLE_CONNECTED); + purple_connection_set_state(gc, PURPLE_CONNECTION_CONNECTED); } return 1; @@ -3962,7 +3964,7 @@ static int purple_ssi_parseack(OscarData *od, FlapConnection *conn, FlapFrame *f case 0x000c: { /* you are over the limit, the cheat is to the limit, come on fhqwhgads */ gchar *buf; buf = g_strdup_printf(_("Unable to add the buddy %s because you have too many buddies in your buddy list. Please remove one and try again."), (retval->name ? retval->name : _("(no name)"))); - if ((retval->name != NULL) && !purple_conv_present_error(retval->name, purple_connection_get_account(gc), buf)) + if ((retval->name != NULL) && !purple_conversation_present_error(retval->name, purple_connection_get_account(gc), buf)) purple_notify_error(gc, NULL, _("Unable to Add"), buf); g_free(buf); } break; @@ -3977,7 +3979,7 @@ static int purple_ssi_parseack(OscarData *od, FlapConnection *conn, FlapFrame *f purple_debug_error("oscar", "ssi: Action 0x%04hx was unsuccessful with error 0x%04hx\n", retval->action, retval->ack); buf = g_strdup_printf(_("Unable to add the buddy %s for an unknown reason."), (retval->name ? retval->name : _("(no name)"))); - if ((retval->name != NULL) && !purple_conv_present_error(retval->name, purple_connection_get_account(gc), buf)) + if ((retval->name != NULL) && !purple_conversation_present_error(retval->name, purple_connection_get_account(gc), buf)) purple_notify_error(gc, NULL, _("Unable to Add"), buf); g_free(buf); } break; @@ -4021,14 +4023,14 @@ purple_ssi_parseaddmod(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) alias_utf8 = oscar_utf8_try_convert(account, od, alias); g_free(alias); - b = purple_find_buddy(account, name); + b = purple_blist_find_buddy(account, name); if (b) { /* * You're logged in somewhere else and you aliased one * of your buddies, so update our local buddy list with * the person's new alias. */ - purple_blist_alias_buddy(b, alias_utf8); + purple_buddy_set_local_alias(b, alias_utf8); } else if (snac_subtype == 0x0008) { /* * You're logged in somewhere else and you added a buddy to @@ -4036,7 +4038,7 @@ purple_ssi_parseaddmod(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) */ b = purple_buddy_new(account, name, alias_utf8); - if (!(g = purple_find_group(gname_utf8 ? gname_utf8 : _("Buddies")))) { + if (!(g = purple_blist_find_group(gname_utf8 ? gname_utf8 : _("Buddies")))) { g = purple_group_new(gname_utf8 ? gname_utf8 : _("Buddies")); purple_blist_add_group(g, NULL); } @@ -4086,7 +4088,7 @@ static int purple_ssi_authgiven(OscarData *od, FlapConnection *conn, FlapFrame * purple_debug_info("oscar", "ssi: %s has given you permission to add him to your buddy list\n", bn); - buddy = purple_find_buddy(purple_connection_get_account(gc), bn); + buddy = purple_blist_find_buddy(purple_connection_get_account(gc), bn); if (buddy && (purple_buddy_get_alias_only(buddy))) nombre = g_strdup_printf("%s (%s)", bn, purple_buddy_get_alias_only(buddy)); else @@ -4155,7 +4157,7 @@ static int purple_ssi_authreply(OscarData *od, FlapConnection *conn, FlapFrame * purple_debug_info("oscar", "ssi: received authorization reply from %s. Reply is 0x%04hx\n", bn, reply); - buddy = purple_find_buddy(purple_connection_get_account(gc), bn); + buddy = purple_blist_find_buddy(purple_connection_get_account(gc), bn); if (buddy && (purple_buddy_get_alias_only(buddy))) nombre = g_strdup_printf("%s (%s)", bn, purple_buddy_get_alias_only(buddy)); else @@ -4187,7 +4189,7 @@ static int purple_ssi_gotadded(OscarData *od, FlapConnection *conn, FlapFrame *f bn = va_arg(ap, char *); va_end(ap); - buddy = purple_find_buddy(account, bn); + buddy = purple_blist_find_buddy(account, bn); purple_debug_info("oscar", "ssi: %s added you to their buddy list\n", bn); purple_account_notify_added(account, bn, NULL, (buddy ? purple_buddy_get_alias_only(buddy) : NULL), NULL); @@ -4287,17 +4289,17 @@ oscar_chat_invite(PurpleConnection *gc, int id, const char *message, const char void oscar_chat_leave(PurpleConnection *gc, int id) { - PurpleConversation *conv; + PurpleChatConversation *conv; struct chat_connection *cc; - conv = purple_find_chat(gc, id); + conv = purple_conversations_find_chat(gc, id); g_return_if_fail(conv != NULL); purple_debug_info("oscar", "Leaving chat room %s\n", - purple_conversation_get_name(conv)); + purple_conversation_get_name(PURPLE_CONVERSATION(conv))); - cc = find_oscar_chat(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv))); + cc = find_oscar_chat(gc, purple_chat_conversation_get_id(conv)); flap_connection_schedule_destroy(cc->conn, OSCAR_DISCONNECT_DONE, NULL); oscar_chat_kill(gc, cc); } @@ -4305,14 +4307,14 @@ oscar_chat_leave(PurpleConnection *gc, int id) int oscar_send_chat(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags) { OscarData *od = purple_connection_get_protocol_data(gc); - PurpleConversation *conv = NULL; + PurpleChatConversation *conv = NULL; struct chat_connection *c = NULL; char *buf, *buf2, *buf3; guint16 charset; char *charsetstr; gsize len; - if (!(conv = purple_find_chat(gc, id))) + if (!(conv = purple_conversations_find_chat(gc, id))) return -EINVAL; if (!(c = find_oscar_chat_by_conv(gc, conv))) @@ -4321,7 +4323,7 @@ int oscar_send_chat(PurpleConnection *gc, int id, const char *message, PurpleMes buf = purple_strdup_withhtml(message); if (strstr(buf, "<IMG ")) - purple_conversation_write(conv, "", + purple_conversation_write(PURPLE_CONVERSATION(conv), "", _("Your IM Image was not sent. " "You cannot send IM Images in AIM chats."), PURPLE_MESSAGE_ERROR, time(NULL)); @@ -4558,16 +4560,16 @@ oscar_status_types(PurpleAccount *account) OSCAR_STATUS_ID_AVAILABLE, NULL, TRUE, TRUE, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), + purple_g_value_new(G_TYPE_STRING), "itmsurl", _("iTunes Music Store Link"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_prepend(status_types, type); type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, OSCAR_STATUS_ID_FREE4CHAT, _("Free For Chat"), TRUE, is_icq, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_prepend(status_types, type); @@ -4575,7 +4577,7 @@ oscar_status_types(PurpleAccount *account) OSCAR_STATUS_ID_EVIL, _("Evil"), TRUE, is_icq, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_prepend(status_types, type); @@ -4583,7 +4585,7 @@ oscar_status_types(PurpleAccount *account) OSCAR_STATUS_ID_DEPRESSION, _("Depression"), TRUE, is_icq, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_prepend(status_types, type); @@ -4591,7 +4593,7 @@ oscar_status_types(PurpleAccount *account) OSCAR_STATUS_ID_ATHOME, _("At home"), TRUE, is_icq, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_prepend(status_types, type); @@ -4599,7 +4601,7 @@ oscar_status_types(PurpleAccount *account) OSCAR_STATUS_ID_ATWORK, _("At work"), TRUE, is_icq, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_prepend(status_types, type); @@ -4608,7 +4610,7 @@ oscar_status_types(PurpleAccount *account) OSCAR_STATUS_ID_LUNCH, _("Lunch"), TRUE, is_icq, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_prepend(status_types, type); @@ -4616,14 +4618,14 @@ oscar_status_types(PurpleAccount *account) OSCAR_STATUS_ID_AWAY, NULL, TRUE, TRUE, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_prepend(status_types, type); type = purple_status_type_new_with_attrs(PURPLE_STATUS_INVISIBLE, OSCAR_STATUS_ID_INVISIBLE, NULL, TRUE, TRUE, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_prepend(status_types, type); @@ -4635,21 +4637,21 @@ oscar_status_types(PurpleAccount *account) OSCAR_STATUS_ID_OCCUPIED, _("Occupied"), TRUE, is_icq, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_prepend(status_types, type); type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE, OSCAR_STATUS_ID_DND, _("Do Not Disturb"), TRUE, is_icq, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_prepend(status_types, type); type = purple_status_type_new_with_attrs(PURPLE_STATUS_EXTENDED_AWAY, OSCAR_STATUS_ID_NA, _("Not Available"), TRUE, is_icq, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_prepend(status_types, type); type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, @@ -4659,8 +4661,8 @@ oscar_status_types(PurpleAccount *account) type = purple_status_type_new_with_attrs(PURPLE_STATUS_MOOD, "mood", NULL, TRUE, is_icq, TRUE, - PURPLE_MOOD_NAME, _("Mood Name"), purple_value_new(PURPLE_TYPE_STRING), - PURPLE_MOOD_COMMENT, _("Mood Comment"), purple_value_new(PURPLE_TYPE_STRING), + PURPLE_MOOD_NAME, _("Mood Name"), purple_g_value_new(G_TYPE_STRING), + PURPLE_MOOD_COMMENT, _("Mood Comment"), purple_g_value_new(G_TYPE_STRING), NULL); status_types = g_list_prepend(status_types, type); @@ -4678,7 +4680,7 @@ static void oscar_ssi_editcomment(struct name_data *data, const char *text) { od = purple_connection_get_protocol_data(gc); account = purple_connection_get_account(gc); - b = purple_find_buddy(account, data->name); + b = purple_blist_find_buddy(account, data->name); if (b == NULL) { oscar_free_name_data(data); return; @@ -4707,7 +4709,7 @@ static void oscar_buddycb_edit_comment(PurpleBlistNode *node, gpointer ignore) { PurpleAccount *account; const char *name; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; name = purple_buddy_get_name(buddy); @@ -4768,7 +4770,7 @@ oscar_ask_directim(gpointer object, gpointer ignored) node = object; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *)node; account = purple_buddy_get_account(buddy); @@ -4799,14 +4801,14 @@ oscar_close_directim(gpointer object, gpointer ignored) PurpleBuddy *buddy; PurpleAccount *account; PurpleConnection *gc; - PurpleConversation *conv; + PurpleIMConversation *im; OscarData *od; PeerConnection *conn; const char *name; node = object; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy*)node; name = purple_buddy_get_name(buddy); @@ -4824,8 +4826,8 @@ oscar_close_directim(gpointer object, gpointer ignored) /* OSCAR_DISCONNECT_LOCAL_CLOSED doesn't write anything to the convo * window. Let the user know that we cancelled the Direct IM. */ - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name); - purple_conversation_write(conv, NULL, _("You closed the connection."), + im = purple_im_conversation_new(account, name); + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, _("You closed the connection."), PURPLE_MESSAGE_SYSTEM, time(NULL)); } } @@ -4838,7 +4840,7 @@ static void oscar_get_icqxstatusmsg(PurpleBlistNode *node, gpointer ignore) PurpleAccount *account; const char *bname; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *)node; bname = purple_buddy_get_name(buddy); @@ -4858,7 +4860,7 @@ oscar_get_aim_info_cb(PurpleBlistNode *node, gpointer ignore) PurpleBuddy *buddy; PurpleConnection *gc; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *)node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); @@ -4958,7 +4960,7 @@ oscar_buddy_menu(PurpleBuddy *buddy) { GList *oscar_blist_node_menu(PurpleBlistNode *node) { - if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if(PURPLE_IS_BUDDY(node)) { return oscar_buddy_menu((PurpleBuddy *) node); } else { return NULL; @@ -5084,7 +5086,7 @@ static void oscar_show_awaitingauth(PurplePluginAction *action) GSList *buddies, *filtered_buddies, *cur; gchar *text; - buddies = purple_find_buddies(account, NULL); + buddies = purple_blist_find_buddies(account, NULL); filtered_buddies = NULL; for (cur = buddies; cur != NULL; cur = cur->next) { PurpleBuddy *buddy; @@ -5176,15 +5178,15 @@ void oscar_set_icon(PurpleConnection *gc, PurpleStoredImage *img) if (img == NULL) { aim_ssi_delicon(od); } else { - PurpleCipherContext *context; + PurpleHash *hash; guchar md5[16]; gconstpointer data = purple_imgstore_get_data(img); size_t len = purple_imgstore_get_size(img); - context = purple_cipher_context_new_by_name("md5", NULL); - purple_cipher_context_append(context, data, len); - purple_cipher_context_digest(context, md5, sizeof(md5)); - purple_cipher_context_destroy(context); + hash = purple_md5_hash_new(); + purple_hash_append(hash, data, len); + purple_hash_digest(hash, md5, sizeof(md5)); + g_object_unref(hash); aim_ssi_seticon(od, md5, 16); } @@ -5483,16 +5485,16 @@ static gboolean oscar_uri_handler(const char *proto, const char *cmd, GHashTable if (bname) { char *message = g_hash_table_lookup(params, "message"); - PurpleConversation *conv = purple_find_conversation_with_account( - PURPLE_CONV_TYPE_IM, bname, acct); - if (conv == NULL) - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, bname); - purple_conversation_present(conv); + PurpleIMConversation *im = purple_conversations_find_im_with_account( + bname, acct); + if (im == NULL) + im = purple_im_conversation_new(acct, bname); + purple_conversation_present(PURPLE_CONVERSATION(im)); if (message) { /* Spaces are encoded as '+' */ g_strdelimit(message, "+", ' '); - purple_conv_send_confirm(conv, message); + purple_conversation_send_confirm(PURPLE_CONVERSATION(im), message); } } /*else diff --git a/libpurple/protocols/oscar/oscar.h b/libpurple/protocols/oscar/oscar.h index 7da1d44b16..ea74414ffb 100644 --- a/libpurple/protocols/oscar/oscar.h +++ b/libpurple/protocols/oscar/oscar.h @@ -30,7 +30,7 @@ #define _OSCAR_H_ #include "internal.h" -#include "circbuffer.h" +#include "circularbuffer.h" #include "debug.h" #include "eventloop.h" #include "http.h" @@ -280,7 +280,7 @@ struct _FlapConnection guint8 header[6]; gssize header_received; FlapFrame buffer_incoming; - PurpleCircBuffer *buffer_outgoing; + PurpleCircularBuffer *buffer_outgoing; guint watcher_incoming; guint watcher_outgoing; @@ -602,7 +602,7 @@ struct chat_connection FlapConnection *conn; int id; PurpleConnection *gc; - PurpleConversation *conv; + PurpleChatConversation *conv; guint16 maxlen; guint16 maxvis; }; diff --git a/libpurple/protocols/oscar/oscarcommon.h b/libpurple/protocols/oscar/oscarcommon.h index a0647dfe44..a3cadfc0ae 100644 --- a/libpurple/protocols/oscar/oscarcommon.h +++ b/libpurple/protocols/oscar/oscarcommon.h @@ -74,7 +74,7 @@ void oscar_login(PurpleAccount *account); void oscar_close(PurpleConnection *gc); int oscar_send_im(PurpleConnection *gc, const char *name, const char *message, PurpleMessageFlags imflags); void oscar_set_info(PurpleConnection *gc, const char *rawinfo); -unsigned int oscar_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state); +unsigned int oscar_send_typing(PurpleConnection *gc, const char *name, PurpleIMTypingState state); void oscar_get_info(PurpleConnection *gc, const char *name); void oscar_set_status(PurpleAccount *account, PurpleStatus *status); void oscar_set_idle(PurpleConnection *gc, int time); diff --git a/libpurple/protocols/oscar/peer.c b/libpurple/protocols/oscar/peer.c index 93ed217c46..699781e9aa 100644 --- a/libpurple/protocols/oscar/peer.c +++ b/libpurple/protocols/oscar/peer.c @@ -115,7 +115,7 @@ peer_connection_new(OscarData *od, guint64 type, const char *bn) conn->od = od; conn->type = type; conn->bn = g_strdup(bn); - conn->buffer_outgoing = purple_circ_buffer_new(0); + conn->buffer_outgoing = purple_circular_buffer_new(0); conn->listenerfd = -1; conn->fd = -1; conn->lastactivity = time(NULL); @@ -189,8 +189,8 @@ peer_connection_close(PeerConnection *conn) conn->buffer_incoming.len = 0; conn->buffer_incoming.offset = 0; - purple_circ_buffer_destroy(conn->buffer_outgoing); - conn->buffer_outgoing = purple_circ_buffer_new(0); + g_object_unref(G_OBJECT(conn->buffer_outgoing)); + conn->buffer_outgoing = purple_circular_buffer_new(0); conn->flags &= ~PEER_CONNECTION_FLAG_IS_INCOMING; } @@ -234,7 +234,7 @@ peer_connection_destroy_cb(gpointer data) g_free(conn->clientip); g_free(conn->verifiedip); g_free(conn->xferdata.name); - purple_circ_buffer_destroy(conn->buffer_outgoing); + g_object_unref(G_OBJECT(conn->buffer_outgoing)); conn->od->peer_connections = g_slist_remove(conn->od->peer_connections, conn); @@ -408,9 +408,10 @@ send_cb(gpointer data, gint source, PurpleInputCondition cond) PeerConnection *conn; gsize writelen; gssize wrotelen; + const gchar *output = NULL; conn = data; - writelen = purple_circ_buffer_get_max_read(conn->buffer_outgoing); + writelen = purple_circular_buffer_get_max_read(conn->buffer_outgoing); if (writelen == 0) { @@ -433,12 +434,13 @@ send_cb(gpointer data, gint source, PurpleInputCondition cond) * file transfer. Somebody should teach those guys how to * write good TCP code. */ - conn->buffer_outgoing->inptr = conn->buffer_outgoing->buffer; - conn->buffer_outgoing->outptr = conn->buffer_outgoing->buffer; + purple_circular_buffer_reset(conn->buffer_outgoing); return; } - wrotelen = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0); + output = purple_circular_buffer_get_output(conn->buffer_outgoing); + + wrotelen = send(conn->fd, output, writelen, 0); if (wrotelen <= 0) { if (wrotelen < 0 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) @@ -465,7 +467,7 @@ send_cb(gpointer data, gint source, PurpleInputCondition cond) return; } - purple_circ_buffer_mark_read(conn->buffer_outgoing, wrotelen); + purple_circular_buffer_mark_read(conn->buffer_outgoing, wrotelen); conn->lastactivity = time(NULL); } @@ -478,7 +480,7 @@ void peer_connection_send(PeerConnection *conn, ByteStream *bs) { /* Add everything to our outgoing buffer */ - purple_circ_buffer_append(conn->buffer_outgoing, bs->data, bs->len); + purple_circular_buffer_append(conn->buffer_outgoing, bs->data, bs->len); /* If we haven't already started writing stuff, then start the cycle */ if ((conn->watcher_outgoing == 0) && (conn->fd >= 0)) @@ -686,7 +688,7 @@ peer_connection_establish_listener_cb(int listenerfd, gpointer data) OscarData *od; PurpleConnection *gc; PurpleAccount *account; - PurpleConversation *conv; + PurpleIMConversation *im; char *tmp; FlapConnection *bos_conn; const char *listener_ip; @@ -750,10 +752,11 @@ peer_connection_establish_listener_cb(int listenerfd, gpointer data) listener_port, ++conn->lastrequestnumber); /* Print a message to a local conversation window */ - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn); + im = purple_im_conversation_new(account, conn->bn); tmp = g_strdup_printf(_("Asking %s to connect to us at %s:%hu for " "Direct IM."), conn->bn, listener_ip, listener_port); - purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, tmp, + PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(tmp); } else if (conn->type == OSCAR_CAPABILITY_SENDFILE) @@ -835,11 +838,11 @@ peer_connection_trynext(PeerConnection *conn) if (conn->type == OSCAR_CAPABILITY_DIRECTIM) { gchar *tmp; - PurpleConversation *conv; + PurpleIMConversation *im; tmp = g_strdup_printf(_("Attempting to connect to %s:%hu."), conn->verifiedip, conn->port); - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn); - purple_conversation_write(conv, NULL, tmp, + im = purple_im_conversation_new(account, conn->bn); + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(tmp); } @@ -909,10 +912,10 @@ peer_connection_trynext(PeerConnection *conn) if (conn->type == OSCAR_CAPABILITY_DIRECTIM) { gchar *tmp; - PurpleConversation *conv; + PurpleIMConversation *im; tmp = g_strdup(_("Attempting to connect via proxy server.")); - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn); - purple_conversation_write(conv, NULL, tmp, + im = purple_im_conversation_new(account, conn->bn); + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(tmp); } @@ -950,15 +953,14 @@ peer_connection_propose(OscarData *od, guint64 type, const char *bn) if (conn->ready) { PurpleAccount *account; - PurpleConversation *conv; + PurpleIMConversation *im; purple_debug_info("oscar", "Already have a direct IM " "session with %s.\n", bn); account = purple_connection_get_account(od->gc); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - bn, account); - if (conv != NULL) - purple_conversation_present(conv); + im = purple_conversations_find_im_with_account(bn, account); + if (im != NULL) + purple_conversation_present(PURPLE_CONVERSATION(im)); return; } diff --git a/libpurple/protocols/oscar/peer.h b/libpurple/protocols/oscar/peer.h index a706c3ff31..ccada7ab4b 100644 --- a/libpurple/protocols/oscar/peer.h +++ b/libpurple/protocols/oscar/peer.h @@ -184,7 +184,7 @@ struct _PeerConnection guint8 proxy_header[12]; gssize proxy_header_received; ByteStream buffer_incoming; - PurpleCircBuffer *buffer_outgoing; + PurpleCircularBuffer *buffer_outgoing; guint watcher_incoming; guint watcher_outgoing; @@ -251,7 +251,7 @@ void peer_connection_got_proposition(OscarData *od, const gchar *bn, const gchar void peer_odc_close(PeerConnection *conn); void peer_odc_recv_frame(PeerConnection *conn, ByteStream *bs); void peer_odc_send_cookie(PeerConnection *conn); -void peer_odc_send_typing(PeerConnection *conn, PurpleTypingState typing); +void peer_odc_send_typing(PeerConnection *conn, PurpleIMTypingState typing); void peer_odc_send_im(PeerConnection *conn, const char *msg, int len, int encoding, gboolean autoreply); /* diff --git a/libpurple/protocols/oscar/userinfo.c b/libpurple/protocols/oscar/userinfo.c index 177263deaa..399797aca2 100644 --- a/libpurple/protocols/oscar/userinfo.c +++ b/libpurple/protocols/oscar/userinfo.c @@ -189,7 +189,7 @@ oscar_user_info_append_status(PurpleConnection *gc, PurpleNotifyUserInfo *user_i return; if (b == NULL) - b = purple_find_buddy(purple_connection_get_account(gc), userinfo->bn); + b = purple_blist_find_buddy(purple_connection_get_account(gc), userinfo->bn); else userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b)); @@ -322,7 +322,7 @@ oscar_user_info_append_extra_info(PurpleConnection *gc, PurpleNotifyUserInfo *us userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b)); if (b == NULL) - b = purple_find_buddy(account, userinfo->bn); + b = purple_blist_find_buddy(account, userinfo->bn); if (b != NULL) { bname = purple_buddy_get_name(b); @@ -369,7 +369,7 @@ oscar_user_info_display_error(OscarData *od, guint16 error_reason, gchar *buddy) purple_notify_user_info_add_pair_plaintext(user_info, NULL, buf); purple_notify_userinfo(od->gc, buddy, user_info, NULL, NULL); purple_notify_user_info_destroy(user_info); - purple_conv_present_error(buddy, purple_connection_get_account(od->gc), buf); + purple_conversation_present_error(buddy, purple_connection_get_account(od->gc), buf); g_free(buf); } @@ -389,7 +389,7 @@ oscar_user_info_display_icq(OscarData *od, struct aim_icq_info *info) user_info = purple_notify_user_info_new(); g_snprintf(who, sizeof(who), "%u", info->uin); - buddy = purple_find_buddy(account, who); + buddy = purple_blist_find_buddy(account, who); if (buddy != NULL) bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, purple_buddy_get_name(buddy))); else diff --git a/libpurple/protocols/oscar/visibility.c b/libpurple/protocols/oscar/visibility.c index 3c091a9781..123f14a595 100644 --- a/libpurple/protocols/oscar/visibility.c +++ b/libpurple/protocols/oscar/visibility.c @@ -94,7 +94,7 @@ show_private_list(PurplePluginAction *action, guint16 list_type, const gchar *ti GSList *buddies, *filtered_buddies, *cur; gchar *text, *secondary; - buddies = purple_find_buddies(account, NULL); + buddies = purple_blist_find_buddies(account, NULL); filtered_buddies = NULL; for (cur = buddies; cur != NULL; cur = cur->next) { PurpleBuddy *buddy; diff --git a/libpurple/protocols/sametime/sametime.c b/libpurple/protocols/sametime/sametime.c index d395bf2d11..3f0bdc9a2c 100644 --- a/libpurple/protocols/sametime/sametime.c +++ b/libpurple/protocols/sametime/sametime.c @@ -33,7 +33,7 @@ /* purple includes */ #include "account.h" #include "accountopt.h" -#include "circbuffer.h" +#include "circularbuffer.h" #include "conversation.h" #include "debug.h" #include "ft.h" @@ -41,7 +41,6 @@ #include "mime.h" #include "notify.h" #include "plugin.h" -#include "privacy.h" #include "prpl.h" #include "request.h" #include "util.h" @@ -221,7 +220,7 @@ struct mwPurplePluginData { gint outpa; /* like inpa, but the other way */ /** circular buffer for outgoing data */ - PurpleCircBuffer *sock_buf; + PurpleCircularBuffer *sock_buf; PurpleConnection *gc; }; @@ -296,7 +295,7 @@ static void convo_data_free(struct convo_data *conv); static void convo_features(struct mwConversation *conv); -static PurpleConversation *convo_get_gconv(struct mwConversation *conv); +static PurpleIMConversation *convo_get_im(struct mwConversation *conv); /* name and id */ @@ -343,7 +342,7 @@ static PurpleConnection *session_to_gc(struct mwSession *session) { static void write_cb(gpointer data, gint source, PurpleInputCondition cond) { struct mwPurplePluginData *pd = data; - PurpleCircBuffer *circ = pd->sock_buf; + PurpleCircularBuffer *circ = pd->sock_buf; gsize avail; int ret; @@ -351,17 +350,17 @@ static void write_cb(gpointer data, gint source, PurpleInputCondition cond) { g_return_if_fail(circ != NULL); - avail = purple_circ_buffer_get_max_read(circ); + avail = purple_circular_buffer_get_max_read(circ); if(BUF_LONG < avail) avail = BUF_LONG; while(avail) { - ret = write(pd->socket, circ->outptr, avail); + ret = write(pd->socket, purple_circular_buffer_get_output(circ), avail); if(ret <= 0) break; - purple_circ_buffer_mark_read(circ, ret); - avail = purple_circ_buffer_get_max_read(circ); + purple_circular_buffer_mark_read(circ, ret); + avail = purple_circular_buffer_get_max_read(circ); if(BUF_LONG < avail) avail = BUF_LONG; } @@ -386,7 +385,7 @@ static int mw_session_io_write(struct mwSession *session, if(pd->outpa) { DEBUG_INFO("already pending INPUT_WRITE, buffering\n"); - purple_circ_buffer_append(pd->sock_buf, buf, len); + purple_circular_buffer_append(pd->sock_buf, buf, len); return 0; } @@ -406,7 +405,7 @@ static int mw_session_io_write(struct mwSession *session, if(err == EAGAIN) { /* append remainder to circular buffer */ DEBUG_INFO("EAGAIN\n"); - purple_circ_buffer_append(pd->sock_buf, buf, len); + purple_circular_buffer_append(pd->sock_buf, buf, len); pd->outpa = purple_input_add(pd->socket, PURPLE_INPUT_WRITE, write_cb, pd); } else if(len > 0) { @@ -477,7 +476,7 @@ static void blist_resolve_alias_cb(struct mwServiceResolve *srvc, match = result->matches->data; g_return_if_fail(match != NULL); - purple_blist_server_alias_buddy(data, match->name); + purple_buddy_set_server_alias(data, match->name); purple_blist_node_set_string(data, BUDDY_KEY_NAME, match->name); } @@ -569,7 +568,7 @@ static void mw_aware_list_on_aware(struct mwAwareList *list, PurpleBlistNode *bnode; group = g_hash_table_lookup(pd->group_list_map, list); - buddy = purple_find_buddy_in_group(acct, id, group); + buddy = purple_blist_find_buddy_in_group(acct, id, group); bnode = (PurpleBlistNode *) buddy; if(! buddy) { @@ -677,7 +676,7 @@ static void blist_export(PurpleConnection *gc, struct mwSametimeList *stlist) { enum mwSametimeGroupType gtype; gboolean gopen; - if(! PURPLE_BLIST_NODE_IS_GROUP(gn)) continue; + if(! PURPLE_IS_GROUP(gn)) continue; grp = (PurpleGroup *) gn; /* the group's type (normal or dynamic) */ @@ -713,13 +712,13 @@ static void blist_export(PurpleConnection *gc, struct mwSametimeList *stlist) { for(cn = purple_blist_node_get_first_child(gn); cn; cn = purple_blist_node_get_sibling_next(cn)) { - if(! PURPLE_BLIST_NODE_IS_CONTACT(cn)) continue; + if(! PURPLE_IS_CONTACT(cn)) continue; for(bn = purple_blist_node_get_first_child(cn); bn; bn = purple_blist_node_get_sibling_next(bn)) { - if(! PURPLE_BLIST_NODE_IS_BUDDY(bn)) continue; - if(! PURPLE_BLIST_NODE_SHOULD_SAVE(bn)) continue; + if(! PURPLE_IS_BUDDY(bn)) continue; + if(purple_blist_node_is_transient(bn)) continue; bdy = (PurpleBuddy *) bn; @@ -734,7 +733,7 @@ static void blist_export(PurpleConnection *gc, struct mwSametimeList *stlist) { stu = mwSametimeUser_new(stg, utype, &idb); mwSametimeUser_setShortName(stu, purple_buddy_get_server_alias(bdy)); - mwSametimeUser_setAlias(stu, purple_buddy_get_local_buddy_alias(bdy)); + mwSametimeUser_setAlias(stu, purple_buddy_get_local_alias(bdy)); } } } @@ -861,7 +860,7 @@ static PurpleBuddy *buddy_ensure(PurpleConnection *gc, PurpleGroup *group, g_return_val_if_fail(id != NULL, NULL); g_return_val_if_fail(*id, NULL); - buddy = purple_find_buddy_in_group(acct, id, group); + buddy = purple_blist_find_buddy_in_group(acct, id, group); if(! buddy) { buddy = purple_buddy_new(acct, id, alias); @@ -869,8 +868,8 @@ static PurpleBuddy *buddy_ensure(PurpleConnection *gc, PurpleGroup *group, buddy_add(pd, buddy); } - purple_blist_alias_buddy(buddy, alias); - purple_blist_server_alias_buddy(buddy, name); + purple_buddy_set_local_alias(buddy, alias); + purple_buddy_set_server_alias(buddy, name); purple_blist_node_set_string((PurpleBlistNode *) buddy, BUDDY_KEY_NAME, name); purple_blist_node_set_int((PurpleBlistNode *) buddy, BUDDY_KEY_TYPE, type); @@ -913,7 +912,7 @@ static PurpleGroup *group_ensure(PurpleConnection *gc, acct = purple_connection_get_account(gc); owner = purple_account_get_username(acct); - blist = purple_get_blist(); + blist = purple_blist_get_buddy_list(); g_return_val_if_fail(blist != NULL, NULL); name = mwSametimeGroup_getName(stgroup); @@ -937,7 +936,7 @@ static PurpleGroup *group_ensure(PurpleConnection *gc, for(gn = purple_blist_get_root(); gn; gn = purple_blist_node_get_sibling_next(gn)) { const char *n, *o; - if(! PURPLE_BLIST_NODE_IS_GROUP(gn)) continue; + if(! PURPLE_IS_GROUP(gn)) continue; n = purple_blist_node_get_string(gn, GROUP_KEY_NAME); o = purple_blist_node_get_string(gn, GROUP_KEY_OWNER); @@ -955,7 +954,7 @@ static PurpleGroup *group_ensure(PurpleConnection *gc, /* try again, by alias */ if(! group) { DEBUG_INFO("searching for group by alias %s\n", NSTR(alias)); - group = purple_find_group(alias); + group = purple_blist_find_group(alias); } /* oh well, no such group. Let's create it! */ @@ -1024,14 +1023,14 @@ static void group_clear(PurpleGroup *group, PurpleAccount *acct, gboolean del) { for(cn = purple_blist_node_get_first_child(gn); cn; cn = purple_blist_node_get_sibling_next(cn)) { - if(! PURPLE_BLIST_NODE_IS_CONTACT(cn)) continue; + if(! PURPLE_IS_CONTACT(cn)) continue; for(bn = purple_blist_node_get_first_child(cn); bn; bn = purple_blist_node_get_sibling_next(bn)) { PurpleBuddy *gb = (PurpleBuddy *) bn; - if(! PURPLE_BLIST_NODE_IS_BUDDY(bn)) continue; + if(! PURPLE_IS_BUDDY(bn)) continue; if(purple_buddy_get_account(gb) == acct) { DEBUG_INFO("clearing %s from group\n", NSTR(purple_buddy_get_name(gb))); @@ -1051,7 +1050,7 @@ static void group_clear(PurpleGroup *group, PurpleAccount *acct, gboolean del) { DEBUG_INFO("cleared buddies\n"); /* optionally remove group from blist */ - if(del && !purple_blist_get_group_size(group, TRUE)) { + if(del && !purple_counting_node_get_total_size(PURPLE_COUNTING_NODE(group))) { DEBUG_INFO("removing empty group\n"); purple_blist_remove_group(group); } @@ -1093,14 +1092,14 @@ static void group_prune(PurpleConnection *gc, PurpleGroup *group, for(cn = purple_blist_node_get_first_child(gn); cn; cn = purple_blist_node_get_sibling_next(cn)) { - if(! PURPLE_BLIST_NODE_IS_CONTACT(cn)) continue; + if(! PURPLE_IS_CONTACT(cn)) continue; for(bn = purple_blist_node_get_first_child(cn); bn; bn = purple_blist_node_get_sibling_next(bn)) { PurpleBuddy *gb = (PurpleBuddy *) bn; - if(! PURPLE_BLIST_NODE_IS_BUDDY(bn)) continue; + if(! PURPLE_IS_BUDDY(bn)) continue; /* if the account is correct and they're not in our table, mark them for pruning */ @@ -1146,7 +1145,7 @@ static void blist_sync(PurpleConnection *gc, struct mwSametimeList *stlist) { acct_n = purple_account_get_username(acct); - blist = purple_get_blist(); + blist = purple_blist_get_buddy_list(); g_return_if_fail(blist != NULL); /* build a hash table for quick lookup while pruning the local @@ -1167,7 +1166,7 @@ static void blist_sync(PurpleConnection *gc, struct mwSametimeList *stlist) { const char *gname, *owner; struct mwSametimeGroup *stgrp; - if(! PURPLE_BLIST_NODE_IS_GROUP(gn)) continue; + if(! PURPLE_IS_GROUP(gn)) continue; /* group not belonging to this account */ if(! purple_group_on_account(grp, acct)) @@ -1280,7 +1279,7 @@ static void conversation_created_cb(PurpleConversation *g_conv, if(pd->gc != gc) return; /* not ours */ - if(purple_conversation_get_type(g_conv) != PURPLE_CONV_TYPE_IM) + if(PURPLE_IS_CHAT_CONVERSATION(g_conv)) return; /* wrong type */ who.user = (char *) purple_conversation_get_name(g_conv); @@ -1308,7 +1307,7 @@ static void blist_menu_nab(PurpleBlistNode *node, gpointer data) { gc = pd->gc; g_return_if_fail(gc != NULL); - g_return_if_fail(PURPLE_BLIST_NODE_IS_GROUP(node)); + g_return_if_fail(PURPLE_IS_GROUP(node)); str = g_string_new(NULL); @@ -1338,7 +1337,7 @@ static void blist_node_menu_cb(PurpleBlistNode *node, PurpleMenuAction *act; /* we only want groups */ - if(! PURPLE_BLIST_NODE_IS_GROUP(node)) return; + if(! PURPLE_IS_GROUP(node)) return; acct = purple_connection_get_account(pd->gc); g_return_if_fail(acct != NULL); @@ -1376,18 +1375,18 @@ static void blist_init(PurpleAccount *acct) { for(gnode = purple_blist_get_root(); gnode; gnode = purple_blist_node_get_sibling_next(gnode)) { - if(! PURPLE_BLIST_NODE_IS_GROUP(gnode)) continue; + if(! PURPLE_IS_GROUP(gnode)) continue; for(cnode = purple_blist_node_get_first_child(gnode); cnode; cnode = purple_blist_node_get_sibling_next(cnode)) { - if(! PURPLE_BLIST_NODE_IS_CONTACT(cnode)) + if(! PURPLE_IS_CONTACT(cnode)) continue; for(bnode = purple_blist_node_get_first_child(cnode); bnode; bnode = purple_blist_node_get_sibling_next(bnode)) { PurpleBuddy *b; - if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + if(!PURPLE_IS_BUDDY(bnode)) continue; b = (PurpleBuddy *)bnode; @@ -1427,7 +1426,7 @@ static void services_starting(struct mwPurplePluginData *pd) { enum mwSametimeGroupType gt; const char *owner; - if(! PURPLE_BLIST_NODE_IS_GROUP(l)) continue; + if(! PURPLE_IS_GROUP(l)) continue; /* if the group is ownerless, or has an owner and we're not it, skip it */ @@ -1574,7 +1573,7 @@ static void mw_session_stateChange(struct mwSession *session, msg = _("Connected"); purple_connection_update_progress(gc, msg, 10, MW_CONNECT_STEPS); - purple_connection_set_state(gc, PURPLE_CONNECTED); + purple_connection_set_state(gc, PURPLE_CONNECTION_CONNECTED); break; case mwSession_STOPPING: @@ -1634,7 +1633,7 @@ static void mw_session_setPrivacyInfo(struct mwSession *session) { PurpleConnection *gc; PurpleAccount *acct; struct mwPrivacyInfo *privacy; - GSList *l, **ll; + GSList *list; guint count; DEBUG_INFO("privacy information set from server\n"); @@ -1653,16 +1652,25 @@ static void mw_session_setPrivacyInfo(struct mwSession *session) { privacy = mwSession_getPrivacyInfo(session); count = privacy->count; - ll = (privacy->deny)? &acct->deny: &acct->permit; - for(l = *ll; l; l = l->next) g_free(l->data); - g_slist_free(*ll); - l = *ll = NULL; - - while(count--) { - struct mwUserItem *u = privacy->users + count; - l = g_slist_prepend(l, g_strdup(u->id)); + if (privacy->deny) { + while ((list = purple_account_privacy_get_denied(acct))) { + g_free(list->data); + purple_account_privacy_deny_remove(acct, list->data, TRUE); + } + while (count--) { + struct mwUserItem *u = privacy->users + count; + purple_account_privacy_deny_add(acct, u->id, TRUE); + } + } else { + while ((list = purple_account_privacy_get_permitted(acct))) { + g_free(list->data); + purple_account_privacy_permit_remove(acct, list->data, TRUE); + } + while (count--) { + struct mwUserItem *u = privacy->users + count; + purple_account_privacy_permit_add(acct, u->id, TRUE); + } } - *ll = l; } @@ -1827,23 +1835,24 @@ static void mw_session_announce(struct mwSession *s, const char *text) { struct mwPurplePluginData *pd; PurpleAccount *acct; - PurpleConversation *conv; + PurpleIMConversation *im; PurpleBuddy *buddy; char *who = from->user_id; char *msg; pd = mwSession_getClientData(s); acct = purple_connection_get_account(pd->gc); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, acct); - if(! conv) conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, who); + im = purple_conversations_find_im_with_account(who, acct); + if(! im) im = purple_im_conversation_new(acct, who); - buddy = purple_find_buddy(acct, who); + buddy = purple_blist_find_buddy(acct, who); if(buddy) who = (char *) purple_buddy_get_contact_alias(buddy); who = g_strdup_printf(_("Announcement from %s"), who); msg = purple_markup_linkify(text); - purple_conversation_write(conv, who, msg ? msg : "", PURPLE_MESSAGE_RECV, time(NULL)); + purple_conversation_write(PURPLE_CONVERSATION(im), who, msg ? msg : "", + PURPLE_MESSAGE_RECV, time(NULL)); g_free(who); g_free(msg); } @@ -1929,14 +1938,14 @@ static void mw_conf_invited(struct mwConference *conf, } -/* The following mess helps us relate a mwConference to a PurpleConvChat +/* The following mess helps us relate a mwConference to a PurpleChatConversation in the various forms by which either may be indicated */ #define CONF_TO_ID(conf) (GPOINTER_TO_INT(conf)) #define ID_TO_CONF(pd, id) (conf_find_by_id((pd), (id))) -#define CHAT_TO_ID(chat) (purple_conv_chat_get_id(chat)) -#define ID_TO_CHAT(id) (purple_find_chat(id)) +#define CHAT_TO_ID(chat) (purple_chat_conversation_get_id(chat)) +#define ID_TO_CHAT(id) (purple_conversations_find_chat(id)) #define CHAT_TO_CONF(pd, chat) (ID_TO_CONF((pd), CHAT_TO_ID(chat))) #define CONF_TO_CHAT(conf) (ID_TO_CHAT(CONF_TO_ID(conf))) @@ -1952,7 +1961,7 @@ conf_find_by_id(struct mwPurplePluginData *pd, int id) { ll = mwServiceConference_getConferences(srvc); for(l = ll; l; l = l->next) { struct mwConference *c = l->data; - PurpleConvChat *h = mwConference_getClientData(c); + PurpleChatConversation *h = mwConference_getClientData(c); if(CHAT_TO_ID(h) == id) { conf = c; @@ -1970,7 +1979,7 @@ static void mw_conf_opened(struct mwConference *conf, GList *members) { struct mwSession *session; struct mwPurplePluginData *pd; PurpleConnection *gc; - PurpleConversation *g_conf; + PurpleChatConversation *g_conf; const char *n = mwConference_getName(conf); const char *t = mwConference_getTitle(conf); @@ -1986,12 +1995,12 @@ static void mw_conf_opened(struct mwConference *conf, GList *members) { if(! t) t = "(no title)"; g_conf = serv_got_joined_chat(gc, CONF_TO_ID(conf), t); - mwConference_setClientData(conf, PURPLE_CONV_CHAT(g_conf), NULL); + mwConference_setClientData(conf, g_conf, NULL); for(; members; members = members->next) { struct mwLoginInfo *peer = members->data; - purple_conv_chat_add_user(PURPLE_CONV_CHAT(g_conf), peer->user_id, - NULL, PURPLE_CBFLAGS_NONE, FALSE); + purple_chat_conversation_add_user(g_conf, peer->user_id, + NULL, PURPLE_CHAT_USER_NONE, FALSE); } } @@ -2022,7 +2031,7 @@ static void mw_conf_closed(struct mwConference *conf, guint32 reason) { static void mw_conf_peer_joined(struct mwConference *conf, struct mwLoginInfo *peer) { - PurpleConvChat *g_conf; + PurpleChatConversation *g_conf; const char *n = mwConference_getName(conf); @@ -2031,15 +2040,15 @@ static void mw_conf_peer_joined(struct mwConference *conf, g_conf = mwConference_getClientData(conf); g_return_if_fail(g_conf != NULL); - purple_conv_chat_add_user(g_conf, peer->user_id, - NULL, PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(g_conf, peer->user_id, + NULL, PURPLE_CHAT_USER_NONE, TRUE); } static void mw_conf_peer_parted(struct mwConference *conf, struct mwLoginInfo *peer) { - PurpleConvChat *g_conf; + PurpleChatConversation *g_conf; const char *n = mwConference_getName(conf); @@ -2048,7 +2057,7 @@ static void mw_conf_peer_parted(struct mwConference *conf, g_conf = mwConference_getClientData(conf); g_return_if_fail(g_conf != NULL); - purple_conv_chat_remove_user(g_conf, peer->user_id, NULL); + purple_chat_conversation_remove_user(g_conf, peer->user_id, NULL); } @@ -2400,7 +2409,7 @@ static void convo_data_new(struct mwConversation *conv) { } -static PurpleConversation *convo_get_gconv(struct mwConversation *conv) { +static PurpleIMConversation *convo_get_im(struct mwConversation *conv) { struct mwServiceIm *srvc; struct mwSession *session; struct mwPurplePluginData *pd; @@ -2417,8 +2426,7 @@ static PurpleConversation *convo_get_gconv(struct mwConversation *conv) { idb = mwConversation_getTarget(conv); - return purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - idb->user, acct); + return purple_conversations_find_im_with_account(idb->user, acct); } @@ -2452,7 +2460,7 @@ static void convo_queue(struct mwConversation *conv, /* Does what it takes to get an error displayed for a conversation */ static void convo_error(struct mwConversation *conv, guint32 err) { - PurpleConversation *gconv; + PurpleIMConversation *im; char *tmp, *text; struct mwIdBlock *idb; @@ -2461,13 +2469,15 @@ static void convo_error(struct mwConversation *conv, guint32 err) { tmp = mwError(err); text = g_strconcat(_("Unable to send message: "), tmp, NULL); - gconv = convo_get_gconv(conv); - if(gconv && !purple_conv_present_error(idb->user, purple_conversation_get_account(gconv), text)) { + im = convo_get_im(conv); + if(im && !purple_conversation_present_error(idb->user, + purple_conversation_get_account(PURPLE_CONVERSATION(im)), text)) { g_free(text); text = g_strdup_printf(_("Unable to send message to %s:"), (idb->user)? idb->user: "(unknown)"); - purple_notify_error(purple_account_get_connection(purple_conversation_get_account(gconv)), + purple_notify_error(purple_account_get_connection( + purple_conversation_get_account(PURPLE_CONVERSATION(im))), NULL, text, tmp); } @@ -2499,16 +2509,17 @@ static void convo_queue_send(struct mwConversation *conv) { inform the purple conversation that it's unsafe to offer any *cool* features. */ static void convo_nofeatures(struct mwConversation *conv) { - PurpleConversation *gconv; + PurpleIMConversation *im; PurpleConnection *gc; - gconv = convo_get_gconv(conv); - if(! gconv) return; + im = convo_get_im(conv); + if(! im) return; - gc = purple_conversation_get_connection(gconv); + gc = purple_conversation_get_connection(PURPLE_CONVERSATION(im)); if(! gc) return; - purple_conversation_set_features(gconv, purple_connection_get_flags(gc)); + purple_conversation_set_features(PURPLE_CONVERSATION(im), + purple_connection_get_flags(gc)); } @@ -2516,29 +2527,29 @@ static void convo_nofeatures(struct mwConversation *conv) { to inform the purple conversation of what features to offer the user */ static void convo_features(struct mwConversation *conv) { - PurpleConversation *gconv; + PurpleIMConversation *im; PurpleConnectionFlags feat; - gconv = convo_get_gconv(conv); - if(! gconv) return; + im = convo_get_im(conv); + if(! im) return; - feat = purple_conversation_get_features(gconv); + feat = purple_conversation_get_features(PURPLE_CONVERSATION(im)); if(mwConversation_isOpen(conv)) { if(mwConversation_supports(conv, mwImSend_HTML)) { - feat |= PURPLE_CONNECTION_HTML; + feat |= PURPLE_CONNECTION_FLAG_HTML; } else { - feat &= ~PURPLE_CONNECTION_HTML; + feat &= ~PURPLE_CONNECTION_FLAG_HTML; } if(mwConversation_supports(conv, mwImSend_MIME)) { - feat &= ~PURPLE_CONNECTION_NO_IMAGES; + feat &= ~PURPLE_CONNECTION_FLAG_NO_IMAGES; } else { - feat |= PURPLE_CONNECTION_NO_IMAGES; + feat |= PURPLE_CONNECTION_FLAG_NO_IMAGES; } DEBUG_INFO("conversation features set to 0x%04x\n", feat); - purple_conversation_set_features(gconv, feat); + purple_conversation_set_features(PURPLE_CONVERSATION(im), feat); } else { convo_nofeatures(conv); @@ -2566,7 +2577,7 @@ static void mw_conversation_opened(struct mwConversation *conv) { if(cd) { convo_queue_send(conv); - if(! convo_get_gconv(conv)) { + if(! convo_get_im(conv)) { mwConversation_free(conv); return; } @@ -2580,7 +2591,7 @@ static void mw_conversation_opened(struct mwConversation *conv) { struct mwLoginInfo *info; info = mwConversation_getTargetInfo(conv); - buddy = purple_find_buddy(acct, info->user_id); + buddy = purple_blist_find_buddy(acct, info->user_id); if(buddy) { purple_blist_node_set_int((PurpleBlistNode *) buddy, BUDDY_KEY_CLIENT, info->type); @@ -2652,7 +2663,7 @@ static void im_recv_typing(struct mwConversation *conv, idb = mwConversation_getTarget(conv); serv_got_typing(pd->gc, idb->user, 0, - typing? PURPLE_TYPING: PURPLE_NOT_TYPING); + typing? PURPLE_IM_TYPING: PURPLE_IM_NOT_TYPING); } @@ -2937,7 +2948,7 @@ static struct mwServiceIm *mw_srvc_im_new(struct mwSession *s) { } -/* The following helps us relate a mwPlace to a PurpleConvChat in the +/* The following helps us relate a mwPlace to a PurpleChatConversation in the various forms by which either may be indicated. Uses some of the similar macros from the conference service above */ @@ -2957,7 +2968,7 @@ place_find_by_id(struct mwPurplePluginData *pd, int id) { l = (GList *) mwServicePlace_getPlaces(srvc); for(; l; l = l->next) { struct mwPlace *p = l->data; - PurpleConvChat *h = PURPLE_CONV_CHAT(mwPlace_getClientData(p)); + PurpleChatConversation *h = mwPlace_getClientData(p); if(CHAT_TO_ID(h) == id) { place = p; @@ -2974,7 +2985,7 @@ static void mw_place_opened(struct mwPlace *place) { struct mwSession *session; struct mwPurplePluginData *pd; PurpleConnection *gc; - PurpleConversation *gconf; + PurpleChatConversation *gconf; GList *members, *l; @@ -2998,8 +3009,8 @@ static void mw_place_opened(struct mwPlace *place) { for(l = members; l; l = l->next) { struct mwIdBlock *idb = l->data; - purple_conv_chat_add_user(PURPLE_CONV_CHAT(gconf), idb->user, - NULL, PURPLE_CBFLAGS_NONE, FALSE); + purple_chat_conversation_add_user(gconf, idb->user, + NULL, PURPLE_CHAT_USER_NONE, FALSE); } g_list_free(members); } @@ -3030,7 +3041,7 @@ static void mw_place_closed(struct mwPlace *place, guint32 code) { static void mw_place_peerJoined(struct mwPlace *place, const struct mwIdBlock *peer) { - PurpleConversation *gconf; + PurpleChatConversation *gconf; const char *n = mwPlace_getName(place); @@ -3039,14 +3050,14 @@ static void mw_place_peerJoined(struct mwPlace *place, gconf = mwPlace_getClientData(place); g_return_if_fail(gconf != NULL); - purple_conv_chat_add_user(PURPLE_CONV_CHAT(gconf), peer->user, - NULL, PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(gconf, peer->user, + NULL, PURPLE_CHAT_USER_NONE, TRUE); } static void mw_place_peerParted(struct mwPlace *place, const struct mwIdBlock *peer) { - PurpleConversation *gconf; + PurpleChatConversation *gconf; const char *n = mwPlace_getName(place); @@ -3055,7 +3066,7 @@ static void mw_place_peerParted(struct mwPlace *place, gconf = mwPlace_getClientData(place); g_return_if_fail(gconf != NULL); - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(gconf), peer->user, NULL); + purple_chat_conversation_remove_user(gconf, peer->user, NULL); } @@ -3150,7 +3161,7 @@ static struct mwPurplePluginData *mwPurplePluginData_new(PurpleConnection *gc) { pd->srvc_resolve = mw_srvc_resolve_new(pd->session); pd->srvc_store = mw_srvc_store_new(pd->session); pd->group_list_map = g_hash_table_new(g_direct_hash, g_direct_equal); - pd->sock_buf = purple_circ_buffer_new(0); + pd->sock_buf = purple_circular_buffer_new(0); mwSession_addService(pd->session, MW_SERVICE(pd->srvc_aware)); mwSession_addService(pd->session, MW_SERVICE(pd->srvc_conf)); @@ -3197,7 +3208,7 @@ static void mwPurplePluginData_free(struct mwPurplePluginData *pd) { mwSession_free(pd->session); g_hash_table_destroy(pd->group_list_map); - purple_circ_buffer_destroy(pd->sock_buf); + g_object_unref(G_OBJECT(pd->sock_buf)); g_free(pd); } @@ -3330,19 +3341,19 @@ static GList *mw_prpl_status_types(PurpleAccount *acct) type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, MW_STATE_ACTIVE, NULL, TRUE, TRUE, FALSE, - MW_STATE_MESSAGE, _("Message"), purple_value_new(PURPLE_TYPE_STRING), + MW_STATE_MESSAGE, _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, type); type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, MW_STATE_AWAY, NULL, TRUE, TRUE, FALSE, - MW_STATE_MESSAGE, _("Message"), purple_value_new(PURPLE_TYPE_STRING), + MW_STATE_MESSAGE, _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, type); type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE, MW_STATE_BUSY, _("Do Not Disturb"), TRUE, TRUE, FALSE, - MW_STATE_MESSAGE, _("Message"), purple_value_new(PURPLE_TYPE_STRING), + MW_STATE_MESSAGE, _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, type); @@ -3533,7 +3544,7 @@ static void blist_menu_conf(PurpleBlistNode *node, gpointer data) { GList *l; g_return_if_fail(node != NULL); - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); acct = purple_buddy_get_account(buddy); g_return_if_fail(acct != NULL); @@ -3572,7 +3583,7 @@ static void blist_menu_announce(PurpleBlistNode *node, gpointer data) { GList *rcpt; g_return_if_fail(node != NULL); - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); acct = buddy->account; g_return_if_fail(acct != NULL); @@ -3601,7 +3612,7 @@ static GList *mw_prpl_blist_node_menu(PurpleBlistNode *node) { GList *l = NULL; PurpleMenuAction *act; - if(! PURPLE_BLIST_NODE_IS_BUDDY(node)) + if(! PURPLE_IS_BUDDY(node)) return l; l = g_list_append(l, NULL); @@ -3668,7 +3679,7 @@ static void mw_prpl_login(PurpleAccount *account) { pd = mwPurplePluginData_new(gc); /* while we do support images, the default is to not offer it */ - purple_connection_set_flags(gc, PURPLE_CONNECTION_NO_IMAGES); + purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_NO_IMAGES); user = g_strdup(purple_account_get_username(account)); @@ -4015,7 +4026,7 @@ static int mw_prpl_send_im(PurpleConnection *gc, static unsigned int mw_prpl_send_typing(PurpleConnection *gc, const char *name, - PurpleTypingState state) { + PurpleIMTypingState state) { struct mwPurplePluginData *pd; struct mwIdBlock who = { (char *) name, NULL }; @@ -4033,7 +4044,7 @@ static unsigned int mw_prpl_send_typing(PurpleConnection *gc, if(mwConversation_isOpen(conv)) { mwConversation_send(conv, mwImSend_TYPING, t); - } else if((state == PURPLE_TYPING) || (state == PURPLE_TYPED)) { + } else if((state == PURPLE_IM_TYPING) || (state == PURPLE_IM_TYPED)) { /* only open a channel for sending typing notification, not for when typing has stopped. There's no point in re-opening a channel just to tell someone that this side isn't typing. */ @@ -4123,7 +4134,7 @@ static void mw_prpl_get_info(PurpleConnection *gc, const char *who) { pd = purple_connection_get_protocol_data(gc); acct = purple_connection_get_account(gc); - b = purple_find_buddy(acct, who); + b = purple_blist_find_buddy(acct, who); user_info = purple_notify_user_info_new(); if(purple_str_has_prefix(who, "@E ")) { @@ -4266,14 +4277,14 @@ static void mw_prpl_set_idle(PurpleConnection *gc, int t) { static void notify_im(PurpleConnection *gc, GList *row, void *user_data) { PurpleAccount *acct; - PurpleConversation *conv; + PurpleIMConversation *im; char *id; acct = purple_connection_get_account(gc); id = g_list_nth_data(row, 1); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, id, acct); - if(! conv) conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, id); - purple_conversation_present(conv); + im = purple_conversations_find_im_with_account(id, acct); + if(! im) im = purple_im_conversation_new(acct, id); + purple_conversation_present(PURPLE_CONVERSATION(im)); } @@ -4385,7 +4396,7 @@ static void add_buddy_resolved(struct mwServiceResolve *srvc, } else { /* same person, set the server alias */ - purple_blist_server_alias_buddy(buddy, match->name); + purple_buddy_set_server_alias(buddy, match->name); purple_blist_node_set_string((PurpleBlistNode *) buddy, BUDDY_KEY_NAME, match->name); @@ -4516,7 +4527,7 @@ static void mw_prpl_add_buddies(PurpleConnection *gc, /* nab the saved server alias and stick it on the buddy */ fn = purple_blist_node_get_string((PurpleBlistNode *) b, BUDDY_KEY_NAME); - purple_blist_server_alias_buddy(b, fn); + purple_buddy_set_server_alias(b, fn); /* convert PurpleBuddy into a mwAwareIdBlock */ idb->type = mwAware_USER; @@ -4604,25 +4615,25 @@ static void mw_prpl_set_permit_deny(PurpleConnection *gc) { g_return_if_fail(session != NULL); switch(purple_account_get_privacy_type(acct)) { - case PURPLE_PRIVACY_DENY_USERS: - DEBUG_INFO("PURPLE_PRIVACY_DENY_USERS\n"); - privacy_fill(&privacy, acct->deny); + case PURPLE_ACCOUNT_PRIVACY_DENY_USERS: + DEBUG_INFO("PURPLE_ACCOUNT_PRIVACY_DENY_USERS\n"); + privacy_fill(&privacy, purple_account_privacy_get_denied(acct)); privacy.deny = TRUE; break; - case PURPLE_PRIVACY_ALLOW_ALL: - DEBUG_INFO("PURPLE_PRIVACY_ALLOW_ALL\n"); + case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL: + DEBUG_INFO("PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL\n"); privacy.deny = TRUE; break; - case PURPLE_PRIVACY_ALLOW_USERS: - DEBUG_INFO("PURPLE_PRIVACY_ALLOW_USERS\n"); - privacy_fill(&privacy, acct->permit); + case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: + DEBUG_INFO("PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS\n"); + privacy_fill(&privacy, purple_account_privacy_get_permitted(acct)); privacy.deny = FALSE; break; - case PURPLE_PRIVACY_DENY_ALL: - DEBUG_INFO("PURPLE_PRIVACY_DENY_ALL\n"); + case PURPLE_ACCOUNT_PRIVACY_DENY_ALL: + DEBUG_INFO("PURPLE_ACCOUNT_PRIVACY_DENY_ALL\n"); privacy.deny = FALSE; break; @@ -4876,12 +4887,12 @@ static void mw_prpl_group_buddy(PurpleConnection *gc, struct mwAwareList *list; /* add who to new_group's aware list */ - group = purple_find_group(new_group); + group = purple_blist_find_group(new_group); list = list_ensure(pd, group); mwAwareList_addAware(list, gl); /* remove who from old_group's aware list */ - group = purple_find_group(old_group); + group = purple_blist_find_group(old_group); list = list_ensure(pd, group); mwAwareList_removeAware(list, gl); @@ -4985,7 +4996,7 @@ static gboolean mw_prpl_can_receive_file(PurpleConnection *gc, acct = purple_connection_get_account(gc); g_return_val_if_fail(acct != NULL, FALSE); - return purple_find_buddy(acct, who) && + return purple_blist_find_buddy(acct, who) && user_supports(srvc, who, mwAttribute_FILE_TRANSFER); } @@ -5317,7 +5328,7 @@ static void remote_group_done(struct mwPurplePluginData *pd, acct = purple_connection_get_account(gc); /* collision checking */ - group = purple_find_group(name); + group = purple_blist_find_group(name); if(group) { const char *msgA; const char *msgB; diff --git a/libpurple/protocols/silc/buddy.c b/libpurple/protocols/silc/buddy.c index ad9dc050c2..ac169e9ea5 100644 --- a/libpurple/protocols/silc/buddy.c +++ b/libpurple/protocols/silc/buddy.c @@ -91,15 +91,15 @@ silcpurple_buddy_keyagr_cb(SilcClient client, /* Open IM window */ - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_IM, client_entry->nickname, sg->account); if (convo) { /* we don't have windows in the core anymore...but we may want to * provide some method for asking the UI to show the window - purple_conv_window_show(purple_conversation_get_window(convo)); + purple_conversation_window_show(purple_conversation_get_window(convo)); */ } else { - convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, sg->account, + convo = purple_im_conversation_new(sg->account, client_entry->nickname); } g_snprintf(tmp, sizeof(tmp), "%s [private key]", client_entry->nickname); @@ -342,7 +342,7 @@ silcpurple_buddy_resetkey(PurpleBlistNode *node, gpointer data) SilcPurple sg; SilcDList clients; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); b = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(b)); @@ -468,7 +468,7 @@ silcpurple_buddy_privkey_menu(PurpleBlistNode *node, gpointer data) PurpleBuddy *buddy; PurpleConnection *gc; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); @@ -597,7 +597,7 @@ silcpurple_buddy_getkey_menu(PurpleBlistNode *node, gpointer data) PurpleBuddy *buddy; PurpleConnection *gc; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); @@ -614,7 +614,7 @@ silcpurple_buddy_showkey(PurpleBlistNode *node, gpointer data) SilcPublicKey public_key; const char *pkfile; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); b = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(b)); @@ -686,7 +686,7 @@ void silcpurple_get_info(PurpleConnection *gc, const char *who) if (strlen(who) > 2 && who[0] == '*' && who[1] == '@') nick = who + 2; - b = purple_find_buddy(purple_connection_get_account(gc), nick); + b = purple_blist_find_buddy(purple_connection_get_account(gc), nick); if (b) { /* See if we have this buddy's public key. If we do use that to search the details. */ @@ -1413,7 +1413,7 @@ void silcpurple_send_buddylist(PurpleConnection *gc) account = purple_connection_get_account(gc); - for (buddies = purple_find_buddies(account, NULL); buddies; + for (buddies = purple_blist_find_buddies(account, NULL); buddies; buddies = g_slist_delete_link(buddies, buddies)) { PurpleBuddy *buddy = buddies->data; @@ -1621,7 +1621,7 @@ silcpurple_buddy_kill(PurpleBlistNode *node, gpointer data) PurpleConnection *gc; SilcPurple sg; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); b = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(b)); diff --git a/libpurple/protocols/silc/chat.c b/libpurple/protocols/silc/chat.c index 764f0fcf7f..9eff2c5dad 100644 --- a/libpurple/protocols/silc/chat.c +++ b/libpurple/protocols/silc/chat.c @@ -496,7 +496,7 @@ silcpurple_chat_chauth(PurpleBlistNode *node, gpointer data) PurpleConnection *gc; SilcPurple sg; - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); + g_return_if_fail(PURPLE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); @@ -583,7 +583,7 @@ silcpurple_chat_prv(PurpleBlistNode *node, gpointer data) PurpleRequestField *f; char tmp[512]; - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); + g_return_if_fail(PURPLE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); @@ -633,7 +633,7 @@ silcpurple_chat_permanent_reset(PurpleBlistNode *node, gpointer data) PurpleConnection *gc; SilcPurple sg; - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); + g_return_if_fail(PURPLE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); @@ -652,7 +652,7 @@ silcpurple_chat_permanent(PurpleBlistNode *node, gpointer data) SilcPurple sg; const char *channel; - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); + g_return_if_fail(PURPLE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); @@ -729,7 +729,7 @@ silcpurple_chat_ulimit(PurpleBlistNode *node, gpointer data) char *ch; char tmp[32]; - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); + g_return_if_fail(PURPLE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); @@ -764,7 +764,7 @@ silcpurple_chat_resettopic(PurpleBlistNode *node, gpointer data) PurpleConnection *gc; SilcPurple sg; - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); + g_return_if_fail(PURPLE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); @@ -782,7 +782,7 @@ silcpurple_chat_settopic(PurpleBlistNode *node, gpointer data) PurpleConnection *gc; SilcPurple sg; - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); + g_return_if_fail(PURPLE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); @@ -800,7 +800,7 @@ silcpurple_chat_resetprivate(PurpleBlistNode *node, gpointer data) PurpleConnection *gc; SilcPurple sg; - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); + g_return_if_fail(PURPLE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); @@ -818,7 +818,7 @@ silcpurple_chat_setprivate(PurpleBlistNode *node, gpointer data) PurpleConnection *gc; SilcPurple sg; - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); + g_return_if_fail(PURPLE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); @@ -836,7 +836,7 @@ silcpurple_chat_resetsecret(PurpleBlistNode *node, gpointer data) PurpleConnection *gc; SilcPurple sg; - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); + g_return_if_fail(PURPLE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); @@ -854,7 +854,7 @@ silcpurple_chat_setsecret(PurpleBlistNode *node, gpointer data) PurpleConnection *gc; SilcPurple sg; - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); + g_return_if_fail(PURPLE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); diff --git a/libpurple/protocols/silc/ops.c b/libpurple/protocols/silc/ops.c index c1b7337733..cfebb3c0b3 100644 --- a/libpurple/protocols/silc/ops.c +++ b/libpurple/protocols/silc/ops.c @@ -195,13 +195,13 @@ silcpurple_mime_message(SilcClient client, SilcClientConnection conn, for (l = sg->grps; l; l = l->next) if (((SilcPurplePrvgrp)l->data)->key == key) { prv = l->data; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, prv->channel, sg->account); break; } } if (channel && !convo) - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, channel->channel_name, sg->account); if (channel && !convo) goto out; @@ -214,7 +214,7 @@ silcpurple_mime_message(SilcClient client, SilcClientConnection conn, imgid); if (channel) - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), + serv_got_chat_in(gc, purple_chat_conversation_get_id(PURPLE_CONV_CHAT(convo)), sender->nickname, cflags, tmp, time(NULL)); else @@ -275,13 +275,13 @@ silc_channel_message(SilcClient client, SilcClientConnection conn, for (l = sg->grps; l; l = l->next) if (((SilcPurplePrvgrp)l->data)->key == key) { prv = l->data; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, prv->channel, sg->account); break; } } if (!convo) - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, channel->channel_name, sg->account); if (!convo) return; @@ -308,7 +308,7 @@ silc_channel_message(SilcClient client, SilcClientConnection conn, tmp = g_markup_escape_text(msg, -1); /* Send to Purple */ - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), + serv_got_chat_in(gc, purple_chat_conversation_get_id(PURPLE_CONV_CHAT(convo)), sender->nickname, 0, tmp, time(NULL)); g_free(tmp); g_free(msg); @@ -337,7 +337,7 @@ silc_channel_message(SilcClient client, SilcClientConnection conn, } tmp = g_markup_escape_text(msg, -1); /* Send to Purple */ - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), + serv_got_chat_in(gc, purple_chat_conversation_get_id(PURPLE_CONV_CHAT(convo)), sender->nickname, 0, tmp, time(NULL)); g_free(salvaged); g_free(tmp); @@ -366,7 +366,7 @@ silc_private_message(SilcClient client, SilcClientConnection conn, return; /* XXX - Should this be PURPLE_CONV_TYPE_IM? */ - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_ANY, sender->nickname, sg->account); if (flags & SILC_MESSAGE_FLAG_SIGNED && @@ -486,7 +486,7 @@ silc_notify(SilcClient client, SilcClientConnection conn, if (client_entry == conn->local_entry) break; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, channel->channel_name, sg->account); if (!convo) break; @@ -494,8 +494,8 @@ silc_notify(SilcClient client, SilcClientConnection conn, /* Join user to channel */ g_snprintf(buf, sizeof(buf), "%s@%s", client_entry->username, client_entry->hostname); - purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), - client_entry->nickname, buf, PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(PURPLE_CONV_CHAT(convo), + client_entry->nickname, buf, PURPLE_CHAT_USER_NONE, TRUE); break; @@ -503,13 +503,13 @@ silc_notify(SilcClient client, SilcClientConnection conn, client_entry = va_arg(va, SilcClientEntry); channel = va_arg(va, SilcChannelEntry); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, channel->channel_name, sg->account); if (!convo) break; /* Remove user from channel */ - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), + purple_chat_conversation_remove_user(PURPLE_CONV_CHAT(convo), client_entry->nickname, NULL); break; @@ -521,11 +521,11 @@ silc_notify(SilcClient client, SilcClientConnection conn, /* Remove from all channels */ silc_hash_table_list(client_entry->channels, &htl); while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, chu->channel->channel_name, sg->account); if (!convo) continue; - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), + purple_chat_conversation_remove_user(PURPLE_CONV_CHAT(convo), client_entry->nickname, tmp); } @@ -541,7 +541,7 @@ silc_notify(SilcClient client, SilcClientConnection conn, tmp = va_arg(va, char *); channel = va_arg(va, SilcChannelEntry); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, channel->channel_name, sg->account); if (!convo) break; @@ -558,30 +558,30 @@ silc_notify(SilcClient client, SilcClientConnection conn, g_snprintf(buf, sizeof(buf), _("%s has changed the topic of <I>%s</I> to: %s"), client_entry->nickname, channel->channel_name, tmp2); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, + purple_chat_conversation_write_message(PURPLE_CONV_CHAT(convo), client_entry->nickname, buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), + purple_chat_conversation_set_topic(PURPLE_CONV_CHAT(convo), client_entry->nickname, tmp); } else if (idtype == SILC_ID_SERVER) { server_entry = (SilcServerEntry)entry; g_snprintf(buf, sizeof(buf), _("%s has changed the topic of <I>%s</I> to: %s"), server_entry->server_name, channel->channel_name, tmp2); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), server_entry->server_name, + purple_chat_conversation_write_message(PURPLE_CONV_CHAT(convo), server_entry->server_name, buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), + purple_chat_conversation_set_topic(PURPLE_CONV_CHAT(convo), server_entry->server_name, tmp); } else if (idtype == SILC_ID_CHANNEL) { channel = (SilcChannelEntry)entry; g_snprintf(buf, sizeof(buf), _("%s has changed the topic of <I>%s</I> to: %s"), channel->channel_name, channel->channel_name, tmp2); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, + purple_chat_conversation_write_message(PURPLE_CONV_CHAT(convo), channel->channel_name, buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), + purple_chat_conversation_set_topic(PURPLE_CONV_CHAT(convo), channel->channel_name, tmp); } else { - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, tmp); + purple_chat_conversation_set_topic(PURPLE_CONV_CHAT(convo), NULL, tmp); } g_free(tmp2); @@ -600,12 +600,12 @@ silc_notify(SilcClient client, SilcClientConnection conn, /* Change nick on all channels */ silc_hash_table_list(client_entry->channels, &htl); while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, chu->channel->channel_name, sg->account); if (!convo) continue; - if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(convo), client_entry->nickname)) - purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo), + if (purple_chat_conversation_has_user(PURPLE_CONV_CHAT(convo), client_entry->nickname)) + purple_chat_conversation_rename_user(PURPLE_CONV_CHAT(convo), tmp, name); } silc_hash_table_list_reset(&htl); @@ -623,7 +623,7 @@ silc_notify(SilcClient client, SilcClientConnection conn, (void)va_arg(va, SilcDList); channel = va_arg(va, SilcChannelEntry); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, channel->channel_name, sg->account); if (!convo) break; @@ -647,20 +647,20 @@ silc_notify(SilcClient client, SilcClientConnection conn, _("<I>%s</I> removed all channel <I>%s</I> modes"), name, channel->channel_name); } - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, + purple_chat_conversation_write_message(PURPLE_CONV_CHAT(convo), channel->channel_name, buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); break; case SILC_NOTIFY_TYPE_CUMODE_CHANGE: { - PurpleConvChatBuddyFlags flags = PURPLE_CBFLAGS_NONE; + PurpleChatUserFlags flags = PURPLE_CHAT_USER_NONE; idtype = va_arg(va, int); entry = va_arg(va, void *); mode = va_arg(va, SilcUInt32); client_entry2 = va_arg(va, SilcClientEntry); channel = va_arg(va, SilcChannelEntry); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, channel->channel_name, sg->account); if (!convo) break; @@ -680,17 +680,17 @@ silc_notify(SilcClient client, SilcClientConnection conn, _("<I>%s</I> set <I>%s's</I> modes to: %s"), name, client_entry2->nickname, buf2); if (mode & SILC_CHANNEL_UMODE_CHANFO) - flags |= PURPLE_CBFLAGS_FOUNDER; + flags |= PURPLE_CHAT_USER_FOUNDER; if (mode & SILC_CHANNEL_UMODE_CHANOP) - flags |= PURPLE_CBFLAGS_OP; + flags |= PURPLE_CHAT_USER_OP; } else { g_snprintf(buf, sizeof(buf), _("<I>%s</I> removed all <I>%s's</I> modes"), name, client_entry2->nickname); } - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, + purple_chat_conversation_write_message(PURPLE_CONV_CHAT(convo), channel->channel_name, buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(convo), client_entry2->nickname, flags); + purple_chat_conversation_user_set_flags(PURPLE_CONV_CHAT(convo), client_entry2->nickname, flags); break; } @@ -706,7 +706,7 @@ silc_notify(SilcClient client, SilcClientConnection conn, client_entry2 = va_arg(va, SilcClientEntry); channel = va_arg(va, SilcChannelEntry); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, channel->channel_name, sg->account); if (!convo) break; @@ -717,14 +717,14 @@ silc_notify(SilcClient client, SilcClientConnection conn, _("You have been kicked off <I>%s</I> by <I>%s</I> (%s)"), channel->channel_name, client_entry2->nickname, tmp ? tmp : ""); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, + purple_chat_conversation_write_message(PURPLE_CONV_CHAT(convo), client_entry->nickname, buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo))); + serv_got_chat_left(gc, purple_chat_conversation_get_id(PURPLE_CONV_CHAT(convo))); } else { /* Remove user from channel */ g_snprintf(buf, sizeof(buf), _("Kicked by %s (%s)"), client_entry2->nickname, tmp ? tmp : ""); - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), + purple_chat_conversation_remove_user(PURPLE_CONV_CHAT(convo), client_entry->nickname, buf); } @@ -758,13 +758,13 @@ silc_notify(SilcClient client, SilcClientConnection conn, /* Remove us from all channels */ silc_hash_table_list(client_entry->channels, &htl); while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, chu->channel->channel_name, sg->account); if (!convo) continue; - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, + purple_chat_conversation_write_message(PURPLE_CONV_CHAT(convo), client_entry->nickname, buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo))); + serv_got_chat_left(gc, purple_chat_conversation_get_id(PURPLE_CONV_CHAT(convo))); } silc_hash_table_list_reset(&htl); @@ -789,11 +789,11 @@ silc_notify(SilcClient client, SilcClientConnection conn, /* Remove user from all channels */ silc_hash_table_list(client_entry->channels, &htl); while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, chu->channel->channel_name, sg->account); if (!convo) continue; - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), + purple_chat_conversation_remove_user(PURPLE_CONV_CHAT(convo), client_entry->nickname, tmp); } silc_hash_table_list_reset(&htl); @@ -813,11 +813,11 @@ silc_notify(SilcClient client, SilcClientConnection conn, /* Remove from all channels */ silc_hash_table_list(client_entry->channels, &htl); while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, chu->channel->channel_name, sg->account); if (!convo) continue; - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), + purple_chat_conversation_remove_user(PURPLE_CONV_CHAT(convo), client_entry->nickname, _("Server signoff")); } @@ -868,7 +868,7 @@ silc_notify(SilcClient client, SilcClientConnection conn, silc_free(pk); /* Find buddy by associated public key */ - for (buddies = purple_find_buddies(account, NULL); buddies; + for (buddies = purple_blist_find_buddies(account, NULL); buddies; buddies = g_slist_delete_link(buddies, buddies)) { b = buddies->data; f = purple_blist_node_get_string(PURPLE_BLIST_NODE(b), "public-key"); @@ -880,7 +880,7 @@ silc_notify(SilcClient client, SilcClientConnection conn, cont: if (!b) { /* Find buddy by nickname */ - b = purple_find_buddy(sg->account, client_entry->nickname); + b = purple_blist_find_buddy(sg->account, client_entry->nickname); if (!b) { purple_debug_warning("silc", "WATCH for %s, unknown buddy\n", client_entry->nickname); @@ -1116,20 +1116,20 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, /* Add channel to Purple */ channel->context = SILC_32_TO_PTR(++sg->channel_ids); serv_got_joined_chat(gc, sg->channel_ids, channel->channel_name); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, channel->channel_name, sg->account); if (!convo) return; /* Add all users to channel */ while (silc_hash_table_get(user_list, NULL, (void *)&chu)) { - PurpleConvChatBuddyFlags f = PURPLE_CBFLAGS_NONE; + PurpleChatUserFlags f = PURPLE_CHAT_USER_NONE; chu->context = SILC_32_TO_PTR(sg->channel_ids); if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) - f |= PURPLE_CBFLAGS_FOUNDER; + f |= PURPLE_CHAT_USER_FOUNDER; if (chu->mode & SILC_CHANNEL_UMODE_CHANOP) - f |= PURPLE_CBFLAGS_OP; + f |= PURPLE_CHAT_USER_OP; users = g_list_append(users, chu->client->nickname); flags = g_list_append(flags, GINT_TO_POINTER(f)); @@ -1148,16 +1148,16 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, } } - purple_conv_chat_add_users(PURPLE_CONV_CHAT(convo), users, NULL, flags, FALSE); + purple_chat_conversation_add_users(PURPLE_CONV_CHAT(convo), users, NULL, flags, FALSE); g_list_free(users); g_list_free(flags); /* Set topic */ if (topic) - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, topic); + purple_chat_conversation_set_topic(PURPLE_CONV_CHAT(convo), NULL, topic); /* Set nick */ - purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), conn->local_entry->nickname); + purple_chat_conversation_set_nick(PURPLE_CONV_CHAT(convo), conn->local_entry->nickname); } break; @@ -1412,7 +1412,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, channel = va_arg(ap, SilcChannelEntry); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, channel->channel_name, sg->account); if (!convo) { purple_debug_error("silc", "Got a topic for %s, which doesn't exist\n", @@ -1422,7 +1422,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, /* Set topic */ if (channel->topic) - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, channel->topic); + purple_chat_conversation_set_topic(PURPLE_CONV_CHAT(convo), NULL, channel->topic); } break; @@ -1445,15 +1445,15 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, /* Change nick on all channels */ silc_hash_table_list(local_entry->channels, &htl); while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + convo = purple_conversations_find_with_account(PURPLE_CONV_TYPE_CHAT, chu->channel->channel_name, sg->account); if (!convo) continue; - oldnick = purple_conv_chat_get_nick(PURPLE_CONV_CHAT(convo)); + oldnick = purple_chat_conversation_get_nick(PURPLE_CONV_CHAT(convo)); if (strcmp(oldnick, purple_normalize(purple_conversation_get_account(convo), newnick))) { - purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo), + purple_chat_conversation_rename_user(PURPLE_CONV_CHAT(convo), oldnick, newnick); - purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), newnick); + purple_chat_conversation_set_nick(PURPLE_CONV_CHAT(convo), newnick); } } silc_hash_table_list_reset(&htl); diff --git a/libpurple/protocols/silc/silc.c b/libpurple/protocols/silc/silc.c index a55bcf4923..40e6954244 100644 --- a/libpurple/protocols/silc/silc.c +++ b/libpurple/protocols/silc/silc.c @@ -260,7 +260,7 @@ silcpurple_connect_cb(SilcClient client, SilcClientConnection conn, sg->conn = conn; /* Connection created successfully */ - purple_connection_set_state(gc, PURPLE_CONNECTED); + purple_connection_set_state(gc, PURPLE_CONNECTION_CONNECTED); /* Send the server our buddy list */ silcpurple_send_buddylist(gc); @@ -1368,7 +1368,7 @@ silcpurple_send_im_resolved(SilcClient client, SilcDList list; gboolean free_list = FALSE; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, im->nick, + convo = purple_conversations_find_im_with_account(im->nick, sg->account); if (!convo) return; @@ -1405,7 +1405,7 @@ silcpurple_send_im_resolved(SilcClient client, buf->data, silc_buffer_len(buf)); silc_mime_partial_free(list); - purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname, + purple_im_conversation_write_message(PURPLE_CONV_IM(convo), conn->local_entry->nickname, im->message, 0, time(NULL)); goto out; } @@ -1414,7 +1414,7 @@ silcpurple_send_im_resolved(SilcClient client, /* Send the message */ silc_client_send_private_message(client, conn, client_entry, im->flags, sg->sha1hash, (unsigned char *)im->message, im->message_len); - purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname, + purple_im_conversation_write_message(PURPLE_CONV_IM(convo), conn->local_entry->nickname, im->message, 0, time(NULL)); goto out; @@ -1533,9 +1533,9 @@ silcpurple_send_im(PurpleConnection *gc, const char *who, const char *message, static GList *silcpurple_blist_node_menu(PurpleBlistNode *node) { /* split this single menu building function back into the two original: one for buddies and one for chats */ - if(PURPLE_BLIST_NODE_IS_CHAT(node)) { + if(PURPLE_IS_CHAT(node)) { return silcpurple_chat_menu((PurpleChat *) node); - } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { + } else if(PURPLE_IS_BUDDY(node)) { return silcpurple_buddy_menu((PurpleBuddy *) node); } else { g_return_val_if_reached(NULL); @@ -1557,11 +1557,11 @@ static PurpleCmdRet silcpurple_cmd_chat_part(PurpleConversation *conv, return PURPLE_CMD_RET_FAILED; if(args && args[0]) - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[0], + convo = purple_conversations_find_chat_with_account(args[0], purple_connection_get_account(gc)); if (convo != NULL) - id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)); + id = purple_chat_conversation_get_id(PURPLE_CONV_CHAT(convo)); if (id == 0) return PURPLE_CMD_RET_FAILED; @@ -1581,13 +1581,13 @@ static PurpleCmdRet silcpurple_cmd_chat_topic(PurpleConversation *conv, const char *topic; gc = purple_conversation_get_connection(conv); - id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)); + id = purple_chat_conversation_get_id(PURPLE_CONV_CHAT(conv)); if (gc == NULL || id == 0) return PURPLE_CMD_RET_FAILED; if (!args || !args[0]) { - topic = purple_conv_chat_get_topic (PURPLE_CONV_CHAT(conv)); + topic = purple_chat_conversation_get_topic (PURPLE_CONV_CHAT(conv)); if (topic) { tmp = g_markup_escape_text(topic, -1); tmp2 = purple_markup_linkify(tmp); @@ -1596,7 +1596,7 @@ static PurpleCmdRet silcpurple_cmd_chat_topic(PurpleConversation *conv, g_free(tmp2); } else buf = g_strdup(_("No topic is set")); - purple_conv_chat_write(PURPLE_CONV_CHAT(conv), purple_account_get_username(purple_connection_get_account(gc)), buf, + purple_chat_conversation_write_message(PURPLE_CONV_CHAT(conv), purple_account_get_username(purple_connection_get_account(gc)), buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); g_free(buf); @@ -1695,11 +1695,11 @@ static PurpleCmdRet silcpurple_cmd_query(PurpleConversation *conv, account = purple_connection_get_account(gc); - convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, args[0]); + convo = purple_im_conversation_new(account, args[0]); if (args[1]) { ret = silcpurple_send_im(gc, args[0], args[1], PURPLE_MESSAGE_SEND); - purple_conv_im_write(PURPLE_CONV_IM(convo), purple_connection_get_display_name(gc), + purple_im_conversation_write_message(PURPLE_CONV_IM(convo), purple_connection_get_display_name(gc), args[1], PURPLE_MESSAGE_SEND, time(NULL)); } @@ -1795,7 +1795,7 @@ static PurpleCmdRet silcpurple_cmd_cmode(PurpleConversation *conv, } else { msg = g_strdup_printf(_("no channel modes are set on %s"), chname); } - purple_conv_chat_write(PURPLE_CONV_CHAT(conv), "", + purple_chat_conversation_write_message(PURPLE_CONV_CHAT(conv), "", msg, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); g_free(msg); return PURPLE_CMD_RET_OK; diff --git a/libpurple/protocols/simple/simple.c b/libpurple/protocols/simple/simple.c index 10ff4be7da..8937990be9 100644 --- a/libpurple/protocols/simple/simple.c +++ b/libpurple/protocols/simple/simple.c @@ -27,12 +27,11 @@ #include "internal.h" #include "accountopt.h" -#include "blist.h" +#include "buddylist.h" #include "conversation.h" #include "dnsquery.h" #include "debug.h" #include "notify.h" -#include "privacy.h" #include "prpl.h" #include "plugin.h" #include "util.h" @@ -101,7 +100,7 @@ static void do_notifies(struct simple_account_data *sip) { static void simple_set_status(PurpleAccount *account, PurpleStatus *status) { PurpleConnection *gc = purple_account_get_connection(account); - PurpleStatusPrimitive primitive = purple_status_type_get_primitive(purple_status_get_type(status)); + PurpleStatusPrimitive primitive = purple_status_type_get_primitive(purple_status_get_status_type(status)); struct simple_account_data *sip = NULL; if (!purple_status_is_active(status)) @@ -200,7 +199,7 @@ static void simple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGro const char *name = purple_buddy_get_name(buddy); if(strncmp(name, "sip:", 4)) { gchar *buf = g_strdup_printf("sip:%s", name); - purple_blist_rename_buddy(buddy, buf); + purple_buddy_set_name(buddy, buf); g_free(buf); } if(!g_hash_table_lookup(sip->buddies, name)) { @@ -220,7 +219,7 @@ static void simple_get_buddies(PurpleConnection *gc) { purple_debug_info("simple", "simple_get_buddies\n"); account = purple_connection_get_account(gc); - buddies = purple_find_buddies(account, NULL); + buddies = purple_blist_find_buddies(account, NULL); while (buddies) { PurpleBuddy *buddy = buddies->data; simple_add_buddy(gc, buddy, purple_buddy_get_group(buddy), NULL); @@ -245,7 +244,7 @@ static GList *simple_status_types(PurpleAccount *acc) { type = purple_status_type_new_with_attrs( PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, type); @@ -274,7 +273,7 @@ static gchar *auth_header(struct simple_account_data *sip, if(auth->type == 1) { /* Digest */ sprintf(noncecount, "%08d", auth->nc++); - response = purple_cipher_http_digest_calculate_response( + response = purple_http_digest_calculate_response( "md5", method, target, NULL, NULL, auth->nonce, noncecount, NULL, auth->digest_session_key); purple_debug(PURPLE_DEBUG_MISC, "simple", "response %s\n", response); @@ -295,7 +294,7 @@ static gchar *auth_header(struct simple_account_data *sip, } sprintf(noncecount, "%08d", auth->nc++); - response = purple_cipher_http_digest_calculate_response( + response = purple_http_digest_calculate_response( "md5", method, target, NULL, NULL, auth->nonce, noncecount, NULL, auth->digest_session_key); purple_debug(PURPLE_DEBUG_MISC, "simple", "response %s\n", response); @@ -399,7 +398,7 @@ static void fill_auth(struct simple_account_data *sip, const gchar *hdr, struct auth->realm ? auth->realm : "(null)"); if(auth->realm) { - auth->digest_session_key = purple_cipher_http_digest_calculate_session_key( + auth->digest_session_key = purple_http_digest_calculate_session_key( "md5", authuser, auth->realm, sip->password, auth->nonce, NULL); auth->nc = 1; @@ -416,8 +415,9 @@ static void simple_canwrite_cb(gpointer data, gint source, PurpleInputCondition struct simple_account_data *sip = purple_connection_get_protocol_data(gc); gsize max_write; gssize written; + const gchar *output = NULL; - max_write = purple_circ_buffer_get_max_read(sip->txbuf); + max_write = purple_circular_buffer_get_max_read(sip->txbuf); if(max_write == 0) { purple_input_remove(sip->tx_handler); @@ -425,7 +425,9 @@ static void simple_canwrite_cb(gpointer data, gint source, PurpleInputCondition return; } - written = write(sip->fd, sip->txbuf->outptr, max_write); + output = purple_circular_buffer_get_output(sip->txbuf); + + written = write(sip->fd, output, max_write); if(written < 0 && errno == EAGAIN) written = 0; @@ -439,7 +441,7 @@ static void simple_canwrite_cb(gpointer data, gint source, PurpleInputCondition return; } - purple_circ_buffer_mark_read(sip->txbuf, written); + purple_circular_buffer_mark_read(sip->txbuf, written); } static void simple_input_cb(gpointer data, gint source, PurpleInputCondition cond); @@ -465,7 +467,7 @@ static void send_later_cb(gpointer data, gint source, const gchar *error_message simple_canwrite_cb(gc, sip->fd, PURPLE_INPUT_WRITE); /* If there is more to write now, we need to register a handler */ - if(sip->txbuf->bufused > 0) + if(purple_circular_buffer_get_used(sip->txbuf) > 0) sip->tx_handler = purple_input_add(sip->fd, PURPLE_INPUT_WRITE, simple_canwrite_cb, gc); @@ -485,10 +487,10 @@ static void sendlater(PurpleConnection *gc, const char *buf) { sip->connecting = TRUE; } - if(purple_circ_buffer_get_max_read(sip->txbuf) > 0) - purple_circ_buffer_append(sip->txbuf, "\r\n", 2); + if(purple_circular_buffer_get_max_read(sip->txbuf) > 0) + purple_circular_buffer_append(sip->txbuf, "\r\n", 2); - purple_circ_buffer_append(sip->txbuf, buf, strlen(buf)); + purple_circular_buffer_append(sip->txbuf, buf, strlen(buf)); } static void sendout_pkt(PurpleConnection *gc, const char *buf) { @@ -529,10 +531,10 @@ static void sendout_pkt(PurpleConnection *gc, const char *buf) { /* XXX: is it OK to do this? You might get part of a request sent with part of another. */ - if(sip->txbuf->bufused > 0) - purple_circ_buffer_append(sip->txbuf, "\r\n", 2); + if(purple_circular_buffer_get_used(sip->txbuf) > 0) + purple_circular_buffer_append(sip->txbuf, "\r\n", 2); - purple_circ_buffer_append(sip->txbuf, buf + ret, + purple_circular_buffer_append(sip->txbuf, buf + ret, writelen - ret); } } @@ -889,13 +891,13 @@ static gboolean simple_add_lcs_contacts(struct simple_account_data *sip, struct if ((group = xmlnode_get_child(isc, "group"))) { name_group = xmlnode_get_attrib(group, "name"); purple_debug_info("simple", "name_group->%s\n", name_group); - g = purple_find_group(name_group); + g = purple_blist_find_group(name_group); if(!g) g = purple_group_new(name_group); } if (!g) { - g = purple_find_group("Buddies"); + g = purple_blist_find_group("Buddies"); if(!g) g = purple_group_new("Buddies"); } @@ -911,14 +913,14 @@ static gboolean simple_add_lcs_contacts(struct simple_account_data *sip, struct buddy_name = g_strdup_printf("sip:%s", uri); - b = purple_find_buddy(sip->account, buddy_name); + b = purple_blist_find_buddy(sip->account, buddy_name); if(!b){ b = purple_buddy_new(sip->account, buddy_name, uri); } g_free(buddy_name); purple_blist_add_buddy(b, NULL, g, NULL); - purple_blist_alias_buddy(b, uri); + purple_buddy_set_local_alias(b, uri); bs = g_new0(struct simple_buddy, 1); bs->name = g_strdup(purple_buddy_get_name(b)); g_hash_table_insert(sip->buddies, bs->name, bs); @@ -1076,7 +1078,7 @@ static void process_incoming_message(struct simple_account_data *sip, struct sip statedata = xmlnode_get_data(state); if(statedata) { if(strstr(statedata, "active")) - serv_got_typing(sip->gc, from, 0, PURPLE_TYPING); + serv_got_typing(sip->gc, from, 0, PURPLE_IM_TYPING); else serv_got_typing_stopped(sip->gc, from); @@ -1105,7 +1107,7 @@ gboolean process_register_response(struct simple_account_data *sip, struct sipms } } sip->registerstatus = SIMPLE_REGISTER_COMPLETE; - purple_connection_set_state(sip->gc, PURPLE_CONNECTED); + purple_connection_set_state(sip->gc, PURPLE_CONNECTION_CONNECTED); /* get buddies from blist */ simple_get_buddies(sip->gc); @@ -1285,7 +1287,7 @@ static void process_incoming_notify(struct simple_account_data *sip, struct sipm send_sip_response(sip->gc, msg, 200, "OK", NULL); } -static unsigned int simple_typing(PurpleConnection *gc, const char *name, PurpleTypingState state) { +static unsigned int simple_typing(PurpleConnection *gc, const char *name, PurpleIMTypingState state) { struct simple_account_data *sip = purple_connection_get_protocol_data(gc); gchar *xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" @@ -1297,11 +1299,11 @@ static unsigned int simple_typing(PurpleConnection *gc, const char *name, Purple "<refresh>60</refresh>\n" "</isComposing>"; gchar *recv = g_strdup(name); - if(state == PURPLE_TYPING) { + if(state == PURPLE_IM_TYPING) { gchar *msg = g_strdup_printf(xml, "active"); simple_send_message(sip, recv, msg, "application/im-iscomposing+xml"); g_free(msg); - } else /* TODO: Only if (state == PURPLE_TYPED) ? */ { + } else /* TODO: Only if (state == PURPLE_IM_TYPED) ? */ { gchar *msg = g_strdup_printf(xml, "idle"); simple_send_message(sip, recv, msg, "application/im-iscomposing+xml"); g_free(msg); @@ -1309,7 +1311,7 @@ static unsigned int simple_typing(PurpleConnection *gc, const char *name, Purple g_free(recv); /* * TODO: Is this right? It will cause the core to call - * serv_send_typing(gc, who, PURPLE_TYPING) once every second + * serv_send_typing(gc, who, PURPLE_IM_TYPING) once every second * until the user stops typing. If that's not desired, * then return 0 instead. */ @@ -1452,7 +1454,7 @@ static void process_incoming_subscribe(struct simple_account_data *sip, struct s if(!watcher) { /* new subscription */ const gchar *acceptheader = sipmsg_find_header(msg, "Accept"); gboolean needsxpidf = FALSE; - if(!purple_privacy_check(sip->account, from)) { + if(!purple_account_privacy_check(sip->account, from)) { send_sip_response(sip->gc, msg, 202, "Ok", NULL); goto privend; } @@ -1941,7 +1943,7 @@ static void simple_login(PurpleAccount *account) sip->udp = purple_account_get_bool(account, "udp", FALSE); /* TODO: is there a good default grow size? */ if(!sip->udp) - sip->txbuf = purple_circ_buffer_new(0); + sip->txbuf = purple_circular_buffer_new(0); userserver = g_strsplit(username, "@", 2); if (userserver[1] == NULL || userserver[1][0] == '\0') { @@ -2037,7 +2039,7 @@ static void simple_close(PurpleConnection *gc) transactions_remove(sip, sip->transactions->data); g_free(sip->publish_etag); if (sip->txbuf) - purple_circ_buffer_destroy(sip->txbuf); + g_object_unref(G_OBJECT(sip->txbuf)); g_free(sip->realhostname); g_free(sip); diff --git a/libpurple/protocols/simple/simple.h b/libpurple/protocols/simple/simple.h index 8f15e4d792..caffe2fcd4 100644 --- a/libpurple/protocols/simple/simple.h +++ b/libpurple/protocols/simple/simple.h @@ -27,7 +27,7 @@ #include <time.h> #include "cipher.h" -#include "circbuffer.h" +#include "circularbuffer.h" #include "dnsquery.h" #include "dnssrv.h" #include "network.h" @@ -101,7 +101,7 @@ struct simple_account_data { guint resendtimeout; gboolean connecting; PurpleAccount *account; - PurpleCircBuffer *txbuf; + PurpleCircularBuffer *txbuf; guint tx_handler; gchar *regcallid; GSList *transactions; diff --git a/libpurple/protocols/simple/sipmsg.c b/libpurple/protocols/simple/sipmsg.c index 51411de2f0..1ae47fa5ff 100644 --- a/libpurple/protocols/simple/sipmsg.c +++ b/libpurple/protocols/simple/sipmsg.c @@ -23,7 +23,7 @@ #include "internal.h" #include "accountopt.h" -#include "blist.h" +#include "buddylist.h" #include "conversation.h" #include "debug.h" #include "notify.h" diff --git a/libpurple/protocols/yahoo/libyahoo.c b/libpurple/protocols/yahoo/libyahoo.c index 5c58ad072c..7424584e2a 100644 --- a/libpurple/protocols/yahoo/libyahoo.c +++ b/libpurple/protocols/yahoo/libyahoo.c @@ -112,16 +112,16 @@ static gboolean yahoo_uri_handler(const char *proto, const char *cmd, GHashTable if (sname) { char *message = g_hash_table_lookup(params, "m"); - PurpleConversation *conv = purple_find_conversation_with_account( - PURPLE_CONV_TYPE_IM, sname, acct); - if (conv == NULL) - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, sname); - purple_conversation_present(conv); + PurpleIMConversation *im = purple_conversations_find_im_with_account( + sname, acct); + if (im == NULL) + im = purple_im_conversation_new(acct, sname); + purple_conversation_present(PURPLE_CONVERSATION(im)); if (message) { /* Spaces are encoded as '+' */ g_strdelimit(message, "+", ' '); - purple_conv_send_confirm(conv, message); + purple_conversation_send_confirm(PURPLE_CONVERSATION(im), message); } } /* else diff --git a/libpurple/protocols/yahoo/libymsg.c b/libpurple/protocols/yahoo/libymsg.c index 74bc7b97fc..8cc96c8ec1 100644 --- a/libpurple/protocols/yahoo/libymsg.c +++ b/libpurple/protocols/yahoo/libymsg.c @@ -25,15 +25,14 @@ #include "account.h" #include "accountopt.h" -#include "blist.h" -#include "cipher.h" +#include "buddylist.h" +#include "ciphers/md5hash.h" #include "cmds.h" #include "core.h" #include "debug.h" #include "http.h" #include "network.h" #include "notify.h" -#include "privacy.h" #include "prpl.h" #include "proxy.h" #include "request.h" @@ -80,7 +79,7 @@ static void yahoo_update_status(PurpleConnection *gc, const char *name, YahooFri { char *status = NULL; - if (!gc || !name || !f || !purple_find_buddy(purple_connection_get_account(gc), name)) + if (!gc || !name || !f || !purple_blist_find_buddy(purple_connection_get_account(gc), name)) return; switch (f->status) { @@ -343,7 +342,7 @@ static void yahoo_process_status(PurpleConnection *gc, struct yahoo_packet *pkt) if (!name) break; - b = purple_find_buddy(purple_connection_get_account(gc), name); + b = purple_blist_find_buddy(purple_connection_get_account(gc), name); if (!cksum || (cksum == -1)) { if (f) @@ -413,7 +412,7 @@ static void yahoo_do_group_check(PurpleAccount *account, GHashTable *ht, const c if (g_hash_table_lookup_extended(ht, name, (gpointer *)&oname, (gpointer *)&list)) g_hash_table_steal(ht, oname); else - list = purple_find_buddies(account, name); + list = purple_blist_find_buddies(account, name); for (i = list; i; i = i->next) { b = i->data; @@ -430,7 +429,7 @@ static void yahoo_do_group_check(PurpleAccount *account, GHashTable *ht, const c if (!onlist) { purple_debug_misc("yahoo", "Uhoh, %s isn't on the list (or not in this group), adding him to group %s.\n", name, group); - if (!(g = purple_find_group(group))) { + if (!(g = purple_blist_find_group(group))) { g = purple_group_new(group); purple_blist_add_group(g, NULL); } @@ -553,10 +552,10 @@ static void yahoo_process_list_15(PurpleConnection *gc, struct yahoo_packet *pkt if (yd->current_list15_grp) { /* This buddy is in a group */ f = yahoo_friend_find_or_new(gc, norm_bud); - if (!purple_find_buddy(account, norm_bud)) { + if (!purple_blist_find_buddy(account, norm_bud)) { PurpleBuddy *b; PurpleGroup *g; - if (!(g = purple_find_group(yd->current_list15_grp))) { + if (!(g = purple_blist_find_group(yd->current_list15_grp))) { g = purple_group_new(yd->current_list15_grp); purple_blist_add_group(g, NULL); } @@ -580,7 +579,7 @@ static void yahoo_process_list_15(PurpleConnection *gc, struct yahoo_packet *pkt } else { /* This buddy is on the ignore list (and therefore in no group) */ purple_debug_info("yahoo", "%s adding %s to the deny list because of the ignore list / no group was found\n", purple_account_get_username(account), norm_bud); - purple_privacy_deny_add(account, norm_bud, 1); + purple_account_privacy_deny_add(account, norm_bud, 1); } g_free(norm_bud); @@ -626,7 +625,7 @@ static void yahoo_process_list_15(PurpleConnection *gc, struct yahoo_packet *pkt purple_connection_set_display_name(gc, purple_normalize(account, purple_account_get_username(account))); yd->logged_in = TRUE; purple_debug_info("yahoo","Authentication: Connection established\n"); - purple_connection_set_state(gc, PURPLE_CONNECTED); + purple_connection_set_state(gc, PURPLE_CONNECTION_CONNECTED); if (yd->picture_upload_todo) { yahoo_buddy_icon_upload(gc, yd->picture_upload_todo); yd->picture_upload_todo = NULL; @@ -708,10 +707,10 @@ static void yahoo_process_list(PurpleConnection *gc, struct yahoo_packet *pkt) norm_bud = g_strdup(purple_normalize(account, *bud)); f = yahoo_friend_find_or_new(gc, norm_bud); - if (!purple_find_buddy(account, norm_bud)) { + if (!purple_blist_find_buddy(account, norm_bud)) { PurpleBuddy *b; PurpleGroup *g; - if (!(g = purple_find_group(grp))) { + if (!(g = purple_blist_find_group(grp))) { g = purple_group_new(grp); purple_blist_add_group(g, NULL); } @@ -743,7 +742,7 @@ static void yahoo_process_list(PurpleConnection *gc, struct yahoo_packet *pkt) for (bud = buddies; bud && *bud; bud++) { /* The server is already ignoring the user */ got_serv_list = TRUE; - purple_privacy_deny_add(account, *bud, 1); + purple_account_privacy_deny_add(account, *bud, 1); } g_strfreev(buddies); @@ -752,12 +751,12 @@ static void yahoo_process_list(PurpleConnection *gc, struct yahoo_packet *pkt) } if (got_serv_list && - ((purple_account_get_privacy_type(account) != PURPLE_PRIVACY_ALLOW_BUDDYLIST) && - (purple_account_get_privacy_type(account) != PURPLE_PRIVACY_DENY_ALL) && - (purple_account_get_privacy_type(account) != PURPLE_PRIVACY_ALLOW_USERS))) + ((purple_account_get_privacy_type(account) != PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST) && + (purple_account_get_privacy_type(account) != PURPLE_ACCOUNT_PRIVACY_DENY_ALL) && + (purple_account_get_privacy_type(account) != PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS))) { - purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS); - purple_debug_info("yahoo", "%s privacy defaulting to PURPLE_PRIVACY_DENY_USERS.\n", + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_DENY_USERS); + purple_debug_info("yahoo", "%s privacy defaulting to PURPLE_ACCOUNT_PRIVACY_DENY_USERS.\n", purple_account_get_username(account)); } @@ -825,7 +824,7 @@ static void yahoo_process_notify(PurpleConnection *gc, struct yahoo_packet *pkt, } if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING")) - && (purple_privacy_check(account, from))) + && (purple_account_privacy_check(account, from))) { char *fed_from = from; switch (fed) { @@ -847,7 +846,7 @@ static void yahoo_process_notify(PurpleConnection *gc, struct yahoo_packet *pkt, } if (stat && *stat == '1') - serv_got_typing(gc, fed_from, 0, PURPLE_TYPING); + serv_got_typing(gc, fed_from, 0, PURPLE_IM_TYPING); else serv_got_typing_stopped(gc, fed_from); @@ -855,7 +854,7 @@ static void yahoo_process_notify(PurpleConnection *gc, struct yahoo_packet *pkt, g_free(fed_from); } else if (!g_ascii_strncasecmp(msg, "GAME", strlen("GAME"))) { - PurpleBuddy *bud = purple_find_buddy(account, from); + PurpleBuddy *bud = purple_blist_find_buddy(account, from); if (!bud) { purple_debug_warning("yahoo", @@ -874,9 +873,9 @@ static void yahoo_process_notify(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_update_status(gc, from, f); } } else if (!g_ascii_strncasecmp(msg, "WEBCAMINVITE", strlen("WEBCAMINVITE"))) { - PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, account); + PurpleIMConversation *im = purple_conversations_find_im_with_account(from, account); char *buf = g_strdup_printf(_("%s has sent you a webcam invite, which is not yet supported."), from); - purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, time(NULL)); + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, time(NULL)); g_free(buf); } } @@ -933,11 +932,11 @@ static void yahoo_process_sms_message(PurpleConnection *gc, struct yahoo_packet if( (pkt->status == -1) || (pkt->status == YAHOO_STATUS_DISCONNECTED) ) { if (server_msg) { - PurpleConversation *c; - c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms->from, account); - if (c == NULL) - c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sms->from); - purple_conversation_write(c, NULL, server_msg, PURPLE_MESSAGE_SYSTEM, time(NULL)); + PurpleIMConversation *im; + im = purple_conversations_find_im_with_account(sms->from, account); + if (im == NULL) + im = purple_im_conversation_new(account, sms->from); + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, server_msg, PURPLE_MESSAGE_SYSTEM, time(NULL)); } else purple_notify_error(gc, NULL, _("Your SMS was not delivered"), NULL); @@ -1049,7 +1048,7 @@ static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt { PurpleWhiteboard *wb; - if (!purple_privacy_check(account, im->from)) { + if (!purple_account_privacy_check(account, im->from)) { purple_debug_info("yahoo", "Doodle request from %s dropped.\n", im->from); g_free(im->fed_from); @@ -1095,7 +1094,7 @@ static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt continue; } - if (!purple_privacy_check(account, im->fed_from)) { + if (!purple_account_privacy_check(account, im->fed_from)) { purple_debug_info("yahoo", "Message from %s dropped.\n", im->fed_from); return; } @@ -1414,7 +1413,7 @@ static void yahoo_buddy_auth_req_15(PurpleConnection *gc, struct yahoo_packet *p if (add_req->id && add_req->who) { char *alias = NULL, *dec_msg = NULL; - if (!purple_privacy_check(account, add_req->who)) + if (!purple_account_privacy_check(account, add_req->who)) { purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n", add_req->who); @@ -1437,7 +1436,7 @@ static void yahoo_buddy_auth_req_15(PurpleConnection *gc, struct yahoo_packet *p */ purple_account_request_authorization(account, add_req->who, add_req->id, alias, dec_msg, - purple_find_buddy(account, add_req->who) != NULL, + purple_blist_find_buddy(account, add_req->who) != NULL, yahoo_buddy_add_authorize_cb, yahoo_buddy_add_deny_cb, add_req); @@ -1487,7 +1486,7 @@ static void yahoo_buddy_added_us(PurpleConnection *gc, struct yahoo_packet *pkt) if (add_req->id && add_req->who) { char *dec_msg = NULL; - if (!purple_privacy_check(account, add_req->who)) { + if (!purple_account_privacy_check(account, add_req->who)) { purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n", add_req->who); yahoo_buddy_add_deny_cb(NULL, add_req); @@ -1502,7 +1501,7 @@ static void yahoo_buddy_added_us(PurpleConnection *gc, struct yahoo_packet *pkt) */ purple_account_request_authorization(account, add_req->who, add_req->id, NULL, dec_msg, - purple_find_buddy(account,add_req->who) != NULL, + purple_blist_find_buddy(account,add_req->who) != NULL, yahoo_buddy_add_authorize_cb, yahoo_buddy_add_deny_cb, add_req); g_free(dec_msg); @@ -1697,8 +1696,7 @@ static void yahoo_auth16_stage3(PurpleConnection *gc, const char *crypt) YahooData *yd = purple_connection_get_protocol_data(gc); PurpleAccount *account = purple_connection_get_account(gc); const char *name = purple_normalize(account, purple_account_get_username(account)); - PurpleCipher *md5_cipher; - PurpleCipherContext *md5_ctx; + PurpleHash *md5_hash; guchar md5_digest[16]; gchar base64_string[25]; struct yahoo_packet *pkt; @@ -1707,10 +1705,9 @@ static void yahoo_auth16_stage3(PurpleConnection *gc, const char *crypt) g_return_if_fail(crypt != NULL); - md5_cipher = purple_ciphers_find_cipher("md5"); - md5_ctx = purple_cipher_context_new(md5_cipher, NULL); - purple_cipher_context_append(md5_ctx, (guchar *)crypt, strlen(crypt)); - purple_cipher_context_digest(md5_ctx, md5_digest, sizeof(md5_digest)); + md5_hash = purple_md5_hash_new(); + purple_hash_append(md5_hash, (guchar *)crypt, strlen(crypt)); + purple_hash_digest(md5_hash, md5_digest, sizeof(md5_digest)); to_y64(base64_string, md5_digest, 16); @@ -1748,7 +1745,7 @@ static void yahoo_auth16_stage3(PurpleConnection *gc, const char *crypt) yahoo_packet_hash_int(pkt, 192, yd->picture_checksum); yahoo_packet_send_and_free(pkt, yd); - purple_cipher_context_destroy(md5_ctx); + g_object_unref(md5_hash); } static void yahoo_auth16_stage2(PurpleHttpConnection *http_conn, @@ -2078,7 +2075,7 @@ static void ignore_buddy(PurpleBuddy *buddy) { static void keep_buddy(PurpleBuddy *b) { - purple_privacy_deny_remove(purple_buddy_get_account(b), + purple_account_privacy_deny_remove(purple_buddy_get_account(b), purple_buddy_get_name(b), 1); } @@ -2122,7 +2119,7 @@ static void yahoo_process_ignore(PurpleConnection *gc, struct yahoo_packet *pkt) who, (ignore ? "ignoring" : "unignoring")); if (ignore) { - b = purple_find_buddy(purple_connection_get_account(gc), who); + b = purple_blist_find_buddy(purple_connection_get_account(gc), who); g_snprintf(buf, sizeof(buf), _("You have tried to ignore %s, but the " "user is on your buddy list. Clicking \"Yes\" " "will remove and ignore the buddy."), who); @@ -2328,7 +2325,7 @@ static void yahoo_process_addbuddy(PurpleConnection *gc, struct yahoo_packet *pk decoded_group = yahoo_string_decode(gc, group, FALSE); buf = g_strdup_printf(_("Unable to add buddy %s to group %s to the server list on account %s."), who, decoded_group, purple_connection_get_display_name(gc)); - if (!purple_conv_present_error(who, purple_connection_get_account(gc), buf)) + if (!purple_conversation_present_error(who, purple_connection_get_account(gc), buf)) purple_notify_error(gc, NULL, _("Unable to add buddy to server list"), buf); g_free(buf); g_free(decoded_group); @@ -2930,7 +2927,7 @@ static void yahoo_process_audible(PurpleConnection *gc, struct yahoo_packet *pkt purple_debug_misc("yahoo", "Warning, nonutf8 audible, ignoring!\n"); return; } - if (!purple_privacy_check(account, who)) { + if (!purple_account_privacy_check(account, who)) { purple_debug_misc("yahoo", "Audible message from %s for %s dropped!\n", purple_account_get_username(account), who); return; @@ -3358,7 +3355,6 @@ yahoo_login_page_cb(PurpleHttpConnection *http_conn, char md5[33], *hashp = md5, *chal; int i; PurpleCipher *cipher; - PurpleCipherContext *context; guchar digest[16]; PurpleHttpRequest *req; @@ -3372,20 +3368,19 @@ yahoo_login_page_cb(PurpleHttpConnection *http_conn, got_data = purple_http_response_get_data(response, &len); hash = yahoo_login_page_hash(got_data, len); - cipher = purple_ciphers_find_cipher("md5"); - context = purple_cipher_context_new(cipher, NULL); + cipher = purple_md5_cipher_new(); - purple_cipher_context_append(context, (const guchar *)pass, strlen(pass)); - purple_cipher_context_digest(context, digest, sizeof(digest)); + purple_cipher_append(cipher, (const guchar *)pass, strlen(pass)); + purple_cipher_digest(cipher, digest, sizeof(digest)); for (i = 0; i < 16; ++i) { g_snprintf(hashp, 3, "%02x", digest[i]); hashp += 2; } chal = g_strconcat(md5, g_hash_table_lookup(hash, ".challenge"), NULL); - purple_cipher_context_reset(context, NULL); - purple_cipher_context_append(context, (const guchar *)chal, strlen(chal)); - purple_cipher_context_digest(context, digest, sizeof(digest)); + purple_cipher_reset(cipher); + purple_cipher_append(cipher, (const guchar *)chal, strlen(chal)); + purple_cipher_digest(cipher, digest, sizeof(digest)); hashp = md5; for (i = 0; i < 16; ++i) { g_snprintf(hashp, 3, "%02x", digest[i]); @@ -3395,9 +3390,9 @@ yahoo_login_page_cb(PurpleHttpConnection *http_conn, * I dunno why this is here and commented out.. but in case it's needed * I updated it.. - purple_cipher_context_reset(context, NULL); - purple_cipher_context_append(context, md5, strlen(md5)); - purple_cipher_context_digest(context, sizeof(digest), digest, NULL); + purple_cipher_reset(cipher); + purple_cipher_append(cipher, md5, strlen(md5)); + purple_cipher_digest(cipher, sizeof(digest), digest, NULL); hashp = md5; for (i = 0; i < 16; ++i) { g_snprintf(hashp, 3, "%02x", digest[i]); @@ -3412,7 +3407,7 @@ yahoo_login_page_cb(PurpleHttpConnection *http_conn, url = g_string_append(url, "&.hash=1&.md5=1"); g_hash_table_destroy(hash); - purple_cipher_context_destroy(context); + g_object_unref(cipher); req = purple_http_request_new(g_string_free(url, FALSE)); purple_http_request_set_max_redirects(req, 0); @@ -3550,7 +3545,7 @@ void yahoo_login(PurpleAccount *account) { PurpleStatus *status = purple_account_get_active_status(account); purple_connection_set_protocol_data(gc, yd); - purple_connection_set_flags(gc, PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC); + purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_HTML | PURPLE_CONNECTION_FLAG_NO_BGCOLOR | PURPLE_CONNECTION_FLAG_NO_URLDESC); purple_connection_update_progress(gc, _("Connecting"), 1, 2); @@ -3562,7 +3557,7 @@ void yahoo_login(PurpleAccount *account) { yd->fd = -1; yd->txhandler = 0; /* TODO: Is there a good grow size for the buffer? */ - yd->txbuf = purple_circ_buffer_new(0); + yd->txbuf = purple_circular_buffer_new(0); yd->http_reqs = purple_http_connection_set_new(); yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free); yd->imvironments = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); @@ -3605,11 +3600,11 @@ void yahoo_close(PurpleConnection *gc) { yd->http_reqs = NULL; for (l = yd->confs; l; l = l->next) { - PurpleConversation *conv = l->data; + PurpleChatConversation *conv = l->data; - yahoo_conf_leave(yd, purple_conversation_get_name(conv), + yahoo_conf_leave(yd, purple_conversation_get_name(PURPLE_CONVERSATION(conv)), purple_connection_get_display_name(gc), - purple_conv_chat_get_users(PURPLE_CONV_CHAT(conv))); + purple_chat_conversation_get_users(conv)); } g_slist_free(yd->confs); @@ -3653,7 +3648,7 @@ void yahoo_close(PurpleConnection *gc) { if (yd->txhandler) purple_input_remove(yd->txhandler); - purple_circ_buffer_destroy(yd->txbuf); + g_object_unref(G_OBJECT(yd->txbuf)); if (yd->fd >= 0) close(yd->fd); @@ -3759,7 +3754,7 @@ static void yahoo_initiate_conference(PurpleBlistNode *node, gpointer data) { YahooData *yd; int id; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); @@ -3799,7 +3794,7 @@ static void yahoo_game(PurpleBlistNode *node, gpointer data) { char url[256]; YahooFriend *f; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); @@ -3921,7 +3916,7 @@ static void yahoo_addbuddyfrommenu_cb(PurpleBlistNode *node, gpointer data) PurpleBuddy *buddy; PurpleConnection *gc; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); @@ -3935,7 +3930,7 @@ static void yahoo_chat_goto_menu(PurpleBlistNode *node, gpointer data) PurpleBuddy *buddy; PurpleConnection *gc; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); @@ -4086,7 +4081,7 @@ static GList *yahoo_buddy_menu(PurpleBuddy *buddy) GList *yahoo_blist_node_menu(PurpleBlistNode *node) { - if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if(PURPLE_IS_BUDDY(node)) { return yahoo_buddy_menu((PurpleBuddy *) node); } else { return NULL; @@ -4256,10 +4251,11 @@ static void yahoo_get_sms_carrier_cb(PurpleHttpConnection *http_conn, char *status = NULL; char *carrier = NULL; PurpleAccount *account = purple_connection_get_account(gc); - PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms_cb_data->who, account); + PurpleIMConversation *im = purple_conversations_find_im_with_account(sms_cb_data->who, account); if (!purple_http_response_is_successful(response)) { - purple_conversation_write(conv, NULL, _("Can't send SMS. Unable to obtain mobile carrier."), PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, + _("Can't send SMS. Unable to obtain mobile carrier."), PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(sms_cb_data->who); g_free(sms_cb_data->what); @@ -4288,7 +4284,7 @@ static void yahoo_get_sms_carrier_cb(PurpleHttpConnection *http_conn, } else { g_hash_table_insert(yd->sms_carrier, g_strdup_printf("+%s", mobile_no), g_strdup("Unknown")); - purple_conversation_write(conv, NULL, + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, _("Can't send SMS. Unknown mobile carrier."), PURPLE_MESSAGE_SYSTEM, time(NULL)); } @@ -4384,7 +4380,7 @@ int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, Purpl gchar *carrier = NULL; const char *alias = NULL; PurpleAccount *account = purple_connection_get_account(gc); - PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account); + PurpleIMConversation *im = purple_conversations_find_im_with_account(who, account); carrier = g_hash_table_lookup(yd->sms_carrier, who); if (!carrier) { @@ -4394,7 +4390,7 @@ int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, Purpl sms_cb_data->who = g_strdup(who); sms_cb_data->what = g_strdup(what); - purple_conversation_write(conv, NULL, _("Getting mobile carrier to send the SMS."), PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, _("Getting mobile carrier to send the SMS."), PURPLE_MESSAGE_SYSTEM, time(NULL)); yahoo_get_sms_carrier(gc, sms_cb_data); @@ -4403,14 +4399,14 @@ int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, Purpl return ret; } else if( strcmp(carrier,"Unknown") == 0 ) { - purple_conversation_write(conv, NULL, _("Can't send SMS. Unknown mobile carrier."), PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, _("Can't send SMS. Unknown mobile carrier."), PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(msg); g_free(msg2); return -1; } - alias = purple_account_get_alias(account); + alias = purple_account_get_private_alias(account); pkt = yahoo_packet_new(YAHOO_SERVICE_SMS_MSG, YAHOO_STATUS_AVAILABLE, yd->session_id); yahoo_packet_hash(pkt, "sssss", 1, purple_connection_get_display_name(gc), @@ -4503,7 +4499,7 @@ int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, Purpl return ret; } -unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state) +unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleIMTypingState state) { YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_p2p_data *p2p_data; @@ -4521,7 +4517,7 @@ unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypi /* check to see if p2p link exists, send through it */ if( (p2p_data = g_hash_table_lookup(yd->peers, who)) && !fed) { yahoo_packet_hash(pkt, "sssssis", 49, "TYPING", 1, purple_connection_get_display_name(gc), - 14, " ", 13, state == PURPLE_TYPING ? "1" : "0", + 14, " ", 13, state == PURPLE_IM_TYPING ? "1" : "0", 5, who, 11, p2p_data->session_id, 1002, "1"); /* To-do: key 15 to be sent in case of p2p */ yahoo_p2p_write_pkt(p2p_data->source, pkt); yahoo_packet_free(pkt); @@ -4542,7 +4538,7 @@ unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypi } yahoo_packet_hash(pkt, "ssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc), - 14, " ", 13, state == PURPLE_TYPING ? "1" : "0", + 14, " ", 13, state == PURPLE_IM_TYPING ? "1" : "0", 5, fed_who, 1002, "1"); if (fed) yahoo_packet_hash_int(pkt, 241, fed); @@ -4706,13 +4702,13 @@ GList *yahoo_status_types(PurpleAccount *account) type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, YAHOO_STATUS_TYPE_AVAILABLE, NULL, TRUE, TRUE, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, type); type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_AWAY, NULL, TRUE, TRUE, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, type); type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_BRB, _("Be Right Back"), TRUE); @@ -4721,7 +4717,7 @@ GList *yahoo_status_types(PurpleAccount *account) type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE, YAHOO_STATUS_TYPE_BUSY, _("Busy"), TRUE, TRUE, FALSE, "message", _("Message"), - purple_value_new(PURPLE_TYPE_STRING), NULL); + purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, type); type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_NOTATHOME, _("Not at Home"), TRUE); @@ -4806,7 +4802,7 @@ void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g, c return; fed_bname = bname = purple_buddy_get_name(buddy); - if (!purple_privacy_check(purple_connection_get_account(gc), bname)) + if (!purple_account_privacy_check(purple_connection_get_account(gc), bname)) return; fed = yahoo_get_federation_from_name(bname); @@ -4874,7 +4870,7 @@ void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g fed = f->fed; gname = purple_group_get_name(group); - buddies = purple_find_buddies(purple_connection_get_account(gc), bname); + buddies = purple_blist_find_buddies(purple_connection_get_account(gc), bname); for (l = buddies; l; l = l->next) { g = purple_buddy_get_group(l->data); if (purple_utf8_strcasecmp(gname, purple_group_get_name(g))) { @@ -4966,16 +4962,16 @@ void yahoo_set_permit_deny(PurpleConnection *gc) switch (purple_account_get_privacy_type(account)) { - case PURPLE_PRIVACY_ALLOW_ALL: - for (deny = account->deny; deny; deny = deny->next) + case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL: + for (deny = purple_account_privacy_get_denied(account); deny; deny = deny->next) yahoo_rem_deny(gc, deny->data); break; - case PURPLE_PRIVACY_ALLOW_BUDDYLIST: - case PURPLE_PRIVACY_ALLOW_USERS: - case PURPLE_PRIVACY_DENY_USERS: - case PURPLE_PRIVACY_DENY_ALL: - for (deny = account->deny; deny; deny = deny->next) + case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST: + case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: + case PURPLE_ACCOUNT_PRIVACY_DENY_USERS: + case PURPLE_ACCOUNT_PRIVACY_DENY_ALL: + for (deny = purple_account_privacy_get_denied(account); deny; deny = deny->next) yahoo_add_deny(gc, deny->data); break; } @@ -5106,16 +5102,16 @@ gboolean yahoo_offline_message(const PurpleBuddy *buddy) gboolean yahoo_send_attention(PurpleConnection *gc, const char *username, guint type) { - PurpleConversation *c; + PurpleIMConversation *im; - c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - username, purple_connection_get_account(gc)); + im = purple_conversations_find_im_with_account(username, + purple_connection_get_account(gc)); - g_return_val_if_fail(c != NULL, FALSE); + g_return_val_if_fail(im != NULL, FALSE); purple_debug_info("yahoo", "Sending <ding> on account %s to buddy %s.\n", - username, purple_conversation_get_name(c)); - purple_conv_im_send_with_flags(PURPLE_CONV_IM(c), "<ding>", PURPLE_MESSAGE_INVISIBLE); + username, purple_conversation_get_name(PURPLE_CONVERSATION(im))); + purple_conversation_send_with_flags(PURPLE_CONVERSATION(im), "<ding>", PURPLE_MESSAGE_INVISIBLE); return TRUE; } diff --git a/libpurple/protocols/yahoo/libymsg.h b/libpurple/protocols/yahoo/libymsg.h index 5f1fc9b17a..ba042b6d55 100644 --- a/libpurple/protocols/yahoo/libymsg.h +++ b/libpurple/protocols/yahoo/libymsg.h @@ -25,7 +25,7 @@ #ifndef _LIBYMSG_H_ #define _LIBYMSG_H_ -#include "circbuffer.h" +#include "circularbuffer.h" #include "cmds.h" #include "http.h" #include "prpl.h" @@ -189,7 +189,7 @@ typedef struct { guint inpa; guchar *rxqueue; int rxlen; - PurpleCircBuffer *txbuf; + PurpleCircularBuffer *txbuf; guint txhandler; GHashTable *friends; @@ -367,7 +367,7 @@ GList *yahoo_blist_node_menu(PurpleBlistNode *node); void yahoo_login(PurpleAccount *account); void yahoo_close(PurpleConnection *gc); int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags); -unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state); +unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleIMTypingState state); void yahoo_set_status(PurpleAccount *account, PurpleStatus *status); void yahoo_set_idle(PurpleConnection *gc, int idle); void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g, const char *message); diff --git a/libpurple/protocols/yahoo/yahoo_aliases.c b/libpurple/protocols/yahoo/yahoo_aliases.c index 91a91ae476..db9e53db26 100644 --- a/libpurple/protocols/yahoo/yahoo_aliases.c +++ b/libpurple/protocols/yahoo/yahoo_aliases.c @@ -26,7 +26,7 @@ #include "account.h" #include "accountopt.h" -#include "blist.h" +#include "buddylist.h" #include "debug.h" #include "http.h" #include "util.h" @@ -143,7 +143,7 @@ yahoo_fetch_aliases_cb(PurpleHttpConnection *http_conn, /* Find the local buddy that matches */ f = yahoo_friend_find(gc, yid); - b = purple_find_buddy(account, yid); + b = purple_blist_find_buddy(account, yid); /* If we don't find a matching buddy, ignore the alias !! */ if (f != NULL && b != NULL) { diff --git a/libpurple/protocols/yahoo/yahoo_aliases.h b/libpurple/protocols/yahoo/yahoo_aliases.h index 0eb7fef1b3..ef5cb78f77 100644 --- a/libpurple/protocols/yahoo/yahoo_aliases.h +++ b/libpurple/protocols/yahoo/yahoo_aliases.h @@ -26,7 +26,7 @@ #include "account.h" #include "accountopt.h" -#include "blist.h" +#include "buddylist.h" #include "debug.h" #include "util.h" #include "version.h" diff --git a/libpurple/protocols/yahoo/yahoo_doodle.c b/libpurple/protocols/yahoo/yahoo_doodle.c index ca64961c28..f1778bb491 100644 --- a/libpurple/protocols/yahoo/yahoo_doodle.c +++ b/libpurple/protocols/yahoo/yahoo_doodle.c @@ -28,12 +28,11 @@ #include "account.h" #include "accountopt.h" -#include "blist.h" +#include "buddylist.h" #include "cipher.h" #include "cmds.h" #include "debug.h" #include "notify.h" -#include "privacy.h" #include "prpl.h" #include "proxy.h" #include "request.h" @@ -94,7 +93,7 @@ PurpleCmdRet yahoo_doodle_purple_cmd_start(PurpleConversation *conv, const char /* Write a local message to this conversation showing that a request for a * Doodle session has been made */ - purple_conv_im_write(PURPLE_CONV_IM(conv), "", _("Sent Doodle request."), + purple_conversation_write_message(conv, "", _("Sent Doodle request."), PURPLE_MESSAGE_NICK | PURPLE_MESSAGE_RECV, time(NULL)); return PURPLE_CMD_RET_OK; diff --git a/libpurple/protocols/yahoo/yahoo_packet.c b/libpurple/protocols/yahoo/yahoo_packet.c index 605009a681..0e08b69de6 100644 --- a/libpurple/protocols/yahoo/yahoo_packet.c +++ b/libpurple/protocols/yahoo/yahoo_packet.c @@ -287,8 +287,9 @@ yahoo_packet_send_can_write(gpointer data, gint source, PurpleInputCondition con { YahooData *yd = data; int ret, writelen; + const gchar *output = NULL; - writelen = purple_circ_buffer_get_max_read(yd->txbuf); + writelen = purple_circular_buffer_get_max_read(yd->txbuf); if (writelen == 0) { purple_input_remove(yd->txhandler); @@ -296,7 +297,9 @@ yahoo_packet_send_can_write(gpointer data, gint source, PurpleInputCondition con return; } - ret = write(yd->fd, yd->txbuf->outptr, writelen); + output = purple_circular_buffer_get_output(yd->txbuf); + + ret = write(yd->fd, output, writelen); if (ret < 0 && errno == EAGAIN) return; @@ -307,7 +310,7 @@ yahoo_packet_send_can_write(gpointer data, gint source, PurpleInputCondition con return; } - purple_circ_buffer_mark_read(yd->txbuf, ret); + purple_circular_buffer_mark_read(yd->txbuf, ret); } @@ -374,7 +377,7 @@ int yahoo_packet_send(struct yahoo_packet *pkt, YahooData *yd) if (yd->txhandler == 0) yd->txhandler = purple_input_add(yd->fd, PURPLE_INPUT_WRITE, yahoo_packet_send_can_write, yd); - purple_circ_buffer_append(yd->txbuf, data + ret, len - ret); + purple_circular_buffer_append(yd->txbuf, data + ret, len - ret); } g_free(data); diff --git a/libpurple/protocols/yahoo/yahoo_picture.c b/libpurple/protocols/yahoo/yahoo_picture.c index 34ee19aa78..5c0336da41 100644 --- a/libpurple/protocols/yahoo/yahoo_picture.c +++ b/libpurple/protocols/yahoo/yahoo_picture.c @@ -25,10 +25,9 @@ #include "account.h" #include "accountopt.h" -#include "blist.h" +#include "buddylist.h" #include "debug.h" #include "http.h" -#include "privacy.h" #include "prpl.h" #include "proxy.h" #include "util.h" @@ -114,7 +113,7 @@ void yahoo_process_picture(PurpleConnection *gc, struct yahoo_packet *pkt) if (!who) return; - if (!purple_privacy_check(purple_connection_get_account(gc), who)) { + if (!purple_account_privacy_check(purple_connection_get_account(gc), who)) { purple_debug_info("yahoo", "Picture packet from %s dropped.\n", who); return; } @@ -160,7 +159,7 @@ void yahoo_process_picture_checksum(PurpleConnection *gc, struct yahoo_packet *p } if (who) { - PurpleBuddy *b = purple_find_buddy(purple_connection_get_account(gc), who); + PurpleBuddy *b = purple_blist_find_buddy(purple_connection_get_account(gc), who); const char *locksum = NULL; /* FIXME: Cleanup this strtol() stuff if possible. */ diff --git a/libpurple/protocols/yahoo/yahoo_profile.c b/libpurple/protocols/yahoo/yahoo_profile.c index cfb30737f3..82dc5e0775 100644 --- a/libpurple/protocols/yahoo/yahoo_profile.c +++ b/libpurple/protocols/yahoo/yahoo_profile.c @@ -696,11 +696,11 @@ static void yahoo_extract_user_info_text(PurpleNotifyUserInfo *user_info, YahooG PurpleBuddy *b; YahooFriend *f; - b = purple_find_buddy(purple_connection_get_account(info_data->gc), + b = purple_blist_find_buddy(purple_connection_get_account(info_data->gc), info_data->name); if (b) { - const char *balias = purple_buddy_get_local_buddy_alias(b); + const char *balias = purple_buddy_get_local_alias(b); if(balias && balias[0]) { purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), balias); } @@ -1196,7 +1196,7 @@ yahoo_got_photo(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, "or format that is not supported at this time."); } else if (profile_state == PROFILE_STATE_NOT_FOUND) { - PurpleBuddy *b = purple_find_buddy + PurpleBuddy *b = purple_blist_find_buddy (purple_connection_get_account(info_data->gc), info_data->name); YahooFriend *f = NULL; diff --git a/libpurple/protocols/yahoo/yahoochat.c b/libpurple/protocols/yahoo/yahoochat.c index ee695b357f..be7a80a7db 100644 --- a/libpurple/protocols/yahoo/yahoochat.c +++ b/libpurple/protocols/yahoo/yahoochat.c @@ -34,7 +34,6 @@ #include "debug.h" #include "http.h" -#include "privacy.h" #include "prpl.h" #include "conversation.h" @@ -78,26 +77,26 @@ static void yahoo_chat_online(PurpleConnection *gc) } /* this is slow, and different from the purple_* version in that it (hopefully) won't add a user twice */ -void yahoo_chat_add_users(PurpleConvChat *chat, GList *newusers) +void yahoo_chat_add_users(PurpleChatConversation *chat, GList *newusers) { GList *i; for (i = newusers; i; i = i->next) { - if (purple_conv_chat_find_user(chat, i->data)) + if (purple_chat_conversation_has_user(chat, i->data)) continue; - purple_conv_chat_add_user(chat, i->data, NULL, PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(chat, i->data, NULL, PURPLE_CHAT_USER_NONE, TRUE); } } -void yahoo_chat_add_user(PurpleConvChat *chat, const char *user, const char *reason) +void yahoo_chat_add_user(PurpleChatConversation *chat, const char *user, const char *reason) { - if (purple_conv_chat_find_user(chat, user)) + if (purple_chat_conversation_has_user(chat, user)) return; - purple_conv_chat_add_user(chat, user, reason, PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(chat, user, reason, PURPLE_CHAT_USER_NONE, TRUE); } -static PurpleConversation *yahoo_find_conference(PurpleConnection *gc, const char *name) +static PurpleChatConversation *yahoo_find_conference(PurpleConnection *gc, const char *name) { YahooData *yd; GSList *l; @@ -105,8 +104,8 @@ static PurpleConversation *yahoo_find_conference(PurpleConnection *gc, const cha yd = purple_connection_get_protocol_data(gc); for (l = yd->confs; l; l = l->next) { - PurpleConversation *c = l->data; - if (!purple_utf8_strcasecmp(purple_conversation_get_name(c), name)) + PurpleChatConversation *c = l->data; + if (!purple_utf8_strcasecmp(purple_conversation_get_name(PURPLE_CONVERSATION(c)), name)) return c; } return NULL; @@ -182,7 +181,7 @@ void yahoo_process_conference_invite(PurpleConnection *gc, struct yahoo_packet * return; } - if (!purple_privacy_check(account, who) || + if (!purple_account_privacy_check(account, who) || (purple_account_get_bool(account, "ignore_invites", FALSE))) { purple_debug_info("yahoo", @@ -209,7 +208,7 @@ void yahoo_process_conference_decline(PurpleConnection *gc, struct yahoo_packet char *room = NULL; char *who = NULL; char *msg = NULL; - PurpleConversation *c = NULL; + PurpleChatConversation *c = NULL; int utf8 = 0; for (l = pkt->hash; l; l = l->next) { @@ -232,7 +231,7 @@ void yahoo_process_conference_decline(PurpleConnection *gc, struct yahoo_packet break; } } - if (!purple_privacy_check(purple_connection_get_account(gc), who)) + if (!purple_account_privacy_check(purple_connection_get_account(gc), who)) { g_free(room); g_free(msg); @@ -247,13 +246,14 @@ void yahoo_process_conference_decline(PurpleConnection *gc, struct yahoo_packet { msg_tmp = yahoo_string_decode(gc, msg, utf8); msg = yahoo_codes_to_html(msg_tmp); - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)), who, 0, msg, time(NULL)); + serv_got_chat_in(gc, purple_chat_conversation_get_id(c), who, 0, msg, time(NULL)); g_free(msg_tmp); g_free(msg); } tmp = g_strdup_printf(_("%s has declined to join."), who); - purple_conversation_write(c, NULL, tmp, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, time(NULL)); + purple_conversation_write(PURPLE_CONVERSATION(c), NULL, tmp, + PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, time(NULL)); g_free(tmp); } @@ -267,7 +267,7 @@ void yahoo_process_conference_logon(PurpleConnection *gc, struct yahoo_packet *p GSList *l; char *room = NULL; char *who = NULL; - PurpleConversation *c; + PurpleChatConversation *c; for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; @@ -287,8 +287,8 @@ void yahoo_process_conference_logon(PurpleConnection *gc, struct yahoo_packet *p c = yahoo_find_conference(gc, room); if (c) { /* Prevent duplicate users in the chat */ - if( !purple_conv_chat_find_user(PURPLE_CONV_CHAT(c), who) ) - yahoo_chat_add_user(PURPLE_CONV_CHAT(c), who, NULL); + if( !purple_chat_conversation_has_user(c, who) ) + yahoo_chat_add_user(c, who, NULL); } g_free(room); } @@ -299,7 +299,7 @@ void yahoo_process_conference_logoff(PurpleConnection *gc, struct yahoo_packet * GSList *l; char *room = NULL; char *who = NULL; - PurpleConversation *c; + PurpleChatConversation *c; for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; @@ -318,7 +318,7 @@ void yahoo_process_conference_logoff(PurpleConnection *gc, struct yahoo_packet * if (who && room) { c = yahoo_find_conference(gc, room); if (c) - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c), who, NULL); + purple_chat_conversation_remove_user(c, who, NULL); g_free(room); } } @@ -330,7 +330,7 @@ void yahoo_process_conference_message(PurpleConnection *gc, struct yahoo_packet char *who = NULL; char *msg = NULL; int utf8 = 0; - PurpleConversation *c; + PurpleChatConversation *c; for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; @@ -363,7 +363,7 @@ void yahoo_process_conference_message(PurpleConnection *gc, struct yahoo_packet msg2 = yahoo_string_decode(gc, msg, utf8); msg = yahoo_codes_to_html(msg2); - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)), who, 0, msg, time(NULL)); + serv_got_chat_in(gc, purple_chat_conversation_get_id(c), who, 0, msg, time(NULL)); g_free(msg); g_free(msg2); } @@ -464,7 +464,7 @@ void yahoo_process_chat_join(PurpleConnection *gc, struct yahoo_packet *pkt) { PurpleAccount *account = purple_connection_get_account(gc); YahooData *yd = purple_connection_get_protocol_data(gc); - PurpleConversation *c = NULL; + PurpleChatConversation *c = NULL; GSList *l; GList *members = NULL; GList *roomies = NULL; @@ -541,63 +541,63 @@ void yahoo_process_chat_join(PurpleConnection *gc, struct yahoo_packet *pkt) yahoo_chat_leave(gc, room, purple_connection_get_display_name(gc), FALSE); - c = purple_find_chat(gc, YAHOO_CHAT_ID); + c = purple_conversations_find_chat(gc, YAHOO_CHAT_ID); - if (room && (!c || purple_conv_chat_has_left(PURPLE_CONV_CHAT(c))) && + if (room && (!c || purple_chat_conversation_has_left(c)) && members && (members->next || !g_ascii_strcasecmp(members->data, purple_connection_get_display_name(gc)))) { GList *l; GList *flags = NULL; for (l = members; l; l = l->next) - flags = g_list_prepend(flags, GINT_TO_POINTER(PURPLE_CBFLAGS_NONE)); - if (c && purple_conv_chat_has_left(PURPLE_CONV_CHAT(c))) { + flags = g_list_prepend(flags, GINT_TO_POINTER(PURPLE_CHAT_USER_NONE)); + if (c && purple_chat_conversation_has_left(c)) { /* this might be a hack, but oh well, it should nicely */ char *tmpmsg; - purple_conversation_set_name(c, room); + purple_conversation_set_name(PURPLE_CONVERSATION(c), room); c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room); if (topic) { - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic); + purple_chat_conversation_set_topic(c, NULL, topic); /* Also print the topic to the backlog so that the captcha link is clickable */ - purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", topic, PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write_message(PURPLE_CONVERSATION(c), "", topic, PURPLE_MESSAGE_SYSTEM, time(NULL)); } yd->in_chat = 1; yd->chat_name = g_strdup(room); - purple_conv_chat_add_users(PURPLE_CONV_CHAT(c), members, NULL, flags, FALSE); + purple_chat_conversation_add_users(c, members, NULL, flags, FALSE); tmpmsg = g_strdup_printf(_("You are now chatting in %s."), room); - purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", tmpmsg, PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write_message(PURPLE_CONVERSATION(c), "", tmpmsg, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(tmpmsg); } else { c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room); if (topic) { - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic); + purple_chat_conversation_set_topic(c, NULL, topic); /* Also print the topic to the backlog so that the captcha link is clickable */ - purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", topic, PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write_message(PURPLE_CONVERSATION(c), "", topic, PURPLE_MESSAGE_SYSTEM, time(NULL)); } yd->in_chat = 1; yd->chat_name = g_strdup(room); - purple_conv_chat_add_users(PURPLE_CONV_CHAT(c), members, NULL, flags, FALSE); + purple_chat_conversation_add_users(c, members, NULL, flags, FALSE); } g_list_free(flags); } else if (c) { if (topic) { - const char *cur_topic = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(c)); + const char *cur_topic = purple_chat_conversation_get_topic(c); if (cur_topic == NULL || strcmp(cur_topic, topic) != 0) - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic); + purple_chat_conversation_set_topic(c, NULL, topic); } - yahoo_chat_add_users(PURPLE_CONV_CHAT(c), members); + yahoo_chat_add_users(c, members); } - if (account->deny && c) { - PurpleConversationUiOps *ops = purple_conversation_get_ui_ops(c); - for (l = account->deny; l != NULL; l = l->next) { + if (purple_account_privacy_get_denied(account) && c) { + PurpleConversationUiOps *ops = purple_conversation_get_ui_ops(PURPLE_CONVERSATION(c)); + for (l = purple_account_privacy_get_denied(account); l != NULL; l = l->next) { for (roomies = members; roomies; roomies = roomies->next) { if (!purple_utf8_strcasecmp((char *)l->data, roomies->data)) { purple_debug_info("yahoo", "Ignoring room member %s in room %s\n" , (char *)roomies->data, room ? room : ""); - purple_conv_chat_ignore(PURPLE_CONV_CHAT(c),roomies->data); - ops->chat_update_user(c, roomies->data); + purple_chat_conversation_ignore(c,roomies->data); + ops->chat_update_user(purple_chat_conversation_find_user(c, roomies->data)); } } } @@ -626,9 +626,10 @@ void yahoo_process_chat_exit(PurpleConnection *gc, struct yahoo_packet *pkt) } if (who && room) { - PurpleConversation *c = purple_find_chat(gc, YAHOO_CHAT_ID); - if (c && !purple_utf8_strcasecmp(purple_conversation_get_name(c), room)) - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c), who, NULL); + PurpleChatConversation *c = purple_conversations_find_chat(gc, YAHOO_CHAT_ID); + if (c && !purple_utf8_strcasecmp(purple_conversation_get_name( + PURPLE_CONVERSATION(c)), room)) + purple_chat_conversation_remove_user(c, who, NULL); } g_free(room); @@ -638,7 +639,7 @@ void yahoo_process_chat_message(PurpleConnection *gc, struct yahoo_packet *pkt) { char *room = NULL, *who = NULL, *msg = NULL, *msg2; int msgtype = 1, utf8 = 1; /* default to utf8 */ - PurpleConversation *c = NULL; + PurpleChatConversation *c = NULL; GSList *l; for (l = pkt->hash; l; l = l->next) { @@ -665,7 +666,7 @@ void yahoo_process_chat_message(PurpleConnection *gc, struct yahoo_packet *pkt) } } - c = purple_find_chat(gc, YAHOO_CHAT_ID); + c = purple_conversations_find_chat(gc, YAHOO_CHAT_ID); if (!who || !c) { if (room) g_free(room); @@ -730,7 +731,7 @@ void yahoo_process_chat_addinvite(PurpleConnection *gc, struct yahoo_packet *pkt if (room && who) { GHashTable *components; - if (!purple_privacy_check(account, who) || + if (!purple_account_privacy_check(account, who) || (purple_account_get_bool(account, "ignore_invites", FALSE))) { purple_debug_info("yahoo", "Invite to room %s from %s has been dropped.\n", room, who); @@ -771,7 +772,7 @@ void yahoo_conf_leave(YahooData *yd, const char *room, const char *dn, GList *wh yahoo_packet_hash_str(pkt, 1, dn); for (w = who; w; w = w->next) { - const char *name = purple_conv_chat_cb_get_name(w->data); + const char *name = purple_chat_user_get_name(w->data); yahoo_packet_hash_str(pkt, 3, name); } @@ -795,7 +796,7 @@ static int yahoo_conf_send(PurpleConnection *gc, const char *dn, const char *roo yahoo_packet_hash_str(pkt, 1, dn); for (who = members; who; who = who->next) { - const char *name = purple_conv_chat_cb_get_name(who->data); + const char *name = purple_chat_user_get_name(who->data); yahoo_packet_hash_str(pkt, 53, name); } yahoo_packet_hash(pkt, "ss", 57, room, 14, msg2); @@ -809,7 +810,7 @@ static int yahoo_conf_send(PurpleConnection *gc, const char *dn, const char *roo return 0; } -static void yahoo_conf_join(YahooData *yd, PurpleConversation *c, const char *dn, const char *room, +static void yahoo_conf_join(YahooData *yd, PurpleChatConversation *c, const char *dn, const char *room, const char *topic, const char *members) { struct yahoo_packet *pkt; @@ -827,7 +828,7 @@ static void yahoo_conf_join(YahooData *yd, PurpleConversation *c, const char *dn if (!strcmp(memarr[i], "") || !strcmp(memarr[i], dn)) continue; yahoo_packet_hash_str(pkt, 3, memarr[i]); - purple_conv_chat_add_user(PURPLE_CONV_CHAT(c), memarr[i], NULL, PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(c, memarr[i], NULL, PURPLE_CHAT_USER_NONE, TRUE); } } yahoo_packet_send_and_free(pkt, yd); @@ -836,7 +837,7 @@ static void yahoo_conf_join(YahooData *yd, PurpleConversation *c, const char *dn g_strfreev(memarr); } -static void yahoo_conf_invite(PurpleConnection *gc, PurpleConversation *c, +static void yahoo_conf_invite(PurpleConnection *gc, PurpleChatConversation *c, const char *dn, const char *buddy, const char *room, const char *msg) { YahooData *yd = purple_connection_get_protocol_data(gc); @@ -847,13 +848,13 @@ static void yahoo_conf_invite(PurpleConnection *gc, PurpleConversation *c, if (msg) msg2 = yahoo_string_encode(gc, msg, NULL); - members = purple_conv_chat_get_users(PURPLE_CONV_CHAT(c)); + members = purple_chat_conversation_get_users(c); pkt = yahoo_packet_new(YAHOO_SERVICE_CONFADDINVITE, YAHOO_STATUS_AVAILABLE, yd->session_id); yahoo_packet_hash(pkt, "sssss", 1, dn, 51, buddy, 57, room, 58, msg?msg2:"", 13, "0"); for(; members; members = members->next) { - const char *name = purple_conv_chat_cb_get_name(members->data); + const char *name = purple_chat_user_get_name(members->data); if (!strcmp(name, dn)) continue; yahoo_packet_hash(pkt, "ss", 52, name, 53, name); @@ -895,7 +896,7 @@ static void yahoo_chat_leave(PurpleConnection *gc, const char *room, const char yd->chat_name = NULL; } - if (purple_find_chat(gc, YAHOO_CHAT_ID) != NULL) + if (purple_conversations_find_chat(gc, YAHOO_CHAT_ID) != NULL) serv_got_chat_left(gc, YAHOO_CHAT_ID); if (!logout) @@ -1026,21 +1027,22 @@ void yahoo_chat_goto(PurpleConnection *gc, const char *name) void yahoo_c_leave(PurpleConnection *gc, int id) { YahooData *yd = purple_connection_get_protocol_data(gc); - PurpleConversation *c; + PurpleChatConversation *c; if (!yd) return; - c = purple_find_chat(gc, id); + c = purple_conversations_find_chat(gc, id); if (!c) return; if (id != YAHOO_CHAT_ID) { - yahoo_conf_leave(yd, purple_conversation_get_name(c), - purple_connection_get_display_name(gc), purple_conv_chat_get_users(PURPLE_CONV_CHAT(c))); + yahoo_conf_leave(yd, purple_conversation_get_name(PURPLE_CONVERSATION(c)), + purple_connection_get_display_name(gc), purple_chat_conversation_get_users(c)); yd->confs = g_slist_remove(yd->confs, c); } else { - yahoo_chat_leave(gc, purple_conversation_get_name(c), purple_connection_get_display_name(gc), TRUE); + yahoo_chat_leave(gc, purple_conversation_get_name(PURPLE_CONVERSATION(c)), + purple_connection_get_display_name(gc), TRUE); } serv_got_chat_left(gc, id); @@ -1048,7 +1050,7 @@ void yahoo_c_leave(PurpleConnection *gc, int id) int yahoo_c_send(PurpleConnection *gc, int id, const char *what, PurpleMessageFlags flags) { - PurpleConversation *c; + PurpleChatConversation *c; int ret; YahooData *yd; @@ -1056,18 +1058,19 @@ int yahoo_c_send(PurpleConnection *gc, int id, const char *what, PurpleMessageFl if (!yd) return -1; - c = purple_find_chat(gc, id); + c = purple_conversations_find_chat(gc, id); if (!c) return -1; if (id != YAHOO_CHAT_ID) { ret = yahoo_conf_send(gc, purple_connection_get_display_name(gc), - purple_conversation_get_name(c), purple_conv_chat_get_users(PURPLE_CONV_CHAT(c)), what); + purple_conversation_get_name(PURPLE_CONVERSATION(c)), + purple_chat_conversation_get_users(c), what); } else { ret = yahoo_chat_send(gc, purple_connection_get_display_name(gc), - purple_conversation_get_name(c), what, flags); + purple_conversation_get_name(PURPLE_CONVERSATION(c)), what, flags); if (!ret) - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)), + serv_got_chat_in(gc, purple_chat_conversation_get_id(c), purple_connection_get_display_name(gc), flags, what, time(NULL)); } return ret; @@ -1108,7 +1111,7 @@ void yahoo_c_join(PurpleConnection *gc, GHashTable *data) { YahooData *yd; char *room, *topic, *type; - PurpleConversation *c; + PurpleChatConversation *c; yd = purple_connection_get_protocol_data(gc); if (!yd) @@ -1128,7 +1131,7 @@ void yahoo_c_join(PurpleConnection *gc, GHashTable *data) id = yd->conf_id++; c = serv_got_joined_chat(gc, id, room); yd->confs = g_slist_prepend(yd->confs, c); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), purple_connection_get_display_name(gc), topic); + purple_chat_conversation_set_topic(c, purple_connection_get_display_name(gc), topic); yahoo_conf_join(yd, c, purple_connection_get_display_name(gc), room, topic, members); return; } else { @@ -1159,18 +1162,18 @@ void yahoo_c_join(PurpleConnection *gc, GHashTable *data) void yahoo_c_invite(PurpleConnection *gc, int id, const char *msg, const char *name) { - PurpleConversation *c; + PurpleChatConversation *c; - c = purple_find_chat(gc, id); - if (!c || !purple_conversation_get_name(c)) + c = purple_conversations_find_chat(gc, id); + if (!c || !purple_conversation_get_name(PURPLE_CONVERSATION(c))) return; if (id != YAHOO_CHAT_ID) { yahoo_conf_invite(gc, c, purple_connection_get_display_name(gc), name, - purple_conversation_get_name(c), msg); + purple_conversation_get_name(PURPLE_CONVERSATION(c)), msg); } else { yahoo_chat_invite(gc, purple_connection_get_display_name(gc), name, - purple_conversation_get_name(c), msg); + purple_conversation_get_name(PURPLE_CONVERSATION(c)), msg); } } diff --git a/libpurple/protocols/yahoo/yahoochat.h b/libpurple/protocols/yahoo/yahoochat.h index 061be7760f..09b76e3e7d 100644 --- a/libpurple/protocols/yahoo/yahoochat.h +++ b/libpurple/protocols/yahoo/yahoochat.h @@ -60,7 +60,7 @@ void yahoo_roomlist_cancel(PurpleRoomlist *list); void yahoo_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category); /* util */ -void yahoo_chat_add_users(PurpleConvChat *chat, GList *newusers); -void yahoo_chat_add_user(PurpleConvChat *chat, const char *user, const char *reason); +void yahoo_chat_add_users(PurpleChatConversation *chat, GList *newusers); +void yahoo_chat_add_user(PurpleChatConversation *chat, const char *user, const char *reason); #endif /* _YAHOO_CHAT_H_ */ diff --git a/libpurple/protocols/yahoo/ycht.c b/libpurple/protocols/yahoo/ycht.c index c6dc7b80cd..70b634be19 100644 --- a/libpurple/protocols/yahoo/ycht.c +++ b/libpurple/protocols/yahoo/ycht.c @@ -78,7 +78,7 @@ static void ycht_process_chatjoin(YchtConn *ycht, YchtPkt *pkt) { char *room, *topic; PurpleConnection *gc = ycht->gc; - PurpleConversation *c = NULL; + PurpleChatConversation *c = NULL; gboolean new_room = FALSE; char **members; int i; @@ -105,19 +105,19 @@ static void ycht_process_chatjoin(YchtConn *ycht, YchtPkt *pkt) ycht->changing_rooms = FALSE; c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room); } else { - c = purple_find_chat(gc, YAHOO_CHAT_ID); + c = purple_conversations_find_chat(gc, YAHOO_CHAT_ID); } if (topic) - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic); + purple_chat_conversation_set_topic(c, NULL, topic); for (i = 0; members[i]; i++) { if (new_room) { /*if (!strcmp(members[i], purple_connection_get_display_name(ycht->gc))) continue;*/ - purple_conv_chat_add_user(PURPLE_CONV_CHAT(c), members[i], NULL, PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(c, members[i], NULL, PURPLE_CHAT_USER_NONE, TRUE); } else { - yahoo_chat_add_user(PURPLE_CONV_CHAT(c), members[i], NULL); + yahoo_chat_add_user(c, members[i], NULL); } } @@ -132,9 +132,9 @@ static void ycht_process_chatpart(YchtConn *ycht, YchtPkt *pkt) who = g_list_nth_data(pkt->data, 1); if (who && room) { - PurpleConversation *c = purple_find_chat(ycht->gc, YAHOO_CHAT_ID); - if (c && !purple_utf8_strcasecmp(purple_conversation_get_name(c), room)) - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c), who, NULL); + PurpleChatConversation *c = purple_conversations_find_chat(ycht->gc, YAHOO_CHAT_ID); + if (c && !purple_utf8_strcasecmp(purple_conversation_get_name(PURPLE_CONVERSATION(c)), room)) + purple_chat_conversation_remove_user(c, who, NULL); } } @@ -142,7 +142,7 @@ static void ycht_process_chatpart(YchtConn *ycht, YchtPkt *pkt) static void ycht_progress_chatmsg(YchtConn *ycht, YchtPkt *pkt) { char *who, *what, *msg; - PurpleConversation *c; + PurpleChatConversation *c; PurpleConnection *gc = ycht->gc; who = g_list_nth_data(pkt->data, 1); @@ -151,7 +151,7 @@ static void ycht_progress_chatmsg(YchtConn *ycht, YchtPkt *pkt) if (!who || !what) return; - c = purple_find_chat(gc, YAHOO_CHAT_ID); + c = purple_conversations_find_chat(gc, YAHOO_CHAT_ID); if (!c) return; @@ -267,8 +267,9 @@ static void ycht_packet_send_write_cb(gpointer data, gint source, PurpleInputCon { YchtConn *ycht = data; int ret, writelen; + const gchar *output = NULL; - writelen = purple_circ_buffer_get_max_read(ycht->txbuf); + writelen = purple_circular_buffer_get_max_read(ycht->txbuf); if (writelen == 0) { purple_input_remove(ycht->tx_handler); @@ -276,7 +277,9 @@ static void ycht_packet_send_write_cb(gpointer data, gint source, PurpleInputCon return; } - ret = write(ycht->fd, ycht->txbuf->outptr, writelen); + output = purple_circular_buffer_get_output(ycht->txbuf); + + ret = write(ycht->fd, output, writelen); if (ret < 0 && errno == EAGAIN) return; @@ -292,7 +295,7 @@ static void ycht_packet_send_write_cb(gpointer data, gint source, PurpleInputCon return; } - purple_circ_buffer_mark_read(ycht->txbuf, ret); + purple_circular_buffer_mark_read(ycht->txbuf, ret); } @@ -345,7 +348,7 @@ static void ycht_packet_send(YchtConn *ycht, YchtPkt *pkt) ycht->tx_handler = purple_input_add(ycht->fd, PURPLE_INPUT_WRITE, ycht_packet_send_write_cb, ycht); - purple_circ_buffer_append(ycht->txbuf, buf + written, + purple_circular_buffer_append(ycht->txbuf, buf + written, len - written); } @@ -444,7 +447,7 @@ void ycht_connection_close(YchtConn *ycht) if (ycht->tx_handler) purple_input_remove(ycht->tx_handler); - purple_circ_buffer_destroy(ycht->txbuf); + g_object_unref(G_OBJECT(ycht->txbuf)); g_free(ycht->rxqueue); diff --git a/libpurple/protocols/yahoo/ycht.h b/libpurple/protocols/yahoo/ycht.h index 325745ceeb..0d4fc7efd9 100644 --- a/libpurple/protocols/yahoo/ycht.h +++ b/libpurple/protocols/yahoo/ycht.h @@ -73,7 +73,7 @@ typedef struct _YchtConn { gboolean changing_rooms; guchar *rxqueue; guint rxlen; - PurpleCircBuffer *txbuf; + PurpleCircularBuffer *txbuf; guint tx_handler; } YchtConn; diff --git a/libpurple/protocols/zephyr/zephyr.c b/libpurple/protocols/zephyr/zephyr.c index da304e257f..91e32f7aed 100644 --- a/libpurple/protocols/zephyr/zephyr.c +++ b/libpurple/protocols/zephyr/zephyr.c @@ -35,7 +35,6 @@ #include "server.h" #include "util.h" #include "cmds.h" -#include "privacy.h" #include "version.h" #include "internal.h" @@ -777,9 +776,9 @@ static void handle_message(PurpleConnection *gc,ZNotice_t notice) if (ZParseLocations(¬ice, NULL, &nlocs, &user) != ZERR_NONE) return; - if ((b = purple_find_buddy(purple_connection_get_account(gc), user)) == NULL) { + if ((b = purple_blist_find_buddy(purple_connection_get_account(gc), user)) == NULL) { char* stripped_user = zephyr_strip_local_realm(zephyr,user); - b = purple_find_buddy(purple_connection_get_account(gc),stripped_user); + b = purple_blist_find_buddy(purple_connection_get_account(gc),stripped_user); g_free(stripped_user); } @@ -794,7 +793,7 @@ static void handle_message(PurpleConnection *gc,ZNotice_t notice) /* TODO: Check whether it's correct to call add_pair_html, or if we should be using add_pair_plaintext */ purple_notify_user_info_add_pair_html(user_info, _("User"), (b ? bname : user)); - balias = purple_buddy_get_local_buddy_alias(b); + balias = purple_buddy_get_local_alias(b); if (b && balias) purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), balias); @@ -825,8 +824,7 @@ static void handle_message(PurpleConnection *gc,ZNotice_t notice) } else { char *buf, *buf2, *buf3; char *send_inst; - PurpleConversation *gconv1; - PurpleConvChat *gcc; + PurpleChatConversation *gcc; char *ptr = (char *) notice.z_message + (strlen(notice.z_message) + 1); int len; char *stripped_sender; @@ -864,7 +862,7 @@ static void handle_message(PurpleConnection *gc,ZNotice_t notice) flags |= PURPLE_MESSAGE_AUTO_RESP; if (!g_ascii_strcasecmp(notice.z_opcode,"PING")) - serv_got_typing(gc,stripped_sender,ZEPHYR_TYPING_RECV_TIMEOUT, PURPLE_TYPING); + serv_got_typing(gc,stripped_sender,ZEPHYR_TYPING_RECV_TIMEOUT, PURPLE_IM_TYPING); else serv_got_im(gc, stripped_sender, buf3, flags, time(NULL)); @@ -898,20 +896,19 @@ static void handle_message(PurpleConnection *gc,ZNotice_t notice) } } - gconv1 = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + gcc = purple_conversations_find_chat_with_account( zt2->name, purple_connection_get_account(gc)); - gcc = purple_conversation_get_chat_data(gconv1); #ifndef INET_ADDRSTRLEN #define INET_ADDRSTRLEN 16 #endif - if (!purple_conv_chat_find_user(gcc, stripped_sender)) { + if (!purple_chat_conversation_has_user(gcc, stripped_sender)) { gchar ipaddr[INET_ADDRSTRLEN]; #ifdef HAVE_INET_NTOP inet_ntop(AF_INET, ¬ice.z_sender_addr.s_addr, ipaddr, sizeof(ipaddr)); #else memcpy(ipaddr,inet_ntoa(notice.z_sender_addr),sizeof(ipaddr)); #endif - purple_conv_chat_add_user(gcc, stripped_sender, ipaddr, PURPLE_CBFLAGS_NONE, TRUE); + purple_chat_conversation_add_user(gcc, stripped_sender, ipaddr, PURPLE_CHAT_USER_NONE, TRUE); } serv_got_chat_in(gc, zt2->id, send_inst_utf8, 0, buf3, time(NULL)); g_free(send_inst_utf8); @@ -1158,9 +1155,9 @@ static gint check_notify_tzc(gpointer data) gchar *locval; user = tree_child(find_node(newparsetree,"user"),2)->contents; - if ((b = purple_find_buddy(purple_connection_get_account(gc), user)) == NULL) { + if ((b = purple_blist_find_buddy(purple_connection_get_account(gc), user)) == NULL) { gchar *stripped_user = zephyr_strip_local_realm(zephyr,user); - b = purple_find_buddy(purple_connection_get_account(gc), stripped_user); + b = purple_blist_find_buddy(purple_connection_get_account(gc), stripped_user); g_free(stripped_user); } locations = find_node(newparsetree,"locations"); @@ -1182,7 +1179,7 @@ static gint check_notify_tzc(gpointer data) or if we should be using add_pair_plaintext */ purple_notify_user_info_add_pair_html(user_info, _("User"), (b ? bname : user)); - balias = b ? purple_buddy_get_local_buddy_alias(b) : NULL; + balias = b ? purple_buddy_get_local_alias(b) : NULL; if (balias) purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), balias); @@ -1272,7 +1269,7 @@ static gint check_loc(gpointer data) int numlocs; int one = 1; - for (buddies = purple_find_buddies(account, NULL); buddies; + for (buddies = purple_blist_find_buddies(account, NULL); buddies; buddies = g_slist_delete_link(buddies, buddies)) { PurpleBuddy *b = buddies->data; char *chk; @@ -1307,7 +1304,7 @@ static gint check_loc(gpointer data) ald.version = NULL; } - for (buddies = purple_find_buddies(account, NULL); buddies; + for (buddies = purple_blist_find_buddies(account, NULL); buddies; buddies = g_slist_delete_link(buddies, buddies)) { PurpleBuddy *b = buddies->data; @@ -1514,7 +1511,7 @@ static void process_anyone(PurpleConnection *gc) PurpleGroup *g; PurpleBuddy *b; - if (!(g = purple_find_group(_("Anyone")))) { + if (!(g = purple_blist_find_group(_("Anyone")))) { g = purple_group_new(_("Anyone")); purple_blist_add_group(g, NULL); } @@ -1524,10 +1521,10 @@ static void process_anyone(PurpleConnection *gc) while (fgets(buff, BUFSIZ, fd)) { strip_comments(buff); if (buff[0]) { - if (!purple_find_buddy(purple_connection_get_account(gc), buff)) { + if (!purple_blist_find_buddy(purple_connection_get_account(gc), buff)) { char *stripped_user = zephyr_strip_local_realm(zephyr,buff); purple_debug_info("zephyr","stripped_user %s\n",stripped_user); - if (!purple_find_buddy(purple_connection_get_account(gc),stripped_user)) { + if (!purple_blist_find_buddy(purple_connection_get_account(gc),stripped_user)) { b = purple_buddy_new(purple_connection_get_account(gc), stripped_user, NULL); purple_blist_add_buddy(b, NULL, g, NULL); } @@ -1574,7 +1571,7 @@ static void zephyr_login(PurpleAccount * account) #ifdef WIN32 username = purple_account_get_username(account); #endif - purple_connection_set_flags(gc, PURPLE_CONNECTION_AUTO_RESP | PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC); + purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_AUTO_RESP | PURPLE_CONNECTION_FLAG_HTML | PURPLE_CONNECTION_FLAG_NO_BGCOLOR | PURPLE_CONNECTION_FLAG_NO_URLDESC); zephyr = g_new0(zephyr_account, 1); purple_connection_set_protocol_data(gc, zephyr); @@ -1855,7 +1852,7 @@ static void zephyr_login(PurpleAccount * account) return; } - purple_connection_set_state(gc, PURPLE_CONNECTED); + purple_connection_set_state(gc, PURPLE_CONNECTION_CONNECTED); if (read_anyone) process_anyone(gc); @@ -1954,7 +1951,7 @@ static void write_anyone(zephyr_account *zephyr) } account = zephyr->account; - for (buddies = purple_find_buddies(account, NULL); buddies; + for (buddies = purple_blist_find_buddies(account, NULL); buddies; buddies = g_slist_delete_link(buddies, buddies)) { PurpleBuddy *b = buddies->data; gchar *stripped_user = zephyr_strip_local_realm(zephyr, purple_buddy_get_name(b)); @@ -2041,8 +2038,7 @@ static int zephyr_chat_send(PurpleConnection * gc, int id, const char *im, Purpl { zephyr_triple *zt; const char *sig; - PurpleConversation *gconv1; - PurpleConvChat *gcc; + PurpleChatConversation *gcc; char *inst; char *recipient; zephyr_account *zephyr = purple_connection_get_protocol_data(gc); @@ -2054,11 +2050,10 @@ static int zephyr_chat_send(PurpleConnection * gc, int id, const char *im, Purpl sig = zephyr_get_signature(); - gconv1 = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, zt->name, + gcc = purple_conversations_find_chat_with_account(zt->name, purple_connection_get_account(gc)); - gcc = purple_conversation_get_chat_data(gconv1); - if (!(inst = (char *)purple_conv_chat_get_topic(gcc))) + if (!(inst = (char *)purple_chat_conversation_get_topic(gcc))) inst = g_strdup("PERSONAL"); if (!g_ascii_strcasecmp(zt->recipient, "*")) @@ -2290,7 +2285,7 @@ static void zephyr_set_status(PurpleAccount *account, PurpleStatus *status) { size_t result; PurpleConnection *gc = purple_account_get_connection(account); zephyr_account *zephyr = purple_connection_get_protocol_data(gc); - PurpleStatusPrimitive primitive = purple_status_type_get_primitive(purple_status_get_type(status)); + PurpleStatusPrimitive primitive = purple_status_type_get_primitive(purple_status_get_status_type(status)); if (zephyr->away) { g_free(zephyr->away); @@ -2357,7 +2352,7 @@ static GList *zephyr_status_types(PurpleAccount *account) type = purple_status_type_new_with_attrs( PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + "message", _("Message"), purple_g_value_new(G_TYPE_STRING), NULL); types = g_list_append(types, type); @@ -2509,7 +2504,7 @@ static PurpleChat *zephyr_find_blist_chat(PurpleAccount *account, const char *na char *zclass, *inst, *recip; char** triple; GHashTable *components; - if(!PURPLE_BLIST_NODE_IS_CHAT(cnode)) + if(!PURPLE_IS_CHAT(cnode)) continue; if(purple_chat_get_account(chat) != account) continue; @@ -2534,13 +2529,13 @@ static const char *zephyr_list_icon(PurpleAccount * a, PurpleBuddy * b) return "zephyr"; } -static unsigned int zephyr_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state) { +static unsigned int zephyr_send_typing(PurpleConnection *gc, const char *who, PurpleIMTypingState state) { gchar *recipient; zephyr_account *zephyr = purple_connection_get_protocol_data(gc); if (use_tzc(zephyr)) return 0; - if (state == PURPLE_NOT_TYPING) + if (state == PURPLE_IM_NOT_TYPING) return 0; /* XXX We probably should care if this fails. Or maybe we don't want to */ @@ -2564,7 +2559,7 @@ static unsigned int zephyr_send_typing(PurpleConnection *gc, const char *who, Pu /* * TODO: Is this correct? It means we will call - * serv_send_typing(gc, who, PURPLE_TYPING) once every 15 seconds + * serv_send_typing(gc, who, PURPLE_IM_TYPING) once every 15 seconds * until the Purple user stops typing. */ return ZEPHYR_TYPING_SEND_TIMEOUT; @@ -2575,8 +2570,7 @@ static unsigned int zephyr_send_typing(PurpleConnection *gc, const char *who, Pu static void zephyr_chat_set_topic(PurpleConnection * gc, int id, const char *topic) { zephyr_triple *zt; - PurpleConversation *gconv; - PurpleConvChat *gcc; + PurpleChatConversation *gcc; gchar *topic_utf8; zephyr_account* zephyr = purple_connection_get_protocol_data(gc); char *sender = (char *)zephyr->username; @@ -2585,12 +2579,11 @@ static void zephyr_chat_set_topic(PurpleConnection * gc, int id, const char *top /* find_sub_by_id can return NULL */ if (!zt) return; - gconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, zt->name, + gcc = purple_conversations_find_chat_with_account(zt->name, purple_connection_get_account(gc)); - gcc = purple_conversation_get_chat_data(gconv); topic_utf8 = zephyr_recv_convert(gc,(gchar *)topic); - purple_conv_chat_set_topic(gcc,sender,topic_utf8); + purple_chat_conversation_set_topic(gcc,sender,topic_utf8); g_free(topic_utf8); return; } @@ -2636,9 +2629,9 @@ static PurpleCmdRet zephyr_purple_cmd_instance(PurpleConversation *conv, * all. This might not be the best thing to do, though having * one word isn't ideal either. */ - PurpleConvChat *gcc = purple_conversation_get_chat_data(conv); const char* instance = args[0]; - zephyr_chat_set_topic(purple_conversation_get_connection(conv),purple_conv_chat_get_id(gcc),instance); + zephyr_chat_set_topic(purple_conversation_get_connection(conv), + purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)),instance); return PURPLE_CMD_RET_OK; } diff --git a/libpurple/proxy.c b/libpurple/proxy.c index 1d9a7aa2a6..c7250d6360 100644 --- a/libpurple/proxy.c +++ b/libpurple/proxy.c @@ -32,7 +32,7 @@ #define _PURPLE_PROXY_C_ #include "internal.h" -#include "cipher.h" +#include "ciphers/md5hash.h" #include "debug.h" #include "dnsquery.h" #include "http.h" @@ -1678,23 +1678,21 @@ s5_readauth(gpointer data, gint source, PurpleInputCondition cond) static void hmacmd5_chap(const unsigned char * challenge, int challen, const char * passwd, unsigned char * response) { - PurpleCipher *cipher; - PurpleCipherContext *ctx; + PurpleHash *hash; int i; unsigned char Kxoripad[65]; unsigned char Kxoropad[65]; size_t pwlen; - cipher = purple_ciphers_find_cipher("md5"); - ctx = purple_cipher_context_new(cipher, NULL); + hash = purple_md5_hash_new(); memset(Kxoripad,0,sizeof(Kxoripad)); memset(Kxoropad,0,sizeof(Kxoropad)); pwlen=strlen(passwd); if (pwlen>64) { - purple_cipher_context_append(ctx, (const guchar *)passwd, strlen(passwd)); - purple_cipher_context_digest(ctx, Kxoripad, sizeof(Kxoripad)); + purple_hash_append(hash, (const guchar *)passwd, strlen(passwd)); + purple_hash_digest(hash, Kxoripad, sizeof(Kxoripad)); pwlen=16; } else { memcpy(Kxoripad, passwd, pwlen); @@ -1706,17 +1704,17 @@ hmacmd5_chap(const unsigned char * challenge, int challen, const char * passwd, Kxoropad[i]^=0x5c; } - purple_cipher_context_reset(ctx, NULL); - purple_cipher_context_append(ctx, Kxoripad, 64); - purple_cipher_context_append(ctx, challenge, challen); - purple_cipher_context_digest(ctx, Kxoripad, sizeof(Kxoripad)); + purple_hash_reset(hash); + purple_hash_append(hash, Kxoripad, 64); + purple_hash_append(hash, challenge, challen); + purple_hash_digest(hash, Kxoripad, sizeof(Kxoripad)); - purple_cipher_context_reset(ctx, NULL); - purple_cipher_context_append(ctx, Kxoropad, 64); - purple_cipher_context_append(ctx, Kxoripad, 16); - purple_cipher_context_digest(ctx, response, 16); + purple_hash_reset(hash); + purple_hash_append(hash, Kxoropad, 64); + purple_hash_append(hash, Kxoripad, 16); + purple_hash_digest(hash, response, 16); - purple_cipher_context_destroy(ctx); + g_object_unref(hash); } static void diff --git a/libpurple/prpl.c b/libpurple/prpl.c index 09edc76682..42de14ae85 100644 --- a/libpurple/prpl.c +++ b/libpurple/prpl.c @@ -214,7 +214,7 @@ purple_prpl_got_user_idle(PurpleAccount *account, const char *name, g_return_if_fail(name != NULL); g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account)); - if ((list = purple_find_buddies(account, name)) == NULL) + if ((list = purple_blist_find_buddies(account, name)) == NULL) return; while (list) { @@ -234,7 +234,7 @@ purple_prpl_got_user_login_time(PurpleAccount *account, const char *name, g_return_if_fail(account != NULL); g_return_if_fail(name != NULL); - if ((list = purple_find_buddies(account, name)) == NULL) + if ((list = purple_blist_find_buddies(account, name)) == NULL) return; if (login_time == 0) @@ -270,7 +270,7 @@ purple_prpl_got_user_status(PurpleAccount *account, const char *name, g_return_if_fail(status_id != NULL); g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account)); - if((list = purple_find_buddies(account, name)) == NULL) + if((list = purple_blist_find_buddies(account, name)) == NULL) return; for(l = list; l != NULL; l = l->next) { @@ -292,7 +292,7 @@ purple_prpl_got_user_status(PurpleAccount *account, const char *name, purple_status_set_active_with_attrs(status, TRUE, args); va_end(args); - purple_blist_update_buddy_status(buddy, old_status); + purple_buddy_update_status(buddy, old_status); } g_slist_free(list); @@ -318,7 +318,7 @@ void purple_prpl_got_user_status_deactive(PurpleAccount *account, const char *na g_return_if_fail(status_id != NULL); g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account)); - if((list = purple_find_buddies(account, name)) == NULL) + if((list = purple_blist_find_buddies(account, name)) == NULL) return; for(l = list; l != NULL; l = l->next) { @@ -332,7 +332,7 @@ void purple_prpl_got_user_status_deactive(PurpleAccount *account, const char *na if (purple_status_is_active(status)) { purple_status_set_active(status, FALSE); - purple_blist_update_buddy_status(buddy, status); + purple_buddy_update_status(buddy, status); } } @@ -437,7 +437,7 @@ purple_prpl_send_attention(PurpleConnection *gc, const char *who, guint type_cod PurpleAttentionType *attn; PurpleMessageFlags flags; PurplePlugin *prpl; - PurpleConversation *conv; + PurpleIMConversation *im; gboolean (*send_attention)(PurpleConnection *, const char *, guint); PurpleBuddy *buddy; const char *alias; @@ -455,7 +455,7 @@ purple_prpl_send_attention(PurpleConnection *gc, const char *who, guint type_cod attn = purple_get_attention_type_from_code(purple_connection_get_account(gc), type_code); - if ((buddy = purple_find_buddy(purple_connection_get_account(gc), who)) != NULL) + if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who)) != NULL) alias = purple_buddy_get_contact_alias(buddy); else alias = who; @@ -474,9 +474,9 @@ purple_prpl_send_attention(PurpleConnection *gc, const char *who, guint type_cod if (!send_attention(gc, who, type_code)) return; - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, purple_connection_get_account(gc), who); - purple_conv_im_write(PURPLE_CONV_IM(conv), NULL, description, flags, mtime); - purple_prpl_attention(conv, who, type_code, PURPLE_MESSAGE_SEND, time(NULL)); + im = purple_im_conversation_new(purple_connection_get_account(gc), who); + purple_conversation_write_message(PURPLE_CONVERSATION(im), NULL, description, flags, mtime); + purple_prpl_attention(PURPLE_CONVERSATION(im), who, type_code, PURPLE_MESSAGE_SEND, time(NULL)); g_free(description); } @@ -501,7 +501,7 @@ got_attention(PurpleConnection *gc, int id, const char *who, guint type_code) /* TODO: if (attn->icon_name) is non-null, use it to lookup an emoticon and display * it next to the attention command. And if it is null, display a generic icon. */ - if ((buddy = purple_find_buddy(purple_connection_get_account(gc), who)) != NULL) + if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who)) != NULL) alias = purple_buddy_get_contact_alias(buddy); else alias = who; @@ -533,7 +533,7 @@ purple_prpl_got_attention(PurpleConnection *gc, const char *who, guint type_code got_attention(gc, -1, who, type_code); conv = - purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, who, account); + purple_conversations_find_with_account(who, account); if (conv) purple_prpl_attention(conv, who, type_code, PURPLE_MESSAGE_RECV, time(NULL)); @@ -602,7 +602,7 @@ purple_prpl_got_media_caps(PurpleAccount *account, const char *name) g_return_if_fail(account != NULL); g_return_if_fail(name != NULL); - if ((list = purple_find_buddies(account, name)) == NULL) + if ((list = purple_blist_find_buddies(account, name)) == NULL) return; while (list) { diff --git a/libpurple/prpl.h b/libpurple/prpl.h index 683d9a335c..44fa9e13f1 100644 --- a/libpurple/prpl.h +++ b/libpurple/prpl.h @@ -71,8 +71,8 @@ typedef struct _PurpleThumbnailSpec PurpleThumbnailSpec; #include <unistd.h> #endif -#include "blist.h" -#include "conversation.h" +#include "buddylist.h" +#include "conversations.h" #include "ft.h" #include "imgstore.h" #include "media.h" @@ -332,13 +332,13 @@ struct _PurplePluginProtocolInfo void (*set_info)(PurpleConnection *, const char *info); /** - * @return If this protocol requires the PURPLE_TYPING message to + * @return If this protocol requires the PURPLE_IM_TYPING message to * be sent repeatedly to signify that the user is still * typing, then the PRPL should return the number of * seconds to wait before sending a subsequent notification. * Otherwise the PRPL should return 0. */ - unsigned int (*send_typing)(PurpleConnection *, const char *name, PurpleTypingState state); + unsigned int (*send_typing)(PurpleConnection *, const char *name, PurpleIMTypingState state); /** * Should arrange for purple_notify_userinfo() to be called with diff --git a/libpurple/purple-client.h b/libpurple/purple-client.h index 87378d35ce..5746dbe841 100644 --- a/libpurple/purple-client.h +++ b/libpurple/purple-client.h @@ -2,6 +2,7 @@ #define _PURPLE_CLIENT_H_INCLUDED_ #include <glib.h> +#include <glib-object.h> #include "purple-client-bindings.h" G_BEGIN_DECLS diff --git a/libpurple/purple.h.in b/libpurple/purple.h.in index 327bea0f9c..22114942d0 100644 --- a/libpurple/purple.h.in +++ b/libpurple/purple.h.in @@ -44,16 +44,16 @@ @PLUGINS_DEFINE@ -#include <account.h> +#include <accounts.h> #include <accountopt.h> -#include <blist.h> +#include <buddylist.h> #include <buddyicon.h> #include <certificate.h> #include <cipher.h> -#include <circbuffer.h> +#include <circularbuffer.h> #include <cmds.h> #include <connection.h> -#include <conversation.h> +#include <conversations.h> #include <core.h> #include <debug.h> #include <desktopitem.h> @@ -75,7 +75,7 @@ #include <pluginpref.h> #include <pounce.h> #include <prefs.h> -#include <privacy.h> +#include <presence.h> #include <proxy.h> #include <prpl.h> #include <request.h> @@ -96,7 +96,6 @@ #include <theme-manager.h> #include <upnp.h> #include <util.h> -#include <value.h> #include <version.h> #include <whiteboard.h> #include <xmlnode.h> diff --git a/libpurple/savedstatuses.c b/libpurple/savedstatuses.c index eaee07ee68..924a88cdba 100644 --- a/libpurple/savedstatuses.c +++ b/libpurple/savedstatuses.c @@ -1172,6 +1172,33 @@ purple_savedstatus_activate_for_account(const PurpleSavedStatus *saved_status, } } +static PurpleSavedStatus * +purple_savedstatus_copy(PurpleSavedStatus *savedstatus) +{ + PurpleSavedStatus *savedstatus_copy; + + g_return_val_if_fail(savedstatus != NULL, NULL); + + savedstatus_copy = g_new(PurpleSavedStatus, 1); + *savedstatus_copy = *savedstatus; + + return savedstatus_copy; +} + +GType +purple_savedstatus_get_g_type(void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static("PurpleSavedStatus", + (GBoxedCopyFunc)purple_savedstatus_copy, + (GBoxedFreeFunc)g_free); + } + + return type; +} + void * purple_savedstatuses_get_handle(void) { @@ -1204,26 +1231,20 @@ purple_savedstatuses_init(void) load_statuses(); purple_signal_register(handle, "savedstatus-changed", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_SAVEDSTATUS), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_SAVEDSTATUS)); + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_SAVEDSTATUS, PURPLE_TYPE_SAVEDSTATUS); purple_signal_register(handle, "savedstatus-added", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_SAVEDSTATUS)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_SAVEDSTATUS); purple_signal_register(handle, "savedstatus-deleted", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_SAVEDSTATUS)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_SAVEDSTATUS); purple_signal_register(handle, "savedstatus-modified", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_SAVEDSTATUS)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_SAVEDSTATUS); purple_signal_connect(purple_accounts_get_handle(), "account-removed", handle, diff --git a/libpurple/savedstatuses.h b/libpurple/savedstatuses.h index 53be07cd55..0e2686588a 100644 --- a/libpurple/savedstatuses.h +++ b/libpurple/savedstatuses.h @@ -54,6 +54,7 @@ * something we should look into once the status box gets fleshed * out more. */ +#define PURPLE_TYPE_SAVEDSTATUS (purple_savedstatus_get_g_type()) typedef struct _PurpleSavedStatus PurpleSavedStatus; typedef struct _PurpleSavedStatusSub PurpleSavedStatusSub; @@ -68,6 +69,13 @@ G_BEGIN_DECLS /*@{*/ /** + * Returns the GType for the PurpleSavedStatus boxed structure. + * TODO Boxing of PurpleSavedStatus is a temporary solution to having a GType + * for saved statuses. This should rather be a GObject instead of a GBoxed. + */ +GType purple_savedstatus_get_g_type(void); + +/** * Create a new saved status. This will add the saved status to the * list of saved statuses and writes the revised list to status.xml. * diff --git a/libpurple/server.c b/libpurple/server.c index ded5f084ae..96130529a3 100644 --- a/libpurple/server.c +++ b/libpurple/server.c @@ -24,13 +24,12 @@ /* This file is the fullcrap */ #include "internal.h" -#include "blist.h" +#include "buddylist.h" #include "conversation.h" #include "debug.h" #include "log.h" #include "notify.h" #include "prefs.h" -#include "privacy.h" #include "prpl.h" #include "request.h" #include "signals.h" @@ -42,7 +41,7 @@ #define SEX_BEFORE_RESENDING_AUTORESPONSE "Only after you're married" unsigned int -serv_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state) +serv_send_typing(PurpleConnection *gc, const char *name, PurpleIMTypingState state) { PurplePlugin *prpl; PurplePluginProtocolInfo *prpl_info; @@ -120,7 +119,7 @@ get_last_auto_response(PurpleConnection *gc, const char *name) int serv_send_im(PurpleConnection *gc, const char *name, const char *message, PurpleMessageFlags flags) { - PurpleConversation *conv = NULL; + PurpleIMConversation *im = NULL; PurpleAccount *account = NULL; PurplePresence *presence = NULL; PurplePlugin *prpl = NULL; @@ -139,7 +138,7 @@ int serv_send_im(PurpleConnection *gc, const char *name, const char *message, account = purple_connection_get_account(gc); presence = purple_account_get_presence(account); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, account); + im = purple_conversations_find_im_with_account(name, account); if (prpl_info->send_im) val = prpl_info->send_im(gc, name, message, flags); @@ -149,7 +148,7 @@ int serv_send_im(PurpleConnection *gc, const char *name, const char *message, * this only reset lar->sent if we're away AND idle? */ auto_reply_pref = purple_prefs_get_string("/purple/away/auto_reply"); - if((purple_connection_get_flags(gc) & PURPLE_CONNECTION_AUTO_RESP) && + if((purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_AUTO_RESP) && !purple_presence_is_available(presence) && !purple_strequal(auto_reply_pref, "never")) { @@ -158,8 +157,8 @@ int serv_send_im(PurpleConnection *gc, const char *name, const char *message, lar->sent = time(NULL); } - if(conv && purple_conv_im_get_send_typed_timeout(PURPLE_CONV_IM(conv))) - purple_conv_im_stop_send_typed_timeout(PURPLE_CONV_IM(conv)); + if(im && purple_im_conversation_get_send_typed_timeout(im)) + purple_im_conversation_stop_send_typed_timeout(im); return val; } @@ -226,7 +225,7 @@ void serv_alias_buddy(PurpleBuddy *b) if (prpl_info->alias_buddy) prpl_info->alias_buddy(gc, purple_buddy_get_name(b), - purple_buddy_get_local_buddy_alias(b)); + purple_buddy_get_local_alias(b)); } } } @@ -238,10 +237,10 @@ serv_got_alias(PurpleConnection *gc, const char *who, const char *alias) PurpleAccount *account; GSList *buddies; PurpleBuddy *b; - PurpleConversation *conv; + PurpleIMConversation *im; account = purple_connection_get_account(gc); - buddies = purple_find_buddies(account, who); + buddies = purple_blist_find_buddies(account, who); while (buddies != NULL) { @@ -255,17 +254,17 @@ serv_got_alias(PurpleConnection *gc, const char *who, const char *alias) if (purple_strequal(server_alias, alias)) continue; - purple_blist_server_alias_buddy(b, alias); + purple_buddy_set_server_alias(b, alias); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(b), account); - if (conv != NULL && alias != NULL && !purple_strequal(alias, who)) + im = purple_conversations_find_im_with_account(purple_buddy_get_name(b), account); + if (im != NULL && alias != NULL && !purple_strequal(alias, who)) { char *escaped = g_markup_escape_text(who, -1); char *escaped2 = g_markup_escape_text(alias, -1); char *tmp = g_strdup_printf(_("%s is now known as %s.\n"), escaped, escaped2); - purple_conversation_write(conv, NULL, tmp, + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, tmp, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, time(NULL)); @@ -284,7 +283,7 @@ purple_serv_got_private_alias(PurpleConnection *gc, const char *who, const char PurpleBuddy *b = NULL; account = purple_connection_get_account(gc); - buddies = purple_find_buddies(account, who); + buddies = purple_blist_find_buddies(account, who); while(buddies != NULL) { const char *balias; @@ -292,11 +291,11 @@ purple_serv_got_private_alias(PurpleConnection *gc, const char *who, const char buddies = g_slist_delete_link(buddies, buddies); - balias = purple_buddy_get_local_buddy_alias(b); + balias = purple_buddy_get_local_alias(b); if (purple_strequal(balias, alias)) continue; - purple_blist_alias_buddy(b, alias); + purple_buddy_set_local_alias(b, alias); } } @@ -467,12 +466,12 @@ void serv_chat_invite(PurpleConnection *gc, int id, const char *message, const c { PurplePlugin *prpl = NULL; PurplePluginProtocolInfo *prpl_info = NULL; - PurpleConversation *conv; + PurpleChatConversation *chat; char *buffy = message && *message ? g_strdup(message) : NULL; - conv = purple_find_chat(gc, id); + chat = purple_conversations_find_chat(gc, id); - if(conv == NULL) + if(chat == NULL) return; if(gc) @@ -482,18 +481,18 @@ void serv_chat_invite(PurpleConnection *gc, int id, const char *message, const c prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); purple_signal_emit(purple_conversations_get_handle(), "chat-inviting-user", - conv, name, &buffy); + chat, name, &buffy); if (prpl_info && prpl_info->chat_invite) prpl_info->chat_invite(gc, id, buffy, name); purple_signal_emit(purple_conversations_get_handle(), "chat-invited-user", - conv, name, buffy); + chat, name, buffy); g_free(buffy); } -/* Ya know, nothing uses this except purple_conversation_destroy(), +/* Ya know, nothing uses this except purple_chat_conversation_dispose(), * I think I'll just merge it into that later... * Then again, something might want to use this, from outside prpl-land * to leave a chat without destroying the conversation. @@ -546,7 +545,7 @@ void serv_got_im(PurpleConnection *gc, const char *who, const char *msg, PurpleMessageFlags flags, time_t mtime) { PurpleAccount *account; - PurpleConversation *conv; + PurpleIMConversation *im; char *message, *name; char *angel, *buffy; int plugin_return; @@ -560,7 +559,7 @@ void serv_got_im(PurpleConnection *gc, const char *who, const char *msg, */ flags |= PURPLE_MESSAGE_RECV; - if (!purple_privacy_check(account, who)) { + if (!purple_account_privacy_check(account, who)) { purple_signal_emit(purple_conversations_get_handle(), "blocked-im-msg", account, who, msg, flags, (unsigned int)mtime); return; @@ -570,7 +569,7 @@ void serv_got_im(PurpleConnection *gc, const char *who, const char *msg, * We should update the conversation window buttons and menu, * if it exists. */ - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, purple_connection_get_account(gc)); + im = purple_conversations_find_im_with_account(who, purple_connection_get_account(gc)); /* * Make copies of the message and the sender in case plugins want @@ -582,7 +581,7 @@ void serv_got_im(PurpleConnection *gc, const char *who, const char *msg, plugin_return = GPOINTER_TO_INT( purple_signal_emit_return_1(purple_conversations_get_handle(), "receiving-im-msg", purple_connection_get_account(gc), - &angel, &buffy, conv, &flags)); + &angel, &buffy, im, &flags)); if (!buffy || !angel || plugin_return) { g_free(buffy); @@ -594,16 +593,16 @@ void serv_got_im(PurpleConnection *gc, const char *who, const char *msg, message = buffy; purple_signal_emit(purple_conversations_get_handle(), "received-im-msg", purple_connection_get_account(gc), - name, message, conv, flags); + name, message, im, flags); /* search for conversation again in case it was created by received-im-msg handler */ - if (conv == NULL) - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, purple_connection_get_account(gc)); + if (im == NULL) + im = purple_conversations_find_im_with_account(name, purple_connection_get_account(gc)); - if (conv == NULL) - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name); + if (im == NULL) + im = purple_im_conversation_new(account, name); - purple_conv_im_write(PURPLE_CONV_IM(conv), name, message, flags, mtime); + purple_conversation_write_message(PURPLE_CONVERSATION(im), name, message, flags, mtime); g_free(message); /* @@ -615,7 +614,7 @@ void serv_got_im(PurpleConnection *gc, const char *who, const char *msg, * - or we're not idle and the 'only auto respond if idle' pref * is set */ - if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_AUTO_RESP) + if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_AUTO_RESP) { PurplePresence *presence; PurpleStatus *status; @@ -629,7 +628,7 @@ void serv_got_im(PurpleConnection *gc, const char *who, const char *msg, presence = purple_account_get_presence(account); status = purple_presence_get_active_status(presence); - status_type = purple_status_get_type(status); + status_type = purple_status_get_status_type(status); primitive = purple_status_type_get_primitive(status_type); mobile = purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_MOBILE); if ((primitive == PURPLE_STATUS_AVAILABLE) || @@ -642,7 +641,7 @@ void serv_got_im(PurpleConnection *gc, const char *who, const char *msg, return; } - away_msg = purple_value_get_string( + away_msg = g_value_get_string( purple_status_get_attr_value(status, "message")); if ((away_msg != NULL) && (*away_msg != '\0')) { @@ -672,7 +671,7 @@ void serv_got_im(PurpleConnection *gc, const char *who, const char *msg, { serv_send_im(gc, name, away_msg, PURPLE_MESSAGE_AUTO_RESP); - purple_conv_im_write(PURPLE_CONV_IM(conv), NULL, away_msg, + purple_conversation_write_message(PURPLE_CONVERSATION(im), NULL, away_msg, PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_AUTO_RESP, mtime); } @@ -684,52 +683,46 @@ void serv_got_im(PurpleConnection *gc, const char *who, const char *msg, } void serv_got_typing(PurpleConnection *gc, const char *name, int timeout, - PurpleTypingState state) { - PurpleConversation *conv; - PurpleConvIm *im = NULL; + PurpleIMTypingState state) { + PurpleIMConversation *im; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, purple_connection_get_account(gc)); - if (conv != NULL) { - im = PURPLE_CONV_IM(conv); - - purple_conv_im_set_typing_state(im, state); + im = purple_conversations_find_im_with_account(name, purple_connection_get_account(gc)); + if (im != NULL) { + purple_im_conversation_set_typing_state(im, state); } else { switch (state) { - case PURPLE_TYPING: + case PURPLE_IM_TYPING: purple_signal_emit(purple_conversations_get_handle(), "buddy-typing", purple_connection_get_account(gc), name); break; - case PURPLE_TYPED: + case PURPLE_IM_TYPED: purple_signal_emit(purple_conversations_get_handle(), "buddy-typed", purple_connection_get_account(gc), name); break; - case PURPLE_NOT_TYPING: + case PURPLE_IM_NOT_TYPING: purple_signal_emit(purple_conversations_get_handle(), "buddy-typing-stopped", purple_connection_get_account(gc), name); break; } } - if (conv != NULL && timeout > 0) - purple_conv_im_start_typing_timeout(im, timeout); + if (im != NULL && timeout > 0) + purple_im_conversation_start_typing_timeout(im, timeout); } void serv_got_typing_stopped(PurpleConnection *gc, const char *name) { - PurpleConversation *conv; - PurpleConvIm *im; + PurpleIMConversation *im; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, purple_connection_get_account(gc)); - if (conv != NULL) + im = purple_conversations_find_im_with_account(name, purple_connection_get_account(gc)); + if (im != NULL) { - im = PURPLE_CONV_IM(conv); - - if (purple_conv_im_get_typing_state(im) == PURPLE_NOT_TYPING) + if (purple_im_conversation_get_typing_state(im) == PURPLE_IM_NOT_TYPING) return; - purple_conv_im_stop_typing_timeout(im); - purple_conv_im_set_typing_state(im, PURPLE_NOT_TYPING); + purple_im_conversation_stop_typing_timeout(im); + purple_im_conversation_set_typing_state(im, PURPLE_IM_NOT_TYPING); } else { @@ -778,7 +771,7 @@ void serv_got_chat_invite(PurpleConnection *gc, const char *name, g_return_if_fail(who != NULL); account = purple_connection_get_account(gc); - if (!purple_privacy_check(account, who)) { + if (!purple_account_privacy_check(account, who)) { purple_signal_emit(purple_conversations_get_handle(), "chat-invite-blocked", account, who, name, message, data); return; @@ -818,11 +811,10 @@ void serv_got_chat_invite(PurpleConnection *gc, const char *name, chat_invite_reject(cid); } -PurpleConversation *serv_got_joined_chat(PurpleConnection *gc, +PurpleChatConversation *serv_got_joined_chat(PurpleConnection *gc, int id, const char *name) { - PurpleConversation *conv; - PurpleConvChat *chat; + PurpleChatConversation *chat; PurpleAccount *account; account = purple_connection_get_account(gc); @@ -830,49 +822,39 @@ PurpleConversation *serv_got_joined_chat(PurpleConnection *gc, g_return_val_if_fail(account != NULL, NULL); g_return_val_if_fail(name != NULL, NULL); - conv = purple_conversation_new(PURPLE_CONV_TYPE_CHAT, account, name); - g_return_val_if_fail(conv != NULL, NULL); - - chat = PURPLE_CONV_CHAT(conv); + chat = purple_chat_conversation_new(account, name); + g_return_val_if_fail(chat != NULL, NULL); - if (!g_slist_find(gc->buddy_chats, conv)) - gc->buddy_chats = g_slist_append(gc->buddy_chats, conv); + if (!g_slist_find(purple_connection_get_active_chats(gc), chat)) + _purple_connection_add_active_chat(gc, chat); - purple_conv_chat_set_id(chat, id); + purple_chat_conversation_set_id(chat, id); - purple_signal_emit(purple_conversations_get_handle(), "chat-joined", conv); + purple_signal_emit(purple_conversations_get_handle(), "chat-joined", chat); - return conv; + return chat; } void serv_got_chat_left(PurpleConnection *g, int id) { GSList *bcs; - PurpleConversation *conv = NULL; - PurpleConvChat *chat = NULL; + PurpleChatConversation *chat = NULL; - for (bcs = g->buddy_chats; bcs != NULL; bcs = bcs->next) { - conv = (PurpleConversation *)bcs->data; + for (bcs = purple_connection_get_active_chats(g); bcs != NULL; bcs = bcs->next) { + chat = PURPLE_CHAT_CONVERSATION(bcs->data); - chat = PURPLE_CONV_CHAT(conv); - - if (purple_conv_chat_get_id(chat) == id) + if (purple_chat_conversation_get_id(chat) == id) break; - - conv = NULL; } - if (!conv) - return; - purple_debug(PURPLE_DEBUG_INFO, "server", "Leaving room: %s\n", - purple_conversation_get_name(conv)); + purple_conversation_get_name(PURPLE_CONVERSATION(chat))); - g->buddy_chats = g_slist_remove(g->buddy_chats, conv); + _purple_connection_remove_active_chat(g, chat); - purple_conv_chat_left(PURPLE_CONV_CHAT(conv)); + purple_chat_conversation_leave(chat); - purple_signal_emit(purple_conversations_get_handle(), "chat-left", conv); + purple_signal_emit(purple_conversations_get_handle(), "chat-left", chat); } void purple_serv_got_join_chat_failed(PurpleConnection *gc, GHashTable *data) @@ -885,31 +867,24 @@ void serv_got_chat_in(PurpleConnection *g, int id, const char *who, PurpleMessageFlags flags, const char *message, time_t mtime) { GSList *bcs; - PurpleConversation *conv = NULL; - PurpleConvChat *chat = NULL; + PurpleChatConversation *chat = NULL; char *buffy, *angel; int plugin_return; g_return_if_fail(who != NULL); g_return_if_fail(message != NULL); - for (bcs = g->buddy_chats; bcs != NULL; bcs = bcs->next) { - conv = (PurpleConversation *)bcs->data; - - chat = PURPLE_CONV_CHAT(conv); + for (bcs = purple_connection_get_active_chats(g); bcs != NULL; bcs = bcs->next) { + chat = PURPLE_CHAT_CONVERSATION(bcs->data); - if (purple_conv_chat_get_id(chat) == id) + if (purple_chat_conversation_get_id(chat) == id) break; - - conv = NULL; } - if (!conv) - return; - /* Did I send the message? */ - if (purple_strequal(purple_conv_chat_get_nick(chat), - purple_normalize(purple_conversation_get_account(conv), who))) { + if (purple_strequal(purple_chat_conversation_get_nick(chat), + purple_normalize(purple_conversation_get_account( + PURPLE_CONVERSATION(chat)), who))) { flags |= PURPLE_MESSAGE_SEND; flags &= ~PURPLE_MESSAGE_RECV; /* Just in case some prpl sets it! */ } else { @@ -926,7 +901,7 @@ void serv_got_chat_in(PurpleConnection *g, int id, const char *who, plugin_return = GPOINTER_TO_INT( purple_signal_emit_return_1(purple_conversations_get_handle(), "receiving-chat-msg", purple_connection_get_account(g), - &angel, &buffy, conv, &flags)); + &angel, &buffy, chat, &flags)); if (!buffy || !angel || plugin_return) { g_free(buffy); @@ -938,9 +913,9 @@ void serv_got_chat_in(PurpleConnection *g, int id, const char *who, message = buffy; purple_signal_emit(purple_conversations_get_handle(), "received-chat-msg", purple_connection_get_account(g), - who, message, conv, flags); + who, message, chat, flags); - purple_conv_chat_write(chat, who, message, flags, mtime); + purple_conversation_write_message(PURPLE_CONVERSATION(chat), who, message, flags, mtime); g_free(angel); g_free(buffy); diff --git a/libpurple/server.h b/libpurple/server.h index d80b05d224..66c40288a2 100644 --- a/libpurple/server.h +++ b/libpurple/server.h @@ -26,8 +26,8 @@ #ifndef _PURPLE_SERVER_H_ #define _PURPLE_SERVER_H_ -#include "account.h" -#include "conversation.h" +#include "accounts.h" +#include "conversations.h" #include "prpl.h" G_BEGIN_DECLS @@ -39,16 +39,16 @@ G_BEGIN_DECLS * * @param gc The connection over which to send the typing notification. * @param name The user to send the typing notification to. - * @param state One of PURPLE_TYPING, PURPLE_TYPED, or PURPLE_NOT_TYPING. + * @param state One of PURPLE_IM_TYPING, PURPLE_IM_TYPED, or PURPLE_IM_NOT_TYPING. * @return A quiet-period, specified in seconds, where Purple will not * send any additional typing notification messages. Most * protocols should return 0, which means that no additional - * PURPLE_TYPING messages need to be sent. If this is 5, for + * PURPLE_IM_TYPING messages need to be sent. If this is 5, for * example, then Purple will wait five seconds, and if the Purple - * user is still typing then Purple will send another PURPLE_TYPING + * user is still typing then Purple will send another PURPLE_IM_TYPING * message. */ -unsigned int serv_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state); +unsigned int serv_send_typing(PurpleConnection *gc, const char *name, PurpleIMTypingState state); void serv_move_buddy(PurpleBuddy *, PurpleGroup *, PurpleGroup *); int serv_send_im(PurpleConnection *, const char *, const char *, PurpleMessageFlags flags); @@ -87,8 +87,8 @@ void purple_serv_got_private_alias(PurpleConnection *gc, const char *who, const /** - * Receive a typing message from a remote user. Either PURPLE_TYPING - * or PURPLE_TYPED. If the user has stopped typing then use + * Receive a typing message from a remote user. Either PURPLE_IM_TYPING + * or PURPLE_IM_TYPED. If the user has stopped typing then use * serv_got_typing_stopped instead. * * TODO: Could probably move this into the conversation API. @@ -97,13 +97,13 @@ void purple_serv_got_private_alias(PurpleConnection *gc, const char *who, const * @param name The name of the remote user. * @param timeout If this is a number greater than 0, then * Purple will wait this number of seconds and then - * set this buddy to the PURPLE_NOT_TYPING state. This + * set this buddy to the PURPLE_IM_NOT_TYPING state. This * is used by protocols that send repeated typing messages * while the user is composing the message. * @param state The typing state received */ void serv_got_typing(PurpleConnection *gc, const char *name, int timeout, - PurpleTypingState state); + PurpleIMTypingState state); /** * TODO: Could probably move this into the conversation API. @@ -148,7 +148,7 @@ void serv_got_chat_invite(PurpleConnection *gc, const char *name, * @param name The name of the chat. * @return The resulting conversation */ -PurpleConversation *serv_got_joined_chat(PurpleConnection *gc, +PurpleChatConversation *serv_got_joined_chat(PurpleConnection *gc, int id, const char *name); /** * Called by a prpl when an attempt to join a chat via serv_join_chat() diff --git a/libpurple/signals.c b/libpurple/signals.c index 60d7d2d7f1..d9cf2737fc 100644 --- a/libpurple/signals.c +++ b/libpurple/signals.c @@ -28,7 +28,6 @@ #include "dbus-maybe.h" #include "debug.h" #include "signals.h" -#include "value.h" /* must include this to use G_VA_COPY */ #include <string.h> @@ -51,8 +50,8 @@ typedef struct PurpleSignalMarshalFunc marshal; int num_values; - PurpleValue **values; - PurpleValue *ret_value; + GType *value_types; + GType ret_type; GList *handlers; size_t handler_count; @@ -87,25 +86,14 @@ destroy_signal_data(PurpleSignalData *signal_data) g_list_foreach(signal_data->handlers, (GFunc)g_free, NULL); g_list_free(signal_data->handlers); - if (signal_data->values != NULL) - { - int i; - - for (i = 0; i < signal_data->num_values; i++) - purple_value_destroy((PurpleValue *)signal_data->values[i]); - - g_free(signal_data->values); - } - - if (signal_data->ret_value != NULL) - purple_value_destroy(signal_data->ret_value); + g_free(signal_data->value_types); g_free(signal_data); } gulong purple_signal_register(void *instance, const char *signal, PurpleSignalMarshalFunc marshal, - PurpleValue *ret_value, int num_values, ...) + GType ret_type, int num_values, ...) { PurpleInstanceData *instance_data; PurpleSignalData *signal_data; @@ -136,19 +124,19 @@ purple_signal_register(void *instance, const char *signal, signal_data->id = instance_data->next_signal_id; signal_data->marshal = marshal; signal_data->next_handler_id = 1; - signal_data->ret_value = ret_value; + signal_data->ret_type = ret_type; signal_data->num_values = num_values; if (num_values > 0) { int i; - signal_data->values = g_new0(PurpleValue *, num_values); + signal_data->value_types = g_new0(GType, num_values); va_start(args, num_values); for (i = 0; i < num_values; i++) - signal_data->values[i] = va_arg(args, PurpleValue *); + signal_data->value_types[i] = va_arg(args, GType); va_end(args); } @@ -203,17 +191,17 @@ purple_signals_unregister_by_instance(void *instance) } void -purple_signal_get_values(void *instance, const char *signal, - PurpleValue **ret_value, - int *num_values, PurpleValue ***values) +purple_signal_get_types(void *instance, const char *signal, + GType *ret_type, + int *num_values, GType **value_types) { PurpleInstanceData *instance_data; PurpleSignalData *signal_data; - g_return_if_fail(instance != NULL); - g_return_if_fail(signal != NULL); - g_return_if_fail(num_values != NULL); - g_return_if_fail(values != NULL); + g_return_if_fail(instance != NULL); + g_return_if_fail(signal != NULL); + g_return_if_fail(num_values != NULL); + g_return_if_fail(value_types != NULL); /* Get the instance data */ instance_data = @@ -227,11 +215,11 @@ purple_signal_get_values(void *instance, const char *signal, g_return_if_fail(signal_data != NULL); - *num_values = signal_data->num_values; - *values = signal_data->values; + *num_values = signal_data->num_values; + *value_types = signal_data->value_types; - if (ret_value != NULL) - *ret_value = signal_data->ret_value; + if (ret_type != NULL) + *ret_type = signal_data->ret_type; } static gint handler_priority(void * a, void * b) { @@ -488,7 +476,7 @@ purple_signal_emit_vargs(void *instance, const char *signal, va_list args) #ifdef HAVE_DBUS purple_dbus_signal_emit_purple(signal, signal_data->num_values, - signal_data->values, args); + signal_data->value_types, args); #endif /* HAVE_DBUS */ } @@ -540,7 +528,7 @@ purple_signal_emit_vargs_return_1(void *instance, const char *signal, #ifdef HAVE_DBUS G_VA_COPY(tmp, args); purple_dbus_signal_emit_purple(signal, signal_data->num_values, - signal_data->values, tmp); + signal_data->value_types, tmp); va_end(tmp); #endif /* HAVE_DBUS */ @@ -693,6 +681,17 @@ purple_marshal_VOID__POINTER_POINTER_UINT_UINT(PurpleCallback cb, va_list args, } void +purple_marshal_VOID__POINTER_UINT_UINT(PurpleCallback cb, va_list args, + void *data, void **return_val) +{ + void *arg1 = va_arg(args, void *); + guint arg2 = va_arg(args, guint); + guint arg3 = va_arg(args, guint); + + ((void (*)(void *, guint, guint, void *))cb)(arg1, arg2, arg3, data); +} + +void purple_marshal_VOID__POINTER_POINTER_POINTER(PurpleCallback cb, va_list args, void *data, void **return_val) { diff --git a/libpurple/signals.h b/libpurple/signals.h index aa732050ef..19e506f8d6 100644 --- a/libpurple/signals.h +++ b/libpurple/signals.h @@ -27,7 +27,7 @@ #define _PURPLE_SIGNALS_H_ #include <glib.h> -#include "value.h" +#include <glib-object.h> #define PURPLE_CALLBACK(func) ((PurpleCallback)func) @@ -68,18 +68,16 @@ G_BEGIN_DECLS * @param instance The instance to register the signal for. * @param signal The signal name. * @param marshal The marshal function. - * @param ret_value The return value type, or NULL for no return value. + * @param ret_type The return type, or G_TYPE_NONE for no return type. * @param num_values The number of values to be passed to the callbacks. * @param ... The values to pass to the callbacks. * * @return The signal ID local to that instance, or 0 if the signal * couldn't be registered. - * - * @see PurpleValue */ gulong purple_signal_register(void *instance, const char *signal, PurpleSignalMarshalFunc marshal, - PurpleValue *ret_value, int num_values, ...); + GType ret_type, int num_values, ...); /** * Unregisters a signal in an instance. @@ -99,15 +97,15 @@ void purple_signals_unregister_by_instance(void *instance); /** * Returns a list of value types used for a signal. * - * @param instance The instance the signal is registered to. - * @param signal The signal. - * @param ret_value The return value from the last signal handler. - * @param num_values The returned number of values. - * @param values The returned list of values. + * @param instance The instance the signal is registered to. + * @param signal The signal. + * @param ret_type The return type. + * @param num_values The returned number of values. + * @param value_types The returned list of values. */ -void purple_signal_get_values(void *instance, const char *signal, - PurpleValue **ret_value, - int *num_values, PurpleValue ***values); +void purple_signal_get_types(void *instance, const char *signal, + GType *ret_type, int *num_values, + GType **value_types); /** * Connects a signal handler to a signal for a particular object. @@ -309,6 +307,8 @@ void purple_marshal_VOID__POINTER_POINTER_UINT( PurpleCallback cb, va_list args, void *data, void **return_val); void purple_marshal_VOID__POINTER_POINTER_UINT_UINT( PurpleCallback cb, va_list args, void *data, void **return_val); +void purple_marshal_VOID__POINTER_UINT_UINT( + PurpleCallback cb, va_list args, void *data, void **return_val); void purple_marshal_VOID__POINTER_POINTER_POINTER( PurpleCallback cb, va_list args, void *data, void **return_val); void purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER( diff --git a/libpurple/smiley.c b/libpurple/smiley.c index 6d5131129d..9a3fbfdf79 100644 --- a/libpurple/smiley.c +++ b/libpurple/smiley.c @@ -32,25 +32,21 @@ #include "util.h" #include "xmlnode.h" +#define PURPLE_SMILEY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_SMILEY, PurpleSmileyPrivate)) + /**************************************************************************/ -/* Main structures, members and constants */ +/* Structs */ /**************************************************************************/ -struct _PurpleSmiley -{ - GObject parent; +typedef struct { PurpleStoredImage *img; /**< The id of the stored image with the the smiley data. */ char *shortcut; /**< Shortcut associated with the custom smiley. This field will work as a unique key by this API. */ char *checksum; /**< The smiley checksum. */ -}; - -struct _PurpleSmileyClass -{ - GObjectClass parent_class; -}; +} PurpleSmileyPrivate; static GHashTable *smiley_shortcut_index = NULL; /* shortcut (char *) => smiley (PurpleSmiley*) */ static GHashTable *smiley_checksum_index = NULL; /* checksum (char *) => smiley (PurpleSmiley*) */ @@ -134,6 +130,7 @@ purple_smiley_data_unstore(const char *filename); static xmlnode * smiley_to_xmlnode(PurpleSmiley *smiley) { + PurpleSmileyPrivate *priv = NULL; xmlnode *smiley_node = NULL; smiley_node = xmlnode_new(XML_SMILEY_TAG); @@ -141,14 +138,16 @@ smiley_to_xmlnode(PurpleSmiley *smiley) if (!smiley_node) return NULL; + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + xmlnode_set_attrib(smiley_node, XML_SHORTCUT_ATTRIB_TAG, - smiley->shortcut); + priv->shortcut); xmlnode_set_attrib(smiley_node, XML_CHECKSUM_ATRIB_TAG, - smiley->checksum); + priv->checksum); xmlnode_set_attrib(smiley_node, XML_FILENAME_ATRIB_TAG, - purple_imgstore_get_filename(smiley->img)); + purple_imgstore_get_filename(priv->img)); return smiley_node; } @@ -310,12 +309,14 @@ purple_smiley_get_property(GObject *object, guint param_id, GValue *value, GParamSpec *spec) { PurpleSmiley *smiley = PURPLE_SMILEY(object); + PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + switch (param_id) { case PROP_SHORTCUT: - g_value_set_string(value, smiley->shortcut); + g_value_set_string(value, priv->shortcut); break; case PROP_IMGSTORE: - g_value_set_pointer(value, smiley->img); + g_value_set_pointer(value, priv->img); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, spec); @@ -328,6 +329,8 @@ purple_smiley_set_property(GObject *object, guint param_id, const GValue *value, GParamSpec *spec) { PurpleSmiley *smiley = PURPLE_SMILEY(object); + PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + switch (param_id) { case PROP_SHORTCUT: { @@ -339,18 +342,18 @@ purple_smiley_set_property(GObject *object, guint param_id, const GValue *value, { PurpleStoredImage *img = g_value_get_pointer(value); - purple_imgstore_unref(smiley->img); - g_free(smiley->checksum); + purple_imgstore_unref(priv->img); + g_free(priv->checksum); - smiley->img = img; + priv->img = img; if (img) { - smiley->checksum = g_compute_checksum_for_data( + priv->checksum = g_compute_checksum_for_data( G_CHECKSUM_SHA1, purple_imgstore_get_data(img), purple_imgstore_get_size(img)); purple_smiley_data_store(img); } else { - smiley->checksum = NULL; + priv->checksum = NULL; } g_object_notify(object, PROP_IMGSTORE_S); @@ -366,17 +369,18 @@ static void purple_smiley_finalize(GObject *obj) { PurpleSmiley *smiley = PURPLE_SMILEY(obj); + PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley); - if (g_hash_table_lookup(smiley_shortcut_index, smiley->shortcut)) { - g_hash_table_remove(smiley_shortcut_index, smiley->shortcut); - g_hash_table_remove(smiley_checksum_index, smiley->checksum); + if (g_hash_table_lookup(smiley_shortcut_index, priv->shortcut)) { + g_hash_table_remove(smiley_shortcut_index, priv->shortcut); + g_hash_table_remove(smiley_checksum_index, priv->checksum); } - g_free(smiley->shortcut); - g_free(smiley->checksum); - if (smiley->img) - purple_smiley_data_unstore(purple_imgstore_get_filename(smiley->img)); - purple_imgstore_unref(smiley->img); + g_free(priv->shortcut); + g_free(priv->checksum); + if (priv->img) + purple_smiley_data_unstore(purple_imgstore_get_filename(priv->img)); + purple_imgstore_unref(priv->img); PURPLE_DBUS_UNREGISTER_POINTER(smiley); @@ -398,6 +402,8 @@ purple_smiley_class_init(PurpleSmileyClass *klass) parent_class = g_type_class_peek_parent(klass); + g_type_class_add_private(klass, sizeof(PurpleSmileyPrivate)); + gobj_class->get_property = purple_smiley_get_property; gobj_class->set_property = purple_smiley_set_property; gobj_class->finalize = purple_smiley_finalize; @@ -473,6 +479,7 @@ static void purple_smiley_load_file(const char *shortcut, const char *checksum, const char *filename) { PurpleSmiley *smiley = NULL; + PurpleSmileyPrivate *priv = NULL; guchar *smiley_data; size_t smiley_data_len; char *fullpath = NULL; @@ -493,7 +500,9 @@ purple_smiley_load_file(const char *shortcut, const char *checksum, const char * return; } - smiley->checksum = g_strdup(checksum); + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + + priv->checksum = g_strdup(checksum); if (read_smiley_file(fullpath, &smiley_data, &smiley_data_len)) purple_smiley_set_data_impl(smiley, smiley_data, @@ -616,6 +625,7 @@ static void purple_smiley_set_data_impl(PurpleSmiley *smiley, guchar *smiley_data, size_t smiley_data_len) { + PurpleSmileyPrivate *priv = NULL; PurpleStoredImage *old_img, *new_img; const char *old_filename = NULL; const char *new_filename = NULL; @@ -624,7 +634,9 @@ purple_smiley_set_data_impl(PurpleSmiley *smiley, guchar *smiley_data, g_return_if_fail(smiley_data != NULL); g_return_if_fail(smiley_data_len > 0); - old_img = smiley->img; + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + + old_img = priv->img; new_img = purple_smiley_data_new(smiley_data, smiley_data_len); @@ -636,7 +648,7 @@ purple_smiley_set_data_impl(PurpleSmiley *smiley, guchar *smiley_data, return; old_filename = purple_imgstore_get_filename(old_img); - new_filename = purple_imgstore_get_filename(smiley->img); + new_filename = purple_imgstore_get_filename(priv->img); if (g_ascii_strcasecmp(old_filename, new_filename)) purple_smiley_data_unstore(old_filename); @@ -683,7 +695,8 @@ static PurpleSmiley * purple_smiley_new_from_stream(const char *shortcut, guchar *smiley_data, size_t smiley_data_len) { - PurpleSmiley *smiley; + PurpleSmiley *smiley = NULL; + PurpleSmileyPrivate *priv = NULL; g_return_val_if_fail(shortcut != NULL, NULL); g_return_val_if_fail(smiley_data != NULL, NULL); @@ -698,9 +711,10 @@ purple_smiley_new_from_stream(const char *shortcut, guchar *smiley_data, if (!smiley) return NULL; - purple_smiley_set_data_impl(smiley, smiley_data, smiley_data_len); + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); - purple_smiley_data_store(smiley->img); + purple_smiley_set_data_impl(smiley, smiley_data, smiley_data_len); + purple_smiley_data_store(priv->img); return smiley; } @@ -734,6 +748,8 @@ purple_smiley_delete(PurpleSmiley *smiley) gboolean purple_smiley_set_shortcut(PurpleSmiley *smiley, const char *shortcut) { + PurpleSmileyPrivate *priv = NULL; + g_return_val_if_fail(smiley != NULL, FALSE); g_return_val_if_fail(shortcut != NULL, FALSE); @@ -741,15 +757,17 @@ purple_smiley_set_shortcut(PurpleSmiley *smiley, const char *shortcut) if (g_hash_table_lookup(smiley_shortcut_index, shortcut)) return FALSE; + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + /* Remove the old shortcut. */ - if (smiley->shortcut) - g_hash_table_remove(smiley_shortcut_index, smiley->shortcut); + if (priv->shortcut) + g_hash_table_remove(smiley_shortcut_index, priv->shortcut); /* Insert the new shortcut. */ g_hash_table_insert(smiley_shortcut_index, g_strdup(shortcut), smiley); - g_free(smiley->shortcut); - smiley->shortcut = g_strdup(shortcut); + g_free(priv->shortcut); + priv->shortcut = g_strdup(shortcut); g_object_notify(G_OBJECT(smiley), PROP_SHORTCUT_S); @@ -762,18 +780,22 @@ void purple_smiley_set_data(PurpleSmiley *smiley, guchar *smiley_data, size_t smiley_data_len) { + PurpleSmileyPrivate *priv = NULL; + g_return_if_fail(smiley != NULL); g_return_if_fail(smiley_data != NULL); g_return_if_fail(smiley_data_len > 0); + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + /* Remove the previous entry */ - g_hash_table_remove(smiley_checksum_index, smiley->checksum); + g_hash_table_remove(smiley_checksum_index, priv->checksum); /* Update the file data. This also updates the checksum. */ purple_smiley_set_data_impl(smiley, smiley_data, smiley_data_len); /* Reinsert the index item. */ - g_hash_table_insert(smiley_checksum_index, g_strdup(smiley->checksum), smiley); + g_hash_table_insert(smiley_checksum_index, g_strdup(priv->checksum), smiley); purple_smileys_save(); } @@ -781,34 +803,45 @@ purple_smiley_set_data(PurpleSmiley *smiley, guchar *smiley_data, PurpleStoredImage * purple_smiley_get_stored_image(const PurpleSmiley *smiley) { - return purple_imgstore_ref(smiley->img); + PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + return purple_imgstore_ref(priv->img); } const char *purple_smiley_get_shortcut(const PurpleSmiley *smiley) { + PurpleSmileyPrivate *priv = NULL; + g_return_val_if_fail(smiley != NULL, NULL); - return smiley->shortcut; + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + return priv->shortcut; } const char * purple_smiley_get_checksum(const PurpleSmiley *smiley) { + PurpleSmileyPrivate *priv = NULL; + g_return_val_if_fail(smiley != NULL, NULL); - return smiley->checksum; + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + return priv->checksum; } gconstpointer purple_smiley_get_data(const PurpleSmiley *smiley, size_t *len) { + PurpleSmileyPrivate *priv = NULL; + g_return_val_if_fail(smiley != NULL, NULL); - if (smiley->img) { + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + + if (priv->img) { if (len != NULL) - *len = purple_imgstore_get_size(smiley->img); + *len = purple_imgstore_get_size(priv->img); - return purple_imgstore_get_data(smiley->img); + return purple_imgstore_get_data(priv->img); } return NULL; @@ -817,20 +850,26 @@ purple_smiley_get_data(const PurpleSmiley *smiley, size_t *len) const char * purple_smiley_get_extension(const PurpleSmiley *smiley) { - if (smiley->img != NULL) - return purple_imgstore_get_extension(smiley->img); + PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + + if (priv->img != NULL) + return purple_imgstore_get_extension(priv->img); return NULL; } char *purple_smiley_get_full_path(PurpleSmiley *smiley) { + PurpleSmileyPrivate *priv = NULL; + g_return_val_if_fail(smiley != NULL, NULL); - if (smiley->img == NULL) + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + + if (priv->img == NULL) return NULL; - return get_file_full_path(purple_imgstore_get_filename(smiley->img)); + return get_file_full_path(purple_imgstore_get_filename(priv->img)); } static void add_smiley_to_list(gpointer key, gpointer value, gpointer user_data) diff --git a/libpurple/smiley.h b/libpurple/smiley.h index c297d1daf0..d2e3cc2a36 100644 --- a/libpurple/smiley.h +++ b/libpurple/smiley.h @@ -50,6 +50,23 @@ typedef struct _PurpleSmileyClass PurpleSmileyClass; #define PURPLE_IS_SMILEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PURPLE_TYPE_SMILEY)) #define PURPLE_SMILEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PURPLE_TYPE_SMILEY, PurpleSmileyClass)) +struct _PurpleSmiley +{ + /*< private >*/ + GObject parent; +}; + +struct _PurpleSmileyClass +{ + /*< private >*/ + GObjectClass parent_class; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); +}; + G_BEGIN_DECLS /**************************************************************************/ diff --git a/libpurple/sound-theme-loader.h b/libpurple/sound-theme-loader.h index 9eb927b156..f17b049e0e 100644 --- a/libpurple/sound-theme-loader.h +++ b/libpurple/sound-theme-loader.h @@ -48,12 +48,19 @@ typedef struct _PurpleSoundThemeLoaderClass PurpleSoundThemeLoaderClass; struct _PurpleSoundThemeLoader { + /*< private >*/ PurpleThemeLoader parent; }; struct _PurpleSoundThemeLoaderClass { + /*< private >*/ PurpleThemeLoaderClass parent_class; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); }; /**************************************************************************/ diff --git a/libpurple/sound-theme.h b/libpurple/sound-theme.h index adde4fddea..007640264e 100644 --- a/libpurple/sound-theme.h +++ b/libpurple/sound-theme.h @@ -50,12 +50,19 @@ typedef struct _PurpleSoundThemeClass PurpleSoundThemeClass; struct _PurpleSoundTheme { + /*< private >*/ PurpleTheme parent; }; struct _PurpleSoundThemeClass { + /*< private >*/ PurpleThemeClass parent_class; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); }; /**************************************************************************/ diff --git a/libpurple/sound.c b/libpurple/sound.c index 4cb4ebb013..25b22c964c 100644 --- a/libpurple/sound.c +++ b/libpurple/sound.c @@ -22,7 +22,7 @@ */ #include "internal.h" -#include "blist.h" +#include "buddylist.h" #include "prefs.h" #include "sound.h" #include "sound-theme-loader.h" @@ -128,10 +128,7 @@ purple_sound_init() purple_signal_register(handle, "playing-sound-event", purple_marshal_BOOLEAN__INT_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 2, - purple_value_new(PURPLE_TYPE_INT), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT)); + G_TYPE_BOOLEAN, 2, G_TYPE_INT, PURPLE_TYPE_ACCOUNT); purple_prefs_add_none("/purple/sound"); purple_prefs_add_int("/purple/sound/while_status", STATUS_AVAILABLE); diff --git a/libpurple/status.c b/libpurple/status.c index 9d43446efb..c508a36aae 100644 --- a/libpurple/status.c +++ b/libpurple/status.c @@ -1,8 +1,3 @@ -/** - * @file status.c Status API - * @ingroup core - */ - /* purple * * Purple is the legal property of its developers, whose names are too numerous @@ -23,11 +18,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#define _PURPLE_STATUS_C_ - #include "internal.h" - -#include "blist.h" +#include "buddylist.h" #include "core.h" #include "dbus-maybe.h" #include "debug.h" @@ -35,6 +27,12 @@ #include "prefs.h" #include "status.h" +#define PURPLE_STATUS_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_STATUS, PurpleStatusPrivate)) + +/** @copydoc _PurpleStatusPrivate */ +typedef struct _PurpleStatusPrivate PurpleStatusPrivate; + /** * A type of status. */ @@ -55,57 +53,19 @@ struct _PurpleStatusType /** * A status attribute. */ -struct _PurpleStatusAttr +struct _PurpleStatusAttribute { char *id; char *name; - PurpleValue *value_type; -}; - -/** - * A list of statuses. - */ -struct _PurplePresence -{ - PurplePresenceContext context; - - gboolean idle; - time_t idle_time; - time_t login_time; - - GList *statuses; - GHashTable *status_table; - - PurpleStatus *active_status; - - union - { - PurpleAccount *account; - - struct - { - PurpleConversation *conv; - char *user; - - } chat; - - struct - { - PurpleAccount *account; - char *name; - PurpleBuddy *buddy; - - } buddy; - - } u; + GValue *value_type; }; /** - * An active status. + * Private data for PurpleStatus */ -struct _PurpleStatus +struct _PurpleStatusPrivate { - PurpleStatusType *type; + PurpleStatusType *status_type; PurplePresence *presence; gboolean active; @@ -114,17 +74,29 @@ struct _PurpleStatus * The current values of the attributes for this status. The * key is a string containing the name of the attribute. It is * a borrowed reference from the list of attrs in the - * PurpleStatusType. The value is a PurpleValue. + * PurpleStatusType. The value is a GValue. */ GHashTable *attr_values; }; +/* GObject property enums */ +enum +{ + PROP_0, + PROP_STATUS_TYPE, + PROP_PRESENCE, + PROP_ACTIVE, + PROP_LAST +}; + typedef struct { PurpleAccount *account; char *name; } PurpleStatusBuddyKey; +static GObjectClass *parent_class; + static int primitive_scores[] = { 0, /* unset */ @@ -146,6 +118,8 @@ static int primitive_scores[] = #define SCORE_IDLE_TIME 10 #define SCORE_OFFLINE_MESSAGE 11 +int *_purple_get_primitive_scores(void); + /************************************************************************** * PurpleStatusPrimitive API **************************************************************************/ @@ -169,6 +143,12 @@ static struct PurpleStatusPrimitiveMap { PURPLE_STATUS_MOOD, "mood", N_("Feeling") }, }; +int * +_purple_get_primitive_scores(void) +{ + return primitive_scores; +} + const char * purple_primitive_get_id_from_type(PurpleStatusPrimitive type) { @@ -259,16 +239,16 @@ purple_status_type_new(PurpleStatusPrimitive primitive, const char *id, static void status_type_add_attr(PurpleStatusType *status_type, const char *id, - const char *name, PurpleValue *value) + const char *name, GValue *value) { - PurpleStatusAttr *attr; + PurpleStatusAttribute *attr; g_return_if_fail(status_type != NULL); g_return_if_fail(id != NULL); g_return_if_fail(name != NULL); g_return_if_fail(value != NULL); - attr = purple_status_attr_new(id, name, value); + attr = purple_status_attribute_new(id, name, value); status_type->attrs = g_list_append(status_type->attrs, attr); } @@ -277,7 +257,7 @@ static void status_type_add_attrs_vargs(PurpleStatusType *status_type, va_list args) { const char *id, *name; - PurpleValue *value; + GValue *value; g_return_if_fail(status_type != NULL); @@ -286,7 +266,7 @@ status_type_add_attrs_vargs(PurpleStatusType *status_type, va_list args) name = va_arg(args, const char *); g_return_if_fail(name != NULL); - value = va_arg(args, PurpleValue *); + value = va_arg(args, GValue *); g_return_if_fail(value != NULL); status_type_add_attr(status_type, id, name, value); @@ -298,7 +278,7 @@ purple_status_type_new_with_attrs(PurpleStatusPrimitive primitive, const char *id, const char *name, gboolean saveable, gboolean user_settable, gboolean independent, const char *attr_id, - const char *attr_name, PurpleValue *attr_value, + const char *attr_name, GValue *attr_value, ...) { PurpleStatusType *status_type; @@ -330,7 +310,7 @@ purple_status_type_destroy(PurpleStatusType *status_type) g_free(status_type->id); g_free(status_type->name); - g_list_foreach(status_type->attrs, (GFunc)purple_status_attr_destroy, NULL); + g_list_foreach(status_type->attrs, (GFunc)purple_status_attribute_destroy, NULL); g_list_free(status_type->attrs); PURPLE_DBUS_UNREGISTER_POINTER(status_type); @@ -405,7 +385,7 @@ purple_status_type_is_available(const PurpleStatusType *status_type) return (primitive == PURPLE_STATUS_AVAILABLE); } -PurpleStatusAttr * +PurpleStatusAttribute * purple_status_type_get_attr(const PurpleStatusType *status_type, const char *id) { GList *l; @@ -415,9 +395,9 @@ purple_status_type_get_attr(const PurpleStatusType *status_type, const char *id) for (l = status_type->attrs; l != NULL; l = l->next) { - PurpleStatusAttr *attr = (PurpleStatusAttr *)l->data; + PurpleStatusAttribute *attr = (PurpleStatusAttribute *)l->data; - if (purple_strequal(purple_status_attr_get_id(attr), id)) + if (purple_strequal(purple_status_attribute_get_id(attr), id)) return attr; } @@ -454,19 +434,19 @@ purple_status_type_find_with_id(GList *status_types, const char *id) /************************************************************************** -* PurpleStatusAttr API +* PurpleStatusAttribute API **************************************************************************/ -PurpleStatusAttr * -purple_status_attr_new(const char *id, const char *name, PurpleValue *value_type) +PurpleStatusAttribute * +purple_status_attribute_new(const char *id, const char *name, GValue *value_type) { - PurpleStatusAttr *attr; + PurpleStatusAttribute *attr; g_return_val_if_fail(id != NULL, NULL); g_return_val_if_fail(name != NULL, NULL); g_return_val_if_fail(value_type != NULL, NULL); - attr = g_new0(PurpleStatusAttr, 1); - PURPLE_DBUS_REGISTER_POINTER(attr, PurpleStatusAttr); + attr = g_new0(PurpleStatusAttribute, 1); + PURPLE_DBUS_REGISTER_POINTER(attr, PurpleStatusAttribute); attr->id = g_strdup(id); attr->name = g_strdup(name); @@ -476,21 +456,21 @@ purple_status_attr_new(const char *id, const char *name, PurpleValue *value_type } void -purple_status_attr_destroy(PurpleStatusAttr *attr) +purple_status_attribute_destroy(PurpleStatusAttribute *attr) { g_return_if_fail(attr != NULL); g_free(attr->id); g_free(attr->name); - purple_value_destroy(attr->value_type); + purple_g_value_free(attr->value_type); PURPLE_DBUS_UNREGISTER_POINTER(attr); g_free(attr); } const char * -purple_status_attr_get_id(const PurpleStatusAttr *attr) +purple_status_attribute_get_id(const PurpleStatusAttribute *attr) { g_return_val_if_fail(attr != NULL, NULL); @@ -498,15 +478,15 @@ purple_status_attr_get_id(const PurpleStatusAttr *attr) } const char * -purple_status_attr_get_name(const PurpleStatusAttr *attr) +purple_status_attribute_get_name(const PurpleStatusAttribute *attr) { g_return_val_if_fail(attr != NULL, NULL); return attr->name; } -PurpleValue * -purple_status_attr_get_value(const PurpleStatusAttr *attr) +GValue * +purple_status_attribute_get_value(const PurpleStatusAttribute *attr) { g_return_val_if_fail(attr != NULL, NULL); @@ -517,54 +497,6 @@ purple_status_attr_get_value(const PurpleStatusAttr *attr) /************************************************************************** * PurpleStatus API **************************************************************************/ -PurpleStatus * -purple_status_new(PurpleStatusType *status_type, PurplePresence *presence) -{ - PurpleStatus *status; - GList *l; - - g_return_val_if_fail(status_type != NULL, NULL); - g_return_val_if_fail(presence != NULL, NULL); - - status = g_new0(PurpleStatus, 1); - PURPLE_DBUS_REGISTER_POINTER(status, PurpleStatus); - - status->type = status_type; - status->presence = presence; - - status->attr_values = - g_hash_table_new_full(g_str_hash, g_str_equal, NULL, - (GDestroyNotify)purple_value_destroy); - - for (l = purple_status_type_get_attrs(status_type); l != NULL; l = l->next) - { - PurpleStatusAttr *attr = (PurpleStatusAttr *)l->data; - PurpleValue *value = purple_status_attr_get_value(attr); - PurpleValue *new_value = purple_value_dup(value); - - g_hash_table_insert(status->attr_values, - (char *)purple_status_attr_get_id(attr), - new_value); - } - - return status; -} - -/* - * TODO: If the PurpleStatus is in a PurplePresence, then - * remove it from the PurplePresence? - */ -void -purple_status_destroy(PurpleStatus *status) -{ - g_return_if_fail(status != NULL); - - g_hash_table_destroy(status->attr_values); - - PURPLE_DBUS_UNREGISTER_POINTER(status); - g_free(status); -} - static void notify_buddy_status_update(PurpleBuddy *buddy, PurplePresence *presence, PurpleStatus *old_status, PurpleStatus *new_status) @@ -620,11 +552,10 @@ static void notify_status_update(PurplePresence *presence, PurpleStatus *old_status, PurpleStatus *new_status) { - PurplePresenceContext context = purple_presence_get_context(presence); - - if (context == PURPLE_PRESENCE_CONTEXT_ACCOUNT) + if (PURPLE_IS_ACCOUNT_PRESENCE(presence)) { - PurpleAccount *account = purple_presence_get_account(presence); + PurpleAccount *account = purple_account_presence_get_account( + PURPLE_ACCOUNT_PRESENCE(presence)); PurpleAccountUiOps *ops = purple_accounts_get_ui_ops(); if (purple_account_get_enabled(account, purple_core_get_ui())) @@ -635,10 +566,11 @@ notify_status_update(PurplePresence *presence, PurpleStatus *old_status, ops->status_changed(account, new_status); } } - else if (context == PURPLE_PRESENCE_CONTEXT_BUDDY) + else if (PURPLE_IS_BUDDY_PRESENCE(presence)) { - notify_buddy_status_update(purple_presence_get_buddy(presence), presence, - old_status, new_status); + notify_buddy_status_update(purple_buddy_presence_get_buddy( + PURPLE_BUDDY_PRESENCE(presence)), presence, old_status, + new_status); } } @@ -659,8 +591,8 @@ status_has_changed(PurpleStatus *status) { old_status = purple_presence_get_active_status(presence); if (old_status != NULL && (old_status != status)) - old_status->active = FALSE; - presence->active_status = status; + PURPLE_STATUS_GET_PRIVATE(old_status)->active = FALSE; + g_object_set(presence, "active-status", status, NULL); } else old_status = NULL; @@ -672,7 +604,7 @@ static void status_set_attr_boolean(PurpleStatus *status, const char *id, gboolean value) { - PurpleValue *attr_value; + GValue *attr_value; g_return_if_fail(status != NULL); g_return_if_fail(id != NULL); @@ -680,15 +612,15 @@ status_set_attr_boolean(PurpleStatus *status, const char *id, /* Make sure this attribute exists and is the correct type. */ attr_value = purple_status_get_attr_value(status, id); g_return_if_fail(attr_value != NULL); - g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_BOOLEAN); + g_return_if_fail(G_VALUE_TYPE(attr_value) == G_TYPE_BOOLEAN); - purple_value_set_boolean(attr_value, value); + g_value_set_boolean(attr_value, value); } static void status_set_attr_int(PurpleStatus *status, const char *id, int value) { - PurpleValue *attr_value; + GValue *attr_value; g_return_if_fail(status != NULL); g_return_if_fail(id != NULL); @@ -696,16 +628,16 @@ status_set_attr_int(PurpleStatus *status, const char *id, int value) /* Make sure this attribute exists and is the correct type. */ attr_value = purple_status_get_attr_value(status, id); g_return_if_fail(attr_value != NULL); - g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_INT); + g_return_if_fail(G_VALUE_TYPE(attr_value) == G_TYPE_INT); - purple_value_set_int(attr_value, value); + g_value_set_int(attr_value, value); } static void status_set_attr_string(PurpleStatus *status, const char *id, const char *value) { - PurpleValue *attr_value; + GValue *attr_value; g_return_if_fail(status != NULL); g_return_if_fail(id != NULL); @@ -720,14 +652,14 @@ status_set_attr_string(PurpleStatus *status, const char *id, "Attempted to set status attribute '%s' for " "status '%s', which is not legal. Fix " "this!\n", id, - purple_status_type_get_name(purple_status_get_type(status))); + purple_status_type_get_name(purple_status_get_status_type(status))); return; } - g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_STRING); + g_return_if_fail(G_VALUE_TYPE(attr_value) == G_TYPE_STRING); /* XXX: Check if the value has actually changed. If it has, and the status * is active, should this trigger 'status_has_changed'? */ - purple_value_set_string(attr_value, value); + g_value_set_string(attr_value, value); } void @@ -767,8 +699,9 @@ purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active, GList *l; GList *specified_attr_ids = NULL; PurpleStatusType *status_type; + PurpleStatusPrivate *priv = PURPLE_STATUS_GET_PRIVATE(status); - g_return_if_fail(status != NULL); + g_return_if_fail(priv != NULL); if (!active && purple_status_is_exclusive(status)) { @@ -778,19 +711,19 @@ purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active, return; } - if (status->active != active) + if (priv->active != active) { changed = TRUE; } - status->active = active; + priv->active = active; /* Set any attributes */ l = attrs; while (l != NULL) { const gchar *id; - PurpleValue *value; + GValue *value; id = l->data; l = l->next; @@ -798,7 +731,7 @@ purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active, if (value == NULL) { purple_debug_warning("status", "The attribute \"%s\" on the status \"%s\" is " - "not supported.\n", id, status->type->name); + "not supported.\n", id, priv->status_type->name); /* Skip over the data and move on to the next attribute */ l = l->next; continue; @@ -806,29 +739,29 @@ purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active, specified_attr_ids = g_list_prepend(specified_attr_ids, (gpointer)id); - if (purple_value_get_type(value) == PURPLE_TYPE_STRING) + if (G_VALUE_TYPE(value) == G_TYPE_STRING) { const gchar *string_data = l->data; l = l->next; - if (purple_strequal(string_data, purple_value_get_string(value))) + if (purple_strequal(string_data, g_value_get_string(value))) continue; status_set_attr_string(status, id, string_data); changed = TRUE; } - else if (purple_value_get_type(value) == PURPLE_TYPE_INT) + else if (G_VALUE_TYPE(value) == G_TYPE_INT) { int int_data = GPOINTER_TO_INT(l->data); l = l->next; - if (int_data == purple_value_get_int(value)) + if (int_data == g_value_get_int(value)) continue; status_set_attr_int(status, id, int_data); changed = TRUE; } - else if (purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN) + else if (G_VALUE_TYPE(value) == G_TYPE_BOOLEAN) { gboolean boolean_data = GPOINTER_TO_INT(l->data); l = l->next; - if (boolean_data == purple_value_get_boolean(value)) + if (boolean_data == g_value_get_boolean(value)) continue; status_set_attr_boolean(status, id, boolean_data); changed = TRUE; @@ -841,20 +774,20 @@ purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active, } /* Reset any unspecified attributes to their default value */ - status_type = purple_status_get_type(status); + status_type = purple_status_get_status_type(status); l = purple_status_type_get_attrs(status_type); while (l != NULL) { - PurpleStatusAttr *attr; + PurpleStatusAttribute *attr; attr = l->data; l = l->next; if (!g_list_find_custom(specified_attr_ids, attr->id, (GCompareFunc)strcmp)) { - PurpleValue *default_value; - default_value = purple_status_attr_get_value(attr); - if (purple_value_get_type(default_value) == PURPLE_TYPE_STRING) { + GValue *default_value; + default_value = purple_status_attribute_get_value(attr); + if (G_VALUE_TYPE(default_value) == G_TYPE_STRING) { const char *cur = purple_status_get_attr_string(status, attr->id); - const char *def = purple_value_get_string(default_value); + const char *def = g_value_get_string(default_value); if ((cur == NULL && def == NULL) || (cur != NULL && def != NULL && !strcmp(cur, def))) { @@ -862,16 +795,16 @@ purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active, } status_set_attr_string(status, attr->id, def); - } else if (purple_value_get_type(default_value) == PURPLE_TYPE_INT) { + } else if (G_VALUE_TYPE(default_value) == G_TYPE_INT) { int cur = purple_status_get_attr_int(status, attr->id); - int def = purple_value_get_int(default_value); + int def = g_value_get_int(default_value); if (cur == def) continue; status_set_attr_int(status, attr->id, def); - } else if (purple_value_get_type(default_value) == PURPLE_TYPE_BOOLEAN) { + } else if (G_VALUE_TYPE(default_value) == G_TYPE_BOOLEAN) { gboolean cur = purple_status_get_attr_boolean(status, attr->id); - gboolean def = purple_value_get_boolean(default_value); + gboolean def = g_value_get_boolean(default_value); if (cur == def) continue; @@ -888,19 +821,23 @@ purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active, } PurpleStatusType * -purple_status_get_type(const PurpleStatus *status) +purple_status_get_status_type(const PurpleStatus *status) { - g_return_val_if_fail(status != NULL, NULL); + PurpleStatusPrivate *priv = PURPLE_STATUS_GET_PRIVATE(status); + + g_return_val_if_fail(priv != NULL, NULL); - return status->type; + return priv->status_type; } PurplePresence * purple_status_get_presence(const PurpleStatus *status) { - g_return_val_if_fail(status != NULL, NULL); + PurpleStatusPrivate *priv = PURPLE_STATUS_GET_PRIVATE(status); + + g_return_val_if_fail(priv != NULL, NULL); - return status->presence; + return priv->presence; } const char * @@ -908,7 +845,7 @@ purple_status_get_id(const PurpleStatus *status) { g_return_val_if_fail(status != NULL, NULL); - return purple_status_type_get_id(purple_status_get_type(status)); + return purple_status_type_get_id(purple_status_get_status_type(status)); } const char * @@ -916,7 +853,7 @@ purple_status_get_name(const PurpleStatus *status) { g_return_val_if_fail(status != NULL, NULL); - return purple_status_type_get_name(purple_status_get_type(status)); + return purple_status_type_get_name(purple_status_get_status_type(status)); } gboolean @@ -924,7 +861,7 @@ purple_status_is_independent(const PurpleStatus *status) { g_return_val_if_fail(status != NULL, FALSE); - return purple_status_type_is_independent(purple_status_get_type(status)); + return purple_status_type_is_independent(purple_status_get_status_type(status)); } gboolean @@ -932,7 +869,7 @@ purple_status_is_exclusive(const PurpleStatus *status) { g_return_val_if_fail(status != NULL, FALSE); - return purple_status_type_is_exclusive(purple_status_get_type(status)); + return purple_status_type_is_exclusive(purple_status_get_status_type(status)); } gboolean @@ -940,15 +877,17 @@ purple_status_is_available(const PurpleStatus *status) { g_return_val_if_fail(status != NULL, FALSE); - return purple_status_type_is_available(purple_status_get_type(status)); + return purple_status_type_is_available(purple_status_get_status_type(status)); } gboolean purple_status_is_active(const PurpleStatus *status) { - g_return_val_if_fail(status != NULL, FALSE); + PurpleStatusPrivate *priv = PURPLE_STATUS_GET_PRIVATE(status); - return status->active; + g_return_val_if_fail(priv != NULL, FALSE); + + return priv->active; } gboolean @@ -958,25 +897,27 @@ purple_status_is_online(const PurpleStatus *status) g_return_val_if_fail( status != NULL, FALSE); - primitive = purple_status_type_get_primitive(purple_status_get_type(status)); + primitive = purple_status_type_get_primitive(purple_status_get_status_type(status)); return (primitive != PURPLE_STATUS_UNSET && primitive != PURPLE_STATUS_OFFLINE); } -PurpleValue * +GValue * purple_status_get_attr_value(const PurpleStatus *status, const char *id) { - g_return_val_if_fail(status != NULL, NULL); - g_return_val_if_fail(id != NULL, NULL); + PurpleStatusPrivate *priv = PURPLE_STATUS_GET_PRIVATE(status); + + g_return_val_if_fail(priv != NULL, NULL); + g_return_val_if_fail(id != NULL, NULL); - return (PurpleValue *)g_hash_table_lookup(status->attr_values, id); + return (GValue *)g_hash_table_lookup(priv->attr_values, id); } gboolean purple_status_get_attr_boolean(const PurpleStatus *status, const char *id) { - const PurpleValue *value; + const GValue *value; g_return_val_if_fail(status != NULL, FALSE); g_return_val_if_fail(id != NULL, FALSE); @@ -984,15 +925,15 @@ purple_status_get_attr_boolean(const PurpleStatus *status, const char *id) if ((value = purple_status_get_attr_value(status, id)) == NULL) return FALSE; - g_return_val_if_fail(purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN, FALSE); + g_return_val_if_fail(G_VALUE_TYPE(value) == G_TYPE_BOOLEAN, FALSE); - return purple_value_get_boolean(value); + return g_value_get_boolean(value); } int purple_status_get_attr_int(const PurpleStatus *status, const char *id) { - const PurpleValue *value; + const GValue *value; g_return_val_if_fail(status != NULL, 0); g_return_val_if_fail(id != NULL, 0); @@ -1000,15 +941,15 @@ purple_status_get_attr_int(const PurpleStatus *status, const char *id) if ((value = purple_status_get_attr_value(status, id)) == NULL) return 0; - g_return_val_if_fail(purple_value_get_type(value) == PURPLE_TYPE_INT, 0); + g_return_val_if_fail(G_VALUE_TYPE(value) == G_TYPE_INT, 0); - return purple_value_get_int(value); + return g_value_get_int(value); } const char * purple_status_get_attr_string(const PurpleStatus *status, const char *id) { - const PurpleValue *value; + const GValue *value; g_return_val_if_fail(status != NULL, NULL); g_return_val_if_fail(id != NULL, NULL); @@ -1016,9 +957,9 @@ purple_status_get_attr_string(const PurpleStatus *status, const char *id) if ((value = purple_status_get_attr_value(status, id)) == NULL) return NULL; - g_return_val_if_fail(purple_value_get_type(value) == PURPLE_TYPE_STRING, NULL); + g_return_val_if_fail(G_VALUE_TYPE(value) == G_TYPE_STRING, NULL); - return purple_value_get_string(value); + return g_value_get_string(value); } gint @@ -1037,8 +978,8 @@ purple_status_compare(const PurpleStatus *status1, const PurpleStatus *status2) else if (status2 == NULL) return -1; - type1 = purple_status_get_type(status1); - type2 = purple_status_get_type(status2); + type1 = purple_status_get_status_type(status1); + type2 = purple_status_get_status_type(status2); if (purple_status_is_active(status1)) score1 = primitive_scores[purple_status_type_get_primitive(type1)]; @@ -1056,525 +997,302 @@ purple_status_compare(const PurpleStatus *status1, const PurpleStatus *status2) /************************************************************************** -* PurplePresence API +* GBoxed code for PurpleStatusType **************************************************************************/ -PurplePresence * -purple_presence_new(PurplePresenceContext context) -{ - PurplePresence *presence; - - g_return_val_if_fail(context != PURPLE_PRESENCE_CONTEXT_UNSET, NULL); - - presence = g_new0(PurplePresence, 1); - PURPLE_DBUS_REGISTER_POINTER(presence, PurplePresence); - - presence->context = context; - - presence->status_table = - g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, NULL); - - return presence; -} - -PurplePresence * -purple_presence_new_for_account(PurpleAccount *account) +static PurpleStatusType * +purple_status_type_copy(PurpleStatusType *status_type) { - PurplePresence *presence = NULL; - g_return_val_if_fail(account != NULL, NULL); - - presence = purple_presence_new(PURPLE_PRESENCE_CONTEXT_ACCOUNT); - presence->u.account = account; - presence->statuses = purple_prpl_get_statuses(account, presence); - - return presence; -} - -PurplePresence * -purple_presence_new_for_conv(PurpleConversation *conv) -{ - PurplePresence *presence; - - g_return_val_if_fail(conv != NULL, NULL); - - presence = purple_presence_new(PURPLE_PRESENCE_CONTEXT_CONV); - presence->u.chat.conv = conv; - /* presence->statuses = purple_prpl_get_statuses(purple_conversation_get_account(conv), presence); ? */ - - return presence; -} - -PurplePresence * -purple_presence_new_for_buddy(PurpleBuddy *buddy) -{ - PurplePresence *presence; - PurpleAccount *account; - - g_return_val_if_fail(buddy != NULL, NULL); - account = purple_buddy_get_account(buddy); - - presence = purple_presence_new(PURPLE_PRESENCE_CONTEXT_BUDDY); + PurpleStatusType *status_type_copy; + GList *l; - presence->u.buddy.name = g_strdup(purple_buddy_get_name(buddy)); - presence->u.buddy.account = account; - presence->statuses = purple_prpl_get_statuses(account, presence); + g_return_val_if_fail(status_type != NULL, NULL); - presence->u.buddy.buddy = buddy; + status_type_copy = purple_status_type_new_full(status_type->primitive, + status_type->id, + status_type->name, + status_type->saveable, + status_type->user_settable, + status_type->independent); - return presence; -} + for (l = status_type->attrs; l != NULL; l = l->next) { + PurpleStatusAttribute *new_attr, *attr = l->data; -void -purple_presence_destroy(PurplePresence *presence) -{ - g_return_if_fail(presence != NULL); - - if (purple_presence_get_context(presence) == PURPLE_PRESENCE_CONTEXT_BUDDY) - { - g_free(presence->u.buddy.name); + new_attr = g_boxed_copy(PURPLE_TYPE_STATUS_ATTRIBUTE, attr); + status_type_copy->attrs = g_list_append(status_type_copy->attrs, new_attr); } - else if (purple_presence_get_context(presence) == PURPLE_PRESENCE_CONTEXT_CONV) - { - g_free(presence->u.chat.user); - } - - g_list_foreach(presence->statuses, (GFunc)purple_status_destroy, NULL); - g_list_free(presence->statuses); - - g_hash_table_destroy(presence->status_table); - PURPLE_DBUS_UNREGISTER_POINTER(presence); - g_free(presence); + return status_type_copy; } -void -purple_presence_set_status_active(PurplePresence *presence, const char *status_id, - gboolean active) +GType +purple_status_type_get_type(void) { - PurpleStatus *status; - - g_return_if_fail(presence != NULL); - g_return_if_fail(status_id != NULL); + static GType type = 0; - status = purple_presence_get_status(presence, status_id); - - g_return_if_fail(status != NULL); - /* TODO: Should we do the following? */ - /* g_return_if_fail(active == status->active); */ - - if (purple_status_is_exclusive(status)) - { - if (!active) - { - purple_debug_warning("status", - "Attempted to set a non-independent status " - "(%s) inactive. Only independent statuses " - "can be specifically marked inactive.", - status_id); - return; - } + if (type == 0) { + type = g_boxed_type_register_static("PurpleStatusType", + (GBoxedCopyFunc)purple_status_type_copy, + (GBoxedFreeFunc)purple_status_type_destroy); } - purple_status_set_active(status, active); -} - -void -purple_presence_switch_status(PurplePresence *presence, const char *status_id) -{ - purple_presence_set_status_active(presence, status_id, TRUE); + return type; } -static void -update_buddy_idle(PurpleBuddy *buddy, PurplePresence *presence, - time_t current_time, gboolean old_idle, gboolean idle) +/************************************************************************** +* GBoxed code for PurpleStatusAttribute +**************************************************************************/ +static PurpleStatusAttribute * +purple_status_attribute_copy(PurpleStatusAttribute *status_attr) { - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - PurpleAccount *account = purple_buddy_get_account(buddy); - - if (!old_idle && idle) - { - if (purple_prefs_get_bool("/purple/logging/log_system")) - { - PurpleLog *log = purple_account_get_log(account, FALSE); - - if (log != NULL) - { - char *tmp, *tmp2; - tmp = g_strdup_printf(_("%s became idle"), - purple_buddy_get_alias(buddy)); - tmp2 = g_markup_escape_text(tmp, -1); - g_free(tmp); - - purple_log_write(log, PURPLE_MESSAGE_SYSTEM, - purple_buddy_get_alias(buddy), current_time, tmp2); - g_free(tmp2); - } - } - } - else if (old_idle && !idle) - { - if (purple_prefs_get_bool("/purple/logging/log_system")) - { - PurpleLog *log = purple_account_get_log(account, FALSE); + g_return_val_if_fail(status_attr != NULL, NULL); - if (log != NULL) - { - char *tmp, *tmp2; - tmp = g_strdup_printf(_("%s became unidle"), - purple_buddy_get_alias(buddy)); - tmp2 = g_markup_escape_text(tmp, -1); - g_free(tmp); - - purple_log_write(log, PURPLE_MESSAGE_SYSTEM, - purple_buddy_get_alias(buddy), current_time, tmp2); - g_free(tmp2); - } - } - } - - if (old_idle != idle) - purple_signal_emit(purple_blist_get_handle(), "buddy-idle-changed", buddy, - old_idle, idle); - - purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy)); - - /* Should this be done here? It'd perhaps make more sense to - * connect to buddy-[un]idle signals and update from there - */ - - if (ops != NULL && ops->update != NULL) - ops->update(purple_get_blist(), (PurpleBlistNode *)buddy); + return purple_status_attribute_new(status_attr->id, + status_attr->name, + purple_g_value_dup(status_attr->value_type)); } -void -purple_presence_set_idle(PurplePresence *presence, gboolean idle, time_t idle_time) +GType +purple_status_attribute_get_type(void) { - gboolean old_idle; - time_t current_time; - - g_return_if_fail(presence != NULL); - - if (presence->idle == idle && presence->idle_time == idle_time) - return; - - old_idle = presence->idle; - presence->idle = idle; - presence->idle_time = (idle ? idle_time : 0); - - current_time = time(NULL); - - if (purple_presence_get_context(presence) == PURPLE_PRESENCE_CONTEXT_BUDDY) - { - update_buddy_idle(purple_presence_get_buddy(presence), presence, current_time, - old_idle, idle); - } - else if (purple_presence_get_context(presence) == PURPLE_PRESENCE_CONTEXT_ACCOUNT) - { - PurpleAccount *account; - PurpleConnection *gc = NULL; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; - - account = purple_presence_get_account(presence); - - if (purple_prefs_get_bool("/purple/logging/log_system")) - { - PurpleLog *log = purple_account_get_log(account, FALSE); - - if (log != NULL) - { - char *msg, *tmp; - - if (idle) - tmp = g_strdup_printf(_("+++ %s became idle"), purple_account_get_username(account)); - else - tmp = g_strdup_printf(_("+++ %s became unidle"), purple_account_get_username(account)); - - msg = g_markup_escape_text(tmp, -1); - g_free(tmp); - purple_log_write(log, PURPLE_MESSAGE_SYSTEM, - purple_account_get_username(account), - (idle ? idle_time : current_time), msg); - g_free(msg); - } - } - - gc = purple_account_get_connection(account); - - if(gc) - prpl = purple_connection_get_prpl(gc); + static GType type = 0; - if(PURPLE_CONNECTION_IS_CONNECTED(gc) && prpl != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if (prpl_info && prpl_info->set_idle) - prpl_info->set_idle(gc, (idle ? (current_time - idle_time) : 0)); + if (type == 0) { + type = g_boxed_type_register_static("PurpleStatusAttribute", + (GBoxedCopyFunc)purple_status_attribute_copy, + (GBoxedFreeFunc)purple_status_attribute_destroy); } -} - -void -purple_presence_set_login_time(PurplePresence *presence, time_t login_time) -{ - g_return_if_fail(presence != NULL); - - if (presence->login_time == login_time) - return; - - presence->login_time = login_time; -} - -PurplePresenceContext -purple_presence_get_context(const PurplePresence *presence) -{ - g_return_val_if_fail(presence != NULL, PURPLE_PRESENCE_CONTEXT_UNSET); - - return presence->context; -} - -PurpleAccount * -purple_presence_get_account(const PurplePresence *presence) -{ - PurplePresenceContext context; - - g_return_val_if_fail(presence != NULL, NULL); - - context = purple_presence_get_context(presence); - g_return_val_if_fail(context == PURPLE_PRESENCE_CONTEXT_ACCOUNT || - context == PURPLE_PRESENCE_CONTEXT_BUDDY, NULL); - - return presence->u.account; + return type; } -PurpleConversation * -purple_presence_get_conversation(const PurplePresence *presence) +/************************************************************************** +* GBoxed code for PurpleMood +**************************************************************************/ +static PurpleMood * +purple_mood_copy(PurpleMood *mood) { - g_return_val_if_fail(presence != NULL, NULL); - g_return_val_if_fail(purple_presence_get_context(presence) == - PURPLE_PRESENCE_CONTEXT_CONV, NULL); + PurpleMood *mood_copy; - return presence->u.chat.conv; -} + g_return_val_if_fail(mood != NULL, NULL); -const char * -purple_presence_get_chat_user(const PurplePresence *presence) -{ - g_return_val_if_fail(presence != NULL, NULL); - g_return_val_if_fail(purple_presence_get_context(presence) == - PURPLE_PRESENCE_CONTEXT_CONV, NULL); - - return presence->u.chat.user; -} + mood_copy = g_new(PurpleMood, 1); -PurpleBuddy * -purple_presence_get_buddy(const PurplePresence *presence) -{ - g_return_val_if_fail(presence != NULL, NULL); - g_return_val_if_fail(purple_presence_get_context(presence) == - PURPLE_PRESENCE_CONTEXT_BUDDY, NULL); + mood_copy->mood = g_strdup(mood->mood); + mood_copy->description = g_strdup(mood->description); - return presence->u.buddy.buddy; + return mood_copy; } -GList * -purple_presence_get_statuses(const PurplePresence *presence) +static void +purple_mood_free(PurpleMood *mood) { - g_return_val_if_fail(presence != NULL, NULL); + g_free((gchar *)mood->mood); + g_free((gchar *)mood->description); - return presence->statuses; + g_free(mood); } -PurpleStatus * -purple_presence_get_status(const PurplePresence *presence, const char *status_id) +GType +purple_mood_get_type(void) { - PurpleStatus *status; - GList *l = NULL; - - g_return_val_if_fail(presence != NULL, NULL); - g_return_val_if_fail(status_id != NULL, NULL); + static GType type = 0; - /* What's the purpose of this hash table? */ - status = (PurpleStatus *)g_hash_table_lookup(presence->status_table, - status_id); - - if (status == NULL) { - for (l = purple_presence_get_statuses(presence); - l != NULL && status == NULL; l = l->next) - { - PurpleStatus *temp_status = l->data; - - if (purple_strequal(status_id, purple_status_get_id(temp_status))) - status = temp_status; - } - - if (status != NULL) - g_hash_table_insert(presence->status_table, - g_strdup(purple_status_get_id(status)), status); + if (type == 0) { + type = g_boxed_type_register_static("PurpleMood", + (GBoxedCopyFunc)purple_mood_copy, + (GBoxedFreeFunc)purple_mood_free); } - return status; + return type; } -PurpleStatus * -purple_presence_get_active_status(const PurplePresence *presence) -{ - g_return_val_if_fail(presence != NULL, NULL); - - return presence->active_status; -} -gboolean -purple_presence_is_available(const PurplePresence *presence) -{ - PurpleStatus *status; - - g_return_val_if_fail(presence != NULL, FALSE); +/************************************************************************** +* GObject code +**************************************************************************/ - status = purple_presence_get_active_status(presence); +/* GObject Property names */ +#define PROP_STATUS_TYPE_S "status-type" +#define PROP_PRESENCE_S "presence" +#define PROP_ACTIVE_S "active" - return ((status != NULL && purple_status_is_available(status)) && - !purple_presence_is_idle(presence)); +/* Set method for GObject properties */ +static void +purple_status_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleStatus *status = PURPLE_STATUS(obj); + PurpleStatusPrivate *priv = PURPLE_STATUS_GET_PRIVATE(status); + + switch (param_id) { + case PROP_STATUS_TYPE: + priv->status_type = g_value_get_pointer(value); + break; + case PROP_PRESENCE: + priv->presence = g_value_get_object(value); + break; + case PROP_ACTIVE: + purple_status_set_active(status, g_value_get_boolean(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } } -gboolean -purple_presence_is_online(const PurplePresence *presence) -{ - PurpleStatus *status; - - g_return_val_if_fail(presence != NULL, FALSE); - - if ((status = purple_presence_get_active_status(presence)) == NULL) - return FALSE; - - return purple_status_is_online(status); +/* Get method for GObject properties */ +static void +purple_status_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleStatus *status = PURPLE_STATUS(obj); + + switch (param_id) { + case PROP_STATUS_TYPE: + g_value_set_pointer(value, purple_status_get_status_type(status)); + break; + case PROP_PRESENCE: + g_value_set_object(value, purple_status_get_presence(status)); + break; + case PROP_ACTIVE: + g_value_set_boolean(value, purple_status_is_active(status)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } } -gboolean -purple_presence_is_status_active(const PurplePresence *presence, - const char *status_id) +/* GObject initialization function */ +static void +purple_status_init(GTypeInstance *instance, gpointer klass) { - PurpleStatus *status; + PurpleStatus *status = PURPLE_STATUS(instance); - g_return_val_if_fail(presence != NULL, FALSE); - g_return_val_if_fail(status_id != NULL, FALSE); - - status = purple_presence_get_status(presence, status_id); + PURPLE_DBUS_REGISTER_POINTER(status, PurpleStatus); - return (status != NULL && purple_status_is_active(status)); + PURPLE_STATUS_GET_PRIVATE(status)->attr_values = + g_hash_table_new_full(g_str_hash, g_str_equal, NULL, + (GDestroyNotify)purple_g_value_free); } -gboolean -purple_presence_is_status_primitive_active(const PurplePresence *presence, - PurpleStatusPrimitive primitive) +/* Called when done constructing */ +static void +purple_status_constructed(GObject *object) { GList *l; + PurpleStatusPrivate *priv = PURPLE_STATUS_GET_PRIVATE(object); - g_return_val_if_fail(presence != NULL, FALSE); - g_return_val_if_fail(primitive != PURPLE_STATUS_UNSET, FALSE); + parent_class->constructed(object); - for (l = purple_presence_get_statuses(presence); - l != NULL; l = l->next) + for (l = purple_status_type_get_attrs(priv->status_type); l != NULL; l = l->next) { - PurpleStatus *temp_status = l->data; - PurpleStatusType *type = purple_status_get_type(temp_status); + PurpleStatusAttribute *attr = (PurpleStatusAttribute *)l->data; + GValue *value = purple_status_attribute_get_value(attr); + GValue *new_value = purple_g_value_dup(value); - if (purple_status_type_get_primitive(type) == primitive && - purple_status_is_active(temp_status)) - return TRUE; + g_hash_table_insert(priv->attr_values, + (char *)purple_status_attribute_get_id(attr), + new_value); } - return FALSE; -} - -gboolean -purple_presence_is_idle(const PurplePresence *presence) -{ - g_return_val_if_fail(presence != NULL, FALSE); - - return purple_presence_is_online(presence) && presence->idle; } -time_t -purple_presence_get_idle_time(const PurplePresence *presence) +/* + * GObject dispose function + * TODO: If the PurpleStatus is in a PurplePresence, then + * remove it from the PurplePresence? + */ +static void +purple_status_dispose(GObject *object) { - g_return_val_if_fail(presence != NULL, 0); + PURPLE_DBUS_UNREGISTER_POINTER(object); - return presence->idle_time; + parent_class->dispose(object); } -time_t -purple_presence_get_login_time(const PurplePresence *presence) +/* GObject finalize function */ +static void +purple_status_finalize(GObject *object) { - g_return_val_if_fail(presence != NULL, 0); + g_hash_table_destroy(PURPLE_STATUS_GET_PRIVATE(object)->attr_values); - return purple_presence_is_online(presence) ? presence->login_time : 0; + parent_class->finalize(object); } -static int -purple_presence_compute_score(const PurplePresence *presence) -{ - GList *l; - int score = 0; - - for (l = purple_presence_get_statuses(presence); l != NULL; l = l->next) { - PurpleStatus *status = (PurpleStatus *)l->data; - PurpleStatusType *type = purple_status_get_type(status); - - if (purple_status_is_active(status)) { - score += primitive_scores[purple_status_type_get_primitive(type)]; - if (!purple_status_is_online(status)) { - PurpleBuddy *b = purple_presence_get_buddy(presence); - if (b && purple_account_supports_offline_message(purple_buddy_get_account(b), b)) - score += primitive_scores[SCORE_OFFLINE_MESSAGE]; - } - } +/* Class initializer function */ +static void +purple_status_class_init(PurpleStatusClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->dispose = purple_status_dispose; + obj_class->finalize = purple_status_finalize; + obj_class->constructed = purple_status_constructed; + + /* Setup properties */ + obj_class->get_property = purple_status_get_property; + obj_class->set_property = purple_status_set_property; + + g_object_class_install_property(obj_class, PROP_STATUS_TYPE, + g_param_spec_pointer(PROP_STATUS_TYPE_S, _("Status type"), + _("The PurpleStatusType of the status."), + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY) + ); + + g_object_class_install_property(obj_class, PROP_PRESENCE, + g_param_spec_object(PROP_PRESENCE_S, _("Presence"), + _("The presence that the status belongs to."), PURPLE_TYPE_PRESENCE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY) + ); + + g_object_class_install_property(obj_class, PROP_ACTIVE, + g_param_spec_boolean(PROP_ACTIVE_S, _("Active"), + _("Whether the status is active or not."), FALSE, + G_PARAM_READWRITE) + ); + + g_type_class_add_private(klass, sizeof(PurpleStatusPrivate)); +} + +GType +purple_status_get_type(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleStatusClass), + NULL, + NULL, + (GClassInitFunc)purple_status_class_init, + NULL, + NULL, + sizeof(PurpleStatus), + 0, + (GInstanceInitFunc)purple_status_init, + NULL, + }; + + type = g_type_register_static(G_TYPE_OBJECT, + "PurpleStatus", + &info, 0); } - score += purple_account_get_int(purple_presence_get_account(presence), "score", 0); - if (purple_presence_is_idle(presence)) - score += primitive_scores[SCORE_IDLE]; - return score; + + return type; } -gint -purple_presence_compare(const PurplePresence *presence1, - const PurplePresence *presence2) +PurpleStatus * +purple_status_new(PurpleStatusType *status_type, PurplePresence *presence) { - time_t idle_time_1, idle_time_2; - int score1 = 0, score2 = 0; - - if (presence1 == presence2) - return 0; - else if (presence1 == NULL) - return 1; - else if (presence2 == NULL) - return -1; - - if (purple_presence_is_online(presence1) && - !purple_presence_is_online(presence2)) - return -1; - else if (purple_presence_is_online(presence2) && - !purple_presence_is_online(presence1)) - return 1; - - /* Compute the score of the first set of statuses. */ - score1 = purple_presence_compute_score(presence1); - - /* Compute the score of the second set of statuses. */ - score2 = purple_presence_compute_score(presence2); - - idle_time_1 = time(NULL) - purple_presence_get_idle_time(presence1); - idle_time_2 = time(NULL) - purple_presence_get_idle_time(presence2); - - if (idle_time_1 > idle_time_2) - score1 += primitive_scores[SCORE_IDLE_TIME]; - else if (idle_time_1 < idle_time_2) - score2 += primitive_scores[SCORE_IDLE_TIME]; - - if (score1 < score2) - return 1; - else if (score1 > score2) - return -1; + g_return_val_if_fail(status_type != NULL, NULL); + g_return_val_if_fail(presence != NULL, NULL); - return 0; + return g_object_new(PURPLE_TYPE_STATUS, + PROP_STATUS_TYPE_S, status_type, + PROP_PRESENCE_S, presence, + NULL); } @@ -1591,16 +1309,16 @@ score_pref_changed_cb(const char *name, PurplePrefType type, } void * -purple_status_get_handle(void) { +purple_statuses_get_handle(void) { static int handle; return &handle; } void -purple_status_init(void) +purple_statuses_init(void) { - void *handle = purple_status_get_handle(); + void *handle = purple_statuses_get_handle(); purple_prefs_add_none("/purple/status"); purple_prefs_add_none("/purple/status/scores"); @@ -1617,6 +1335,8 @@ purple_status_init(void) primitive_scores[PURPLE_STATUS_EXTENDED_AWAY]); purple_prefs_add_int("/purple/status/scores/idle", primitive_scores[SCORE_IDLE]); + purple_prefs_add_int("/purple/status/scores/idle_time", + primitive_scores[SCORE_IDLE_TIME]); purple_prefs_add_int("/purple/status/scores/offline_msg", primitive_scores[SCORE_OFFLINE_MESSAGE]); @@ -1638,6 +1358,9 @@ purple_status_init(void) purple_prefs_connect_callback(handle, "/purple/status/scores/idle", score_pref_changed_cb, GINT_TO_POINTER(SCORE_IDLE)); + purple_prefs_connect_callback(handle, "/purple/status/scores/idle_time", + score_pref_changed_cb, + GINT_TO_POINTER(SCORE_IDLE_TIME)); purple_prefs_connect_callback(handle, "/purple/status/scores/offline_msg", score_pref_changed_cb, GINT_TO_POINTER(SCORE_OFFLINE_MESSAGE)); @@ -1648,11 +1371,12 @@ purple_status_init(void) purple_prefs_trigger_callback("/purple/status/scores/away"); purple_prefs_trigger_callback("/purple/status/scores/extended_away"); purple_prefs_trigger_callback("/purple/status/scores/idle"); + purple_prefs_trigger_callback("/purple/status/scores/idle_time"); purple_prefs_trigger_callback("/purple/status/scores/offline_msg"); } void -purple_status_uninit(void) +purple_statuses_uninit(void) { purple_prefs_disconnect_by_handle(purple_prefs_get_handle()); } diff --git a/libpurple/status.h b/libpurple/status.h index 6c7e525776..694948b180 100644 --- a/libpurple/status.h +++ b/libpurple/status.h @@ -1,3 +1,7 @@ +/** + * @file status.h Status API + * @ingroup core + */ /* * purple * @@ -22,10 +26,7 @@ #ifndef _PURPLE_STATUS_H_ #define _PURPLE_STATUS_H_ -/** - * @file status.h Status API - * @ingroup core - * +/* * A brief explanation of the status API: * * PurpleStatusType's are created by each PRPL. They outline the @@ -54,7 +55,6 @@ * If "saveable" is set to FALSE then the status is NEVER saved. * All PurpleStatuses should be inside a PurplePresence. * - * * A PurpleStatus is either "independent" or "exclusive." * Independent statuses can be active or inactive and they don't * affect anything else. However, you can only have one exclusive @@ -62,14 +62,9 @@ * then the previous exclusive status is automatically deactivated. * * A PurplePresence is like a collection of PurpleStatuses (plus some - * other random info). For any buddy, or for any one of your accounts, - * or for any person with which you're chatting, you may know various - * amounts of information. This information is all contained in - * one PurplePresence. If one of your buddies is away and idle, - * then the presence contains the PurpleStatus for their awayness, - * and it contains their current idle time. PurplePresences are - * never saved to disk. The information they contain is only relevant - * for the current PurpleSession. + * other random info). + * + * @see presence.h */ /** @@ -82,10 +77,27 @@ * hardcoded in each PRPL and will not change often. And because * they are hardcoded, they do not need to be saved to any XML file. */ -typedef struct _PurpleStatusType PurpleStatusType; -typedef struct _PurpleStatusAttr PurpleStatusAttr; -typedef struct _PurplePresence PurplePresence; -typedef struct _PurpleStatus PurpleStatus; +#define PURPLE_TYPE_STATUS (purple_status_get_type()) +#define PURPLE_STATUS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_STATUS, PurpleStatus)) +#define PURPLE_STATUS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_STATUS, PurpleStatusClass)) +#define PURPLE_IS_STATUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_STATUS)) +#define PURPLE_IS_STATUS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_STATUS)) +#define PURPLE_STATUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_STATUS, PurpleStatusClass)) + +/** @copydoc _PurpleStatus */ +typedef struct _PurpleStatus PurpleStatus; +/** @copydoc _PurpleStatusClass */ +typedef struct _PurpleStatusClass PurpleStatusClass; + +#define PURPLE_TYPE_STATUS_TYPE (purple_status_type_get_type()) + +typedef struct _PurpleStatusType PurpleStatusType; + +#define PURPLE_TYPE_STATUS_ATTRIBUTE (purple_status_attribute_get_type()) + +typedef struct _PurpleStatusAttribute PurpleStatusAttribute; + +#define PURPLE_TYPE_MOOD (purple_mood_get_type()) typedef struct _PurpleMood { const char *mood; @@ -94,20 +106,6 @@ typedef struct _PurpleMood { } PurpleMood; /** - * A context for a presence. - * - * The context indicates to what the presence applies. - */ -typedef enum -{ - PURPLE_PRESENCE_CONTEXT_UNSET = 0, - PURPLE_PRESENCE_CONTEXT_ACCOUNT, - PURPLE_PRESENCE_CONTEXT_CONV, - PURPLE_PRESENCE_CONTEXT_BUDDY - -} PurplePresenceContext; - -/** * A primitive defining the basic structure of a status type. */ /* @@ -129,10 +127,7 @@ typedef enum PURPLE_STATUS_NUM_PRIMITIVES } PurpleStatusPrimitive; -#include "account.h" -#include "blist.h" -#include "conversation.h" -#include "value.h" +#include "presence.h" #define PURPLE_TUNE_ARTIST "tune_artist" #define PURPLE_TUNE_TITLE "tune_title" @@ -148,6 +143,26 @@ typedef enum #define PURPLE_MOOD_NAME "mood" #define PURPLE_MOOD_COMMENT "moodtext" +/** + * Represents an active status. + */ +struct _PurpleStatus +{ + /*< private >*/ + GObject gparent; +}; + +/** Base class for all #PurpleStatus's */ +struct _PurpleStatusClass { + /*< private >*/ + GObjectClass parent_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + G_BEGIN_DECLS /**************************************************************************/ @@ -194,6 +209,11 @@ PurpleStatusPrimitive purple_primitive_get_type_from_id(const char *id); /*@{*/ /** + * Returns the GType for the PurpleStatusType boxed structure. + */ +GType purple_status_type_get_type(void); + +/** * Creates a new status type. * * @param primitive The primitive status type. @@ -247,7 +267,7 @@ PurpleStatusType *purple_status_type_new(PurpleStatusPrimitive primitive, * status type. * @param attr_id The ID of the first attribute. * @param attr_name The name of the first attribute. - * @param attr_value The value type of the first attribute attribute. + * @param attr_value The value type of the first attribute. * @param ... Additional attribute information. * * @return A new status type. @@ -260,7 +280,7 @@ PurpleStatusType *purple_status_type_new_with_attrs(PurpleStatusPrimitive primit gboolean independent, const char *attr_id, const char *attr_name, - PurpleValue *attr_value, ...) G_GNUC_NULL_TERMINATED; + GValue *attr_value, ...) G_GNUC_NULL_TERMINATED; /** * Destroys a status type. @@ -358,7 +378,7 @@ gboolean purple_status_type_is_available(const PurpleStatusType *status_type); * * @return The attribute, if found. NULL otherwise. */ -PurpleStatusAttr *purple_status_type_get_attr(const PurpleStatusType *status_type, +PurpleStatusAttribute *purple_status_type_get_attr(const PurpleStatusType *status_type, const char *id); /** @@ -385,11 +405,16 @@ const PurpleStatusType *purple_status_type_find_with_id(GList *status_types, /*@}*/ /**************************************************************************/ -/** @name PurpleStatusAttr API */ +/** @name PurpleStatusAttribute API */ /**************************************************************************/ /*@{*/ /** + * Returns the GType for the PurpleStatusAttribute boxed structure. + */ +GType purple_status_attribute_get_type(void); + +/** * Creates a new status attribute. * * @param id The ID of the attribute. @@ -398,15 +423,15 @@ const PurpleStatusType *purple_status_type_find_with_id(GList *status_types, * * @return A new status attribute. */ -PurpleStatusAttr *purple_status_attr_new(const char *id, const char *name, - PurpleValue *value_type); +PurpleStatusAttribute *purple_status_attribute_new(const char *id, const char *name, + GValue *value_type); /** * Destroys a status attribute. * * @param attr The status attribute to destroy. */ -void purple_status_attr_destroy(PurpleStatusAttr *attr); +void purple_status_attribute_destroy(PurpleStatusAttribute *attr); /** * Returns the ID of a status attribute. @@ -415,7 +440,7 @@ void purple_status_attr_destroy(PurpleStatusAttr *attr); * * @return The status attribute's ID. */ -const char *purple_status_attr_get_id(const PurpleStatusAttr *attr); +const char *purple_status_attribute_get_id(const PurpleStatusAttribute *attr); /** * Returns the name of a status attribute. @@ -424,7 +449,7 @@ const char *purple_status_attr_get_id(const PurpleStatusAttr *attr); * * @return The status attribute's name. */ -const char *purple_status_attr_get_name(const PurpleStatusAttr *attr); +const char *purple_status_attribute_get_name(const PurpleStatusAttribute *attr); /** * Returns the value of a status attribute. @@ -433,16 +458,33 @@ const char *purple_status_attr_get_name(const PurpleStatusAttr *attr); * * @return The status attribute's value. */ -PurpleValue *purple_status_attr_get_value(const PurpleStatusAttr *attr); +GValue *purple_status_attribute_get_value(const PurpleStatusAttribute *attr); /*@}*/ /**************************************************************************/ -/** @name PurpleStatus API */ +/** @name PurpleMood API */ /**************************************************************************/ /*@{*/ /** + * Returns the GType for the PurpleMood boxed structure. + */ +GType purple_mood_get_type(void); + +/*@}*/ + +/**************************************************************************/ +/** @name PurpleStatus API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the Status object. + */ +GType purple_status_get_type(void); + +/** * Creates a new status. * * @param status_type The type of status. @@ -454,13 +496,6 @@ PurpleStatus *purple_status_new(PurpleStatusType *status_type, PurplePresence *presence); /** - * Destroys a status. - * - * @param status The status to destroy. - */ -void purple_status_destroy(PurpleStatus *status); - -/** * Sets whether or not a status is active. * * This should only be called by the account, conversation, and buddy APIs. @@ -507,7 +542,7 @@ void purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean act * * @return The status's type. */ -PurpleStatusType *purple_status_get_type(const PurpleStatus *status); +PurpleStatusType *purple_status_get_status_type(const PurpleStatus *status); /** * Returns the status's presence. @@ -606,7 +641,7 @@ gboolean purple_status_is_online(const PurpleStatus *status); * * @return The value of the attribute. */ -PurpleValue *purple_status_get_attr_value(const PurpleStatus *status, +GValue *purple_status_get_attr_value(const PurpleStatus *status, const char *id); /** @@ -656,271 +691,7 @@ gint purple_status_compare(const PurpleStatus *status1, const PurpleStatus *stat /*@}*/ /**************************************************************************/ -/** @name PurplePresence API */ -/**************************************************************************/ -/*@{*/ - -/** - * Creates a new presence. - * - * @param context The presence context. - * - * @return A new presence. - */ -PurplePresence *purple_presence_new(PurplePresenceContext context); - -/** - * Creates a presence for an account. - * - * @param account The account. - * - * @return The new presence. - */ -PurplePresence *purple_presence_new_for_account(PurpleAccount *account); - -/** - * Creates a presence for a conversation. - * - * @param conv The conversation. - * - * @return The new presence. - */ -PurplePresence *purple_presence_new_for_conv(PurpleConversation *conv); - -/** - * Creates a presence for a buddy. - * - * @param buddy The buddy. - * - * @return The new presence. - */ -PurplePresence *purple_presence_new_for_buddy(PurpleBuddy *buddy); - -/** - * Destroys a presence. - * - * All statuses added to this list will be destroyed along with - * the presence. - * - * @param presence The presence to destroy. - */ -void purple_presence_destroy(PurplePresence *presence); - -/** - * Sets the active state of a status in a presence. - * - * Only independent statuses can be set unactive. Normal statuses can only - * be set active, so if you wish to disable a status, set another - * non-independent status to active, or use purple_presence_switch_status(). - * - * @param presence The presence. - * @param status_id The ID of the status. - * @param active The active state. - */ -void purple_presence_set_status_active(PurplePresence *presence, - const char *status_id, gboolean active); - -/** - * Switches the active status in a presence. - * - * This is similar to purple_presence_set_status_active(), except it won't - * activate independent statuses. - * - * @param presence The presence. - * @param status_id The status ID to switch to. - */ -void purple_presence_switch_status(PurplePresence *presence, - const char *status_id); - -/** - * Sets the idle state and time on a presence. - * - * @param presence The presence. - * @param idle The idle state. - * @param idle_time The idle time, if @a idle is TRUE. This - * is the time at which the user became idle, - * in seconds since the epoch. If this value is - * unknown then 0 should be used. - */ -void purple_presence_set_idle(PurplePresence *presence, gboolean idle, - time_t idle_time); - -/** - * Sets the login time on a presence. - * - * @param presence The presence. - * @param login_time The login time. - */ -void purple_presence_set_login_time(PurplePresence *presence, time_t login_time); - - -/** - * Returns the presence's context. - * - * @param presence The presence. - * - * @return The presence's context. - */ -PurplePresenceContext purple_presence_get_context(const PurplePresence *presence); - -/** - * Returns a presence's account. - * - * @param presence The presence. - * - * @return The presence's account. - */ -PurpleAccount *purple_presence_get_account(const PurplePresence *presence); - -/** - * Returns a presence's conversation. - * - * @param presence The presence. - * - * @return The presence's conversation. - */ -PurpleConversation *purple_presence_get_conversation(const PurplePresence *presence); - -/** - * Returns a presence's chat user. - * - * @param presence The presence. - * - * @return The chat's user. - */ -const char *purple_presence_get_chat_user(const PurplePresence *presence); - -/** - * Returns the presence's buddy. - * - * @param presence The presence. - * - * @return The presence's buddy. - */ -PurpleBuddy *purple_presence_get_buddy(const PurplePresence *presence); - -/** - * Returns all the statuses in a presence. - * - * @param presence The presence. - * - * @constreturn The statuses. - */ -GList *purple_presence_get_statuses(const PurplePresence *presence); - -/** - * Returns the status with the specified ID from a presence. - * - * @param presence The presence. - * @param status_id The ID of the status. - * - * @return The status if found, or NULL. - */ -PurpleStatus *purple_presence_get_status(const PurplePresence *presence, - const char *status_id); - -/** - * Returns the active exclusive status from a presence. - * - * @param presence The presence. - * - * @return The active exclusive status. - */ -PurpleStatus *purple_presence_get_active_status(const PurplePresence *presence); - -/** - * Returns whether or not a presence is available. - * - * Available presences are online and possibly invisible, but not away or idle. - * - * @param presence The presence. - * - * @return TRUE if the presence is available, or FALSE otherwise. - */ -gboolean purple_presence_is_available(const PurplePresence *presence); - -/** - * Returns whether or not a presence is online. - * - * @param presence The presence. - * - * @return TRUE if the presence is online, or FALSE otherwise. - */ -gboolean purple_presence_is_online(const PurplePresence *presence); - -/** - * Returns whether or not a status in a presence is active. - * - * A status is active if itself or any of its sub-statuses are active. - * - * @param presence The presence. - * @param status_id The ID of the status. - * - * @return TRUE if the status is active, or FALSE. - */ -gboolean purple_presence_is_status_active(const PurplePresence *presence, - const char *status_id); - -/** - * Returns whether or not a status with the specified primitive type - * in a presence is active. - * - * A status is active if itself or any of its sub-statuses are active. - * - * @param presence The presence. - * @param primitive The status primitive. - * - * @return TRUE if the status is active, or FALSE. - */ -gboolean purple_presence_is_status_primitive_active( - const PurplePresence *presence, PurpleStatusPrimitive primitive); - -/** - * Returns whether or not a presence is idle. - * - * @param presence The presence. - * - * @return TRUE if the presence is idle, or FALSE otherwise. - * If the presence is offline (purple_presence_is_online() - * returns FALSE) then FALSE is returned. - */ -gboolean purple_presence_is_idle(const PurplePresence *presence); - -/** - * Returns the presence's idle time. - * - * @param presence The presence. - * - * @return The presence's idle time. - */ -time_t purple_presence_get_idle_time(const PurplePresence *presence); - -/** - * Returns the presence's login time. - * - * @param presence The presence. - * - * @return The presence's login time. - */ -time_t purple_presence_get_login_time(const PurplePresence *presence); - -/** - * Compares two presences for availability. - * - * @param presence1 The first presence. - * @param presence2 The second presence. - * - * @return -1 if @a presence1 is more available than @a presence2. - * 0 if @a presence1 is equal to @a presence2. - * 1 if @a presence1 is less available than @a presence2. - */ -gint purple_presence_compare(const PurplePresence *presence1, - const PurplePresence *presence2); - -/*@}*/ - -/**************************************************************************/ -/** @name Status subsystem */ +/** @name Statuses subsystem */ /**************************************************************************/ /*@{*/ @@ -929,17 +700,17 @@ gint purple_presence_compare(const PurplePresence *presence1, * * @return the handle to the status subsystem */ -void *purple_status_get_handle(void); +void *purple_statuses_get_handle(void); /** * Initializes the status subsystem. */ -void purple_status_init(void); +void purple_statuses_init(void); /** * Uninitializes the status subsystem. */ -void purple_status_uninit(void); +void purple_statuses_uninit(void); /*@}*/ diff --git a/libpurple/tests/test_cipher.c b/libpurple/tests/test_cipher.c index f686f07f64..8f21a6935c 100644 --- a/libpurple/tests/test_cipher.c +++ b/libpurple/tests/test_cipher.c @@ -7,28 +7,32 @@ #include "tests.h" -#include "../cipher.h" +#include "../ciphers/des3cipher.h" +#include "../ciphers/descipher.h" +#include "../ciphers/hmaccipher.h" +#include "../ciphers/md4hash.h" +#include "../ciphers/md5hash.h" +#include "../ciphers/sha1hash.h" +#include "../ciphers/sha256hash.h" /****************************************************************************** * MD4 Tests *****************************************************************************/ #define MD4_TEST(data, digest) { \ - PurpleCipher *cipher = NULL; \ - PurpleCipherContext *context = NULL; \ + PurpleHash *hash = NULL; \ gchar cdigest[33]; \ gboolean ret = FALSE; \ \ - cipher = purple_ciphers_find_cipher("md4"); \ - context = purple_cipher_context_new(cipher, NULL); \ - purple_cipher_context_append(context, (guchar *)(data), strlen((data))); \ + hash = purple_md4_hash_new(); \ + purple_hash_append(hash, (guchar *)(data), strlen((data))); \ \ - ret = purple_cipher_context_digest_to_str(context, cdigest, sizeof(cdigest)); \ + ret = purple_hash_digest_to_str(hash, cdigest, sizeof(cdigest)); \ \ fail_unless(ret == TRUE, NULL); \ \ fail_unless(strcmp((digest), cdigest) == 0, NULL); \ \ - purple_cipher_context_destroy(context); \ + g_object_unref(hash); \ } START_TEST(test_md4_empty_string) { @@ -75,22 +79,20 @@ END_TEST * MD5 Tests *****************************************************************************/ #define MD5_TEST(data, digest) { \ - PurpleCipher *cipher = NULL; \ - PurpleCipherContext *context = NULL; \ + PurpleHash *hash = NULL; \ gchar cdigest[33]; \ gboolean ret = FALSE; \ \ - cipher = purple_ciphers_find_cipher("md5"); \ - context = purple_cipher_context_new(cipher, NULL); \ - purple_cipher_context_append(context, (guchar *)(data), strlen((data))); \ + hash = purple_md5_hash_new(); \ + purple_hash_append(hash, (guchar *)(data), strlen((data))); \ \ - ret = purple_cipher_context_digest_to_str(context, cdigest, sizeof(cdigest)); \ + ret = purple_hash_digest_to_str(hash, cdigest, sizeof(cdigest)); \ \ fail_unless(ret == TRUE, NULL); \ \ fail_unless(strcmp((digest), cdigest) == 0, NULL); \ \ - purple_cipher_context_destroy(context); \ + g_object_unref(hash); \ } START_TEST(test_md5_empty_string) { @@ -136,17 +138,15 @@ END_TEST * SHA-1 Tests *****************************************************************************/ #define SHA1_TEST(data, digest) { \ - PurpleCipher *cipher = NULL; \ - PurpleCipherContext *context = NULL; \ + PurpleHash *hash = NULL; \ gchar cdigest[41]; \ gboolean ret = FALSE; \ gchar *input = data; \ \ - cipher = purple_ciphers_find_cipher("sha1"); \ - context = purple_cipher_context_new(cipher, NULL); \ + hash = purple_sha1_hash_new(); \ \ if (input) { \ - purple_cipher_context_append(context, (guchar *)input, strlen(input)); \ + purple_hash_append(hash, (guchar *)input, strlen(input)); \ } else { \ gint j; \ guchar buff[1000]; \ @@ -154,16 +154,16 @@ END_TEST memset(buff, 'a', 1000); \ \ for(j = 0; j < 1000; j++) \ - purple_cipher_context_append(context, buff, 1000); \ + purple_hash_append(hash, buff, 1000); \ } \ \ - ret = purple_cipher_context_digest_to_str(context, cdigest, sizeof(cdigest)); \ + ret = purple_hash_digest_to_str(hash, cdigest, sizeof(cdigest)); \ \ fail_unless(ret == TRUE, NULL); \ \ fail_unless(strcmp((digest), cdigest) == 0, NULL); \ \ - purple_cipher_context_destroy(context); \ + g_object_unref(hash); \ } START_TEST(test_sha1_empty_string) { @@ -196,17 +196,15 @@ END_TEST * SHA-256 Tests *****************************************************************************/ #define SHA256_TEST(data, digest) { \ - PurpleCipher *cipher = NULL; \ - PurpleCipherContext *context = NULL; \ + PurpleHash *hash = NULL; \ gchar cdigest[65]; \ gboolean ret = FALSE; \ gchar *input = data; \ \ - cipher = purple_ciphers_find_cipher("sha256"); \ - context = purple_cipher_context_new(cipher, NULL); \ + hash = purple_sha256_hash_new(); \ \ if (input) { \ - purple_cipher_context_append(context, (guchar *)input, strlen(input)); \ + purple_hash_append(hash, (guchar *)input, strlen(input)); \ } else { \ gint j; \ guchar buff[1000]; \ @@ -214,16 +212,16 @@ END_TEST memset(buff, 'a', 1000); \ \ for(j = 0; j < 1000; j++) \ - purple_cipher_context_append(context, buff, 1000); \ + purple_hash_append(hash, buff, 1000); \ } \ \ - ret = purple_cipher_context_digest_to_str(context, cdigest, sizeof(cdigest)); \ + ret = purple_hash_digest_to_str(hash, cdigest, sizeof(cdigest)); \ \ fail_unless(ret == TRUE, NULL); \ \ fail_unless(strcmp((digest), cdigest) == 0, NULL); \ \ - purple_cipher_context_destroy(context); \ + g_object_unref(hash); \ } START_TEST(test_sha256_empty_string) { @@ -257,26 +255,24 @@ END_TEST *****************************************************************************/ #define DES_TEST(in, keyz, out, len) { \ PurpleCipher *cipher = NULL; \ - PurpleCipherContext *context = NULL; \ guchar answer[len+1]; \ gint ret = 0; \ guchar decrypt[len+1] = in; \ guchar key[8+1] = keyz;\ guchar encrypt[len+1] = out;\ \ - cipher = purple_ciphers_find_cipher("des"); \ - context = purple_cipher_context_new(cipher, NULL); \ - purple_cipher_context_set_key(context, key, 8); \ + cipher = purple_des_cipher_new(); \ + purple_cipher_set_key(cipher, key, 8); \ \ - ret = purple_cipher_context_encrypt(context, decrypt, len, answer, len); \ + ret = purple_cipher_encrypt(cipher, decrypt, len, answer, len); \ fail_unless(ret == len, NULL); \ fail_unless(memcmp(encrypt, answer, len) == 0, NULL); \ \ - ret = purple_cipher_context_decrypt(context, encrypt, len, answer, len); \ + ret = purple_cipher_decrypt(cipher, encrypt, len, answer, len); \ fail_unless(ret == len, NULL); \ fail_unless(memcmp(decrypt, answer, len) == 0, NULL); \ \ - purple_cipher_context_destroy(context); \ + g_object_unref(cipher); \ } START_TEST(test_des_12345678) { @@ -303,28 +299,25 @@ END_TEST #define DES3_TEST(in, key, iv, out, len, mode) { \ PurpleCipher *cipher = NULL; \ - PurpleCipherContext *context = NULL; \ guchar answer[len+1]; \ guchar decrypt[len+1] = in; \ guchar encrypt[len+1] = out; \ gint ret = 0; \ \ - cipher = purple_ciphers_find_cipher("des3"); \ - context = purple_cipher_context_new(cipher, NULL); \ - purple_cipher_context_set_key(context, (guchar *)key, 24); \ - purple_cipher_context_set_batch_mode(context, (mode)); \ - purple_cipher_context_set_iv(context, (guchar *)iv, 8); \ + cipher = purple_des3_cipher_new(); \ + purple_cipher_set_key(cipher, (guchar *)key, 24); \ + purple_cipher_set_batch_mode(cipher, (mode)); \ + purple_cipher_set_iv(cipher, (guchar *)iv, 8); \ \ - fprintf(stderr, "len: %lu\n", len); \ - ret = purple_cipher_context_encrypt(context, decrypt, len, answer, len); \ + ret = purple_cipher_encrypt(cipher, decrypt, len, answer, len); \ fail_unless(ret == len, NULL); \ fail_unless(memcmp(encrypt, answer, len) == 0, NULL); \ \ - ret = purple_cipher_context_decrypt(context, encrypt, len, answer, len); \ + ret = purple_cipher_decrypt(cipher, encrypt, len, answer, len); \ fail_unless(ret == len, NULL); \ fail_unless(memcmp(decrypt, answer, len) == 0, NULL); \ \ - purple_cipher_context_destroy(context); \ + g_object_unref(cipher); \ } START_TEST(test_des3_ecb_nist1) { @@ -472,22 +465,22 @@ END_TEST #define HMAC_TEST(data, data_len, key, key_len, type, digest) { \ PurpleCipher *cipher = NULL; \ - PurpleCipherContext *context = NULL; \ + PurpleHash *hash = NULL; \ gchar cdigest[41]; \ gboolean ret = FALSE; \ \ - cipher = purple_ciphers_find_cipher("hmac"); \ - context = purple_cipher_context_new(cipher, NULL); \ - purple_cipher_context_set_option(context, "hash", type); \ - purple_cipher_context_set_key(context, (guchar *)key, (key_len)); \ + hash = purple_##type##_hash_new(); \ + cipher = purple_hmac_cipher_new(hash); \ + purple_cipher_set_key(cipher, (guchar *)key, (key_len)); \ \ - purple_cipher_context_append(context, (guchar *)(data), (data_len)); \ - ret = purple_cipher_context_digest_to_str(context, cdigest, sizeof(cdigest)); \ + purple_cipher_append(cipher, (guchar *)(data), (data_len)); \ + ret = purple_cipher_digest_to_str(cipher, cdigest, sizeof(cdigest)); \ \ fail_unless(ret == TRUE, NULL); \ fail_unless(strcmp((digest), cdigest) == 0, NULL); \ \ - purple_cipher_context_destroy(context); \ + g_object_unref(cipher); \ + g_object_unref(hash); \ } /* HMAC MD5 */ @@ -497,7 +490,7 @@ START_TEST(test_hmac_md5_Hi) { 8, "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 16, - "md5", + md5, "9294727a3638bb1c13f48ef8158bfc9d"); } END_TEST @@ -507,7 +500,7 @@ START_TEST(test_hmac_md5_what) { 28, "Jefe", 4, - "md5", + md5, "750c783e6ab0b503eaa86e310a5db738"); } END_TEST @@ -521,7 +514,7 @@ START_TEST(test_hmac_md5_dd) { 50, "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 16, - "md5", + md5, "56be34521d144c88dbb8c733f0e8b3f6"); } END_TEST @@ -537,7 +530,7 @@ START_TEST(test_hmac_md5_cd) { "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" "\x15\x16\x17\x18\x19", 25, - "md5", + md5, "697eaf0aca3a3aea3a75164746ffaa79"); } END_TEST @@ -547,7 +540,7 @@ START_TEST(test_hmac_md5_truncation) { 20, "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", 16, - "md5", + md5, "56461ef2342edc00f9bab995690efd4c"); } END_TEST @@ -564,7 +557,7 @@ START_TEST(test_hmac_md5_large_key) { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80, - "md5", + md5, "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd"); } END_TEST @@ -581,7 +574,7 @@ START_TEST(test_hmac_md5_large_key_and_data) { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80, - "md5", + md5, "6f630fad67cda0ee1fb1f562db3aa53e"); } END_TEST @@ -592,7 +585,7 @@ START_TEST(test_hmac_md5_null_key) { "\x0a\x0b\x00\x0d\x0e\x0f\x1a\x2f\x0b\x0b" "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", 20, - "md5", + md5, "597bfd644b797a985561eeb03a169e59"); } END_TEST @@ -603,7 +596,7 @@ START_TEST(test_hmac_md5_null_text) { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20, - "md5", + md5, "70be8e1b7b50dfcc335d6cd7992c564f"); } END_TEST @@ -614,7 +607,7 @@ START_TEST(test_hmac_md5_null_key_and_text) { "\x0c\x0d\x00\x0f\x10\x1a\x3a\x3a\xe6\x34" "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", 20, - "md5", + md5, "b31bcbba35a33a067cbba9131cba4889"); } END_TEST @@ -627,7 +620,7 @@ START_TEST(test_hmac_sha1_Hi) { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20, - "sha1", + sha1, "b617318655057264e28bc0b6fb378c8ef146be00"); } END_TEST @@ -637,7 +630,7 @@ START_TEST(test_hmac_sha1_what) { 28, "Jefe", 4, - "sha1", + sha1, "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79"); } END_TEST @@ -652,7 +645,7 @@ START_TEST(test_hmac_sha1_dd) { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 20, - "sha1", + sha1, "125d7342b9ac11cd91a39af48aa17b4f63f175d3"); } END_TEST @@ -668,7 +661,7 @@ START_TEST(test_hmac_sha1_cd) { "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" "\x15\x16\x17\x18\x19", 25, - "sha1", + sha1, "4c9007f4026250c6bc8414f9bf50c86c2d7235da"); } END_TEST @@ -679,7 +672,7 @@ START_TEST(test_hmac_sha1_truncation) { "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", 20, - "sha1", + sha1, "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04"); } END_TEST @@ -696,7 +689,7 @@ START_TEST(test_hmac_sha1_large_key) { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80, - "sha1", + sha1, "aa4ae5e15272d00e95705637ce8a3b55ed402112"); } END_TEST @@ -713,7 +706,7 @@ START_TEST(test_hmac_sha1_large_key_and_data) { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80, - "sha1", + sha1, "e8e99d0f45237d786d6bbaa7965c7808bbff1a91"); } END_TEST @@ -724,7 +717,7 @@ START_TEST(test_hmac_sha1_null_key) { "\x0a\x0b\x00\x0d\x0e\x0f\x1a\x2f\x0b\x0b" "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", 20, - "sha1", + sha1, "eb62a2e0e33d300be669c52aab3f591bc960aac5"); } END_TEST @@ -735,7 +728,7 @@ START_TEST(test_hmac_sha1_null_text) { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20, - "sha1", + sha1, "31ca58d849e971e418e3439de2c6f83144b6abb7"); } END_TEST @@ -746,7 +739,7 @@ START_TEST(test_hmac_sha1_null_key_and_text) { "\x0c\x0d\x00\x0f\x10\x1a\x3a\x3a\xe6\x34" "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", 20, - "sha1", + sha1, "e6b8e2fede87aa09dcb13e554df1435e056eae36"); } END_TEST diff --git a/libpurple/tests/test_jabber_caps.c b/libpurple/tests/test_jabber_caps.c index 6af180b658..c0d4cd1893 100644 --- a/libpurple/tests/test_jabber_caps.c +++ b/libpurple/tests/test_jabber_caps.c @@ -3,6 +3,8 @@ #include "tests.h" #include "../xmlnode.h" #include "../protocols/jabber/caps.h" +#include "../ciphers/md5hash.h" +#include "../ciphers/sha1hash.h" START_TEST(test_parse_invalid) { @@ -25,14 +27,22 @@ END_TEST #define assert_caps_calculate_match(hash_func, hash, str) { \ xmlnode *query = xmlnode_from_str((str), -1); \ + PurpleHash *hasher = NULL; \ JabberCapsClientInfo *info = jabber_caps_parse_client_info(query); \ - gchar *got_hash = jabber_caps_calculate_hash(info, (hash_func)); \ + gchar *got_hash; \ + if (g_str_equal(hash_func, "sha-1")) { \ + hasher = purple_sha1_hash_new(); \ + } else if (g_str_equal(hash_func, "md5")) { \ + hasher = purple_md5_hash_new(); \ + } \ + got_hash = jabber_caps_calculate_hash(info, hasher); \ + g_object_unref(hasher); \ assert_string_equal_free((hash), got_hash); \ } START_TEST(test_calculate_caps) { - assert_caps_calculate_match("sha1", "GNjxthSckUNvAIoCCJFttjl6VL8=", + assert_caps_calculate_match("sha-1", "GNjxthSckUNvAIoCCJFttjl6VL8=", "<query xmlns='http://jabber.org/protocol/disco#info' node='http://tkabber.jabber.ru/#GNjxthSckUNvAIoCCJFttjl6VL8='><identity category='client' type='pc' name='Tkabber'/><x xmlns='jabber:x:data' type='result'><field var='FORM_TYPE' type='hidden'><value>urn:xmpp:dataforms:softwareinfo</value></field><field var='software'><value>Tkabber</value></field><field var='software_version'><value> ( 8.5.5 )</value></field><field var='os'><value>ATmega640-16AU</value></field><field var='os_version'><value/></field></x><feature var='games:board'/><feature var='google:mail:notify'/><feature var='http://jabber.org/protocol/activity'/><feature var='http://jabber.org/protocol/bytestreams'/><feature var='http://jabber.org/protocol/chatstates'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/disco#info'/><feature var='http://jabber.org/protocol/disco#items'/><feature var='http://jabber.org/protocol/feature-neg'/><feature var='http://jabber.org/protocol/geoloc'/><feature var='http://jabber.org/protocol/ibb'/><feature var='http://jabber.org/protocol/iqibb'/><feature var='http://jabber.org/protocol/mood'/><feature var='http://jabber.org/protocol/muc'/><feature var='http://jabber.org/protocol/mute#ancestor'/><feature var='http://jabber.org/protocol/mute#editor'/><feature var='http://jabber.org/protocol/rosterx'/><feature var='http://jabber.org/protocol/si'/><feature var='http://jabber.org/protocol/si/profile/file-transfer'/><feature var='http://jabber.org/protocol/tune'/><feature var='jabber:iq:avatar'/><feature var='jabber:iq:browse'/><feature var='jabber:iq:dtcp'/><feature var='jabber:iq:filexfer'/><feature var='jabber:iq:ibb'/><feature var='jabber:iq:inband'/><feature var='jabber:iq:jidlink'/><feature var='jabber:iq:last'/><feature var='jabber:iq:oob'/><feature var='jabber:iq:privacy'/><feature var='jabber:iq:time'/><feature var='jabber:iq:version'/><feature var='jabber:x:data'/><feature var='jabber:x:event'/><feature var='jabber:x:oob'/><feature var='urn:xmpp:ping'/><feature var='urn:xmpp:receipts'/><feature var='urn:xmpp:time'/></query>"); } END_TEST diff --git a/libpurple/tests/test_jabber_scram.c b/libpurple/tests/test_jabber_scram.c index 512bc05a29..bb440100a5 100644 --- a/libpurple/tests/test_jabber_scram.c +++ b/libpurple/tests/test_jabber_scram.c @@ -4,8 +4,9 @@ #include "../util.h" #include "../protocols/jabber/auth_scram.h" #include "../protocols/jabber/jutil.h" +#include "../ciphers/sha1hash.h" -static JabberScramHash sha1_mech = { "-SHA-1", "sha1", 20 }; +static JabberScramHash sha1_mech = { "-SHA-1", purple_sha1_hash_new, 20 }; #define assert_pbkdf2_equal(password, salt, count, expected) { \ GString *p = g_string_new(password); \ diff --git a/libpurple/theme-loader.h b/libpurple/theme-loader.h index dedef39d9f..ec9f99c896 100644 --- a/libpurple/theme-loader.h +++ b/libpurple/theme-loader.h @@ -49,14 +49,22 @@ typedef struct _PurpleThemeLoaderClass PurpleThemeLoaderClass; struct _PurpleThemeLoader { + /*< private >*/ GObject parent; }; struct _PurpleThemeLoaderClass { + /*< private >*/ GObjectClass parent_class; + PurpleTheme *((*purple_theme_loader_build)(const gchar*)); gboolean (*probe_directory)(const gchar *); + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); }; /**************************************************************************/ diff --git a/libpurple/theme-manager.h b/libpurple/theme-manager.h index f7273394c0..6c31e81065 100644 --- a/libpurple/theme-manager.h +++ b/libpurple/theme-manager.h @@ -45,11 +45,18 @@ typedef struct _PurpleThemeManagerClass PurpleThemeManagerClass; #define PURPLE_GET_THEME_MANAGER_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_THEME_MANAGER, PurpleThemeManagerClass)) struct _PurpleThemeManager { + /*< private >*/ GObject parent; }; struct _PurpleThemeManagerClass { + /*< private >*/ GObjectClass parent_class; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); }; /**************************************************************************/ diff --git a/libpurple/theme.h b/libpurple/theme.h index 9f4b0bc8f1..dfc4ea6f21 100644 --- a/libpurple/theme.h +++ b/libpurple/theme.h @@ -48,12 +48,19 @@ typedef struct _PurpleThemeClass PurpleThemeClass; struct _PurpleTheme { + /*< private >*/ GObject parent; }; struct _PurpleThemeClass { + /*< private >*/ GObjectClass parent_class; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); }; /**************************************************************************/ diff --git a/libpurple/util.c b/libpurple/util.c index 1294ec6e78..b2abccb94e 100644 --- a/libpurple/util.c +++ b/libpurple/util.c @@ -23,7 +23,7 @@ */ #include "internal.h" -#include "cipher.h" +#include "ciphers/md5hash.h" #include "conversation.h" #include "core.h" #include "debug.h" @@ -4748,3 +4748,197 @@ purple_uuid_random(void) b, (tmp >> 16) & 0xFFFF, g_random_int()); } + +GValue * +purple_g_value_new(GType type) +{ + GValue *ret; + + g_return_val_if_fail(type != G_TYPE_NONE, NULL); + + ret = g_new0(GValue, 1); + g_value_init(ret, type); + + return ret; +} + +GValue * +purple_g_value_dup(GValue *value) +{ + GValue *ret; + + g_return_val_if_fail(value != NULL, NULL); + + ret = g_new0(GValue, 1); + g_value_init(ret, G_VALUE_TYPE(value)); + g_value_copy(value, ret); + + return ret; +} + +void +purple_g_value_free(GValue *value) +{ + g_return_if_fail(value != NULL); + + g_value_unset(value); + g_free(value); +} + +gchar *purple_http_digest_calculate_session_key( + const gchar *algorithm, + const gchar *username, + const gchar *realm, + const gchar *password, + const gchar *nonce, + const gchar *client_nonce) +{ + PurpleHash *hasher; + gchar hash[33]; /* We only support MD5. */ + + g_return_val_if_fail(username != NULL, NULL); + g_return_val_if_fail(realm != NULL, NULL); + g_return_val_if_fail(password != NULL, NULL); + g_return_val_if_fail(nonce != NULL, NULL); + + /* Check for a supported algorithm. */ + g_return_val_if_fail(algorithm == NULL || + *algorithm == '\0' || + g_ascii_strcasecmp(algorithm, "MD5") || + g_ascii_strcasecmp(algorithm, "MD5-sess"), NULL); + + hasher = purple_md5_hash_new(); + g_return_val_if_fail(hash != NULL, NULL); + + purple_hash_append(hasher, (guchar *)username, strlen(username)); + purple_hash_append(hasher, (guchar *)":", 1); + purple_hash_append(hasher, (guchar *)realm, strlen(realm)); + purple_hash_append(hasher, (guchar *)":", 1); + purple_hash_append(hasher, (guchar *)password, strlen(password)); + + if (algorithm != NULL && !g_ascii_strcasecmp(algorithm, "MD5-sess")) + { + guchar digest[16]; + + if (client_nonce == NULL) + { + g_object_unref(hasher); + purple_debug_error("hash", "Required client_nonce missing for MD5-sess digest calculation.\n"); + return NULL; + } + + purple_hash_digest(hasher, digest, sizeof(digest)); + + purple_hash_reset(hasher); + purple_hash_append(hasher, digest, sizeof(digest)); + purple_hash_append(hasher, (guchar *)":", 1); + purple_hash_append(hasher, (guchar *)nonce, strlen(nonce)); + purple_hash_append(hasher, (guchar *)":", 1); + purple_hash_append(hasher, (guchar *)client_nonce, strlen(client_nonce)); + } + + purple_hash_digest_to_str(hasher, hash, sizeof(hash)); + g_object_unref(hasher); + + return g_strdup(hash); +} + +gchar *purple_http_digest_calculate_response( + const gchar *algorithm, + const gchar *method, + const gchar *digest_uri, + const gchar *qop, + const gchar *entity, + const gchar *nonce, + const gchar *nonce_count, + const gchar *client_nonce, + const gchar *session_key) +{ + PurpleHash *hash; + static gchar hash2[33]; /* We only support MD5. */ + + g_return_val_if_fail(method != NULL, NULL); + g_return_val_if_fail(digest_uri != NULL, NULL); + g_return_val_if_fail(nonce != NULL, NULL); + g_return_val_if_fail(session_key != NULL, NULL); + + /* Check for a supported algorithm. */ + g_return_val_if_fail(algorithm == NULL || + *algorithm == '\0' || + g_ascii_strcasecmp(algorithm, "MD5") || + g_ascii_strcasecmp(algorithm, "MD5-sess"), NULL); + + /* Check for a supported "quality of protection". */ + g_return_val_if_fail(qop == NULL || + *qop == '\0' || + g_ascii_strcasecmp(qop, "auth") || + g_ascii_strcasecmp(qop, "auth-int"), NULL); + + hash = purple_md5_hash_new(); + g_return_val_if_fail(hash != NULL, NULL); + + purple_hash_append(hash, (guchar *)method, strlen(method)); + purple_hash_append(hash, (guchar *)":", 1); + purple_hash_append(hash, (guchar *)digest_uri, strlen(digest_uri)); + + if (qop != NULL && !g_ascii_strcasecmp(qop, "auth-int")) + { + PurpleHash *hash2; + gchar entity_hash[33]; + + if (entity == NULL) + { + g_object_unref(hash); + purple_debug_error("hash", "Required entity missing for auth-int digest calculation.\n"); + return NULL; + } + + hash2 = purple_md5_hash_new(); + purple_hash_append(hash2, (guchar *)entity, strlen(entity)); + purple_hash_digest_to_str(hash2, entity_hash, sizeof(entity_hash)); + g_object_unref(hash2); + + purple_hash_append(hash, (guchar *)":", 1); + purple_hash_append(hash, (guchar *)entity_hash, strlen(entity_hash)); + } + + purple_hash_digest_to_str(hash, hash2, sizeof(hash2)); + purple_hash_reset(hash); + + purple_hash_append(hash, (guchar *)session_key, strlen(session_key)); + purple_hash_append(hash, (guchar *)":", 1); + purple_hash_append(hash, (guchar *)nonce, strlen(nonce)); + purple_hash_append(hash, (guchar *)":", 1); + + if (qop != NULL && *qop != '\0') + { + if (nonce_count == NULL) + { + g_object_unref(hash); + purple_debug_error("hash", "Required nonce_count missing for digest calculation.\n"); + return NULL; + } + + if (client_nonce == NULL) + { + g_object_unref(hash); + purple_debug_error("hash", "Required client_nonce missing for digest calculation.\n"); + return NULL; + } + + purple_hash_append(hash, (guchar *)nonce_count, strlen(nonce_count)); + purple_hash_append(hash, (guchar *)":", 1); + purple_hash_append(hash, (guchar *)client_nonce, strlen(client_nonce)); + purple_hash_append(hash, (guchar *)":", 1); + + purple_hash_append(hash, (guchar *)qop, strlen(qop)); + + purple_hash_append(hash, (guchar *)":", 1); + } + + purple_hash_append(hash, (guchar *)hash2, strlen(hash2)); + purple_hash_digest_to_str(hash, hash2, sizeof(hash2)); + g_object_unref(hash); + + return g_strdup(hash2); +} diff --git a/libpurple/util.h b/libpurple/util.h index a8e9ab0cd8..c4e2d7ef07 100644 --- a/libpurple/util.h +++ b/libpurple/util.h @@ -1431,6 +1431,73 @@ const gchar *purple_get_host_name(void); */ gchar *purple_uuid_random(void); +/** + * Creates a new GValue of the specified type. + * + * @param type The type of data to be held by the GValue + * + * @return The created GValue + */ +GValue *purple_g_value_new(GType type); + +/** + * Duplicates a GValue. + * + * @param value The GValue to duplicate + * + * @return The duplicated GValue + */ +GValue *purple_g_value_dup(GValue *value); + +/** + * Frees a GValue. + * + * @param value The GValue to free. + */ +void purple_g_value_free(GValue *value); + +/** + * Calculates a session key for HTTP Digest authentation + * + * See RFC 2617 for more information. + * + * @param algorithm The hash algorithm to use + * @param username The username provided by the user + * @param realm The authentication realm provided by the server + * @param password The password provided by the user + * @param nonce The nonce provided by the server + * @param client_nonce The nonce provided by the client + * + * @return The session key, or @c NULL if an error occurred. + */ +gchar *purple_http_digest_calculate_session_key( + const gchar *algorithm, const gchar *username, + const gchar *realm, const gchar *password, + const gchar *nonce, const gchar *client_nonce); + +/** Calculate a response for HTTP Digest authentication + * + * See RFC 2617 for more information. + * + * @param algorithm The hash algorithm to use + * @param method The HTTP method in use + * @param digest_uri The URI from the initial request + * @param qop The "quality of protection" + * @param entity The entity body + * @param nonce The nonce provided by the server + * @param nonce_count The nonce count + * @param client_nonce The nonce provided by the client + * @param session_key The session key from purple_cipher_http_digest_calculate_session_key() + * + * @return The hashed response, or @c NULL if an error occurred. + */ +gchar *purple_http_digest_calculate_response( + const gchar *algorithm, const gchar *method, + const gchar *digest_uri, const gchar *qop, + const gchar *entity, const gchar *nonce, + const gchar *nonce_count, const gchar *client_nonce, + const gchar *session_key); + G_END_DECLS #endif /* _PURPLE_UTIL_H_ */ diff --git a/libpurple/value.c b/libpurple/value.c deleted file mode 100644 index 34ed57baa5..0000000000 --- a/libpurple/value.c +++ /dev/null @@ -1,526 +0,0 @@ -/** - * @file value.c Value wrapper API - * @ingroup core - */ - -/* purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "internal.h" - -#include "value.h" - -#define OUTGOING_FLAG 0x01 - -/** - * A wrapper for a type, subtype, and specific type of value. - */ -struct _PurpleValue -{ - PurpleType type; - unsigned short flags; - - union - { - char char_data; - unsigned char uchar_data; - gboolean boolean_data; - short short_data; - unsigned short ushort_data; - int int_data; - unsigned int uint_data; - long long_data; - unsigned long ulong_data; - gint64 int64_data; - guint64 uint64_data; - char *string_data; - void *object_data; - void *pointer_data; - int enum_data; - void *boxed_data; - - } data; - - union - { - unsigned int subtype; - char *specific_type; - - } u; - -}; - -PurpleValue * -purple_value_new(PurpleType type, ...) -{ - PurpleValue *value; - va_list args; - - g_return_val_if_fail(type != PURPLE_TYPE_UNKNOWN, NULL); - - value = g_new0(PurpleValue, 1); - - value->type = type; - - va_start(args, type); - - if (type == PURPLE_TYPE_SUBTYPE) - value->u.subtype = va_arg(args, int); - else if (type == PURPLE_TYPE_BOXED) - value->u.specific_type = g_strdup(va_arg(args, char *)); - - va_end(args); - - return value; -} - -PurpleValue * -purple_value_new_outgoing(PurpleType type, ...) -{ - PurpleValue *value; - va_list args; - - g_return_val_if_fail(type != PURPLE_TYPE_UNKNOWN, NULL); - - value = g_new0(PurpleValue, 1); - - value->type = type; - - va_start(args, type); - - if (type == PURPLE_TYPE_SUBTYPE) - value->u.subtype = va_arg(args, int); - else if (type == PURPLE_TYPE_BOXED) - value->u.specific_type = g_strdup(va_arg(args, char *)); - - va_end(args); - - value->flags |= OUTGOING_FLAG; - - return value; -} - -void -purple_value_destroy(PurpleValue *value) -{ - g_return_if_fail(value != NULL); - - if (purple_value_get_type(value) == PURPLE_TYPE_BOXED) - { - g_free(value->u.specific_type); - } - else if (purple_value_get_type(value) == PURPLE_TYPE_STRING) - { - g_free(value->data.string_data); - } - - g_free(value); -} - -PurpleValue * -purple_value_dup(const PurpleValue *value) -{ - PurpleValue *new_value; - PurpleType type; - - g_return_val_if_fail(value != NULL, NULL); - - type = purple_value_get_type(value); - - if (type == PURPLE_TYPE_SUBTYPE) - { - new_value = purple_value_new(PURPLE_TYPE_SUBTYPE, - purple_value_get_subtype(value)); - } - else if (type == PURPLE_TYPE_BOXED) - { - new_value = purple_value_new(PURPLE_TYPE_BOXED, - purple_value_get_specific_type(value)); - } - else - new_value = purple_value_new(type); - - new_value->flags = value->flags; - - switch (type) - { - case PURPLE_TYPE_CHAR: - purple_value_set_char(new_value, purple_value_get_char(value)); - break; - - case PURPLE_TYPE_UCHAR: - purple_value_set_uchar(new_value, purple_value_get_uchar(value)); - break; - - case PURPLE_TYPE_BOOLEAN: - purple_value_set_boolean(new_value, purple_value_get_boolean(value)); - break; - - case PURPLE_TYPE_SHORT: - purple_value_set_short(new_value, purple_value_get_short(value)); - break; - - case PURPLE_TYPE_USHORT: - purple_value_set_ushort(new_value, purple_value_get_ushort(value)); - break; - - case PURPLE_TYPE_INT: - purple_value_set_int(new_value, purple_value_get_int(value)); - break; - - case PURPLE_TYPE_UINT: - purple_value_set_uint(new_value, purple_value_get_uint(value)); - break; - - case PURPLE_TYPE_LONG: - purple_value_set_long(new_value, purple_value_get_long(value)); - break; - - case PURPLE_TYPE_ULONG: - purple_value_set_ulong(new_value, purple_value_get_ulong(value)); - break; - - case PURPLE_TYPE_INT64: - purple_value_set_int64(new_value, purple_value_get_int64(value)); - break; - - case PURPLE_TYPE_UINT64: - purple_value_set_uint64(new_value, purple_value_get_uint64(value)); - break; - - case PURPLE_TYPE_STRING: - purple_value_set_string(new_value, purple_value_get_string(value)); - break; - - case PURPLE_TYPE_OBJECT: - purple_value_set_object(new_value, purple_value_get_object(value)); - break; - - case PURPLE_TYPE_POINTER: - purple_value_set_pointer(new_value, purple_value_get_pointer(value)); - break; - - case PURPLE_TYPE_ENUM: - purple_value_set_enum(new_value, purple_value_get_enum(value)); - break; - - case PURPLE_TYPE_BOXED: - purple_value_set_boxed(new_value, purple_value_get_boxed(value)); - break; - - default: - break; - } - - return new_value; -} - -PurpleType -purple_value_get_type(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, PURPLE_TYPE_UNKNOWN); - - return value->type; -} - -unsigned int -purple_value_get_subtype(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, 0); - g_return_val_if_fail(purple_value_get_type(value) == PURPLE_TYPE_SUBTYPE, 0); - - return value->u.subtype; -} - -const char * -purple_value_get_specific_type(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, NULL); - g_return_val_if_fail(purple_value_get_type(value) == PURPLE_TYPE_BOXED, NULL); - - return value->u.specific_type; -} - -gboolean -purple_value_is_outgoing(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, FALSE); - - return (value->flags & OUTGOING_FLAG); -} - -void -purple_value_set_char(PurpleValue *value, char data) -{ - g_return_if_fail(value != NULL); - - value->data.char_data = data; -} - -void -purple_value_set_uchar(PurpleValue *value, unsigned char data) -{ - g_return_if_fail(value != NULL); - - value->data.uchar_data = data; -} - -void -purple_value_set_boolean(PurpleValue *value, gboolean data) -{ - g_return_if_fail(value != NULL); - - value->data.boolean_data = data; -} - -void -purple_value_set_short(PurpleValue *value, short data) -{ - g_return_if_fail(value != NULL); - - value->data.short_data = data; -} - -void -purple_value_set_ushort(PurpleValue *value, unsigned short data) -{ - g_return_if_fail(value != NULL); - - value->data.ushort_data = data; -} - -void -purple_value_set_int(PurpleValue *value, int data) -{ - g_return_if_fail(value != NULL); - - value->data.int_data = data; -} - -void -purple_value_set_uint(PurpleValue *value, unsigned int data) -{ - g_return_if_fail(value != NULL); - - value->data.int_data = data; -} - -void -purple_value_set_long(PurpleValue *value, long data) -{ - g_return_if_fail(value != NULL); - - value->data.long_data = data; -} - -void -purple_value_set_ulong(PurpleValue *value, unsigned long data) -{ - g_return_if_fail(value != NULL); - - value->data.long_data = data; -} - -void -purple_value_set_int64(PurpleValue *value, gint64 data) -{ - g_return_if_fail(value != NULL); - - value->data.int64_data = data; -} - -void -purple_value_set_uint64(PurpleValue *value, guint64 data) -{ - g_return_if_fail(value != NULL); - - value->data.uint64_data = data; -} - -void -purple_value_set_string(PurpleValue *value, const char *data) -{ - g_return_if_fail(value != NULL); - g_return_if_fail(data == NULL || g_utf8_validate(data, -1, NULL)); - - g_free(value->data.string_data); - value->data.string_data = g_strdup(data); -} - -void -purple_value_set_object(PurpleValue *value, void *data) -{ - g_return_if_fail(value != NULL); - - value->data.object_data = data; -} - -void -purple_value_set_pointer(PurpleValue *value, void *data) -{ - g_return_if_fail(value != NULL); - - value->data.pointer_data = data; -} - -void -purple_value_set_enum(PurpleValue *value, int data) -{ - g_return_if_fail(value != NULL); - - value->data.enum_data = data; -} - -void -purple_value_set_boxed(PurpleValue *value, void *data) -{ - g_return_if_fail(value != NULL); - - value->data.boxed_data = data; -} - -char -purple_value_get_char(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, 0); - - return value->data.char_data; -} - -unsigned char -purple_value_get_uchar(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, 0); - - return value->data.uchar_data; -} - -gboolean -purple_value_get_boolean(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, FALSE); - - return value->data.boolean_data; -} - -short -purple_value_get_short(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, 0); - - return value->data.short_data; -} - -unsigned short -purple_value_get_ushort(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, 0); - - return value->data.ushort_data; -} - -int -purple_value_get_int(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, 0); - - return value->data.int_data; -} - -unsigned int -purple_value_get_uint(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, 0); - - return value->data.int_data; -} - -long -purple_value_get_long(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, 0); - - return value->data.long_data; -} - -unsigned long -purple_value_get_ulong(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, 0); - - return value->data.long_data; -} - -gint64 -purple_value_get_int64(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, 0); - - return value->data.int64_data; -} - -guint64 -purple_value_get_uint64(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, 0); - - return value->data.uint64_data; -} - -const char * -purple_value_get_string(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, NULL); - - return value->data.string_data; -} - -void * -purple_value_get_object(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, NULL); - - return value->data.object_data; -} - -void * -purple_value_get_pointer(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, NULL); - - return value->data.pointer_data; -} - -int -purple_value_get_enum(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, -1); - - return value->data.enum_data; -} - -void * -purple_value_get_boxed(const PurpleValue *value) -{ - g_return_val_if_fail(value != NULL, NULL); - - return value->data.boxed_data; -} - diff --git a/libpurple/value.h b/libpurple/value.h deleted file mode 100644 index 5cd26afbc9..0000000000 --- a/libpurple/value.h +++ /dev/null @@ -1,467 +0,0 @@ -/** - * @file value.h Value wrapper API - * @ingroup core - */ - -/* purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _PURPLE_VALUE_H_ -#define _PURPLE_VALUE_H_ - -#include <glib.h> - -/** - * Specific value types. - */ -typedef enum -{ - PURPLE_TYPE_UNKNOWN = 0, /**< Unknown type. */ - PURPLE_TYPE_SUBTYPE, /**< Subtype. */ - PURPLE_TYPE_CHAR, /**< Character. */ - PURPLE_TYPE_UCHAR, /**< Unsigned character. */ - PURPLE_TYPE_BOOLEAN, /**< Boolean. */ - PURPLE_TYPE_SHORT, /**< Short integer. */ - PURPLE_TYPE_USHORT, /**< Unsigned short integer. */ - PURPLE_TYPE_INT, /**< Integer. */ - PURPLE_TYPE_UINT, /**< Unsigned integer. */ - PURPLE_TYPE_LONG, /**< Long integer. */ - PURPLE_TYPE_ULONG, /**< Unsigned long integer. */ - PURPLE_TYPE_INT64, /**< 64-bit integer. */ - PURPLE_TYPE_UINT64, /**< 64-bit unsigned integer. */ - PURPLE_TYPE_STRING, /**< String. */ - PURPLE_TYPE_OBJECT, /**< Object pointer. */ - PURPLE_TYPE_POINTER, /**< Generic pointer. */ - PURPLE_TYPE_ENUM, /**< Enum. */ - PURPLE_TYPE_BOXED /**< Boxed pointer with specific type. */ - -} PurpleType; - - -/** - * Purple-specific subtype values. - */ -typedef enum -{ - PURPLE_SUBTYPE_UNKNOWN = 0, - PURPLE_SUBTYPE_ACCOUNT, - PURPLE_SUBTYPE_BLIST, - PURPLE_SUBTYPE_BLIST_BUDDY, - PURPLE_SUBTYPE_BLIST_GROUP, - PURPLE_SUBTYPE_BLIST_CHAT, - PURPLE_SUBTYPE_BUDDY_ICON, - PURPLE_SUBTYPE_CONNECTION, - PURPLE_SUBTYPE_CONVERSATION, - PURPLE_SUBTYPE_PLUGIN, - PURPLE_SUBTYPE_BLIST_NODE, - PURPLE_SUBTYPE_CIPHER, - PURPLE_SUBTYPE_STATUS, - PURPLE_SUBTYPE_LOG, - PURPLE_SUBTYPE_XFER, - PURPLE_SUBTYPE_SAVEDSTATUS, - PURPLE_SUBTYPE_XMLNODE, - PURPLE_SUBTYPE_USERINFO, - PURPLE_SUBTYPE_STORED_IMAGE, - PURPLE_SUBTYPE_CERTIFICATEPOOL, - PURPLE_SUBTYPE_CHATBUDDY -} PurpleSubType; - -/** - * A wrapper for a type, subtype, and specific type of value. - */ -typedef struct _PurpleValue PurpleValue; - -G_BEGIN_DECLS - -/** - * Creates a new PurpleValue. - * - * This function takes a type and, depending on that type, a sub-type - * or specific type. - * - * If @a type is PURPLE_TYPE_BOXED, the next parameter must be a - * string representing the specific type. - * - * If @a type is PURPLE_TYPE_SUBTYPE, the next parameter must be a - * integer or enum representing the sub-type. - * - * If the subtype or specific type is not set when required, random - * errors may occur. You have been warned. - * - * @param type The type. - * - * @return The new value. - */ -PurpleValue *purple_value_new(PurpleType type, ...); - -/** - * Creates a new outgoing PurpleValue. If a value is an "outgoing" value - * it means the value can be modified by plugins and scripts. - * - * This function takes a type and, depending on that type, a sub-type - * or specific type. - * - * If @a type is PURPLE_TYPE_BOXED, the next parameter must be a - * string representing the specific type. - * - * If @a type is PURPLE_TYPE_SUBTYPE, the next parameter must be a - * integer or enum representing the sub-type. - * - * If the sub-type or specific type is not set when required, random - * errors may occur. You have been warned. - * - * @param type The type. - * - * @return The new value. - */ -PurpleValue *purple_value_new_outgoing(PurpleType type, ...); - -/** - * Destroys a PurpleValue. - * - * @param value The value to destroy. - */ -void purple_value_destroy(PurpleValue *value); - -/** - * Duplicated a PurpleValue. - * - * @param value The value to duplicate. - * - * @return The duplicate value. - */ -PurpleValue *purple_value_dup(const PurpleValue *value); - -/** - * Returns a value's type. - * - * @param value The value whose type you want. - * - * @return The value's type. - */ -PurpleType purple_value_get_type(const PurpleValue *value); - -/** - * Returns a value's subtype. - * - * If the value's type is not PURPLE_TYPE_SUBTYPE, this will return 0. - * Subtypes should never have a subtype of 0. - * - * @param value The value whose subtype you want. - * - * @return The value's subtype, or 0 if @a type is not PURPLE_TYPE_SUBTYPE. - */ -unsigned int purple_value_get_subtype(const PurpleValue *value); - -/** - * Returns a value's specific type. - * - * If the value's type is not PURPLE_TYPE_BOXED, this will return @c NULL. - * - * @param value The value whose specific type you want. - * - * @return The value's specific type, or @a NULL if not PURPLE_TYPE_BOXED. - */ -const char *purple_value_get_specific_type(const PurpleValue *value); - -/** - * Returns whether or not the value is an outgoing value. - * - * @param value The value. - * - * @return TRUE if the value is outgoing, or FALSE otherwise. - */ -gboolean purple_value_is_outgoing(const PurpleValue *value); - -/** - * Sets the value's character data. - * - * @param value The value. - * @param data The character data. - */ -void purple_value_set_char(PurpleValue *value, char data); - -/** - * Sets the value's unsigned character data. - * - * @param value The value. - * @param data The unsigned character data. - */ -void purple_value_set_uchar(PurpleValue *value, unsigned char data); - -/** - * Sets the value's boolean data. - * - * @param value The value. - * @param data The boolean data. - */ -void purple_value_set_boolean(PurpleValue *value, gboolean data); - -/** - * Sets the value's short integer data. - * - * @param value The value. - * @param data The short integer data. - */ -void purple_value_set_short(PurpleValue *value, short data); - -/** - * Sets the value's unsigned short integer data. - * - * @param value The value. - * @param data The unsigned short integer data. - */ -void purple_value_set_ushort(PurpleValue *value, unsigned short data); - -/** - * Sets the value's integer data. - * - * @param value The value. - * @param data The integer data. - */ -void purple_value_set_int(PurpleValue *value, int data); - -/** - * Sets the value's unsigned integer data. - * - * @param value The value. - * @param data The unsigned integer data. - */ -void purple_value_set_uint(PurpleValue *value, unsigned int data); - -/** - * Sets the value's long integer data. - * - * @param value The value. - * @param data The long integer data. - */ -void purple_value_set_long(PurpleValue *value, long data); - -/** - * Sets the value's unsigned long integer data. - * - * @param value The value. - * @param data The unsigned long integer data. - */ -void purple_value_set_ulong(PurpleValue *value, unsigned long data); - -/** - * Sets the value's 64-bit integer data. - * - * @param value The value. - * @param data The 64-bit integer data. - */ -void purple_value_set_int64(PurpleValue *value, gint64 data); - -/** - * Sets the value's unsigned 64-bit integer data. - * - * @param value The value. - * @param data The unsigned 64-bit integer data. - */ -void purple_value_set_uint64(PurpleValue *value, guint64 data); - -/** - * Sets the value's string data. - * - * @param value The value. - * @param data The string data. - */ -void purple_value_set_string(PurpleValue *value, const char *data); - -/** - * Sets the value's object data. - * - * @param value The value. - * @param data The object data. - */ -void purple_value_set_object(PurpleValue *value, void *data); - -/** - * Sets the value's pointer data. - * - * @param value The value. - * @param data The pointer data. - */ -void purple_value_set_pointer(PurpleValue *value, void *data); - -/** - * Sets the value's enum data. - * - * @param value The value. - * @param data The enum data. - */ -void purple_value_set_enum(PurpleValue *value, int data); - -/** - * Sets the value's boxed data. - * - * @param value The value. - * @param data The boxed data. - */ -void purple_value_set_boxed(PurpleValue *value, void *data); - -/** - * Returns the value's character data. - * - * @param value The value. - * - * @return The character data. - */ -char purple_value_get_char(const PurpleValue *value); - -/** - * Returns the value's unsigned character data. - * - * @param value The value. - * - * @return The unsigned character data. - */ -unsigned char purple_value_get_uchar(const PurpleValue *value); - -/** - * Returns the value's boolean data. - * - * @param value The value. - * - * @return The boolean data. - */ -gboolean purple_value_get_boolean(const PurpleValue *value); - -/** - * Returns the value's short integer data. - * - * @param value The value. - * - * @return The short integer data. - */ -short purple_value_get_short(const PurpleValue *value); - -/** - * Returns the value's unsigned short integer data. - * - * @param value The value. - * - * @return The unsigned short integer data. - */ -unsigned short purple_value_get_ushort(const PurpleValue *value); - -/** - * Returns the value's integer data. - * - * @param value The value. - * - * @return The integer data. - */ -int purple_value_get_int(const PurpleValue *value); - -/** - * Returns the value's unsigned integer data. - * - * @param value The value. - * - * @return The unsigned integer data. - */ -unsigned int purple_value_get_uint(const PurpleValue *value); - -/** - * Returns the value's long integer data. - * - * @param value The value. - * - * @return The long integer data. - */ -long purple_value_get_long(const PurpleValue *value); - -/** - * Returns the value's unsigned long integer data. - * - * @param value The value. - * - * @return The unsigned long integer data. - */ -unsigned long purple_value_get_ulong(const PurpleValue *value); - -/** - * Returns the value's 64-bit integer data. - * - * @param value The value. - * - * @return The 64-bit integer data. - */ -gint64 purple_value_get_int64(const PurpleValue *value); - -/** - * Returns the value's unsigned 64-bit integer data. - * - * @param value The value. - * - * @return The unsigned 64-bit integer data. - */ -guint64 purple_value_get_uint64(const PurpleValue *value); - -/** - * Returns the value's string data. - * - * @param value The value. - * - * @return The string data. - */ -const char *purple_value_get_string(const PurpleValue *value); - -/** - * Returns the value's object data. - * - * @param value The value. - * - * @return The object data. - */ -void *purple_value_get_object(const PurpleValue *value); - -/** - * Returns the value's pointer data. - * - * @param value The value. - * - * @return The pointer data. - */ -void *purple_value_get_pointer(const PurpleValue *value); - -/** - * Returns the value's enum data. - * - * @param value The value. - * - * @return The enum data. - */ -int purple_value_get_enum(const PurpleValue *value); - -/** - * Returns the value's boxed data. - * - * @param value The value. - * - * @return The boxed data. - */ -void *purple_value_get_boxed(const PurpleValue *value); - -G_END_DECLS - -#endif /* _PURPLE_VALUE_H_ */ diff --git a/libpurple/xmlnode.c b/libpurple/xmlnode.c index 81285a514f..3c5cbbcae2 100644 --- a/libpurple/xmlnode.c +++ b/libpurple/xmlnode.c @@ -967,3 +967,17 @@ xmlnode_get_next_twin(xmlnode *node) return NULL; } + +GType +xmlnode_get_type(void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static("xmlnode", + (GBoxedCopyFunc)xmlnode_copy, + (GBoxedFreeFunc)xmlnode_free); + } + + return type; +} diff --git a/libpurple/xmlnode.h b/libpurple/xmlnode.h index 29a768ba20..b4011a3298 100644 --- a/libpurple/xmlnode.h +++ b/libpurple/xmlnode.h @@ -27,6 +27,9 @@ #define _PURPLE_XMLNODE_H_ #include <glib.h> +#include <glib-object.h> + +#define PURPLE_TYPE_XMLNODE (xmlnode_get_type()) /** * The valid types for an xmlnode @@ -60,6 +63,11 @@ struct _xmlnode G_BEGIN_DECLS /** + * Returns the GType for the xmlnode boxed structure. + */ +GType xmlnode_get_type(void); + +/** * Creates a new xmlnode. * * @param name The name of the node. diff --git a/pidgin/gtkaccount.c b/pidgin/gtkaccount.c index 574cc1e751..041baa1a56 100644 --- a/pidgin/gtkaccount.c +++ b/pidgin/gtkaccount.c @@ -165,6 +165,10 @@ static void add_account_to_liststore(PurpleAccount *account, gpointer user_data) static void set_account(GtkListStore *store, GtkTreeIter *iter, PurpleAccount *account, GdkPixbuf *global_buddyicon); +/* privacy UI ops */ +void pidgin_permit_added_removed(PurpleAccount *account, const char *name); +void pidgin_deny_added_removed(PurpleAccount *account, const char *name); + /************************************************************************** * Add/Modify Account dialog **************************************************************************/ @@ -859,9 +863,9 @@ add_user_options(AccountPrefsDialog *dialog, GtkWidget *parent) gpointer data = NULL; size_t len = 0; - if (purple_account_get_alias(dialog->account)) + if (purple_account_get_private_alias(dialog->account)) gtk_entry_set_text(GTK_ENTRY(dialog->alias_entry), - purple_account_get_alias(dialog->account)); + purple_account_get_private_alias(dialog->account)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->new_mail_check), purple_account_get_check_mail(dialog->account)); @@ -1401,7 +1405,7 @@ account_register_cb(PurpleAccount *account, gboolean succeeded, void *user_data) if (succeeded) { const PurpleSavedStatus *saved_status = purple_savedstatus_get_current(); - purple_signal_emit(pidgin_account_get_handle(), "account-modified", account); + purple_signal_emit(pidgin_accounts_get_handle(), "account-modified", account); if (saved_status != NULL && purple_account_get_remember_password(account)) { purple_savedstatus_activate_for_account(saved_status, account); @@ -1485,9 +1489,9 @@ ok_account_prefs_cb(GtkWidget *w, AccountPrefsDialog *dialog) value = gtk_entry_get_text(GTK_ENTRY(dialog->alias_entry)); if (*value != '\0') - purple_account_set_alias(account, value); + purple_account_set_private_alias(account, value); else - purple_account_set_alias(account, NULL); + purple_account_set_private_alias(account, NULL); /* Buddy Icon */ if (dialog->prpl_info != NULL && dialog->prpl_info->icon_spec.format != NULL) @@ -1668,7 +1672,7 @@ ok_account_prefs_cb(GtkWidget *w, AccountPrefsDialog *dialog) if (new_acct) purple_accounts_add(account); else - purple_signal_emit(pidgin_account_get_handle(), "account-modified", account); + purple_signal_emit(pidgin_accounts_get_handle(), "account-modified", account); /* If this is a new account, then sign on! */ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->register_button))) { @@ -2556,7 +2560,7 @@ pidgin_accounts_window_show(void) /* Close button */ pidgin_dialog_add_button(GTK_DIALOG(win), GTK_STOCK_CLOSE, G_CALLBACK(close_accounts_cb), dialog); - purple_signal_connect(pidgin_account_get_handle(), "account-modified", + purple_signal_connect(pidgin_accounts_get_handle(), "account-modified", accounts_window, PURPLE_CALLBACK(account_modified_cb), accounts_window); purple_prefs_connect_callback(accounts_window, @@ -2902,10 +2906,11 @@ static PurpleAccountUiOps ui_ops = pidgin_accounts_request_add, pidgin_accounts_request_authorization, pidgin_accounts_request_close, - NULL, - NULL, - NULL, - NULL + pidgin_permit_added_removed, + pidgin_permit_added_removed, + pidgin_deny_added_removed, + pidgin_deny_added_removed, + NULL, NULL, NULL, NULL }; PurpleAccountUiOps * @@ -2915,14 +2920,14 @@ pidgin_accounts_get_ui_ops(void) } void * -pidgin_account_get_handle(void) { +pidgin_accounts_get_handle(void) { static int handle; return &handle; } void -pidgin_account_init(void) +pidgin_accounts_init(void) { char *default_avatar = NULL; purple_prefs_add_none(PIDGIN_PREFS_ROOT "/accounts"); @@ -2942,29 +2947,28 @@ pidgin_account_init(void) purple_prefs_add_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon", default_avatar); g_free(default_avatar); - purple_signal_register(pidgin_account_get_handle(), "account-modified", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT)); + purple_signal_register(pidgin_accounts_get_handle(), "account-modified", + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_ACCOUNT); /* Setup some purple signal handlers. */ purple_signal_connect(purple_connections_get_handle(), "signed-on", - pidgin_account_get_handle(), + pidgin_accounts_get_handle(), PURPLE_CALLBACK(signed_on_off_cb), NULL); purple_signal_connect(purple_connections_get_handle(), "signed-off", - pidgin_account_get_handle(), + pidgin_accounts_get_handle(), PURPLE_CALLBACK(signed_on_off_cb), NULL); purple_signal_connect(purple_accounts_get_handle(), "account-added", - pidgin_account_get_handle(), + pidgin_accounts_get_handle(), PURPLE_CALLBACK(add_account_to_liststore), NULL); purple_signal_connect(purple_accounts_get_handle(), "account-removed", - pidgin_account_get_handle(), + pidgin_accounts_get_handle(), PURPLE_CALLBACK(account_removed_cb), NULL); purple_signal_connect(purple_accounts_get_handle(), "account-disabled", - pidgin_account_get_handle(), + pidgin_accounts_get_handle(), PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(FALSE)); purple_signal_connect(purple_accounts_get_handle(), "account-enabled", - pidgin_account_get_handle(), + pidgin_accounts_get_handle(), PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(TRUE)); account_pref_wins = @@ -2972,7 +2976,7 @@ pidgin_account_init(void) } void -pidgin_account_uninit(void) +pidgin_accounts_uninit(void) { /* * TODO: Need to free all the dialogs in here. Could probably create @@ -2981,7 +2985,7 @@ pidgin_account_uninit(void) */ g_hash_table_destroy(account_pref_wins); - purple_signals_disconnect_by_handle(pidgin_account_get_handle()); - purple_signals_unregister_by_instance(pidgin_account_get_handle()); + purple_signals_disconnect_by_handle(pidgin_accounts_get_handle()); + purple_signals_unregister_by_instance(pidgin_accounts_get_handle()); } diff --git a/pidgin/gtkaccount.h b/pidgin/gtkaccount.h index 8410d8817d..14df316e65 100644 --- a/pidgin/gtkaccount.h +++ b/pidgin/gtkaccount.h @@ -27,7 +27,7 @@ #ifndef _PIDGINACCOUNT_H_ #define _PIDGINACCOUNT_H_ -#include "account.h" +#include "accounts.h" typedef enum { @@ -70,17 +70,17 @@ PurpleAccountUiOps *pidgin_accounts_get_ui_ops(void); * * @return The handle to the GTK+ account system */ -void *pidgin_account_get_handle(void); +void *pidgin_accounts_get_handle(void); /** * Initializes the GTK+ account system */ -void pidgin_account_init(void); +void pidgin_accounts_init(void); /** * Uninitializes the GTK+ account system */ -void pidgin_account_uninit(void); +void pidgin_accounts_uninit(void); G_END_DECLS diff --git a/pidgin/gtkblist.c b/pidgin/gtkblist.c index 57bf8327bc..bd41d25103 100644 --- a/pidgin/gtkblist.c +++ b/pidgin/gtkblist.c @@ -203,7 +203,7 @@ static gboolean gtk_blist_visibility_cb(GtkWidget *w, GdkEventVisibility *event, old_state != GDK_VISIBILITY_FULLY_OBSCURED) { /* no longer fully obscured */ - pidgin_blist_refresh_timer(purple_get_blist()); + pidgin_blist_refresh_timer(purple_blist_get_buddy_list()); } /* continue to handle event normally */ @@ -217,7 +217,7 @@ static gboolean gtk_blist_window_state_cb(GtkWidget *w, GdkEventWindowState *eve purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_visible", FALSE); else { purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_visible", TRUE); - pidgin_blist_refresh_timer(purple_get_blist()); + pidgin_blist_refresh_timer(purple_blist_get_buddy_list()); } } @@ -231,7 +231,7 @@ static gboolean gtk_blist_window_state_cb(GtkWidget *w, GdkEventWindowState *eve /* Refresh gtkblist if un-iconifying */ if (event->changed_mask & GDK_WINDOW_STATE_ICONIFIED){ if (!(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED)) - pidgin_blist_refresh_timer(purple_get_blist()); + pidgin_blist_refresh_timer(purple_blist_get_buddy_list()); } return FALSE; @@ -376,9 +376,8 @@ find_conversation_with_buddy(PurpleBuddy *buddy) PidginBlistNode *ui = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy)); if (ui) return ui->conv.conv; - return purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - purple_buddy_get_name(buddy), - purple_buddy_get_account(buddy)); + return PURPLE_CONVERSATION(purple_conversations_find_im_with_account( + purple_buddy_get_name(buddy), purple_buddy_get_account(buddy))); } static void gtk_blist_join_chat(PurpleChat *chat) @@ -405,8 +404,8 @@ static void gtk_blist_join_chat(PurpleChat *chat) else name = purple_chat_get_name(chat); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, name, - account); + conv = PURPLE_CONVERSATION(purple_conversations_find_chat_with_account(name, + account)); if (conv != NULL) { pidgin_conv_attach_to_conversation(conv); @@ -444,22 +443,16 @@ static void gtk_blist_renderer_editing_started_cb(GtkCellRenderer *renderer, gtk_tree_path_free (path); gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); - switch (purple_blist_node_get_type(node)) { - case PURPLE_BLIST_CONTACT_NODE: + if (PURPLE_IS_CONTACT(node)) text = purple_contact_get_alias(PURPLE_CONTACT(node)); - break; - case PURPLE_BLIST_BUDDY_NODE: + else if (PURPLE_IS_BUDDY(node)) text = purple_buddy_get_alias(PURPLE_BUDDY(node)); - break; - case PURPLE_BLIST_GROUP_NODE: + else if (PURPLE_IS_GROUP(node)) text = purple_group_get_name(PURPLE_GROUP(node)); - break; - case PURPLE_BLIST_CHAT_NODE: + else if (PURPLE_IS_CHAT(node)) text = purple_chat_get_name(PURPLE_CHAT(node)); - break; - default: + else g_return_if_reached(); - } if (GTK_IS_ENTRY (editable)) { GtkEntry *entry = GTK_ENTRY (editable); @@ -482,17 +475,12 @@ gtk_blist_do_personize(GList *merges) for (tmp = merges; tmp; tmp = tmp->next) { PurpleBlistNode *node = tmp->data; PurpleBlistNode *b; - PurpleBlistNodeType type; int i = 0; - type = purple_blist_node_get_type(node); - - if (type == PURPLE_BLIST_BUDDY_NODE) { + if (PURPLE_IS_BUDDY(node)) node = purple_blist_node_get_parent(node); - type = purple_blist_node_get_type(node); - } - if (type != PURPLE_BLIST_CONTACT_NODE) + if (!PURPLE_IS_CONTACT(node)) continue; for (b = purple_blist_node_get_first_child(node); @@ -514,13 +502,13 @@ gtk_blist_do_personize(GList *merges) /* Merge all those buddies into this contact */ for (tmp = merges; tmp; tmp = tmp->next) { PurpleBlistNode *node = tmp->data; - if (purple_blist_node_get_type(node) == PURPLE_BLIST_BUDDY_NODE) + if (PURPLE_IS_BUDDY(node)) node = purple_blist_node_get_parent(node); if (node == contact) continue; - purple_blist_merge_contact((PurpleContact *)node, contact); + purple_contact_merge((PurpleContact *)node, contact); } /* And show the expanded contact, so the people know what's going on */ @@ -541,7 +529,7 @@ gtk_blist_auto_personize(PurpleBlistNode *group, const char *alias) contact != NULL; contact = purple_blist_node_get_sibling_next(contact)) { char *node_alias; - if (purple_blist_node_get_type(contact) != PURPLE_BLIST_CONTACT_NODE) + if (!PURPLE_IS_CONTACT(contact)) continue; node_alias = g_utf8_casefold(purple_contact_get_alias((PurpleContact *)contact), -1); @@ -557,7 +545,7 @@ gtk_blist_auto_personize(PurpleBlistNode *group, const char *alias) buddy; buddy = purple_blist_node_get_sibling_next(buddy)) { - if (purple_blist_node_get_type(buddy) != PURPLE_BLIST_BUDDY_NODE) + if (!PURPLE_IS_BUDDY(buddy)) continue; node_alias = g_utf8_casefold(purple_buddy_get_alias(PURPLE_BUDDY(buddy)), -1); @@ -590,6 +578,7 @@ static void gtk_blist_renderer_edited_cb(GtkCellRendererText *text_rend, char *a GtkTreePath *path; PurpleBlistNode *node; PurpleGroup *dest; + gchar *alias; editing_blist = FALSE; path = gtk_tree_path_new_from_string (arg1); @@ -599,56 +588,46 @@ static void gtk_blist_renderer_edited_cb(GtkCellRendererText *text_rend, char *a gtk_tree_view_set_enable_search (GTK_TREE_VIEW(gtkblist->treeview), TRUE); g_object_set(G_OBJECT(gtkblist->text_rend), "editable", FALSE, NULL); - switch (purple_blist_node_get_type(node)) - { - case PURPLE_BLIST_CONTACT_NODE: - { - PurpleContact *contact = PURPLE_CONTACT(node); - struct _pidgin_blist_node *gtknode = - (struct _pidgin_blist_node *)purple_blist_node_get_ui_data(node); + if (PURPLE_IS_CONTACT(node)) { + PurpleContact *contact = PURPLE_CONTACT(node); + struct _pidgin_blist_node *gtknode = + (struct _pidgin_blist_node *)purple_blist_node_get_ui_data(node); - /* - * XXX Using purple_contact_get_alias here breaks because we - * specifically want to check the contact alias only (i.e. not - * the priority buddy, which purple_contact_get_alias does). - * Adding yet another get_alias is evil, so figure this out - * later :-P - */ - if (contact->alias || gtknode->contact_expanded) { - purple_blist_alias_contact(contact, arg2); - gtk_blist_auto_personize(purple_blist_node_get_parent(node), arg2); - } else { - PurpleBuddy *buddy = purple_contact_get_priority_buddy(contact); - purple_blist_alias_buddy(buddy, arg2); - serv_alias_buddy(buddy); - gtk_blist_auto_personize(purple_blist_node_get_parent(node), arg2); - } - } - break; - - case PURPLE_BLIST_BUDDY_NODE: - { - PurpleGroup *group = purple_buddy_get_group(PURPLE_BUDDY(node)); + /* + * Using purple_contact_get_alias here breaks because we + * specifically want to check the contact alias only (i.e. not + * the priority buddy, which purple_contact_get_alias does). + * The "alias" GObject property gives us just the alias. + */ + g_object_get(contact, "alias", &alias, NULL); - purple_blist_alias_buddy(PURPLE_BUDDY(node), arg2); - serv_alias_buddy(PURPLE_BUDDY(node)); - gtk_blist_auto_personize(PURPLE_BLIST_NODE(group), arg2); - } - break; - case PURPLE_BLIST_GROUP_NODE: - dest = purple_find_group(arg2); - if (dest != NULL && purple_utf8_strcasecmp(arg2, purple_group_get_name(PURPLE_GROUP(node)))) { - pidgin_dialogs_merge_groups(PURPLE_GROUP(node), arg2); - } else { - purple_blist_rename_group(PURPLE_GROUP(node), arg2); - } - break; - case PURPLE_BLIST_CHAT_NODE: - purple_blist_alias_chat(PURPLE_CHAT(node), arg2); - break; - default: - break; + if (alias || gtknode->contact_expanded) { + purple_contact_set_alias(contact, arg2); + gtk_blist_auto_personize(purple_blist_node_get_parent(node), arg2); + } else { + PurpleBuddy *buddy = purple_contact_get_priority_buddy(contact); + purple_buddy_set_local_alias(buddy, arg2); + serv_alias_buddy(buddy); + gtk_blist_auto_personize(purple_blist_node_get_parent(node), arg2); + } + } else if (PURPLE_IS_BUDDY(node)) { + PurpleGroup *group = purple_buddy_get_group(PURPLE_BUDDY(node)); + + purple_buddy_set_local_alias(PURPLE_BUDDY(node), arg2); + serv_alias_buddy(PURPLE_BUDDY(node)); + gtk_blist_auto_personize(PURPLE_BLIST_NODE(group), arg2); + } else if (PURPLE_IS_GROUP(node)) { + dest = purple_blist_find_group(arg2); + if (dest != NULL && purple_utf8_strcasecmp(arg2, purple_group_get_name(PURPLE_GROUP(node)))) { + pidgin_dialogs_merge_groups(PURPLE_GROUP(node), arg2); + } else { + purple_group_set_name(PURPLE_GROUP(node), arg2); + } + } else if (PURPLE_IS_CHAT(node)) { + purple_chat_set_alias(PURPLE_CHAT(node), arg2); } + + g_free(alias); pidgin_blist_refresh(list); } @@ -762,12 +741,12 @@ static void gtk_blist_menu_showlog_cb(GtkWidget *w, PurpleBlistNode *node) pidgin_set_cursor(gtkblist->window, GDK_WATCH); - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (PURPLE_IS_BUDDY(node)) { PurpleBuddy *b = (PurpleBuddy*) node; type = PURPLE_LOG_IM; name = g_strdup(purple_buddy_get_name(b)); account = purple_buddy_get_account(b); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { PurpleChat *c = PURPLE_CHAT(node); PurplePluginProtocolInfo *prpl_info = NULL; type = PURPLE_LOG_CHAT; @@ -776,7 +755,7 @@ static void gtk_blist_menu_showlog_cb(GtkWidget *w, PurpleBlistNode *node) if (prpl_info && prpl_info->get_chat_name) { name = prpl_info->get_chat_name(purple_chat_get_components(c)); } - } else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + } else if (PURPLE_IS_CONTACT(node)) { pidgin_log_show_contact(PURPLE_CONTACT(node)); pidgin_clear_cursor(gtkblist->window); return; @@ -798,13 +777,13 @@ static void gtk_blist_menu_showlog_cb(GtkWidget *w, PurpleBlistNode *node) static void gtk_blist_menu_showoffline_cb(GtkWidget *w, PurpleBlistNode *node) { - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (PURPLE_IS_BUDDY(node)) { purple_blist_node_set_bool(node, "show_offline", !purple_blist_node_get_bool(node, "show_offline")); - pidgin_blist_update(purple_get_blist(), node); + pidgin_blist_update(purple_blist_get_buddy_list(), node); } - else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + else if (PURPLE_IS_CONTACT(node)) { PurpleBlistNode *bnode; gboolean setting = !purple_blist_node_get_bool(node, "show_offline"); @@ -815,9 +794,9 @@ static void gtk_blist_menu_showoffline_cb(GtkWidget *w, PurpleBlistNode *node) bnode = purple_blist_node_get_sibling_next(bnode)) { purple_blist_node_set_bool(bnode, "show_offline", setting); - pidgin_blist_update(purple_get_blist(), bnode); + pidgin_blist_update(purple_blist_get_buddy_list(), bnode); } - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { PurpleBlistNode *cnode, *bnode; gboolean setting = !purple_blist_node_get_bool(node, "show_offline"); @@ -832,7 +811,7 @@ static void gtk_blist_menu_showoffline_cb(GtkWidget *w, PurpleBlistNode *node) bnode = purple_blist_node_get_sibling_next(bnode)) { purple_blist_node_set_bool(bnode, "show_offline", setting); - pidgin_blist_update(purple_get_blist(), bnode); + pidgin_blist_update(purple_blist_get_buddy_list(), bnode); } } } @@ -960,7 +939,7 @@ pidgin_blist_update_privacy_cb(PurpleBuddy *buddy) struct _pidgin_blist_node *ui_data = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy)); if (ui_data == NULL || ui_data->row == NULL) return; - pidgin_blist_update_buddy(purple_get_blist(), PURPLE_BLIST_NODE(buddy), TRUE); + pidgin_blist_update_buddy(purple_blist_get_buddy_list(), PURPLE_BLIST_NODE(buddy), TRUE); } static gboolean @@ -1011,7 +990,7 @@ make_blist_request_dialog(PidginBlistRequestData *data, PurpleAccount *account, img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_QUESTION, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_HUGE)); - gtkblist = PIDGIN_BLIST(purple_get_blist()); + gtkblist = PIDGIN_BLIST(purple_blist_get_buddy_list()); blist_window = gtkblist ? GTK_WINDOW(gtkblist->window) : NULL; data->window = gtk_dialog_new(); @@ -1194,7 +1173,7 @@ static void gtk_blist_row_expanded_cb(GtkTreeView *tv, GtkTreeIter *iter, GtkTre gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), iter, NODE_COLUMN, &node, -1); - if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + if (PURPLE_IS_GROUP(node)) { char *title; title = pidgin_get_group_title(node, TRUE); @@ -1216,7 +1195,7 @@ static void gtk_blist_row_collapsed_cb(GtkTreeView *tv, GtkTreeIter *iter, GtkTr gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), iter, NODE_COLUMN, &node, -1); - if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + if (PURPLE_IS_GROUP(node)) { char *title; struct _pidgin_blist_node *gtknode; PurpleBlistNode *cnode; @@ -1232,7 +1211,7 @@ static void gtk_blist_row_collapsed_cb(GtkTreeView *tv, GtkTreeIter *iter, GtkTr purple_blist_node_set_bool(node, "collapsed", TRUE); for(cnode = purple_blist_node_get_first_child(node); cnode; cnode = purple_blist_node_get_sibling_next(cnode)) { - if (PURPLE_BLIST_NODE_IS_CONTACT(cnode)) { + if (PURPLE_IS_CONTACT(cnode)) { gtknode = purple_blist_node_get_ui_data(cnode); if (!gtknode->contact_expanded) continue; @@ -1241,7 +1220,7 @@ static void gtk_blist_row_collapsed_cb(GtkTreeView *tv, GtkTreeIter *iter, GtkTr } } pidgin_blist_tooltip_destroy(); - } else if(PURPLE_BLIST_NODE_IS_CONTACT(node)) { + } else if(PURPLE_IS_CONTACT(node)) { pidgin_blist_collapse_contact_cb(NULL, node); } } @@ -1253,18 +1232,18 @@ static void gtk_blist_row_activated_cb(GtkTreeView *tv, GtkTreePath *path, GtkTr gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); - if(PURPLE_BLIST_NODE_IS_CONTACT(node) || PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if(PURPLE_IS_CONTACT(node) || PURPLE_IS_BUDDY(node)) { PurpleBuddy *buddy; - if(PURPLE_BLIST_NODE_IS_CONTACT(node)) + if(PURPLE_IS_CONTACT(node)) buddy = purple_contact_get_priority_buddy((PurpleContact*)node); else buddy = (PurpleBuddy*)node; pidgin_dialogs_im_with_user(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy)); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { gtk_blist_join_chat((PurpleChat *)node); - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { /* if (gtk_tree_view_row_expanded(tv, path)) gtk_tree_view_collapse_row(tv, path); else @@ -1280,11 +1259,11 @@ static void pidgin_blist_add_chat_cb(void) if(gtk_tree_selection_get_selected(sel, NULL, &iter)){ gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (PURPLE_IS_BUDDY(node)) purple_blist_request_add_chat(NULL, purple_buddy_get_group(PURPLE_BUDDY(node)), NULL, NULL); - if (PURPLE_BLIST_NODE_IS_CONTACT(node) || PURPLE_BLIST_NODE_IS_CHAT(node)) + if (PURPLE_IS_CONTACT(node) || PURPLE_IS_CHAT(node)) purple_blist_request_add_chat(NULL, purple_contact_get_group(PURPLE_CONTACT(node)), NULL, NULL); - else if (PURPLE_BLIST_NODE_IS_GROUP(node)) + else if (PURPLE_IS_GROUP(node)) purple_blist_request_add_chat(NULL, (PurpleGroup*)node, NULL, NULL); } else { @@ -1300,13 +1279,13 @@ static void pidgin_blist_add_buddy_cb(void) if(gtk_tree_selection_get_selected(sel, NULL, &iter)){ gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (PURPLE_IS_BUDDY(node)) { PurpleGroup *group = purple_buddy_get_group(PURPLE_BUDDY(node)); purple_blist_request_add_buddy(NULL, NULL, purple_group_get_name(group), NULL); - } else if (PURPLE_BLIST_NODE_IS_CONTACT(node) || PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CONTACT(node) || PURPLE_IS_CHAT(node)) { PurpleGroup *group = purple_contact_get_group(PURPLE_CONTACT(node)); purple_blist_request_add_buddy(NULL, NULL, purple_group_get_name(group), NULL); - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { purple_blist_request_add_buddy(NULL, NULL, purple_group_get_name(PURPLE_GROUP(node)), NULL); } } @@ -1318,13 +1297,13 @@ static void pidgin_blist_add_buddy_cb(void) static void pidgin_blist_remove_cb (GtkWidget *w, PurpleBlistNode *node) { - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (PURPLE_IS_BUDDY(node)) { pidgin_dialogs_remove_buddy((PurpleBuddy*)node); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { pidgin_dialogs_remove_chat((PurpleChat*)node); - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { pidgin_dialogs_remove_group((PurpleGroup*)node); - } else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + } else if (PURPLE_IS_CONTACT(node)) { pidgin_dialogs_remove_contact((PurpleContact*)node); } } @@ -1356,7 +1335,7 @@ pidgin_blist_expand_contact_cb(GtkWidget *w, PurpleBlistNode *node) PurpleBlistNode *bnode; GtkTreePath *path; - if(!PURPLE_BLIST_NODE_IS_CONTACT(node)) + if(!PURPLE_IS_CONTACT(node)) return; gtknode = purple_blist_node_get_ui_data(node); @@ -1389,7 +1368,7 @@ pidgin_blist_collapse_contact_cb(GtkWidget *w, PurpleBlistNode *node) PurpleBlistNode *bnode; struct _pidgin_blist_node *gtknode; - if(!PURPLE_BLIST_NODE_IS_CONTACT(node)) + if(!PURPLE_IS_CONTACT(node)) return; gtknode = purple_blist_node_get_ui_data(node); @@ -1409,23 +1388,23 @@ toggle_privacy(GtkWidget *widget, PurpleBlistNode *node) gboolean permitted; const char *name; - if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (!PURPLE_IS_BUDDY(node)) return; buddy = (PurpleBuddy *)node; account = purple_buddy_get_account(buddy); name = purple_buddy_get_name(buddy); - permitted = purple_privacy_check(account, name); + permitted = purple_account_privacy_check(account, name); /* XXX: Perhaps ask whether to restore the previous lists where appropirate? */ if (permitted) - purple_privacy_deny(account, name, FALSE, FALSE); + purple_account_privacy_deny(account, name); else - purple_privacy_allow(account, name, FALSE, FALSE); + purple_account_privacy_allow(account, name); - pidgin_blist_update(purple_get_blist(), node); + pidgin_blist_update(purple_blist_get_buddy_list(), node); } void pidgin_append_blist_node_privacy_menu(GtkWidget *menu, PurpleBlistNode *node) @@ -1435,7 +1414,7 @@ void pidgin_append_blist_node_privacy_menu(GtkWidget *menu, PurpleBlistNode *nod gboolean permitted; account = purple_buddy_get_account(buddy); - permitted = purple_privacy_check(account, purple_buddy_get_name(buddy)); + permitted = purple_account_privacy_check(account, purple_buddy_get_name(buddy)); pidgin_new_item_from_stock(menu, permitted ? _("_Block") : _("Un_block"), permitted ? PIDGIN_STOCK_TOOLBAR_BLOCK : PIDGIN_STOCK_TOOLBAR_UNBLOCK, G_CALLBACK(toggle_privacy), @@ -1488,7 +1467,7 @@ pidgin_append_blist_node_move_to_menu(GtkWidget *menu, PurpleBlistNode *node) gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); for (group = purple_blist_get_root(); group; group = purple_blist_node_get_sibling_next(group)) { - if (!PURPLE_BLIST_NODE_IS_GROUP(group)) + if (!PURPLE_IS_GROUP(group)) continue; if (group == purple_blist_node_get_parent(node)) continue; @@ -1577,7 +1556,7 @@ pidgin_blist_make_buddy_menu(GtkWidget *menu, PurpleBuddy *buddy, gboolean sub) G_CALLBACK(gtk_blist_menu_showlog_cb), buddy, 0, 0, NULL); } - if (!PURPLE_BLIST_NODE_HAS_FLAG(node, PURPLE_BLIST_NODE_FLAG_NO_SAVE)) { + if (!purple_blist_node_is_transient(node)) { gboolean show_offline = purple_blist_node_get_bool(node, "show_offline"); pidgin_new_item_from_stock(menu, show_offline ? _("Hide When Offline") : _("Show When Offline"), NULL, G_CALLBACK(gtk_blist_menu_showoffline_cb), node, 0, 0, NULL); @@ -1628,9 +1607,9 @@ gtk_blist_key_press_cb(GtkWidget *tv, GdkEventKey *event, gpointer data) (event->keyval == 'o' || event->keyval == 'O')) { PurpleBuddy *buddy; - if(PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if(PURPLE_IS_CONTACT(node)) { buddy = purple_contact_get_priority_buddy((PurpleContact*)node); - } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { + } else if(PURPLE_IS_BUDDY(node)) { buddy = (PurpleBuddy*)node; } else { return FALSE; @@ -1669,11 +1648,11 @@ gtk_blist_key_press_cb(GtkWidget *tv, GdkEventKey *event, gpointer data) path = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); if (!gtk_tree_view_row_expanded(GTK_TREE_VIEW(tv), path)) { /* Expand the Group */ - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if (PURPLE_IS_CONTACT(node)) { pidgin_blist_expand_contact_cb(NULL, node); gtk_tree_path_free(path); return TRUE; - } else if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) { + } else if (!PURPLE_IS_BUDDY(node)) { gtk_tree_view_expand_row(GTK_TREE_VIEW(tv), path, FALSE); gtk_tree_path_free(path); return TRUE; @@ -1757,7 +1736,7 @@ create_group_menu (PurpleBlistNode *node, PurpleGroup *g) G_CALLBACK(pidgin_blist_remove_cb), node, 0, 0, NULL); pidgin_new_item_from_stock(menu, _("_Rename"), NULL, G_CALLBACK(gtk_blist_menu_alias_cb), node, 0, 0, NULL); - if (!(purple_blist_node_get_flags(node) & PURPLE_BLIST_NODE_FLAG_NO_SAVE)) { + if (!purple_blist_node_is_transient(node)) { gboolean show_offline = purple_blist_node_get_bool(node, "show_offline"); pidgin_new_item_from_stock(menu, show_offline ? _("Hide When Offline") : _("Show When Offline"), NULL, G_CALLBACK(gtk_blist_menu_showoffline_cb), node, 0, 0, NULL); @@ -1847,7 +1826,7 @@ create_buddy_menu(PurpleBlistNode *node, PurpleBuddy *b) menu = gtk_menu_new(); pidgin_blist_make_buddy_menu(menu, b, FALSE); - if(PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if(PURPLE_IS_CONTACT(node)) { pidgin_separator(menu); add_buddy_icon_menu_items(menu, node); @@ -1912,20 +1891,20 @@ pidgin_blist_show_context_menu(PurpleBlistNode *node, gboolean handled = FALSE; /* Create a menu based on the thing we right-clicked on */ - if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + if (PURPLE_IS_GROUP(node)) { PurpleGroup *g = (PurpleGroup *)node; menu = create_group_menu(node, g); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { PurpleChat *c = (PurpleChat *)node; menu = create_chat_menu(node, c); - } else if ((PURPLE_BLIST_NODE_IS_CONTACT(node)) && (gtknode->contact_expanded)) { + } else if ((PURPLE_IS_CONTACT(node)) && (gtknode->contact_expanded)) { menu = create_contact_menu(node); - } else if (PURPLE_BLIST_NODE_IS_CONTACT(node) || PURPLE_BLIST_NODE_IS_BUDDY(node)) { + } else if (PURPLE_IS_CONTACT(node) || PURPLE_IS_BUDDY(node)) { PurpleBuddy *b; - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + if (PURPLE_IS_CONTACT(node)) b = purple_contact_get_priority_buddy((PurpleContact*)node); else b = (PurpleBuddy *)node; @@ -1980,7 +1959,7 @@ gtk_blist_button_press_cb(GtkWidget *tv, GdkEventButton *event, gpointer user_da /* CTRL+middle click expands or collapse a contact */ } else if ((event->button == 2) && (event->type == GDK_BUTTON_PRESS) && - (event->state & GDK_CONTROL_MASK) && (PURPLE_BLIST_NODE_IS_CONTACT(node))) { + (event->state & GDK_CONTROL_MASK) && (PURPLE_IS_CONTACT(node))) { if (gtknode->contact_expanded) pidgin_blist_collapse_contact_cb(NULL, node); else @@ -1989,9 +1968,9 @@ gtk_blist_button_press_cb(GtkWidget *tv, GdkEventButton *event, gpointer user_da /* Double middle click gets info */ } else if ((event->button == 2) && (event->type == GDK_2BUTTON_PRESS) && - ((PURPLE_BLIST_NODE_IS_CONTACT(node)) || (PURPLE_BLIST_NODE_IS_BUDDY(node)))) { + ((PURPLE_IS_CONTACT(node)) || (PURPLE_IS_BUDDY(node)))) { PurpleBuddy *b; - if(PURPLE_BLIST_NODE_IS_CONTACT(node)) + if(PURPLE_IS_CONTACT(node)) b = purple_contact_get_priority_buddy((PurpleContact*)node); else b = (PurpleBuddy *)node; @@ -2316,11 +2295,11 @@ static void pidgin_blist_drag_data_get_cb(GtkWidget *widget, sourcerow); gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + if (PURPLE_IS_CONTACT(node)) { buddy = purple_contact_get_priority_buddy((PurpleContact *)node); } - else if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) + else if (!PURPLE_IS_BUDDY(node)) { gtk_tree_path_free(sourcerow); return; @@ -2351,11 +2330,11 @@ static void pidgin_blist_drag_data_get_cb(GtkWidget *widget, protocol, purple_buddy_get_name(buddy)); - if (purple_buddy_get_local_buddy_alias(buddy) != NULL) + if (purple_buddy_get_local_alias(buddy) != NULL) { g_string_append_printf(str, "X-IM-Alias: %s\r\n", - purple_buddy_get_local_buddy_alias(buddy)); + purple_buddy_get_local_alias(buddy)); } g_string_append(str, "\r\n"); @@ -2399,12 +2378,12 @@ static void pidgin_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, &iter, NODE_COLUMN, &node, -1); gtknode = purple_blist_node_get_ui_data(node); - if (PURPLE_BLIST_NODE_IS_CONTACT(n)) { + if (PURPLE_IS_CONTACT(n)) { PurpleContact *c = (PurpleContact*)n; - if (PURPLE_BLIST_NODE_IS_CONTACT(node) && gtknode->contact_expanded) { - purple_blist_merge_contact(c, node); - } else if (PURPLE_BLIST_NODE_IS_CONTACT(node) || - PURPLE_BLIST_NODE_IS_CHAT(node)) { + if (PURPLE_IS_CONTACT(node) && gtknode->contact_expanded) { + purple_contact_merge(c, node); + } else if (PURPLE_IS_CONTACT(node) || + PURPLE_IS_CHAT(node)) { switch(position) { case GTK_TREE_VIEW_DROP_AFTER: case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: @@ -2417,14 +2396,14 @@ static void pidgin_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, node->prev); break; } - } else if(PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if(PURPLE_IS_GROUP(node)) { purple_blist_add_contact(c, (PurpleGroup*)node, NULL); - } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { - purple_blist_merge_contact(c, node); + } else if(PURPLE_IS_BUDDY(node)) { + purple_contact_merge(c, node); } - } else if (PURPLE_BLIST_NODE_IS_BUDDY(n)) { + } else if (PURPLE_IS_BUDDY(n)) { PurpleBuddy *b = (PurpleBuddy*)n; - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (PURPLE_IS_BUDDY(node)) { switch(position) { case GTK_TREE_VIEW_DROP_AFTER: case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: @@ -2438,12 +2417,12 @@ static void pidgin_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, node->prev); break; } - } else if(PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if(PURPLE_IS_CHAT(node)) { purple_blist_add_buddy(b, NULL, (PurpleGroup*)node->parent, NULL); - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { purple_blist_add_buddy(b, NULL, (PurpleGroup*)node, NULL); - } else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + } else if (PURPLE_IS_CONTACT(node)) { if(gtknode->contact_expanded) { switch(position) { case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: @@ -2472,9 +2451,9 @@ static void pidgin_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, } } } - } else if (PURPLE_BLIST_NODE_IS_CHAT(n)) { + } else if (PURPLE_IS_CHAT(n)) { PurpleChat *chat = (PurpleChat *)n; - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (PURPLE_IS_BUDDY(node)) { switch(position) { case GTK_TREE_VIEW_DROP_AFTER: case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: @@ -2485,8 +2464,8 @@ static void pidgin_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, node->parent); break; } - } else if(PURPLE_BLIST_NODE_IS_CONTACT(node) || - PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if(PURPLE_IS_CONTACT(node) || + PURPLE_IS_CHAT(node)) { switch(position) { case GTK_TREE_VIEW_DROP_AFTER: case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: @@ -2497,12 +2476,12 @@ static void pidgin_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, purple_blist_add_chat(chat, (PurpleGroup*)node->parent, node->prev); break; } - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { purple_blist_add_chat(chat, (PurpleGroup*)node, NULL); } - } else if (PURPLE_BLIST_NODE_IS_GROUP(n)) { + } else if (PURPLE_IS_GROUP(n)) { PurpleGroup *g = (PurpleGroup*)n; - if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + if (PURPLE_IS_GROUP(node)) { switch (position) { case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: case GTK_TREE_VIEW_DROP_AFTER: @@ -2513,10 +2492,10 @@ static void pidgin_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, purple_blist_add_group(g, node->prev); break; } - } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { + } else if(PURPLE_IS_BUDDY(node)) { purple_blist_add_group(g, node->parent->parent); - } else if(PURPLE_BLIST_NODE_IS_CONTACT(node) || - PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if(PURPLE_IS_CONTACT(node) || + PURPLE_IS_CHAT(node)) { purple_blist_add_group(g, node->parent); } } @@ -2545,16 +2524,16 @@ static void pidgin_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (PURPLE_IS_BUDDY(node)) { group = (PurpleGroup *)node->parent->parent; } - else if (PURPLE_BLIST_NODE_IS_CHAT(node) || - PURPLE_BLIST_NODE_IS_CONTACT(node)) + else if (PURPLE_IS_CHAT(node) || + PURPLE_IS_CONTACT(node)) { group = (PurpleGroup *)node->parent; } - else if (PURPLE_BLIST_NODE_IS_GROUP(node)) + else if (PURPLE_IS_GROUP(node)) { group = (PurpleGroup *)node; } @@ -2605,16 +2584,16 @@ static void pidgin_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (PURPLE_IS_BUDDY(node)) { group = (PurpleGroup *)node->parent->parent; } - else if (PURPLE_BLIST_NODE_IS_CHAT(node) || - PURPLE_BLIST_NODE_IS_CONTACT(node)) + else if (PURPLE_IS_CHAT(node) || + PURPLE_IS_CONTACT(node)) { group = (PurpleGroup *)node->parent; } - else if (PURPLE_BLIST_NODE_IS_GROUP(node)) + else if (PURPLE_IS_GROUP(node)) { group = (PurpleGroup *)node; } @@ -2639,8 +2618,8 @@ static void pidgin_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); - if (PURPLE_BLIST_NODE_IS_BUDDY(node) || PURPLE_BLIST_NODE_IS_CONTACT(node)) { - PurpleBuddy *b = PURPLE_BLIST_NODE_IS_BUDDY(node) ? PURPLE_BUDDY(node) : purple_contact_get_priority_buddy(PURPLE_CONTACT(node)); + if (PURPLE_IS_BUDDY(node) || PURPLE_IS_CONTACT(node)) { + PurpleBuddy *b = PURPLE_IS_BUDDY(node) ? PURPLE_BUDDY(node) : purple_contact_get_priority_buddy(PURPLE_CONTACT(node)); pidgin_dnd_file_manage(sd, purple_buddy_get_account(b), purple_buddy_get_name(b)); gtk_drag_finish(dc, TRUE, gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); @@ -2696,15 +2675,15 @@ static GdkPixbuf *pidgin_blist_get_buddy_icon(PurpleBlistNode *node, PurplePluginProtocolInfo *prpl_info = NULL; gint orig_width, orig_height, scale_width, scale_height; - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if (PURPLE_IS_CONTACT(node)) { buddy = purple_contact_get_priority_buddy((PurpleContact*)node); contact = (PurpleContact*)node; - } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + } else if (PURPLE_IS_BUDDY(node)) { buddy = (PurpleBuddy*)node; contact = purple_buddy_get_contact(buddy); - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { group = (PurpleGroup*)node; - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { /* We don't need to do anything here. We just need to not fall * into the else block and return. */ } else { @@ -2776,7 +2755,7 @@ static GdkPixbuf *pidgin_blist_get_buddy_icon(PurpleBlistNode *node, if (purple_presence_is_idle(presence)) idle = TRUE; } else if (group) { - if (purple_blist_get_group_online_count(group) == 0) + if (purple_counting_node_get_online_count(PURPLE_COUNTING_NODE(group)) == 0) offline = TRUE; } @@ -2911,9 +2890,9 @@ static struct tooltip_data * create_tip_for_node(PurpleBlistNode *node, gboolean PurpleAccount *account = NULL; char *tmp = NULL, *node_name = NULL, *tooltip_text = NULL; - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (PURPLE_IS_BUDDY(node)) { account = purple_buddy_get_account((PurpleBuddy*)(node)); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { account = purple_chat_get_account((PurpleChat*)(node)); } @@ -2928,11 +2907,11 @@ static struct tooltip_data * create_tip_for_node(PurpleBlistNode *node, gboolean td->layout = create_pango_layout(tooltip_text, &td->width, &td->height); } - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (PURPLE_IS_BUDDY(node)) { tmp = g_markup_escape_text(purple_buddy_get_name((PurpleBuddy*)node), -1); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if (PURPLE_IS_CHAT(node)) { tmp = g_markup_escape_text(purple_chat_get_name((PurpleChat*)node), -1); - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { tmp = g_markup_escape_text(purple_group_get_name((PurpleGroup*)node), -1); } else { /* I don't believe this can happen currently, I think @@ -3201,12 +3180,12 @@ pidgin_blist_create_tooltip_for_node(GtkWidget *widget, gpointer data, int *w, i } gtkblist->tipwindow = widget; - if (PURPLE_BLIST_NODE_IS_CHAT(node) || - PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (PURPLE_IS_CHAT(node) || + PURPLE_IS_BUDDY(node)) { struct tooltip_data *td = create_tip_for_node(node, TRUE); pidgin_blist_align_tooltip(td, gtkblist->tipwindow); gtkblist->tooltipdata = g_list_append(gtkblist->tooltipdata, td); - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { PurpleGroup *group = (PurpleGroup*)node; GSList *accounts; struct tooltip_data *td = create_tip_for_node(node, TRUE); @@ -3221,13 +3200,13 @@ pidgin_blist_create_tooltip_for_node(GtkWidget *widget, gpointer data, int *w, i td = create_tip_for_account(account); gtkblist->tooltipdata = g_list_append(gtkblist->tooltipdata, td); } - } else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + } else if (PURPLE_IS_CONTACT(node)) { PurpleBlistNode *child; PurpleBuddy *b = purple_contact_get_priority_buddy((PurpleContact *)node); for(child = node->child; child; child = child->next) { - if(PURPLE_BLIST_NODE_IS_BUDDY(child) && buddy_is_displayable((PurpleBuddy*)child)) { + if(PURPLE_IS_BUDDY(child) && buddy_is_displayable((PurpleBuddy*)child)) { struct tooltip_data *td = create_tip_for_node(child, (b == (PurpleBuddy*)child)); pidgin_blist_align_tooltip(td, gtkblist->tipwindow); if (b == (PurpleBuddy *)child) { @@ -3274,7 +3253,7 @@ static gboolean pidgin_blist_expand_timeout(GtkWidget *tv) gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); - if(!PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if(!PURPLE_IS_CONTACT(node)) { gtk_tree_path_free(path); return FALSE; } @@ -3490,7 +3469,7 @@ edit_mood_cb(PurpleConnection *gc, PurpleRequestFields *fields) const char *text; PurpleAccount *account = purple_connection_get_account(gc); - if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES) { + if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOOD_MESSAGES) { PurpleRequestField *text_field; text_field = purple_request_fields_get_field(fields, "text"); text = purple_request_field_string_get_value(text_field); @@ -3506,7 +3485,7 @@ edit_mood_cb(PurpleConnection *gc, PurpleRequestFields *fields) PurpleAccount *account = (PurpleAccount *) accounts->data; PurpleConnection *gc = purple_account_get_connection(account); - if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOODS)) { + if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOODS)) { update_status_with_mood(account, mood, NULL); } } @@ -3541,12 +3520,12 @@ get_global_moods(void) if (purple_account_is_connected(account)) { PurpleConnection *gc = purple_account_get_connection(account); - if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOODS) { + if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOODS) { PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); PurpleMood *mood = NULL; - /* PURPLE_CONNECTION_SUPPORT_MOODS would not be set if the prpl doesn't + /* PURPLE_CONNECTION_FLAG_SUPPORT_MOODS would not be set if the prpl doesn't * have get_moods, so using PURPLE_PROTOCOL_PLUGIN_HAS_FUNC isn't necessary * here */ for (mood = prpl_info->get_moods(account) ; @@ -3602,7 +3581,7 @@ get_global_mood_status(void) if (purple_account_is_connected(account) && (purple_connection_get_flags(purple_account_get_connection(account)) & - PURPLE_CONNECTION_SUPPORT_MOODS)) { + PURPLE_CONNECTION_FLAG_SUPPORT_MOODS)) { PurplePresence *presence = purple_account_get_presence(account); PurpleStatus *status = purple_presence_get_status(presence, "mood"); const gchar *curr_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME); @@ -3676,7 +3655,7 @@ set_mood_cb(GtkWidget *widget, PurpleAccount *account) purple_request_fields_add_group(fields, g); /* if the connection allows setting a mood message */ - if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES)) { + if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOOD_MESSAGES)) { g = purple_request_field_group_new(NULL); f = purple_request_field_string_new("text", _("Message (optional)"), NULL, FALSE); @@ -3829,14 +3808,14 @@ static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full) PurplePluginProtocolInfo *prpl_info = NULL; char *tmp; - if (PURPLE_BLIST_NODE_IS_CHAT(node)) + if (PURPLE_IS_CHAT(node)) { PurpleChat *chat; GList *connections; GList *cur; struct proto_chat_entry *pce; char *name, *value; - PurpleConversation *conv; + PurpleChatConversation *conv; PidginBlistNode *bnode = purple_blist_node_get_ui_data(node); chat = (PurpleChat *)node; @@ -3852,7 +3831,7 @@ static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full) } if (bnode && bnode->conv.conv) { - conv = bnode->conv.conv; + conv = PURPLE_CHAT_CONVERSATION(bnode->conv.conv); } else { char *chat_name; if (prpl_info && prpl_info->get_chat_name) @@ -3860,17 +3839,17 @@ static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full) else chat_name = g_strdup(purple_chat_get_name(chat)); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, chat_name, + conv = purple_conversations_find_chat_with_account(chat_name, purple_chat_get_account(chat)); g_free(chat_name); } - if (conv && !purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) { + if (conv && !purple_chat_conversation_has_left(conv)) { g_string_append_printf(str, _("\n<b>Occupants:</b> %d"), - g_list_length(purple_conv_chat_get_users(PURPLE_CONV_CHAT(conv)))); + g_list_length(purple_chat_conversation_get_users(conv))); if (prpl_info && (prpl_info->options & OPT_PROTO_CHAT_TOPIC)) { - const char *chattopic = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(conv)); + const char *chattopic = purple_chat_conversation_get_topic(conv); char *topic = chattopic ? g_markup_escape_text(chattopic, -1) : NULL; g_string_append_printf(str, _("\n<b>Topic:</b> %s"), topic ? topic : _("(no topic set)")); g_free(topic); @@ -3904,7 +3883,7 @@ static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full) cur = g_list_delete_link(cur, cur); } } - else if (PURPLE_BLIST_NODE_IS_CONTACT(node) || PURPLE_BLIST_NODE_IS_BUDDY(node)) + else if (PURPLE_IS_CONTACT(node) || PURPLE_IS_BUDDY(node)) { /* NOTE: THIS FUNCTION IS NO LONGER CALLED FOR CONTACTS. * It is only called by create_tip_for_node(), and create_tip_for_node() is never called for a contact. @@ -3915,9 +3894,10 @@ static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full) PurpleNotifyUserInfo *user_info; GList *connections; char *tmp; + gchar *alias; time_t idle_secs, signon; - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + if (PURPLE_IS_CONTACT(node)) { c = (PurpleContact *)node; b = purple_contact_get_priority_buddy(c); @@ -3945,12 +3925,13 @@ static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full) /* Alias */ /* If there's not a contact alias, the node is being displayed with * this alias, so there's no point in showing it in the tooltip. */ - if (full && c && purple_buddy_get_local_buddy_alias(b) != NULL && purple_buddy_get_local_buddy_alias(b)[0] != '\0' && - (c->alias != NULL && c->alias[0] != '\0') && - strcmp(c->alias, purple_buddy_get_local_buddy_alias(b)) != 0) + g_object_get(c, "alias", &alias, NULL); + if (full && c && purple_buddy_get_local_alias(b) != NULL && purple_buddy_get_local_alias(b)[0] != '\0' && + (alias != NULL && alias[0] != '\0') && + strcmp(alias, purple_buddy_get_local_alias(b)) != 0) { purple_notify_user_info_add_pair_plaintext(user_info, - _("Buddy Alias"), purple_buddy_get_local_buddy_alias(b)); + _("Buddy Alias"), purple_buddy_get_local_alias(b)); } /* Nickname/Server Alias */ @@ -4000,7 +3981,7 @@ static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full) PurpleBlistNode *bnode; int lastseen = 0; - if (gtknode && (!gtknode->contact_expanded || PURPLE_BLIST_NODE_IS_CONTACT(node))) + if (gtknode && (!gtknode->contact_expanded || PURPLE_IS_CONTACT(node))) { /* We're either looking at a buddy for a collapsed contact or * an expanded contact itself so we show the most recent @@ -4054,16 +4035,17 @@ static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full) tmp = purple_notify_user_info_get_text_with_newline(user_info, "\n"); g_string_append(str, tmp); g_free(tmp); + g_free(alias); purple_notify_user_info_destroy(user_info); - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + } else if (PURPLE_IS_GROUP(node)) { gint count; PurpleGroup *group = (PurpleGroup*)node; PurpleNotifyUserInfo *user_info; user_info = purple_notify_user_info_new(); - count = purple_blist_get_group_online_count(group); + count = purple_counting_node_get_online_count(PURPLE_COUNTING_NODE(group)); if (count != 0) { /* Online buddies in group */ char tmp2[12]; @@ -4072,7 +4054,7 @@ static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full) _("Online Buddies"), tmp2); } - count = purple_blist_get_group_size(group, FALSE); + count = purple_counting_node_get_current_size(PURPLE_COUNTING_NODE(group)); if (count != 0) { /* Total buddies (from online accounts) in group */ char tmp2[12]; @@ -4133,11 +4115,11 @@ pidgin_blist_get_emblem(PurpleBlistNode *node) PurplePresence *p = NULL; PurpleStatus *tune; - if(PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if(PURPLE_IS_CONTACT(node)) { if(!gtknode->contact_expanded) { buddy = purple_contact_get_priority_buddy((PurpleContact*)node); } - } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { + } else if(PURPLE_IS_BUDDY(node)) { buddy = (PurpleBuddy*)node; p = purple_buddy_get_presence(buddy); if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOBILE)) { @@ -4159,7 +4141,7 @@ pidgin_blist_get_emblem(PurpleBlistNode *node) g_return_val_if_fail(buddy != NULL, NULL); - if (!purple_privacy_check(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy))) { + if (!purple_account_privacy_check(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy))) { path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "blocked.png", NULL); return _pidgin_blist_get_cached_emblem(path); } @@ -4239,16 +4221,16 @@ pidgin_blist_get_status_icon(PurpleBlistNode *node, PidginStatusIconSize size) GtkIconSize icon_size = gtk_icon_size_from_name((size == PIDGIN_STATUS_ICON_LARGE) ? PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL : PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC); - if(PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if(PURPLE_IS_CONTACT(node)) { if(!gtknode->contact_expanded) { buddy = purple_contact_get_priority_buddy((PurpleContact*)node); if (buddy != NULL) gtkbuddynode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy)); } - } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { + } else if(PURPLE_IS_BUDDY(node)) { buddy = (PurpleBuddy*)node; gtkbuddynode = purple_blist_node_get_ui_data(node); - } else if(PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if(PURPLE_IS_CHAT(node)) { chat = (PurpleChat*)node; } else { return NULL; @@ -4358,6 +4340,7 @@ pidgin_blist_get_name_markup(PurpleBuddy *b, gboolean selected, gboolean aliased gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"); PidginThemeFont *statusfont = NULL, *namefont = NULL; PidginBlistTheme *theme; + gchar *contact_alias; if (conv != NULL) { PidginBlistNode *ui = purple_blist_node_get_ui_data(&(b->node)); @@ -4375,9 +4358,11 @@ pidgin_blist_get_name_markup(PurpleBuddy *b, gboolean selected, gboolean aliased if(contact) gtkcontactnode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(contact)); + g_object_get(contact, "alias", &contact_alias, NULL); + /* Name */ - if (gtkcontactnode && !gtkcontactnode->contact_expanded && contact->alias) - name = contact->alias; + if (gtkcontactnode && !gtkcontactnode->contact_expanded && contact_alias) + name = contact_alias; else name = purple_buddy_get_alias(b); @@ -4531,6 +4516,7 @@ pidgin_blist_get_name_markup(PurpleBuddy *b, gboolean selected, gboolean aliased g_free(nametext); g_free(statustext); g_free(idletime); + g_free(contact_alias); if (hidden_conv) { char *tmp = text; @@ -4584,10 +4570,10 @@ static gboolean pidgin_blist_refresh_timer(PurpleBuddyList *list) return TRUE; for(gnode = list->root; gnode; gnode = gnode->next) { - if(!PURPLE_BLIST_NODE_IS_GROUP(gnode)) + if(!PURPLE_IS_GROUP(gnode)) continue; for(cnode = gnode->child; cnode; cnode = cnode->next) { - if(PURPLE_BLIST_NODE_IS_CONTACT(cnode)) { + if(PURPLE_IS_CONTACT(cnode)) { PurpleBuddy *buddy; buddy = purple_contact_get_priority_buddy((PurpleContact*)cnode); @@ -4615,8 +4601,8 @@ static void pidgin_blist_hide_node(PurpleBuddyList *list, PurpleBlistNode *node, gtkblist->selected_node = NULL; if (get_iter_from_node(node, &iter)) { gtk_tree_store_remove(gtkblist->treemodel, &iter); - if(update && (PURPLE_BLIST_NODE_IS_CONTACT(node) || - PURPLE_BLIST_NODE_IS_BUDDY(node) || PURPLE_BLIST_NODE_IS_CHAT(node))) { + if(update && (PURPLE_IS_CONTACT(node) || + PURPLE_IS_BUDDY(node) || PURPLE_IS_CHAT(node))) { pidgin_blist_update(list, node->parent); } } @@ -4697,11 +4683,9 @@ unseen_conv_menu(void) menu = NULL; } - ims = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_IM, - PIDGIN_UNSEEN_TEXT, FALSE, 0); + ims = pidgin_conversations_get_unseen_ims(PIDGIN_UNSEEN_TEXT, FALSE, 0); - chats = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_CHAT, - PIDGIN_UNSEEN_NICK, FALSE, 0); + chats = pidgin_conversations_get_unseen_chats(PIDGIN_UNSEEN_NICK, FALSE, 0); if(ims && chats) convs = g_list_concat(ims, chats); @@ -4730,12 +4714,10 @@ menutray_press_cb(GtkWidget *widget, GdkEventButton *event) switch (event->button) { case 1: - convs = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_IM, - PIDGIN_UNSEEN_TEXT, FALSE, 1); + convs = pidgin_conversations_get_unseen_ims(PIDGIN_UNSEEN_TEXT, FALSE, 1); if(!convs) - convs = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_CHAT, - PIDGIN_UNSEEN_NICK, FALSE, 1); + convs = pidgin_conversations_get_unseen_chats(PIDGIN_UNSEEN_NICK, FALSE, 1); if (convs) { pidgin_conv_present_conversation((PurpleConversation*)convs->data); g_list_free(convs); @@ -4749,7 +4731,7 @@ menutray_press_cb(GtkWidget *widget, GdkEventButton *event) } static void -conversation_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type, +conversation_updated_cb(PurpleConversation *conv, PurpleConversationUpdateType type, PidginBuddyList *gtkblist) { PurpleAccount *account = purple_conversation_get_account(conv); @@ -4757,11 +4739,11 @@ conversation_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type, GList *ims, *chats; GList *l = NULL; - if (type != PURPLE_CONV_UPDATE_UNSEEN) + if (type != PURPLE_CONVERSATION_UPDATE_UNSEEN) return; if(account != NULL && purple_conversation_get_name(conv) != NULL) { - PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); + PurpleBuddy *buddy = purple_blist_find_buddy(account, purple_conversation_get_name(conv)); if(buddy != NULL) pidgin_blist_update_buddy(NULL, PURPLE_BLIST_NODE(buddy), TRUE); } @@ -4771,11 +4753,9 @@ conversation_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type, gtkblist->menutrayicon = NULL; } - ims = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_IM, - PIDGIN_UNSEEN_TEXT, FALSE, 0); + ims = pidgin_conversations_get_unseen_ims(PIDGIN_UNSEEN_TEXT, FALSE, 0); - chats = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_CHAT, - PIDGIN_UNSEEN_NICK, FALSE, 0); + chats = pidgin_conversations_get_unseen_chats(PIDGIN_UNSEEN_NICK, FALSE, 0); if(ims && chats) convs = g_list_concat(ims, chats); @@ -4796,8 +4776,8 @@ conversation_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type, if(gtkconv) count = gtkconv->unseen_count; - else if(purple_conversation_get_data(l->data, "unseen-count")) - count = GPOINTER_TO_INT(purple_conversation_get_data(l->data, "unseen-count")); + else if(g_object_get_data(G_OBJECT(l->data), "unseen-count")) + count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(l->data), "unseen-count")); g_string_append_printf(tooltip_text, ngettext("%d unread message from %s\n", "%d unread messages from %s\n", count), @@ -4826,7 +4806,7 @@ conversation_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type, static void conversation_deleting_cb(PurpleConversation *conv, PidginBuddyList *gtkblist) { - conversation_updated_cb(conv, PURPLE_CONV_UPDATE_UNSEEN, gtkblist); + conversation_updated_cb(conv, PURPLE_CONVERSATION_UPDATE_UNSEEN, gtkblist); } static void @@ -4848,12 +4828,11 @@ written_msg_update_ui_cb(PurpleAccount *account, const char *who, const char *me !(flag & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV))) return; ui->conv.flags |= PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE; - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT - && (flag & PURPLE_MESSAGE_NICK)) + if (PURPLE_IS_CHAT_CONVERSATION(conv) && (flag & PURPLE_MESSAGE_NICK)) ui->conv.flags |= PIDGIN_BLIST_CHAT_HAS_PENDING_MESSAGE_WITH_NICK; ui->conv.last_message = time(NULL); /* XXX: for lack of better data */ - pidgin_blist_update(purple_get_blist(), node); + pidgin_blist_update(purple_blist_get_buddy_list(), node); } static void @@ -4864,7 +4843,7 @@ displayed_msg_update_ui_cb(PidginConversation *gtkconv, PurpleBlistNode *node) return; ui->conv.flags &= ~(PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE | PIDGIN_BLIST_CHAT_HAS_PENDING_MESSAGE_WITH_NICK); - pidgin_blist_update(purple_get_blist(), node); + pidgin_blist_update(purple_blist_get_buddy_list(), node); } static void @@ -4872,50 +4851,41 @@ conversation_created_cb(PurpleConversation *conv, PidginBuddyList *gtkblist) { PurpleAccount *account = purple_conversation_get_account(conv); - switch (purple_conversation_get_type(conv)) { - case PURPLE_CONV_TYPE_IM: - { - GSList *buddies = purple_find_buddies(account, purple_conversation_get_name(conv)); - while (buddies) { - PurpleBlistNode *buddy = buddies->data; - struct _pidgin_blist_node *ui = purple_blist_node_get_ui_data(buddy); - buddies = g_slist_delete_link(buddies, buddies); - if (!ui) - continue; - ui->conv.conv = conv; - ui->conv.flags = 0; - ui->conv.last_message = 0; - purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation", - ui, PURPLE_CALLBACK(conversation_deleted_update_ui_cb), ui); - purple_signal_connect(purple_conversations_get_handle(), "wrote-im-msg", - ui, PURPLE_CALLBACK(written_msg_update_ui_cb), buddy); - purple_signal_connect(pidgin_conversations_get_handle(), "conversation-displayed", - ui, PURPLE_CALLBACK(displayed_msg_update_ui_cb), buddy); - } - } - break; - case PURPLE_CONV_TYPE_CHAT: - { - PurpleChat *chat = purple_blist_find_chat(account, purple_conversation_get_name(conv)); - struct _pidgin_blist_node *ui; - if (!chat) - break; - ui = purple_blist_node_get_ui_data(&(chat->node)); - if (!ui) - break; - ui->conv.conv = conv; - ui->conv.flags = 0; - ui->conv.last_message = 0; - purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation", - ui, PURPLE_CALLBACK(conversation_deleted_update_ui_cb), ui); - purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", - ui, PURPLE_CALLBACK(written_msg_update_ui_cb), chat); - purple_signal_connect(pidgin_conversations_get_handle(), "conversation-displayed", - ui, PURPLE_CALLBACK(displayed_msg_update_ui_cb), chat); - } - break; - default: - break; + if (PURPLE_IS_IM_CONVERSATION(conv)) { + GSList *buddies = purple_blist_find_buddies(account, purple_conversation_get_name(conv)); + while (buddies) { + PurpleBlistNode *buddy = buddies->data; + struct _pidgin_blist_node *ui = purple_blist_node_get_ui_data(buddy); + buddies = g_slist_delete_link(buddies, buddies); + if (!ui) + continue; + ui->conv.conv = conv; + ui->conv.flags = 0; + ui->conv.last_message = 0; + purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation", + ui, PURPLE_CALLBACK(conversation_deleted_update_ui_cb), ui); + purple_signal_connect(purple_conversations_get_handle(), "wrote-im-msg", + ui, PURPLE_CALLBACK(written_msg_update_ui_cb), buddy); + purple_signal_connect(pidgin_conversations_get_handle(), "conversation-displayed", + ui, PURPLE_CALLBACK(displayed_msg_update_ui_cb), buddy); + } + } else { + PurpleChat *chat = purple_blist_find_chat(account, purple_conversation_get_name(conv)); + struct _pidgin_blist_node *ui; + if (!chat) + return; + ui = purple_blist_node_get_ui_data(&(chat->node)); + if (!ui) + return; + ui->conv.conv = conv; + ui->conv.flags = 0; + ui->conv.last_message = 0; + purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation", + ui, PURPLE_CALLBACK(conversation_deleted_update_ui_cb), ui); + purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", + ui, PURPLE_CALLBACK(written_msg_update_ui_cb), chat); + purple_signal_connect(pidgin_conversations_get_handle(), "conversation-displayed", + ui, PURPLE_CALLBACK(displayed_msg_update_ui_cb), chat); } } @@ -4940,13 +4910,13 @@ static void pidgin_blist_new_node(PurpleBlistNode *node) gboolean pidgin_blist_node_is_contact_expanded(PurpleBlistNode *node) { - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + if (PURPLE_IS_BUDDY(node)) { node = node->parent; if (node == NULL) return FALSE; } - g_return_val_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(node), FALSE); + g_return_val_if_fail(PURPLE_IS_CONTACT(node), FALSE); return ((struct _pidgin_blist_node *)purple_blist_node_get_ui_data(node))->contact_expanded; } @@ -4990,7 +4960,7 @@ static void _prefs_change_redo_list(const char *name, PurplePrefType type, gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); } - redo_buddy_list(purple_get_blist(), FALSE, FALSE); + redo_buddy_list(purple_blist_get_buddy_list(), FALSE, FALSE); gtk_tree_view_columns_autosize(GTK_TREE_VIEW(gtkblist->treeview)); if (node) @@ -5882,12 +5852,12 @@ pidgin_blist_search_equal_func(GtkTreeModel *model, gint column, return TRUE; compare = NULL; - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if (PURPLE_IS_CONTACT(node)) { PurpleBuddy *b = purple_contact_get_priority_buddy(PURPLE_CONTACT(node)); - if (!purple_buddy_get_local_buddy_alias(b)) + if (!purple_buddy_get_local_alias(b)) compare = purple_buddy_get_name(b); - } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { - if (!purple_buddy_get_local_buddy_alias(PURPLE_BUDDY(node))) + } else if (PURPLE_IS_BUDDY(node)) { + if (!purple_buddy_get_local_alias(PURPLE_BUDDY(node))) compare = purple_buddy_get_name(PURPLE_BUDDY(node)); } @@ -6308,7 +6278,7 @@ static void pidgin_blist_show(PurpleBuddyList *list) purple_signal_connect(handle, "account-actions-changed", gtkblist, PURPLE_CALLBACK(account_actions_changed), NULL); - handle = pidgin_account_get_handle(); + handle = pidgin_accounts_get_handle(); purple_signal_connect(handle, "account-modified", gtkblist, PURPLE_CALLBACK(account_modified), gtkblist); @@ -6359,14 +6329,14 @@ static void redo_buddy_list(PurpleBuddyList *list, gboolean remove, gboolean rer /* This is only needed when we're reverting to a non-GTK+ sorted * status. We shouldn't need to remove otherwise. */ - if (remove && !PURPLE_BLIST_NODE_IS_GROUP(node)) + if (remove && !PURPLE_IS_GROUP(node)) pidgin_blist_hide_node(list, node, FALSE); - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (PURPLE_IS_BUDDY(node)) pidgin_blist_update_buddy(list, node, rerender); - else if (PURPLE_BLIST_NODE_IS_CHAT(node)) + else if (PURPLE_IS_CHAT(node)) pidgin_blist_update(list, node); - else if (PURPLE_BLIST_NODE_IS_GROUP(node)) + else if (PURPLE_IS_GROUP(node)) pidgin_blist_update(list, node); node = purple_blist_node_next(node, FALSE); } @@ -6384,8 +6354,8 @@ pidgin_blist_update_refresh_timeout() PurpleBuddyList *blist; PidginBuddyList *gtkblist; - blist = purple_get_blist(); - gtkblist = PIDGIN_BLIST(purple_get_blist()); + blist = purple_blist_get_buddy_list(); + gtkblist = PIDGIN_BLIST(purple_blist_get_buddy_list()); gtkblist->refresh_timer = purple_timeout_add_seconds(30,(GSourceFunc)pidgin_blist_refresh_timer, blist); } @@ -6479,7 +6449,7 @@ static void pidgin_blist_selection_changed(GtkTreeSelection *selection, gpointer * but we don't do it for groups, because it causes total bizarness - * the previously selected buddy node might rendered at half height. */ - if ((new_selection != NULL) && PURPLE_BLIST_NODE_IS_GROUP(new_selection)) { + if ((new_selection != NULL) && PURPLE_IS_GROUP(new_selection)) { do_selection_changed(new_selection); } else { g_timeout_add(0, (GSourceFunc)do_selection_changed, new_selection); @@ -6501,7 +6471,7 @@ static gboolean insert_node(PurpleBuddyList *list, PurpleBlistNode *node, GtkTre if(get_iter_from_node(node, &cur)) curptr = &cur; - if(PURPLE_BLIST_NODE_IS_CONTACT(node) || PURPLE_BLIST_NODE_IS_CHAT(node)) { + if(PURPLE_IS_CONTACT(node) || PURPLE_IS_CHAT(node)) { current_sort_method->func(node, list, parent_iter, curptr, iter); } else { sort_method_none(node, list, parent_iter, curptr, iter); @@ -6531,10 +6501,10 @@ static gboolean insert_node(PurpleBuddyList *list, PurpleBlistNode *node, GtkTre GtkTreePath *expand = NULL; struct _pidgin_blist_node *gtkparentnode = purple_blist_node_get_ui_data(node->parent); - if(PURPLE_BLIST_NODE_IS_GROUP(node->parent)) { + if(PURPLE_IS_GROUP(node->parent)) { if(!purple_blist_node_get_bool(node->parent, "collapsed")) expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &parent_iter); - } else if(PURPLE_BLIST_NODE_IS_CONTACT(node->parent) && + } else if(PURPLE_IS_CONTACT(node->parent) && gtkparentnode->contact_expanded) { expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &parent_iter); } @@ -6553,7 +6523,7 @@ static gboolean pidgin_blist_group_has_show_offline_buddy(PurpleGroup *group) gnode = PURPLE_BLIST_NODE(group); for(cnode = gnode->child; cnode; cnode = cnode->next) { - if(PURPLE_BLIST_NODE_IS_CONTACT(cnode)) { + if(PURPLE_IS_CONTACT(cnode)) { for(bnode = cnode->child; bnode; bnode = bnode->next) { PurpleBuddy *buddy = (PurpleBuddy *)bnode; if (purple_account_is_connected(purple_buddy_get_account(buddy)) && @@ -6581,11 +6551,11 @@ static void pidgin_blist_update_group(PurpleBuddyList *list, if (editing_blist) return; - if (PURPLE_BLIST_NODE_IS_GROUP(node)) + if (PURPLE_IS_GROUP(node)) gnode = node; - else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + else if (PURPLE_IS_BUDDY(node)) gnode = node->parent->parent; - else if (PURPLE_BLIST_NODE_IS_CONTACT(node) || PURPLE_BLIST_NODE_IS_CHAT(node)) + else if (PURPLE_IS_CONTACT(node) || PURPLE_IS_CHAT(node)) gnode = node->parent; else return; @@ -6595,13 +6565,13 @@ static void pidgin_blist_update_group(PurpleBuddyList *list, show_offline = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies"); if(show_offline) - count = purple_blist_get_group_size(group, FALSE); + count = purple_counting_node_get_current_size(PURPLE_COUNTING_NODE(group)); else - count = purple_blist_get_group_online_count(group); + count = purple_counting_node_get_online_count(PURPLE_COUNTING_NODE(group)); if (count > 0 || purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_empty_groups")) show = TRUE; - else if (PURPLE_BLIST_NODE_IS_BUDDY(node) && buddy_is_displayable((PurpleBuddy*)node)) { /* Or chat? */ + else if (PURPLE_IS_BUDDY(node) && buddy_is_displayable((PurpleBuddy*)node)) { /* Or chat? */ show = TRUE; } else if (!show_offline) { show = pidgin_blist_group_has_show_offline_buddy(group); @@ -6680,8 +6650,8 @@ static char *pidgin_get_group_title(PurpleBlistNode *gnode, gboolean expanded) if (!expanded) { g_snprintf(group_count, sizeof(group_count), "%d/%d", - purple_blist_get_group_online_count(group), - purple_blist_get_group_size(group, FALSE)); + purple_counting_node_get_online_count(PURPLE_COUNTING_NODE(group)), + purple_counting_node_get_current_size(PURPLE_COUNTING_NODE(group))); } theme = pidgin_blist_get_theme(); @@ -6836,15 +6806,15 @@ static void pidgin_blist_update_contact(PurpleBuddyList *list, PurpleBlistNode * if (editing_blist) return; - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (PURPLE_IS_BUDDY(node)) cnode = node->parent; else cnode = node; - g_return_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(cnode)); + g_return_if_fail(PURPLE_IS_CONTACT(cnode)); /* First things first, update the group */ - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (PURPLE_IS_BUDDY(node)) pidgin_blist_update_group(list, node); else pidgin_blist_update_group(list, cnode->parent); @@ -6926,7 +6896,7 @@ static void pidgin_blist_update_buddy(PurpleBuddyList *list, PurpleBlistNode *no PurpleBuddy *buddy; struct _pidgin_blist_node *gtkparentnode; - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + g_return_if_fail(PURPLE_IS_BUDDY(node)); if (node->parent == NULL) return; @@ -6957,7 +6927,7 @@ static void pidgin_blist_update_chat(PurpleBuddyList *list, PurpleBlistNode *nod { PurpleChat *chat; - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); + g_return_if_fail(PURPLE_IS_CHAT(node)); if (editing_blist) return; @@ -7075,23 +7045,14 @@ static void pidgin_blist_update(PurpleBuddyList *list, PurpleBlistNode *node) if (purple_blist_node_get_ui_data(node) == NULL) pidgin_blist_new_node(node); - switch (purple_blist_node_get_type(node)) { - case PURPLE_BLIST_GROUP_NODE: - pidgin_blist_update_group(list, node); - break; - case PURPLE_BLIST_CONTACT_NODE: - pidgin_blist_update_contact(list, node); - break; - case PURPLE_BLIST_BUDDY_NODE: - pidgin_blist_update_buddy(list, node, TRUE); - break; - case PURPLE_BLIST_CHAT_NODE: - pidgin_blist_update_chat(list, node); - break; - case PURPLE_BLIST_OTHER_NODE: - return; - } - + if (PURPLE_IS_GROUP(node)) + pidgin_blist_update_group(list, node); + else if (PURPLE_IS_CONTACT(node)) + pidgin_blist_update_contact(list, node); + else if (PURPLE_IS_BUDDY(node)) + pidgin_blist_update_buddy(list, node, TRUE); + else if (PURPLE_IS_CHAT(node)) + pidgin_blist_update_chat(list, node); } static void pidgin_blist_destroy(PurpleBuddyList *list) @@ -7179,17 +7140,17 @@ groups_tree(void) g_list_free(list); list = NULL; - if (purple_get_blist()->root == NULL) + if (purple_blist_get_buddy_list()->root == NULL) { list = g_list_append(list, (gpointer)_("Buddies")); } else { - for (gnode = purple_get_blist()->root; + for (gnode = purple_blist_get_buddy_list()->root; gnode != NULL; gnode = gnode->next) { - if (PURPLE_BLIST_NODE_IS_GROUP(gnode)) + if (PURPLE_IS_GROUP(gnode)) { g = (PurpleGroup *)gnode; list = g_list_append(list, (char *) purple_group_get_name(g)); @@ -7238,7 +7199,7 @@ add_buddy_cb(GtkWidget *w, int resp, PidginAddBuddyData *data) PurpleAccount *account; PurpleGroup *g; PurpleBuddy *b; - PurpleConversation *c; + PurpleIMConversation *im; PurpleBuddyIcon *icon; if (resp == GTK_RESPONSE_OK) @@ -7257,15 +7218,15 @@ add_buddy_cb(GtkWidget *w, int resp, PidginAddBuddyData *data) g = NULL; if ((grp != NULL) && (*grp != '\0')) { - if ((g = purple_find_group(grp)) == NULL) + if ((g = purple_blist_find_group(grp)) == NULL) { g = purple_group_new(grp); purple_blist_add_group(g, NULL); } - b = purple_find_buddy_in_group(account, who, g); + b = purple_blist_find_buddy_in_group(account, who, g); } - else if ((b = purple_find_buddy(account, who)) != NULL) + else if ((b = purple_blist_find_buddy(account, who)) != NULL) { g = purple_buddy_get_group(b); } @@ -7297,9 +7258,9 @@ add_buddy_cb(GtkWidget *w, int resp, PidginAddBuddyData *data) * Or something. --Mark */ - c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, data->rq_data.account); - if (c != NULL) { - icon = purple_conv_im_get_icon(PURPLE_CONV_IM(c)); + im = purple_conversations_find_im_with_account(who, data->rq_data.account); + if (im != NULL) { + icon = purple_im_conversation_get_icon(im); if (icon != NULL) purple_buddy_icon_update(icon); } @@ -7419,7 +7380,7 @@ add_chat_cb(GtkWidget *w, PidginAddChatData *data) group = NULL; if ((group_name != NULL) && (*group_name != '\0') && - ((group = purple_find_group(group_name)) == NULL)) + ((group = purple_blist_find_group(group_name)) == NULL)) { group = purple_group_new(group_name); purple_blist_add_group(group, NULL); @@ -7672,15 +7633,15 @@ static gboolean autojoin_cb(PurpleConnection *gc, gpointer data) { PurpleAccount *account = purple_connection_get_account(gc); PurpleBlistNode *gnode, *cnode; - for(gnode = purple_get_blist()->root; gnode; gnode = gnode->next) + for(gnode = purple_blist_get_buddy_list()->root; gnode; gnode = gnode->next) { - if(!PURPLE_BLIST_NODE_IS_GROUP(gnode)) + if(!PURPLE_IS_GROUP(gnode)) continue; for(cnode = gnode->child; cnode; cnode = cnode->next) { PurpleChat *chat; - if(!PURPLE_BLIST_NODE_IS_CHAT(cnode)) + if(!PURPLE_IS_CHAT(cnode)) continue; chat = (PurpleChat *)cnode; @@ -7713,6 +7674,7 @@ static gboolean buddy_signonoff_timeout_cb(PurpleBuddy *buddy) pidgin_blist_update(NULL, PURPLE_BLIST_NODE(buddy)); + g_object_unref(buddy); return FALSE; } @@ -7730,6 +7692,8 @@ static void buddy_signonoff_cb(PurpleBuddy *buddy) if(gtknode->recent_signonoff_timer > 0) purple_timeout_remove(gtknode->recent_signonoff_timer); + + g_object_ref(buddy); gtknode->recent_signonoff_timer = purple_timeout_add_seconds(10, (GSourceFunc)buddy_signonoff_timeout_cb, buddy); } @@ -7738,7 +7702,7 @@ void pidgin_blist_set_theme(PidginBlistTheme *theme) { PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); - PurpleBuddyList *list = purple_get_blist(); + PurpleBuddyList *list = purple_blist_get_buddy_list(); if (theme != NULL) purple_prefs_set_string(PIDGIN_PREFS_ROOT "/blist/theme", @@ -7791,32 +7755,26 @@ void pidgin_blist_init(void) /* Register our signals */ purple_signal_register(gtk_blist_handle, "gtkblist-hiding", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_BUDDY_LIST); purple_signal_register(gtk_blist_handle, "gtkblist-unhiding", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_BUDDY_LIST); purple_signal_register(gtk_blist_handle, "gtkblist-created", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_BUDDY_LIST); purple_signal_register(gtk_blist_handle, "drawing-tooltip", - purple_marshal_VOID__POINTER_POINTER_UINT, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_NODE), - purple_value_new_outgoing(PURPLE_TYPE_BOXED, "GString *"), - purple_value_new(PURPLE_TYPE_BOOLEAN)); + purple_marshal_VOID__POINTER_POINTER_UINT, G_TYPE_NONE, + 3, PURPLE_TYPE_BLIST_NODE, + G_TYPE_POINTER, /* pointer to a (GString *) */ + G_TYPE_BOOLEAN); purple_signal_register(gtk_blist_handle, "drawing-buddy", purple_marshal_POINTER__POINTER, - purple_value_new(PURPLE_TYPE_STRING), 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_BLIST_BUDDY)); + G_TYPE_STRING, 1, PURPLE_TYPE_BUDDY); purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", gtk_blist_handle, PURPLE_CALLBACK(buddy_signonoff_cb), NULL); @@ -7899,9 +7857,9 @@ void pidgin_blist_sort_method_set(const char *id){ return; } if (!strcmp(id, "none")) { - redo_buddy_list(purple_get_blist(), TRUE, FALSE); + redo_buddy_list(purple_blist_get_buddy_list(), TRUE, FALSE); } else { - redo_buddy_list(purple_get_blist(), FALSE, FALSE); + redo_buddy_list(purple_blist_get_buddy_list(), FALSE, FALSE); } } @@ -7934,9 +7892,9 @@ static void sort_method_alphabetical(PurpleBlistNode *node, PurpleBuddyList *bli const char *my_name; - if(PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if(PURPLE_IS_CONTACT(node)) { my_name = purple_contact_get_alias((PurpleContact*)node); - } else if(PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if(PURPLE_IS_CHAT(node)) { my_name = purple_chat_get_name((PurpleChat*)node); } else { sort_method_none(node, blist, groupiter, cur, iter); @@ -7955,9 +7913,9 @@ static void sort_method_alphabetical(PurpleBlistNode *node, PurpleBuddyList *bli gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &more_z, NODE_COLUMN, &n, -1); - if(PURPLE_BLIST_NODE_IS_CONTACT(n)) { + if(PURPLE_IS_CONTACT(n)) { this_name = purple_contact_get_alias((PurpleContact*)n); - } else if(PURPLE_BLIST_NODE_IS_CHAT(n)) { + } else if(PURPLE_IS_CHAT(n)) { this_name = purple_chat_get_name((PurpleChat*)n); } else { this_name = NULL; @@ -7994,9 +7952,9 @@ static void sort_method_status(PurpleBlistNode *node, PurpleBuddyList *blist, Gt PurpleBuddy *my_buddy, *this_buddy; - if(PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if(PURPLE_IS_CONTACT(node)) { my_buddy = purple_contact_get_priority_buddy((PurpleContact*)node); - } else if(PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if(PURPLE_IS_CHAT(node)) { if (cur != NULL) { *iter = *cur; return; @@ -8022,7 +7980,7 @@ static void sort_method_status(PurpleBlistNode *node, PurpleBuddyList *blist, Gt gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &more_z, NODE_COLUMN, &n, -1); - if(PURPLE_BLIST_NODE_IS_CONTACT(n)) { + if(PURPLE_IS_CONTACT(n)) { this_buddy = purple_contact_get_priority_buddy((PurpleContact*)n); } else { this_buddy = NULL; @@ -8034,9 +7992,9 @@ static void sort_method_status(PurpleBlistNode *node, PurpleBuddyList *blist, Gt ? purple_contact_get_alias(purple_buddy_get_contact(this_buddy)) : NULL)); - presence_cmp = purple_presence_compare( - purple_buddy_get_presence(my_buddy), - this_buddy ? purple_buddy_get_presence(this_buddy) : NULL); + presence_cmp = purple_buddy_presence_compare( + PURPLE_BUDDY_PRESENCE(purple_buddy_get_presence(my_buddy)), + this_buddy ? PURPLE_BUDDY_PRESENCE(purple_buddy_get_presence(this_buddy)) : NULL); if (this_buddy == NULL || (presence_cmp < 0 || @@ -8082,7 +8040,7 @@ static void sort_method_log_activity(PurpleBlistNode *node, PurpleBuddyList *bli return; } - if(PURPLE_BLIST_NODE_IS_CONTACT(node)) { + if(PURPLE_IS_CONTACT(node)) { PurpleBlistNode *n; PurpleBuddy *buddy; for (n = node->child; n; n = n->next) { @@ -8090,7 +8048,7 @@ static void sort_method_log_activity(PurpleBlistNode *node, PurpleBuddyList *bli activity_score += purple_log_get_activity_score(PURPLE_LOG_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); } buddy_name = purple_contact_get_alias((PurpleContact*)node); - } else if(PURPLE_BLIST_NODE_IS_CHAT(node)) { + } else if(PURPLE_IS_CHAT(node)) { /* we don't have a reliable way of getting the log filename * from the chat info in the blist, yet */ if (cur != NULL) { @@ -8120,7 +8078,7 @@ static void sort_method_log_activity(PurpleBlistNode *node, PurpleBuddyList *bli gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &more_z, NODE_COLUMN, &n, -1); this_log_activity_score = 0; - if(PURPLE_BLIST_NODE_IS_CONTACT(n)) { + if(PURPLE_IS_CONTACT(n)) { for (n2 = n->child; n2; n2 = n2->next) { buddy = (PurpleBuddy*)n2; this_log_activity_score += purple_log_get_activity_score(PURPLE_LOG_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); @@ -8132,7 +8090,7 @@ static void sort_method_log_activity(PurpleBlistNode *node, PurpleBuddyList *bli cmp = purple_utf8_strcasecmp(buddy_name, this_buddy_name); - if (!PURPLE_BLIST_NODE_IS_CONTACT(n) || activity_score > this_log_activity_score || + if (!PURPLE_IS_CONTACT(n) || activity_score > this_log_activity_score || ((activity_score == this_log_activity_score) && (cmp < 0 || (cmp == 0 && node < n)))) { if (cur != NULL) { @@ -8357,7 +8315,7 @@ pidgin_blist_update_accounts_menu(void) (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods) || PURPLE_PLUGIN_HAS_ACTIONS(plugin))) { if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods) && - (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOODS)) { + (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOODS)) { if (purple_account_get_status(account, "mood")) { menuitem = gtk_menu_item_new_with_mnemonic(_("Set _Mood...")); diff --git a/pidgin/gtkblist.h b/pidgin/gtkblist.h index 209f45a1d2..49bbb3578c 100644 --- a/pidgin/gtkblist.h +++ b/pidgin/gtkblist.h @@ -59,7 +59,7 @@ typedef enum { } PidginStatusIconSize; #include "pidgin.h" -#include "blist.h" +#include "buddylist.h" #include "gtkblist-theme.h" /************************************************************************** diff --git a/pidgin/gtkconv.c b/pidgin/gtkconv.c index b2860cedd8..7ba25b3a70 100644 --- a/pidgin/gtkconv.c +++ b/pidgin/gtkconv.c @@ -170,7 +170,7 @@ typedef struct { GtkWidget *entry; GtkWidget *message; - PurpleConversation *conv; + PurpleChatConversation *chat; } InviteBuddyInfo; @@ -200,9 +200,9 @@ static gboolean infopane_entry_activate(PidginConversation *gtkconv); static void got_typing_keypress(PidginConversation *gtkconv, gboolean first); #endif static void gray_stuff_out(PidginConversation *gtkconv); -static void add_chat_buddy_common(PurpleConversation *conv, PurpleConvChatBuddy *cb, const char *old_name); +static void add_chat_user_common(PurpleChatConversation *chat, PurpleChatUser *cb, const char *old_name); static gboolean tab_complete(PurpleConversation *conv); -static void pidgin_conv_updated(PurpleConversation *conv, PurpleConvUpdateType type); +static void pidgin_conv_updated(PurpleConversation *conv, PurpleConversationUpdateType type); static void conv_set_unseen(PurpleConversation *gtkconv, PidginUnseenState state); static void gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state); static void update_typing_icon(PidginConversation *gtkconv); @@ -210,7 +210,7 @@ static void update_typing_message(PidginConversation *gtkconv, const char *messa gboolean pidgin_conv_has_focus(PurpleConversation *conv); static GArray* generate_nick_colors(guint numcolors, GdkColor background); static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); -static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag, gboolean create); +static GtkTextTag *get_buddy_tag(PurpleChatConversation *chat, const char *who, PurpleMessageFlags flag, gboolean create); static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); @@ -247,17 +247,13 @@ get_conversation_blist_node(PurpleConversation *conv) PurpleAccount *account = purple_conversation_get_account(conv); PurpleBlistNode *node = NULL; - switch (purple_conversation_get_type(conv)) { - case PURPLE_CONV_TYPE_IM: - node = PURPLE_BLIST_NODE(purple_find_buddy(account, purple_conversation_get_name(conv))); - node = node ? node->parent : NULL; - break; - case PURPLE_CONV_TYPE_CHAT: - node = PURPLE_BLIST_NODE(purple_blist_find_chat(account, purple_conversation_get_name(conv))); - break; - default: - break; + if (PURPLE_IS_IM_CONVERSATION(conv)) { + node = PURPLE_BLIST_NODE(purple_blist_find_buddy(account, purple_conversation_get_name(conv))); + node = node ? node->parent : NULL; + } else { + node = PURPLE_BLIST_NODE(purple_blist_find_chat(account, purple_conversation_get_name(conv))); } + return node; } @@ -270,7 +266,7 @@ close_this_sucker(gpointer data) { PidginConversation *gtkconv = data; GList *list = g_list_copy(gtkconv->convs); - g_list_foreach(list, (GFunc)purple_conversation_destroy, NULL); + g_list_foreach(list, (GFunc)g_object_unref, NULL); g_list_free(list); return FALSE; } @@ -287,27 +283,18 @@ close_conv_cb(GtkButton *button, PidginConversation *gtkconv) PurpleAccount *account = purple_conversation_get_account(conv); const char *name = purple_conversation_get_name(conv); - switch (purple_conversation_get_type(conv)) { - case PURPLE_CONV_TYPE_IM: - { - if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/close_immediately")) - close_this_sucker(gtkconv); - else - hide_conv(gtkconv, TRUE); - break; - } - case PURPLE_CONV_TYPE_CHAT: - { - PurpleChat *chat = purple_blist_find_chat(account, name); - if (!chat || - !purple_blist_node_get_bool(&chat->node, "gtk-persistent")) - close_this_sucker(gtkconv); - else - hide_conv(gtkconv, FALSE); - break; - } - default: - ; + if (PURPLE_IS_IM_CONVERSATION(conv)) { + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/close_immediately")) + close_this_sucker(gtkconv); + else + hide_conv(gtkconv, TRUE); + } else { + PurpleChat *chat = purple_blist_find_chat(account, name); + if (!chat || + !purple_blist_node_get_bool(&chat->node, "gtk-persistent")) + close_this_sucker(gtkconv); + else + hide_conv(gtkconv, FALSE); } return TRUE; @@ -361,10 +348,7 @@ static PurpleCmdRet say_command_cb(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) - purple_conv_im_send(PURPLE_CONV_IM(conv), args[0]); - else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) - purple_conv_chat_send(PURPLE_CONV_CHAT(conv), args[0]); + purple_conversation_send(conv, args[0]); return PURPLE_CMD_RET_OK; } @@ -376,11 +360,7 @@ me_command_cb(PurpleConversation *conv, char *tmp; tmp = g_strdup_printf("/me %s", args[0]); - - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) - purple_conv_im_send(PURPLE_CONV_IM(conv), tmp); - else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) - purple_conv_chat_send(PURPLE_CONV_CHAT(conv), tmp); + purple_conversation_send(conv, tmp); g_free(tmp); return PURPLE_CMD_RET_OK; @@ -444,10 +424,7 @@ debug_command_cb(PurpleConversation *conv, } markup = g_markup_escape_text(tmp, -1); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) - purple_conv_im_send(PURPLE_CONV_IM(conv), markup); - else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) - purple_conv_chat_send(PURPLE_CONV_CHAT(conv), markup); + purple_conversation_send(conv, markup); g_free(tmp); g_free(markup); @@ -477,7 +454,10 @@ static PurpleCmdRet clearall_command_cb(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - purple_conversation_foreach(purple_conversation_clear_message_history); + GList *l; + for (l = purple_conversations_get_all(); l != NULL; l = l->next) + purple_conversation_clear_message_history(PURPLE_CONVERSATION(l->data)); + return PURPLE_CMD_RET_OK; } @@ -607,7 +587,7 @@ check_for_and_do_command(PurpleConversation *conv) retval = TRUE; break; case PURPLE_CMD_STATUS_WRONG_TYPE: - if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) + if(PURPLE_IS_IM_CONVERSATION(conv)) purple_conversation_write(conv, "", _("That command only works in chats, not IMs."), PURPLE_MESSAGE_NO_LOG, time(NULL)); else @@ -644,8 +624,8 @@ send_cb(GtkWidget *widget, PidginConversation *gtkconv) return; } - if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) && - purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) + if (PURPLE_IS_CHAT_CONVERSATION(conv) && + purple_chat_conversation_has_left(PURPLE_CHAT_CONVERSATION(conv))) return; if (!purple_account_is_connected(account)) @@ -672,7 +652,7 @@ send_cb(GtkWidget *widget, PidginConversation *gtkconv) #endif gc = NULL/*purple_account_get_connection(account)*/; - if (gc && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_NO_NEWLINES)) { + if (gc && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_FLAG_NO_NEWLINES)) { #if 0 /* TODO WebKit */ char **bufs; @@ -681,10 +661,7 @@ send_cb(GtkWidget *widget, PidginConversation *gtkconv) bufs = gtk_webview_get_markup_lines(GTK_WEBVIEW(gtkconv->entry)); for (i = 0; bufs[i]; i++) { send_history_add(gtkconv, bufs[i]); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) - purple_conv_im_send_with_flags(PURPLE_CONV_IM(conv), bufs[i], flags); - else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) - purple_conv_chat_send_with_flags(PURPLE_CONV_CHAT(conv), bufs[i], flags); + purple_conversation_send_with_flags(conv, bufs[i], flags); } g_strfreev(bufs); @@ -692,10 +669,7 @@ send_cb(GtkWidget *widget, PidginConversation *gtkconv) } else { send_history_add(gtkconv, buf); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) - purple_conv_im_send_with_flags(PURPLE_CONV_IM(conv), buf, flags); - else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) - purple_conv_chat_send_with_flags(PURPLE_CONV_CHAT(conv), buf, flags); + purple_conversation_send_with_flags(conv, buf, flags); } g_free(clean); @@ -716,15 +690,15 @@ add_remove_cb(GtkWidget *widget, PidginConversation *gtkconv) account = purple_conversation_get_account(conv); name = purple_conversation_get_name(conv); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + if (PURPLE_IS_IM_CONVERSATION(conv)) { PurpleBuddy *b; - b = purple_find_buddy(account, name); + b = purple_blist_find_buddy(account, name); if (b != NULL) pidgin_dialogs_remove_buddy(b); else if (account != NULL && purple_account_is_connected(account)) purple_blist_request_add_buddy(account, (char *)name, NULL, NULL); - } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + } else { PurpleChat *c; c = purple_blist_find_chat(account, name); @@ -739,11 +713,11 @@ add_remove_cb(GtkWidget *widget, PidginConversation *gtkconv) static void chat_do_info(PidginConversation *gtkconv, const char *who) { - PurpleConversation *conv = gtkconv->active_conv; + PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(gtkconv->active_conv); PurpleConnection *gc; - if ((gc = purple_conversation_get_connection(conv))) { - pidgin_retrieve_user_info_in_chat(gc, who, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv))); + if ((gc = purple_conversation_get_connection(gtkconv->active_conv))) { + pidgin_retrieve_user_info_in_chat(gc, who, purple_chat_conversation_get_id(chat)); } } @@ -753,11 +727,11 @@ info_cb(GtkWidget *widget, PidginConversation *gtkconv) { PurpleConversation *conv = gtkconv->active_conv; - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + if (PURPLE_IS_IM_CONVERSATION(conv)) { pidgin_retrieve_user_info(purple_conversation_get_connection(conv), purple_conversation_get_name(conv)); gtk_widget_grab_focus(gtkconv->entry); - } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + } else { /* Get info of the person currently selected in the GtkTreeView */ PidginChatPane *gtkchat; GtkTreeIter iter; @@ -831,9 +805,9 @@ static void do_invite(GtkWidget *w, int resp, InviteBuddyInfo *info) { const char *buddy, *message; - PurpleConversation *conv; + PurpleChatConversation *chat; - conv = info->conv; + chat = info->chat; if (resp == GTK_RESPONSE_OK) { buddy = gtk_entry_get_text(GTK_ENTRY(info->entry)); @@ -842,8 +816,8 @@ do_invite(GtkWidget *w, int resp, InviteBuddyInfo *info) if (!g_ascii_strcasecmp(buddy, "")) return; - serv_chat_invite(purple_conversation_get_connection(conv), - purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), + serv_chat_invite(purple_conversation_get_connection(PURPLE_CONVERSATION(chat)), + purple_chat_conversation_get_id(chat), message, buddy); } @@ -861,7 +835,8 @@ invite_dnd_recv(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, const char *convprotocol; gboolean success = TRUE; - convprotocol = purple_account_get_protocol_id(purple_conversation_get_account(info->conv)); + convprotocol = purple_account_get_protocol_id( + purple_conversation_get_account(PURPLE_CONVERSATION(info->chat))); if (dnd_info == PIDGIN_DRAG_BLIST_NODE) { @@ -871,16 +846,16 @@ invite_dnd_recv(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, memcpy(&node, data, sizeof(node)); - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + if (PURPLE_IS_CONTACT(node)) buddy = purple_contact_get_priority_buddy((PurpleContact *)node); - else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + else if (PURPLE_IS_BUDDY(node)) buddy = (PurpleBuddy *)node; else return; if (strcmp(convprotocol, purple_account_get_protocol_id(purple_buddy_get_account(buddy)))) { - purple_notify_error(PIDGIN_CONVERSATION(info->conv), NULL, + purple_notify_error(PIDGIN_CONVERSATION(PURPLE_CONVERSATION(info->chat)), NULL, _("That buddy is not on the same protocol as this " "chat."), NULL); success = FALSE; @@ -902,13 +877,13 @@ invite_dnd_recv(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, { if (account == NULL) { - purple_notify_error(PIDGIN_CONVERSATION(info->conv), NULL, + purple_notify_error(PIDGIN_CONVERSATION(PURPLE_CONVERSATION(info->chat)), NULL, _("You are not currently signed on with an account that " "can invite that buddy."), NULL); } else if (strcmp(convprotocol, purple_account_get_protocol_id(account))) { - purple_notify_error(PIDGIN_CONVERSATION(info->conv), NULL, + purple_notify_error(PIDGIN_CONVERSATION(PURPLE_CONVERSATION(info->chat)), NULL, _("That buddy is not on the same protocol as this " "chat."), NULL); success = FALSE; @@ -930,7 +905,7 @@ invite_dnd_recv(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, static void invite_cb(GtkWidget *widget, PidginConversation *gtkconv) { - PurpleConversation *conv = gtkconv->active_conv; + PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(gtkconv->active_conv); InviteBuddyInfo *info = NULL; if (invite_dialog == NULL) { @@ -944,7 +919,7 @@ invite_cb(GtkWidget *widget, PidginConversation *gtkconv) gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_HUGE)); info = g_new0(InviteBuddyInfo, 1); - info->conv = conv; + info->chat = chat; gtkwin = pidgin_conv_get_window(gtkconv); @@ -1007,7 +982,7 @@ invite_cb(GtkWidget *widget, PidginConversation *gtkconv) /* Now the Buddy drop-down entry field. */ info->entry = gtk_entry_new(); pidgin_setup_screenname_autocomplete(info->entry, NULL, chat_invite_filter, - purple_conversation_get_account(conv)); + purple_conversation_get_account(PURPLE_CONVERSATION(chat))); gtk_table_attach_defaults(GTK_TABLE(table), info->entry, 1, 2, 0, 1); gtk_label_set_mnemonic_widget(GTK_LABEL(label), info->entry); @@ -1113,7 +1088,7 @@ menu_save_as_cb(GtkAction *action, gpointer data) PidginWindow *win = data; PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); PurpleAccount *account = purple_conversation_get_account(conv); - PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); + PurpleBuddy *buddy = purple_blist_find_buddy(account, purple_conversation_get_name(conv)); const char *name; gchar *buf; gchar *c; @@ -1151,13 +1126,7 @@ menu_view_log_cb(GtkAction *action, gpointer data) GSList *cur; conv = pidgin_conv_window_get_active_conversation(win); - - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) - type = PURPLE_LOG_IM; - else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) - type = PURPLE_LOG_CHAT; - else - return; + type = PURPLE_IS_IM_CONVERSATION(conv) ? PURPLE_LOG_IM : PURPLE_LOG_CHAT; gtkblist = pidgin_blist_get_default_gtk_blist(); @@ -1167,7 +1136,7 @@ menu_view_log_cb(GtkAction *action, gpointer data) name = purple_conversation_get_name(conv); account = purple_conversation_get_account(conv); - buddies = purple_find_buddies(account, name); + buddies = purple_blist_find_buddies(account, name); for (cur = buddies; cur != NULL; cur = cur->next) { PurpleBlistNode *node = cur->data; @@ -1230,7 +1199,7 @@ menu_send_file_cb(GtkAction *action, gpointer data) PidginWindow *win = data; PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + if (PURPLE_IS_IM_CONVERSATION(conv)) { serv_send_file(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), NULL); } @@ -1242,7 +1211,7 @@ menu_get_attention_cb(GObject *obj, gpointer data) PidginWindow *win = data; PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + if (PURPLE_IS_IM_CONVERSATION(conv)) { int index; if ((GtkAction *)obj == win->menu.get_attention) index = 0; @@ -1303,13 +1272,13 @@ menu_alias_cb(GtkAction *action, gpointer data) account = purple_conversation_get_account(conv); name = purple_conversation_get_name(conv); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + if (PURPLE_IS_IM_CONVERSATION(conv)) { PurpleBuddy *b; - b = purple_find_buddy(account, name); + b = purple_blist_find_buddy(account, name); if (b != NULL) pidgin_dialogs_alias_buddy(b); - } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + } else { PurpleChat *c; c = purple_blist_find_chat(account, name); @@ -1376,7 +1345,7 @@ menu_add_remove_cb(GtkAction *action, gpointer data) static gboolean close_already(gpointer data) { - purple_conversation_destroy(data); + g_object_unref(data); return FALSE; } @@ -1391,11 +1360,11 @@ hide_conv(PidginConversation *gtkconv, gboolean closetimer) for (list = g_list_copy(gtkconv->convs); list; list = g_list_delete_link(list, list)) { PurpleConversation *conv = list->data; if (closetimer) { - guint timer = GPOINTER_TO_INT(purple_conversation_get_data(conv, "close-timer")); + guint timer = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "close-timer")); if (timer) purple_timeout_remove(timer); timer = purple_timeout_add_seconds(CLOSE_CONV_TIMEOUT_SECS, close_already, conv); - purple_conversation_set_data(conv, "close-timer", GINT_TO_POINTER(timer)); + g_object_set_data(G_OBJECT(conv), "close-timer", GINT_TO_POINTER(timer)); } #if 0 /* I will miss you */ @@ -1457,24 +1426,16 @@ menu_logging_cb(GtkAction *action, gpointer data) } /* Save the setting IFF it's different than the pref. */ - switch (purple_conversation_get_type(conv)) - { - case PURPLE_CONV_TYPE_IM: - if (logging == purple_prefs_get_bool("/purple/logging/log_ims")) - purple_blist_node_remove_setting(node, "enable-logging"); - else - purple_blist_node_set_bool(node, "enable-logging", logging); - break; - - case PURPLE_CONV_TYPE_CHAT: - if (logging == purple_prefs_get_bool("/purple/logging/log_chats")) - purple_blist_node_remove_setting(node, "enable-logging"); - else - purple_blist_node_set_bool(node, "enable-logging", logging); - break; - - default: - break; + if (PURPLE_IS_IM_CONVERSATION(conv)) { + if (logging == purple_prefs_get_bool("/purple/logging/log_ims")) + purple_blist_node_remove_setting(node, "enable-logging"); + else + purple_blist_node_set_bool(node, "enable-logging", logging); + } else { + if (logging == purple_prefs_get_bool("/purple/logging/log_chats")) + purple_blist_node_remove_setting(node, "enable-logging"); + else + purple_blist_node_set_bool(node, "enable-logging", logging); } } @@ -1526,7 +1487,7 @@ chat_do_im(PidginConversation *gtkconv, const char *who) if (prpl_info && prpl_info->get_cb_real_name) real_who = prpl_info->get_cb_real_name(gc, - purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); + purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)), who); if(!who && !real_who) return; @@ -1536,27 +1497,25 @@ chat_do_im(PidginConversation *gtkconv, const char *who) g_free(real_who); } -static void pidgin_conv_chat_update_user(PurpleConversation *conv, const char *user); +static void pidgin_conv_chat_update_user(PurpleChatUser *chatuser); static void ignore_cb(GtkWidget *w, PidginConversation *gtkconv) { - PurpleConversation *conv = gtkconv->active_conv; - PurpleConvChat *chat; + PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(gtkconv->active_conv); const char *name; - chat = PURPLE_CONV_CHAT(conv); name = g_object_get_data(G_OBJECT(w), "user_data"); if (name == NULL) return; - if (purple_conv_chat_is_user_ignored(chat, name)) - purple_conv_chat_unignore(chat, name); + if (purple_chat_conversation_is_ignored_user(chat, name)) + purple_chat_conversation_unignore(chat, name); else - purple_conv_chat_ignore(chat, name); + purple_chat_conversation_ignore(chat, name); - pidgin_conv_chat_update_user(conv, name); + pidgin_conv_chat_update_user(purple_chat_conversation_find_user(chat, name)); } static void @@ -1582,7 +1541,7 @@ menu_chat_send_file_cb(GtkWidget *w, PidginConversation *gtkconv) if (prpl_info && prpl_info->get_cb_real_name) real_who = prpl_info->get_cb_real_name(gc, - purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); + purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)), who); serv_send_file(gc, real_who ? real_who : who, NULL); g_free(real_who); @@ -1608,7 +1567,7 @@ menu_chat_add_remove_cb(GtkWidget *w, PidginConversation *gtkconv) account = purple_conversation_get_account(conv); name = g_object_get_data(G_OBJECT(w), "user_data"); - b = purple_find_buddy(account, name); + b = purple_blist_find_buddy(account, name); if (b != NULL) pidgin_dialogs_remove_buddy(b); @@ -1666,11 +1625,11 @@ menu_last_said_cb(GtkWidget *w, PidginConversation *gtkconv) } static GtkWidget * -create_chat_menu(PurpleConversation *conv, const char *who, PurpleConnection *gc) +create_chat_menu(PurpleChatConversation *chat, const char *who, PurpleConnection *gc) { static GtkWidget *menu = NULL; PurplePluginProtocolInfo *prpl_info = NULL; - PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); + PurpleConversation *conv = PURPLE_CONVERSATION(chat); PurpleAccount *account = purple_conversation_get_account(conv); gboolean is_me = FALSE; GtkWidget *button; @@ -1686,7 +1645,7 @@ create_chat_menu(PurpleConversation *conv, const char *who, PurpleConnection *gc if (menu) gtk_widget_destroy(menu); - if (!strcmp(purple_conv_chat_get_nick(chat), purple_normalize(account, who))) + if (!strcmp(purple_chat_conversation_get_nick(chat), purple_normalize(account, who))) is_me = TRUE; menu = gtk_menu_new(); @@ -1715,7 +1674,7 @@ create_chat_menu(PurpleConversation *conv, const char *who, PurpleConnection *gc gchar *real_who = NULL; if (prpl_info->get_cb_real_name) real_who = prpl_info->get_cb_real_name(gc, - purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); + purple_chat_conversation_get_id(chat), who); if (!(!prpl_info->can_receive_file || prpl_info->can_receive_file(gc, real_who ? real_who : who))) can_receive_file = FALSE; g_free(real_who); @@ -1728,7 +1687,7 @@ create_chat_menu(PurpleConversation *conv, const char *who, PurpleConnection *gc } - if (purple_conv_chat_is_user_ignored(PURPLE_CONV_CHAT(conv), who)) + if (purple_chat_conversation_is_ignored_user(chat, who)) button = pidgin_new_item_from_stock(menu, _("Un-Ignore"), PIDGIN_STOCK_IGNORE, G_CALLBACK(ignore_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL); else @@ -1752,7 +1711,7 @@ create_chat_menu(PurpleConversation *conv, const char *who, PurpleConnection *gc } if (!is_me && prpl_info && !(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { - if ((buddy = purple_find_buddy(account, who)) != NULL) + if ((buddy = purple_blist_find_buddy(account, who)) != NULL) button = pidgin_new_item_from_stock(menu, _("Remove"), GTK_STOCK_REMOVE, G_CALLBACK(menu_chat_add_remove_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL); else @@ -1809,7 +1768,7 @@ gtkconv_chat_popup_menu_cb(GtkWidget *widget, PidginConversation *gtkconv) return FALSE; gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1); - menu = create_chat_menu (conv, who, gc); + menu = create_chat_menu (PURPLE_CHAT_CONVERSATION(conv), who, gc); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, pidgin_treeview_popup_menu_position_func, widget, 0, GDK_CURRENT_TIME); @@ -1874,7 +1833,7 @@ right_click_chat_cb(GtkWidget *widget, GdkEventButton *event, webkit_dom_element_scroll_into_view(WEBKIT_DOM_ELEMENT(node), TRUE); } else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) { - GtkWidget *menu = create_chat_menu (conv, who, gc); + GtkWidget *menu = create_chat_menu (PURPLE_CHAT_CONVERSATION(conv), who, gc); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, event->time); } @@ -1943,7 +1902,7 @@ static gboolean gtkconv_cycle_focus(PidginConversation *gtkconv, GtkDirectionType dir) { PurpleConversation *conv = gtkconv->active_conv; - gboolean chat = purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT; + gboolean chat = PURPLE_IS_CHAT_CONVERSATION(conv); GtkWidget *next = NULL; struct { GtkWidget *from; @@ -2332,10 +2291,10 @@ pidgin_conv_switch_active_conversation(PurpleConversation *conv) gtk_webview_set_protocol_name(GTK_WEBVIEW(gtkconv->webview), protocol_name); features = purple_conversation_get_features(conv); - if (!(features & PURPLE_CONNECTION_HTML)) + if (!(features & PURPLE_CONNECTION_FLAG_HTML)) gtk_webview_clear_formatting(GTK_WEBVIEW(gtkconv->entry)); - else if (features & PURPLE_CONNECTION_FORMATTING_WBFO && - !(purple_conversation_get_features(old_conv) & PURPLE_CONNECTION_FORMATTING_WBFO)) + else if (features & PURPLE_CONNECTION_FLAG_FORMATTING_WBFO && + !(purple_conversation_get_features(old_conv) & PURPLE_CONNECTION_FLAG_FORMATTING_WBFO)) { /* The old conversation allowed formatting on parts of the * buffer, but the new one only allows it on the whole @@ -2383,12 +2342,12 @@ pidgin_conv_switch_active_conversation(PurpleConversation *conv) gtk_webview_toggle_fontface(entry, fontface); - if (!(features & PURPLE_CONNECTION_NO_FONTSIZE)) + if (!(features & PURPLE_CONNECTION_FLAG_NO_FONTSIZE)) gtk_webview_font_set_size(entry, fontsize); gtk_webview_toggle_forecolor(entry, forecolor); - if (!(features & PURPLE_CONNECTION_NO_BGCOLOR)) + if (!(features & PURPLE_CONNECTION_FLAG_NO_BGCOLOR)) { gtk_webview_toggle_backcolor(entry, backcolor); #if 0 @@ -2410,7 +2369,7 @@ pidgin_conv_switch_active_conversation(PurpleConversation *conv) * here, we didn't call gtk_imhtml_clear_formatting() (because we want to * preserve the formatting exactly as it is), so we have to do this now. */ gtk_webview_set_whole_buffer_formatting_only(entry, - (features & PURPLE_CONNECTION_FORMATTING_WBFO)); + (features & PURPLE_CONNECTION_FLAG_FORMATTING_WBFO)); } purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv); @@ -2429,13 +2388,13 @@ menu_conv_sel_send_cb(GObject *m, gpointer data) { PurpleAccount *account = g_object_get_data(m, "purple_account"); gchar *name = g_object_get_data(m, "purple_buddy_name"); - PurpleConversation *conv; + PurpleIMConversation *im; if (gtk_check_menu_item_get_active((GtkCheckMenuItem*) m) == FALSE) return; - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name); - pidgin_conv_switch_active_conversation(conv); + im = purple_im_conversation_new(account, name); + pidgin_conv_switch_active_conversation(PURPLE_CONVERSATION(im)); } #if 0 @@ -2460,7 +2419,7 @@ delete_text_cb(GtkTextBuffer *textbuffer, GtkTextIter *start_pos, { PidginConversation *gtkconv = (PidginConversation *)user_data; PurpleConversation *conv; - PurpleConvIm *im; + PurpleIMConversation *im; g_return_if_fail(gtkconv != NULL); @@ -2474,11 +2433,11 @@ delete_text_cb(GtkTextBuffer *textbuffer, GtkTextIter *start_pos, if (gtk_text_iter_is_start(start_pos) && gtk_text_iter_is_end(end_pos)) { /* We deleted all the text, so turn off typing. */ - purple_conv_im_stop_send_typed_timeout(im); + purple_im_conversation_stop_send_typed_timeout(im); serv_send_typing(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), - PURPLE_NOT_TYPING); + PURPLE_IM_NOT_TYPING); } else { /* We're deleting, but not all of it, so it counts as typing. */ @@ -2524,8 +2483,8 @@ pidgin_conv_get_tab_icons(PurpleConversation *conv) g_return_val_if_fail(name != NULL, NULL); /* Use the buddy icon, if possible */ - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - PurpleBuddy *b = purple_find_buddy(account, name); + if (PURPLE_IS_IM_CONVERSATION(conv)) { + PurpleBuddy *b = purple_blist_find_buddy(account, name); if (b != NULL) { PurplePresence *p; p = purple_buddy_get_presence(b); @@ -2557,15 +2516,15 @@ pidgin_conv_get_icon_stock(PurpleConversation *conv) g_return_val_if_fail(account != NULL, NULL); /* Use the buddy icon, if possible */ - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + if (PURPLE_IS_IM_CONVERSATION(conv)) { const char *name = NULL; PurpleBuddy *b; name = purple_conversation_get_name(conv); - b = purple_find_buddy(account, name); + b = purple_blist_find_buddy(account, name); if (b != NULL) { PurplePresence *p = purple_buddy_get_presence(b); PurpleStatus *active = purple_presence_get_active_status(p); - PurpleStatusType *type = purple_status_get_type(active); + PurpleStatusType *type = purple_status_get_status_type(active); PurpleStatusPrimitive prim = purple_status_type_get_primitive(type); stock = pidgin_stock_id_from_status_primitive(prim); } else { @@ -2597,8 +2556,8 @@ pidgin_conv_get_icon(PurpleConversation *conv, GtkWidget *parent, const char *ic g_return_val_if_fail(name != NULL, NULL); /* Use the buddy icon, if possible */ - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - PurpleBuddy *b = purple_find_buddy(account, name); + if (PURPLE_IS_IM_CONVERSATION(conv)) { + PurpleBuddy *b = purple_blist_find_buddy(account, name); if (b != NULL) { /* I hate this hack. It fixes a bug where the pending message icon * displays in the conv tab even though it shouldn't. @@ -2641,8 +2600,8 @@ update_tab_icon(PurpleConversation *conv) status = infopane_status = pidgin_conv_get_icon_stock(conv); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - PurpleBuddy *b = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); + if (PURPLE_IS_IM_CONVERSATION(conv)) { + PurpleBuddy *b = purple_blist_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); if (b) emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b); } @@ -2679,8 +2638,7 @@ update_tab_icon(PurpleConversation *conv) gtk_widget_queue_draw(gtkconv->infopane); if (pidgin_conv_window_is_active_conversation(conv) && - (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_IM || - gtkconv->u.im->anim == NULL)) + (PURPLE_IS_CHAT_CONVERSATION(conv) || gtkconv->u.im->anim == NULL)) { l = pidgin_conv_get_tab_icons(conv); @@ -2824,12 +2782,12 @@ static void saveicon_writefile_cb(void *user_data, const char *filename) { PidginConversation *gtkconv = (PidginConversation *)user_data; - PurpleConversation *conv = gtkconv->active_conv; + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(gtkconv->active_conv); PurpleBuddyIcon *icon; const void *data; size_t len; - icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv)); + icon = purple_im_conversation_get_icon(im); data = purple_buddy_icon_get_data(icon, &len); if ((len <= 0) || (data == NULL) || !purple_util_write_data_to_file_absolute(filename, data, len)) { @@ -2849,7 +2807,7 @@ custom_icon_sel_cb(const char *filename, gpointer data) PurpleAccount *account = purple_conversation_get_account(conv); name = purple_conversation_get_name(conv); - buddy = purple_find_buddy(account, name); + buddy = purple_blist_find_buddy(account, name); if (!buddy) { purple_debug_info("custom-icon", "You can only set custom icons for people on your buddylist.\n"); return; @@ -2884,9 +2842,9 @@ change_size_cb(GtkWidget *widget, PidginConversation *gtkconv) } gtk_widget_set_size_request(gtkconv->u.im->icon_container, -1, size); - pidgin_conv_update_buddy_icon(conv); + pidgin_conv_update_buddy_icon(PURPLE_IM_CONVERSATION(conv)); - buddies = purple_find_buddies(purple_conversation_get_account(conv), + buddies = purple_blist_find_buddies(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); for (; buddies; buddies = g_slist_delete_link(buddies, buddies)) { PurpleBuddy *buddy = buddies->data; @@ -2906,7 +2864,7 @@ remove_custom_icon_cb(GtkWidget *widget, PidginConversation *gtkconv) account = purple_conversation_get_account(conv); name = purple_conversation_get_name(conv); - buddy = purple_find_buddy(account, name); + buddy = purple_blist_find_buddy(account, name); if (!buddy) { return; } @@ -2924,7 +2882,7 @@ icon_menu_save_cb(GtkWidget *widget, PidginConversation *gtkconv) g_return_if_fail(conv != NULL); - ext = purple_buddy_icon_get_extension(purple_conv_im_get_icon(PURPLE_CONV_IM(conv))); + ext = purple_buddy_icon_get_extension(purple_im_conversation_get_icon(PURPLE_IM_CONVERSATION(conv))); buf = g_strdup_printf("%s.%s", purple_normalize(purple_conversation_get_account(conv), purple_conversation_get_name(conv)), ext); @@ -3008,7 +2966,7 @@ icon_menu(GtkWidget *widget, GdkEventButton *e, PidginConversation *gtkconv) /* Is there a custom icon for this person? */ conv = gtkconv->active_conv; - buddy = purple_find_buddy(purple_conversation_get_account(conv), + buddy = purple_blist_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); if (buddy) { @@ -3046,24 +3004,15 @@ pidgin_conv_present_conversation(PurpleConversation *conv) gtk_window_present(GTK_WINDOW(gtkconv->win->window)); } -GList * -pidgin_conversations_find_unseen_list(PurpleConversationType type, - PidginUnseenState min_state, - gboolean hidden_only, - guint max_count) +static GList * +pidgin_conversations_get_unseen(GList *l, + PidginUnseenState min_state, + gboolean hidden_only, + guint max_count) { - GList *l; GList *r = NULL; guint c = 0; - if (type == PURPLE_CONV_TYPE_IM) { - l = purple_get_ims(); - } else if (type == PURPLE_CONV_TYPE_CHAT) { - l = purple_get_chats(); - } else { - l = purple_get_conversations(); - } - for (; l != NULL && (max_count == 0 || c < max_count); l = l->next) { PurpleConversation *conv = (PurpleConversation*)l->data; PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); @@ -3083,6 +3032,33 @@ pidgin_conversations_find_unseen_list(PurpleConversationType type, return r; } +GList * +pidgin_conversations_get_unseen_all(PidginUnseenState min_state, + gboolean hidden_only, + guint max_count) +{ + return pidgin_conversations_get_unseen(purple_conversations_get_all(), + min_state, hidden_only, max_count); +} + +GList * +pidgin_conversations_get_unseen_ims(PidginUnseenState min_state, + gboolean hidden_only, + guint max_count) +{ + return pidgin_conversations_get_unseen(purple_conversations_get_ims(), + min_state, hidden_only, max_count); +} + +GList * +pidgin_conversations_get_unseen_chats(PidginUnseenState min_state, + gboolean hidden_only, + guint max_count) +{ + return pidgin_conversations_get_unseen(purple_conversations_get_chats(), + min_state, hidden_only, max_count); +} + static void unseen_conv_menu_cb(GtkMenuItem *item, PurpleConversation *conv) { @@ -3283,7 +3259,7 @@ populate_menu_with_options(GtkWidget *menu, PidginConversation *gtkconv, gboolea conv = gtkconv->active_conv; account = purple_conversation_get_account(conv); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + if (PURPLE_IS_CHAT_CONVERSATION(conv)) { chat = purple_blist_find_chat(account, purple_conversation_get_name(conv)); if ((chat == NULL) && (gtkconv->webview != NULL)) { @@ -3306,8 +3282,7 @@ populate_menu_with_options(GtkWidget *menu, PidginConversation *gtkconv, gboolea g_strdup(purple_conversation_get_name(conv))); } chat = purple_chat_new(account, NULL, components); - purple_blist_node_set_flags((PurpleBlistNode *)chat, - PURPLE_BLIST_NODE_FLAG_NO_SAVE); + purple_blist_node_set_transient((PurpleBlistNode *)chat, TRUE); g_object_set_data_full(G_OBJECT(gtkconv->webview), "transient_chat", chat, (GDestroyNotify)purple_blist_remove_chat); } @@ -3315,16 +3290,15 @@ populate_menu_with_options(GtkWidget *menu, PidginConversation *gtkconv, gboolea if (!purple_account_is_connected(account)) return FALSE; - buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); + buddy = purple_blist_find_buddy(account, purple_conversation_get_name(conv)); if (!buddy && gtkconv->webview) { buddy = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_buddy"); if (!buddy) { buddy = purple_buddy_new(account, purple_conversation_get_name(conv), NULL); - purple_blist_node_set_flags((PurpleBlistNode *)buddy, - PURPLE_BLIST_NODE_FLAG_NO_SAVE); + purple_blist_node_set_transient((PurpleBlistNode *)buddy, TRUE); g_object_set_data_full(G_OBJECT(gtkconv->webview), "transient_buddy", - buddy, (GDestroyNotify)purple_buddy_destroy); + buddy, (GDestroyNotify)g_object_unref); } } } @@ -3383,8 +3357,7 @@ regenerate_media_items(PidginWindow *win) * Check if account support voice and/or calls, and * if the current buddy supports it. */ - if (account != NULL && purple_conversation_get_type(conv) - == PURPLE_CONV_TYPE_IM) { + if (account != NULL && PURPLE_IS_IM_CONVERSATION(conv)) { PurpleMediaCaps caps = purple_prpl_get_media_caps(account, purple_conversation_get_name(conv)); @@ -3398,8 +3371,7 @@ regenerate_media_items(PidginWindow *win) gtk_action_set_sensitive(win->menu.audio_video_call, caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO ? TRUE : FALSE); - } else if (purple_conversation_get_type(conv) - == PURPLE_CONV_TYPE_CHAT) { + } else if (PURPLE_IS_CHAT_CONVERSATION(conv)) { /* for now, don't care about chats... */ gtk_action_set_sensitive(win->menu.audio_call, FALSE); gtk_action_set_sensitive(win->menu.video_call, FALSE); @@ -3743,27 +3715,27 @@ static void got_typing_keypress(PidginConversation *gtkconv, gboolean first) { PurpleConversation *conv = gtkconv->active_conv; - PurpleConvIm *im; + PurpleIMConversation *im; /* * We know we got something, so we at least have to make sure we don't - * send PURPLE_TYPED any time soon. + * send PURPLE_IM_TYPED any time soon. */ im = PURPLE_CONV_IM(conv); - purple_conv_im_stop_send_typed_timeout(im); - purple_conv_im_start_send_typed_timeout(im); + purple_im_conversation_stop_send_typed_timeout(im); + purple_im_conversation_start_send_typed_timeout(im); - /* Check if we need to send another PURPLE_TYPING message */ - if (first || (purple_conv_im_get_type_again(im) != 0 && - time(NULL) > purple_conv_im_get_type_again(im))) + /* Check if we need to send another PURPLE_IM_TYPING message */ + if (first || (purple_im_conversation_get_type_again(im) != 0 && + time(NULL) > purple_im_conversation_get_type_again(im))) { unsigned int timeout; timeout = serv_send_typing(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), - PURPLE_TYPING); - purple_conv_im_set_type_again(im, timeout); + PURPLE_IM_TYPING); + purple_im_conversation_set_type_again(im, timeout); } } @@ -3850,17 +3822,13 @@ update_typing_message(PidginConversation *gtkconv, const char *message) static void update_typing_icon(PidginConversation *gtkconv) { - PurpleConvIm *im = NULL; - PurpleConversation *conv = gtkconv->active_conv; + PurpleIMConversation *im = PURPLE_IM_CONVERSATION(gtkconv->active_conv); char *message = NULL; - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) - im = PURPLE_CONV_IM(conv); - if (im == NULL) return; - if (purple_conv_im_get_typing_state(im) == PURPLE_NOT_TYPING) { + if (purple_im_conversation_get_typing_state(im) == PURPLE_IM_NOT_TYPING) { #ifdef RESERVE_LINE update_typing_message(gtkconv, NULL); #else @@ -3869,10 +3837,10 @@ update_typing_icon(PidginConversation *gtkconv) return; } - if (purple_conv_im_get_typing_state(im) == PURPLE_TYPING) { - message = g_strdup_printf(_("\n%s is typing..."), purple_conversation_get_title(conv)); + if (purple_im_conversation_get_typing_state(im) == PURPLE_IM_TYPING) { + message = g_strdup_printf(_("\n%s is typing..."), purple_conversation_get_title(PURPLE_CONVERSATION(im))); } else { - message = g_strdup_printf(_("\n%s has stopped typing"), purple_conversation_get_title(conv)); + message = g_strdup_printf(_("\n%s has stopped typing"), purple_conversation_get_title(PURPLE_CONVERSATION(im))); } update_typing_message(gtkconv, message); @@ -3901,7 +3869,7 @@ update_send_to_selection(PidginWindow *win) if (win->menu.send_to == NULL) return FALSE; - if (!(b = purple_find_buddy(account, purple_conversation_get_name(conv)))) + if (!(b = purple_blist_find_buddy(account, purple_conversation_get_name(conv)))) return FALSE; gtk_widget_show(win->menu.send_to); @@ -3917,7 +3885,7 @@ update_send_to_selection(PidginWindow *win) PurpleAccount *item_account = g_object_get_data(G_OBJECT(item), "purple_account"); gchar *buddy_name = g_object_get_data(G_OBJECT(item), "purple_buddy_name"); - item_buddy = purple_find_buddy(item_account, buddy_name); + item_buddy = purple_blist_find_buddy(item_account, buddy_name); if (b == item_buddy) { gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); @@ -4023,8 +3991,8 @@ compare_buddy_presence(PurplePresence *p1, PurplePresence *p2) /* This is necessary because multiple PurpleBuddy's don't share the same * PurplePresence anymore. */ - PurpleBuddy *b1 = purple_presence_get_buddy(p1); - PurpleBuddy *b2 = purple_presence_get_buddy(p2); + PurpleBuddy *b1 = purple_buddy_presence_get_buddy(PURPLE_BUDDY_PRESENCE(p1)); + PurpleBuddy *b2 = purple_buddy_presence_get_buddy(PURPLE_BUDDY_PRESENCE(p2)); if (purple_buddy_get_account(b1) == purple_buddy_get_account(b2) && strcmp(purple_buddy_get_name(b1), purple_buddy_get_name(b2)) == 0) return FALSE; @@ -4060,8 +4028,8 @@ generate_send_to_items(PidginWindow *win) gtk_widget_show(menu); - if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_IM) { - buds = purple_find_buddies(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv)); + if (PURPLE_IS_IM_CONVERSATION(gtkconv->active_conv)) { + buds = purple_blist_find_buddies(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv)); if (buds == NULL) { @@ -4081,7 +4049,7 @@ generate_send_to_items(PidginWindow *win) PurpleBuddy *buddy = (PurpleBuddy *)node; PurpleAccount *account; - if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (!PURPLE_IS_BUDDY(node)) continue; account = purple_buddy_get_account(buddy); @@ -4102,7 +4070,7 @@ generate_send_to_items(PidginWindow *win) * since we did a g_list_prepend() earlier. */ for (iter = g_list_last(list); iter != NULL; iter = iter->prev) { PurplePresence *pre = iter->data; - PurpleBuddy *buddy = purple_presence_get_buddy(pre); + PurpleBuddy *buddy = purple_buddy_presence_get_buddy(PURPLE_BUDDY_PRESENCE(pre)); create_sendto_item(menu, sg, &group, buddy, purple_buddy_get_account(buddy), purple_buddy_get_name(buddy)); } @@ -4122,19 +4090,19 @@ generate_send_to_items(PidginWindow *win) } static const char * -get_chat_buddy_status_icon(PurpleConvChat *chat, const char *name, PurpleConvChatBuddyFlags flags) +get_chat_user_status_icon(PurpleChatConversation *chat, const char *name, PurpleChatUserFlags flags) { const char *image = NULL; - if (flags & PURPLE_CBFLAGS_FOUNDER) { + if (flags & PURPLE_CHAT_USER_FOUNDER) { image = PIDGIN_STOCK_STATUS_FOUNDER; - } else if (flags & PURPLE_CBFLAGS_OP) { + } else if (flags & PURPLE_CHAT_USER_OP) { image = PIDGIN_STOCK_STATUS_OPERATOR; - } else if (flags & PURPLE_CBFLAGS_HALFOP) { + } else if (flags & PURPLE_CHAT_USER_HALFOP) { image = PIDGIN_STOCK_STATUS_HALFOP; - } else if (flags & PURPLE_CBFLAGS_VOICE) { + } else if (flags & PURPLE_CHAT_USER_VOICE) { image = PIDGIN_STOCK_STATUS_VOICE; - } else if ((!flags) && purple_conv_chat_is_user_ignored(chat, name)) { + } else if ((!flags) && purple_chat_conversation_is_ignored_user(chat, name)) { image = PIDGIN_STOCK_STATUS_IGNORED; } else { return NULL; @@ -4143,22 +4111,22 @@ get_chat_buddy_status_icon(PurpleConvChat *chat, const char *name, PurpleConvCha } static void -deleting_chat_buddy_cb(PurpleConvChatBuddy *cb) +deleting_chat_user_cb(PurpleChatUser *cb) { - GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb); + GtkTreeRowReference *ref = purple_chat_user_get_ui_data(cb); if (ref) { gtk_tree_row_reference_free(ref); - purple_conv_chat_cb_set_ui_data(cb, NULL); + purple_chat_user_set_ui_data(cb, NULL); } } static void -add_chat_buddy_common(PurpleConversation *conv, PurpleConvChatBuddy *cb, const char *old_name) +add_chat_user_common(PurpleChatConversation *chat, PurpleChatUser *cb, const char *old_name) { PidginConversation *gtkconv; + PurpleConversation *conv; PidginChatPane *gtkchat; - PurpleConvChat *chat; PurpleConnection *gc; PurplePluginProtocolInfo *prpl_info; GtkTreeModel *tm; @@ -4170,14 +4138,14 @@ add_chat_buddy_common(PurpleConversation *conv, PurpleConvChatBuddy *cb, const c gboolean is_buddy; const gchar *name, *alias; gchar *tmp, *alias_key; - PurpleConvChatBuddyFlags flags; + PurpleChatUserFlags flags; GdkColor *color = NULL; - alias = purple_conv_chat_cb_get_alias(cb); - name = purple_conv_chat_cb_get_name(cb); - flags = purple_conv_chat_cb_get_flags(cb); + alias = purple_chat_user_get_alias(cb); + name = purple_chat_user_get_name(cb); + flags = purple_chat_user_get_flags(cb); - chat = PURPLE_CONV_CHAT(conv); + conv = PURPLE_CONVERSATION(chat); gtkconv = PIDGIN_CONVERSATION(conv); gtkchat = gtkconv->u.chat; gc = purple_conversation_get_connection(conv); @@ -4188,12 +4156,12 @@ add_chat_buddy_common(PurpleConversation *conv, PurpleConvChatBuddy *cb, const c tm = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); ls = GTK_LIST_STORE(tm); - stock = get_chat_buddy_status_icon(chat, name, flags); + stock = get_chat_user_status_icon(chat, name, flags); - if (!strcmp(purple_conv_chat_get_nick(chat), purple_normalize(purple_conversation_get_account(conv), old_name != NULL ? old_name : name))) + if (!strcmp(purple_chat_conversation_get_nick(chat), purple_normalize(purple_conversation_get_account(conv), old_name != NULL ? old_name : name))) is_me = TRUE; - is_buddy = purple_conv_chat_cb_is_buddy(cb); + is_buddy = purple_chat_user_is_buddy(cb); tmp = g_utf8_casefold(alias, -1); alias_key = g_utf8_collate_key(tmp, -1); @@ -4209,9 +4177,9 @@ add_chat_buddy_common(PurpleConversation *conv, PurpleConvChatBuddy *cb, const c #endif /* if 0 */ } else { GtkTextTag *tag; - if ((tag = get_buddy_tag(conv, name, 0, FALSE))) + if ((tag = get_buddy_tag(chat, name, 0, FALSE))) g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL); - if ((tag = get_buddy_tag(conv, name, PURPLE_MESSAGE_NICK, FALSE))) + if ((tag = get_buddy_tag(chat, name, PURPLE_MESSAGE_NICK, FALSE))) g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL); color = (GdkColor*)get_nick_color(gtkconv, name); } @@ -4234,13 +4202,13 @@ add_chat_buddy_common(PurpleConversation *conv, PurpleConvChatBuddy *cb, const c CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -1); - if (purple_conv_chat_cb_get_ui_data(cb)) { - GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb); + if (purple_chat_user_get_ui_data(cb)) { + GtkTreeRowReference *ref = purple_chat_user_get_ui_data(cb); gtk_tree_row_reference_free(ref); } newpath = gtk_tree_model_get_path(tm, &iter); - purple_conv_chat_cb_set_ui_data(cb, gtk_tree_row_reference_new(tm, newpath)); + purple_chat_user_set_ui_data(cb, gtk_tree_row_reference_new(tm, newpath)); gtk_tree_path_free(newpath); if (is_me && color) @@ -4333,7 +4301,7 @@ tab_complete(PurpleConversation *conv) /* if there's nothing there just return */ if (!gtk_text_iter_compare(&cursor, &start_buffer)) - return (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) ? TRUE : FALSE; + return PURPLE_IS_CHAT_CONVERSATION(conv); text = gtk_text_buffer_get_text(gtkconv->entry_buffer, &start_buffer, &cursor, FALSE); @@ -4371,7 +4339,7 @@ tab_complete(PurpleConversation *conv) if (!g_utf8_strlen(entered, -1)) { g_free(entered); - return (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) ? TRUE : FALSE; + return PURPLE_IS_CHAT_CONVERSATION(conv); } nick_partial = g_malloc0(entered_bytes + 1); @@ -4386,9 +4354,9 @@ tab_complete(PurpleConversation *conv) &matches, l->data); } g_list_free(list); - } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { - PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); - GList *l = purple_conv_chat_get_users(chat); + } else if (PURPLE_IS_CHAT_CONVERSATION(conv)) { + PurpleChatConversation *chat = PURPLE_CONV_CHAT(conv); + GList *l = purple_chat_conversation_get_users(chat); GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(PIDGIN_CONVERSATION(conv)->u.chat->list)); GtkTreeIter iter; int f; @@ -4396,7 +4364,7 @@ tab_complete(PurpleConversation *conv) /* Users */ for (; l != NULL; l = l->next) { tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial, - &matches, purple_conv_chat_cb_get_name((PurpleConvChatBuddy *)l->data)); + &matches, purple_chat_user_get_name((PurpleChatUser *)l->data)); } @@ -4435,7 +4403,7 @@ tab_complete(PurpleConversation *conv) if (!matches) { /* if matches isn't set partials won't be either */ g_free(entered); - return (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) ? TRUE : FALSE; + return PURPLE_IS_CHAT_CONVERSATION(conv); } gtk_text_buffer_delete(gtkconv->entry_buffer, &word_start, &cursor); @@ -4505,7 +4473,7 @@ static void topic_callback(GtkWidget *w, PidginConversation *gtkconv) gtkconv = PIDGIN_CONVERSATION(conv); gtkchat = gtkconv->u.chat; new_topic = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtkchat->topic_text))); - current_topic = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(conv)); + current_topic = purple_chat_conversation_get_topic(PURPLE_CHAT_CONVERSATION(conv)); if(current_topic && !g_utf8_collate(new_topic, current_topic)){ g_free(new_topic); @@ -4517,7 +4485,7 @@ static void topic_callback(GtkWidget *w, PidginConversation *gtkconv) else gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text), ""); - prpl_info->set_chat_topic(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), + prpl_info->set_chat_topic(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)), new_topic); g_free(new_topic); @@ -4526,7 +4494,7 @@ static void topic_callback(GtkWidget *w, PidginConversation *gtkconv) static gint sort_chat_users(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata) { - PurpleConvChatBuddyFlags f1 = 0, f2 = 0; + PurpleChatUserFlags f1 = 0, f2 = 0; char *user1 = NULL, *user2 = NULL; gboolean buddy1 = FALSE, buddy2 = FALSE; gint ret = 0; @@ -4543,10 +4511,10 @@ sort_chat_users(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer us -1); /* Only sort by membership levels */ - f1 &= PURPLE_CBFLAGS_VOICE | PURPLE_CBFLAGS_HALFOP | PURPLE_CBFLAGS_OP | - PURPLE_CBFLAGS_FOUNDER; - f2 &= PURPLE_CBFLAGS_VOICE | PURPLE_CBFLAGS_HALFOP | PURPLE_CBFLAGS_OP | - PURPLE_CBFLAGS_FOUNDER; + f1 &= PURPLE_CHAT_USER_VOICE | PURPLE_CHAT_USER_HALFOP | PURPLE_CHAT_USER_OP | + PURPLE_CHAT_USER_FOUNDER; + f2 &= PURPLE_CHAT_USER_VOICE | PURPLE_CHAT_USER_HALFOP | PURPLE_CHAT_USER_OP | + PURPLE_CHAT_USER_FOUNDER; if (user1 == NULL || user2 == NULL) { if (!(user1 == NULL && user2 == NULL)) @@ -4567,18 +4535,17 @@ sort_chat_users(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer us } static void -update_chat_alias(PurpleBuddy *buddy, PurpleConversation *conv, PurpleConnection *gc, PurplePluginProtocolInfo *prpl_info) +update_chat_alias(PurpleBuddy *buddy, PurpleChatConversation *chat, PurpleConnection *gc, PurplePluginProtocolInfo *prpl_info) { - PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); - PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); - PurpleAccount *account = purple_conversation_get_account(conv); + PidginConversation *gtkconv = PIDGIN_CONVERSATION(PURPLE_CONVERSATION(chat)); + PurpleAccount *account = purple_conversation_get_account(PURPLE_CONVERSATION(chat)); GtkTreeModel *model; char *normalized_name; GtkTreeIter iter; int f; g_return_if_fail(buddy != NULL); - g_return_if_fail(conv != NULL); + g_return_if_fail(chat != NULL); /* This is safe because this callback is only used in chats, not IMs. */ model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkconv->u.chat->list)); @@ -4599,10 +4566,10 @@ update_chat_alias(PurpleBuddy *buddy, PurpleConversation *conv, PurpleConnection char *alias_key = NULL; PurpleBuddy *buddy2; - if (strcmp(purple_conv_chat_get_nick(chat), purple_normalize(account, name))) { + if (strcmp(purple_chat_conversation_get_nick(chat), purple_normalize(account, name))) { /* This user is not me, so look into updating the alias. */ - if ((buddy2 = purple_find_buddy(account, name)) != NULL) { + if ((buddy2 = purple_blist_find_buddy(account, name)) != NULL) { alias = purple_buddy_get_contact_alias(buddy2); } @@ -4629,10 +4596,11 @@ update_chat_alias(PurpleBuddy *buddy, PurpleConversation *conv, PurpleConnection } static void -blist_node_aliased_cb(PurpleBlistNode *node, const char *old_alias, PurpleConversation *conv) +blist_node_aliased_cb(PurpleBlistNode *node, const char *old_alias, PurpleChatConversation *chat) { PurpleConnection *gc; PurplePluginProtocolInfo *prpl_info; + PurpleConversation *conv = PURPLE_CONVERSATION(chat); g_return_if_fail(node != NULL); g_return_if_fail(conv != NULL); @@ -4645,21 +4613,21 @@ blist_node_aliased_cb(PurpleBlistNode *node, const char *old_alias, PurpleConver if (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME) return; - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + if (PURPLE_IS_CONTACT(node)) { PurpleBlistNode *bnode; for(bnode = node->child; bnode; bnode = bnode->next) { - if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + if(!PURPLE_IS_BUDDY(bnode)) continue; - update_chat_alias((PurpleBuddy *)bnode, conv, gc, prpl_info); + update_chat_alias((PurpleBuddy *)bnode, chat, gc, prpl_info); } } - else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) - update_chat_alias((PurpleBuddy *)node, conv, gc, prpl_info); - else if (PURPLE_BLIST_NODE_IS_CHAT(node) && + else if (PURPLE_IS_BUDDY(node)) + update_chat_alias((PurpleBuddy *)node, chat, gc, prpl_info); + else if (PURPLE_IS_CHAT(node) && purple_conversation_get_account(conv) == purple_chat_get_account((PurpleChat*)node)) { if (old_alias == NULL || g_utf8_collate(old_alias, purple_conversation_get_title(conv)) == 0) @@ -4668,12 +4636,13 @@ blist_node_aliased_cb(PurpleBlistNode *node, const char *old_alias, PurpleConver } static void -buddy_cb_common(PurpleBuddy *buddy, PurpleConversation *conv, gboolean is_buddy) +buddy_cb_common(PurpleBuddy *buddy, PurpleChatConversation *chat, gboolean is_buddy) { GtkTreeModel *model; char *normalized_name; GtkTreeIter iter; GtkTextTag *texttag; + PurpleConversation *conv = PURPLE_CONVERSATION(chat); int f; g_return_if_fail(buddy != NULL); @@ -4710,35 +4679,35 @@ buddy_cb_common(PurpleBuddy *buddy, PurpleConversation *conv, gboolean is_buddy) g_free(normalized_name); - blist_node_aliased_cb((PurpleBlistNode *)buddy, NULL, conv); + blist_node_aliased_cb((PurpleBlistNode *)buddy, NULL, chat); - texttag = get_buddy_tag(conv, purple_buddy_get_name(buddy), 0, FALSE); /* XXX: do we want the normalized name? */ + texttag = get_buddy_tag(chat, purple_buddy_get_name(buddy), 0, FALSE); /* XXX: do we want the normalized name? */ if (texttag) { g_object_set(texttag, "weight", is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, NULL); } } static void -buddy_added_cb(PurpleBlistNode *node, PurpleConversation *conv) +buddy_added_cb(PurpleBlistNode *node, PurpleChatConversation *chat) { - if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (!PURPLE_IS_BUDDY(node)) return; - buddy_cb_common(PURPLE_BUDDY(node), conv, TRUE); + buddy_cb_common(PURPLE_BUDDY(node), chat, TRUE); } static void -buddy_removed_cb(PurpleBlistNode *node, PurpleConversation *conv) +buddy_removed_cb(PurpleBlistNode *node, PurpleChatConversation *chat) { - if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (!PURPLE_IS_BUDDY(node)) return; /* If there's another buddy for the same "dude" on the list, do nothing. */ - if (purple_find_buddy(purple_buddy_get_account(PURPLE_BUDDY(node)), + if (purple_blist_find_buddy(purple_buddy_get_account(PURPLE_BUDDY(node)), purple_buddy_get_name(PURPLE_BUDDY(node))) != NULL) return; - buddy_cb_common(PURPLE_BUDDY(node), conv, FALSE); + buddy_cb_common(PURPLE_BUDDY(node), chat, FALSE); } static void @@ -4845,7 +4814,7 @@ minimum_entry_lines_pref_cb(const char *name, gconstpointer value, gpointer data) { - GList *l = purple_get_conversations(); + GList *l = purple_conversations_get_all(); PurpleConversation *conv; while (l != NULL) { @@ -4913,7 +4882,7 @@ pidgin_conv_userlist_create_tooltip(GtkWidget *tipwindow, GtkTreePath *path, gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1); prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(purple_account_get_connection(account))); - node = (PurpleBlistNode*)(purple_find_buddy(purple_conversation_get_account(conv), who)); + node = (PurpleBlistNode*)(purple_blist_find_buddy(purple_conversation_get_account(conv), who)); if (node && prpl_info && (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) pidgin_blist_draw_tooltip(node, gtkconv->infopane); @@ -5027,12 +4996,12 @@ pidgin_conv_create_tooltip(GtkWidget *tipwindow, gpointer userdata, int *w, int PidginConversation *gtkconv = userdata; conv = gtkconv->active_conv; - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + if (PURPLE_IS_CHAT_CONVERSATION(conv)) { node = (PurpleBlistNode*)(purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv))); if (!node) node = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_chat"); } else { - node = (PurpleBlistNode*)(purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv))); + node = (PurpleBlistNode*)(purple_blist_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv))); #if 0 /* Using the transient blist nodes to show the tooltip doesn't quite work yet. */ if (!node) @@ -5136,12 +5105,12 @@ replace_header_tokens(PurpleConversation *conv, const char *text) replace = purple_conversation_get_name(conv); } else if (g_str_has_prefix(cur, "%sourceName%")) { - replace = purple_account_get_alias(account); + replace = purple_account_get_private_alias(account); if (replace == NULL) replace = purple_account_get_username(account); } else if (g_str_has_prefix(cur, "%destinationName%")) { - PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); + PurpleBuddy *buddy = purple_blist_find_buddy(account, purple_conversation_get_name(conv)); if (buddy) { replace = purple_buddy_get_alias(buddy); } else { @@ -5149,7 +5118,7 @@ replace_header_tokens(PurpleConversation *conv, const char *text) } } else if (g_str_has_prefix(cur, "%incomingIconPath%")) { - PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv)); + PurpleBuddyIcon *icon = purple_im_conversation_get_icon(PURPLE_IM_CONVERSATION(conv)); if (icon) replace = purple_buddy_icon_get_full_path(icon); @@ -5335,7 +5304,7 @@ load_conv_theme(PidginConversation *gtkconv) webkit_web_view_load_string(WEBKIT_WEB_VIEW(gtkconv->webview), template, "text/html", "UTF-8", baseuri); - if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_CHAT) + if (PURPLE_IS_CHAT_CONVERSATION(gtkconv->active_conv)) gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), "document.getElementById('Chat').className = 'groupchat'"); @@ -5355,7 +5324,7 @@ setup_common_pane(PidginConversation *gtkconv) GtkTreePath *path; PurpleConversation *conv = gtkconv->active_conv; PurpleBuddy *buddy; - gboolean chat = (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT); + gboolean chat = PURPLE_IS_CHAT_CONVERSATION(conv); int buddyicon_size = 0; /* Setup the top part of the pane */ @@ -5404,7 +5373,7 @@ setup_common_pane(PidginConversation *gtkconv) else { gtkconv->u.im->icon_container = gtk_vbox_new(FALSE, 0); - if ((buddy = purple_find_buddy(purple_conversation_get_account(conv), + if ((buddy = purple_blist_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv))) != NULL) { PurpleContact *contact = purple_buddy_get_contact(buddy); if (contact) { @@ -5541,7 +5510,7 @@ conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, { PurpleConversation *conv = gtkconv->active_conv; PidginWindow *win = gtkconv->win; - PurpleConversation *c; + PurpleIMConversation *im; PurpleAccount *convaccount = purple_conversation_get_account(conv); PurpleConnection *gc = purple_account_get_connection(convaccount); PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL; @@ -5557,9 +5526,9 @@ conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, n = *(PurpleBlistNode **) data; - if (PURPLE_BLIST_NODE_IS_CONTACT(n)) + if (PURPLE_IS_CONTACT(n)) b = purple_contact_get_priority_buddy((PurpleContact*)n); - else if (PURPLE_BLIST_NODE_IS_BUDDY(n)) + else if (PURPLE_IS_BUDDY(n)) b = (PurpleBuddy*)n; else return; @@ -5570,29 +5539,29 @@ conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, * If a buddy is dragged to a chat window of the same protocol, * invite him to the chat. */ - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && + if (PURPLE_IS_CHAT_CONVERSATION(conv) && prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, chat_invite) && strcmp(purple_account_get_protocol_id(convaccount), purple_account_get_protocol_id(buddyaccount)) == 0) { - purple_conv_chat_invite_user(PURPLE_CONV_CHAT(conv), buddyname, NULL, TRUE); + purple_chat_conversation_invite_user(PURPLE_CHAT_CONVERSATION(conv), buddyname, NULL, TRUE); } else { /* * If we already have an open conversation with this buddy, then * just move the conv to this window. Otherwise, create a new * conv and add it to this window. */ - c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddyname, buddyaccount); - if (c != NULL) { + im = purple_conversations_find_im_with_account(buddyname, buddyaccount); + if (im != NULL) { PidginWindow *oldwin; - gtkconv = PIDGIN_CONVERSATION(c); + gtkconv = PIDGIN_CONVERSATION(PURPLE_CONVERSATION(im)); oldwin = gtkconv->win; if (oldwin != win) { pidgin_conv_window_remove_gtkconv(oldwin, gtkconv); pidgin_conv_window_add_gtkconv(win, gtkconv); } } else { - c = purple_conversation_new(PURPLE_CONV_TYPE_IM, buddyaccount, buddyname); - gtkconv = PIDGIN_CONVERSATION(c); + im = purple_im_conversation_new(buddyaccount, buddyname); + gtkconv = PIDGIN_CONVERSATION(PURPLE_CONVERSATION(im)); if (gtkconv->win != win) { pidgin_conv_window_remove_gtkconv(gtkconv->win, gtkconv); pidgin_conv_window_add_gtkconv(win, gtkconv); @@ -5626,13 +5595,13 @@ conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, * If a buddy is dragged to a chat window of the same protocol, * invite him to the chat. */ - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && + if (PURPLE_IS_CHAT_CONVERSATION(conv) && prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, chat_invite) && strcmp(purple_account_get_protocol_id(convaccount), protocol) == 0) { - purple_conv_chat_invite_user(PURPLE_CONV_CHAT(conv), username, NULL, TRUE); + purple_chat_conversation_invite_user(PURPLE_CHAT_CONVERSATION(conv), username, NULL, TRUE); } else { - c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, username); - gtkconv = PIDGIN_CONVERSATION(c); + im = purple_im_conversation_new(account, username); + gtkconv = PIDGIN_CONVERSATION(PURPLE_CONVERSATION(im)); if (gtkconv->win != win) { pidgin_conv_window_remove_gtkconv(gtkconv->win, gtkconv); pidgin_conv_window_add_gtkconv(win, gtkconv); @@ -5648,7 +5617,7 @@ conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); } else if (info == WEBKIT_WEB_VIEW_TARGET_INFO_URI_LIST) { - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) + if (PURPLE_IS_IM_CONVERSATION(conv)) pidgin_dnd_file_manage(sd, convaccount, purple_conversation_get_name(conv)); gtk_drag_finish(dc, TRUE, gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); @@ -5661,7 +5630,7 @@ conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, static PidginConversation * pidgin_conv_find_gtkconv(PurpleConversation * conv) { - PurpleBuddy *bud = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); + PurpleBuddy *bud = purple_blist_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); PurpleContact *c; PurpleBlistNode *cn, *bn; @@ -5674,10 +5643,10 @@ pidgin_conv_find_gtkconv(PurpleConversation * conv) cn = PURPLE_BLIST_NODE(c); for (bn = purple_blist_node_get_first_child(cn); bn; bn = purple_blist_node_get_sibling_next(bn)) { PurpleBuddy *b = PURPLE_BUDDY(bn); - PurpleConversation *conv; - if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(b), purple_buddy_get_account(b)))) { - if (PIDGIN_CONVERSATION(conv)) - return PIDGIN_CONVERSATION(conv); + PurpleIMConversation *im; + if ((im = purple_conversations_find_im_with_account(purple_buddy_get_name(b), purple_buddy_get_account(b)))) { + if (PIDGIN_CONVERSATION(PURPLE_CONVERSATION(im))) + return PIDGIN_CONVERSATION(PURPLE_CONVERSATION(im)); } } @@ -5690,7 +5659,7 @@ buddy_update_cb(PurpleBlistNode *bnode, gpointer null) GList *list; g_return_if_fail(bnode); - if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + if (!PURPLE_IS_BUDDY(bnode)) return; for (list = pidgin_conv_windows_get_list(); list; list = list->next) @@ -5698,7 +5667,7 @@ buddy_update_cb(PurpleBlistNode *bnode, gpointer null) PidginWindow *win = list->data; PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); - if (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_IM) + if (PURPLE_IS_CHAT_CONVERSATION(conv)) continue; pidgin_conv_update_fields(conv, PIDGIN_CONV_MENU); @@ -5763,13 +5732,13 @@ private_gtkconv_new(PurpleConversation *conv, gboolean hidden) PidginConversation *gtkconv; const char *theme_name; PurpleTheme *theme = NULL; - PurpleConversationType conv_type = purple_conversation_get_type(conv); + gboolean is_chat = PURPLE_IS_CHAT_CONVERSATION(conv); GtkWidget *pane = NULL; GtkWidget *tab_cont; PurpleBlistNode *convnode; GtkTargetList *targets; - if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) { + if (!is_chat && (gtkconv = pidgin_conv_find_gtkconv(conv))) { purple_conversation_set_ui_data(conv, gtkconv); if (!g_list_find(gtkconv->convs, conv)) gtkconv->convs = g_list_prepend(gtkconv->convs, conv); @@ -5795,17 +5764,17 @@ private_gtkconv_new(PurpleConversation *conv, gboolean hidden) gtkconv->last_flags = 0; - if (conv_type == PURPLE_CONV_TYPE_IM) { + if (!is_chat) { gtkconv->u.im = g_malloc0(sizeof(PidginImPane)); - } else if (conv_type == PURPLE_CONV_TYPE_CHAT) { + } else { gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane)); } pane = setup_common_pane(gtkconv); if (pane == NULL) { - if (conv_type == PURPLE_CONV_TYPE_CHAT) + if (is_chat) g_free(gtkconv->u.chat); - else if (conv_type == PURPLE_CONV_TYPE_IM) + else g_free(gtkconv->u.im); g_free(gtkconv); @@ -5901,7 +5870,7 @@ private_gtkconv_new(PurpleConversation *conv, gboolean hidden) gtkconv->nick_colors = g_array_ref(generated_nick_colors); } - if (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) + if (purple_conversation_get_features(conv) & PURPLE_CONNECTION_FLAG_ALLOW_CUSTOM_SMILEY) pidgin_themes_smiley_themeize_custom(gtkconv->entry); } @@ -5947,16 +5916,16 @@ received_im_msg_cb(PurpleAccount *account, char *sender, char *message, if (hide) { ui_ops->create_conversation = pidgin_conv_new_hidden; - purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender); + purple_im_conversation_new(account, sender); ui_ops->create_conversation = pidgin_conv_new; } /* Somebody wants to keep this conversation around, so don't time it out */ if (conv) { - timer = GPOINTER_TO_INT(purple_conversation_get_data(conv, "close-timer")); + timer = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "close-timer")); if (timer) { purple_timeout_remove(timer); - purple_conversation_set_data(conv, "close-timer", GINT_TO_POINTER(0)); + g_object_set_data(G_OBJECT(conv), "close-timer", GINT_TO_POINTER(0)); } } } @@ -5972,7 +5941,7 @@ pidgin_conv_destroy(PurpleConversation *conv) /* Make sure the destroyed conversation is not the active one */ if (gtkconv->active_conv == conv) { gtkconv->active_conv = gtkconv->convs->data; - purple_conversation_update(gtkconv->active_conv, PURPLE_CONV_UPDATE_FEATURES); + purple_conversation_update(gtkconv->active_conv, PURPLE_CONVERSATION_UPDATE_FEATURES); } return; } @@ -5986,7 +5955,7 @@ pidgin_conv_destroy(PurpleConversation *conv) gtk_widget_destroy(gtkconv->tab_cont); g_object_unref(gtkconv->tab_cont); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + if (PURPLE_IS_IM_CONVERSATION(conv)) { if (gtkconv->u.im->icon_timer != 0) g_source_remove(gtkconv->u.im->icon_timer); @@ -5997,7 +5966,7 @@ pidgin_conv_destroy(PurpleConversation *conv) g_source_remove(gtkconv->u.im->typing_timer); g_free(gtkconv->u.im); - } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + } else { purple_signals_disconnect_by_handle(gtkconv->u.chat); g_free(gtkconv->u.chat); } @@ -6021,11 +5990,12 @@ pidgin_conv_destroy(PurpleConversation *conv) static void -pidgin_conv_write_im(PurpleConversation *conv, const char *who, +pidgin_conv_write_im(PurpleIMConversation *im, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime) { PidginConversation *gtkconv; + PurpleConversation *conv = PURPLE_CONVERSATION(im); gtkconv = PIDGIN_CONVERSATION(conv); @@ -6033,7 +6003,7 @@ pidgin_conv_write_im(PurpleConversation *conv, const char *who, flags & PURPLE_MESSAGE_ACTIVE_ONLY) { /* Plugins that want these messages suppressed should be - * calling purple_conv_im_write(), so they get suppressed here, + * calling purple_im_conversation_write_message(), so they get suppressed here, * before being written to the log. */ purple_debug_info("gtkconv", "Suppressing message for an inactive conversation in pidgin_conv_write_im()\n"); @@ -6134,7 +6104,7 @@ static gboolean buddytag_event(GtkTextTag *tag, GObject *imhtml, } #endif -static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag, +static GtkTextTag *get_buddy_tag(PurpleChatConversation *chat, const char *who, PurpleMessageFlags flag, gboolean create) { /* TODO WEBKIT */ @@ -6161,7 +6131,7 @@ static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, Purp buddytag = gtk_text_buffer_create_tag( buffer, str, "foreground-gdk", get_nick_color(gtkconv, who), - "weight", purple_find_buddy(purple_conversation_get_account(conv), who) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, + "weight", purple_blist_find_buddy(purple_conversation_get_account(conv), who) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, NULL); g_object_set_data(G_OBJECT(buddytag), "cursor", ""); @@ -6308,7 +6278,7 @@ replace_message_tokens( replace = freeval = g_build_filename("Outgoing", "buddy_icon.png", NULL); } } else if (flags & PURPLE_MESSAGE_RECV) { - PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv)); + PurpleBuddyIcon *icon = purple_im_conversation_get_icon(PURPLE_IM_CONVERSATION(conv)); if (icon) replace = purple_buddy_icon_get_full_path(icon); if (replace == NULL || !g_file_test(replace, G_FILE_TEST_EXISTS)) { @@ -6391,7 +6361,6 @@ pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *a char *sml_attrib = NULL; size_t length; #endif - PurpleConversationType type; char *displaying; gboolean plugin_return; #if 0 @@ -6425,7 +6394,7 @@ pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *a { /* Unless this had PURPLE_MESSAGE_NO_LOG, this message * was logged. Plugin writers: if this isn't what - * you wanted, call purple_conv_im_write() instead of + * you wanted, call purple_im_conversation_write_message() instead of * purple_conversation_write(). */ purple_debug_info("gtkconv", "Suppressing message for an inactive conversation in pidgin_conv_write_conv()\n"); @@ -6438,7 +6407,6 @@ pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *a pidgin_conv_switch_active_conversation(conv); } - type = purple_conversation_get_type(conv); account = purple_conversation_get_account(conv); g_return_if_fail(account != NULL); gc = purple_account_get_connection(account); @@ -6451,7 +6419,7 @@ pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *a displaying = purple_markup_linkify(message); plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1( - pidgin_conversations_get_handle(), (type == PURPLE_CONV_TYPE_IM ? + pidgin_conversations_get_handle(), (PURPLE_IS_IM_CONVERSATION(conv) ? "displaying-im-msg" : "displaying-chat-msg"), account, name, &displaying, conv, flags)); if (plugin_return) @@ -6475,7 +6443,7 @@ pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *a } else if ((flags & PURPLE_MESSAGE_RECV) && (old_flags & PURPLE_MESSAGE_RECV)) { GList *history = purple_conversation_get_message_history(gtkconv->last_conversed); - PurpleConvMessage *last_msg = history ? (PurpleConvMessage *)history->data : NULL; + PurpleConversationMessage *last_msg = history ? (PurpleConversationMessage *)history->data : NULL; g_assert(history != NULL); g_assert(last_msg != NULL); @@ -6564,7 +6532,7 @@ pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *a gtk_font_options |= GTK_IMHTML_USE_POINTSIZE; } - if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) + if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_FLAG_ALLOW_CUSTOM_SMILEY)) { /* We want to see our own smileys. Need to revert it after send*/ pidgin_themes_smiley_themeize_custom(gtkconv->webview); @@ -6726,7 +6694,7 @@ pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *a } #if 0 - if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) + if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_FLAG_ALLOW_CUSTOM_SMILEY)) { /* Restore the smiley-data */ pidgin_themes_smiley_themeize(gtkconv->webview); @@ -6736,7 +6704,7 @@ pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *a /* on rejoin only request message history from after this message */ if (flags & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV) && - purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + PURPLE_IS_CHAT_CONVERSATION(conv)) { PurpleChat *chat = purple_blist_find_chat( purple_conversation_get_account(conv), purple_conversation_get_name(conv)); @@ -6775,13 +6743,13 @@ pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *a } purple_signal_emit(pidgin_conversations_get_handle(), - (type == PURPLE_CONV_TYPE_IM ? "displayed-im-msg" : "displayed-chat-msg"), + (PURPLE_IS_IM_CONVERSATION(conv) ? "displayed-im-msg" : "displayed-chat-msg"), account, name, displaying, conv, flags); g_free(displaying); update_typing_message(gtkconv, NULL); } -static gboolean get_iter_from_chatbuddy(PurpleConvChatBuddy *cb, GtkTreeIter *iter) +static gboolean get_iter_from_chatuser(PurpleChatUser *cb, GtkTreeIter *iter) { GtkTreeRowReference *ref; GtkTreePath *path; @@ -6789,7 +6757,7 @@ static gboolean get_iter_from_chatbuddy(PurpleConvChatBuddy *cb, GtkTreeIter *it g_return_val_if_fail(cb != NULL, FALSE); - ref = purple_conv_chat_cb_get_ui_data(cb); + ref = purple_chat_user_get_ui_data(cb); if (!ref) return FALSE; @@ -6807,9 +6775,8 @@ static gboolean get_iter_from_chatbuddy(PurpleConvChatBuddy *cb, GtkTreeIter *it } static void -pidgin_conv_chat_add_users(PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals) +pidgin_conv_chat_add_users(PurpleChatConversation *chat, GList *cbuddies, gboolean new_arrivals) { - PurpleConvChat *chat; PidginConversation *gtkconv; PidginChatPane *gtkchat; GtkListStore *ls; @@ -6818,11 +6785,10 @@ pidgin_conv_chat_add_users(PurpleConversation *conv, GList *cbuddies, gboolean n char tmp[BUF_LONG]; int num_users; - chat = PURPLE_CONV_CHAT(conv); - gtkconv = PIDGIN_CONVERSATION(conv); + gtkconv = PIDGIN_CONVERSATION(PURPLE_CONVERSATION(chat)); gtkchat = gtkconv->u.chat; - num_users = g_list_length(purple_conv_chat_get_users(chat)); + num_users = g_list_length(purple_chat_conversation_get_users(chat)); g_snprintf(tmp, sizeof(tmp), ngettext("%d person in room", "%d people in room", @@ -6838,7 +6804,7 @@ pidgin_conv_chat_add_users(PurpleConversation *conv, GList *cbuddies, gboolean n l = cbuddies; while (l != NULL) { - add_chat_buddy_common(conv, (PurpleConvChatBuddy *)l->data, NULL); + add_chat_user_common(chat, (PurpleChatUser *)l->data, NULL); l = l->next; } @@ -6850,19 +6816,17 @@ pidgin_conv_chat_add_users(PurpleConversation *conv, GList *cbuddies, gboolean n } static void -pidgin_conv_chat_rename_user(PurpleConversation *conv, const char *old_name, +pidgin_conv_chat_rename_user(PurpleChatConversation *chat, const char *old_name, const char *new_name, const char *new_alias) { - PurpleConvChat *chat; PidginConversation *gtkconv; PidginChatPane *gtkchat; - PurpleConvChatBuddy *old_cbuddy, *new_cbuddy; + PurpleChatUser *old_chatuser, *new_chatuser; GtkTreeIter iter; GtkTreeModel *model; GtkTextTag *tag; - chat = PURPLE_CONV_CHAT(conv); - gtkconv = PIDGIN_CONVERSATION(conv); + gtkconv = PIDGIN_CONVERSATION(PURPLE_CONVERSATION(chat)); gtkchat = gtkconv->u.chat; model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); @@ -6870,34 +6834,33 @@ pidgin_conv_chat_rename_user(PurpleConversation *conv, const char *old_name, if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) return; - if ((tag = get_buddy_tag(conv, old_name, 0, FALSE))) + if ((tag = get_buddy_tag(chat, old_name, 0, FALSE))) g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL); - if ((tag = get_buddy_tag(conv, old_name, PURPLE_MESSAGE_NICK, FALSE))) + if ((tag = get_buddy_tag(chat, old_name, PURPLE_MESSAGE_NICK, FALSE))) g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL); - old_cbuddy = purple_conv_chat_cb_find(chat, old_name); - if (!old_cbuddy) + old_chatuser = purple_chat_conversation_find_user(chat, old_name); + if (!old_chatuser) return; - if (get_iter_from_chatbuddy(old_cbuddy, &iter)) { - GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(old_cbuddy); + if (get_iter_from_chatuser(old_chatuser, &iter)) { + GtkTreeRowReference *ref = purple_chat_user_get_ui_data(old_chatuser); gtk_list_store_remove(GTK_LIST_STORE(model), &iter); gtk_tree_row_reference_free(ref); - purple_conv_chat_cb_set_ui_data(old_cbuddy, NULL); + purple_chat_user_set_ui_data(old_chatuser, NULL); } g_return_if_fail(new_alias != NULL); - new_cbuddy = purple_conv_chat_cb_find(chat, new_name); + new_chatuser = purple_chat_conversation_find_user(chat, new_name); - add_chat_buddy_common(conv, new_cbuddy, old_name); + add_chat_user_common(chat, new_chatuser, old_name); } static void -pidgin_conv_chat_remove_users(PurpleConversation *conv, GList *users) +pidgin_conv_chat_remove_users(PurpleChatConversation *chat, GList *users) { - PurpleConvChat *chat; PidginConversation *gtkconv; PidginChatPane *gtkchat; GtkTreeIter iter; @@ -6908,11 +6871,10 @@ pidgin_conv_chat_remove_users(PurpleConversation *conv, GList *users) gboolean f; GtkTextTag *tag; - chat = PURPLE_CONV_CHAT(conv); - gtkconv = PIDGIN_CONVERSATION(conv); + gtkconv = PIDGIN_CONVERSATION(PURPLE_CONVERSATION(chat)); gtkchat = gtkconv->u.chat; - num_users = g_list_length(purple_conv_chat_get_users(chat)); + num_users = g_list_length(purple_chat_conversation_get_users(chat)); for (l = users; l != NULL; l = l->next) { model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); @@ -6936,9 +6898,9 @@ pidgin_conv_chat_remove_users(PurpleConversation *conv, GList *users) g_free(val); } while (f); - if ((tag = get_buddy_tag(conv, l->data, 0, FALSE))) + if ((tag = get_buddy_tag(chat, l->data, 0, FALSE))) g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL); - if ((tag = get_buddy_tag(conv, l->data, PURPLE_MESSAGE_NICK, FALSE))) + if ((tag = get_buddy_tag(chat, l->data, PURPLE_MESSAGE_NICK, FALSE))) g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL); } @@ -6950,17 +6912,19 @@ pidgin_conv_chat_remove_users(PurpleConversation *conv, GList *users) } static void -pidgin_conv_chat_update_user(PurpleConversation *conv, const char *user) +pidgin_conv_chat_update_user(PurpleChatUser *chatuser) { - PurpleConvChat *chat; - PurpleConvChatBuddy *cbuddy; + PurpleChatConversation *chat; PidginConversation *gtkconv; PidginChatPane *gtkchat; GtkTreeIter iter; GtkTreeModel *model; - chat = PURPLE_CONV_CHAT(conv); - gtkconv = PIDGIN_CONVERSATION(conv); + if (!chatuser) + return; + + chat = purple_chat_user_get_chat(chatuser); + gtkconv = PIDGIN_CONVERSATION(PURPLE_CONVERSATION(chat)); gtkchat = gtkconv->u.chat; model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); @@ -6968,19 +6932,15 @@ pidgin_conv_chat_update_user(PurpleConversation *conv, const char *user) if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) return; - cbuddy = purple_conv_chat_cb_find(chat, user); - if (!cbuddy) - return; - - if (get_iter_from_chatbuddy(cbuddy, &iter)) { - GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cbuddy); + if (get_iter_from_chatuser(chatuser, &iter)) { + GtkTreeRowReference *ref = purple_chat_user_get_ui_data(chatuser); gtk_list_store_remove(GTK_LIST_STORE(model), &iter); gtk_tree_row_reference_free(ref); - purple_conv_chat_cb_set_ui_data(cbuddy, NULL); + purple_chat_user_set_ui_data(chatuser, NULL); } - if (cbuddy) - add_chat_buddy_common(conv, cbuddy, NULL); + if (chatuser) + add_chat_user_common(chat, chatuser, NULL); } gboolean @@ -7190,7 +7150,7 @@ gray_stuff_out(PidginConversation *gtkconv) * supports it or not--that only affects if the button or menu item * is sensitive or not. */ - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + if (PURPLE_IS_IM_CONVERSATION(conv)) { /* Show stuff that applies to IMs, hide stuff that applies to chats */ /* Deal with menu items */ @@ -7201,7 +7161,7 @@ gray_stuff_out(PidginConversation *gtkconv) gtk_action_set_visible(win->menu.get_info, TRUE); gtk_action_set_visible(win->menu.invite, FALSE); gtk_action_set_visible(win->menu.alias, TRUE); - if (purple_privacy_check(account, purple_conversation_get_name(conv))) { + if (purple_account_privacy_check(account, purple_conversation_get_name(conv))) { gtk_action_set_visible(win->menu.unblock, FALSE); gtk_action_set_visible(win->menu.block, TRUE); } else { @@ -7209,7 +7169,7 @@ gray_stuff_out(PidginConversation *gtkconv) gtk_action_set_visible(win->menu.unblock, TRUE); } - if (purple_find_buddy(account, purple_conversation_get_name(conv)) == NULL) { + if (purple_blist_find_buddy(account, purple_conversation_get_name(conv)) == NULL) { gtk_action_set_visible(win->menu.add, TRUE); gtk_action_set_visible(win->menu.remove, FALSE); } else { @@ -7219,7 +7179,7 @@ gray_stuff_out(PidginConversation *gtkconv) gtk_action_set_visible(win->menu.insert_link, TRUE); gtk_action_set_visible(win->menu.insert_image, TRUE); - } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + } else { /* Show stuff that applies to Chats, hide stuff that applies to IMs */ /* Deal with menu items */ @@ -7252,38 +7212,38 @@ gray_stuff_out(PidginConversation *gtkconv) * and what features that account supports. */ if ((gc != NULL) && - ((purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT) || - !purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)) )) + (PURPLE_IS_IM_CONVERSATION(conv) || + !purple_chat_conversation_has_left(PURPLE_CHAT_CONVERSATION(conv)) )) { PurpleConnectionFlags features = purple_conversation_get_features(conv); /* Account is online */ /* Deal with the toolbar */ - if (features & PURPLE_CONNECTION_HTML) + if (features & PURPLE_CONNECTION_FLAG_HTML) { buttons = GTK_WEBVIEW_ALL; /* Everything on */ - if (features & PURPLE_CONNECTION_NO_BGCOLOR) + if (features & PURPLE_CONNECTION_FLAG_NO_BGCOLOR) buttons &= ~GTK_WEBVIEW_BACKCOLOR; - if (features & PURPLE_CONNECTION_NO_FONTSIZE) + if (features & PURPLE_CONNECTION_FLAG_NO_FONTSIZE) { buttons &= ~GTK_WEBVIEW_GROW; buttons &= ~GTK_WEBVIEW_SHRINK; } - if (features & PURPLE_CONNECTION_NO_URLDESC) + if (features & PURPLE_CONNECTION_FLAG_NO_URLDESC) buttons &= ~GTK_WEBVIEW_LINKDESC; } else { buttons = GTK_WEBVIEW_SMILEY | GTK_WEBVIEW_IMAGE; } if (!(prpl_info->options & OPT_PROTO_IM_IMAGE) - && !(features & PURPLE_CONNECTION_NO_IMAGES)) { - features |= PURPLE_CONNECTION_NO_IMAGES; + && !(features & PURPLE_CONNECTION_FLAG_NO_IMAGES)) { + features |= PURPLE_CONNECTION_FLAG_NO_IMAGES; purple_conversation_set_features(conv, features); } - if (features & PURPLE_CONNECTION_NO_IMAGES) + if (features & PURPLE_CONNECTION_FLAG_NO_IMAGES) buttons &= ~GTK_WEBVIEW_IMAGE; - if (features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) + if (features & PURPLE_CONNECTION_FLAG_ALLOW_CUSTOM_SMILEY) buttons |= GTK_WEBVIEW_CUSTOM_SMILEY; else buttons &= ~GTK_WEBVIEW_CUSTOM_SMILEY; @@ -7297,10 +7257,10 @@ gray_stuff_out(PidginConversation *gtkconv) gtk_action_set_sensitive(win->menu.add_pounce, TRUE); gtk_action_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL)); gtk_action_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL)); - gtk_action_set_sensitive(win->menu.insert_link, (features & PURPLE_CONNECTION_HTML)); - gtk_action_set_sensitive(win->menu.insert_image, !(features & PURPLE_CONNECTION_NO_IMAGES)); + gtk_action_set_sensitive(win->menu.insert_link, (features & PURPLE_CONNECTION_FLAG_HTML)); + gtk_action_set_sensitive(win->menu.insert_image, !(features & PURPLE_CONNECTION_FLAG_NO_IMAGES)); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) + if (PURPLE_IS_IM_CONVERSATION(conv)) { gtk_action_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL)); gtk_action_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL)); @@ -7310,9 +7270,9 @@ gray_stuff_out(PidginConversation *gtkconv) gtk_action_set_sensitive(win->menu.get_attention, (prpl_info->send_attention != NULL)); gtk_action_set_sensitive(win->menu.alias, (account != NULL) && - (purple_find_buddy(account, purple_conversation_get_name(conv)) != NULL)); + (purple_blist_find_buddy(account, purple_conversation_get_name(conv)) != NULL)); } - else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) + else { gtk_action_set_sensitive(win->menu.add, (prpl_info->join_chat != NULL)); gtk_action_set_sensitive(win->menu.remove, (prpl_info->join_chat != NULL)); @@ -7345,10 +7305,10 @@ gray_stuff_out(PidginConversation *gtkconv) if (pidgin_conv_window_is_active_conversation(conv)) { GList *l = NULL; - if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) && + if (PURPLE_IS_IM_CONVERSATION(conv) && (gtkconv->u.im->anim)) { - PurpleBuddy *buddy = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); + PurpleBuddy *buddy = purple_blist_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); window_icon = gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim); @@ -7388,8 +7348,8 @@ pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields) if (fields & PIDGIN_CONV_BUDDY_ICON) { - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) - pidgin_conv_update_buddy_icon(conv); + if (PURPLE_IS_IM_CONVERSATION(conv)) + pidgin_conv_update_buddy_icon(PURPLE_IM_CONVERSATION(conv)); } if (fields & PIDGIN_CONV_MENU) @@ -7406,15 +7366,14 @@ pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields) } if ((fields & PIDGIN_CONV_TOPIC) && - purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) + PURPLE_IS_CHAT_CONVERSATION(conv)) { const char *topic; - PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); PidginChatPane *gtkchat = gtkconv->u.chat; if (gtkchat->topic_text != NULL) { - topic = purple_conv_chat_get_topic(chat); + topic = purple_chat_conversation_get_topic(PURPLE_CHAT_CONVERSATION(conv)); gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text), topic ? topic : ""); gtk_widget_set_tooltip_text(gtkchat->topic_text, @@ -7432,7 +7391,7 @@ pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields) (fields & PIDGIN_CONV_TOPIC)) { char *title; - PurpleConvIm *im = NULL; + PurpleIMConversation *im = NULL; PurpleAccount *account = purple_conversation_get_account(conv); PurpleBuddy *buddy = NULL; char *markup = NULL; @@ -7440,25 +7399,25 @@ pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields) /* I think this is a little longer than it needs to be but I'm lazy. */ char *style; - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) - im = PURPLE_CONV_IM(conv); + if (PURPLE_IS_IM_CONVERSATION(conv)) + im = PURPLE_IM_CONVERSATION(conv); if ((account == NULL) || !purple_account_is_connected(account) || - ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) - && purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)))) + (PURPLE_IS_CHAT_CONVERSATION(conv) + && purple_chat_conversation_has_left(PURPLE_CHAT_CONVERSATION(conv)))) title = g_strdup_printf("(%s)", purple_conversation_get_title(conv)); else title = g_strdup(purple_conversation_get_title(conv)); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); + if (PURPLE_IS_IM_CONVERSATION(conv)) { + buddy = purple_blist_find_buddy(account, purple_conversation_get_name(conv)); if (buddy) { markup = pidgin_blist_get_name_markup(buddy, FALSE, FALSE); } else { markup = title; } - } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + } else if (PURPLE_IS_CHAT_CONVERSATION(conv)) { const char *topic = gtkconv->u.chat->topic_text ? gtk_entry_get_text(GTK_ENTRY(gtkconv->u.chat->topic_text)) : NULL; @@ -7498,11 +7457,11 @@ pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields) accessibility_obj = gtk_widget_get_accessible(gtkconv->tab_cont); if (im != NULL && - purple_conv_im_get_typing_state(im) == PURPLE_TYPING) { + purple_im_conversation_get_typing_state(im) == PURPLE_IM_TYPING) { atk_object_set_description(accessibility_obj, _("Typing")); style = "tab-label-typing"; } else if (im != NULL && - purple_conv_im_get_typing_state(im) == PURPLE_TYPED) { + purple_im_conversation_get_typing_state(im) == PURPLE_IM_TYPED) { atk_object_set_description(accessibility_obj, _("Stopped Typing")); style = "tab-label-typed"; } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_NICK) { @@ -7510,7 +7469,7 @@ pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields) style = "tab-label-attention"; } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT) { atk_object_set_description(accessibility_obj, _("Unread Messages")); - if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_CHAT) + if (PURPLE_IS_CHAT_CONVERSATION(gtkconv->active_conv)) style = "tab-label-unreadchat"; else style = "tab-label-attention"; @@ -7553,46 +7512,46 @@ pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields) } static void -pidgin_conv_updated(PurpleConversation *conv, PurpleConvUpdateType type) +pidgin_conv_updated(PurpleConversation *conv, PurpleConversationUpdateType type) { PidginConvFields flags = 0; g_return_if_fail(conv != NULL); - if (type == PURPLE_CONV_UPDATE_ACCOUNT) + if (type == PURPLE_CONVERSATION_UPDATE_ACCOUNT) { flags = PIDGIN_CONV_ALL; } - else if (type == PURPLE_CONV_UPDATE_TYPING || - type == PURPLE_CONV_UPDATE_UNSEEN || - type == PURPLE_CONV_UPDATE_TITLE) + else if (type == PURPLE_CONVERSATION_UPDATE_TYPING || + type == PURPLE_CONVERSATION_UPDATE_UNSEEN || + type == PURPLE_CONVERSATION_UPDATE_TITLE) { flags = PIDGIN_CONV_COLORIZE_TITLE; } - else if (type == PURPLE_CONV_UPDATE_TOPIC) + else if (type == PURPLE_CONVERSATION_UPDATE_TOPIC) { flags = PIDGIN_CONV_TOPIC; } - else if (type == PURPLE_CONV_ACCOUNT_ONLINE || - type == PURPLE_CONV_ACCOUNT_OFFLINE) + else if (type == PURPLE_CONVERSATION_ACCOUNT_ONLINE || + type == PURPLE_CONVERSATION_ACCOUNT_OFFLINE) { flags = PIDGIN_CONV_MENU | PIDGIN_CONV_TAB_ICON | PIDGIN_CONV_SET_TITLE; } - else if (type == PURPLE_CONV_UPDATE_AWAY) + else if (type == PURPLE_CONVERSATION_UPDATE_AWAY) { flags = PIDGIN_CONV_TAB_ICON; } - else if (type == PURPLE_CONV_UPDATE_ADD || - type == PURPLE_CONV_UPDATE_REMOVE || - type == PURPLE_CONV_UPDATE_CHATLEFT) + else if (type == PURPLE_CONVERSATION_UPDATE_ADD || + type == PURPLE_CONVERSATION_UPDATE_REMOVE || + type == PURPLE_CONVERSATION_UPDATE_CHATLEFT) { flags = PIDGIN_CONV_SET_TITLE | PIDGIN_CONV_MENU; } - else if (type == PURPLE_CONV_UPDATE_ICON) + else if (type == PURPLE_CONVERSATION_UPDATE_ICON) { flags = PIDGIN_CONV_BUDDY_ICON; } - else if (type == PURPLE_CONV_UPDATE_FEATURES) + else if (type == PURPLE_CONVERSATION_UPDATE_FEATURES) { flags = PIDGIN_CONV_MENU; } @@ -7657,9 +7616,10 @@ pidgin_conversations_get_conv_ui_ops(void) * Public conversation utility functions **************************************************************************/ void -pidgin_conv_update_buddy_icon(PurpleConversation *conv) +pidgin_conv_update_buddy_icon(PurpleIMConversation *im) { PidginConversation *gtkconv; + PurpleConversation *conv; PidginWindow *win; PurpleBuddy *buddy; @@ -7680,9 +7640,10 @@ pidgin_conv_update_buddy_icon(PurpleConversation *conv) PurpleBuddyIcon *icon; + conv = PURPLE_CONVERSATION(im); + g_return_if_fail(conv != NULL); g_return_if_fail(PIDGIN_IS_PIDGIN_CONVERSATION(conv)); - g_return_if_fail(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM); gtkconv = PIDGIN_CONVERSATION(conv); win = gtkconv->win; @@ -7725,7 +7686,7 @@ pidgin_conv_update_buddy_icon(PurpleConversation *conv) if (purple_conversation_get_connection(conv) == NULL) return; - buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); + buddy = purple_blist_find_buddy(account, purple_conversation_get_name(conv)); if (buddy) { PurpleContact *contact = purple_buddy_get_contact(buddy); @@ -7740,7 +7701,7 @@ pidgin_conv_update_buddy_icon(PurpleConversation *conv) } if (data == NULL) { - icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv)); + icon = purple_im_conversation_get_icon(im); if (icon == NULL) { gtk_widget_set_size_request(gtkconv->u.im->icon_container, @@ -7934,7 +7895,7 @@ close_on_tabs_pref_cb(const char *name, PurplePrefType type, PurpleConversation *conv; PidginConversation *gtkconv; - for (l = purple_get_conversations(); l != NULL; l = l->next) { + for (l = purple_conversations_get_all(); l != NULL; l = l->next) { conv = (PurpleConversation *)l->data; if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv)) @@ -7957,7 +7918,7 @@ spellcheck_pref_cb(const char *name, PurplePrefType type, PurpleConversation *conv; PidginConversation *gtkconv; - for (cl = purple_get_conversations(); cl != NULL; cl = cl->next) { + for (cl = purple_conversations_get_all(); cl != NULL; cl = cl->next) { conv = (PurpleConversation *)cl->data; @@ -7999,7 +7960,7 @@ show_formatting_toolbar_pref_cb(const char *name, PurplePrefType type, PidginConversation *gtkconv; PidginWindow *win; - for (l = purple_get_conversations(); l != NULL; l = l->next) + for (l = purple_conversations_get_all(); l != NULL; l = l->next) { conv = (PurpleConversation *)l->data; @@ -8035,7 +7996,7 @@ animate_buddy_icons_pref_cb(const char *name, PurplePrefType type, return; /* Set the "animate" flag for each icon based on the new preference */ - for (l = purple_get_ims(); l != NULL; l = l->next) { + for (l = purple_conversations_get_ims(); l != NULL; l = l->next) { conv = (PurpleConversation *)l->data; gtkconv = PIDGIN_CONVERSATION(conv); if (gtkconv) @@ -8046,7 +8007,7 @@ animate_buddy_icons_pref_cb(const char *name, PurplePrefType type, for (l = pidgin_conv_windows_get_list(); l != NULL; l = l->next) { win = l->data; conv = pidgin_conv_window_get_active_conversation(win); - pidgin_conv_update_buddy_icon(conv); + pidgin_conv_update_buddy_icon(PURPLE_IM_CONVERSATION(conv)); } } @@ -8056,7 +8017,7 @@ show_buddy_icons_pref_cb(const char *name, PurplePrefType type, { GList *l; - for (l = purple_get_conversations(); l != NULL; l = l->next) { + for (l = purple_conversations_get_all(); l != NULL; l = l->next) { PurpleConversation *conv = l->data; if (!PIDGIN_CONVERSATION(conv)) continue; @@ -8065,8 +8026,8 @@ show_buddy_icons_pref_cb(const char *name, PurplePrefType type, else gtk_widget_hide(PIDGIN_CONVERSATION(conv)->infopane_hbox); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - pidgin_conv_update_buddy_icon(conv); + if (PURPLE_IS_IM_CONVERSATION(conv)) { + pidgin_conv_update_buddy_icon(PURPLE_IM_CONVERSATION(conv)); } } @@ -8084,7 +8045,7 @@ show_protocol_icons_pref_cb(const char *name, PurplePrefType type, gconstpointer value, gpointer data) { GList *l; - for (l = purple_get_conversations(); l != NULL; l = l->next) { + for (l = purple_conversations_get_all(); l != NULL; l = l->next) { PurpleConversation *conv = l->data; if (PIDGIN_CONVERSATION(conv)) update_tab_icon(conv); @@ -8117,7 +8078,7 @@ account_status_changed_cb(PurpleAccount *account, PurpleStatus *oldstatus, l = l->next; conv = gtkconv->active_conv; - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT || + if (PURPLE_IS_CHAT_CONVERSATION(conv) || account != purple_conversation_get_account(conv)) continue; @@ -8125,7 +8086,7 @@ account_status_changed_cb(PurpleAccount *account, PurpleStatus *oldstatus, /* TODO: do we need to do anything for any other conversations that are in the same gtkconv here? * I'm a little concerned that not doing so will cause the "pending" indicator in the gtkblist not to be cleared. -DAA*/ - purple_conversation_update(conv, PURPLE_CONV_UPDATE_UNSEEN); + purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_UNSEEN); } } @@ -8154,7 +8115,7 @@ hide_new_pref_cb(const char *name, PurplePrefType type, conv = gtkconv->active_conv; - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT || + if (PURPLE_IS_CHAT_CONVERSATION(conv) || gtkconv->unseen_count == 0 || (when_away && !purple_status_is_available( purple_account_get_active_status( @@ -8193,10 +8154,10 @@ get_gtkconv_with_contact(PurpleContact *contact) for (; node; node = node->next) { PurpleBuddy *buddy = (PurpleBuddy*)node; - PurpleConversation *conv; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); - if (conv) - return PIDGIN_CONVERSATION(conv); + PurpleIMConversation *im; + im = purple_conversations_find_im_with_account(purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); + if (im) + return PIDGIN_CONVERSATION(PURPLE_CONVERSATION(im)); } return NULL; } @@ -8206,7 +8167,7 @@ account_signed_off_cb(PurpleConnection *gc, gpointer event) { GList *iter; - for (iter = purple_get_conversations(); iter; iter = iter->next) + for (iter = purple_conversations_get_all(); iter; iter = iter->next) { PurpleConversation *conv = iter->data; @@ -8219,9 +8180,9 @@ account_signed_off_cb(PurpleConnection *gc, gpointer event) PIDGIN_CONV_MENU | PIDGIN_CONV_COLORIZE_TITLE); if (PURPLE_CONNECTION_IS_CONNECTED(gc) && - purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && + PURPLE_IS_CHAT_CONVERSATION(conv) && purple_conversation_get_account(conv) == purple_connection_get_account(gc) && - purple_conversation_get_data(conv, "want-to-rejoin")) { + g_object_get_data(G_OBJECT(conv), "want-to-rejoin")) { GHashTable *comps = NULL; PurpleChat *chat = purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); if (chat == NULL) { @@ -8242,16 +8203,16 @@ account_signed_off_cb(PurpleConnection *gc, gpointer event) static void account_signing_off(PurpleConnection *gc) { - GList *list = purple_get_chats(); + GList *list = purple_conversations_get_chats(); PurpleAccount *account = purple_connection_get_account(gc); /* We are about to sign off. See which chats we are currently in, and mark * them for rejoin on reconnect. */ while (list) { PurpleConversation *conv = list->data; - if (!purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)) && + if (!purple_chat_conversation_has_left(PURPLE_CHAT_CONVERSATION(conv)) && purple_conversation_get_account(conv) == account) { - purple_conversation_set_data(conv, "want-to-rejoin", GINT_TO_POINTER(TRUE)); + g_object_set_data(G_OBJECT(conv), "want-to-rejoin", GINT_TO_POINTER(TRUE)); purple_conversation_write(conv, NULL, _("The account has disconnected and you are no " "longer in this chat. You will automatically rejoin the chat when " "the account reconnects."), @@ -8295,21 +8256,21 @@ update_buddy_privacy_changed(PurpleBuddy *buddy) static void update_buddy_idle_changed(PurpleBuddy *buddy, gboolean old, gboolean newidle) { - PurpleConversation *conv; + PurpleIMConversation *im; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); - if (conv) - pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON); + im = purple_conversations_find_im_with_account(purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); + if (im) + pidgin_conv_update_fields(PURPLE_CONVERSATION(im), PIDGIN_CONV_TAB_ICON); } static void update_buddy_icon(PurpleBuddy *buddy) { - PurpleConversation *conv; + PurpleIMConversation *im; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); - if (conv) - pidgin_conv_update_fields(conv, PIDGIN_CONV_BUDDY_ICON); + im = purple_conversations_find_im_with_account(purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); + if (im) + pidgin_conv_update_fields(PURPLE_CONVERSATION(im), PIDGIN_CONV_BUDDY_ICON); } static void @@ -8343,7 +8304,7 @@ update_buddy_typing(PurpleAccount *account, const char *who) PurpleConversation *conv; PidginConversation *gtkconv; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account); + conv = PURPLE_CONVERSATION(purple_conversations_find_im_with_account(who, account)); if (!conv) return; @@ -8353,25 +8314,25 @@ update_buddy_typing(PurpleAccount *account, const char *who) } static void -update_chat(PurpleConversation *conv) +update_chat(PurpleChatConversation *chat) { - pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC | + pidgin_conv_update_fields(PURPLE_CONVERSATION(chat), PIDGIN_CONV_TOPIC | PIDGIN_CONV_MENU | PIDGIN_CONV_SET_TITLE); } static void -update_chat_topic(PurpleConversation *conv, const char *old, const char *new) +update_chat_topic(PurpleChatConversation *chat, const char *old, const char *new) { - pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC); + pidgin_conv_update_fields(PURPLE_CONVERSATION(chat), PIDGIN_CONV_TOPIC); } /* Message history stuff */ -/* Compare two PurpleConvMessage's, according to time in ascending order. */ +/* Compare two PurpleConversationMessage's, according to time in ascending order. */ static int message_compare(gconstpointer p1, gconstpointer p2) { - const PurpleConvMessage *m1 = p1, *m2 = p2; + const PurpleConversationMessage *m1 = p1, *m2 = p2; return (purple_conversation_message_get_timestamp(m1) > purple_conversation_message_get_timestamp(m2)); } @@ -8384,18 +8345,18 @@ add_message_history_to_gtkconv(gpointer data) int count = 0; int timer = gtkconv->attach.timer; time_t when = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkconv->entry), "attach-start-time")); - gboolean im = (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_IM); + gboolean im = (PURPLE_IS_IM_CONVERSATION(gtkconv->active_conv)); gtkconv->attach.timer = 0; while (gtkconv->attach.current && count < 100) { /* XXX: 100 is a random value here */ - PurpleConvMessage *msg = gtkconv->attach.current->data; + PurpleConversationMessage *msg = gtkconv->attach.current->data; if (!im && when && when < purple_conversation_message_get_timestamp(msg)) { gtk_webview_append_html(webview, "<BR><HR>"); gtk_webview_scroll_to_end(webview, TRUE); g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); } pidgin_conv_write_conv( - purple_conversation_message_get_conv(msg), + purple_conversation_message_get_conversation(msg), purple_conversation_message_get_sender(msg), purple_conversation_message_get_alias(msg), purple_conversation_message_get_message(msg), @@ -8422,16 +8383,16 @@ add_message_history_to_gtkconv(gpointer data) PurpleConversation *conv = iter->data; GList *history = purple_conversation_get_message_history(conv); for (; history; history = history->next) { - PurpleConvMessage *msg = history->data; + PurpleConversationMessage *msg = history->data; if (purple_conversation_message_get_timestamp(msg) > when) msgs = g_list_prepend(msgs, msg); } } msgs = g_list_sort(msgs, message_compare); for (; msgs; msgs = g_list_delete_link(msgs, msgs)) { - PurpleConvMessage *msg = msgs->data; + PurpleConversationMessage *msg = msgs->data; pidgin_conv_write_conv( - purple_conversation_message_get_conv(msg), + purple_conversation_message_get_conversation(msg), purple_conversation_message_get_sender(msg), purple_conversation_message_get_alias(msg), purple_conversation_message_get_message(msg), @@ -8453,15 +8414,15 @@ static void pidgin_conv_attach(PurpleConversation *conv) { int timer; - purple_conversation_set_data(conv, "unseen-count", NULL); - purple_conversation_set_data(conv, "unseen-state", NULL); + g_object_set_data(G_OBJECT(conv), "unseen-count", NULL); + g_object_set_data(G_OBJECT(conv), "unseen-state", NULL); purple_conversation_set_ui_ops(conv, pidgin_conversations_get_conv_ui_ops()); - if (!PIDGIN_CONVERSATION(conv)) - private_gtkconv_new(conv, FALSE); - timer = GPOINTER_TO_INT(purple_conversation_get_data(conv, "close-timer")); + purple_conversation_set_ui_data(conv, NULL); + private_gtkconv_new(conv, FALSE); + timer = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "close-timer")); if (timer) { purple_timeout_remove(timer); - purple_conversation_set_data(conv, "close-timer", NULL); + g_object_set_data(G_OBJECT(conv), "close-timer", NULL); } } @@ -8492,39 +8453,34 @@ gboolean pidgin_conv_attach_to_conversation(PurpleConversation *conv) list = purple_conversation_get_message_history(conv); if (list) { - switch (purple_conversation_get_type(conv)) { - case PURPLE_CONV_TYPE_IM: - { - GList *convs; - list = g_list_copy(list); - for (convs = purple_get_ims(); convs; convs = convs->next) - if (convs->data != conv && - pidgin_conv_find_gtkconv(convs->data) == gtkconv) { - pidgin_conv_attach(convs->data); - list = g_list_concat(list, g_list_copy(purple_conversation_get_message_history(convs->data))); - } - list = g_list_sort(list, message_compare); - gtkconv->attach.current = list; - list = g_list_last(list); - break; - } - case PURPLE_CONV_TYPE_CHAT: - gtkconv->attach.current = g_list_last(list); - break; - default: - g_return_val_if_reached(TRUE); + if (PURPLE_IS_IM_CONVERSATION(conv)) { + GList *convs; + list = g_list_copy(list); + for (convs = purple_conversations_get_ims(); convs; convs = convs->next) + if (convs->data != conv && + pidgin_conv_find_gtkconv(convs->data) == gtkconv) { + pidgin_conv_attach(convs->data); + list = g_list_concat(list, g_list_copy(purple_conversation_get_message_history(convs->data))); + } + list = g_list_sort(list, message_compare); + gtkconv->attach.current = list; + list = g_list_last(list); + } else { + gtkconv->attach.current = g_list_last(list); } + g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", - GINT_TO_POINTER(purple_conversation_message_get_timestamp((PurpleConvMessage*)(list->data)))); + GINT_TO_POINTER(purple_conversation_message_get_timestamp((PurpleConversationMessage*)(list->data)))); gtkconv->attach.timer = g_idle_add(add_message_history_to_gtkconv, gtkconv); } else { purple_signal_emit(pidgin_conversations_get_handle(), "conversation-displayed", gtkconv); } - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + if (PURPLE_IS_CHAT_CONVERSATION(conv)) { + PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(conv); pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC); - pidgin_conv_chat_add_users(conv, purple_conv_chat_get_users(PURPLE_CONV_CHAT(conv)), TRUE); + pidgin_conv_chat_add_users(chat, purple_chat_conversation_get_users(chat), TRUE); } return TRUE; @@ -8647,11 +8603,9 @@ pidgin_conversations_init(void) * Register signals **********************************************************************/ purple_signal_register(handle, "conversation-dragging", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_BOXED, - "PidginWindow *"), - purple_value_new(PURPLE_TYPE_BOXED, - "PidginWindow *")); + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + G_TYPE_POINTER, /* pointer to a (PidginWindow *) */ + G_TYPE_POINTER); /* pointer to a (PidginWindow *) */ purple_signal_register(handle, "conversation-timestamp", #if SIZEOF_TIME_T == 4 @@ -8661,90 +8615,58 @@ pidgin_conversations_init(void) #else #error Unkown size of time_t #endif - purple_value_new(PURPLE_TYPE_STRING), 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), + G_TYPE_STRING, 3, PURPLE_TYPE_CONVERSATION, #if SIZEOF_TIME_T == 4 - purple_value_new(PURPLE_TYPE_INT), + G_TYPE_INT, #elif SIZEOF_TIME_T == 8 - purple_value_new(PURPLE_TYPE_INT64), + G_TYPE_INT64, #else # error Unknown size of time_t #endif - purple_value_new(PURPLE_TYPE_BOOLEAN)); + G_TYPE_BOOLEAN); purple_signal_register(handle, "displaying-im-msg", purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_INT)); + G_TYPE_BOOLEAN, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_POINTER, /* pointer to a string */ + PURPLE_TYPE_CONVERSATION, G_TYPE_INT); purple_signal_register(handle, "displayed-im-msg", purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, - NULL, 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_INT)); + G_TYPE_NONE, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_STRING, PURPLE_TYPE_CONVERSATION, G_TYPE_INT); purple_signal_register(handle, "displaying-chat-msg", purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_INT)); + G_TYPE_BOOLEAN, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_POINTER, /* pointer to a string */ + PURPLE_TYPE_CONVERSATION, G_TYPE_INT); purple_signal_register(handle, "displayed-chat-msg", purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, - NULL, 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_INT)); + G_TYPE_NONE, 5, PURPLE_TYPE_ACCOUNT, G_TYPE_STRING, + G_TYPE_STRING, PURPLE_TYPE_CONVERSATION, G_TYPE_INT); purple_signal_register(handle, "conversation-switched", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION)); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + PURPLE_TYPE_CONVERSATION); purple_signal_register(handle, "conversation-hiding", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_BOXED, - "PidginConversation *")); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + G_TYPE_POINTER); /* (PidginConversation *) */ purple_signal_register(handle, "conversation-displayed", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_BOXED, - "PidginConversation *")); + purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, + G_TYPE_POINTER); /* (PidginConversation *) */ purple_signal_register(handle, "chat-nick-autocomplete", purple_marshal_BOOLEAN__POINTER_BOOLEAN, - purple_value_new(PURPLE_TYPE_BOOLEAN), 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION)); + G_TYPE_BOOLEAN, 1, PURPLE_TYPE_CONVERSATION); purple_signal_register(handle, "chat-nick-clicked", purple_marshal_BOOLEAN__POINTER_POINTER_UINT, - purple_value_new(PURPLE_TYPE_BOOLEAN), 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_UINT)); + G_TYPE_BOOLEAN, 3, PURPLE_TYPE_CONVERSATION, + G_TYPE_STRING, G_TYPE_UINT); /********************************************************************** @@ -8775,10 +8697,10 @@ pidgin_conversations_init(void) purple_signal_connect(purple_connections_get_handle(), "signed-on", handle, G_CALLBACK(account_signed_off_cb), - GINT_TO_POINTER(PURPLE_CONV_ACCOUNT_ONLINE)); + GINT_TO_POINTER(PURPLE_CONVERSATION_ACCOUNT_ONLINE)); purple_signal_connect(purple_connections_get_handle(), "signed-off", handle, G_CALLBACK(account_signed_off_cb), - GINT_TO_POINTER(PURPLE_CONV_ACCOUNT_OFFLINE)); + GINT_TO_POINTER(PURPLE_CONVERSATION_ACCOUNT_OFFLINE)); purple_signal_connect(purple_connections_get_handle(), "signing-off", handle, G_CALLBACK(account_signing_off), NULL); @@ -8787,8 +8709,8 @@ pidgin_conversations_init(void) purple_signal_connect(purple_conversations_get_handle(), "cleared-message-history", handle, G_CALLBACK(clear_conversation_scrollback_cb), NULL); - purple_signal_connect(purple_conversations_get_handle(), "deleting-chat-buddy", - handle, G_CALLBACK(deleting_chat_buddy_cb), NULL); + purple_signal_connect(purple_conversations_get_handle(), "deleting-chat-user", + handle, G_CALLBACK(deleting_chat_user_cb), NULL); purple_conversations_set_ui_ops(&conversation_ui_ops); @@ -9035,7 +8957,7 @@ close_win_cb(GtkWidget *w, GdkEventAny *e, gpointer d) l != NULL; l = l->next) { PidginConversation *gtkconv = l->data; - if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_IM && + if (PURPLE_IS_IM_CONVERSATION(gtkconv->active_conv) && gtkconv->unseen_state >= PIDGIN_UNSEEN_TEXT) { build_warn_close_dialog(win); @@ -9056,11 +8978,11 @@ conv_set_unseen(PurpleConversation *conv, PidginUnseenState state) int unseen_count = 0; PidginUnseenState unseen_state = PIDGIN_UNSEEN_NONE; - if(purple_conversation_get_data(conv, "unseen-count")) - unseen_count = GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count")); + if(g_object_get_data(G_OBJECT(conv), "unseen-count")) + unseen_count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "unseen-count")); - if(purple_conversation_get_data(conv, "unseen-state")) - unseen_state = GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-state")); + if(g_object_get_data(G_OBJECT(conv), "unseen-state")) + unseen_state = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "unseen-state")); if (state == PIDGIN_UNSEEN_NONE) { @@ -9076,10 +8998,10 @@ conv_set_unseen(PurpleConversation *conv, PidginUnseenState state) unseen_state = state; } - purple_conversation_set_data(conv, "unseen-count", GINT_TO_POINTER(unseen_count)); - purple_conversation_set_data(conv, "unseen-state", GINT_TO_POINTER(unseen_state)); + g_object_set_data(G_OBJECT(conv), "unseen-count", GINT_TO_POINTER(unseen_count)); + g_object_set_data(G_OBJECT(conv), "unseen-state", GINT_TO_POINTER(unseen_state)); - purple_conversation_update(conv, PURPLE_CONV_UPDATE_UNSEEN); + purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_UNSEEN); } static void @@ -9099,10 +9021,10 @@ gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state) gtkconv->unseen_state = state; } - purple_conversation_set_data(gtkconv->active_conv, "unseen-count", GINT_TO_POINTER(gtkconv->unseen_count)); - purple_conversation_set_data(gtkconv->active_conv, "unseen-state", GINT_TO_POINTER(gtkconv->unseen_state)); + g_object_set_data(G_OBJECT(gtkconv->active_conv), "unseen-count", GINT_TO_POINTER(gtkconv->unseen_count)); + g_object_set_data(G_OBJECT(gtkconv->active_conv), "unseen-state", GINT_TO_POINTER(gtkconv->unseen_state)); - purple_conversation_update(gtkconv->active_conv, PURPLE_CONV_UPDATE_UNSEEN); + purple_conversation_update(gtkconv->active_conv, PURPLE_CONVERSATION_UPDATE_UNSEEN); } /* @@ -9560,7 +9482,7 @@ before_switch_conv_cb(GtkNotebook *notebook, GtkWidget *page, gint page_num, g_return_if_fail(conv != NULL); - if (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_IM) + if (PURPLE_IS_CHAT_CONVERSATION(conv)) return; gtkconv = PIDGIN_CONVERSATION(conv); @@ -9778,14 +9700,14 @@ alias_cb(GtkEntry *entry, gpointer user_data) account = purple_conversation_get_account(conv); name = purple_conversation_get_name(conv); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + if (PURPLE_IS_IM_CONVERSATION(conv)) { PurpleBuddy *buddy; - buddy = purple_find_buddy(account, name); + buddy = purple_blist_find_buddy(account, name); if (buddy != NULL) { - purple_blist_alias_buddy(buddy, gtk_entry_get_text(entry)); + purple_buddy_set_local_alias(buddy, gtk_entry_get_text(entry)); } serv_alias_buddy(buddy); - } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + } else { gtk_entry_set_text(GTK_ENTRY(gtkconv->u.chat->topic_text), gtk_entry_get_text(entry)); topic_callback(NULL, gtkconv); } @@ -9809,14 +9731,14 @@ infopane_entry_activate(PidginConversation *gtkconv) return FALSE; } - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - PurpleBuddy *buddy = purple_find_buddy(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv)); + if (PURPLE_IS_IM_CONVERSATION(conv)) { + PurpleBuddy *buddy = purple_blist_find_buddy(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv)); if (!buddy) /* This buddy isn't in your buddy list, so we can't alias him */ return FALSE; text = purple_buddy_get_contact_alias(buddy); - } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + } else { PurpleConnection *gc; PurplePluginProtocolInfo *prpl_info = NULL; @@ -9827,7 +9749,7 @@ infopane_entry_activate(PidginConversation *gtkconv) /* This protocol doesn't support setting the chat room topic */ return FALSE; - text = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(conv)); + text = purple_chat_conversation_get_topic(PURPLE_CHAT_CONVERSATION(conv)); } /* alias label */ @@ -9904,7 +9826,7 @@ switch_conv_cb(GtkNotebook *notebook, GtkWidget *page, gint page_num, * We pause icons when they are not visible. If this icon should * be animated then start it back up again. */ - if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) && + if (PURPLE_IS_IM_CONVERSATION(conv) && (gtkconv->u.im->animate)) start_anim(NULL, gtkconv); @@ -10293,11 +10215,8 @@ pidgin_conv_window_add_gtkconv(PidginWindow *win, PidginConversation *gtkconv) PurpleConversation *conv = gtkconv->active_conv; PidginConversation *focus_gtkconv; GtkWidget *tab_cont = gtkconv->tab_cont; - PurpleConversationType conv_type; const gchar *tmp_lab; - conv_type = purple_conversation_get_type(conv); - win->gtkconvs = g_list_append(win->gtkconvs, gtkconv); gtkconv->win = win; @@ -10342,8 +10261,8 @@ pidgin_conv_window_add_gtkconv(PidginWindow *win, PidginConversation *gtkconv) gtk_widget_show(gtkconv->menu_tabby); - if (conv_type == PURPLE_CONV_TYPE_IM) - pidgin_conv_update_buddy_icon(conv); + if (PURPLE_IS_IM_CONVERSATION(conv)) + pidgin_conv_update_buddy_icon(PURPLE_IM_CONVERSATION(conv)); /* Build and set conversations tab */ pidgin_conv_tab_pack(win, gtkconv); @@ -10581,15 +10500,12 @@ pidgin_conv_window_get_gtkconv_count(PidginWindow *win) } PidginWindow * -pidgin_conv_window_first_with_type(PurpleConversationType type) +pidgin_conv_window_first_im(void) { GList *wins, *convs; PidginWindow *win; PidginConversation *conv; - if (type == PURPLE_CONV_TYPE_UNKNOWN) - return NULL; - for (wins = pidgin_conv_windows_get_list(); wins != NULL; wins = wins->next) { win = wins->data; @@ -10599,7 +10515,7 @@ pidgin_conv_window_first_with_type(PurpleConversationType type) conv = convs->data; - if (purple_conversation_get_type(conv->active_conv) == type) + if (PURPLE_IS_IM_CONVERSATION(conv->active_conv)) return win; } } @@ -10608,14 +10524,62 @@ pidgin_conv_window_first_with_type(PurpleConversationType type) } PidginWindow * -pidgin_conv_window_last_with_type(PurpleConversationType type) +pidgin_conv_window_last_im(void) { GList *wins, *convs; PidginWindow *win; PidginConversation *conv; - if (type == PURPLE_CONV_TYPE_UNKNOWN) - return NULL; + for (wins = g_list_last(pidgin_conv_windows_get_list()); + wins != NULL; + wins = wins->prev) { + + win = wins->data; + + for (convs = win->gtkconvs; + convs != NULL; + convs = convs->next) { + + conv = convs->data; + + if (PURPLE_IS_IM_CONVERSATION(conv->active_conv)) + return win; + } + } + + return NULL; +} + +PidginWindow * +pidgin_conv_window_first_chat(void) +{ + GList *wins, *convs; + PidginWindow *win; + PidginConversation *conv; + + for (wins = pidgin_conv_windows_get_list(); wins != NULL; wins = wins->next) { + win = wins->data; + + for (convs = win->gtkconvs; + convs != NULL; + convs = convs->next) { + + conv = convs->data; + + if (PURPLE_IS_CHAT_CONVERSATION(conv->active_conv)) + return win; + } + } + + return NULL; +} + +PidginWindow * +pidgin_conv_window_last_chat(void) +{ + GList *wins, *convs; + PidginWindow *win; + PidginConversation *conv; for (wins = g_list_last(pidgin_conv_windows_get_list()); wins != NULL; @@ -10629,7 +10593,7 @@ pidgin_conv_window_last_with_type(PurpleConversationType type) conv = convs->data; - if (purple_conversation_get_type(conv->active_conv) == type) + if (PURPLE_IS_CHAT_CONVERSATION(conv->active_conv)) return win; } } @@ -10680,7 +10644,6 @@ conv_placement_last_created_win_type_configured_cb(GtkWidget *w, GdkEventConfigure *event, PidginConversation *conv) { int x, y; - PurpleConversationType type = purple_conversation_get_type(conv->active_conv); GList *all; if (gtk_widget_get_visible(w)) @@ -10701,18 +10664,18 @@ conv_placement_last_created_win_type_configured_cb(GtkWidget *w, return FALSE; /* carry on normally */ for (all = conv->convs; all != NULL; all = all->next) { - if (type != purple_conversation_get_type(all->data)) { + if (PURPLE_IS_IM_CONVERSATION(conv->active_conv) != PURPLE_IS_IM_CONVERSATION(all->data)) { /* this window has different types of conversation, don't save */ return FALSE; } } - if (type == PURPLE_CONV_TYPE_IM) { + if (PURPLE_IS_IM_CONVERSATION(conv->active_conv)) { purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/x", x); purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/y", y); purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/width", event->width); purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/height", event->height); - } else if (type == PURPLE_CONV_TYPE_CHAT) { + } else { purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/x", x); purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/y", y); purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/width", event->width); @@ -10727,19 +10690,22 @@ conv_placement_last_created_win_type(PidginConversation *conv) { PidginWindow *win; - win = pidgin_conv_window_last_with_type(purple_conversation_get_type(conv->active_conv)); + if (PURPLE_IS_IM_CONVERSATION(conv->active_conv)) + win = pidgin_conv_window_last_im(); + else + win = pidgin_conv_window_last_chat(); if (win == NULL) { win = pidgin_conv_window_new(); - if (PURPLE_CONV_TYPE_IM == purple_conversation_get_type(conv->active_conv) || + if (PURPLE_IS_IM_CONVERSATION(conv->active_conv) || purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/width") == 0) { pidgin_conv_set_position_size(win, purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/x"), purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/y"), purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/width"), purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/height")); - } else if (PURPLE_CONV_TYPE_CHAT == purple_conversation_get_type(conv->active_conv)) { + } else if (PURPLE_IS_CHAT_CONVERSATION(conv->active_conv)) { pidgin_conv_set_position_size(win, purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/x"), purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/y"), @@ -10777,16 +10743,16 @@ conv_get_group(PidginConversation *conv) { PurpleGroup *group = NULL; - if (purple_conversation_get_type(conv->active_conv) == PURPLE_CONV_TYPE_IM) { + if (PURPLE_IS_IM_CONVERSATION(conv->active_conv)) { PurpleBuddy *buddy; - buddy = purple_find_buddy(purple_conversation_get_account(conv->active_conv), + buddy = purple_blist_find_buddy(purple_conversation_get_account(conv->active_conv), purple_conversation_get_name(conv->active_conv)); if (buddy != NULL) group = purple_buddy_get_group(buddy); - } else if (purple_conversation_get_type(conv->active_conv) == PURPLE_CONV_TYPE_CHAT) { + } else { PurpleChat *chat; chat = purple_blist_find_chat(purple_conversation_get_account(conv->active_conv), diff --git a/pidgin/gtkconv.h b/pidgin/gtkconv.h index f82eb7fc58..94d09bca4e 100644 --- a/pidgin/gtkconv.h +++ b/pidgin/gtkconv.h @@ -178,7 +178,7 @@ PurpleTheme *pidgin_conversations_get_default_theme(void); * * @param conv The conversation. */ -void pidgin_conv_update_buddy_icon(PurpleConversation *conv); +void pidgin_conv_update_buddy_icon(PurpleIMConversation *im); /** * Sets the active conversation within a GTK-conversation. @@ -195,14 +195,13 @@ void pidgin_conv_switch_active_conversation(PurpleConversation *conv); void pidgin_conv_update_buttons_by_protocol(PurpleConversation *conv); /** - * Returns a list of conversations of the given type which have an unseen + * Returns a list of conversations of any type which have an unseen * state greater than or equal to the specified minimum state. Using the * hidden_only parameter, this search can be limited to hidden * conversations. The max_count parameter will limit the total number of * converations returned if greater than zero. The returned list should * be freed by the caller. * - * @param type The type of conversation. * @param min_state The minimum unseen state. * @param hidden_only If TRUE, only consider hidden conversations. * @param max_count Maximum number of conversations to return, or 0 for @@ -210,8 +209,47 @@ void pidgin_conv_update_buttons_by_protocol(PurpleConversation *conv); * @return List of PurpleConversation matching criteria, or NULL. */ GList * -pidgin_conversations_find_unseen_list(PurpleConversationType type, - PidginUnseenState min_state, +pidgin_conversations_get_unseen_all(PidginUnseenState min_state, + gboolean hidden_only, + guint max_count); + +/** + * Returns a list of IM conversations which have an unseen state greater + * than or equal to the specified minimum state. Using the hidden_only + * parameter, this search can be limited to hidden IM conversations. The + * max_count parameter will limit the total number of IM converations + * returned if greater than zero. The returned list should be freed by the + * caller. + * + * @param min_state The minimum unseen state. + * @param hidden_only If TRUE, only consider hidden conversations. + * @param max_count Maximum number of conversations to return, or 0 for + * no maximum. + * @return List of PurpleIMConversation matching criteria, + * or NULL. + */ +GList * +pidgin_conversations_get_unseen_ims(PidginUnseenState min_state, + gboolean hidden_only, + guint max_count); + +/** + * Returns a list of chat conversations which have an unseen state greater + * than or equal to the specified minimum state. Using the hidden_only + * parameter, this search can be limited to hidden chat conversations. The + * max_count parameter will limit the total number of chat converations + * returned if greater than zero. The returned list should be freed by the + * caller. + * + * @param min_state The minimum unseen state. + * @param hidden_only If TRUE, only consider hidden conversations. + * @param max_count Maximum number of conversations to return, or 0 for + * no maximum. + * @return List of PurpleChatConversation matching criteria, + * or NULL. + */ +GList * +pidgin_conversations_get_unseen_chats(PidginUnseenState min_state, gboolean hidden_only, guint max_count); diff --git a/pidgin/gtkconvwin.h b/pidgin/gtkconvwin.h index 078c47f3ae..6b192cbcba 100644 --- a/pidgin/gtkconvwin.h +++ b/pidgin/gtkconvwin.h @@ -123,8 +123,10 @@ PidginWindow *pidgin_conv_window_get_at_event(GdkEvent *event); GList *pidgin_conv_window_get_gtkconvs(PidginWindow *win); guint pidgin_conv_window_get_gtkconv_count(PidginWindow *win); -PidginWindow *pidgin_conv_window_first_with_type(PurpleConversationType type); -PidginWindow *pidgin_conv_window_last_with_type(PurpleConversationType type); +PidginWindow *pidgin_conv_window_first_im(void); +PidginWindow *pidgin_conv_window_last_im(void); +PidginWindow *pidgin_conv_window_first_chat(void); +PidginWindow *pidgin_conv_window_last_chat(void); /*@}*/ diff --git a/pidgin/gtkdialogs.c b/pidgin/gtkdialogs.c index afac1a3d3c..d175f34577 100644 --- a/pidgin/gtkdialogs.c +++ b/pidgin/gtkdialogs.c @@ -938,7 +938,7 @@ pidgin_dialogs_im(void) purple_request_field_set_required(field, TRUE); purple_request_field_group_add_field(group, field); - purple_request_fields(purple_get_blist(), _("New Instant Message"), + purple_request_fields(purple_blist_get_buddy_list(), _("New Instant Message"), NULL, _("Please enter the username or alias of the person " "you would like to IM."), @@ -952,18 +952,18 @@ pidgin_dialogs_im(void) void pidgin_dialogs_im_with_user(PurpleAccount *account, const char *username) { - PurpleConversation *conv; + PurpleIMConversation *im; g_return_if_fail(account != NULL); g_return_if_fail(username != NULL); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, account); + im = purple_conversations_find_im_with_account(username, account); - if (conv == NULL) - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, username); + if (im == NULL) + im = purple_im_conversation_new(account, username); - pidgin_conv_attach_to_conversation(conv); - purple_conversation_present(conv); + pidgin_conv_attach_to_conversation(PURPLE_CONVERSATION(im)); + purple_conversation_present(PURPLE_CONVERSATION(im)); } static gboolean @@ -1078,7 +1078,7 @@ pidgin_dialogs_info(void) purple_request_field_set_required(field, TRUE); purple_request_field_group_add_field(group, field); - purple_request_fields(purple_get_blist(), _("Get User Info"), + purple_request_fields(purple_blist_get_buddy_list(), _("Get User Info"), NULL, _("Please enter the username or alias of the person " "whose info you would like to view."), @@ -1108,7 +1108,7 @@ pidgin_dialogs_log_cb(gpointer data, PurpleRequestFields *fields) pidgin_set_cursor(gtkblist->window, GDK_WATCH); - buddies = purple_find_buddies(account, username); + buddies = purple_blist_find_buddies(account, username); for (cur = buddies; cur != NULL; cur = cur->next) { PurpleBlistNode *node = cur->data; @@ -1170,7 +1170,7 @@ pidgin_dialogs_log(void) purple_request_field_set_required(field, TRUE); purple_request_field_group_add_field(group, field); - purple_request_fields(purple_get_blist(), _("View User Log"), + purple_request_fields(purple_blist_get_buddy_list(), _("View User Log"), NULL, _("Please enter the username or alias of the person " "whose log you would like to view."), @@ -1184,7 +1184,7 @@ pidgin_dialogs_log(void) static void pidgin_dialogs_alias_buddy_cb(PurpleBuddy *buddy, const char *new_alias) { - purple_blist_alias_buddy(buddy, new_alias); + purple_buddy_set_local_alias(buddy, new_alias); serv_alias_buddy(buddy); } @@ -1198,7 +1198,7 @@ pidgin_dialogs_alias_buddy(PurpleBuddy *buddy) secondary = g_strdup_printf(_("Enter an alias for %s."), purple_buddy_get_name(buddy)); purple_request_input(NULL, _("Alias Buddy"), NULL, - secondary, purple_buddy_get_local_buddy_alias(buddy), FALSE, FALSE, NULL, + secondary, purple_buddy_get_local_alias(buddy), FALSE, FALSE, NULL, _("Alias"), G_CALLBACK(pidgin_dialogs_alias_buddy_cb), _("Cancel"), NULL, purple_buddy_get_account(buddy), purple_buddy_get_name(buddy), NULL, @@ -1210,17 +1210,21 @@ pidgin_dialogs_alias_buddy(PurpleBuddy *buddy) static void pidgin_dialogs_alias_chat_cb(PurpleChat *chat, const char *new_alias) { - purple_blist_alias_chat(chat, new_alias); + purple_chat_set_alias(chat, new_alias); } void pidgin_dialogs_alias_chat(PurpleChat *chat) { + gchar *alias; + g_return_if_fail(chat != NULL); + g_object_get(chat, "alias", &alias, NULL); + purple_request_input(NULL, _("Alias Chat"), NULL, _("Enter an alias for this chat."), - chat->alias, FALSE, FALSE, NULL, + alias, FALSE, FALSE, NULL, _("Alias"), G_CALLBACK(pidgin_dialogs_alias_chat_cb), _("Cancel"), NULL, purple_chat_get_account(chat), NULL, NULL, @@ -1256,6 +1260,7 @@ pidgin_dialogs_remove_contact(PurpleContact *contact) pidgin_dialogs_remove_buddy(buddy); } else { gchar *text; + int contact_size = purple_counting_node_get_total_size(PURPLE_COUNTING_NODE(contact)); text = g_strdup_printf( ngettext( "You are about to remove the contact containing %s " @@ -1263,8 +1268,8 @@ pidgin_dialogs_remove_contact(PurpleContact *contact) "want to continue?", "You are about to remove the contact containing %s " "and %d other buddies from your buddy list. Do you " - "want to continue?", purple_contact_get_contact_size(contact, TRUE) - 1), - purple_buddy_get_name(buddy), purple_contact_get_contact_size(contact, TRUE) - 1); + "want to continue?", contact_size - 1), + purple_buddy_get_name(buddy), contact_size - 1); purple_request_action(contact, NULL, _("Remove Contact"), text, 0, NULL, purple_contact_get_alias(contact), NULL, @@ -1286,7 +1291,7 @@ static void free_ggmo(struct _PidginGroupMergeObject *ggp) static void pidgin_dialogs_merge_groups_cb(struct _PidginGroupMergeObject *GGP) { - purple_blist_rename_group(GGP->parent, GGP->new_name); + purple_group_set_name(GGP->parent, GGP->new_name); free_ggmo(GGP); } @@ -1324,12 +1329,12 @@ pidgin_dialogs_remove_group_cb(PurpleGroup *group) cnode = ((PurpleBlistNode*)group)->child; while (cnode) { - if (PURPLE_BLIST_NODE_IS_CONTACT(cnode)) { + if (PURPLE_IS_CONTACT(cnode)) { bnode = cnode->child; cnode = cnode->next; while (bnode) { PurpleBuddy *buddy; - if (PURPLE_BLIST_NODE_IS_BUDDY(bnode)) { + if (PURPLE_IS_BUDDY(bnode)) { buddy = (PurpleBuddy*)bnode; bnode = bnode->next; if (purple_account_is_connected(purple_buddy_get_account(buddy))) { @@ -1340,7 +1345,7 @@ pidgin_dialogs_remove_group_cb(PurpleGroup *group) bnode = bnode->next; } } - } else if (PURPLE_BLIST_NODE_IS_CHAT(cnode)) { + } else if (PURPLE_IS_CHAT(cnode)) { PurpleChat *chat = (PurpleChat *)cnode; cnode = cnode->next; if (purple_account_is_connected(purple_chat_get_account(chat))) diff --git a/pidgin/gtkdocklet.c b/pidgin/gtkdocklet.c index e5ec27b0d8..5033cab1d8 100644 --- a/pidgin/gtkdocklet.c +++ b/pidgin/gtkdocklet.c @@ -132,15 +132,13 @@ get_pending_list(guint max) { GList *l_im, *l_chat; - l_im = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_IM, - PIDGIN_UNSEEN_TEXT, - FALSE, max); + l_im = pidgin_conversations_get_unseen_ims(PIDGIN_UNSEEN_TEXT, FALSE, max); /* Short circuit if we have our information already */ if (max == 1 && l_im != NULL) return l_im; - l_chat = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_CHAT, + l_chat = pidgin_conversations_get_unseen_chats( purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/notification_chat"), FALSE, max); @@ -202,8 +200,8 @@ docklet_update_status(void) } else { g_string_append_printf(tooltip_text, ngettext("%d unread message from %s\n", "%d unread messages from %s\n", - GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count"))), - GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count")), + GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "unseen-count"))), + GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "unseen-count")), purple_conversation_get_title(conv)); } } @@ -289,9 +287,9 @@ docklet_update_status_cb(void *data) } static void -docklet_conv_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type) +docklet_conv_updated_cb(PurpleConversation *conv, PurpleConversationUpdateType type) { - if (type == PURPLE_CONV_UPDATE_UNSEEN) + if (type == PURPLE_CONVERSATION_UPDATE_UNSEEN) docklet_update_status(); } diff --git a/pidgin/gtkimhtml.c b/pidgin/gtkimhtml.c index 40288e62cd..0599c456cf 100644 --- a/pidgin/gtkimhtml.c +++ b/pidgin/gtkimhtml.c @@ -5713,20 +5713,20 @@ void gtk_imhtml_setup_entry(GtkIMHtml *imhtml, PurpleConnectionFlags flags) { GtkIMHtmlButtons buttons; - if (flags & PURPLE_CONNECTION_HTML) { + if (flags & PURPLE_CONNECTION_FLAG_HTML) { char color[8]; GdkColor fg_color, bg_color; buttons = GTK_IMHTML_ALL; - if (flags & PURPLE_CONNECTION_NO_BGCOLOR) + if (flags & PURPLE_CONNECTION_FLAG_NO_BGCOLOR) buttons &= ~GTK_IMHTML_BACKCOLOR; - if (flags & PURPLE_CONNECTION_NO_FONTSIZE) + if (flags & PURPLE_CONNECTION_FLAG_NO_FONTSIZE) { buttons &= ~GTK_IMHTML_GROW; buttons &= ~GTK_IMHTML_SHRINK; } - if (flags & PURPLE_CONNECTION_NO_URLDESC) + if (flags & PURPLE_CONNECTION_FLAG_NO_URLDESC) buttons &= ~GTK_IMHTML_LINKDESC; gtk_imhtml_set_format_functions(imhtml, GTK_IMHTML_ALL); @@ -5742,7 +5742,7 @@ void gtk_imhtml_setup_entry(GtkIMHtml *imhtml, PurpleConnectionFlags flags) gtk_imhtml_toggle_fontface(imhtml, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/font_face")); - if (!(flags & PURPLE_CONNECTION_NO_FONTSIZE)) + if (!(flags & PURPLE_CONNECTION_FLAG_NO_FONTSIZE)) { int size = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/font_size"); @@ -5764,7 +5764,7 @@ void gtk_imhtml_setup_entry(GtkIMHtml *imhtml, PurpleConnectionFlags flags) gtk_imhtml_toggle_forecolor(imhtml, color); - if(!(flags & PURPLE_CONNECTION_NO_BGCOLOR) && + if(!(flags & PURPLE_CONNECTION_FLAG_NO_BGCOLOR) && strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"), "") != 0) { gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"), @@ -5778,7 +5778,7 @@ void gtk_imhtml_setup_entry(GtkIMHtml *imhtml, PurpleConnectionFlags flags) gtk_imhtml_toggle_background(imhtml, color); - if (flags & PURPLE_CONNECTION_FORMATTING_WBFO) + if (flags & PURPLE_CONNECTION_FLAG_FORMATTING_WBFO) gtk_imhtml_set_whole_buffer_formatting_only(imhtml, TRUE); else gtk_imhtml_set_whole_buffer_formatting_only(imhtml, FALSE); @@ -5787,10 +5787,10 @@ void gtk_imhtml_setup_entry(GtkIMHtml *imhtml, PurpleConnectionFlags flags) imhtml_clear_formatting(imhtml); } - if (flags & PURPLE_CONNECTION_NO_IMAGES) + if (flags & PURPLE_CONNECTION_FLAG_NO_IMAGES) buttons &= ~GTK_IMHTML_IMAGE; - if (flags & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) + if (flags & PURPLE_CONNECTION_FLAG_ALLOW_CUSTOM_SMILEY) buttons |= GTK_IMHTML_CUSTOM_SMILEY; else buttons &= ~GTK_IMHTML_CUSTOM_SMILEY; diff --git a/pidgin/gtkimhtmltoolbar.c b/pidgin/gtkimhtmltoolbar.c index 5e7cf1bb19..6f6bdf167e 100644 --- a/pidgin/gtkimhtmltoolbar.c +++ b/pidgin/gtkimhtmltoolbar.c @@ -1600,7 +1600,7 @@ void gtk_imhtmltoolbar_switch_active_conversation(GtkIMHtmlToolbar *toolbar, /* gray out attention button on protocols that don't support it for the time being it is always disabled for chats */ gtk_widget_set_sensitive(toolbar->attention, - conv && prpl && purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM && + conv && prpl && PURPLE_IS_IM_CONVERSATION(conv) && PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->send_attention != NULL); } diff --git a/pidgin/gtklog.c b/pidgin/gtklog.c index 3872340b7e..ae03abc897 100644 --- a/pidgin/gtklog.c +++ b/pidgin/gtklog.c @@ -282,7 +282,7 @@ static void log_delete_log_cb(GtkWidget *menuitem, gpointer *data) if (log->type == PURPLE_LOG_IM) { - PurpleBuddy *buddy = purple_find_buddy(log->account, log->name); + PurpleBuddy *buddy = purple_blist_find_buddy(log->account, log->name); if (buddy != NULL) name = purple_buddy_get_contact_alias(buddy); else @@ -720,7 +720,7 @@ void pidgin_log_show(PurpleLogType type, const char *buddyname, PurpleAccount *a } else { PurpleBuddy *buddy; - buddy = purple_find_buddy(account, buddyname); + buddy = purple_blist_find_buddy(account, buddyname); if (buddy != NULL) name = purple_buddy_get_contact_alias(buddy); @@ -769,7 +769,7 @@ void pidgin_log_show_contact(PurpleContact *contact) { const char *buddy_name; PurpleAccount *account; - if (!PURPLE_BLIST_NODE_IS_BUDDY(child)) + if (!PURPLE_IS_BUDDY(child)) continue; buddy_name = purple_buddy_get_name((PurpleBuddy *)child); @@ -790,17 +790,16 @@ void pidgin_log_show_contact(PurpleContact *contact) { image = NULL; } - if (contact->alias != NULL) - name = contact->alias; - else if (contact->priority != NULL) - name = purple_buddy_get_contact_alias(contact->priority); + name = purple_contact_get_alias(contact); /* This will happen if the contact doesn't have an alias, * and none of the contact's buddies are online. * There is probably a better way to deal with this. */ if (name == NULL) { - if (contact->node.child != NULL && PURPLE_BLIST_NODE_IS_BUDDY(contact->node.child)) - name = purple_buddy_get_contact_alias((PurpleBuddy *) contact->node.child); + if (PURPLE_BLIST_NODE(contact)->child != NULL && + PURPLE_IS_BUDDY(PURPLE_BLIST_NODE(contact)->child)) + name = purple_buddy_get_contact_alias(PURPLE_BUDDY( + PURPLE_BLIST_NODE(contact)->child)); if (name == NULL) name = ""; } @@ -851,11 +850,9 @@ void pidgin_log_init(void) purple_signal_register(handle, "log-displaying", purple_marshal_VOID__POINTER_POINTER, - NULL, 2, - purple_value_new(PURPLE_TYPE_BOXED, - "PidginLogViewer *"), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_LOG)); + G_TYPE_NONE, 2, + G_TYPE_POINTER, /* (PidginLogViewer *) */ + PURPLE_TYPE_LOG); } void diff --git a/pidgin/gtkmain.c b/pidgin/gtkmain.c index 76b9a54e14..f1b8658bd7 100644 --- a/pidgin/gtkmain.c +++ b/pidgin/gtkmain.c @@ -265,7 +265,6 @@ pidgin_ui_init(void) purple_xfers_set_ui_ops(pidgin_xfers_get_ui_ops()); purple_blist_set_ui_ops(pidgin_blist_get_ui_ops()); purple_notify_set_ui_ops(pidgin_notify_get_ui_ops()); - purple_privacy_set_ui_ops(pidgin_privacy_get_ui_ops()); purple_request_set_ui_ops(pidgin_request_get_ui_ops()); purple_sound_set_ui_ops(pidgin_sound_get_ui_ops()); purple_connections_set_ui_ops(pidgin_connections_get_ui_ops()); @@ -274,7 +273,7 @@ pidgin_ui_init(void) purple_idle_set_ui_ops(pidgin_idle_get_ui_ops()); #endif - pidgin_account_init(); + pidgin_accounts_init(); pidgin_connection_init(); pidgin_blist_init(); pidgin_status_init(); @@ -310,7 +309,7 @@ pidgin_quit(void) pidgin_docklet_uninit(); pidgin_blist_uninit(); pidgin_connection_uninit(); - pidgin_account_uninit(); + pidgin_accounts_uninit(); pidgin_xfers_uninit(); pidgin_debug_uninit(); diff --git a/pidgin/gtkmedia.c b/pidgin/gtkmedia.c index 468f01dd8c..5aa574e351 100644 --- a/pidgin/gtkmedia.c +++ b/pidgin/gtkmedia.c @@ -522,8 +522,8 @@ pidgin_media_finalize(GObject *media) static void pidgin_media_emit_message(PidginMedia *gtkmedia, const char *msg) { - PurpleConversation *conv = purple_find_conversation_with_account( - PURPLE_CONV_TYPE_ANY, gtkmedia->priv->screenname, + PurpleConversation *conv = purple_conversations_find_with_account( + gtkmedia->priv->screenname, purple_media_get_account(gtkmedia->priv->media)); if (conv != NULL) purple_conversation_write(conv, NULL, msg, @@ -595,8 +595,8 @@ realize_cb(GtkWidget *widget, PidginMediaRealizeData *data) static void pidgin_media_error_cb(PidginMedia *media, const char *error, PidginMedia *gtkmedia) { - PurpleConversation *conv = purple_find_conversation_with_account( - PURPLE_CONV_TYPE_ANY, gtkmedia->priv->screenname, + PurpleConversation *conv = purple_conversations_find_with_account( + gtkmedia->priv->screenname, purple_media_get_account(gtkmedia->priv->media)); if (conv != NULL) purple_conversation_write(conv, NULL, error, @@ -637,7 +637,7 @@ pidgin_request_timeout_cb(PidginMedia *gtkmedia) gchar *message = NULL; account = purple_media_get_account(gtkmedia->priv->media); - buddy = purple_find_buddy(account, gtkmedia->priv->screenname); + buddy = purple_blist_find_buddy(account, gtkmedia->priv->screenname); alias = buddy ? purple_buddy_get_contact_alias(buddy) : gtkmedia->priv->screenname; type = gtkmedia->priv->request_type; @@ -1045,7 +1045,7 @@ pidgin_media_new_cb(PurpleMediaManager *manager, PurpleMedia *media, { PidginMedia *gtkmedia = PIDGIN_MEDIA( pidgin_media_new(media, screenname)); - PurpleBuddy *buddy = purple_find_buddy(account, screenname); + PurpleBuddy *buddy = purple_blist_find_buddy(account, screenname); const gchar *alias = buddy ? purple_buddy_get_contact_alias(buddy) : screenname; gtk_window_set_title(GTK_WINDOW(gtkmedia), alias); diff --git a/pidgin/gtknotify.c b/pidgin/gtknotify.c index 14b18764e9..0406352728 100644 --- a/pidgin/gtknotify.c +++ b/pidgin/gtknotify.c @@ -192,11 +192,10 @@ open_im_foreach(GtkTreeModel *model, GtkTreePath *path, -1); if (pounce_data != NULL) { - PurpleConversation *conv; + PurpleIMConversation *im; - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, - pounce_data->account, pounce_data->pouncee); - purple_conversation_present(conv); + im = purple_im_conversation_new(pounce_data->account, pounce_data->pouncee); + purple_conversation_present(PURPLE_CONVERSATION(im)); } } diff --git a/pidgin/gtkpounce.c b/pidgin/gtkpounce.c index 8a308fc047..2f53345e8c 100644 --- a/pidgin/gtkpounce.c +++ b/pidgin/gtkpounce.c @@ -435,9 +435,9 @@ pounce_dnd_recv(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, memcpy(&node, sd_data, sizeof(node)); - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + if (PURPLE_IS_CONTACT(node)) buddy = purple_contact_get_priority_buddy((PurpleContact *)node); - else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + else if (PURPLE_IS_BUDDY(node)) buddy = (PurpleBuddy *)node; else return; @@ -493,7 +493,7 @@ reset_send_msg_entry(PidginPounceDialog *dialog, GtkWidget *dontcare) { PurpleAccount *account = pidgin_account_option_menu_get_selected(dialog->account_menu); gtk_webview_setup_entry(GTK_WEBVIEW(dialog->send_msg_entry), - (account && purple_account_get_connection(account)) ? purple_connection_get_flags(purple_account_get_connection(account)) : PURPLE_CONNECTION_HTML); + (account && purple_account_get_connection(account)) ? purple_connection_get_flags(purple_account_get_connection(account)) : PURPLE_CONNECTION_FLAG_HTML); } void @@ -974,7 +974,7 @@ pidgin_pounce_editor_show(PurpleAccount *account, const char *name, PurpleBuddy *buddy = NULL; if (name != NULL) - buddy = purple_find_buddy(account, name); + buddy = purple_blist_find_buddy(account, name); /* Set some defaults */ if (buddy == NULL) @@ -1412,7 +1412,7 @@ pidgin_pounces_manager_hide(void) static void pounce_cb(PurplePounce *pounce, PurplePounceEvent events, void *data) { - PurpleConversation *conv; + PurpleIMConversation *im; PurpleAccount *account; PurpleBuddy *buddy; const char *pouncee; @@ -1421,7 +1421,7 @@ pounce_cb(PurplePounce *pounce, PurplePounceEvent events, void *data) pouncee = purple_pounce_get_pouncee(pounce); account = purple_pounce_get_pouncer(pounce); - buddy = purple_find_buddy(account, pouncee); + buddy = purple_blist_find_buddy(account, pouncee); if (buddy != NULL) { alias = purple_buddy_get_alias(buddy); @@ -1433,8 +1433,8 @@ pounce_cb(PurplePounce *pounce, PurplePounceEvent events, void *data) if (purple_pounce_action_is_enabled(pounce, "open-window")) { - if (!purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, pouncee, account)) - purple_conversation_new(PURPLE_CONV_TYPE_IM, account, pouncee); + if (!purple_conversations_find_im_with_account(pouncee, account)) + purple_im_conversation_new(account, pouncee); } if (purple_pounce_action_is_enabled(pounce, "popup-notify")) @@ -1487,12 +1487,12 @@ pounce_cb(PurplePounce *pounce, PurplePounceEvent events, void *data) if (message != NULL) { - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, pouncee, account); + im = purple_conversations_find_im_with_account(pouncee, account); - if (conv == NULL) - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, pouncee); + if (im == NULL) + im = purple_im_conversation_new(account, pouncee); - purple_conversation_write(conv, NULL, message, + purple_conversation_write(PURPLE_CONVERSATION(im), NULL, message, PURPLE_MESSAGE_SEND, time(NULL)); serv_send_im(purple_account_get_connection(account), (char *)pouncee, (char *)message, 0); diff --git a/pidgin/gtkprefs.c b/pidgin/gtkprefs.c index 556e6ad53e..afdbcb0d17 100644 --- a/pidgin/gtkprefs.c +++ b/pidgin/gtkprefs.c @@ -1395,7 +1395,7 @@ prefs_set_status_icon_theme_cb(GtkComboBox *combo_box, gpointer user_data) g_free(name); pidgin_stock_load_status_icon_theme(theme); - pidgin_blist_refresh(purple_get_blist()); + pidgin_blist_refresh(purple_blist_get_buddy_list()); } } @@ -1957,8 +1957,8 @@ conv_page(void) gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); gtk_webview_setup_entry(GTK_WEBVIEW(webview), - PURPLE_CONNECTION_HTML | - PURPLE_CONNECTION_FORMATTING_WBFO); + PURPLE_CONNECTION_FLAG_HTML | + PURPLE_CONNECTION_FLAG_FORMATTING_WBFO); g_signal_connect_after(G_OBJECT(webview), "format-toggled", G_CALLBACK(formatting_toggle_cb), NULL); diff --git a/pidgin/gtkprivacy.c b/pidgin/gtkprivacy.c index 9455b4a7f9..a6cc03232d 100644 --- a/pidgin/gtkprivacy.c +++ b/pidgin/gtkprivacy.c @@ -28,7 +28,6 @@ #include "connection.h" #include "debug.h" -#include "privacy.h" #include "request.h" #include "util.h" @@ -80,17 +79,20 @@ static struct } const menu_entries[] = { - { N_("Allow all users to contact me"), PURPLE_PRIVACY_ALLOW_ALL }, - { N_("Allow only the users on my buddy list"), PURPLE_PRIVACY_ALLOW_BUDDYLIST }, - { N_("Allow only the users below"), PURPLE_PRIVACY_ALLOW_USERS }, - { N_("Block all users"), PURPLE_PRIVACY_DENY_ALL }, - { N_("Block only the users below"), PURPLE_PRIVACY_DENY_USERS } + { N_("Allow all users to contact me"), PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL }, + { N_("Allow only the users on my buddy list"), PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST }, + { N_("Allow only the users below"), PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS }, + { N_("Block all users"), PURPLE_ACCOUNT_PRIVACY_DENY_ALL }, + { N_("Block only the users below"), PURPLE_ACCOUNT_PRIVACY_DENY_USERS } }; static const size_t menu_entry_count = sizeof(menu_entries) / sizeof(*menu_entries); static PidginPrivacyDialog *privacy_dialog = NULL; +void pidgin_permit_added_removed(PurpleAccount *account, const char *name); +void pidgin_deny_added_removed(PurpleAccount *account, const char *name); + static void rebuild_allow_list(PidginPrivacyDialog *dialog) { @@ -99,7 +101,7 @@ rebuild_allow_list(PidginPrivacyDialog *dialog) gtk_list_store_clear(dialog->allow_store); - for (l = dialog->account->permit; l != NULL; l = l->next) { + for (l = purple_account_privacy_get_permitted(dialog->account); l != NULL; l = l->next) { gtk_list_store_append(dialog->allow_store, &iter); gtk_list_store_set(dialog->allow_store, &iter, 0, l->data, -1); } @@ -113,7 +115,7 @@ rebuild_block_list(PidginPrivacyDialog *dialog) gtk_list_store_clear(dialog->block_store); - for (l = dialog->account->deny; l != NULL; l = l->next) { + for (l = purple_account_privacy_get_denied(dialog->account); l != NULL; l = l->next) { gtk_list_store_append(dialog->block_store, &iter); gtk_list_store_set(dialog->block_store, &iter, 0, l->data, -1); } @@ -239,12 +241,12 @@ type_changed_cb(GtkComboBox *combo, PidginPrivacyDialog *dialog) gtk_widget_hide(dialog->block_widget); gtk_widget_hide(dialog->button_box); - if (new_type == PURPLE_PRIVACY_ALLOW_USERS) { + if (new_type == PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS) { gtk_widget_show(dialog->allow_widget); gtk_widget_show_all(dialog->button_box); dialog->in_allow_list = TRUE; } - else if (new_type == PURPLE_PRIVACY_DENY_USERS) { + else if (new_type == PURPLE_ACCOUNT_PRIVACY_DENY_USERS) { gtk_widget_show(dialog->block_widget); gtk_widget_show_all(dialog->button_box); dialog->in_allow_list = FALSE; @@ -254,7 +256,7 @@ type_changed_cb(GtkComboBox *combo, PidginPrivacyDialog *dialog) gtk_widget_show(dialog->button_box); purple_blist_schedule_save(); - pidgin_blist_refresh(purple_get_blist()); + pidgin_blist_refresh(purple_blist_get_buddy_list()); } static void @@ -295,9 +297,9 @@ remove_cb(GtkWidget *button, PidginPrivacyDialog *dialog) return; if (dialog->in_allow_list) - purple_privacy_permit_remove(dialog->account, name, FALSE); + purple_account_privacy_permit_remove(dialog->account, name, FALSE); else - purple_privacy_deny_remove(dialog->account, name, FALSE); + purple_account_privacy_deny_remove(dialog->account, name, FALSE); g_free(name); } @@ -307,17 +309,17 @@ removeall_cb(GtkWidget *button, PidginPrivacyDialog *dialog) { GSList *l; if (dialog->in_allow_list) - l = dialog->account->permit; + l = purple_account_privacy_get_permitted(dialog->account); else - l = dialog->account->deny; + l = purple_account_privacy_get_denied(dialog->account); while (l) { char *user; user = l->data; l = l->next; if (dialog->in_allow_list) - purple_privacy_permit_remove(dialog->account, user, FALSE); + purple_account_privacy_permit_remove(dialog->account, user, FALSE); else - purple_privacy_deny_remove(dialog->account, user, FALSE); + purple_account_privacy_deny_remove(dialog->account, user, FALSE); } } @@ -413,12 +415,12 @@ privacy_dialog_new(void) type_changed_cb(GTK_COMBO_BOX(dialog->type_menu), dialog); #if 0 - if (purple_account_get_privacy_type(dialog->account) == PURPLE_PRIVACY_ALLOW_USERS) { + if (purple_account_get_privacy_type(dialog->account) == PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS) { gtk_widget_show(dialog->allow_widget); gtk_widget_show(dialog->button_box); dialog->in_allow_list = TRUE; } - else if (purple_account_get_privacy_type(dialog->account) == PURPLE_PRIVACY_DENY_USERS) { + else if (purple_account_get_privacy_type(dialog->account) == PURPLE_ACCOUNT_PRIVACY_DENY_USERS) { gtk_widget_show(dialog->block_widget); gtk_widget_show(dialog->button_box); dialog->in_allow_list = FALSE; @@ -462,9 +464,9 @@ static void confirm_permit_block_cb(PidginPrivacyRequestData *data, int option) { if (data->block) - purple_privacy_deny(data->account, data->name, FALSE, FALSE); + purple_account_privacy_deny(data->account, data->name); else - purple_privacy_allow(data->account, data->name, FALSE, FALSE); + purple_account_privacy_allow(data->account, data->name); destroy_request_data(data); } @@ -558,38 +560,20 @@ pidgin_request_add_block(PurpleAccount *account, const char *name) } } -static void +void pidgin_permit_added_removed(PurpleAccount *account, const char *name) { if (privacy_dialog != NULL) rebuild_allow_list(privacy_dialog); } -static void +void pidgin_deny_added_removed(PurpleAccount *account, const char *name) { if (privacy_dialog != NULL) rebuild_block_list(privacy_dialog); } -static PurplePrivacyUiOps privacy_ops = -{ - pidgin_permit_added_removed, - pidgin_permit_added_removed, - pidgin_deny_added_removed, - pidgin_deny_added_removed, - NULL, - NULL, - NULL, - NULL -}; - -PurplePrivacyUiOps * -pidgin_privacy_get_ui_ops(void) -{ - return &privacy_ops; -} - void pidgin_privacy_init(void) { diff --git a/pidgin/gtkprivacy.h b/pidgin/gtkprivacy.h index 6ee81a4745..ebc6962371 100644 --- a/pidgin/gtkprivacy.h +++ b/pidgin/gtkprivacy.h @@ -26,7 +26,7 @@ #ifndef _PIDGINPRIVACY_H_ #define _PIDGINPRIVACY_H_ -#include "privacy.h" +#include "account.h" G_BEGIN_DECLS @@ -67,13 +67,6 @@ void pidgin_request_add_permit(PurpleAccount *account, const char *name); */ void pidgin_request_add_block(PurpleAccount *account, const char *name); -/** - * Returns the UI operations structure for the GTK+ privacy subsystem. - * - * @return The GTK+ UI privacy operations structure. - */ -PurplePrivacyUiOps *pidgin_privacy_get_ui_ops(void); - G_END_DECLS #endif /* _PIDGINPRIVACY_H_ */ diff --git a/pidgin/gtksession.c b/pidgin/gtksession.c index 462a0e6b82..1e5094841b 100644 --- a/pidgin/gtksession.c +++ b/pidgin/gtksession.c @@ -376,7 +376,7 @@ pidgin_session_init(gchar *argv0, gchar *previous_id, gchar *config_dir) g_free(tmp); session_set_gchar(session, SmRestartStyleHint, (gchar) SmRestartIfRunning); - session_set_string(session, SmProgram, g_get_prgname()); + session_set_string(session, SmProgram, (gchar *) g_get_prgname()); myself = g_strdup(argv0); purple_debug(PURPLE_DEBUG_MISC, "Session Management", diff --git a/pidgin/gtksound.c b/pidgin/gtksound.c index a9349bbafb..b59e0a250f 100644 --- a/pidgin/gtksound.c +++ b/pidgin/gtksound.c @@ -85,19 +85,19 @@ unmute_login_sounds_cb(gpointer data) } static gboolean -chat_nick_matches_name(PurpleConversation *conv, const char *aname) +chat_nick_matches_name(PurpleChatConversation *chat, const char *aname) { - PurpleConvChat *chat = NULL; char *nick = NULL; char *name = NULL; gboolean ret = FALSE; - chat = purple_conversation_get_chat_data(conv); if (chat==NULL) return ret; - nick = g_strdup(purple_normalize(purple_conversation_get_account(conv), purple_conv_chat_get_nick(chat))); - name = g_strdup(purple_normalize(purple_conversation_get_account(conv), aname)); + nick = g_strdup(purple_normalize(purple_conversation_get_account( + PURPLE_CONVERSATION(chat)), purple_chat_conversation_get_nick(chat))); + name = g_strdup(purple_normalize(purple_conversation_get_account( + PURPLE_CONVERSATION(chat)), aname)); if (g_utf8_collate(nick, name) == 0) ret = TRUE; @@ -158,26 +158,26 @@ static void im_msg_sent_cb(PurpleAccount *account, const char *receiver, const char *message, PurpleSoundEventID event) { - PurpleConversation *conv = purple_find_conversation_with_account( - PURPLE_CONV_TYPE_IM, receiver, account); + PurpleConversation *conv = PURPLE_CONVERSATION( + purple_conversations_find_im_with_account(receiver, account)); play_conv_event(conv, event); } static void -chat_buddy_join_cb(PurpleConversation *conv, const char *name, - PurpleConvChatBuddyFlags flags, gboolean new_arrival, +chat_user_join_cb(PurpleChatConversation *chat, const char *name, + PurpleChatUserFlags flags, gboolean new_arrival, PurpleSoundEventID event) { - if (new_arrival && !chat_nick_matches_name(conv, name)) - play_conv_event(conv, event); + if (new_arrival && !chat_nick_matches_name(chat, name)) + play_conv_event(PURPLE_CONVERSATION(chat), event); } static void -chat_buddy_left_cb(PurpleConversation *conv, const char *name, +chat_user_left_cb(PurpleChatConversation *chat, const char *name, const char *reason, PurpleSoundEventID event) { - if (!chat_nick_matches_name(conv, name)) - play_conv_event(conv, event); + if (!chat_nick_matches_name(chat, name)) + play_conv_event(PURPLE_CONVERSATION(chat), event); } static void @@ -188,31 +188,29 @@ chat_msg_sent_cb(PurpleAccount *account, const char *message, PurpleConversation *conv = NULL; if (conn!=NULL) - conv = purple_find_chat(conn,id); + conv = PURPLE_CONVERSATION(purple_conversations_find_chat(conn,id)); play_conv_event(conv, event); } static void chat_msg_received_cb(PurpleAccount *account, char *sender, - char *message, PurpleConversation *conv, + char *message, PurpleChatConversation *chat, PurpleMessageFlags flags, PurpleSoundEventID event) { - PurpleConvChat *chat; - + PurpleConversation *conv = PURPLE_CONVERSATION(chat); if (flags & PURPLE_MESSAGE_DELAYED || flags & PURPLE_MESSAGE_NOTIFY) return; - chat = purple_conversation_get_chat_data(conv); - g_return_if_fail(chat != NULL); + g_return_if_fail(conv != NULL); - if (purple_conv_chat_is_user_ignored(chat, sender)) + if (purple_chat_conversation_is_ignored_user(chat, sender)) return; - if (chat_nick_matches_name(conv, sender)) + if (chat_nick_matches_name(chat, sender)) return; - if (flags & PURPLE_MESSAGE_NICK || purple_utf8_has_word(message, purple_conv_chat_get_nick(chat))) + if (flags & PURPLE_MESSAGE_NICK || purple_utf8_has_word(message, purple_chat_conversation_get_nick(chat))) /* This isn't quite right; if you have the PURPLE_SOUND_CHAT_NICK event disabled * and the PURPLE_SOUND_CHAT_SAY event enabled, you won't get a sound at all */ play_conv_event(conv, PURPLE_SOUND_CHAT_NICK); @@ -343,11 +341,11 @@ pidgin_sound_init(void) purple_signal_connect(conv_handle, "sent-im-msg", gtk_sound_handle, PURPLE_CALLBACK(im_msg_sent_cb), GINT_TO_POINTER(PURPLE_SOUND_SEND)); - purple_signal_connect(conv_handle, "chat-buddy-joined", - gtk_sound_handle, PURPLE_CALLBACK(chat_buddy_join_cb), + purple_signal_connect(conv_handle, "chat-user-joined", + gtk_sound_handle, PURPLE_CALLBACK(chat_user_join_cb), GINT_TO_POINTER(PURPLE_SOUND_CHAT_JOIN)); - purple_signal_connect(conv_handle, "chat-buddy-left", - gtk_sound_handle, PURPLE_CALLBACK(chat_buddy_left_cb), + purple_signal_connect(conv_handle, "chat-user-left", + gtk_sound_handle, PURPLE_CALLBACK(chat_user_left_cb), GINT_TO_POINTER(PURPLE_SOUND_CHAT_LEAVE)); purple_signal_connect(conv_handle, "sent-chat-msg", gtk_sound_handle, PURPLE_CALLBACK(chat_msg_sent_cb), diff --git a/pidgin/gtkstatusbox.c b/pidgin/gtkstatusbox.c index 715a2acd12..73598a3c05 100644 --- a/pidgin/gtkstatusbox.c +++ b/pidgin/gtkstatusbox.c @@ -254,7 +254,7 @@ update_to_reflect_account_status(PidginStatusBox *status_box, PurpleAccount *acc const char *message; statustype = purple_status_type_find_with_id((GList *)purple_account_get_status_types(account), - (char *)purple_status_type_get_id(purple_status_get_type(newstatus))); + (char *)purple_status_type_get_id(purple_status_get_status_type(newstatus))); for (l = purple_account_get_status_types(account); l != NULL; l = l->next) { PurpleStatusType *status_type = (PurpleStatusType *)l->data; @@ -702,7 +702,7 @@ pidgin_status_box_refresh(PidginStatusBox *status_box) PurpleStatusType *status_type; PurpleStatusPrimitive prim; if (account_status) { - status_type = purple_status_get_type(purple_account_get_active_status(acct)); + status_type = purple_status_get_status_type(purple_account_get_active_status(acct)); prim = purple_status_type_get_primitive(status_type); } else { prim = purple_savedstatus_get_type(saved_status); diff --git a/pidgin/gtkthemes.c b/pidgin/gtkthemes.c index 4e3ceb7a87..10ca5c0e44 100644 --- a/pidgin/gtkthemes.c +++ b/pidgin/gtkthemes.c @@ -341,7 +341,7 @@ void pidgin_themes_load_smiley_theme(const char *file, gboolean load) pidgin_themes_destroy_smiley_theme_smileys(current_smiley_theme); current_smiley_theme = theme; - for (cnv = purple_get_conversations(); cnv != NULL; cnv = cnv->next) { + for (cnv = purple_conversations_get_all(); cnv != NULL; cnv = cnv->next) { PurpleConversation *conv = cnv->data; if (PIDGIN_IS_PIDGIN_CONVERSATION(conv)) { diff --git a/pidgin/gtkutils.c b/pidgin/gtkutils.c index 66c9d3a743..32c64ace78 100644 --- a/pidgin/gtkutils.c +++ b/pidgin/gtkutils.c @@ -730,10 +730,10 @@ create_account_menu(PurpleAccount *default_account, gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE); } - if (purple_account_get_alias(account)) { + if (purple_account_get_private_alias(account)) { g_snprintf(buf, sizeof(buf), "%s (%s) (%s)", purple_account_get_username(account), - purple_account_get_alias(account), + purple_account_get_private_alias(account), purple_account_get_protocol_name(account)); } else { g_snprintf(buf, sizeof(buf), "%s (%s)", @@ -1378,7 +1378,7 @@ static void dnd_image_ok_callback(_DndData *data, int choice) break; } - buddy = purple_find_buddy(data->account, data->who); + buddy = purple_blist_find_buddy(data->account, data->who); if (!buddy) { purple_debug_info("custom-icon", "You can only set custom icons for people on your buddylist.\n"); break; @@ -1390,7 +1390,7 @@ static void dnd_image_ok_callback(_DndData *data, int choice) serv_send_file(purple_account_get_connection(data->account), data->who, data->filename); break; case DND_IM_IMAGE: - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, data->account, data->who); + conv = PURPLE_CONVERSATION(purple_im_conversation_new(data->account, data->who)); gtkconv = PIDGIN_CONVERSATION(conv); if (!g_file_get_contents(data->filename, &filedata, &size, @@ -1570,7 +1570,7 @@ pidgin_dnd_file_manage(GtkSelectionData *sd, PurpleAccount *account, const char PidginConversation *gtkconv; case PURPLE_DESKTOP_ITEM_TYPE_LINK: - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, who); + conv = PURPLE_CONVERSATION(purple_im_conversation_new(account, who)); gtkconv = PIDGIN_CONVERSATION(conv); gtk_webview_insert_link(GTK_WEBVIEW(gtkconv->entry), purple_desktop_item_get_string(item, "URL"), @@ -1685,7 +1685,7 @@ pidgin_stock_id_from_presence(PurplePresence *presence) g_return_val_if_fail(presence, NULL); status = purple_presence_get_active_status(presence); - type = purple_status_get_type(status); + type = purple_status_get_status_type(status); prim = purple_status_type_get_primitive(type); idle = purple_presence_is_idle(presence); @@ -1965,19 +1965,22 @@ add_completion_list(PidginCompletionData *data) PidginFilterBuddyCompletionEntryFunc filter_func = data->filter_func; gpointer user_data = data->filter_func_user_data; GHashTable *sets; + gchar *alias; gtk_list_store_clear(data->store); - for (gnode = purple_get_blist()->root; gnode != NULL; gnode = gnode->next) + for (gnode = purple_blist_get_buddy_list()->root; gnode != NULL; gnode = gnode->next) { - if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) + if (!PURPLE_IS_GROUP(gnode)) continue; for (cnode = gnode->child; cnode != NULL; cnode = cnode->next) { - if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) + if (!PURPLE_IS_CONTACT(cnode)) continue; + g_object_get(cnode, "alias", &alias, NULL); + for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) { PidginBuddyCompletionEntry entry; @@ -1986,13 +1989,15 @@ add_completion_list(PidginCompletionData *data) if (filter_func(&entry, user_data)) { add_buddyname_autocomplete_entry(data->store, - ((PurpleContact *)cnode)->alias, + alias, purple_buddy_get_contact_alias(entry.entry.buddy), purple_buddy_get_account(entry.entry.buddy), purple_buddy_get_name(entry.entry.buddy) ); } } + + g_free(alias); } } diff --git a/pidgin/gtkwebview.c b/pidgin/gtkwebview.c index 3ad89f73a7..67a1a5a703 100644 --- a/pidgin/gtkwebview.c +++ b/pidgin/gtkwebview.c @@ -1783,19 +1783,19 @@ gtk_webview_setup_entry(GtkWebView *webview, PurpleConnectionFlags flags) g_return_if_fail(webview != NULL); - if (flags & PURPLE_CONNECTION_HTML) { + if (flags & PURPLE_CONNECTION_FLAG_HTML) { gboolean bold, italic, underline, strike; buttons = GTK_WEBVIEW_ALL; - if (flags & PURPLE_CONNECTION_NO_BGCOLOR) + if (flags & PURPLE_CONNECTION_FLAG_NO_BGCOLOR) buttons &= ~GTK_WEBVIEW_BACKCOLOR; - if (flags & PURPLE_CONNECTION_NO_FONTSIZE) + if (flags & PURPLE_CONNECTION_FLAG_NO_FONTSIZE) { buttons &= ~GTK_WEBVIEW_GROW; buttons &= ~GTK_WEBVIEW_SHRINK; } - if (flags & PURPLE_CONNECTION_NO_URLDESC) + if (flags & PURPLE_CONNECTION_FLAG_NO_URLDESC) buttons &= ~GTK_WEBVIEW_LINKDESC; gtk_webview_get_current_format(webview, &bold, &italic, &underline, &strike); @@ -1816,7 +1816,7 @@ gtk_webview_setup_entry(GtkWebView *webview, PurpleConnectionFlags flags) gtk_webview_toggle_fontface(webview, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/font_face")); - if (!(flags & PURPLE_CONNECTION_NO_FONTSIZE)) + if (!(flags & PURPLE_CONNECTION_FLAG_NO_FONTSIZE)) { int size = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/font_size"); @@ -1828,14 +1828,14 @@ gtk_webview_setup_entry(GtkWebView *webview, PurpleConnectionFlags flags) gtk_webview_toggle_forecolor(webview, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor")); - if (!(flags & PURPLE_CONNECTION_NO_BGCOLOR)) { + if (!(flags & PURPLE_CONNECTION_FLAG_NO_BGCOLOR)) { gtk_webview_toggle_backcolor(webview, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor")); } else { gtk_webview_toggle_backcolor(webview, ""); } - if (flags & PURPLE_CONNECTION_FORMATTING_WBFO) + if (flags & PURPLE_CONNECTION_FLAG_FORMATTING_WBFO) gtk_webview_set_whole_buffer_formatting_only(webview, TRUE); else gtk_webview_set_whole_buffer_formatting_only(webview, FALSE); @@ -1844,10 +1844,10 @@ gtk_webview_setup_entry(GtkWebView *webview, PurpleConnectionFlags flags) webview_clear_formatting(webview); } - if (flags & PURPLE_CONNECTION_NO_IMAGES) + if (flags & PURPLE_CONNECTION_FLAG_NO_IMAGES) buttons &= ~GTK_WEBVIEW_IMAGE; - if (flags & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) + if (flags & PURPLE_CONNECTION_FLAG_ALLOW_CUSTOM_SMILEY) buttons |= GTK_WEBVIEW_CUSTOM_SMILEY; else buttons &= ~GTK_WEBVIEW_CUSTOM_SMILEY; diff --git a/pidgin/gtkwebviewtoolbar.c b/pidgin/gtkwebviewtoolbar.c index 9258d68ce1..b8be27ee0b 100644 --- a/pidgin/gtkwebviewtoolbar.c +++ b/pidgin/gtkwebviewtoolbar.c @@ -1632,7 +1632,7 @@ gtk_webviewtoolbar_switch_active_conversation(GtkWebViewToolbar *toolbar, /* gray out attention button on protocols that don't support it for the time being it is always disabled for chats */ gtk_action_set_sensitive(priv->attention, - conv && prpl && purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM && + conv && prpl && PURPLE_IS_IM_CONVERSATION(conv) && PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->send_attention != NULL); gtk_action_set_sensitive(priv->smiley, diff --git a/pidgin/gtkwhiteboard.c b/pidgin/gtkwhiteboard.c index 47e4987d9e..dd6df9f325 100644 --- a/pidgin/gtkwhiteboard.c +++ b/pidgin/gtkwhiteboard.c @@ -22,7 +22,7 @@ */ #include "internal.h" -#include "blist.h" +#include "buddylist.h" #include "debug.h" #include "gtkwhiteboard.h" @@ -156,7 +156,7 @@ static void pidgin_whiteboard_create(PurpleWhiteboard *wb) /* Try and set window title as the name of the buddy, else just use their * username */ - buddy = purple_find_buddy(purple_whiteboard_get_account(wb), purple_whiteboard_get_who(wb)); + buddy = purple_blist_find_buddy(purple_whiteboard_get_account(wb), purple_whiteboard_get_who(wb)); window = pidgin_create_window(buddy != NULL ? purple_buddy_get_contact_alias(buddy) : purple_whiteboard_get_who(wb), 0, NULL, FALSE); gtkwb->window = window; @@ -351,7 +351,7 @@ static void pidginwhiteboard_button_start_press(GtkButton *button, gpointer data /* XXXX because otherwise gettext will see this string, even though it's * in an #if 0 block. Remove the XXXX if you want to use this code. * But, it really shouldn't be a Yahoo-specific string. ;) */ - purple_conv_im_write(PURPLE_CONV_IM(conv), "", XXXX_("Sent Doodle request."), + purple_im_conversation_write_message(PURPLE_CONV_IM(conv), "", XXXX_("Sent Doodle request."), PURPLE_MESSAGE_NICK | PURPLE_MESSAGE_RECV, time(NULL)); yahoo_doodle_command_send_request(gc, to); diff --git a/pidgin/plugins/cap/cap.c b/pidgin/plugins/cap/cap.c index d5faffa23b..f9a9122713 100644 --- a/pidgin/plugins/cap/cap.c +++ b/pidgin/plugins/cap/cap.c @@ -349,7 +349,7 @@ static void sent_im_msg(PurpleAccount *account, const char *receiver, const char guint interval, words; CapStatistics *stats = NULL; - buddy = purple_find_buddy(account, receiver); + buddy = purple_blist_find_buddy(account, receiver); if (buddy == NULL) return; @@ -378,7 +378,7 @@ received_im_msg(PurpleAccount *account, char *sender, char *message, PurpleConve if (flags & PURPLE_MESSAGE_AUTO_RESP) return; - buddy = purple_find_buddy(account, sender); + buddy = purple_blist_find_buddy(account, sender); if (buddy == NULL) return; @@ -439,7 +439,7 @@ static void buddy_signed_off(PurpleBuddy *buddy) { /* drawing-tooltip */ static void drawing_tooltip(PurpleBlistNode *node, GString *text, gboolean full) { if(node->type == PURPLE_BLIST_BUDDY_NODE) { - PurpleBuddy *buddy = (PurpleBuddy *)node; + PurpleBuddy *buddy = PURPLE_BUDDY(node); CapStatistics *stats = get_stats_for(buddy); /* get the probability that this buddy will respond and add to the tooltip */ if(stats->prediction->probability >= 0.0) { diff --git a/pidgin/plugins/cap/cap.h b/pidgin/plugins/cap/cap.h index 3832b3f901..d4adc47d69 100644 --- a/pidgin/plugins/cap/cap.h +++ b/pidgin/plugins/cap/cap.h @@ -32,7 +32,7 @@ #include "gtkplugin.h" #include "gtkutils.h" -#include "blist.h" +#include "buddylist.h" #include "notify.h" #include "version.h" #include "debug.h" diff --git a/pidgin/plugins/cap/cap_statistics.h b/pidgin/plugins/cap/cap_statistics.h index f52495efdc..85a11da3d5 100644 --- a/pidgin/plugins/cap/cap_statistics.h +++ b/pidgin/plugins/cap/cap_statistics.h @@ -22,7 +22,7 @@ #ifndef _CAP_STATISTICS_H_ #define _CAP_STATISTICS_H_ -#include "blist.h" +#include "buddylist.h" #include <gdk/gdk.h> #include <glib.h> #include <time.h> diff --git a/pidgin/plugins/convcolors.c b/pidgin/plugins/convcolors.c index 391dbf611a..8f8627cabb 100644 --- a/pidgin/plugins/convcolors.c +++ b/pidgin/plugins/convcolors.c @@ -113,10 +113,8 @@ displaying_msg(PurpleAccount *account, const char *who, char **displaying, g_snprintf(tmp, sizeof(tmp), "%s/enabled", formats[i].prefix); if (!purple_prefs_get_bool(tmp) || - (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM && - !purple_prefs_get_bool(PREF_IMS)) || - (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && - !purple_prefs_get_bool(PREF_CHATS))) + (PURPLE_IS_IM_CONVERSATION(conv) && !purple_prefs_get_bool(PREF_IMS)) || + (PURPLE_IS_CHAT_CONVERSATION(conv) && !purple_prefs_get_bool(PREF_CHATS))) return FALSE; g_snprintf(tmp, sizeof(tmp), "%s/color", formats[i].prefix); diff --git a/pidgin/plugins/crazychat/cc_network.c b/pidgin/plugins/crazychat/cc_network.c index a80e580c18..45c30eab14 100644 --- a/pidgin/plugins/crazychat/cc_network.c +++ b/pidgin/plugins/crazychat/cc_network.c @@ -97,22 +97,22 @@ void cc_net_send_invite(struct crazychat *cc, char *name, PurpleAccount *account { struct cc_session *session; PurpleConversation *conv; - PurpleConvIm *im; + PurpleIMConversation *im; char buf[BUFSIZ]; session = cc_find_session(cc, name); if (session) return; /* already have a session with this guy */ session = cc_add_session(cc, name); session->state = INVITE; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, name, account); + conv = purple_conversations_find_with_account(name, account); if (!conv) { - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name); + conv = purple_im_conversation_new(account, name); } im = purple_conversation_get_im_data(conv); snprintf(buf, BUFSIZ, "%s%s!%d", CRAZYCHAT_INVITE_CODE, purple_network_get_my_ip(-1), cc->tcp_port); Debug("Sent invite to %s for port: %d\n", name, cc->tcp_port); - purple_conv_im_send(im, buf); + purple_im_conversation_send(im, buf); } void cc_net_recv_invite(PurpleAccount *account, struct crazychat *cc, char *name, @@ -131,7 +131,7 @@ void cc_net_recv_invite(PurpleAccount *account, struct crazychat *cc, char *name session = cc_find_session(cc, name); if (!session) { Debug("Creating a CrazyChat session invite dialog box!\n"); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, name, account); + conv = purple_conversations_find_with_account(name, account); if (conv) convwin = purple_conversation_get_window(conv); else convwin = NULL; /* pop gtk window asking if want to accept */ @@ -206,15 +206,15 @@ static void cc_net_send_ready(PurpleAccount *account, struct cc_session *session /* socket created, send the ready message */ PurpleConversation *conv; - PurpleConvIm *im; + PurpleIMConversation *im; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, session->name, account); + conv = purple_conversations_find_with_account(session->name, account); if (!conv) { - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, + conv = purple_im_conversation_new(account, session->name); } im = purple_conversation_get_im_data(conv); - purple_conv_im_send(im, CRAZYCHAT_READY_CODE); + purple_im_conversation_send(im, CRAZYCHAT_READY_CODE); /* register timer callback for checking socket connection */ args = (struct sock_accept_args*)malloc(sizeof(*args)); @@ -260,7 +260,7 @@ static void invite_handler(GtkDialog *dialog, gint response, struct accept_args struct cc_session *session; char buf[BUFSIZ]; PurpleConversation *conv; - PurpleConvIm *im; + PurpleIMConversation *im; if (response == GTK_RESPONSE_ACCEPT) { assert(args); @@ -272,14 +272,14 @@ static void invite_handler(GtkDialog *dialog, gint response, struct accept_args session->peer_port = args->peer_port; snprintf(buf, BUFSIZ, "%s%s", CRAZYCHAT_ACCEPT_CODE, purple_network_get_my_ip(-1)); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, args->name, + conv = purple_conversations_find_with_account(args->name, args->account); if (!conv) { conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, args->account, args->name); } im = purple_conversation_get_im_data(conv); - purple_conv_im_send(im, buf); + purple_im_conversation_send(im, buf); } free(args->name); free(args); diff --git a/pidgin/plugins/crazychat/cc_pidgin_plugin.c b/pidgin/plugins/crazychat/cc_pidgin_plugin.c index 6219d5f615..c88750c807 100644 --- a/pidgin/plugins/crazychat/cc_pidgin_plugin.c +++ b/pidgin/plugins/crazychat/cc_pidgin_plugin.c @@ -413,7 +413,7 @@ static gboolean cc_signed_on(PurpleConnection *gc, void *plugin) (purple_connections_get_handle(), "signed-on", plugin, PURPLE_CALLBACK(cc_signed_on)); purple_signal_connect(PIDGIN_BLIST - (purple_get_blist()), + (purple_blist_get_buddy_list()), "drawing-menu", plugin, PURPLE_CALLBACK(cc_buddy_menu), NULL); conv_handle = purple_conversations_get_handle(); @@ -433,7 +433,7 @@ static gboolean plugin_load(PurplePlugin *plugin) return FALSE; cc_init(&cc_info); - buddy_list = purple_get_blist(); + buddy_list = purple_blist_get_buddy_list(); if (buddy_list) { purple_signal_connect(PIDGIN_BLIST (buddy_list), @@ -464,7 +464,7 @@ static gboolean plugin_unload(PurplePlugin *plugin) cc_destroy(extra); conv_handle = purple_conversations_get_handle(); purple_signal_disconnect(PIDGIN_BLIST - (purple_get_blist()), + (purple_blist_get_buddy_list()), "drawing-menu", plugin, PURPLE_CALLBACK(cc_buddy_menu)); purple_signal_disconnect(conv_handle, "received-im", plugin, diff --git a/pidgin/plugins/extplacement.c b/pidgin/plugins/extplacement.c index 494e0849d2..bb387311f3 100644 --- a/pidgin/plugins/extplacement.c +++ b/pidgin/plugins/extplacement.c @@ -35,7 +35,8 @@ conv_placement_by_number(PidginConversation *conv) GList *wins = NULL; if (purple_prefs_get_bool("/plugins/gtk/extplacement/placement_number_separate")) - win = pidgin_conv_window_last_with_type(purple_conversation_get_type(conv->active_conv)); + win = PURPLE_IS_IM_CONVERSATION(conv->active_conv) ? + pidgin_conv_window_last_im() : pidgin_conv_window_last_chat(); else if ((wins = pidgin_conv_windows_get_list()) != NULL) win = g_list_last(wins)->data; @@ -57,7 +58,7 @@ conv_placement_by_number(PidginConversation *conv) win = l->data; if (purple_prefs_get_bool("/plugins/gtk/extplacement/placement_number_separate") && - purple_conversation_get_type(pidgin_conv_window_get_active_conversation(win)) != purple_conversation_get_type(conv->active_conv)) + PURPLE_IS_IM_CONVERSATION(pidgin_conv_window_get_active_conversation(win)) != PURPLE_IS_IM_CONVERSATION(conv->active_conv)) continue; count = pidgin_conv_window_get_gtkconv_count(win); diff --git a/pidgin/plugins/gestures/gestures.c b/pidgin/plugins/gestures/gestures.c index 51c13f011e..da43ecc342 100644 --- a/pidgin/plugins/gestures/gestures.c +++ b/pidgin/plugins/gestures/gestures.c @@ -49,7 +49,7 @@ stroke_close(GtkWidget *widget, void *data) gtkconv = PIDGIN_CONVERSATION(conv); gstroke_cleanup(gtkconv->webview); - purple_conversation_destroy(conv); + g_object_unref(conv); } static void @@ -174,7 +174,7 @@ plugin_load(PurplePlugin *plugin) PurpleConversation *conv; GList *l; - for (l = purple_get_conversations(); l != NULL; l = l->next) { + for (l = purple_conversations_get_all(); l != NULL; l = l->next) { conv = (PurpleConversation *)l->data; if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv)) @@ -197,7 +197,7 @@ plugin_unload(PurplePlugin *plugin) PidginConversation *gtkconv; GList *l; - for (l = purple_get_conversations(); l != NULL; l = l->next) { + for (l = purple_conversations_get_all(); l != NULL; l = l->next) { conv = (PurpleConversation *)l->data; if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv)) diff --git a/pidgin/plugins/gevolution/add_buddy_dialog.c b/pidgin/plugins/gevolution/add_buddy_dialog.c index 4570726936..eb376bc2ad 100644 --- a/pidgin/plugins/gevolution/add_buddy_dialog.c +++ b/pidgin/plugins/gevolution/add_buddy_dialog.c @@ -192,7 +192,7 @@ add_ims(GevoAddBuddyDialog *dialog, EContact *contact, const char *name, if (account_name == NULL) continue; - if (purple_find_buddy(dialog->account, account_name) != NULL) + if (purple_blist_find_buddy(dialog->account, account_name) != NULL) continue; gtk_list_store_append(dialog->model, &iter); diff --git a/pidgin/plugins/gevolution/gevo-util.c b/pidgin/plugins/gevolution/gevo-util.c index 77d31a4ffe..3d8ed1ca63 100644 --- a/pidgin/plugins/gevolution/gevo-util.c +++ b/pidgin/plugins/gevolution/gevo-util.c @@ -33,16 +33,16 @@ gevo_add_buddy(PurpleAccount *account, const char *group_name, PurpleBuddy *buddy; PurpleGroup *group; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy_name, account); + conv = purple_conversations_find_im_with_account(buddy_name, account); - group = purple_find_group(group_name); + group = purple_blist_find_group(group_name); if (group == NULL) { group = purple_group_new(group_name); purple_blist_add_group(group, NULL); } - buddy = purple_find_buddy_in_group(account, buddy_name, group); + buddy = purple_blist_find_buddy_in_group(account, buddy_name, group); if (buddy == NULL) { buddy = purple_buddy_new(account, buddy_name, alias); @@ -53,8 +53,8 @@ gevo_add_buddy(PurpleAccount *account, const char *group_name, if (conv != NULL) { - purple_buddy_icon_update(purple_conv_im_get_icon(PURPLE_CONV_IM(conv))); - purple_conversation_update(conv, PURPLE_CONV_UPDATE_ADD); + purple_buddy_icon_update(purple_im_conversation_get_icon(PURPLE_CONV_IM(conv))); + purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_ADD); } } @@ -68,19 +68,19 @@ gevo_get_groups(void) g_list_free(list); list = NULL; - if (purple_get_blist()->root == NULL) + if (purple_blist_get_buddy_list()->root == NULL) { list = g_list_append(list, (gpointer)_("Buddies")); } else { - for (gnode = purple_get_blist()->root; + for (gnode = purple_blist_get_buddy_list()->root; gnode != NULL; gnode = gnode->next) { - if (PURPLE_BLIST_NODE_IS_GROUP(gnode)) + if (PURPLE_IS_GROUP(gnode)) { - g = (PurpleGroup *)gnode; + g = PURPLE_GROUP(gnode); list = g_list_append(list, g->name); } } diff --git a/pidgin/plugins/gevolution/gevolution.c b/pidgin/plugins/gevolution/gevolution.c index 9398393b23..244460738e 100644 --- a/pidgin/plugins/gevolution/gevolution.c +++ b/pidgin/plugins/gevolution/gevolution.c @@ -99,7 +99,7 @@ update_ims_from_contact(EContact *contact, const char *name, me = g_strdup(purple_normalize(account, purple_account_get_username(account))); for (l2 = ims; l2 != NULL; l2 = l2->next) { - if (purple_find_buddy(account, l2->data) != NULL || + if (purple_blist_find_buddy(account, l2->data) != NULL || !strcmp(me, purple_normalize(account, l2->data))) continue; @@ -220,14 +220,14 @@ signed_on_cb(PurpleConnection *gc) static void menu_item_activate_cb(PurpleBlistNode *node, gpointer user_data) { - PurpleBuddy *buddy = (PurpleBuddy *)node; + PurpleBuddy *buddy = PURPLE_BUDDY(node); gevo_associate_buddy_dialog_new(buddy); } static void menu_item_send_mail_activate_cb(PurpleBlistNode *node, gpointer user_data) { - PurpleBuddy *buddy = (PurpleBuddy *)node; + PurpleBuddy *buddy = PURPLE_BUDDY(node); char *mail = NULL; mail = gevo_get_email_for_buddy(buddy); @@ -268,10 +268,10 @@ blist_node_extended_menu_cb(PurpleBlistNode *node, GList **menu) EContact *contact; char *mail; - if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (!PURPLE_IS_BUDDY(node)) return; - buddy = (PurpleBuddy *)node; + buddy = PURPLE_BUDDY(node); account = purple_buddy_get_account(buddy); if (!gevo_prpl_is_supported(account, buddy)) diff --git a/pidgin/plugins/gtk-signals-test.c b/pidgin/plugins/gtk-signals-test.c index a1cf84bf25..f61f50a28d 100644 --- a/pidgin/plugins/gtk-signals-test.c +++ b/pidgin/plugins/gtk-signals-test.c @@ -110,7 +110,7 @@ conversation_switched_cb(PurpleConversation *conv, void *data) static gboolean plugin_load(PurplePlugin *plugin) { - void *accounts_handle = pidgin_account_get_handle(); + void *accounts_handle = pidgin_accounts_get_handle(); void *blist_handle = pidgin_blist_get_handle(); void *conv_handle = pidgin_conversations_get_handle(); diff --git a/pidgin/plugins/history.c b/pidgin/plugins/history.c index f2d1d913d0..faea163a68 100644 --- a/pidgin/plugins/history.c +++ b/pidgin/plugins/history.c @@ -34,7 +34,6 @@ static void historize(PurpleConversation *c) { PurpleAccount *account = purple_conversation_get_account(c); const char *name = purple_conversation_get_name(c); - PurpleConversationType convtype; GList *logs = NULL; const char *alias = name; guint flags; @@ -52,13 +51,12 @@ static void historize(PurpleConversation *c) char *escaped_alias; const char *header_date; - convtype = purple_conversation_get_type(c); gtkconv = PIDGIN_CONVERSATION(c); g_return_if_fail(gtkconv != NULL); /* An IM which is the first active conversation. */ g_return_if_fail(gtkconv->convs != NULL); - if (convtype == PURPLE_CONV_TYPE_IM && !gtkconv->convs->next) + if (PURPLE_IS_IM_CONVERSATION(c) && !gtkconv->convs->next) { GSList *buddies; GSList *cur; @@ -69,11 +67,11 @@ static void historize(PurpleConversation *c) return; /* Find buddies for this conversation. */ - buddies = purple_find_buddies(account, name); + buddies = purple_blist_find_buddies(account, name); /* If we found at least one buddy, save the first buddy's alias. */ if (buddies != NULL) - alias = purple_buddy_get_contact_alias((PurpleBuddy *)buddies->data); + alias = purple_buddy_get_contact_alias(PURPLE_BUDDY(buddies->data)); for (cur = buddies; cur != NULL; cur = cur->next) { @@ -86,7 +84,7 @@ static void historize(PurpleConversation *c) PurpleBlistNode *parent = purple_blist_node_get_parent(node); PurpleBlistNode *child = purple_blist_node_get_first_child(parent); - alias = purple_buddy_get_contact_alias((PurpleBuddy *)node); + alias = purple_buddy_get_contact_alias(PURPLE_BUDDY(node)); /* We've found a buddy that matches this conversation. It's part of a * PurpleContact with more than one PurpleBuddy. Loop through the PurpleBuddies @@ -94,8 +92,8 @@ static void historize(PurpleConversation *c) for (node2 = child ; node2 != NULL ; node2 = purple_blist_node_get_sibling_next(node2)) { logs = g_list_concat(purple_log_get_logs(PURPLE_LOG_IM, - purple_buddy_get_name((PurpleBuddy *)node2), - purple_buddy_get_account((PurpleBuddy *)node2)), + purple_buddy_get_name(PURPLE_BUDDY(node2)), + purple_buddy_get_account(PURPLE_BUDDY(node2))), logs); } break; @@ -108,7 +106,7 @@ static void historize(PurpleConversation *c) else logs = g_list_sort(logs, purple_log_compare); } - else if (convtype == PURPLE_CONV_TYPE_CHAT) + else if (PURPLE_IS_CHAT_CONVERSATION(c)) { /* If we're not logging, don't show anything. * Otherwise, we might show a very old log. */ diff --git a/pidgin/plugins/mailchk.c b/pidgin/plugins/mailchk.c index ed279b5ecf..c9bf0e9f55 100644 --- a/pidgin/plugins/mailchk.c +++ b/pidgin/plugins/mailchk.c @@ -55,7 +55,7 @@ static gboolean check_timeout(gpointer data) { gint count = check_mail(); - PurpleBuddyList *list = purple_get_blist(); + PurpleBuddyList *list = purple_blist_get_buddy_list(); if (count == -1) return FALSE; @@ -90,7 +90,7 @@ check_timeout(gpointer data) static void signon_cb(PurpleConnection *gc) { - PurpleBuddyList *list = purple_get_blist(); + PurpleBuddyList *list = purple_blist_get_buddy_list(); if (list && PURPLE_IS_GTK_BLIST(list) && !timer) { check_timeout(NULL); /* we want the box to be drawn immediately */ timer = purple_timeout_add_seconds(2, check_timeout, NULL); @@ -100,7 +100,7 @@ signon_cb(PurpleConnection *gc) static void signoff_cb(PurpleConnection *gc) { - PurpleBuddyList *list = purple_get_blist(); + PurpleBuddyList *list = purple_blist_get_buddy_list(); if ((!list || !PURPLE_IS_GTK_BLIST(list) || !PIDGIN_BLIST(list)->vbox) && timer) { purple_timeout_remove(timer); timer = 0; @@ -114,7 +114,7 @@ signoff_cb(PurpleConnection *gc) static gboolean plugin_load(PurplePlugin *plugin) { - PurpleBuddyList *list = purple_get_blist(); + PurpleBuddyList *list = purple_blist_get_buddy_list(); void *conn_handle = purple_connections_get_handle(); if (!check_timeout(NULL)) { diff --git a/pidgin/plugins/markerline.c b/pidgin/plugins/markerline.c index 461da4fd61..bf1e552187 100644 --- a/pidgin/plugins/markerline.c +++ b/pidgin/plugins/markerline.c @@ -45,15 +45,13 @@ static void update_marker_for_gtkconv(PidginConversation *gtkconv) { PurpleConversation *conv; - PurpleConversationType type; g_return_if_fail(gtkconv != NULL); conv = gtkconv->active_conv; - type = purple_conversation_get_type(conv); - if ((type == PURPLE_CONV_TYPE_CHAT && !purple_prefs_get_bool(PREF_CHATS)) || - (type == PURPLE_CONV_TYPE_IM && !purple_prefs_get_bool(PREF_IMS))) + if ((PURPLE_IS_CHAT_CONVERSATION(conv) && !purple_prefs_get_bool(PREF_CHATS)) || + (PURPLE_IS_IM_CONVERSATION(conv) && !purple_prefs_get_bool(PREF_IMS))) return; gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), @@ -166,9 +164,8 @@ jump_to_markerline(PurpleConversation *conv, gpointer null) static void conv_menu_cb(PurpleConversation *conv, GList **list) { - PurpleConversationType type = purple_conversation_get_type(conv); - gboolean enabled = ((type == PURPLE_CONV_TYPE_IM && purple_prefs_get_bool(PREF_IMS)) || - (type == PURPLE_CONV_TYPE_CHAT && purple_prefs_get_bool(PREF_CHATS))); + gboolean enabled = ((PURPLE_IS_IM_CONVERSATION(conv) && purple_prefs_get_bool(PREF_IMS)) || + (PURPLE_IS_CHAT_CONVERSATION(conv) && purple_prefs_get_bool(PREF_CHATS))); PurpleMenuAction *action = purple_menu_action_new(_("Jump to markerline"), enabled ? PURPLE_CALLBACK(jump_to_markerline) : NULL, NULL, NULL); *list = g_list_append(*list, action); diff --git a/pidgin/plugins/musicmessaging/musicmessaging.c b/pidgin/plugins/musicmessaging/musicmessaging.c index dd157d0262..0a481a5908 100644 --- a/pidgin/plugins/musicmessaging/musicmessaging.c +++ b/pidgin/plugins/musicmessaging/musicmessaging.c @@ -111,7 +111,7 @@ void music_messaging_change_request(const int session, const char *command, cons GString *to_send = g_string_new(""); g_string_append_printf(to_send, "##MM## request %s %s##MM##", command, parameters); - purple_conv_im_send(PURPLE_CONV_IM(mmconv->conv), to_send->str); + purple_conversation_send(mmconv->conv, to_send->str); purple_debug_misc("musicmessaging", "Sent request: %s\n", to_send->str); } @@ -131,7 +131,7 @@ void music_messaging_change_confirmed(const int session, const char *command, co GString *to_send = g_string_new(""); g_string_append_printf(to_send, "##MM## confirm %s %s##MM##", command, parameters); - purple_conv_im_send(PURPLE_CONV_IM(mmconv->conv), to_send->str); + purple_conversation_send(mmconv->conv, to_send->str); } else { /* Do nothing. If they aren't the originator, then they can't confirm. */ @@ -154,7 +154,7 @@ void music_messaging_change_failed(const int session, const char *id, const char GString *to_send = g_string_new(""); g_string_append_printf(to_send, "##MM## failed %s %s %s##MM##", id, command, parameters); - purple_conv_im_send(PURPLE_CONV_IM(mmconv->conv), to_send->str); + purple_conversation_send(mmconv->conv, to_send->str); } else { /* Do nothing. If they aren't the originator, then they can't confirm. */ @@ -261,6 +261,7 @@ mmconv_from_conv(PurpleConversation *conv) static gboolean plugin_load(PurplePlugin *plugin) { void *conv_list_handle; + GList *l; PURPLE_DBUS_RETURN_FALSE_IF_DISABLED(plugin); @@ -273,7 +274,8 @@ plugin_load(PurplePlugin *plugin) { plugin_pointer = plugin; /* Add the button to all the current conversations */ - purple_conversation_foreach (init_conversation); + for (l = purple_conversations_get_all(); l != NULL; l = l->next) + init_conversation((PurpleConversation *)l->data); /* Listen for any new conversations */ conv_list_handle = purple_conversations_get_handle(); diff --git a/pidgin/plugins/notify.c b/pidgin/plugins/notify.c index d8d6101e13..6a651ecf75 100644 --- a/pidgin/plugins/notify.c +++ b/pidgin/plugins/notify.c @@ -150,7 +150,7 @@ count_messages(PidginWindow *purplewin) for (convs = purplewin->gtkconvs; convs != NULL; convs = convs->next) { PidginConversation *conv = convs->data; for (l = conv->convs; l != NULL; l = l->next) { - count += GPOINTER_TO_INT(purple_conversation_get_data(l->data, "notify-message-count")); + count += GPOINTER_TO_INT(g_object_get_data(G_OBJECT(l->data), "notify-message-count")); } } @@ -173,9 +173,9 @@ notify(PurpleConversation *conv, gboolean increment) purplewin = PIDGIN_CONVERSATION(conv)->win; /* If we aren't doing notifications for this type of conversation, return */ - if (((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) && + if ((PURPLE_IS_IM_CONVERSATION(conv) && !purple_prefs_get_bool("/plugins/gtk/X11/notify/type_im")) || - ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) && + (PURPLE_IS_CHAT_CONVERSATION(conv) && !purple_prefs_get_bool("/plugins/gtk/X11/notify/type_chat"))) return 0; @@ -185,9 +185,9 @@ notify(PurpleConversation *conv, gboolean increment) if (purple_prefs_get_bool("/plugins/gtk/X11/notify/type_focused") || !has_focus) { if (increment) { - count = GPOINTER_TO_INT(purple_conversation_get_data(conv, "notify-message-count")); + count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "notify-message-count")); count++; - purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(count)); + g_object_set_data(G_OBJECT(conv), "notify-message-count", GINT_TO_POINTER(count)); } notify_win(purplewin, conv); @@ -237,7 +237,7 @@ unnotify(PurpleConversation *conv, gboolean reset) * removing it just to have it readded in re-notify is an * unnecessary couple extra RTs to the server */ handle_urgent(purplewin, FALSE); - purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0)); + g_object_set_data(G_OBJECT(conv), "notify-message-count", GINT_TO_POINTER(0)); /* Same logic as for the urgent hint, xprops are also a RT. * This needs to go here so that it gets the updated message * count. */ @@ -250,7 +250,7 @@ unnotify(PurpleConversation *conv, gboolean reset) static int unnotify_cb(GtkWidget *widget, gpointer data, PurpleConversation *conv) { - if (GPOINTER_TO_INT(purple_conversation_get_data(conv, "notify-message-count")) != 0) + if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "notify-message-count")) != 0) unnotify(conv, TRUE); return 0; @@ -260,7 +260,7 @@ static gboolean message_displayed_cb(PurpleAccount *account, const char *who, char *message, PurpleConversation *conv, PurpleMessageFlags flags) { - if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && + if ((PURPLE_IS_CHAT_CONVERSATION(conv) && purple_prefs_get_bool("/plugins/gtk/X11/notify/type_chat_nick") && !(flags & PURPLE_MESSAGE_NICK))) return FALSE; @@ -274,22 +274,22 @@ message_displayed_cb(PurpleAccount *account, const char *who, char *message, static void im_sent_im(PurpleAccount *account, const char *receiver, const char *message) { - PurpleConversation *conv = NULL; + PurpleIMConversation *im = NULL; if (purple_prefs_get_bool("/plugins/gtk/X11/notify/notify_send")) { - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, receiver, account); - unnotify(conv, TRUE); + im = purple_conversations_find_im_with_account(receiver, account); + unnotify(PURPLE_CONVERSATION(im), TRUE); } } static void chat_sent_im(PurpleAccount *account, const char *message, int id) { - PurpleConversation *conv = NULL; + PurpleChatConversation *chat = NULL; if (purple_prefs_get_bool("/plugins/gtk/X11/notify/notify_send")) { - conv = purple_find_chat(purple_account_get_connection(account), id); - unnotify(conv, TRUE); + chat = purple_conversations_find_chat(purple_account_get_connection(account), id); + unnotify(PURPLE_CONVERSATION(chat), TRUE); } } @@ -339,8 +339,8 @@ attach_signals(PurpleConversation *conv) entry_ids = g_slist_append(entry_ids, GUINT_TO_POINTER(id)); } - purple_conversation_set_data(conv, "notify-webview-signals", webview_ids); - purple_conversation_set_data(conv, "notify-entry-signals", entry_ids); + g_object_set_data(G_OBJECT(conv), "notify-webview-signals", webview_ids); + g_object_set_data(G_OBJECT(conv), "notify-entry-signals", entry_ids); return 0; } @@ -355,26 +355,26 @@ detach_signals(PurpleConversation *conv) if (!gtkconv) return; - ids = purple_conversation_get_data(conv, "notify-webview-signals"); + ids = g_object_get_data(G_OBJECT(conv), "notify-webview-signals"); for (l = ids; l != NULL; l = l->next) g_signal_handler_disconnect(gtkconv->webview, GPOINTER_TO_INT(l->data)); g_slist_free(ids); - ids = purple_conversation_get_data(conv, "notify-entry-signals"); + ids = g_object_get_data(G_OBJECT(conv), "notify-entry-signals"); for (l = ids; l != NULL; l = l->next) g_signal_handler_disconnect(gtkconv->entry, GPOINTER_TO_INT(l->data)); g_slist_free(ids); - purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0)); + g_object_set_data(G_OBJECT(conv), "notify-message-count", GINT_TO_POINTER(0)); - purple_conversation_set_data(conv, "notify-webview-signals", NULL); - purple_conversation_set_data(conv, "notify-entry-signals", NULL); + g_object_set_data(G_OBJECT(conv), "notify-webview-signals", NULL); + g_object_set_data(G_OBJECT(conv), "notify-entry-signals", NULL); } static void conv_created(PurpleConversation *conv) { - purple_conversation_set_data(conv, "notify-message-count", + g_object_set_data(G_OBJECT(conv), "notify-message-count", GINT_TO_POINTER(0)); /* always attach the signals, notify() will take care of conversation @@ -423,7 +423,7 @@ deleting_conv(PurpleConversation *conv) purplewin = gtkconv->win; handle_urgent(purplewin, FALSE); - purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0)); + g_object_set_data(G_OBJECT(conv), "notify-message-count", GINT_TO_POINTER(0)); return; @@ -454,7 +454,7 @@ conversation_dragging(PurpleConversation *active_conv, printf("if else count = %d\n", count_messages(old_purplewin)); /* PurpleConversation *old_active_conv = NULL; - old_active_conv = purple_conv_window_get_active_conversation(new_purplewin); + old_active_conv = purple_conversation_window_get_active_conversation(new_purplewin); purple_conversation_autoset_title(old_active_conv); handle_urgent(old_purplewin, FALSE); @@ -636,14 +636,14 @@ apply_method() { GList *convs; - for (convs = purple_get_conversations(); convs != NULL; + for (convs = purple_conversations_get_all(); convs != NULL; convs = convs->next) { PurpleConversation *conv = (PurpleConversation *)convs->data; /* remove notifications */ unnotify(conv, FALSE); - if (GPOINTER_TO_INT(purple_conversation_get_data(conv, "notify-message-count")) != 0) + if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(conv), "notify-message-count")) != 0) /* reattach appropriate notifications */ notify(conv, FALSE); } @@ -652,7 +652,7 @@ apply_method() static void apply_notify() { - GList *convs = purple_get_conversations(); + GList *convs = purple_conversations_get_all(); while (convs) { PurpleConversation *conv = (PurpleConversation *)convs->data; @@ -836,7 +836,7 @@ get_config_frame(PurplePlugin *plugin) static gboolean plugin_load(PurplePlugin *plugin) { - GList *convs = purple_get_conversations(); + GList *convs = purple_conversations_get_all(); void *conv_handle = purple_conversations_get_handle(); void *gtk_conv_handle = pidgin_conversations_get_handle(); @@ -876,7 +876,7 @@ plugin_load(PurplePlugin *plugin) static gboolean plugin_unload(PurplePlugin *plugin) { - GList *convs = purple_get_conversations(); + GList *convs = purple_conversations_get_all(); while (convs) { PurpleConversation *conv = (PurpleConversation *)convs->data; diff --git a/pidgin/plugins/perl/common/GtkAccount.xs b/pidgin/plugins/perl/common/GtkAccount.xs index 9a8eb69c5b..8f1195384c 100644 --- a/pidgin/plugins/perl/common/GtkAccount.xs +++ b/pidgin/plugins/perl/common/GtkAccount.xs @@ -4,7 +4,7 @@ MODULE = Pidgin::Account PACKAGE = Pidgin::Account PREFIX = pidgin_account_ PROTOTYPES: ENABLE Purple::Handle -pidgin_account_get_handle() +pidgin_accounts_get_handle() MODULE = Pidgin::Account PACKAGE = Pidgin::Account::Dialog PREFIX = pidgin_account_dialog_ PROTOTYPES: ENABLE diff --git a/pidgin/plugins/perl/common/GtkConv.xs b/pidgin/plugins/perl/common/GtkConv.xs index 042a43c871..6ec68b6710 100644 --- a/pidgin/plugins/perl/common/GtkConv.xs +++ b/pidgin/plugins/perl/common/GtkConv.xs @@ -4,8 +4,8 @@ MODULE = Pidgin::Conversation PACKAGE = Pidgin::Conversation PREFIX = pidgin_c PROTOTYPES: ENABLE void -pidgin_conv_update_buddy_icon(conv) - Purple::Conversation conv +pidgin_conv_update_buddy_icon(im) + Purple::IMConversation im void pidgin_conv_switch_active_conversation(conv) @@ -46,8 +46,19 @@ MODULE = Pidgin::Conversation PACKAGE = Pidgin::Conversations PREFIX = pidgin_ PROTOTYPES: ENABLE void -pidgin_conversations_find_unseen_list(type, min_state, hidden_only, max_count) - Purple::ConversationType type +pidgin_conversations_get_unseen_all(min_state, hidden_only, max_count) + Pidgin::UnseenState min_state + gboolean hidden_only + guint max_count + +void +pidgin_conversations_get_unseen_ims(min_state, hidden_only, max_count) + Pidgin::UnseenState min_state + gboolean hidden_only + guint max_count + +void +pidgin_conversations_get_unseen_chats(min_state, hidden_only, max_count) Pidgin::UnseenState min_state gboolean hidden_only guint max_count diff --git a/pidgin/plugins/perl/common/GtkConvWin.xs b/pidgin/plugins/perl/common/GtkConvWin.xs index 1fc71ffdce..948daf438f 100644 --- a/pidgin/plugins/perl/common/GtkConvWin.xs +++ b/pidgin/plugins/perl/common/GtkConvWin.xs @@ -74,12 +74,16 @@ pidgin_conv_window_get_gtkconv_count(win) Pidgin::Conversation::Window win Pidgin::Conversation::Window -pidgin_conv_window_first_with_type(type) - Purple::ConversationType type +pidgin_conv_window_first_im() Pidgin::Conversation::Window -pidgin_conv_window_last_with_type(type) - Purple::ConversationType type +pidgin_conv_window_last_im() + +Pidgin::Conversation::Window +pidgin_conv_window_first_chat() + +Pidgin::Conversation::Window +pidgin_conv_window_last_chat() MODULE = Pidgin::Conversation::Window PACKAGE = Pidgin::Conversation::Placement PREFIX = pidgin_conv_placement_ PROTOTYPES: ENABLE diff --git a/pidgin/plugins/pidgininc.c b/pidgin/plugins/pidgininc.c index 7e03243371..8078c5ba55 100644 --- a/pidgin/plugins/pidgininc.c +++ b/pidgin/plugins/pidgininc.c @@ -49,9 +49,9 @@ static void bud(PurpleBuddy *who) { PurpleAccount *acct = who->account; - PurpleConversation *conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, who->name); + PurpleConversation *conv = purple_im_conversation_new(acct, who->name); - purple_conv_im_send(PURPLE_CONV_IM(conv), "Hello!"); + purple_im_conversation_send(PURPLE_CONV_IM(conv), "Hello!"); } /* diff --git a/pidgin/plugins/sendbutton.c b/pidgin/plugins/sendbutton.c index 943ee0568a..8fdc4eb383 100644 --- a/pidgin/plugins/sendbutton.c +++ b/pidgin/plugins/sendbutton.c @@ -117,7 +117,7 @@ conversation_displayed_cb(PidginConversation *gtkconv) static gboolean plugin_load(PurplePlugin *plugin) { - GList *convs = purple_get_conversations(); + GList *convs = purple_conversations_get_all(); void *gtk_conv_handle = pidgin_conversations_get_handle(); purple_signal_connect(gtk_conv_handle, "conversation-displayed", plugin, @@ -145,7 +145,7 @@ plugin_load(PurplePlugin *plugin) static gboolean plugin_unload(PurplePlugin *plugin) { - GList *convs = purple_get_conversations(); + GList *convs = purple_conversations_get_all(); while (convs) { PurpleConversation *conv = (PurpleConversation *)convs->data; diff --git a/pidgin/plugins/spellchk.c b/pidgin/plugins/spellchk.c index 54eda50439..40b345c1c3 100644 --- a/pidgin/plugins/spellchk.c +++ b/pidgin/plugins/spellchk.c @@ -2119,7 +2119,7 @@ plugin_load(PurplePlugin *plugin) load_conf(); /* Attach to existing conversations */ - for (convs = purple_get_conversations(); convs != NULL; convs = convs->next) + for (convs = purple_conversations_get_all(); convs != NULL; convs = convs->next) { spellchk_new_attach((PurpleConversation *)convs->data); } @@ -2136,7 +2136,7 @@ plugin_unload(PurplePlugin *plugin) GList *convs; /* Detach from existing conversations */ - for (convs = purple_get_conversations(); convs != NULL; convs = convs->next) + for (convs = purple_conversations_get_all(); convs != NULL; convs = convs->next) { PidginConversation *gtkconv = PIDGIN_CONVERSATION((PurpleConversation *)convs->data); spellchk *spell = g_object_get_data(G_OBJECT(gtkconv->entry), SPELLCHK_OBJECT_KEY); diff --git a/pidgin/plugins/themeedit-icon.c b/pidgin/plugins/themeedit-icon.c index 252423f7d4..9d54051614 100644 --- a/pidgin/plugins/themeedit-icon.c +++ b/pidgin/plugins/themeedit-icon.c @@ -180,7 +180,7 @@ use_icon_theme(GtkWidget *w, GtkWidget *window) PidginStatusIconTheme *theme = create_icon_theme(window); pidgin_stock_load_status_icon_theme(PIDGIN_STATUS_ICON_THEME(theme)); pidgin_stock_load_stock_icon_theme((PidginStockIconTheme *)theme); - pidgin_blist_refresh(purple_get_blist()); + pidgin_blist_refresh(purple_blist_get_buddy_list()); g_object_unref(theme); } diff --git a/pidgin/plugins/themeedit.c b/pidgin/plugins/themeedit.c index 3263f4225e..36f0f1d690 100644 --- a/pidgin/plugins/themeedit.c +++ b/pidgin/plugins/themeedit.c @@ -98,7 +98,7 @@ theme_font_face_selected(GtkWidget *dialog, gint response, gpointer font) if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY) { const char *fontname = gtk_font_chooser_get_font(GTK_FONT_CHOOSER(dialog)); pidgin_theme_font_set_font_face(font, fontname); - pidgin_blist_refresh(purple_get_blist()); + pidgin_blist_refresh(purple_blist_get_buddy_list()); } gtk_widget_destroy(dialog); } diff --git a/pidgin/plugins/ticker/ticker.c b/pidgin/plugins/ticker/ticker.c index ea26d0fb88..c91e1a82b5 100644 --- a/pidgin/plugins/ticker/ticker.c +++ b/pidgin/plugins/ticker/ticker.c @@ -27,7 +27,7 @@ #include "internal.h" #include "pidgin.h" -#include "blist.h" +#include "buddylist.h" #include "conversation.h" #include "debug.h" #include "prpl.h" @@ -92,10 +92,9 @@ static gboolean buddy_click_cb(GtkWidget *widget, GdkEventButton *event, gpointe PurpleContact *contact = user_data; PurpleBuddy *b = purple_contact_get_priority_buddy(contact); - PurpleConversation *conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, - purple_buddy_get_account(b), - purple_buddy_get_name(b)); - purple_conversation_present(conv); + PurpleIMConversation *im = purple_im_conversation_new(purple_buddy_get_account(b), + purple_buddy_get_name(b)); + purple_conversation_present(PURPLE_CONVERSATION(im)); return TRUE; } @@ -235,21 +234,21 @@ static void buddy_ticker_show(void) gnode; gnode = purple_blist_node_get_sibling_next(gnode)) { - if(!PURPLE_BLIST_NODE_IS_GROUP(gnode)) + if(!PURPLE_IS_GROUP(gnode)) continue; for(cnode = purple_blist_node_get_first_child(gnode); cnode; cnode = purple_blist_node_get_sibling_next(cnode)) { - if(!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) + if(!PURPLE_IS_CONTACT(cnode)) continue; for(bnode = purple_blist_node_get_first_child(cnode); bnode; bnode = purple_blist_node_get_sibling_next(bnode)) { - if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + if(!PURPLE_IS_BUDDY(bnode)) continue; - b = (PurpleBuddy *)bnode; + b = PURPLE_BUDDY(bnode); if(PURPLE_BUDDY_IS_ONLINE(b)) buddy_ticker_add_buddy(b); } diff --git a/pidgin/plugins/win32/transparency/win2ktrans.c b/pidgin/plugins/win32/transparency/win2ktrans.c index 4e2eb82d05..efade65b7a 100644 --- a/pidgin/plugins/win32/transparency/win2ktrans.c +++ b/pidgin/plugins/win32/transparency/win2ktrans.c @@ -43,9 +43,9 @@ */ #define WINTRANS_PLUGIN_ID "gtk-win-trans" -#define blist (purple_get_blist() \ - ? (PIDGIN_BLIST(purple_get_blist()) \ - ? ((PIDGIN_BLIST(purple_get_blist()))->window) \ +#define blist (purple_blist_get_buddy_list() \ + ? (PIDGIN_BLIST(purple_blist_get_buddy_list()) \ + ? ((PIDGIN_BLIST(purple_blist_get_buddy_list()))->window) \ : NULL) \ : NULL) @@ -386,11 +386,11 @@ static void update_convs_wintrans(GtkWidget *toggle_btn, const char *pref) { } static void -conv_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type) { +conv_updated_cb(PurpleConversation *conv, PurpleConversationUpdateType type) { PidginConversation *pconv = PIDGIN_CONVERSATION(conv); PidginWindow *win = pidgin_conv_get_window(pconv); - if (type == PURPLE_CONV_UPDATE_UNSEEN && !pidgin_conv_is_hidden(pconv) + if (type == PURPLE_CONVERSATION_UPDATE_UNSEEN && !pidgin_conv_is_hidden(pconv) && pconv->unseen_state == PIDGIN_UNSEEN_NONE && pidgin_conv_window_get_gtkconv_count(win) == 1) { GtkWidget *window = win->window; diff --git a/pidgin/plugins/win32/winprefs/winprefs.c b/pidgin/plugins/win32/winprefs/winprefs.c index e92c718729..cc3d3a1414 100644 --- a/pidgin/plugins/win32/winprefs/winprefs.c +++ b/pidgin/plugins/win32/winprefs/winprefs.c @@ -88,7 +88,7 @@ static void blist_set_ontop(gboolean val) { if(!blist) return; - gtk_window_set_keep_above(GTK_WINDOW(PIDGIN_BLIST(purple_get_blist())->window), val); + gtk_window_set_keep_above(GTK_WINDOW(PIDGIN_BLIST(purple_blist_get_buddy_list())->window), val); } static void blist_dock_cb(gboolean val) { @@ -233,9 +233,9 @@ static gboolean plugin_load(PurplePlugin *plugin) { handle = plugin; /* blist docking init */ - if(purple_get_blist() && PIDGIN_BLIST(purple_get_blist()) - && PIDGIN_BLIST(purple_get_blist())->window) { - blist_create_cb(purple_get_blist(), NULL); + if(purple_blist_get_buddy_list() && PIDGIN_BLIST(purple_blist_get_buddy_list()) + && PIDGIN_BLIST(purple_blist_get_buddy_list())->window) { + blist_create_cb(purple_blist_get_buddy_list(), NULL); } /* This really shouldn't happen anymore generally, but if for some strange |