# HG changeset patch # User Paul Aurich # Date 1239496981 0 # Node ID 178718b181e4f134017916116b7903425422d822 # Parent acee7d2b1983888048c270bbab7ece134b73dfd0# Parent e7861a7978dcd7489e7709327542655edc4c1b09 propagate from branch 'im.pidgin.pidgin' (head e7a572653bbe02d5d4ec2efc43c303629911993b) to branch 'im.pidgin.cpw.darkrain42.xmpp.bosh' (head 96588eb41bf6a5544a8d0ffb7f7f7e5f82b4c38b) diff -r acee7d2b1983 -r 178718b181e4 COPYRIGHT --- a/COPYRIGHT Sat Apr 11 21:20:31 2009 +0000 +++ b/COPYRIGHT Sun Apr 12 00:43:01 2009 +0000 @@ -30,6 +30,7 @@ Derek Battams Martin Bayard Curtis Beattie +Carlos Bederian Dave Bell Igor Belyi Brian Bernas diff -r acee7d2b1983 -r 178718b181e4 ChangeLog --- a/ChangeLog Sat Apr 11 21:20:31 2009 +0000 +++ b/ChangeLog Sun Apr 12 00:43:01 2009 +0000 @@ -8,6 +8,8 @@ in a group on the buddy list. * Removed the unmaintained and unneeded toc protocol plugin. * Fixed NTLM authentication on big-endian systems. + * Dragging a buddy onto a chat pops up a chat-invitation dialog. + (Carlos Bederian) libpurple: * Various memory cleanups when unloading libpurple. (Nick Hebner) diff -r acee7d2b1983 -r 178718b181e4 ChangeLog.API --- a/ChangeLog.API Sat Apr 11 21:20:31 2009 +0000 +++ b/ChangeLog.API Sun Apr 12 00:43:01 2009 +0000 @@ -22,6 +22,7 @@ * purple_connection_get_protocol_data * purple_connection_set_protocol_data * purple_contact_destroy + * purple_conv_chat_invite_user * purple_global_proxy_set_info * purple_group_destroy * purple_log_get_activity_score diff -r acee7d2b1983 -r 178718b181e4 finch/gntconv.c --- a/finch/gntconv.c Sat Apr 11 21:20:31 2009 +0000 +++ b/finch/gntconv.c Sun Apr 12 00:43:01 2009 +0000 @@ -559,44 +559,11 @@ } static void -invite_select_cb(FinchConv *fc, PurpleRequestFields *fields) -{ - PurpleConversation *conv = fc->active_conv; - const char *buddy = purple_request_fields_get_string(fields, "screenname"); - const char *message = purple_request_fields_get_string(fields, "message"); - serv_chat_invite(purple_conversation_get_gc(conv), - purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), - message, buddy); - -} - -static void invite_cb(GntMenuItem *item, gpointer ggconv) { - PurpleRequestFields *fields; - PurpleRequestFieldGroup *group; - PurpleRequestField *field; - - fields = purple_request_fields_new(); - - group = purple_request_field_group_new(NULL); - purple_request_fields_add_group(fields, group); - - field = purple_request_field_string_new("screenname", _("Name"), NULL, FALSE); - purple_request_field_set_type_hint(field, "screenname"); - purple_request_field_set_required(field, TRUE); - purple_request_field_group_add_field(group, field); - field = purple_request_field_string_new("message", _("Invite message"), NULL, FALSE); - purple_request_field_group_add_field(group, field); - purple_request_fields(finch_conv_get_handle(), _("Invite"), - NULL, - _("Please enter the name of the user " - "you wish to invite,\nalong with an optional invite message."), - fields, - _("OK"), G_CALLBACK(invite_select_cb), - _("Cancel"), NULL, - NULL, NULL, NULL, - ggconv); + FinchConv *fc = ggconv; + PurpleConversation *conv = fc->active_conv; + purple_conv_chat_invite_user(PURPLE_CONV_CHAT(conv), NULL, NULL, TRUE); } static void diff -r acee7d2b1983 -r 178718b181e4 finch/gntmedia.c --- a/finch/gntmedia.c Sat Apr 11 21:20:31 2009 +0000 +++ b/finch/gntmedia.c Sun Apr 12 00:43:01 2009 +0000 @@ -37,11 +37,11 @@ #include "cmds.h" #include "conversation.h" #include "debug.h" -#include "media-gst.h" #include "mediamanager.h" /* An incredibly large part of the following is from gtkmedia.c */ #ifdef USE_VV +#include "media-gst.h" #undef hangup diff -r acee7d2b1983 -r 178718b181e4 libpurple/account.c --- a/libpurple/account.c Sat Apr 11 21:20:31 2009 +0000 +++ b/libpurple/account.c Sun Apr 12 00:43:01 2009 +0000 @@ -2787,7 +2787,6 @@ void purple_accounts_uninit(void) { - GList* account; gpointer handle = purple_accounts_get_handle(); if (save_timer != 0) { @@ -2799,9 +2798,6 @@ purple_signals_disconnect_by_handle(handle); purple_signals_unregister_by_instance(handle); - account = purple_accounts_get_all(); - while (account) { - purple_account_destroy(account->data); - account = g_list_delete_link(account, account); - } + for (; accounts; accounts = g_list_delete_link(accounts, accounts)) + purple_account_destroy(accounts->data); } diff -r acee7d2b1983 -r 178718b181e4 libpurple/blist.c --- a/libpurple/blist.c Sat Apr 11 21:20:31 2009 +0000 +++ b/libpurple/blist.c Sun Apr 12 00:43:01 2009 +0000 @@ -699,10 +699,23 @@ return purplebuddylist ? purplebuddylist->root : NULL; } -GHashTable * +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() { - return purplebuddylist ? purplebuddylist->buddies : NULL; + GSList *buddies = NULL; + + if (!purplebuddylist) + return NULL; + + g_hash_table_foreach(purplebuddylist->buddies, append_buddy, &buddies); + return buddies; } void * @@ -2616,7 +2629,7 @@ purple_blist_node_destroy(PurpleBlistNode *node) { PurpleBlistNode *child, *next_child; - + child = node->child; while (child) { next_child = child->next; @@ -2936,6 +2949,7 @@ purple_blist_node_destroy(node); node = next_node; } + purplebuddylist->root = NULL; purple_signals_unregister_by_instance(purple_blist_get_handle()); } diff -r acee7d2b1983 -r 178718b181e4 libpurple/blist.h --- a/libpurple/blist.h Sat Apr 11 21:20:31 2009 +0000 +++ b/libpurple/blist.h Sun Apr 12 00:43:01 2009 +0000 @@ -260,13 +260,14 @@ PurpleBlistNode *purple_blist_get_root(void); /** - * Returns the hash table of every buddy in the list. + * Returns a list of every buddy in the list. * - * @return The hash table of every buddy in the list. + * @return A list of every buddy in the list. Caller is responsible for + * freeing the list. * * @since 2.6.0 */ -GHashTable *purple_blist_get_buddies(void); +GSList *purple_blist_get_buddies(void); /** * Returns the UI data for the list. diff -r acee7d2b1983 -r 178718b181e4 libpurple/conversation.c --- a/libpurple/conversation.c Sat Apr 11 21:20:31 2009 +0000 +++ b/libpurple/conversation.c Sun Apr 12 00:43:01 2009 +0000 @@ -2005,6 +2005,66 @@ purple_conversation_update(chat->conv, PURPLE_CONV_UPDATE_CHATLEFT); } +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_gc(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) { diff -r acee7d2b1983 -r 178718b181e4 libpurple/conversation.h --- a/libpurple/conversation.h Sat Apr 11 21:20:31 2009 +0000 +++ b/libpurple/conversation.h Sun Apr 12 00:43:01 2009 +0000 @@ -1300,6 +1300,22 @@ void purple_conv_chat_left(PurpleConvChat *chat); /** + * 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 #user or #message is @c NULL. + * + * @since 2.6.0 + */ +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. * diff -r acee7d2b1983 -r 178718b181e4 libpurple/media.c --- a/libpurple/media.c Sat Apr 11 21:20:31 2009 +0000 +++ b/libpurple/media.c Sun Apr 12 00:43:01 2009 +0000 @@ -31,12 +31,15 @@ #include "account.h" #include "marshallers.h" #include "media.h" -#include "media-gst.h" #include "mediamanager.h" #include "network.h" #include "debug.h" +#ifdef USE_GSTREAMER +#include "media-gst.h" +#endif + #ifdef USE_VV #include @@ -1909,6 +1912,7 @@ } #endif +#ifdef USE_GSTREAMER GstElement * purple_media_get_src(PurpleMedia *media, const gchar *sess_id) { @@ -1921,6 +1925,7 @@ return NULL; #endif } +#endif /* USE_GSTREAMER */ #ifdef USE_VV static PurpleMediaSession * @@ -3035,6 +3040,7 @@ #endif } +#ifdef USE_GSTREAMER GstElement * purple_media_get_tee(PurpleMedia *media, const gchar *session_id, const gchar *participant) @@ -3057,6 +3063,7 @@ return NULL; #endif } +#endif /* USE_GSTREAMER */ gboolean purple_media_transmitter_exists(const gchar *transmitter) diff -r acee7d2b1983 -r 178718b181e4 libpurple/mediamanager.c --- a/libpurple/mediamanager.c Sat Apr 11 21:20:31 2009 +0000 +++ b/libpurple/mediamanager.c Sun Apr 12 00:43:01 2009 +0000 @@ -30,8 +30,11 @@ #include "debug.h" #include "marshallers.h" #include "media.h" +#include "mediamanager.h" + +#ifdef USE_GSTREAMER #include "media-gst.h" -#include "mediamanager.h" +#endif #ifdef USE_VV @@ -218,6 +221,7 @@ } #endif +#ifdef USE_GSTREAMER GstElement * purple_media_manager_get_pipeline(PurpleMediaManager *manager) { @@ -246,6 +250,7 @@ return NULL; #endif } +#endif /* USE_GSTREAMER */ PurpleMedia * purple_media_manager_create_media(PurpleMediaManager *manager, @@ -366,6 +371,7 @@ } #endif +#ifdef USE_GSTREAMER GstElement * purple_media_manager_get_element(PurpleMediaManager *manager, PurpleMediaSessionType type, PurpleMedia *media, @@ -611,6 +617,7 @@ return NULL; } +#endif /* USE_GSTREAMER */ #ifdef USE_VV static void @@ -844,6 +851,7 @@ #endif } +#ifdef USE_GSTREAMER /* * PurpleMediaElementType @@ -1115,3 +1123,5 @@ return NULL; } +#endif /* USE_GSTREAMER */ + diff -r acee7d2b1983 -r 178718b181e4 libpurple/protocols/bonjour/jabber.c --- a/libpurple/protocols/bonjour/jabber.c Sat Apr 11 21:20:31 2009 +0000 +++ b/libpurple/protocols/bonjour/jabber.c Sun Apr 12 00:43:01 2009 +0000 @@ -237,7 +237,7 @@ }; static void -_match_buddies_by_address(gpointer key, gpointer value, gpointer data) +_match_buddies_by_address(gpointer value, gpointer data) { PurpleBuddy *pb = value; PurpleAccount *account = NULL; @@ -638,6 +638,7 @@ char *address_text = NULL; struct _match_buddies_by_address_t *mbba; BonjourJabberConversation *bconv; + GSList *buddies; /* Check that it is a read condition */ if (condition != PURPLE_INPUT_READ) @@ -658,7 +659,10 @@ mbba = g_new0(struct _match_buddies_by_address_t, 1); mbba->address = address_text; mbba->jdata = jdata; - g_hash_table_foreach(purple_blist_get_buddies(), _match_buddies_by_address, mbba); + + buddies = purple_blist_get_buddies(); + g_slist_foreach(buddies, _match_buddies_by_address, mbba); + g_slist_free(buddies); if (mbba->matched_buddies == NULL) { purple_debug_info("bonjour", "We don't like invisible buddies, this is not a superheros comic\n"); @@ -850,11 +854,15 @@ bonjour_jabber_conv_match_by_ip(BonjourJabberConversation *bconv) { BonjourJabber *jdata = ((BonjourData*) bconv->account->gc->proto_data)->jabber_data; struct _match_buddies_by_address_t *mbba; + GSList *buddies; mbba = g_new0(struct _match_buddies_by_address_t, 1); mbba->address = bconv->ip; mbba->jdata = jdata; - g_hash_table_foreach(purple_blist_get_buddies(), _match_buddies_by_address, mbba); + + buddies = purple_blist_get_buddies(); + g_slist_foreach(buddies, _match_buddies_by_address, mbba); + g_slist_free(buddies); /* If there is exactly one match, use it */ if(mbba->matched_buddies != NULL) { diff -r acee7d2b1983 -r 178718b181e4 libpurple/protocols/yahoo/yahoo.c --- a/libpurple/protocols/yahoo/yahoo.c Sat Apr 11 21:20:31 2009 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Sun Apr 12 00:43:01 2009 +0000 @@ -4416,7 +4416,7 @@ "Cookie: T=%s; path=/; domain=.yahoo.com; Y=%s; path=/; domain=.yahoo.com;\r\n" "User-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\n" "Host: validate.msg.yahoo.com\r\n" - "Content-Length: %d\r\n" + "Content-Length: %" G_GSIZE_FORMAT "\r\n" "Cache-Control: no-cache\r\n\r\n%s", YAHOO_CLIENT_VERSION, yd->cookie_t, yd->cookie_y, strlen(validate_request_str), validate_request_str); diff -r acee7d2b1983 -r 178718b181e4 libpurple/protocols/yahoo/yahoo_filexfer.c --- a/libpurple/protocols/yahoo/yahoo_filexfer.c Sat Apr 11 21:20:31 2009 +0000 +++ b/libpurple/protocols/yahoo/yahoo_filexfer.c Sun Apr 12 00:43:01 2009 +0000 @@ -1385,7 +1385,13 @@ strcpy(time_str + strlen(time_str) - 1, "\0"); if (xd->txbuflen == 0) { - xd->txbuf = g_strdup_printf("HTTP/1.0 200 OK\r\nDate: %s GMT\r\nServer: Y!/1.0\r\nMIME-version: 1.0\r\nLast-modified: %s GMT\r\nContent-length: %d\r\n\r\n", time_str, time_str, xfer->size); + xd->txbuf = g_strdup_printf("HTTP/1.0 200 OK\r\n" + "Date: %s GMT\r\n" + "Server: Y!/1.0\r\n" + "MIME-version: 1.0\r\n" + "Last-modified: %s GMT\r\n" + "Content-length: %" G_GSIZE_FORMAT "\r\n\r\n", + time_str, time_str, xfer->size); xd->txbuflen = strlen(xd->txbuf); xd->txbuf_written = 0; } diff -r acee7d2b1983 -r 178718b181e4 pidgin/gtkconv.c --- a/pidgin/gtkconv.c Sat Apr 11 21:20:31 2009 +0000 +++ b/pidgin/gtkconv.c Sun Apr 12 00:43:01 2009 +0000 @@ -4981,11 +4981,17 @@ PurpleConversation *conv = gtkconv->active_conv; PidginWindow *win = gtkconv->win; PurpleConversation *c; + PurpleAccount *convaccount = purple_conversation_get_account(conv); + PurpleConnection *gc = purple_account_get_connection(convaccount); + PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl) : NULL; + if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE)) { PurpleBlistNode *n = NULL; PurpleBuddy *b; PidginConversation *gtkconv = NULL; + PurpleAccount *buddyaccount; + const char *buddyname; n = *(PurpleBlistNode **)sd->data; @@ -4996,32 +5002,44 @@ else return; + buddyaccount = purple_buddy_get_account(b); + buddyname = purple_buddy_get_name(b); /* - * 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. + * If a buddy is dragged to a chat window of the same protocol, + * invite him to the chat. */ - c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, b->name, b->account); - if (c != NULL) { - PidginWindow *oldwin; - gtkconv = PIDGIN_CONVERSATION(c); - oldwin = gtkconv->win; - if (oldwin != win) { - pidgin_conv_window_remove_gtkconv(oldwin, gtkconv); - pidgin_conv_window_add_gtkconv(win, gtkconv); - } + if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && + 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); } else { - c = purple_conversation_new(PURPLE_CONV_TYPE_IM, b->account, b->name); - gtkconv = PIDGIN_CONVERSATION(c); - if (gtkconv->win != win) - { - pidgin_conv_window_remove_gtkconv(gtkconv->win, gtkconv); - pidgin_conv_window_add_gtkconv(win, gtkconv); + /* + * 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) { + PidginWindow *oldwin; + gtkconv = PIDGIN_CONVERSATION(c); + 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); + if (gtkconv->win != win) { + pidgin_conv_window_remove_gtkconv(gtkconv->win, gtkconv); + pidgin_conv_window_add_gtkconv(win, gtkconv); + } } - } - - /* Make this conversation the active conversation */ - pidgin_conv_window_switch_gtkconv(win, gtkconv); + + /* Make this conversation the active conversation */ + pidgin_conv_window_switch_gtkconv(win, gtkconv); + } gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); } @@ -5040,15 +5058,22 @@ purple_notify_error(win, NULL, _("You are not currently signed on with an account that " "can add that buddy."), NULL); - } - else - { - c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, username); - gtkconv = PIDGIN_CONVERSATION(c); - if (gtkconv->win != win) - { - pidgin_conv_window_remove_gtkconv(gtkconv->win, gtkconv); - pidgin_conv_window_add_gtkconv(win, gtkconv); + } else { + /* + * 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 && + 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); + } else { + c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, username); + gtkconv = PIDGIN_CONVERSATION(c); + if (gtkconv->win != win) { + pidgin_conv_window_remove_gtkconv(gtkconv->win, gtkconv); + pidgin_conv_window_add_gtkconv(win, gtkconv); + } } } } @@ -5060,7 +5085,7 @@ } else if (sd->target == gdk_atom_intern("text/uri-list", FALSE)) { if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) - pidgin_dnd_file_manage(sd, purple_conversation_get_account(conv), purple_conversation_get_name(conv)); + pidgin_dnd_file_manage(sd, convaccount, purple_conversation_get_name(conv)); gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); } else @@ -6801,7 +6826,8 @@ wrote_msg_update_unseen_cb(PurpleAccount *account, const char *who, const char *message, PurpleConversation *conv, PurpleMessageFlags flags, gpointer null) { - if (conv == NULL || PIDGIN_IS_PIDGIN_CONVERSATION(conv)) + PidginConversation *gtkconv = conv ? PIDGIN_CONVERSATION(conv) : NULL; + if (conv == NULL || (gtkconv && gtkconv->win != hidden_convwin)) return; if (flags & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV)) { PidginUnseenState unseen = PIDGIN_UNSEEN_NONE;