Mercurial > pidgin.yaz
changeset 30186:06fa97f637a7
merged with im.pidgin.pidgin
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Thu, 22 Apr 2010 14:45:57 +0900 |
parents | bd0ce3844104 (current diff) 9e60e300541a (diff) |
children | c9413547ee33 |
files | configure.ac libpurple/protocols/jabber/jabber.c libpurple/protocols/msn/msn.c libpurple/protocols/oscar/family_icbm.c libpurple/protocols/oscar/oscar.h libpurple/util.c libpurple/util.h pidgin/gtkblist.c pidgin/gtkimhtml.c pidgin/gtkutils.c |
diffstat | 36 files changed, 527 insertions(+), 98 deletions(-) [+] |
line wrap: on
line diff
--- a/COPYRIGHT Thu Apr 15 16:48:50 2010 +0900 +++ b/COPYRIGHT Thu Apr 22 14:45:57 2010 +0900 @@ -245,6 +245,7 @@ Jochen Kemnade Yann Kerherve Gordian Klein +Marten Klencke Krzysztof Klinikowski Akuke Kok Kir Kolyshkin @@ -530,6 +531,7 @@ Zac West Daniel Westermann-Clark Andrew Whewell +Stephen Whitmore Simon Wilkinson Dan Willemsen Justin Williams (Jaywalker)
--- a/ChangeLog Thu Apr 15 16:48:50 2010 +0900 +++ b/ChangeLog Thu Apr 22 14:45:57 2010 +0900 @@ -18,6 +18,8 @@ GnuTLS manual for documentation on the format of the priority strings. * Fix autoconf detection of Python. (Brad Smith) + * Fix a crash when a Windows proxy (in IE) does not have a port. + (Marten Klencke) Pidgin: * Moved the "Debugging Information" section of the About box to a @@ -45,6 +47,8 @@ buddy icons. * The 'Message Timestamp Formats' plugin allows changing the timestamp format from the timestamps' context menu in conversation log. + * Fix pastes from Chrome (rich-text pastes and probably URLs + having garbage appended to them) Bonjour: * Added support for IPv6. (Thanks to T_X for testing) @@ -82,6 +86,10 @@ BoB XEP). * Present a better error message when authentication fails while trying to connect to Facebook. (David Reiss, Facebook) + * Send whitespace keepalives if we haven't sent data in a while (2 + minutes). This fixes an issue with Openfire disconnecting a + libpurple-baesd client that has just been quiet for about 6 + minutes. Yahoo/Yahoo JAPAN: * Attempt to better handle transparent proxies interfering with HTTP-based
--- a/ChangeLog.API Thu Apr 15 16:48:50 2010 +0900 +++ b/ChangeLog.API Thu Apr 22 14:45:57 2010 +0900 @@ -8,6 +8,8 @@ * account-signed-off * account-connection-error * purple_account_get_name_for_display + * purple_account_get_privacy_type + * purple_account_set_privacy_type * purple_buddy_get_media_caps * purple_buddy_set_media_caps * purple_contact_get_group @@ -15,11 +17,20 @@ * purple_media_codec_copy * purple_media_manager_get_backend_type * purple_media_manager_set_backend_type - * purple_network_get_all_local_system_ips, which returns all local - IPs on the system. On systems with the getifaddrs() function, - this will return both IPv4 and IPv6 addresses (excluding link-local - and loopback addresses). On others, it returns just IPv4 addresses. + * purple_network_get_all_local_system_ips, which returns all + local IPs on the system. On systems with the getifaddrs() + function, this will return both IPv4 and IPv6 addresses + (excluding link-local and loopback addresses). On others, + it returns just IPv4 addresses. + * purple_network_listen_family and + purple_network_listen_range_family. These will replace the + versions without _family in 3.0.0 and allow the caller to + specifically request either an IPv4 or IPv6 socket. IPv6 is + only supported if the getaddrinfo() function is available + at build-time (not the case on Windows, currently). * purple_prpl_got_media_caps + * purple_socket_get_family + * purple_socket_speaks_ipv4 * purple_unescape_text * purple_uuid_random * media_caps to the PurpleBuddy struct @@ -28,9 +39,10 @@ * sent-attention conversation signal * got-attention conversation signal * PurpleMood struct in status.h - * purple_certificates_import for importing multiple certificates from - a single file (and corresponding import_certificates member of - PurpleCertificateScheme struct) + * purple_certificates_import for importing multiple + certificates from a single file (and corresponding + import_certificates member of PurpleCertificateScheme struct) + * autojoin connection signal Pidgin: Added: @@ -48,7 +60,7 @@ purple_xfer_request_denied if an error is found when selecting a file to send. Request denied is still used when a receive request is not allowed. - * xmlnode_from_str now properly handles paring an attribute which + * xmlnode_from_str now properly handles parsing an attribute which contain "<br>", which were previously transformed into a newline character (libxml2 unescapes all entities except representations of '&', and libpurple's purple_unescape_html
--- a/configure.ac Thu Apr 15 16:48:50 2010 +0900 +++ b/configure.ac Thu Apr 22 14:45:57 2010 +0900 @@ -184,6 +184,12 @@ [Define if struct sockaddr has an sa_len member])],[:], [#include <sys/socket.h>]) +dnl Check for v6-only sockets +AC_CHECK_DECL([IPV6_V6ONLY], + [AC_DEFINE([HAVE_IPV6_V6ONLY],[1], + [Define if the IPV6_V6ONLY setsockopt option exists])], + [], [#include <netinet/in.h>]) + dnl to prevent the g_stat()/g_unlink() crash, dnl (09:50:07) Robot101: LSchiere2: it's easy. +LC_SYS_LARGEFILE somewhere in configure.ac AC_SYS_LARGEFILE @@ -1791,13 +1797,13 @@ AC_SUBST(GNUTLS_LIBS) if test "x$enable_gnutls" = "xyes"; then - AC_MSG_CHECKING(for gnutls_priority_set_direct) + AC_MSG_CHECKING(for gnutls_priority_set_direct and gnutls_priority_set) LIBS_save="$LIBS" LIBS="$LIBS $GNUTLS_LIBS" CPPFLAGS_save="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $GNUTLS_CFLAGS" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <gnutls/gnutls.h>]], - [[gnutls_session s; gnutls_priority_set_direct(s, NULL, NULL);]])], + [[gnutls_session s; gnutls_priority_set_direct(s, NULL, NULL); gnutls_priority_set(s, NULL);]])], [AC_DEFINE([HAVE_GNUTLS_PRIORITY_FUNCS], 1, [Define if your gnutls has gnutls_priority_set_direct and friends]) AC_MSG_RESULT(yes)],
--- a/doc/blist-signals.dox Thu Apr 15 16:48:50 2010 +0900 +++ b/doc/blist-signals.dox Thu Apr 22 14:45:57 2010 +0900 @@ -11,6 +11,8 @@ @signal buddy-removed @signal buddy-icon-changed @signal blist-node-aliased + @signal buddy-caps-changed + @signal ui-caps-changed @endsignals @see blist.h @@ -124,5 +126,29 @@ Emitted when a blist node (buddy, chat, or contact) is aliased. @endsignaldef + @signaldef buddy-caps-changed + @signalproto +void (*buddy_caps_changed)(PurpleBuddy *buddy, PurpleMediaCaps newcaps, + PurpleMediaCaps oldcaps) + @endsignalproto + @signaldesc + Emitted when updating a buddy's media capabilities. + @param buddy The buddy + @param newcaps + @param oldcaps + @since 2.7.0 + @endsignaldef + + @signaldef ui-caps-changed + @signalproto +void (*ui_caps_changed)(PurpleMediaCaps newcaps, PurpleMediaCaps oldcaps) + @endsignalproto + @signaldesc + Emitted when updating the media capabilities of the UI. + @param newcaps + @param oldcaps + @since 2.7.0 + @endsignaldef + */ // vim: syntax=c.doxygen tw=75 et
--- a/doc/connection-signals.dox Thu Apr 15 16:48:50 2010 +0900 +++ b/doc/connection-signals.dox Thu Apr 22 14:45:57 2010 +0900 @@ -3,6 +3,7 @@ @signals @signal signing-on @signal signed-on + @signal autojoin @signal signing-off @signal signed-off @signal connection-error @@ -30,6 +31,22 @@ @param gc The connection that has signed on. @endsignaldef + @signaldef autojoin + @signalproto +gboolean (*autojoin)(PurpleConnection *gc); + @endsignalproto + @signaldesc + Emitted when a connection has signed on, after the signed-on signal, to + signal UIs to autojoin chats if they wish. UIs should connect to this + with @c PURPLE_SIGNAL_PRIORITY_HIGHEST to allow plugins to block this + signal before the UI sees it and then re-emit it later. + @param gc The connection that has signed on. + @return @c TRUE if the signal was handled or @c FALSE otherwise. In + practice, the return value is irrelevant, as it really only + exists so plugins can block the UI's autojoin. + @since 2.7.0 + @endsignaldef + @signaldef signing-off @signalproto void (*signing_off)(PurpleConnection *gc);
--- a/doc/conversation-signals.dox Thu Apr 15 16:48:50 2010 +0900 +++ b/doc/conversation-signals.dox Thu Apr 22 14:45:57 2010 +0900 @@ -33,6 +33,8 @@ @signal chat-left @signal chat-topic-changed @signal conversation-extended-menu + @signal sent-attention + @signal got-attention @endsignals @see conversation.h @@ -476,5 +478,33 @@ @param list A pointer to the list of actions. @since 2.1.0 @endsignaldef + + @signaldef sent-attention + @signalproto +void (*got_attention)(PurpleAccount *account, const char *who, + PurpleConversation *conv, guint type) + @endsignalproto + @signaldesc + Emitted when receiving an attention message (buzz, nudge, etc.). + @param account The account + @param who The name of the person receiving the attention + @param conv The conversation + @param type The attention type (an index starting at 0) + @since 2.7.0 + @endsignaldef + + @signaldef got-attention + @signalproto +void (*got_attention)(PurpleAccount *account, const char *who, + PurpleConversation *conv, guint type) + @endsignalproto + @signaldesc + Emitted when receiving an attention message (buzz, nudge, etc.). + @param account The account + @param who The name of the person sending the attention + @param conv The conversation + @param type The attention type (an index starting at 0) + @since 2.7.0 + @endsignaldef */ // vim: syntax=c.doxygen tw=75 et
--- a/doc/gtkimhtml-signals.dox Thu Apr 15 16:48:50 2010 +0900 +++ b/doc/gtkimhtml-signals.dox Thu Apr 22 14:45:57 2010 +0900 @@ -63,7 +63,7 @@ @signalproto void (*paste) (GtkIMHtml *imhtml, char *format) @endsignalproto - @signaldef Emitted when paste from the clipboard is requested. + @signaldesc Emitted when paste from the clipboard is requested. @param imhtml The GtkIMHtml emitting the signal. @param format If 'text', then the formatting of the clipboard content will be removed before pasting. If empty or 'html', then
--- a/finch/gntblist.c Thu Apr 15 16:48:50 2010 +0900 +++ b/finch/gntblist.c Thu Apr 22 14:45:57 2010 +0900 @@ -144,7 +144,7 @@ static void blist_show(PurpleBuddyList *list); static void update_node_display(PurpleBlistNode *buddy, FinchBlist *ggblist); static void update_buddy_display(PurpleBuddy *buddy, FinchBlist *ggblist); -static void account_signed_on_cb(PurpleConnection *pc, gpointer null); +static gboolean account_autojoin_cb(PurpleConnection *pc, gpointer null); static void finch_request_add_buddy(PurpleAccount *account, const char *username, const char *grp, const char *alias); static void menu_group_set_cb(GntMenuItem *item, gpointer null); @@ -2213,8 +2213,10 @@ purple_prefs_connect_callback(finch_blist_get_handle(), PREF_ROOT "/grouping", redraw_blist, NULL); - purple_signal_connect(purple_connections_get_handle(), "signed-on", purple_blist_get_handle(), - G_CALLBACK(account_signed_on_cb), NULL); + purple_signal_connect_priority(purple_connections_get_handle(), + "autojoin", purple_blist_get_handle(), + G_CALLBACK(account_autojoin_cb), NULL, + PURPLE_SIGNAL_PRIORITY_HIGHEST); finch_blist_install_manager(&default_manager); @@ -2684,10 +2686,11 @@ return FALSE; } -static void -account_signed_on_cb(PurpleConnection *gc, gpointer null) +static gboolean +account_autojoin_cb(PurpleConnection *gc, gpointer null) { g_idle_add(auto_join_chats, gc); + return TRUE; } static void toggle_pref_cb(GntMenuItem *item, gpointer n)
--- a/libpurple/account.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/account.c Thu Apr 22 14:45:57 2010 +0900 @@ -1709,6 +1709,14 @@ } void +purple_account_set_privacy_type(PurpleAccount *account, PurplePrivacyType privacy_type) +{ + g_return_if_fail(account != NULL); + + account->perm_deny = privacy_type; +} + +void purple_account_set_status_types(PurpleAccount *account, GList *status_types) { g_return_if_fail(account != NULL); @@ -2105,6 +2113,14 @@ return account->proxy_info; } +PurplePrivacyType +purple_account_get_privacy_type(const PurpleAccount *account) +{ + g_return_val_if_fail(account != NULL, PURPLE_PRIVACY_ALLOW_ALL); + + return account->perm_deny; +} + PurpleStatus * purple_account_get_active_status(const PurpleAccount *account) {
--- a/libpurple/account.h Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/account.h Thu Apr 22 14:45:57 2010 +0900 @@ -414,6 +414,16 @@ void purple_account_set_proxy_info(PurpleAccount *account, PurpleProxyInfo *info); /** + * Sets the account's privacy type. + * + * @param account The account. + * @param privacy_type The privacy type. + * + * @since 2.7.0 + */ +void purple_account_set_privacy_type(PurpleAccount *account, PurplePrivacyType privacy_type); + +/** * Sets the account's status types. * * @param account The account. @@ -683,6 +693,17 @@ PurpleProxyInfo *purple_account_get_proxy_info(const PurpleAccount *account); /** + * Returns the account's privacy type. + * + * @param account The account. + * + * @return The privacy type. + * + * @since 2.7.0 + */ +PurplePrivacyType purple_account_get_privacy_type(const PurpleAccount *account); + +/** * Returns the active status for this account. This looks through * the PurplePresence associated with this account and returns the * PurpleStatus that has its active flag set to "TRUE." There can be
--- a/libpurple/connection.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/connection.c Thu Apr 22 14:45:57 2010 +0900 @@ -372,6 +372,7 @@ purple_blist_add_account(account); purple_signal_emit(purple_connections_get_handle(), "signed-on", gc); + purple_signal_emit_return_1(purple_connections_get_handle(), "autojoin", gc); serv_set_permit_deny(gc); @@ -715,6 +716,11 @@ purple_value_new(PURPLE_TYPE_ENUM), purple_value_new(PURPLE_TYPE_STRING)); + purple_signal_register(handle, "autojoin", + purple_marshal_BOOLEAN__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONNECTION)); + } void
--- a/libpurple/network.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/network.c Thu Apr 22 14:45:57 2010 +0900 @@ -394,7 +394,7 @@ } static PurpleNetworkListenData * -purple_network_do_listen(unsigned short port, int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data) +purple_network_do_listen(unsigned short port, int socket_family, int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data) { int listenfd = -1; int flags; @@ -412,7 +412,7 @@ g_snprintf(serv, sizeof(serv), "%hu", port); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags = AI_PASSIVE; - hints.ai_family = AF_UNSPEC; + hints.ai_family = socket_family; hints.ai_socktype = socket_type; errnum = getaddrinfo(NULL /* any IP */, serv, &hints, &res); if (errnum != 0) { @@ -436,7 +436,7 @@ if (listenfd < 0) continue; if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) - purple_debug_warning("network", "setsockopt: %s\n", g_strerror(errno)); + purple_debug_warning("network", "setsockopt(SO_REUSEADDR): %s\n", g_strerror(errno)); if (bind(listenfd, next->ai_addr, next->ai_addrlen) == 0) break; /* success */ /* XXX - It is unclear to me (datallah) whether we need to be @@ -451,6 +451,13 @@ #else struct sockaddr_in sockin; + if (socket_family != AF_INET && socket_family != AF_UNSPEC) { + purple_debug_warning("network", "Address family %d only " + "supported when built with getaddrinfo() " + "support\n", socket_family); + return NULL; + } + if ((listenfd = socket(AF_INET, socket_type, 0)) < 0) { purple_debug_warning("network", "socket: %s\n", g_strerror(errno)); return NULL; @@ -492,7 +499,8 @@ listen_data->cb_data = cb_data; listen_data->socket_type = socket_type; - if (!listen_map_external || !purple_prefs_get_bool("/purple/network/map_ports")) + if (!purple_socket_speaks_ipv4(listenfd) || !listen_map_external || + !purple_prefs_get_bool("/purple/network/map_ports")) { purple_debug_info("network", "Skipping external port mapping.\n"); /* The pmp_map_cb does what we want to do */ @@ -519,17 +527,29 @@ } PurpleNetworkListenData * -purple_network_listen(unsigned short port, int socket_type, - PurpleNetworkListenCallback cb, gpointer cb_data) +purple_network_listen_family(unsigned short port, int socket_family, + int socket_type, PurpleNetworkListenCallback cb, + gpointer cb_data) { g_return_val_if_fail(port != 0, NULL); - return purple_network_do_listen(port, socket_type, cb, cb_data); + return purple_network_do_listen(port, socket_family, socket_type, + cb, cb_data); } PurpleNetworkListenData * -purple_network_listen_range(unsigned short start, unsigned short end, - int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data) +purple_network_listen(unsigned short port, int socket_type, + PurpleNetworkListenCallback cb, gpointer cb_data) +{ + return purple_network_listen_family(port, AF_UNSPEC, socket_type, + cb, cb_data); +} + +PurpleNetworkListenData * +purple_network_listen_range_family(unsigned short start, unsigned short end, + int socket_family, int socket_type, + PurpleNetworkListenCallback cb, + gpointer cb_data) { PurpleNetworkListenData *ret = NULL; @@ -542,7 +562,7 @@ } for (; start <= end; start++) { - ret = purple_network_do_listen(start, socket_type, cb, cb_data); + ret = purple_network_do_listen(start, AF_UNSPEC, socket_type, cb, cb_data); if (ret != NULL) break; } @@ -550,6 +570,15 @@ return ret; } +PurpleNetworkListenData * +purple_network_listen_range(unsigned short start, unsigned short end, + int socket_type, PurpleNetworkListenCallback cb, + gpointer cb_data) +{ + return purple_network_listen_range_family(start, end, AF_UNSPEC, + socket_type, cb, cb_data); +} + void purple_network_listen_cancel(PurpleNetworkListenData *listen_data) { if (listen_data->mapping_data != NULL)
--- a/libpurple/network.h Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/network.h Thu Apr 22 14:45:57 2010 +0900 @@ -138,8 +138,8 @@ * * This opens a listening port. The caller will want to set up a watcher * of type PURPLE_INPUT_READ on the fd returned in cb. It will probably call - * accept in the watcher callback, and then possibly remove the watcher and close - * the listening socket, and add a new watcher on the new socket accept + * accept in the watcher callback, and then possibly remove the watcher and + * close the listening socket, and add a new watcher on the new socket accept * returned. * * @param port The port number to bind to. Must be greater than 0. @@ -158,6 +158,27 @@ int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data); /** + * \copydoc purple_network_listen + * + * Libpurple does not currently do any port mapping (stateful firewall hole + * poking) for IPv6-only listeners (if an IPv6 socket supports v4-mapped + * addresses, a mapping is done). + * + * @param socket_family The protocol family of the socket. This should be + * AF_INET for IPv4 or AF_INET6 for IPv6. IPv6 sockets + * may or may not be able to accept IPv4 connections + * based on the system configuration (use + * purple_socket_speaks_ipv4 to check). If an IPv6 + * socket doesn't accept V4-mapped addresses, you will + * need a second listener to support both v4 and v6. + * @since 2.7.0 + * @deprecated This function will be renamed to purple_network_listen in 3.0.0. + */ +PurpleNetworkListenData *purple_network_listen_family(unsigned short port, + int socket_family, int socket_type, PurpleNetworkListenCallback cb, + gpointer cb_data); + +/** * Opens a listening port selected from a range of ports. The range of * ports used is chosen in the following manner: * If a range is specified in preferences, these values are used. @@ -192,6 +213,28 @@ PurpleNetworkListenCallback cb, gpointer cb_data); /** + * \copydoc purple_network_listen_range + * + * Libpurple does not currently do any port mapping (stateful firewall hole + * poking) for IPv6-only listeners (if an IPv6 socket supports v4-mapped + * addresses, a mapping is done). + * + * @param socket_family The protocol family of the socket. This should be + * AF_INET for IPv4 or AF_INET6 for IPv6. IPv6 sockets + * may or may not be able to accept IPv4 connections + * based on the system configuration (use + * purple_socket_speaks_ipv4 to check). If an IPv6 + * socket doesn't accept V4-mapped addresses, you will + * need a second listener to support both v4 and v6. + * @since 2.7.0 + * @deprecated This function will be renamed to purple_network_listen_range + * in 3.0.0. + */ +PurpleNetworkListenData *purple_network_listen_range_family( + unsigned short start, unsigned short end, int socket_family, + int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data); + +/** * This can be used to cancel any in-progress listener connection * by passing in the return value from either purple_network_listen() * or purple_network_listen_range().
--- a/libpurple/protocols/gg/gg.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/protocols/gg/gg.c Thu Apr 22 14:45:57 2010 +0900 @@ -1034,6 +1034,7 @@ case GG_STATUS_DND: case GG_STATUS_DND_DESCR: st = purple_primitive_get_id_from_type(PURPLE_STATUS_UNAVAILABLE); + break; case GG_STATUS_BLOCKED: /* user is blocking us.... */ st = "blocked";
--- a/libpurple/protocols/jabber/auth.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/protocols/jabber/auth.c Thu Apr 22 14:45:57 2010 +0900 @@ -208,6 +208,11 @@ } } + while (mechanisms) { + g_free(mechanisms->data); + mechanisms = g_slist_delete_link(mechanisms, mechanisms); + } + if (js->auth_mech == NULL) { /* Found no good mechanisms... */ purple_connection_error_reason(js->gc,
--- a/libpurple/protocols/jabber/auth_scram.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/protocols/jabber/auth_scram.c Thu Apr 22 14:45:57 2010 +0900 @@ -301,11 +301,17 @@ #endif ret = jabber_scram_calc_proofs(data, salt, iterations); - if (!ret) + + g_string_free(salt, TRUE); + salt = NULL; + if (!ret) { + g_free(nonce); return FALSE; + } proof = purple_base64_encode((guchar *)data->client_proof->str, data->client_proof->len); *out = g_strdup_printf("c=%s,r=%s,p=%s", "biws", nonce, proof); + g_free(nonce); g_free(proof); } else if (data->step == 2) { gchar *server_sig, *enc_server_sig; @@ -419,7 +425,7 @@ { JabberScramData *data = js->auth_mech_data; xmlnode *reply; - gchar *enc_in, *dec_in; + gchar *enc_in, *dec_in = NULL; gchar *enc_out = NULL, *dec_out = NULL; gsize len; JabberSaslState state = JABBER_SASL_STATE_FAIL; @@ -434,7 +440,6 @@ } dec_in = (gchar *)purple_base64_decode(enc_in, &len); - g_free(enc_in); if (!dec_in || len != strlen(dec_in)) { /* Danger afoot; SCRAM shouldn't contain NUL bytes */ reply = xmlnode_new("abort"); @@ -468,6 +473,8 @@ state = JABBER_SASL_STATE_CONTINUE; out: + g_free(enc_in); + g_free(dec_in); g_free(enc_out); g_free(dec_out); @@ -506,11 +513,13 @@ purple_debug_misc("jabber", "decoded success: %s\n", dec_in); if (!jabber_scram_feed_parser(data, dec_in, &dec_out) || dec_out != NULL) { + g_free(dec_in); g_free(dec_out); *error = g_strdup(_("Invalid challenge from server")); return JABBER_SASL_STATE_FAIL; } + g_free(dec_in); /* Hooray */ return JABBER_SASL_STATE_OK; }
--- a/libpurple/protocols/jabber/bosh.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/protocols/jabber/bosh.c Thu Apr 22 14:45:57 2010 +0900 @@ -78,13 +78,11 @@ } state; guint8 failed_connections; - int max_inactivity; int wait; int max_requests; int requests; - guint inactivity_timer; guint send_timer; }; @@ -239,8 +237,6 @@ if (conn->send_timer) purple_timeout_remove(conn->send_timer); - if (conn->inactivity_timer) - purple_timeout_remove(conn->inactivity_timer); purple_circ_buffer_destroy(conn->pending); @@ -433,34 +429,14 @@ return FALSE; } -static gboolean -bosh_inactivity_cb(gpointer data) +void +jabber_bosh_connection_send_keepalive(PurpleBOSHConnection *bosh) { - PurpleBOSHConnection *bosh = data; - bosh->inactivity_timer = 0; - if (bosh->send_timer != 0) purple_timeout_remove(bosh->send_timer); /* clears bosh->send_timer */ send_timer_cb(bosh); - - return FALSE; -} - -static void -restart_inactivity_timer(PurpleBOSHConnection *conn) -{ - if (conn->inactivity_timer != 0) { - purple_timeout_remove(conn->inactivity_timer); - conn->inactivity_timer = 0; - } - - if (conn->max_inactivity != 0) { - conn->inactivity_timer = - purple_timeout_add_seconds(conn->max_inactivity - 5 /* rounding */, - bosh_inactivity_cb, conn); - } } static void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode *node) { @@ -541,19 +517,20 @@ } if (inactivity) { - conn->max_inactivity = atoi(inactivity); - if (conn->max_inactivity <= 5) { + js->max_inactivity = atoi(inactivity); + if (js->max_inactivity <= 5) { purple_debug_warning("jabber", "Ignoring bogusly small inactivity: %s\n", inactivity); - conn->max_inactivity = 0; + /* Leave it at the default */ } else { - /* TODO: Integrate this with jabber.c keepalive checks... */ /* TODO: Can this check fail? It shouldn't */ - if (conn->inactivity_timer == 0) { + js->max_inactivity -= 5; /* rounding */ + + if (js->inactivity_timer == 0) { purple_debug_misc("jabber", "Starting BOSH inactivity timer " "for %d secs (compensating for rounding)\n", - conn->max_inactivity - 5); - restart_inactivity_timer(conn); + js->max_inactivity); + jabber_stream_restart_inactivity_timer(js); } } } @@ -976,7 +953,7 @@ size_t len; /* Sending something to the server, restart the inactivity timer */ - restart_inactivity_timer(conn->bosh); + jabber_stream_restart_inactivity_timer(conn->bosh->js); data = g_strdup_printf("POST %s HTTP/1.1\r\n" "Host: %s\r\n"
--- a/libpurple/protocols/jabber/bosh.h Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/protocols/jabber/bosh.h Thu Apr 22 14:45:57 2010 +0900 @@ -35,6 +35,7 @@ void jabber_bosh_connection_destroy(PurpleBOSHConnection *conn); gboolean jabber_bosh_connection_is_ssl(PurpleBOSHConnection *conn); +void jabber_bosh_connection_send_keepalive(PurpleBOSHConnection *conn); void jabber_bosh_connection_connect(PurpleBOSHConnection *conn); void jabber_bosh_connection_close(PurpleBOSHConnection *conn);
--- a/libpurple/protocols/jabber/jabber.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/protocols/jabber/jabber.c Thu Apr 22 14:45:57 2010 +0900 @@ -71,6 +71,10 @@ #include "jingle/rtp.h" #define PING_TIMEOUT 60 +/* Send a whitespace keepalive to the server if we haven't sent + * anything in the last 120 seconds + */ +#define DEFAULT_INACTIVITY_TIME 120 GList *jabber_features = NULL; GList *jabber_identities = NULL; @@ -166,6 +170,8 @@ char *msg = jabber_parse_error(js, packet, &reason); purple_connection_error_reason(js->gc, reason, msg); g_free(msg); + + return; } jabber_session_init(js); @@ -361,6 +367,9 @@ if (len == -1) len = strlen(data); + if (js->state == JABBER_STREAM_CONNECTED) + jabber_stream_restart_inactivity_timer(js); + if (js->writeh == 0) ret = jabber_do_send(js, data, len); else { @@ -842,6 +851,7 @@ purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, _("Invalid XMPP ID")); + g_free(user); /* Destroying the connection will free the JabberStream */ return NULL; } @@ -850,6 +860,7 @@ purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, _("Invalid XMPP ID. Username portion must be set.")); + g_free(user); /* Destroying the connection will free the JabberStream */ return NULL; } @@ -858,6 +869,7 @@ purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, _("Invalid XMPP ID. Domain must be set.")); + g_free(user); /* Destroying the connection will free the JabberStream */ return NULL; } @@ -886,6 +898,7 @@ js->write_buffer = purple_circ_buffer_new(512); js->old_length = 0; js->keepalive_timeout = 0; + js->max_inactivity = DEFAULT_INACTIVITY_TIME; /* Set the default protocol version to 1.0. Overridden in parser.c. */ js->protocol_version.major = 1; js->protocol_version.minor = 0; @@ -1540,7 +1553,8 @@ g_free(js->avatar_hash); g_free(js->caps_hash); - purple_circ_buffer_destroy(js->write_buffer); + if (js->write_buffer) + purple_circ_buffer_destroy(js->write_buffer); if(js->writeh) purple_input_remove(js->writeh); if (js->auth_mech && js->auth_mech->dispose) @@ -1579,6 +1593,8 @@ if (js->keepalive_timeout != 0) purple_timeout_remove(js->keepalive_timeout); + if (js->inactivity_timer != 0) + purple_timeout_remove(js->inactivity_timer); g_free(js->srv_rec); js->srv_rec = NULL; @@ -1630,6 +1646,9 @@ case JABBER_STREAM_CONNECTED: /* Send initial presence */ jabber_presence_send(js, TRUE); + /* Start up the inactivity timer */ + jabber_stream_restart_inactivity_timer(js); + purple_connection_set_state(js->gc, PURPLE_CONNECTED); break; } @@ -1918,6 +1937,38 @@ (!js->bosh && js->gsc); } +static gboolean +inactivity_cb(gpointer data) +{ + JabberStream *js = data; + + /* We want whatever is sent to set this. It's okay because + * the eventloop unsets it via the return FALSE. + */ + js->inactivity_timer = 0; + + if (js->bosh) + jabber_bosh_connection_send_keepalive(js->bosh); + else + jabber_send_raw(js, "\t", 1); + + return FALSE; +} + +void jabber_stream_restart_inactivity_timer(JabberStream *js) +{ + if (js->inactivity_timer != 0) { + purple_timeout_remove(js->inactivity_timer); + js->inactivity_timer = 0; + } + + g_return_if_fail(js->max_inactivity > 0); + + js->inactivity_timer = + purple_timeout_add_seconds(js->max_inactivity, + inactivity_cb, js); +} + const char *jabber_list_icon(PurpleAccount *a, PurpleBuddy *b) { return "jabber"; @@ -3684,6 +3735,11 @@ jabber_presence_uninit(); jabber_iq_uninit(); +#ifdef USE_VV + g_signal_handlers_disconnect_by_func(G_OBJECT(purple_media_manager_get()), + G_CALLBACK(jabber_caps_broadcast_change), NULL); +#endif + jabber_auth_uninit(); jabber_features_destroy(); jabber_identities_destroy();
--- a/libpurple/protocols/jabber/jabber.h Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/protocols/jabber/jabber.h Thu Apr 22 14:45:57 2010 +0900 @@ -255,6 +255,8 @@ /* A purple timeout tag for the keepalive */ guint keepalive_timeout; + guint max_inactivity; + guint inactivity_timer; PurpleSrvResponse *srv_rec; guint srv_rec_idx; @@ -349,6 +351,13 @@ */ gboolean jabber_stream_is_ssl(JabberStream *js); +/** + * Restart the "we haven't sent anything in a while and should send + * something or the server will kick us off" timer (obviously + * called when sending something. It's exposed for BOSH.) + */ +void jabber_stream_restart_inactivity_timer(JabberStream *js); + /** PRPL functions */ const char *jabber_list_icon(PurpleAccount *a, PurpleBuddy *b); const char* jabber_list_emblem(PurpleBuddy *b);
--- a/libpurple/protocols/jabber/presence.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/protocols/jabber/presence.c Thu Apr 22 14:45:57 2010 +0900 @@ -823,6 +823,7 @@ if (presence->jb != js->user_jb) { purple_debug_warning("jabber", "Got presence for unknown buddy %s on account %s (%p)\n", buddy_name, purple_account_get_username(account), account); + g_free(buddy_name); return FALSE; } else { /* this is a different resource of our own account. Resume even when this account isn't on our blist */
--- a/libpurple/protocols/msn/msn.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/protocols/msn/msn.c Thu Apr 22 14:45:57 2010 +0900 @@ -610,6 +610,14 @@ { MsnSlpLink *slplink = xfer->data; msn_slplink_request_ft(slplink, xfer); + msn_slplink_unref(slplink); +} + +static void +t_msn_xfer_cancel_send(PurpleXfer *xfer) +{ + MsnSlpLink *slplink = xfer->data; + msn_slplink_unref(slplink); } static PurpleXfer* @@ -624,9 +632,10 @@ g_return_val_if_fail(xfer != NULL, NULL); - xfer->data = msn_session_get_slplink(session, who); + xfer->data = msn_slplink_ref(msn_session_get_slplink(session, who)); purple_xfer_set_init_fnc(xfer, t_msn_xfer_init); + purple_xfer_set_cancel_send_fnc(xfer, t_msn_xfer_cancel_send); return xfer; }
--- a/libpurple/protocols/msn/notification.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/protocols/msn/notification.c Thu Apr 22 14:45:57 2010 +0900 @@ -983,19 +983,12 @@ static void fln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { - MsnSlpLink *slplink; MsnUser *user; /* Tell libpurple that the user has signed off */ user = msn_userlist_find_user(cmdproc->session->userlist, cmd->params[0]); msn_user_set_state(user, NULL); msn_user_update(user); - - /* If we have an open MsnSlpLink with the user then close it */ - slplink = msn_session_find_slplink(cmdproc->session, cmd->params[0]); - if (slplink != NULL) - msn_slplink_destroy(slplink); - } static void
--- a/libpurple/protocols/msn/slplink.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/protocols/msn/slplink.c Thu Apr 22 14:45:57 2010 +0900 @@ -78,7 +78,7 @@ session->slplinks = g_list_append(session->slplinks, slplink); - return slplink; + return msn_slplink_ref(slplink); } void @@ -94,6 +94,11 @@ if (slplink->swboard != NULL) slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink); + if (slplink->refs > 1) { + slplink->refs--; + return; + } + session = slplink->session; #if 0 @@ -115,6 +120,31 @@ } MsnSlpLink * +msn_slplink_ref(MsnSlpLink *slplink) +{ + g_return_val_if_fail(slplink != NULL, NULL); + + slplink->refs++; + if (purple_debug_is_verbose()) + purple_debug_info("msn", "slplink ref (%p)[%d]\n", slplink, slplink->refs); + + return slplink; +} + +void +msn_slplink_unref(MsnSlpLink *slplink) +{ + g_return_if_fail(slplink != NULL); + + slplink->refs--; + if (purple_debug_is_verbose()) + purple_debug_info("msn", "slplink unref (%p)[%d]\n", slplink, slplink->refs); + + if (slplink->refs == 0) + msn_slplink_destroy(slplink); +} + +MsnSlpLink * msn_session_find_slplink(MsnSession *session, const char *who) { GList *l;
--- a/libpurple/protocols/msn/slplink.h Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/protocols/msn/slplink.h Thu Apr 22 14:45:57 2010 +0900 @@ -43,6 +43,8 @@ MsnSession *session; MsnSwitchBoard *swboard; + int refs; + char *remote_user; int slp_seq_id; @@ -55,6 +57,9 @@ GQueue *slp_msg_queue; }; +MsnSlpLink *msn_slplink_ref(MsnSlpLink *slplink); +void msn_slplink_unref(MsnSlpLink *slplink); + void msn_slplink_destroy(MsnSlpLink *slplink); /**
--- a/libpurple/protocols/msn/switchboard.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/protocols/msn/switchboard.c Thu Apr 22 14:45:57 2010 +0900 @@ -937,7 +937,7 @@ } imgid = purple_imgstore_add_with_id(image_data, image_len, NULL); - image_msg = g_strdup_printf("<IMG ID='%d'/>", imgid); + image_msg = g_strdup_printf("<IMG ID='%d'>", imgid); if (swboard->current_users > 1 || ((swboard->conv != NULL) &&
--- a/libpurple/protocols/oscar/family_icbm.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/protocols/oscar/family_icbm.c Thu Apr 22 14:45:57 2010 +0900 @@ -274,8 +274,8 @@ | AIM_IMPARAM_FLAG_MISSED_CALLS_ENABLED | AIM_IMPARAM_FLAG_EVENTS_ALLOWED | AIM_IMPARAM_FLAG_SMS_SUPPORTED - | AIM_IMPARAM_FLAG_SEND_ME_HTML_FOR_ICQ - | AIM_IMPARAM_FLAG_OFFLINE_MSGS_ALLOWED; + | AIM_IMPARAM_FLAG_OFFLINE_MSGS_ALLOWED + | AIM_IMPARAM_FLAG_USE_HTML_FOR_ICQ; params.maxmsglen = 8000; params.minmsginterval = 0;
--- a/libpurple/protocols/oscar/oscar.h Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/protocols/oscar/oscar.h Thu Apr 22 14:45:57 2010 +0900 @@ -746,7 +746,21 @@ #define AIM_IMPARAM_FLAG_EVENTS_ALLOWED 0x00000008 #define AIM_IMPARAM_FLAG_SMS_SUPPORTED 0x00000010 #define AIM_IMPARAM_FLAG_OFFLINE_MSGS_ALLOWED 0x00000100 -#define AIM_IMPARAM_FLAG_SEND_ME_HTML_FOR_ICQ 0x00000400 + +/** + * This flag tells the server that we always send HTML in messages + * sent from an ICQ account to an ICQ account. (If this flag is + * not sent then plaintext is sent ICQ<-->ICQ (HTML is sent in all + * other cases)). + * + * If we send an HTML message to an old client that doesn't support + * HTML messages, then the oscar servers will merrily strip the HTML + * for us. + * + * When we receive an IM we look at the features on the ICBM to + * determine if the message is HTML or plaintext. + */ +#define AIM_IMPARAM_FLAG_USE_HTML_FOR_ICQ 0x00000400 /* This is what the server will give you if you don't set them yourself. */ /* This is probably out of date. */
--- a/libpurple/proxy.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/proxy.c Thu Apr 22 14:45:57 2010 +0900 @@ -379,11 +379,16 @@ char *d; d = g_strrstr(host, ":"); - if (d) + if (d) { *d = '\0'; - d++; - if (*d) - sscanf(d, "%d", &port); + + d++; + if (*d) + sscanf(d, "%d", &port); + + if (port == 0) + port = default_port; + } purple_proxy_info_set_host(info, host); purple_proxy_info_set_port(info, port);
--- a/libpurple/util.c Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/util.c Thu Apr 22 14:45:57 2010 +0900 @@ -586,6 +586,7 @@ { purple_debug_error("util", "Format conversion failed in purple_utf8_strftime(): %s\n", err->message); g_error_free(err); + err = NULL; locale = g_strdup(format); } @@ -3011,22 +3012,86 @@ #endif } +typedef union purple_sockaddr { + struct sockaddr sa; + struct sockaddr_in sa_in; +#if defined(AF_INET6) + struct sockaddr_in6 sa_in6; +#endif + struct sockaddr_storage sa_stor; +} PurpleSockaddr; + char * purple_fd_get_ip(int fd) { - struct sockaddr addr; + PurpleSockaddr addr; socklen_t namelen = sizeof(addr); - struct in_addr in; + int family; g_return_val_if_fail(fd != 0, NULL); - if (getsockname(fd, &addr, &namelen)) + if (getsockname(fd, &(addr.sa), &namelen)) return NULL; - in = ((struct sockaddr_in *)&addr)->sin_addr; - return g_strdup(inet_ntoa(in)); + family = addr.sa.sa_family; + + if (family == AF_INET) { + return g_strdup(inet_ntoa(addr.sa_in.sin_addr)); + } +#if defined(AF_INET6) && defined(HAVE_INET_NTOP) + else if (family == AF_INET6) { + char host[INET6_ADDRSTRLEN]; + const char *tmp; + + tmp = inet_ntop(family, &(addr.sa_in6.sin6_addr), host, sizeof(host)); + return g_strdup(tmp); + } +#endif + + return NULL; } +int +purple_socket_get_family(int fd) +{ + PurpleSockaddr addr; + socklen_t len = sizeof(addr); + + g_return_val_if_fail(fd >= 0, -1); + + if (getsockname(fd, &(addr.sa), &len)) + return -1; + + return addr.sa.sa_family; +} + +gboolean +purple_socket_speaks_ipv4(int fd) +{ + int family; + + g_return_val_if_fail(fd >= 0, FALSE); + + family = purple_socket_get_family(fd); + + switch (family) { + case AF_INET: + return TRUE; +#if defined(IPV6_V6ONLY) + case AF_INET6: + { + int val = 0; + guint len = sizeof(val); + + if (getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, &len) != 0) + return FALSE; + return !val; + } +#endif + default: + return FALSE; + } +} /************************************************************************** * String Functions
--- a/libpurple/util.h Thu Apr 15 16:48:50 2010 +0900 +++ b/libpurple/util.h Thu Apr 22 14:45:57 2010 +0900 @@ -819,6 +819,29 @@ */ char *purple_fd_get_ip(int fd); +/** + * Returns the address family of a socket. + * + * @param fd The socket file descriptor. + * + * @return The address family of the socket (AF_INET, AF_INET6, etc) or -1 + * on error. + * @since 2.7.0 + */ +int purple_socket_get_family(int fd); + +/** + * Returns TRUE if a socket is capable of speaking IPv4. + * + * This is the case for IPv4 sockets and, on some systems, IPv6 sockets + * (due to the IPv4-mapped address functionality). + * + * @param fd The socket file descriptor + * @return TRUE if a socket can speak IPv4. + * @since 2.7.0 + */ +gboolean purple_socket_speaks_ipv4(int fd); + /*@}*/
--- a/pidgin/gtkblist.c Thu Apr 15 16:48:50 2010 +0900 +++ b/pidgin/gtkblist.c Thu Apr 22 14:45:57 2010 +0900 @@ -7467,7 +7467,7 @@ return gtkblist; } -static void account_signon_cb(PurpleConnection *gc, gpointer z) +static gboolean autojoin_cb(PurpleConnection *gc, gpointer data) { PurpleAccount *account = purple_connection_get_account(gc); PurpleBlistNode *gnode, *cnode; @@ -7493,6 +7493,9 @@ serv_join_chat(gc, chat->components); } } + + /* Stop processing; we handled the autojoins. */ + return TRUE; } void * @@ -7569,10 +7572,6 @@ cached_emblems = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); - purple_signal_connect(purple_connections_get_handle(), "signed-on", - gtk_blist_handle, PURPLE_CALLBACK(account_signon_cb), - NULL); - /* Initialize prefs */ purple_prefs_add_none(PIDGIN_PREFS_ROOT "/blist"); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons", TRUE); @@ -7631,6 +7630,9 @@ purple_signal_connect(purple_blist_get_handle(), "buddy-privacy-changed", gtk_blist_handle, PURPLE_CALLBACK(pidgin_blist_update_privacy_cb), NULL); + purple_signal_connect_priority(purple_connections_get_handle(), "autojoin", + gtk_blist_handle, PURPLE_CALLBACK(autojoin_cb), + NULL, PURPLE_SIGNAL_PRIORITY_HIGHEST); } void @@ -7746,7 +7748,6 @@ return; } - if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(gtkblist->treemodel), &more_z, &groupiter)) { gtk_tree_store_insert(gtkblist->treemodel, iter, &groupiter, 0); return;
--- a/pidgin/gtkimhtml.c Thu Apr 15 16:48:50 2010 +0900 +++ b/pidgin/gtkimhtml.c Thu Apr 22 14:45:57 2010 +0900 @@ -1198,8 +1198,14 @@ printf("\n"); } #endif - text = g_malloc(selection_data->length); + + text = g_malloc(selection_data->length + 1); memcpy(text, selection_data->data, selection_data->length); + /* Make sure the paste data is null-terminated. Given that + * we're passed length (but assume later that it is + * null-terminated), this seems sensible to me. + */ + text[selection_data->length] = '\0'; } #ifdef _WIN32
--- a/pidgin/gtkutils.c Thu Apr 15 16:48:50 2010 +0900 +++ b/pidgin/gtkutils.c Thu Apr 22 14:45:57 2010 +0900 @@ -2469,7 +2469,7 @@ break; } - if (spec->max_filesize == 0 || length < spec->max_filesize) { + if (spec->max_filesize == 0 || length <= spec->max_filesize) { /* We were able to save the image as this image type and have it be within the size constraints. Great! Return the image. */ @@ -2507,7 +2507,7 @@ new_height = orig_height * scale_factor; g_object_unref(G_OBJECT(pixbuf)); pixbuf = gdk_pixbuf_scale_simple(original, new_width, new_height, GDK_INTERP_HYPER); - } while (new_width > 10 || new_height > 10); + } while ((new_width > 10 || new_height > 10) && new_width > spec->min_width && new_height > spec->min_height); g_strfreev(prpl_formats); g_object_unref(G_OBJECT(pixbuf)); g_object_unref(G_OBJECT(original));
--- a/pidgin/plugins/ticker/gtkticker.c Thu Apr 15 16:48:50 2010 +0900 +++ b/pidgin/plugins/ticker/gtkticker.c Thu Apr 22 14:45:57 2010 +0900 @@ -343,7 +343,7 @@ window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); -#if GTK_CHECK_VERSION(2,14,0) +#if GTK_CHECK_VERSION(2,18,0) gtk_widget_set_window (widget, window); #else widget->window = window;