Mercurial > pidgin.yaz
comparison pidgin/gtkconv.c @ 32156:1693114a2655
applied changes from 6cf1aee8ac5e3c836af832eaf26ccedd611dc70b
through e802003adbf0be4496de3de8ac03b47c1e471d00
Original commit message:
Start looking at the GError parameter every time we call these functions:
- gdk_pixbuf_loader_write
- gdk_pixbuf_loader_close
- gdk_pixbuf_new_from_file
- gdk_pixbuf_new_from_file_at_size
- gdk_pixbuf_new_from_file_at_scale
There are times when gdkpixbuf returns a semi-invalid GdkPixbuf object and
also sets the GError. If this happens we want to discard and ignore the
GdkPixbuf object because it can cause problems. For example, calling
gdk_pixbuf_scale_simple() causes gdkpixbuf to rapidly consume memory in
an infinite loop. And that's bad.
This commit adds some helper functions to gtkutils.[c|h] that make it a
little easier to check the GError value. We should use them everywhere
we call any of the above functions.
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Wed, 22 Jun 2011 07:09:42 +0000 |
parents | 5ffd5582f5fe |
children | 47c604efed32 |
comparison
equal
deleted
inserted
replaced
32155:5ffd5582f5fe | 32156:1693114a2655 |
---|---|
6406 pidgin_conv_custom_smiley_write(PurpleConversation *conv, const char *smile, | 6406 pidgin_conv_custom_smiley_write(PurpleConversation *conv, const char *smile, |
6407 const guchar *data, gsize size) | 6407 const guchar *data, gsize size) |
6408 { | 6408 { |
6409 PidginConversation *gtkconv; | 6409 PidginConversation *gtkconv; |
6410 GtkIMHtmlSmiley *smiley; | 6410 GtkIMHtmlSmiley *smiley; |
6411 GdkPixbufLoader *loader; | |
6412 const char *sml; | 6411 const char *sml; |
6412 GError *error = NULL; | |
6413 | 6413 |
6414 sml = purple_account_get_protocol_name(conv->account); | 6414 sml = purple_account_get_protocol_name(conv->account); |
6415 gtkconv = PIDGIN_CONVERSATION(conv); | 6415 gtkconv = PIDGIN_CONVERSATION(conv); |
6416 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile); | 6416 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile); |
6417 | 6417 |
6420 | 6420 |
6421 smiley->data = g_realloc(smiley->data, smiley->datasize + size); | 6421 smiley->data = g_realloc(smiley->data, smiley->datasize + size); |
6422 g_memmove((guchar *)smiley->data + smiley->datasize, data, size); | 6422 g_memmove((guchar *)smiley->data + smiley->datasize, data, size); |
6423 smiley->datasize += size; | 6423 smiley->datasize += size; |
6424 | 6424 |
6425 loader = smiley->loader; | 6425 if (!smiley->loader) |
6426 if (!loader) | |
6427 return; | 6426 return; |
6428 | 6427 |
6429 gdk_pixbuf_loader_write(loader, data, size, NULL); | 6428 if (!gdk_pixbuf_loader_write(smiley->loader, data, size, &error) || error) { |
6429 purple_debug_warning("gtkconv", "gdk_pixbuf_loader_write() " | |
6430 "failed with size=%zu: %s\n", size, | |
6431 error ? error->message : "(no error message)"); | |
6432 if (error) | |
6433 g_error_free(error); | |
6434 /* We must stop using the GdkPixbufLoader because trying to load | |
6435 certain invalid GIFs with at least gdk-pixbuf 2.23.3 can return | |
6436 a GdkPixbuf that will cause some operations (like | |
6437 gdk_pixbuf_scale_simple()) to consume memory in an infinite loop. | |
6438 But we also don't want to set smiley->loader to NULL because our | |
6439 code might expect it to be set. So create a new loader. */ | |
6440 g_object_unref(G_OBJECT(smiley->loader)); | |
6441 smiley->loader = gdk_pixbuf_loader_new(); | |
6442 } | |
6430 } | 6443 } |
6431 | 6444 |
6432 static void | 6445 static void |
6433 pidgin_conv_custom_smiley_close(PurpleConversation *conv, const char *smile) | 6446 pidgin_conv_custom_smiley_close(PurpleConversation *conv, const char *smile) |
6434 { | 6447 { |
6435 PidginConversation *gtkconv; | 6448 PidginConversation *gtkconv; |
6436 GtkIMHtmlSmiley *smiley; | 6449 GtkIMHtmlSmiley *smiley; |
6437 GdkPixbufLoader *loader; | |
6438 const char *sml; | 6450 const char *sml; |
6451 GError *error = NULL; | |
6439 | 6452 |
6440 g_return_if_fail(conv != NULL); | 6453 g_return_if_fail(conv != NULL); |
6441 g_return_if_fail(smile != NULL); | 6454 g_return_if_fail(smile != NULL); |
6442 | 6455 |
6443 sml = purple_account_get_protocol_name(conv->account); | 6456 sml = purple_account_get_protocol_name(conv->account); |
6445 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile); | 6458 smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile); |
6446 | 6459 |
6447 if (!smiley) | 6460 if (!smiley) |
6448 return; | 6461 return; |
6449 | 6462 |
6450 loader = smiley->loader; | 6463 if (!smiley->loader) |
6451 | |
6452 if (!loader) | |
6453 return; | 6464 return; |
6454 | 6465 |
6455 | |
6456 | |
6457 purple_debug_info("gtkconv", "About to close the smiley pixbuf\n"); | 6466 purple_debug_info("gtkconv", "About to close the smiley pixbuf\n"); |
6458 | 6467 |
6459 gdk_pixbuf_loader_close(loader, NULL); | 6468 if (!gdk_pixbuf_loader_close(smiley->loader, &error) || error) { |
6460 | 6469 purple_debug_warning("gtkconv", "gdk_pixbuf_loader_close() " |
6470 "failed: %s\n", | |
6471 error ? error->message : "(no error message)"); | |
6472 if (error) | |
6473 g_error_free(error); | |
6474 /* We must stop using the GdkPixbufLoader because if we tried to | |
6475 load certain invalid GIFs with all current versions of GDK (as | |
6476 of 2011-06-15) then it's possible the loader will contain data | |
6477 that could cause some operations (like gdk_pixbuf_scale_simple()) | |
6478 to consume memory in an infinite loop. But we also don't want | |
6479 to set smiley->loader to NULL because our code might expect it | |
6480 to be set. So create a new loader. */ | |
6481 g_object_unref(G_OBJECT(smiley->loader)); | |
6482 smiley->loader = gdk_pixbuf_loader_new(); | |
6483 } | |
6461 } | 6484 } |
6462 | 6485 |
6463 static void | 6486 static void |
6464 pidgin_conv_send_confirm(PurpleConversation *conv, const char *message) | 6487 pidgin_conv_send_confirm(PurpleConversation *conv, const char *message) |
6465 { | 6488 { |
6955 PidginConversation *gtkconv; | 6978 PidginConversation *gtkconv; |
6956 PidginWindow *win; | 6979 PidginWindow *win; |
6957 | 6980 |
6958 PurpleBuddy *buddy; | 6981 PurpleBuddy *buddy; |
6959 | 6982 |
6960 GdkPixbufLoader *loader; | |
6961 GdkPixbufAnimation *anim; | |
6962 GError *err = NULL; | |
6963 | |
6964 PurpleStoredImage *custom_img = NULL; | 6983 PurpleStoredImage *custom_img = NULL; |
6965 gconstpointer data = NULL; | 6984 gconstpointer data = NULL; |
6966 size_t len; | 6985 size_t len; |
6967 | 6986 |
6968 GdkPixbuf *buf; | 6987 GdkPixbuf *buf; |
7036 } | 7055 } |
7037 } | 7056 } |
7038 | 7057 |
7039 if (data == NULL) { | 7058 if (data == NULL) { |
7040 icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv)); | 7059 icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv)); |
7041 | |
7042 if (icon == NULL) | 7060 if (icon == NULL) |
7043 { | 7061 { |
7044 gtk_widget_set_size_request(gtkconv->u.im->icon_container, | 7062 gtk_widget_set_size_request(gtkconv->u.im->icon_container, |
7045 -1, BUDDYICON_SIZE_MIN); | 7063 -1, BUDDYICON_SIZE_MIN); |
7046 return; | 7064 return; |
7047 } | 7065 } |
7048 | 7066 |
7049 data = purple_buddy_icon_get_data(icon, &len); | 7067 data = purple_buddy_icon_get_data(icon, &len); |
7050 | |
7051 if (data == NULL) | 7068 if (data == NULL) |
7052 { | 7069 { |
7053 gtk_widget_set_size_request(gtkconv->u.im->icon_container, | 7070 gtk_widget_set_size_request(gtkconv->u.im->icon_container, |
7054 -1, BUDDYICON_SIZE_MIN); | 7071 -1, BUDDYICON_SIZE_MIN); |
7055 return; | 7072 return; |
7056 } | 7073 } |
7057 } | 7074 } |
7058 | 7075 |
7059 loader = gdk_pixbuf_loader_new(); | 7076 gtkconv->u.im->anim = pidgin_pixbuf_anim_from_data(data, len); |
7060 gdk_pixbuf_loader_write(loader, data, len, NULL); | |
7061 gdk_pixbuf_loader_close(loader, &err); | |
7062 | |
7063 purple_imgstore_unref(custom_img); | 7077 purple_imgstore_unref(custom_img); |
7064 | 7078 |
7065 anim = gdk_pixbuf_loader_get_animation(loader); | 7079 if (!gtkconv->u.im->anim) { |
7066 if (anim) | 7080 purple_debug_error("gtkconv", "Couldn't load icon for conv %s\n", |
7067 g_object_ref(G_OBJECT(anim)); | 7081 purple_conversation_get_name(conv)); |
7068 g_object_unref(loader); | |
7069 | |
7070 if (!anim) | |
7071 return; | 7082 return; |
7072 gtkconv->u.im->anim = anim; | |
7073 | |
7074 if (err) { | |
7075 purple_debug(PURPLE_DEBUG_ERROR, "gtkconv", | |
7076 "Buddy icon error: %s\n", err->message); | |
7077 g_error_free(err); | |
7078 } | 7083 } |
7079 | 7084 |
7080 if (gdk_pixbuf_animation_is_static_image(gtkconv->u.im->anim)) { | 7085 if (gdk_pixbuf_animation_is_static_image(gtkconv->u.im->anim)) { |
7081 GdkPixbuf *stat; | 7086 GdkPixbuf *stat; |
7082 gtkconv->u.im->iter = NULL; | 7087 gtkconv->u.im->iter = NULL; |