pidgin/ljfisher-ssl-client-auth
propagate from branch 'im.pidgin.pidgin.next.minor' (head 6367f2188824192295955b993cce219a7efd9df6)
to branch 'im.pidgin.pidgin' (head 7e061aebed8b5bf744958b6663e6a4c555b2de09)
--- a/ChangeLog Wed Jun 22 02:35:45 2011 +0000
+++ b/ChangeLog Sat Jun 25 19:54:02 2011 +0000
@@ -5,25 +5,36 @@
* Significantly improved performance of larger IRC channels (regression
-version 2.8.1 (MM/DD/YYYY):
+version 2.9.1 (MM/DD/YYYY): + * Fixed searching for buddies in public directory. (Tomasz Wasilczyk) + * Better status message handling. (Tomasz Wasilczyk) (#14314) +version 2.9.0 (06/23/2011): + * Fix a potential remote denial-of-service bug related to displaying + * Significantly improved performance of larger IRC channels (regression * Fix Conversation->Add on AIM and MSN.
- * Entries in the chat user list are sorted properly again.
+ * Entries in the chat user list are sorted properly again. This was + inadvertenly broken in 2.8.0. - * Fixed logging in to ICQ.
+ * Fix logging in to ICQ. * media: Actually use the specified TCP port from the TURN configuration to
create a TCP relay candidate.
+ * Fix crashes on some non-mainstream OSes when attempting to + printf("%s", NULL). (Clemens Huebner) (#14297) * The Evolution Integration plugin compiles again.
- * Fixed searching for buddies in public directory. (Tomasz Wasilczyk)
version 2.8.0 (06/07/2011):
* Implement simple silence suppression for voice calls, preventing
--- a/ChangeLog.API Wed Jun 22 02:35:45 2011 +0000
+++ b/ChangeLog.API Sat Jun 25 19:54:02 2011 +0000
@@ -1,12 +1,17 @@
Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
-version 2.9.0 (MM/DD/YYYY):
* Hash table to PurpleConvChat struct, used to make
purple_conv_chat_cb_find O(1).
* ui_data pointer to PurpleConvChatBuddy struct.
* deleting-chat-buddy signal (conversation signals)
+ * pidgin_pixbuf_from_data + * pidgin_pixbuf_anim_from_data + * pidgin_pixbuf_new_from_file + * pidgin_pixbuf_new_from_file_at_size + * pidgin_pixbuf_new_from_file_at_scale * purple_conv_chat_set_users
--- a/libpurple/protocols/gg/gg.c Wed Jun 22 02:35:45 2011 +0000
+++ b/libpurple/protocols/gg/gg.c Sat Jun 25 19:54:02 2011 +0000
@@ -1071,6 +1071,7 @@
+ char *status_msg = NULL; ggp_update_buddy_avatar(gc, uin);
@@ -1108,14 +1109,24 @@
- purple_debug_info("gg", "st = %s\n", st);
- //msg = charset_convert(descr, "CP1250", "UTF-8");
+ status_msg = g_strdup(descr); + g_strstrip(status_msg); + if (status_msg[0] == '\0') { + purple_debug_info("gg", "status of %u is %s [%s]\n", uin, st, + status_msg ? status_msg : ""); + if (status_msg == NULL) { purple_prpl_got_user_status(purple_connection_get_account(gc),
purple_prpl_got_user_status(purple_connection_get_account(gc),
- from, st, "message", descr, NULL);
+ from, st, "message", status_msg, NULL); @@ -1945,23 +1956,18 @@
- status = purple_presence_get_active_status(purple_buddy_get_presence(b));
+ status = purple_presence_get_active_status( + purple_buddy_get_presence(b)); msg = purple_status_get_attr_string(status, "message");
- tmp = purple_markup_strip_html(msg);
- text = g_markup_escape_text(tmp, -1);
- tmp = purple_utf8_salvage(purple_status_get_name(status));
- text = g_markup_escape_text(tmp, -1);
+ tmp = purple_markup_strip_html(msg); + text = g_markup_escape_text(tmp, -1); static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
--- a/libpurple/protocols/irc/irc.c Wed Jun 22 02:35:45 2011 +0000
+++ b/libpurple/protocols/irc/irc.c Sat Jun 25 19:54:02 2011 +0000
@@ -101,7 +101,11 @@
static int irc_send_raw(PurpleConnection *gc, const char *buf, int len)
struct irc_conn *irc = (struct irc_conn*)gc->proto_data;
- return do_send(irc, buf, len);
+ irc_send_len(irc, buf, len); @@ -144,16 +148,18 @@
int irc_send(struct irc_conn *irc, const char *buf)
+ return irc_send_len(irc, buf, strlen(buf)); +int irc_send_len(struct irc_conn *irc, const char *buf, int buflen) char *tosend= g_strdup(buf);
purple_signal_emit(_irc_plugin, "irc-sending-text", purple_account_get_connection(irc->account), &tosend);
- buflen = strlen(tosend);
/* If we're not buffering writes, try to send immediately */
ret = do_send(irc, tosend, buflen);
--- a/libpurple/protocols/irc/irc.h Wed Jun 22 02:35:45 2011 +0000
+++ b/libpurple/protocols/irc/irc.h Sat Jun 25 19:54:02 2011 +0000
@@ -106,6 +106,7 @@
typedef int (*IRCCmdCallback) (struct irc_conn *irc, const char *cmd, const char *target, const char **args);
int irc_send(struct irc_conn *irc, const char *buf);
+int irc_send_len(struct irc_conn *irc, const char *buf, int len); gboolean irc_blist_timeout(struct irc_conn *irc);
gboolean irc_who_channel_timeout(struct irc_conn *irc);
void irc_buddy_query(struct irc_conn *irc);
--- a/libpurple/protocols/jabber/jabber.c Wed Jun 22 02:35:45 2011 +0000
+++ b/libpurple/protocols/jabber/jabber.c Sat Jun 25 19:54:02 2011 +0000
@@ -579,7 +579,7 @@
jabber_send_raw(js, buf, len);
+ return (len < 0 ? strlen(buf) : len); void jabber_send_signal_cb(PurpleConnection *pc, xmlnode **packet,
--- a/libpurple/tests/Makefile.am Wed Jun 22 02:35:45 2011 +0000
+++ b/libpurple/tests/Makefile.am Sat Jun 25 19:54:02 2011 +0000
@@ -17,6 +17,7 @@
$(top_builddir)/libpurple/util.h
--- a/libpurple/tests/check_libpurple.c Wed Jun 22 02:35:45 2011 +0000
+++ b/libpurple/tests/check_libpurple.c Sat Jun 25 19:54:02 2011 +0000
@@ -91,6 +91,7 @@
srunner_add_suite(sr, oscar_util_suite());
srunner_add_suite(sr, yahoo_util_suite());
srunner_add_suite(sr, util_suite());
+ srunner_add_suite(sr, xmlnode_suite()); /* make this a libpurple "ui" */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/tests/test_xmlnode.c Sat Jun 25 19:54:02 2011 +0000
@@ -0,0 +1,34 @@
+ * If we really wanted to test the billion laughs attack we would + * need to have more than just 4 ha's. But as long as this shorter + * document fails to parse, the longer one should also fail to parse. +START_TEST(test_xmlnode_billion_laughs_attack) + const char *malicious_xml_doc = "<!DOCTYPE root [ <!ENTITY ha \"Ha !\"><!ENTITY ha2 \"&ha; &ha;\"><!ENTITY ha3 \"&ha2; &ha2;\"> ]><root>&ha3;</root>"; + /* Uncomment this line if you want to see the error message given by + the parser for the above XML document */ + /* purple_debug_set_enabled(TRUE); */ + fail_if(xmlnode_from_str(malicious_xml_doc, -1), + "xmlnode_from_str() returned an XML tree, but we didn't want it to"); + Suite *s = suite_create("Utility Functions"); + TCase *tc = tcase_create("xmlnode"); + tcase_add_test(tc, test_xmlnode_billion_laughs_attack); + suite_add_tcase(s, tc); --- a/libpurple/tests/tests.h Wed Jun 22 02:35:45 2011 +0000
+++ b/libpurple/tests/tests.h Sat Jun 25 19:54:02 2011 +0000
@@ -16,6 +16,7 @@
Suite * oscar_util_suite(void);
Suite * yahoo_util_suite(void);
Suite * util_suite(void);
+Suite * xmlnode_suite(void); #define assert_int_equal(expected, actual) { \
--- a/pidgin/gtkaccount.c Wed Jun 22 02:35:45 2011 +0000
+++ b/pidgin/gtkaccount.c Sat Jun 25 19:54:02 2011 +0000
@@ -2135,7 +2135,7 @@
gtk_list_store_clear(dialog->model);
if ((path = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon")) != NULL) {
- GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, NULL);
+ GdkPixbuf *pixbuf = pidgin_pixbuf_new_from_file(path); global_buddyicon = gdk_pixbuf_scale_simple(pixbuf, 22, 22, GDK_INTERP_HYPER);
g_object_unref(G_OBJECT(pixbuf));
--- a/pidgin/gtkblist.c Wed Jun 22 02:35:45 2011 +0000
+++ b/pidgin/gtkblist.c Sat Jun 25 19:54:02 2011 +0000
@@ -2643,7 +2643,6 @@
gboolean scaled, gboolean greyed)
- GdkPixbufLoader *loader;
PurpleBuddy *buddy = NULL;
PurpleGroup *group = NULL;
const guchar *data = NULL;
@@ -2710,21 +2709,20 @@
- loader = gdk_pixbuf_loader_new();
- gdk_pixbuf_loader_write(loader, data, len, NULL);
- gdk_pixbuf_loader_close(loader, NULL);
- purple_imgstore_unref(custom_img);
+ buf = pidgin_pixbuf_from_data(data, len); purple_buddy_icon_unref(icon);
- buf = gdk_pixbuf_loader_get_pixbuf(loader);
- g_object_ref(G_OBJECT(buf));
- g_object_unref(G_OBJECT(loader));
+ purple_debug_warning("gtkblist", "Couldn't load buddy icon " + "on account %s (%s) buddyname=%s " + "custom_img_data=%p\n", + account ? purple_account_get_username(account) : "(no account)", + account ? purple_account_get_protocol_id(account) : "(no account)", + buddy ? purple_buddy_get_name(buddy) : "(no buddy)", + custom_img ? purple_imgstore_get_data(custom_img) : NULL); + purple_imgstore_unref(custom_img); + purple_imgstore_unref(custom_img); gboolean offline = FALSE, idle = FALSE;
@@ -3952,7 +3950,7 @@
- pb = gdk_pixbuf_new_from_file(path, NULL);
+ pb = pidgin_pixbuf_new_from_file(path); /* We don't want to own a ref to the pixbuf, but we need to keep clean up. */
/* I'm not sure if it would be better to just keep our ref and not let the emblem ever be destroyed */
--- a/pidgin/gtkconv.c Wed Jun 22 02:35:45 2011 +0000
+++ b/pidgin/gtkconv.c Sat Jun 25 19:54:02 2011 +0000
@@ -6320,8 +6320,6 @@
gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
gtk_tree_row_reference_free(ref);
add_chat_buddy_common(conv, cbuddy, NULL);
@@ -6408,8 +6406,8 @@
PidginConversation *gtkconv;
- GdkPixbufLoader *loader;
sml = purple_account_get_protocol_name(conv->account);
gtkconv = PIDGIN_CONVERSATION(conv);
@@ -6422,11 +6420,24 @@
g_memmove((guchar *)smiley->data + smiley->datasize, data, size);
smiley->datasize += size;
- loader = smiley->loader;
- gdk_pixbuf_loader_write(loader, data, size, NULL);
+ if (!gdk_pixbuf_loader_write(smiley->loader, data, size, &error) || error) { + purple_debug_warning("gtkconv", "gdk_pixbuf_loader_write() " + "failed with size=%zu: %s\n", size, + error ? error->message : "(no error message)"); + /* We must stop using the GdkPixbufLoader because trying to load + certain invalid GIFs with at least gdk-pixbuf 2.23.3 can return + a GdkPixbuf that will cause some operations (like + gdk_pixbuf_scale_simple()) to consume memory in an infinite loop. + But we also don't want to set smiley->loader to NULL because our + code might expect it to be set. So create a new loader. */ + g_object_unref(G_OBJECT(smiley->loader)); + smiley->loader = gdk_pixbuf_loader_new(); @@ -6434,8 +6445,8 @@
PidginConversation *gtkconv;
- GdkPixbufLoader *loader;
g_return_if_fail(conv != NULL);
g_return_if_fail(smile != NULL);
@@ -6447,17 +6458,27 @@
- loader = smiley->loader;
purple_debug_info("gtkconv", "About to close the smiley pixbuf\n");
- gdk_pixbuf_loader_close(loader, NULL);
+ if (!gdk_pixbuf_loader_close(smiley->loader, &error) || error) { + purple_debug_warning("gtkconv", "gdk_pixbuf_loader_close() " + error ? error->message : "(no error message)"); + /* We must stop using the GdkPixbufLoader because if we tried to + load certain invalid GIFs with all current versions of GDK (as + of 2011-06-15) then it's possible the loader will contain data + that could cause some operations (like gdk_pixbuf_scale_simple()) + to consume memory in an infinite loop. But we also don't want + to set smiley->loader to NULL because our code might expect it + to be set. So create a new loader. */ + g_object_unref(G_OBJECT(smiley->loader)); + smiley->loader = gdk_pixbuf_loader_new(); @@ -6957,10 +6978,6 @@
- GdkPixbufLoader *loader;
- GdkPixbufAnimation *anim;
PurpleStoredImage *custom_img = NULL;
gconstpointer data = NULL;
@@ -7038,7 +7055,6 @@
icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv));
gtk_widget_set_size_request(gtkconv->u.im->icon_container,
@@ -7047,7 +7063,6 @@
data = purple_buddy_icon_get_data(icon, &len);
gtk_widget_set_size_request(gtkconv->u.im->icon_container,
@@ -7056,25 +7071,13 @@
- loader = gdk_pixbuf_loader_new();
- gdk_pixbuf_loader_write(loader, data, len, NULL);
- gdk_pixbuf_loader_close(loader, &err);
+ gtkconv->u.im->anim = pidgin_pixbuf_anim_from_data(data, len); purple_imgstore_unref(custom_img);
- anim = gdk_pixbuf_loader_get_animation(loader);
- g_object_ref(G_OBJECT(anim));
- g_object_unref(loader);
+ if (!gtkconv->u.im->anim) { + purple_debug_error("gtkconv", "Couldn't load icon for conv %s\n", + purple_conversation_get_name(conv)); - gtkconv->u.im->anim = anim;
- purple_debug(PURPLE_DEBUG_ERROR, "gtkconv",
- "Buddy icon error: %s\n", err->message);
if (gdk_pixbuf_animation_is_static_image(gtkconv->u.im->anim)) {
--- a/pidgin/gtkdialogs.c Wed Jun 22 02:35:45 2011 +0000
+++ b/pidgin/gtkdialogs.c Sat Jun 25 19:54:02 2011 +0000
@@ -433,7 +433,7 @@
/* Generate a logo with a version number */
filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "logo.png", NULL);
- pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
+ pixbuf = pidgin_pixbuf_new_from_file(filename); #if 0 /* Don't versionize the logo when the logo has the version in it */
--- a/pidgin/gtkft.c Wed Jun 22 02:35:45 2011 +0000
+++ b/pidgin/gtkft.c Sat Jun 25 19:54:02 2011 +0000
@@ -1149,8 +1149,8 @@
if (purple_xfer_get_size(xfer) <= PIDGIN_XFER_MAX_SIZE_IMAGE_THUMBNAIL) {
- gdk_pixbuf_new_from_file_at_size(
- purple_xfer_get_local_filename(xfer), 128, 128, NULL);
+ pidgin_pixbuf_new_from_file_at_size( + purple_xfer_get_local_filename(xfer), 128, 128); gchar **formats_split = g_strsplit(formats, ",", 0);
--- a/pidgin/gtkimhtml.c Wed Jun 22 02:35:45 2011 +0000
+++ b/pidgin/gtkimhtml.c Sat Jun 25 19:54:02 2011 +0000
@@ -5057,16 +5057,8 @@
data = imhtml->funcs->image_get_data(image);
len = imhtml->funcs->image_get_size(image);
- GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
- gdk_pixbuf_loader_write(loader, data, len, NULL);
- gdk_pixbuf_loader_close(loader, NULL);
- anim = gdk_pixbuf_loader_get_animation(loader);
- g_object_ref(G_OBJECT(anim));
- g_object_unref(G_OBJECT(loader));
+ anim = pidgin_pixbuf_anim_from_data(data, len); --- a/pidgin/gtkmain.c Wed Jun 22 02:35:45 2011 +0000
+++ b/pidgin/gtkmain.c Sat Jun 25 19:54:02 2011 +0000
@@ -270,7 +270,7 @@
/* use the nice PNG icon for all the windows */
for(i=0; i<G_N_ELEMENTS(icon_sizes); i++) {
icon_path = g_build_filename(DATADIR, "icons", "hicolor", icon_sizes[i].dir, "apps", icon_sizes[i].filename, NULL);
- icon = gdk_pixbuf_new_from_file(icon_path, NULL);
+ icon = pidgin_pixbuf_new_from_file(icon_path); icons = g_list_append(icons,icon);
--- a/pidgin/gtkprefs.c Wed Jun 22 02:35:45 2011 +0000
+++ b/pidgin/gtkprefs.c Sat Jun 25 19:54:02 2011 +0000
@@ -382,7 +382,7 @@
* LEAK - Gentoo memprof thinks pixbuf is leaking here... but it
* looks like it should be ok to me. Anyone know what's up? --Mark
- pixbuf = (theme->icon ? gdk_pixbuf_new_from_file(theme->icon, NULL) : NULL);
+ pixbuf = (theme->icon ? pidgin_pixbuf_new_from_file(theme->icon) : NULL); gtk_list_store_set(prefs_smiley_themes, &iter,
@@ -452,7 +452,7 @@
image_full = purple_theme_get_image_full(theme);
- pixbuf = gdk_pixbuf_new_from_file_at_scale(image_full, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE, NULL);
+ pixbuf = pidgin_pixbuf_new_from_file_at_scale(image_full, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE); @@ -473,7 +473,7 @@
image_full = purple_theme_get_image_full(theme);
- pixbuf = gdk_pixbuf_new_from_file_at_scale(image_full, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE, NULL);
+ pixbuf = pidgin_pixbuf_new_from_file_at_scale(image_full, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE); @@ -529,7 +529,7 @@
purple_theme_manager_refresh();
tmp = g_build_filename(DATADIR, "icons", "hicolor", "32x32", "apps", "pidgin.png", NULL);
- pixbuf = gdk_pixbuf_new_from_file_at_scale(tmp, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE, NULL);
+ pixbuf = pidgin_pixbuf_new_from_file_at_scale(tmp, PREFS_OPTIMAL_ICON_SIZE, PREFS_OPTIMAL_ICON_SIZE, TRUE); --- a/pidgin/gtkrequest.c Wed Jun 22 02:35:45 2011 +0000
+++ b/pidgin/gtkrequest.c Sat Jun 25 19:54:02 2011 +0000
@@ -653,35 +653,30 @@
- GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
- GdkPixbuf *pixbuf = NULL;
- if (gdk_pixbuf_loader_write(loader, icon_data, icon_size, NULL)) {
- pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
- /* scale the image if it is too large */
- int width = gdk_pixbuf_get_width(pixbuf);
- int height = gdk_pixbuf_get_height(pixbuf);
- if (width > 128 || height > 128) {
- int scaled_width = width > height ? 128 : (128 * width) / height;
- int scaled_height = height > width ? 128 : (128 * height) / width;
- gdk_pixbuf_scale_simple(pixbuf, scaled_width, scaled_height,
+ GdkPixbuf *pixbuf = pidgin_pixbuf_from_data(icon_data, icon_size); + /* scale the image if it is too large */ + int width = gdk_pixbuf_get_width(pixbuf); + int height = gdk_pixbuf_get_height(pixbuf); + if (width > 128 || height > 128) { + int scaled_width = width > height ? 128 : (128 * width) / height; + int scaled_height = height > width ? 128 : (128 * height) / width; + gdk_pixbuf_scale_simple(pixbuf, scaled_width, scaled_height, - purple_debug_info("pidgin",
- "dialog icon was too large, scale it down\n");
- g_object_unref(pixbuf);
+ purple_debug_info("pidgin", + "dialog icon was too large, scaled it down\n"); + g_object_unref(pixbuf); - img = gtk_image_new_from_pixbuf(pixbuf);
+ img = gtk_image_new_from_pixbuf(pixbuf); + g_object_unref(pixbuf); purple_debug_info("pidgin", "failed to parse dialog icon\n");
- gdk_pixbuf_loader_close(loader, NULL);
- g_object_unref(loader);
@@ -1016,22 +1011,17 @@
- GdkPixbufLoader *loader;
- loader = gdk_pixbuf_loader_new();
- gdk_pixbuf_loader_write(loader,
- (const guchar *)purple_request_field_image_get_buffer(field),
- purple_request_field_image_get_size(field),
- gdk_pixbuf_loader_close(loader, NULL);
- buf = gdk_pixbuf_loader_get_pixbuf(loader);
+ buf = pidgin_pixbuf_from_data( + (const guchar *)purple_request_field_image_get_buffer(field), + purple_request_field_image_get_size(field)); scale = gdk_pixbuf_scale_simple(buf,
purple_request_field_image_get_scale_x(field) * gdk_pixbuf_get_width(buf),
purple_request_field_image_get_scale_y(field) * gdk_pixbuf_get_height(buf),
widget = gtk_image_new_from_pixbuf(scale);
- g_object_unref(G_OBJECT(loader));
+ g_object_unref(G_OBJECT(buf)); g_object_unref(G_OBJECT(scale));
@@ -1132,7 +1122,7 @@
GdkPixbuf* pixbuf = NULL;
- pixbuf = gdk_pixbuf_new_from_file(icon_path, NULL);
+ pixbuf = pidgin_pixbuf_new_from_file(icon_path); gtk_list_store_set(store, &iter,
0, purple_request_field_list_get_data(field, text),
--- a/pidgin/gtksmiley.c Wed Jun 22 02:35:45 2011 +0000
+++ b/pidgin/gtksmiley.c Sat Jun 25 19:54:02 2011 +0000
@@ -332,7 +332,7 @@
s->filename = g_strdup(filename);
- pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, 64, 64, FALSE, NULL);
+ pixbuf = pidgin_pixbuf_new_from_file_at_scale(filename, 64, 64, FALSE); gtk_image_set_from_pixbuf(GTK_IMAGE(s->smiley_image), pixbuf);
g_object_unref(G_OBJECT(pixbuf));
@@ -690,7 +690,6 @@
@@ -709,13 +708,11 @@
- image = gdk_pixbuf_new_from_file(path, &err);
+ image = pidgin_pixbuf_new_from_file(path);
ps = pidgin_smiley_edit(dialog->window, NULL);
pidgin_smiley_editor_set_image(ps, image);
--- a/pidgin/gtkstatusbox.c Wed Jun 22 02:35:45 2011 +0000
+++ b/pidgin/gtkstatusbox.c Sat Jun 25 19:54:02 2011 +0000
@@ -2225,22 +2225,45 @@
if (status_box->buddy_icon_img != NULL)
- GdkPixbuf *buf, *scale;
- int scale_width, scale_height;
- GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
+ GdkPixbufLoader *loader; + loader = gdk_pixbuf_loader_new(); g_signal_connect(G_OBJECT(loader), "size-prepared", G_CALLBACK(pixbuf_size_prepared_cb), NULL);
- gdk_pixbuf_loader_write(loader, purple_imgstore_get_data(status_box->buddy_icon_img),
- purple_imgstore_get_size(status_box->buddy_icon_img), NULL);
- gdk_pixbuf_loader_close(loader, NULL);
- buf = gdk_pixbuf_loader_get_pixbuf(loader);
- scale_width = gdk_pixbuf_get_width(buf);
- scale_height = gdk_pixbuf_get_height(buf);
- scale = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, scale_width, scale_height);
- gdk_pixbuf_fill(scale, 0x00000000);
- gdk_pixbuf_copy_area(buf, 0, 0, scale_width, scale_height, scale, 0, 0);
- if (pidgin_gdk_pixbuf_is_opaque(scale))
- pidgin_gdk_pixbuf_make_round(scale);
- status_box->buddy_icon = scale;
+ if (!gdk_pixbuf_loader_write(loader, + purple_imgstore_get_data(status_box->buddy_icon_img), + purple_imgstore_get_size(status_box->buddy_icon_img), + purple_debug_warning("gtkstatusbox", "gdk_pixbuf_loader_write() " + "failed with size=%zu: %s\n", + purple_imgstore_get_size(status_box->buddy_icon_img), + error ? error->message : "(no error message)"); + } else if (!gdk_pixbuf_loader_close(loader, &error) || error) { + purple_debug_warning("gtkstatusbox", "gdk_pixbuf_loader_close() " + "failed for image of size %zu: %s\n", + purple_imgstore_get_size(status_box->buddy_icon_img), + error ? error->message : "(no error message)"); + GdkPixbuf *buf, *scale; + int scale_width, scale_height; + buf = gdk_pixbuf_loader_get_pixbuf(loader); + scale_width = gdk_pixbuf_get_width(buf); + scale_height = gdk_pixbuf_get_height(buf); + scale = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, scale_width, scale_height); + gdk_pixbuf_fill(scale, 0x00000000); + gdk_pixbuf_copy_area(buf, 0, 0, scale_width, scale_height, scale, 0, 0); + if (pidgin_gdk_pixbuf_is_opaque(scale)) + pidgin_gdk_pixbuf_make_round(scale); + status_box->buddy_icon = scale; --- a/pidgin/gtkutils.c Wed Jun 22 02:35:45 2011 +0000
+++ b/pidgin/gtkutils.c Sat Jun 25 19:54:02 2011 +0000
@@ -615,7 +615,7 @@
- pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
+ pixbuf = pidgin_pixbuf_new_from_file(filename); @@ -704,7 +704,7 @@
"16", "google-talk.png", NULL);
- pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
+ pixbuf = pidgin_pixbuf_new_from_file(filename); gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
@@ -723,7 +723,7 @@
"16", "facebook.png", NULL);
- pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
+ pixbuf = pidgin_pixbuf_new_from_file(filename); gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
@@ -1593,7 +1593,7 @@
/* Are we dealing with an image? */
- pb = gdk_pixbuf_new_from_file(filename, NULL);
+ pb = pidgin_pixbuf_new_from_file(filename); _DndData *data = g_malloc(sizeof(_DndData));
gboolean ft = FALSE, im = FALSE;
@@ -2265,7 +2265,7 @@
filename = gtk_file_chooser_get_preview_filename(
GTK_FILE_CHOOSER(dialog->icon_filesel));
- if (!filename || g_stat(filename, &st) || !(pixbuf = gdk_pixbuf_new_from_file(filename, NULL)))
+ if (!filename || g_stat(filename, &st) || !(pixbuf = pidgin_pixbuf_new_from_file(filename))) gtk_image_set_from_pixbuf(GTK_IMAGE(dialog->icon_preview), NULL);
gtk_label_set_markup(GTK_LABEL(dialog->icon_text), "");
@@ -3086,17 +3086,134 @@
-GdkPixbuf * pidgin_pixbuf_from_imgstore(PurpleStoredImage *image)
+static GObject *pidgin_pixbuf_from_data_helper(const guchar *buf, gsize count, gboolean animated) + GdkPixbufLoader *loader; + loader = gdk_pixbuf_loader_new(); + if (!gdk_pixbuf_loader_write(loader, buf, count, &error) || error) { + purple_debug_warning("gtkutils", "gdk_pixbuf_loader_write() " + "failed with size=%zu: %s\n", count, + error ? error->message : "(no error message)"); + g_object_unref(G_OBJECT(loader)); + if (!gdk_pixbuf_loader_close(loader, &error) || error) { + purple_debug_warning("gtkutils", "gdk_pixbuf_loader_close() " + "failed for image of size %zu: %s\n", count, + error ? error->message : "(no error message)"); + g_object_unref(G_OBJECT(loader)); + pixbuf = G_OBJECT(gdk_pixbuf_loader_get_animation(loader)); + pixbuf = G_OBJECT(gdk_pixbuf_loader_get_pixbuf(loader)); + purple_debug_warning("gtkutils", "%s() returned NULL for image " + animated ? "gdk_pixbuf_loader_get_animation" + : "gdk_pixbuf_loader_get_pixbuf", count); + g_object_unref(G_OBJECT(loader)); + g_object_unref(G_OBJECT(loader)); +GdkPixbuf *pidgin_pixbuf_from_data(const guchar *buf, gsize count) + return GDK_PIXBUF(pidgin_pixbuf_from_data_helper(buf, count, FALSE)); +GdkPixbufAnimation *pidgin_pixbuf_anim_from_data(const guchar *buf, gsize count) + return GDK_PIXBUF_ANIMATION(pidgin_pixbuf_from_data_helper(buf, count, TRUE)); +GdkPixbuf *pidgin_pixbuf_from_imgstore(PurpleStoredImage *image) + return pidgin_pixbuf_from_data(purple_imgstore_get_data(image), + purple_imgstore_get_size(image)); +GdkPixbuf *pidgin_pixbuf_new_from_file(const gchar *filename) - GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
- gdk_pixbuf_loader_write(loader, purple_imgstore_get_data(image),
- purple_imgstore_get_size(image), NULL);
- gdk_pixbuf_loader_close(loader, NULL);
- pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
- g_object_unref(loader);
+ pixbuf = gdk_pixbuf_new_from_file(filename, &error); + if (!pixbuf || error) { + purple_debug_warning("gtkutils", "gdk_pixbuf_new_from_file() " + "returned %s for file %s: %s\n", + pixbuf ? "something" : "nothing", + error ? error->message : "(no error message)"); + g_object_unref(G_OBJECT(pixbuf)); +GdkPixbuf *pidgin_pixbuf_new_from_file_at_size(const char *filename, int width, int height) + pixbuf = gdk_pixbuf_new_from_file_at_size(filename, + width, height, &error); + if (!pixbuf || error) { + purple_debug_warning("gtkutils", "gdk_pixbuf_new_from_file_at_size() " + "returned %s for file %s: %s\n", + pixbuf ? "something" : "nothing", + error ? error->message : "(no error message)"); + g_object_unref(G_OBJECT(pixbuf)); +GdkPixbuf *pidgin_pixbuf_new_from_file_at_scale(const char *filename, int width, int height, gboolean preserve_aspect_ratio) + pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, + width, height, preserve_aspect_ratio, &error); + if (!pixbuf || error) { + purple_debug_warning("gtkutils", "gdk_pixbuf_new_from_file_at_scale() " + "returned %s for file %s: %s\n", + pixbuf ? "something" : "nothing", + error ? error->message : "(no error message)"); + g_object_unref(G_OBJECT(pixbuf)); --- a/pidgin/gtkutils.h Wed Jun 22 02:35:45 2011 +0000
+++ b/pidgin/gtkutils.h Sat Jun 25 19:54:02 2011 +0000
@@ -834,6 +834,32 @@
GtkWidget *pidgin_add_widget_to_vbox(GtkBox *vbox, const char *widget_label, GtkSizeGroup *sg, GtkWidget *widget, gboolean expand, GtkWidget **p_label);
+ * Create a GdkPixbuf from a chunk of image data. + * @param buf The raw binary image data. + * @param count The length of buf in bytes. + * @return A GdkPixbuf created from the image data, or NULL if + * there was an error parsing the data. +GdkPixbuf *pidgin_pixbuf_from_data(const guchar *buf, gsize count); + * Create a GdkPixbufAnimation from a chunk of image data. + * @param buf The raw binary image data. + * @param count The length of buf in bytes. + * @return A GdkPixbufAnimation created from the image data, or NULL if + * there was an error parsing the data. +GdkPixbufAnimation *pidgin_pixbuf_anim_from_data(const guchar *buf, gsize count); * Create a GdkPixbuf from a PurpleStoredImage.
* @param image A PurpleStoredImage.
@@ -845,6 +871,86 @@
GdkPixbuf *pidgin_pixbuf_from_imgstore(PurpleStoredImage *image);
+ * Helper function that calls gdk_pixbuf_new_from_file() and checks both + * the return code and the GError and returns NULL if either one failed. + * The gdk-pixbuf documentation implies that it is sufficient to check + * the return value of gdk_pixbuf_new_from_file() to determine + * whether the image was able to be loaded. However, this is not the case + * with gdk-pixbuf 2.23.3 and probably many earlier versions. In some + * cases a GdkPixbuf object is returned that will cause some operations + * (like gdk_pixbuf_scale_simple()) to rapidly consume memory in an + * This function shouldn't be necessary once Pidgin requires a version of + * gdk-pixbuf where the aforementioned bug is fixed. However, it might be + * nice to keep this function around for the debug message that it logs. + * @param filename Name of file to load, in the GLib file name encoding + * @return The GdkPixbuf if successful. Otherwise NULL is returned and +GdkPixbuf *pidgin_pixbuf_new_from_file(const char *filename); + * Helper function that calls gdk_pixbuf_new_from_file_at_size() and checks + * both the return code and the GError and returns NULL if either one failed. + * The gdk-pixbuf documentation implies that it is sufficient to check + * the return value of gdk_pixbuf_new_from_file_at_size() to determine + * whether the image was able to be loaded. However, this is not the case + * with gdk-pixbuf 2.23.3 and probably many earlier versions. In some + * cases a GdkPixbuf object is returned that will cause some operations + * (like gdk_pixbuf_scale_simple()) to rapidly consume memory in an + * This function shouldn't be necessary once Pidgin requires a version of + * gdk-pixbuf where the aforementioned bug is fixed. However, it might be + * nice to keep this function around for the debug message that it logs. + * @param filename Name of file to load, in the GLib file name encoding + * @param width The width the image should have or -1 to not constrain the width + * @param height The height the image should have or -1 to not constrain the height + * @return The GdkPixbuf if successful. Otherwise NULL is returned and +GdkPixbuf *pidgin_pixbuf_new_from_file_at_size(const char *filename, int width, int height); + * Helper function that calls gdk_pixbuf_new_from_file_at_scale() and checks + * both the return code and the GError and returns NULL if either one failed. + * The gdk-pixbuf documentation implies that it is sufficient to check + * the return value of gdk_pixbuf_new_from_file_at_scale() to determine + * whether the image was able to be loaded. However, this is not the case + * with gdk-pixbuf 2.23.3 and probably many earlier versions. In some + * cases a GdkPixbuf object is returned that will cause some operations + * (like gdk_pixbuf_scale_simple()) to rapidly consume memory in an + * This function shouldn't be necessary once Pidgin requires a version of + * gdk-pixbuf where the aforementioned bug is fixed. However, it might be + * nice to keep this function around for the debug message that it logs. + * @param filename Name of file to load, in the GLib file name encoding + * @param width The width the image should have or -1 to not constrain the width + * @param height The height the image should have or -1 to not constrain the height + * @param preserve_aspect_ratio TRUE to preserve the image's aspect ratio + * @return The GdkPixbuf if successful. Otherwise NULL is returned and +GdkPixbuf *pidgin_pixbuf_new_from_file_at_scale(const char *filename, int width, int height, gboolean preserve_aspect_ratio); * Add scrollbars to a widget
* @param widget The child widget
* @hscrollbar_policy Horizontal scrolling policy
--- a/po/ChangeLog Wed Jun 22 02:35:45 2011 +0000
+++ b/po/ChangeLog Sat Jun 25 19:54:02 2011 +0000
@@ -1,5 +1,11 @@
Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
+ * German translation updated (Björn Voigt, Jochen Kemnade) * Albanian translation updated (Besnik Bleta)
* Bengali translation updated (Jamil Ahmed)
--- a/po/de.po Wed Jun 22 02:35:45 2011 +0000
+++ b/po/de.po Sat Jun 25 19:54:02 2011 +0000
@@ -11,8 +11,8 @@
"Project-Id-Version: de\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2011-05-12 09:37+0200\n"
-"PO-Revision-Date: 2011-05-12 09:37+0200\n"
+"POT-Creation-Date: 2011-06-21 09:12+0200\n" +"PO-Revision-Date: 2011-06-21 09:11+0200\n" "Last-Translator: Björn Voigt <bjoern@cs.tu-berlin.de>\n"
"Language-Team: German <de@li.org>\n"
@@ -6361,13 +6361,16 @@
-msgid "You have %i suggested friends."
-msgstr "Sie haben %i vorgeschlagene(n) Freund(e)."
-msgid "We found %i contacts that match your search."
-"Wir fanden %i Kontakt(e), die Ihrer Suchanfrage entspricht/entsprechen."
+msgid "You have %i suggested friend." +msgid_plural "You have %i suggested friends." +msgstr[0] "Sie haben %i vorgeschlagenen Freund." +msgstr[1] "Sie haben %i vorgeschlagene Freunde." +msgid "We found %i contact that matches your search." +msgid_plural "We found %i contacts that match your search." +msgstr[0] "Wir fanden %i Kontakt, der Ihrer Suchanfrage entspricht." +msgstr[1] "Wir fanden %i Kontakte, die Ihrer Suchanfrage entsprechen." #. we must have lost the connection, so terminate it so that we can reconnect
msgid "We have lost the connection to MXit. Please reconnect."
@@ -13182,6 +13185,9 @@