# HG changeset patch # User Elliott Sales de Andrade # Date 1272231633 0 # Node ID 35cbe46841779322ce7be5a2b3fa78788cc068ea # Parent 0f1df8098d0084e771438b2f8f4018a7bfc956d5# Parent 45ec328db5bd1484cd78576715f611da6547b988 propagate from branch 'im.pidgin.pidgin' (head 1ccb1507e6594c80788043ea114c7fb942828e48) to branch 'im.pidgin.cpw.malu.ft_thumbnails' (head b439e619df4a497e9807614d87f9fb47308d648b) diff -r 45ec328db5bd -r 35cbe4684177 COPYRIGHT --- a/COPYRIGHT Sun Apr 25 21:24:06 2010 +0000 +++ b/COPYRIGHT Sun Apr 25 21:40:33 2010 +0000 @@ -245,6 +245,7 @@ Jochen Kemnade Yann Kerherve Gordian Klein +Marten Klencke Krzysztof Klinikowski Akuke Kok Kir Kolyshkin @@ -294,6 +295,7 @@ Paolo Maggi Sulabh Mahajan Willian T. Mahan +Jonathan Maltz Tobias Markmann Kris Marsh Fidel Martinez diff -r 45ec328db5bd -r 35cbe4684177 ChangeLog --- a/ChangeLog Sun Apr 25 21:24:06 2010 +0000 +++ b/ChangeLog Sun Apr 25 21:40:33 2010 +0000 @@ -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 (from IE) does not have a port. + (Marten Klencke) Pidgin: * Moved the "Debugging Information" section of the About box to a @@ -39,12 +41,14 @@ * Default binding of Ctrl+Shift+v to 'Paste as Plain Text' in conversation windows. This can be changed in .gtkrc-2.0. For example, Ctrl+v can be bound to 'Paste as Plain Text' by default. - * Plugins can now handle markup in buddy names by attaching to the signal - "drawing-buddy". (Daniele Ricci, Andrea Piccinelli) + * Plugins can now handle markup in buddy names by attaching to the + "drawing-buddy" signal. (Daniele Ricci, Andrea Piccinelli) * Be more accommodating when scaling down large images for use as buddy icons. * The 'Message Timestamp Formats' plugin allows changing the timestamp format from the timestamps' context menu in conversation log. + * The 'Message Timestamp Formats' plugin allows forcing 12-hour + timestamps. (Jonathan Maltz) * Fix pastes from Chrome (rich-text pastes and probably URLs having garbage appended to them) @@ -58,9 +62,9 @@ AIM and ICQ: * X-Status (Custom ICQ status icon) support. Since most of the icons - available reflect moods, this is labeled "Set Mood" on the Accounts->ICQ - Account menu. (Andrew Ivanov, Tomáš Kebert, Yuriy Yevgrafov, and trac - users bob007, salieff, and nops) + available reflect moods, this is labeled "Set Mood" on the + Accounts->ICQ Account menu. (Andrew Ivanov, Tomáš Kebert, + Yuriy Yevgrafov, and trac users bob007, salieff, and nops) * Allow setting and displaying icons between 1x1 and 100x100 pixels for ICQ. Previously only icons between 48x48 and 52x64 were allowed. * When using the clientLogin authentication method, prompt for a @@ -77,22 +81,27 @@ * Direct messages to a specific resource only upon receipt of a message with content (as opposed to a typing notification, etc). (Thanks to rjoly for testing) - * When sending data using in-band-bytestreams, interpret the block-size - attribute as the size of the BASE64-encoded representation of the data. - * Validate the hash on incoming BoB data objects (for custom smileys etc.), - cache based per JID when the CID is not a valid hash (as specified by the - BoB XEP). * Present a better error message when authentication fails while trying to connect to Facebook. (David Reiss, Facebook) + * When sending data using in-band-bytestreams, interpret the block-size + attribute as the size of the BASE64-encoded representation of the + data. + * Validate the hash on incoming BoB data objects (for custom smileys + etc.), cache based per JID when the CID is not a valid hash (as + specified by the BoB XEP). + * 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 - login. + * Attempt to better handle transparent proxies interfering with + HTTP-based login. * Fix handling of P2P packets, thus fixing the loss of some messages. * Retrieve the pager server address from Yahoo!'s servers directly. * Removed the "Pager server" account option, as it is no longer needed. - * The authentication code is now less order-sensitive with the components - of the server's response. + * The authentication code is now less order-sensitive with the + components of the server's response. * The authentication process now acts more like the official client. Finch: diff -r 45ec328db5bd -r 35cbe4684177 finch/gntblist.c --- a/finch/gntblist.c Sun Apr 25 21:24:06 2010 +0000 +++ b/finch/gntblist.c Sun Apr 25 21:40:33 2010 +0000 @@ -1117,6 +1117,8 @@ list = g_list_delete_link(list, list)) { PurpleMenuAction *act = (PurpleMenuAction *) list->data; + if (!act) + continue; act->data = node; gnt_append_menu_action(menu, act, NULL); g_signal_connect_swapped(G_OBJECT(menu), "destroy", diff -r 45ec328db5bd -r 35cbe4684177 libpurple/protocols/gg/gg.c --- a/libpurple/protocols/gg/gg.c Sun Apr 25 21:24:06 2010 +0000 +++ b/libpurple/protocols/gg/gg.c Sun Apr 25 21:40:33 2010 +0000 @@ -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"; diff -r 45ec328db5bd -r 35cbe4684177 libpurple/protocols/jabber/bosh.c --- a/libpurple/protocols/jabber/bosh.c Sun Apr 25 21:24:06 2010 +0000 +++ b/libpurple/protocols/jabber/bosh.c Sun Apr 25 21:40:33 2010 +0000 @@ -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" diff -r 45ec328db5bd -r 35cbe4684177 libpurple/protocols/jabber/bosh.h --- a/libpurple/protocols/jabber/bosh.h Sun Apr 25 21:24:06 2010 +0000 +++ b/libpurple/protocols/jabber/bosh.h Sun Apr 25 21:40:33 2010 +0000 @@ -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); diff -r 45ec328db5bd -r 35cbe4684177 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Sun Apr 25 21:24:06 2010 +0000 +++ b/libpurple/protocols/jabber/jabber.c Sun Apr 25 21:40:33 2010 +0000 @@ -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; @@ -363,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 { @@ -889,6 +896,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; @@ -1583,6 +1591,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; @@ -1634,6 +1644,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; } @@ -1922,6 +1935,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"; diff -r 45ec328db5bd -r 35cbe4684177 libpurple/protocols/jabber/jabber.h --- a/libpurple/protocols/jabber/jabber.h Sun Apr 25 21:24:06 2010 +0000 +++ b/libpurple/protocols/jabber/jabber.h Sun Apr 25 21:40:33 2010 +0000 @@ -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); diff -r 45ec328db5bd -r 35cbe4684177 libpurple/protocols/msn/msg.c --- a/libpurple/protocols/msn/msg.c Sun Apr 25 21:24:06 2010 +0000 +++ b/libpurple/protocols/msn/msg.c Sun Apr 25 21:40:33 2010 +0000 @@ -970,14 +970,13 @@ static void got_wink_cb(MsnSlpCall *slpcall, const guchar *data, gsize size) { - FILE *f; + FILE *f = NULL; char *path = NULL; const char *who = slpcall->slplink->remote_user; purple_debug_info("msn", "Received wink from %s\n", who); - if ((f = purple_mkstemp(&path, TRUE))) { - fwrite(data, size, 1, f); - fclose(f); + if ((f = purple_mkstemp(&path, TRUE)) && + (fwrite(data, 1, size, f) == size)) { datacast_inform_user(slpcall->slplink->swboard, who, _("%s sent a wink. Click here to play it"), @@ -988,21 +987,22 @@ who, _("%s sent a wink, but it could not be saved"), NULL); - } + } + if (f) + fclose(f); g_free(path); } static void got_voiceclip_cb(MsnSlpCall *slpcall, const guchar *data, gsize size) { - FILE *f; + FILE *f = NULL; char *path = NULL; const char *who = slpcall->slplink->remote_user; purple_debug_info("msn", "Received voice clip from %s\n", who); - if ((f = purple_mkstemp(&path, TRUE))) { - fwrite(data, size, 1, f); - fclose(f); + if ((f = purple_mkstemp(&path, TRUE)) && + (fwrite(data, 1, size, f) == size)) { datacast_inform_user(slpcall->slplink->swboard, who, _("%s sent a voice clip. Click here to play it"), @@ -1013,7 +1013,9 @@ who, _("%s sent a voice clip, but it could not be saved"), NULL); - } + } + if (f) + fclose(f); g_free(path); } diff -r 45ec328db5bd -r 35cbe4684177 libpurple/protocols/msn/session.c --- a/libpurple/protocols/msn/session.c Sun Apr 25 21:24:06 2010 +0000 +++ b/libpurple/protocols/msn/session.c Sun Apr 25 21:40:33 2010 +0000 @@ -407,7 +407,7 @@ /* Prevent the connection progress going backwards, eg. if we get * transferred several times during login */ - if (session->login_step > step) + if (session->login_step >= step) return; /* If we're already logged in, we're probably here because of a diff -r 45ec328db5bd -r 35cbe4684177 libpurple/proxy.c --- a/libpurple/proxy.c Sun Apr 25 21:24:06 2010 +0000 +++ b/libpurple/proxy.c Sun Apr 25 21:40:33 2010 +0000 @@ -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); diff -r 45ec328db5bd -r 35cbe4684177 pidgin/gtkutils.c --- a/pidgin/gtkutils.c Sun Apr 25 21:24:06 2010 +0000 +++ b/pidgin/gtkutils.c Sun Apr 25 21:40:33 2010 +0000 @@ -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)); diff -r 45ec328db5bd -r 35cbe4684177 pidgin/plugins/timestamp_format.c --- a/pidgin/plugins/timestamp_format.c Sun Apr 25 21:24:06 2010 +0000 +++ b/pidgin/plugins/timestamp_format.c Sun Apr 25 21:40:33 2010 +0000 @@ -12,6 +12,17 @@ #include +static const char *format_12hour_hour(const struct tm *tm) +{ + static char hr[3]; + int hour = tm->tm_hour % 12; + if (hour == 0) + hour = 12; + + g_snprintf(hr, sizeof(hr), "%d", hour); + return hr; +} + static PurplePluginPrefFrame * get_plugin_pref_frame(PurplePlugin *plugin) { @@ -24,10 +35,14 @@ ppref = purple_plugin_pref_new_with_label(_("Timestamp Format Options")); purple_plugin_pref_frame_add(frame, ppref); - tmp = g_strdup_printf(_("_Force 24-hour time format")); + tmp = g_strdup_printf(_("_Force timestamp format:")); ppref = purple_plugin_pref_new_with_name_and_label( - "/plugins/gtk/timestamp_format/force_24hr", + "/plugins/gtk/timestamp_format/force", tmp); + purple_plugin_pref_set_type(ppref, PURPLE_PLUGIN_PREF_CHOICE); + purple_plugin_pref_add_choice(ppref, _("Use system default"), "default"); + purple_plugin_pref_add_choice(ppref, _("12 hour time format"), "force12"); + purple_plugin_pref_add_choice(ppref, _("24 hour time format"), "force24"); purple_plugin_pref_frame_add(frame, ppref); g_free(tmp); @@ -58,27 +73,50 @@ static char *timestamp_cb_common(PurpleConversation *conv, time_t t, gboolean show_date, - gboolean force, + const char *force, const char *dates, gboolean parens) { + struct tm *tm; + g_return_val_if_fail(dates != NULL, NULL); + tm = localtime(&t); + if (show_date || !strcmp(dates, "always") || (conv != NULL && purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && !strcmp(dates, "chats"))) { - struct tm *tm = localtime(&t); - if (force) + if (g_str_equal(force, "force24")) return g_strdup_printf("%s%s%s", parens ? "(" : "", purple_utf8_strftime("%Y-%m-%d %H:%M:%S", tm), parens ? ")" : ""); - else + else if (g_str_equal(force, "force12")) { + char *date = g_strdup_printf("%s", purple_utf8_strftime("%Y-%m-%d ", tm)); + char *remtime = g_strdup_printf("%s", purple_utf8_strftime(":%M:%S %p", tm)); + const char *hour = format_12hour_hour(tm); + char *output; + + output = g_strdup_printf("%s%s%s%s%s", + parens ? "(" : "", date, + hour, remtime, parens ? ")" : ""); + + g_free(date); + g_free(remtime); + + return output; + } else return g_strdup_printf("%s%s%s", parens ? "(" : "", purple_date_format_long(tm), parens ? ")" : ""); } - if (force) - { - struct tm *tm = localtime(&t); + if (g_str_equal(force, "force24")) return g_strdup_printf("%s%s%s", parens ? "(" : "", purple_utf8_strftime("%H:%M:%S", tm), parens ? ")" : ""); + else if (g_str_equal(force, "force12")) { + const char *hour = format_12hour_hour(tm); + char *remtime = g_strdup_printf("%s", purple_utf8_strftime(":%M:%S %p", tm)); + char *output = g_strdup_printf("%s%s%s%s", parens ? "(" : "", hour, remtime, parens ? ")" : ""); + + g_free(remtime); + + return output; } return NULL; @@ -87,8 +125,8 @@ static char *conversation_timestamp_cb(PurpleConversation *conv, time_t t, gboolean show_date, gpointer data) { - gboolean force = purple_prefs_get_bool( - "/plugins/gtk/timestamp_format/force_24hr"); + const char *force = purple_prefs_get_string( + "/plugins/gtk/timestamp_format/force"); const char *dates = purple_prefs_get_string( "/plugins/gtk/timestamp_format/use_dates/conversation"); @@ -99,8 +137,8 @@ static char *log_timestamp_cb(PurpleLog *log, time_t t, gboolean show_date, gpointer data) { - gboolean force = purple_prefs_get_bool( - "/plugins/gtk/timestamp_format/force_24hr"); + const char *force = purple_prefs_get_string( + "/plugins/gtk/timestamp_format/force"); const char *dates = purple_prefs_get_string( "/plugins/gtk/timestamp_format/use_dates/log"); @@ -264,7 +302,17 @@ purple_prefs_add_none("/plugins/gtk"); purple_prefs_add_none("/plugins/gtk/timestamp_format"); - purple_prefs_add_bool("/plugins/gtk/timestamp_format/force_24hr", TRUE); + if (!purple_prefs_exists("/plugins/gtk/timestamp_format/force") && + purple_prefs_exists("/plugins/gtk/timestamp_format/force_24hr")) + { + if (purple_prefs_get_bool( + "/plugins/gtk/timestamp_format/force_24hr")) + purple_prefs_add_string("/plugins/gtk/timestamp_format/force", "force24"); + else + purple_prefs_add_string("/plugins/gtk/timestamp_format/force", "default"); + } + else + purple_prefs_add_string("/plugins/gtk/timestamp_format/force", "default"); purple_prefs_add_none("/plugins/gtk/timestamp_format/use_dates"); purple_prefs_add_string("/plugins/gtk/timestamp_format/use_dates/conversation", "automatic");