Mercurial > pidgin
changeset 29218:a78a44f0cdcd
merge of '6a184b4a50c778257ab194f0339b91beda1f97c8'
and 'd6d5f18ff695ad46c11336cf3301aa955b41d5bb'
author | John Bailey <rekkanoryo@rekkanoryo.org> |
---|---|
date | Sat, 31 Oct 2009 17:49:11 +0000 |
parents | 7819d3819f4c (diff) fd2afe1b2d3c (current diff) |
children | e3206d6da6c7 |
files | ChangeLog pidgin/gtkutils.c |
diffstat | 27 files changed, 378 insertions(+), 56 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Thu Oct 15 10:45:22 2009 +0000 +++ b/ChangeLog Sat Oct 31 17:49:11 2009 +0000 @@ -13,15 +13,20 @@ * Moved the Translator information from the About box to a "Translator Information" dialog accessible on the Help menu. -version 2.6.3 (??/??/20??): +version 2.6.4 (??/??/20??): + libpurple: + * Actually emit the hold signal for media calls. + General: * New 'plugins' sub-command to 'debug' command (i.e. '/debug plugins') to announce the list of loaded plugins (in both Finch and Pidgin). - * Fix a crash when performing DNS queries on Unixes that use the - blocking DNS lookups. (Brian Lu) * Fix building the GnuTLS plugin with older versions of GnuTLS. * Fix DNS TXT query resolution. + MSN: + * Don't forget display names for buddies. + * Fix a random crash that might occur when idle. + XMPP: * Users connecting to Google Talk now have an "Initiate Chat" context menu option for their buddies. (Eion Robb) @@ -46,6 +51,17 @@ Pidgin: * The userlist in a multiuser chat can be styled via gtkrc by using the widget name "pidgin_conv_userlist". (Heiko Schmitt) + * Add a hold button to the media window. + +version 2.6.3 (10/16/2009): + General: + * Fix a crash when performing DNS queries on Unixes that use the + blocking DNS lookups. (Brian Lu) + + AIM and ICQ: + * Fix a crash when some clients send contacts in a format we don't + understand. + * Fix blocking and other privacy lists. (Thanks to AOL) version 2.6.2 (09/05/2009): libpurple:
--- a/ChangeLog.API Thu Oct 15 10:45:22 2009 +0000 +++ b/ChangeLog.API Sat Oct 31 17:49:11 2009 +0000 @@ -5,7 +5,11 @@ Added: * purple_account_get_name_for_display * purple_network_get_all_local_system_ips + * purple_prpl_got_media_caps * purple_uuid_random + * media_caps to the PurpleBuddy struct + * buddy-caps-changed blist signal + * ui-caps-changed media manager signal Pidgin: Added: @@ -13,6 +17,9 @@ * pidgin_dialogs_developers (should not be used by anything but Pidgin) * pidgin_dialogs_translators (should not be used by anything but Pidgin) +version 2.6.3 (10/16/2009): + No changes + version 2.6.2 (09/05/2009): Perl: Added:
--- a/ChangeLog.win32 Thu Oct 15 10:45:22 2009 +0000 +++ b/ChangeLog.win32 Sat Oct 31 17:49:11 2009 +0000 @@ -2,6 +2,9 @@ * Minimum required GTK+ version increased to 2.14.0 * Win9x no longer supported. +version 2.6.3 (10/16/2009): + * No changes + version 2.6.2 (09/05/2009): * No changes
--- a/NEWS Thu Oct 15 10:45:22 2009 +0000 +++ b/NEWS Sat Oct 31 17:49:11 2009 +0000 @@ -2,6 +2,11 @@ Our development blog is available at: http://planet.pidgin.im +2.6.3 (10/16/2009): + Mark: Someone reported a fairly serious bug in our AIM/ICQ code + so we're releasing a special "severe bug fix only" build. See the + ChangeLog for details. Enjoy! + 2.6.2 (09/05/2009): Mark: Woo boy it's been a busy two weeks. There was a lot of new code in 2.6.0, and with new code comes new bugs. The cadre of relentless
--- a/libpurple/blist.c Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/blist.c Sat Oct 31 17:49:11 2009 +0000 @@ -3187,6 +3187,13 @@ 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),
--- a/libpurple/blist.h Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/blist.h Sat Oct 31 17:49:11 2009 +0000 @@ -108,6 +108,7 @@ #include "account.h" #include "buddyicon.h" +#include "media.h" #include "status.h" /**************************************************************************/ @@ -143,6 +144,7 @@ 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/libpurple/certificate.c Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/certificate.c Sat Oct 31 17:49:11 2009 +0000 @@ -1402,13 +1402,15 @@ if (flags & PURPLE_CERTIFICATE_NAME_MISMATCH) { gchar *sn = purple_certificate_get_subject_name(peer_crt); - g_string_append_printf(errors, _("The certificate claims to be " - "from \"%s\" instead. This could mean that you are " - "not connecting to the service you believe you are."), - sn); - g_free(sn); + if (sn) { + g_string_append_printf(errors, _("The certificate claims to be " + "from \"%s\" instead. This could mean that you are " + "not connecting to the service you believe you are."), + sn); + g_free(sn); - flags &= ~PURPLE_CERTIFICATE_NAME_MISMATCH; + flags &= ~PURPLE_CERTIFICATE_NAME_MISMATCH; + } } while (i != PURPLE_CERTIFICATE_LAST) {
--- a/libpurple/ft.h Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/ft.h Sat Oct 31 17:49:11 2009 +0000 @@ -674,7 +674,7 @@ void purple_xfer_ui_ready(PurpleXfer *xfer); /** - * Allows the prpl to signal it's readh to send/receive data (depending on + * Allows the prpl to signal it's ready to send/receive data (depending on * the direction of the file transfer. Used when the prpl provides read/write * ops and cannot/does not provide a raw fd to the core. *
--- a/libpurple/marshallers.list Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/marshallers.list Sat Oct 31 17:49:11 2009 +0000 @@ -4,3 +4,4 @@ VOID:STRING,STRING,DOUBLE VOID:ENUM,STRING,STRING VOID:ENUM,STRING,STRING,BOOLEAN +VOID:FLAGS,FLAGS
--- a/libpurple/media.c Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/media.c Sat Oct 31 17:49:11 2009 +0000 @@ -103,6 +103,8 @@ gboolean initiator; gboolean accepted; gboolean candidates_prepared; + gboolean held; + gboolean paused; GList *active_local_candidates; GList *active_remote_candidates; @@ -281,7 +283,7 @@ { PURPLE_MEDIA_INFO_HOLD, "PURPLE_MEDIA_INFO_HOLD", "hold" }, { PURPLE_MEDIA_INFO_UNHOLD, - "PURPLE_MEDIA_INFO_HOLD", "unhold" }, + "PURPLE_MEDIA_INFO_UNHOLD", "unhold" }, { 0, NULL, NULL } }; type = g_enum_register_static("PurpleMediaInfoType", values); @@ -289,6 +291,40 @@ return type; } +GType +purple_media_caps_get_type() +{ + static GType type = 0; + if (type == 0) { + static const GEnumValue values[] = { + { PURPLE_MEDIA_CAPS_NONE, + "PURPLE_MEDIA_CAPS_NONE", "none" }, + { PURPLE_MEDIA_CAPS_AUDIO, + "PURPLE_MEDIA_CAPS_AUDIO", "audio" }, + { PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION, + "PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION", + "audio-single-direction" }, + { PURPLE_MEDIA_CAPS_VIDEO, + "PURPLE_MEDIA_CAPS_VIDEO", "video" }, + { PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION, + "PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION", + "video-single-direction" }, + { PURPLE_MEDIA_CAPS_AUDIO_VIDEO, + "PURPLE_MEDIA_CAPS_AUDIO_VIDEO", + "audio-video" }, + { PURPLE_MEDIA_CAPS_MODIFY_SESSION, + "PURPLE_MEDIA_CAPS_MODIFY_SESSION", + "modify-session" }, + { PURPLE_MEDIA_CAPS_CHANGE_DIRECTION, + "PURPLE_MEDIA_CAPS_CHANGE_DIRECTION", + "change-direction" }, + { 0, NULL, NULL } + }; + type = g_enum_register_static("PurpleMediaCaps", values); + } + return type; +} + #ifdef USE_VV static void purple_media_class_init (PurpleMediaClass *klass) @@ -2330,11 +2366,46 @@ for (; streams; streams = g_list_delete_link(streams, streams)) { PurpleMediaStream *stream = streams->data; if (stream->session->type & PURPLE_MEDIA_SEND_VIDEO) { + stream->paused = active; + + if (!stream->held) + g_object_set(stream->stream, "direction", + purple_media_to_fs_stream_direction( + stream->session->type & ((active) ? + ~PURPLE_MEDIA_SEND_VIDEO : + PURPLE_MEDIA_VIDEO)), NULL); + } + } + } else if (local == TRUE && (type == PURPLE_MEDIA_INFO_HOLD || + type == PURPLE_MEDIA_INFO_UNHOLD)) { + GList *streams; + gboolean active = (type == PURPLE_MEDIA_INFO_HOLD); + + g_return_if_fail(PURPLE_IS_MEDIA(media)); + + streams = purple_media_get_streams(media, + session_id, participant); + for (; streams; streams = g_list_delete_link(streams, streams)) { + PurpleMediaStream *stream = streams->data; + stream->held = active; + if (stream->session->type & PURPLE_MEDIA_VIDEO) { + FsStreamDirection direction; + + direction = ((active) ? + ~PURPLE_MEDIA_VIDEO : + PURPLE_MEDIA_VIDEO); + if (!active && stream->paused) + direction &= ~PURPLE_MEDIA_SEND_VIDEO; + + g_object_set(stream->stream, "direction", + purple_media_to_fs_stream_direction( + stream->session->type & direction), NULL); + } else if (stream->session->type & PURPLE_MEDIA_AUDIO) { g_object_set(stream->stream, "direction", purple_media_to_fs_stream_direction( stream->session->type & ((active) ? - ~PURPLE_MEDIA_SEND_VIDEO : - PURPLE_MEDIA_VIDEO)), NULL); + ~PURPLE_MEDIA_AUDIO : + PURPLE_MEDIA_AUDIO)), NULL); } } }
--- a/libpurple/media.h Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/media.h Sat Oct 31 17:49:11 2009 +0000 @@ -58,6 +58,7 @@ #define PURPLE_TYPE_MEDIA_NETWORK_PROTOCOL (purple_media_network_protocol_get_type()) #define PURPLE_MEDIA_TYPE_STATE (purple_media_state_changed_get_type()) #define PURPLE_MEDIA_TYPE_INFO_TYPE (purple_media_info_type_get_type()) +#define PURPLE_MEDIA_TYPE_CAPS (purple_media_caps_get_type()) /** An opaque structure representing a media call. */ typedef struct _PurpleMedia PurpleMedia; @@ -190,6 +191,15 @@ GType purple_media_info_type_get_type(void); /** + * Gets the type of the media caps flags + * + * @return The media caps flags' GType + * + * @since 2.7.0 + */ +GType purple_media_caps_get_type(void); + +/** * Gets the type of the media candidate structure. * * @return The media canditate's GType
--- a/libpurple/mediamanager.c Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/mediamanager.c Sat Oct 31 17:49:11 2009 +0000 @@ -100,6 +100,7 @@ enum { INIT_MEDIA, + UI_CAPS_CHANGED, LAST_SIGNAL }; static guint purple_media_manager_signals[LAST_SIGNAL] = {0}; @@ -148,6 +149,15 @@ purple_smarshal_BOOLEAN__OBJECT_POINTER_STRING, G_TYPE_BOOLEAN, 3, PURPLE_TYPE_MEDIA, G_TYPE_POINTER, G_TYPE_STRING); + + purple_media_manager_signals[UI_CAPS_CHANGED] = g_signal_new ("ui-caps-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + purple_smarshal_VOID__FLAGS_FLAGS, + G_TYPE_NONE, 2, PURPLE_MEDIA_TYPE_CAPS, + PURPLE_MEDIA_TYPE_CAPS); + g_type_class_add_private(klass, sizeof(PurpleMediaManagerPrivate)); } @@ -894,8 +904,17 @@ PurpleMediaCaps caps) { #ifdef USE_VV + PurpleMediaCaps oldcaps; + g_return_if_fail(PURPLE_IS_MEDIA_MANAGER(manager)); + + oldcaps = manager->priv->ui_caps; manager->priv->ui_caps = caps; + + if (caps != oldcaps) + g_signal_emit(manager, + purple_media_manager_signals[UI_CAPS_CHANGED], + 0, caps, oldcaps); #endif }
--- a/libpurple/protocols/jabber/chat.c Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/protocols/jabber/chat.c Sat Oct 31 17:49:11 2009 +0000 @@ -106,7 +106,7 @@ { char *room_jid = g_strdup_printf("%s@%s", room, server); - chat = g_hash_table_lookup(js->chats, jabber_normalize(NULL, room_jid)); + chat = g_hash_table_lookup(js->chats, room_jid); g_free(room_jid); } @@ -177,10 +177,21 @@ xmlnode_insert_data(body, msg, -1); } else { xmlnode_set_attrib(message, "to", name); + /* + * Putting the reason into the body was an 'undocumented protocol, + * ...not part of "groupchat 1.0"'. + * http://xmpp.org/extensions/attic/jep-0045-1.16.html#invite + * + * Left here for compatibility. + */ body = xmlnode_new_child(message, "body"); xmlnode_insert_data(body, msg, -1); + x = xmlnode_new_child(message, "x"); xmlnode_set_attrib(x, "jid", room_jid); + + /* The better place for it! XEP-0249 style. */ + xmlnode_set_attrib(x, "reason", msg); xmlnode_set_namespace(x, "jabber:x:conference"); } @@ -216,7 +227,8 @@ JabberChat *chat; char *jid; - g_return_val_if_fail(jabber_chat_find(js, room, server) == NULL, NULL); + if (jabber_chat_find(js, room, server) != NULL) + return NULL; chat = g_new0(JabberChat, 1); chat->js = js; @@ -264,7 +276,8 @@ char *jid; chat = jabber_chat_new(js, room, server, handle, password, data); - g_return_val_if_fail(chat != NULL, NULL); + if (chat == NULL) + return NULL; gc = js->gc; account = purple_connection_get_account(gc); @@ -371,7 +384,7 @@ JabberStream *js = chat->js; char *room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); - g_hash_table_remove(js->chats, jabber_normalize(NULL, room_jid)); + g_hash_table_remove(js->chats, room_jid); g_free(room_jid); }
--- a/libpurple/protocols/jabber/chat.h Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/protocols/jabber/chat.h Sat Oct 31 17:49:11 2009 +0000 @@ -62,6 +62,8 @@ * in-prpl function for joining a chat room. Doesn't require sticking goop * into a hash table. * + * @param room The room to join. This MUST be normalized already. + * @param server The server the room is on. This MUST be normalized already. * @param password The password (if required) to join the room. May be NULL. * @param data The chat hash table. May be NULL (it will be generated * for current core<>prpl API interface.)
--- a/libpurple/protocols/jabber/jabber.c Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Sat Oct 31 17:49:11 2009 +0000 @@ -3239,7 +3239,7 @@ id = purple_cmd_register("part", "s", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", - jabber_cmd_chat_part, _("part [room]: Leave the room."), + jabber_cmd_chat_part, _("part [message]: Leave the room."), NULL); jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id)); @@ -3453,6 +3453,9 @@ jabber_add_feature(JINGLE_APP_RTP_SUPPORT_VIDEO, jabber_video_enabled); jabber_add_feature(JINGLE_TRANSPORT_RAWUDP, 0); jabber_add_feature(JINGLE_TRANSPORT_ICEUDP, 0); + + g_signal_connect(G_OBJECT(purple_media_manager_get()), "ui-caps-changed", + G_CALLBACK(jabber_caps_broadcast_change), NULL); #endif /* IPC functions */
--- a/libpurple/protocols/jabber/message.c Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/protocols/jabber/message.c Sat Oct 31 17:49:11 2009 +0000 @@ -758,9 +758,22 @@ jm->type != JABBER_MESSAGE_ERROR) { const char *jid = xmlnode_get_attrib(child, "jid"); if(jid) { + const char *reason = xmlnode_get_attrib(child, "reason"); + const char *password = xmlnode_get_attrib(child, "password"); + jm->type = JABBER_MESSAGE_GROUPCHAT_INVITE; g_free(jm->to); jm->to = g_strdup(jid); + + if (reason) { + g_free(jm->body); + jm->body = g_strdup(reason); + } + + if (password) { + g_free(jm->password); + jm->password = g_strdup(password); + } } } else if(!strcmp(xmlns, "http://jabber.org/protocol/muc#user") && jm->type != JABBER_MESSAGE_ERROR) { @@ -775,8 +788,10 @@ g_free(jm->body); jm->body = xmlnode_get_data(reason); } - if((password = xmlnode_get_child(child, "password"))) + if((password = xmlnode_get_child(child, "password"))) { + g_free(jm->password); jm->password = xmlnode_get_data(password); + } jm->type = JABBER_MESSAGE_GROUPCHAT_INVITE; }
--- a/libpurple/protocols/jabber/presence.c Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/protocols/jabber/presence.c Sat Oct 31 17:49:11 2009 +0000 @@ -458,6 +458,10 @@ jbr->caps.info = info; jbr->caps.exts = exts; + purple_prpl_got_media_caps( + purple_connection_get_account(userdata->js->gc), + userdata->from); + if (info == NULL) goto out; @@ -476,7 +480,7 @@ /* * Versions of libpurple before 2.6.0 didn't advertise this capability, so * we can't yet use Entity Capabilities to determine whether or not the - * other client supports Entity Capabilities. + * other client supports Chat States. */ if (jabber_resource_has_capability(jbr, "http://jabber.org/protocol/chatstates")) jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED;
--- a/libpurple/protocols/oscar/oscar.c Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/protocols/oscar/oscar.c Sat Oct 31 17:49:11 2009 +0000 @@ -2874,25 +2874,46 @@ gchar **text; text = g_strsplit(args->msg, "\376", 0); if (text) { - num = 0; - for (i=0; i<strlen(text[0]); i++) - num = num*10 + text[0][i]-48; - for (i=0; i<num; i++) { - struct name_data *data = g_new(struct name_data, 1); - gchar *message = g_strdup_printf(_("ICQ user %u has sent you a buddy: %s (%s)"), args->uin, text[i*2+2], text[i*2+1]); - data->gc = gc; - data->name = g_strdup(text[i*2+1]); - data->nick = g_strdup(text[i*2+2]); - - purple_request_action(gc, NULL, message, - _("Do you want to add this buddy " - "to your buddy list?"), - PURPLE_DEFAULT_ACTION_NONE, - purple_connection_get_account(gc), data->name, NULL, - data, 2, - _("_Add"), G_CALLBACK(purple_icq_buddyadd), - _("_Decline"), G_CALLBACK(oscar_free_name_data)); - g_free(message); + /* Read the number of contacts that we were sent */ + errno = 0; + num = strtoul(text[0], NULL, 10); + + if (num > 0 && errno == 0) { + for (i=0; i<num; i++) { + struct name_data *data; + gchar *message; + + if (!text[i*2 + 1] || !text[i*2 + 2]) { + /* We're missing the contact name or nickname. Bail out. */ + gchar *tmp = g_strescape(args->msg, NULL); + purple_debug_error("oscar", "Unknown syntax parsing " + "ICQ buddies. args->msg=%s\n", tmp); + g_free(tmp); + break; + } + + message = g_strdup_printf(_("ICQ user %u has sent you a buddy: %s (%s)"), args->uin, text[i*2+2], text[i*2+1]); + + data = g_new(struct name_data, 1); + data->gc = gc; + data->name = g_strdup(text[i*2+1]); + data->nick = g_strdup(text[i*2+2]); + + purple_request_action(gc, NULL, message, + _("Do you want to add this buddy " + "to your buddy list?"), + PURPLE_DEFAULT_ACTION_NONE, + purple_connection_get_account(gc), data->name, NULL, + data, 2, + _("_Add"), G_CALLBACK(purple_icq_buddyadd), + _("_Decline"), G_CALLBACK(oscar_free_name_data)); + g_free(message); + } + } else { + gchar *tmp = g_strescape(args->msg, NULL); + purple_debug_error("oscar", "Unknown syntax parsing " + "ICQ buddies. args->msg=%s\n", tmp); + g_free(tmp); } g_strfreev(text); } @@ -3909,12 +3930,8 @@ od->rights.maxpermits = (guint)maxpermits; od->rights.maxdenies = (guint)maxdenies; - purple_connection_set_state(gc, PURPLE_CONNECTED); - purple_debug_info("oscar", "buddy list loaded\n"); - aim_srv_clientready(od, conn); - if (purple_account_get_user_info(account) != NULL) serv_set_info(gc, purple_account_get_user_info(account)); @@ -3957,6 +3974,22 @@ aim_srv_requestnew(od, SNAC_FAMILY_ALERT); aim_srv_requestnew(od, SNAC_FAMILY_CHATNAV); + od->bos.have_rights = TRUE; + + /* + * If we've already received our feedbag data then we're not waiting on + * anything else, so send the server clientready. + * + * Normally we get bos rights before we get our feedbag data, so this + * rarely (never?) happens. And I'm not sure it actually matters if we + * wait for bos rights before calling clientready. But it seems safer + * to do it this way. + */ + if (od->ssi.received_data) { + aim_srv_clientready(od, conn); + purple_connection_set_state(gc, PURPLE_CONNECTED); + } + return 1; } @@ -5396,6 +5429,15 @@ oscar_set_icon(gc, img); purple_imgstore_unref(img); + /* + * If we've already received our bos rights then we're not waiting on + * anything else, so send the server clientready. + */ + if (od->bos.have_rights) { + aim_srv_clientready(od, conn); + purple_connection_set_state(gc, PURPLE_CONNECTED); + } + return 1; }
--- a/libpurple/protocols/oscar/oscar.h Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/protocols/oscar/oscar.h Sat Oct 31 17:49:11 2009 +0000 @@ -535,6 +535,10 @@ struct aim_userinfo_s *userinfo; } locate; + struct { + gboolean have_rights; + } bos; + /* Server-stored information (ssi) */ struct { gboolean received_data;
--- a/libpurple/prpl.c Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/prpl.c Sat Oct 31 17:49:11 2009 +0000 @@ -288,8 +288,10 @@ /* The buddy is no longer online, they are therefore by definition not * still typing to us. */ - if (!purple_status_is_online(status)) + if (!purple_status_is_online(status)) { serv_got_typing_stopped(purple_account_get_connection(account), name); + purple_prpl_got_media_caps(account, name); + } } void purple_prpl_got_user_status_deactive(PurpleAccount *account, const char *name, @@ -560,6 +562,35 @@ return PURPLE_MEDIA_CAPS_NONE; } +void +purple_prpl_got_media_caps(PurpleAccount *account, const char *name) +{ +#ifdef USE_VV + GSList *list; + + g_return_if_fail(account != NULL); + g_return_if_fail(name != NULL); + + if ((list = purple_find_buddies(account, name)) == NULL) + return; + + while (list) { + PurpleBuddy *buddy = list->data; + PurpleMediaCaps oldcaps = buddy->media_caps; + const gchar *bname = purple_buddy_get_name(buddy); + list = g_slist_delete_link(list, list); + buddy->media_caps = purple_prpl_get_media_caps(account, bname); + + if (oldcaps == buddy->media_caps) + continue; + + purple_signal_emit(purple_blist_get_handle(), + "buddy-caps-changed", buddy, + buddy->media_caps, oldcaps); + } +#endif +} + /************************************************************************** * Protocol Plugin Subsystem API **************************************************************************/
--- a/libpurple/prpl.h Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/prpl.h Sat Oct 31 17:49:11 2009 +0000 @@ -815,6 +815,17 @@ const char *who, PurpleMediaSessionType type); +/** + * Signals that the prpl received capabilities for the given contact. + * + * This function is intended to be used only by prpls. + * + * @param account The account the user is on. + * @param who The name of the contact for which capabilities have been received. + * @since 2.7.0 + */ +void purple_prpl_got_media_caps(PurpleAccount *account, const char *who); + /*@}*/ /**************************************************************************/
--- a/libpurple/tests/test_jabber_jutil.c Thu Oct 15 10:45:22 2009 +0000 +++ b/libpurple/tests/test_jabber_jutil.c Sat Oct 31 17:49:11 2009 +0000 @@ -134,6 +134,14 @@ assert_invalid_jid("paul@2[::1]124/as"); assert_invalid_jid("paul@まつ.おおかみ/\x01"); + /* + * RFC 3454 Section 6 reads, in part, + * "If a string contains any RandALCat character, the + * string MUST NOT contain any LCat character." + * The character is U+066D (ARABIC FIVE POINTED STAR). + */ + assert_invalid_jid("foo@example.com/٭simplexe٭"); + /* Ensure that jabber_id_new is properly lowercasing node and domains */ assert_jid_parts("paul", "darkrain42.org", "PaUL@darkrain42.org"); assert_jid_parts("paul", "darkrain42.org", "paul@DaRkRaIn42.org");
--- a/pidgin/gtkmedia.c Thu Oct 15 10:45:22 2009 +0000 +++ b/pidgin/gtkmedia.c Sat Oct 31 17:49:11 2009 +0000 @@ -89,6 +89,7 @@ GtkWidget *menubar; GtkWidget *statusbar; + GtkWidget *hold; GtkWidget *mute; GtkWidget *pause; @@ -187,6 +188,15 @@ } static void +pidgin_media_hold_toggled(GtkToggleButton *toggle, PidginMedia *media) +{ + purple_media_stream_info(media->priv->media, + gtk_toggle_button_get_active(toggle) ? + PURPLE_MEDIA_INFO_HOLD : PURPLE_MEDIA_INFO_UNHOLD, + NULL, NULL, TRUE); +} + +static void pidgin_media_mute_toggled(GtkToggleButton *toggle, PidginMedia *media) { purple_media_stream_info(media->priv->media, @@ -633,6 +643,16 @@ FALSE, FALSE, 0); gtk_widget_show(GTK_WIDGET(button_widget)); gtk_widget_show(send_widget); + + /* Hold button */ + gtkmedia->priv->hold = + gtk_toggle_button_new_with_mnemonic("_Hold"); + g_signal_connect(gtkmedia->priv->hold, "toggled", + G_CALLBACK(pidgin_media_hold_toggled), + gtkmedia); + gtk_box_pack_end(GTK_BOX(button_widget), gtkmedia->priv->hold, + FALSE, FALSE, 0); + gtk_widget_show(gtkmedia->priv->hold); } else { send_widget = gtkmedia->priv->send_widget; button_widget = gtkmedia->priv->button_widget;
--- a/pidgin/gtkroomlist.c Thu Oct 15 10:45:22 2009 +0000 +++ b/pidgin/gtkroomlist.c Sat Oct 31 17:49:11 2009 +0000 @@ -111,7 +111,18 @@ static void dialog_select_account_cb(GObject *w, PurpleAccount *account, PidginRoomlistDialog *dialog) { + gboolean change = (account != dialog->account); dialog->account = account; + + if (change && dialog->roomlist) { + PidginRoomlist *rl = dialog->roomlist->ui_data; + if (rl->tree) { + gtk_widget_destroy(rl->tree); + rl->tree = NULL; + } + purple_roomlist_unref(dialog->roomlist); + dialog->roomlist = NULL; + } } static void list_button_cb(GtkButton *button, PidginRoomlistDialog *dialog)
--- a/pidgin/gtkutils.c Thu Oct 15 10:45:22 2009 +0000 +++ b/pidgin/gtkutils.c Sat Oct 31 17:49:11 2009 +0000 @@ -75,7 +75,7 @@ } AopMenu; static guint accels_save_timer = 0; -static GList *gnome_url_handlers = NULL; +static GSList *registered_url_handlers = NULL; static gboolean url_clicked_idle_cb(gpointer data) @@ -3395,7 +3395,7 @@ start += sizeof("/desktop/gnome/url-handlers/") - 1; protocol = g_strdup_printf("%s:", start); - gnome_url_handlers = g_list_prepend(gnome_url_handlers, protocol); + registered_url_handlers = g_slist_prepend(registered_url_handlers, protocol); gtk_imhtml_class_register_protocol(protocol, url_clicked_cb, link_context_menu); } start = c + 1; @@ -3403,7 +3403,7 @@ } g_free(tmp); - return (gnome_url_handlers != NULL); + return (registered_url_handlers != NULL); } #ifdef _WIN32 @@ -3415,16 +3415,18 @@ do { DWORD nameSize = 256; - char protocol[256]; + char start[256]; /* I don't think we need to worry about non-ASCII protocol names */ - ret = RegEnumKeyExA(HKEY_CLASSES_ROOT, idx++, protocol, &nameSize, + ret = RegEnumKeyExA(HKEY_CLASSES_ROOT, idx++, start, &nameSize, NULL, NULL, NULL, NULL); if (ret == ERROR_SUCCESS) { HKEY reg_key = NULL; - ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, protocol, 0, KEY_READ, ®_key); + ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, start, 0, KEY_READ, ®_key); if (ret == ERROR_SUCCESS) { ret = RegQueryValueExA(reg_key, "URL Protocol", NULL, NULL, NULL, NULL); if (ret == ERROR_SUCCESS) { + gchar *protocol = g_strdup_printf("%s:", start); + registered_url_handlers = g_slist_prepend(registered_url_handlers, protocol); /* We still pass everything to the "http" "open" handler for security reasons */ gtk_imhtml_class_register_protocol(protocol, url_clicked_cb, link_context_menu); } @@ -3469,16 +3471,16 @@ gtk_imhtml_class_register_protocol("open://", NULL, NULL); /* If we have GNOME handlers registered, unregister them. */ - if (gnome_url_handlers) + if (registered_url_handlers) { - GList *l; - for (l = gnome_url_handlers ; l ; l = l->next) + GSList *l; + for (l = registered_url_handlers; l; l = l->next) { gtk_imhtml_class_register_protocol((char *)l->data, NULL, NULL); g_free(l->data); } - g_list_free(gnome_url_handlers); - gnome_url_handlers = NULL; + g_slist_free(registered_url_handlers); + registered_url_handlers = NULL; return; }
--- a/pidgin/plugins/disco/gtkdisco.c Thu Oct 15 10:45:22 2009 +0000 +++ b/pidgin/plugins/disco/gtkdisco.c Sat Oct 31 17:49:11 2009 +0000 @@ -141,8 +141,18 @@ static void dialog_select_account_cb(GObject *w, PurpleAccount *account, PidginDiscoDialog *dialog) { + gboolean change = (account != dialog->account); dialog->account = account; gtk_widget_set_sensitive(dialog->browse_button, account != NULL); + + if (change && dialog->discolist) { + if (dialog->discolist->tree) { + gtk_widget_destroy(dialog->discolist->tree); + dialog->discolist->tree = NULL; + } + pidgin_disco_list_unref(dialog->discolist); + dialog->discolist = NULL; + } } static void register_button_cb(GtkWidget *unused, PidginDiscoDialog *dialog)
--- a/po/ChangeLog Thu Oct 15 10:45:22 2009 +0000 +++ b/po/ChangeLog Sat Oct 31 17:49:11 2009 +0000 @@ -2,8 +2,11 @@ version 2.7.0 +version 2.6.4 + * Vietnamese translation updated (Clytie Siddall) + version 2.6.3 - * Vietnamese translation updated (Clytie Siddall) + * No changes version 2.6.2 * Afrikaans translation updated (Friedel Wolff)