summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libpurple/buddyicon.c186
-rw-r--r--libpurple/buddyicon.h30
-rw-r--r--libpurple/image.c75
-rw-r--r--libpurple/image.h8
-rw-r--r--libpurple/imgstore.c7
-rw-r--r--valgrind-suppressions8
6 files changed, 200 insertions, 114 deletions
diff --git a/libpurple/buddyicon.c b/libpurple/buddyicon.c
index bd6bbc3d60..c05da1b6ba 100644
--- a/libpurple/buddyicon.c
+++ b/libpurple/buddyicon.c
@@ -25,7 +25,7 @@
#include "conversation.h"
#include "dbus-maybe.h"
#include "debug.h"
-#include "imgstore.h"
+#include "image.h"
#include "util.h"
/* NOTE: Instances of this struct are allocated without zeroing the memory, so
@@ -33,7 +33,7 @@
struct _PurpleBuddyIcon
{
PurpleAccount *account; /* The account the user is on. */
- PurpleStoredImage *img; /* The stored image containing
+ PurpleImage *img; /* The image containing
the icon data. */
char *username; /* The username the icon belongs to. */
char *checksum; /* The protocol checksum. */
@@ -53,7 +53,7 @@ struct _PurpleBuddyIcon
static GHashTable *account_cache = NULL;
/*
- * This hash table contains a bunch of PurpleStoredImages that are
+ * This hash table contains a bunch of PurpleImages that are
* shared across all accounts.
*
* Key is the filename for this image as constructed by
@@ -61,11 +61,10 @@ static GHashTable *account_cache = NULL;
* sha-1 hash plus an appropriate file extension. For example:
* "0f4972d17d1e70e751c43c90c948e72efbff9796.gif"
*
- * The value is a PurpleStoredImage containing the icon data. These
- * images are reference counted, and when the count reaches 0
- * imgstore.c emits the image-deleting signal and we remove the image
- * from the hash table (but it might still be saved on disk, if the
- * icon is being used by offline accounts or some such).
+ * The value is a PurpleImage containing the icon data. These images are
+ * reference counted, and when the count reaches 0 we remove the image from
+ * the hash table (but it might still be saved on disk, if the icon is being
+ * used by offline accounts or some such).
*/
static GHashTable *icon_data_cache = NULL;
@@ -77,7 +76,7 @@ static GHashTable *icon_data_cache = NULL;
* time Pidgin starts.
*
* Key is the filename for this image as constructed by
- * purple_util_get_image_filename(). So it is the base16 encoded
+ * purple_image_generate_filename(). So it is the base16 encoded
* sha-1 hash plus an appropriate file extension. For example:
* "0f4972d17d1e70e751c43c90c948e72efbff9796.gif"
*
@@ -140,34 +139,43 @@ unref_filename(const char *filename)
}
}
+static const gchar *
+image_get_filename(PurpleImage *img)
+{
+ return g_object_get_data(G_OBJECT(img), "purple-buddyicon-filename");
+}
+
static void
-purple_buddy_icon_data_cache(PurpleStoredImage *img)
+purple_buddy_icon_data_cache(PurpleImage *img)
{
- const char *dirname;
- char *path;
+ const gchar *dirname, *filename;
+ gchar *path;
- g_return_if_fail(img != NULL);
+ g_return_if_fail(PURPLE_IS_IMAGE(img));
if (!purple_buddy_icons_is_caching())
return;
dirname = purple_buddy_icons_get_cache_dir();
- path = g_build_filename(dirname, purple_imgstore_get_filename(img), NULL);
+ filename = image_get_filename(img);
+ g_return_if_fail(filename != NULL);
+ path = g_build_filename(dirname, filename, NULL);
if (!g_file_test(dirname, G_FILE_TEST_IS_DIR))
{
- purple_debug_info("buddyicon", "Creating icon cache directory.\n");
+ purple_debug_info("buddyicon", "creating icon cache directory");
if (g_mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0)
{
purple_debug_error("buddyicon",
- "Unable to create directory %s: %s\n",
- dirname, g_strerror(errno));
+ "unable to create directory %s: %s",
+ dirname, g_strerror(errno));
+ return;
}
}
- purple_util_write_data_to_file_absolute(path, purple_imgstore_get_data(img),
- purple_imgstore_get_size(img));
+ if (!purple_image_save(img, path))
+ purple_debug_error("buddyicon", "failed to save icon %s", path);
g_free(path);
}
@@ -218,51 +226,50 @@ value_equals(gpointer key, gpointer value, gpointer user_data)
}
static void
-image_deleting_cb(const PurpleStoredImage *img, gpointer data)
+image_deleting_cb(gpointer _filename)
{
- const char *filename = purple_imgstore_get_filename(img);
+ PurpleImage *img;
+ gchar *filename = _filename;
- /* If there's no filename, it can't be one of our images. */
- if (filename == NULL)
- return;
+ img = g_hash_table_lookup(icon_data_cache, filename);
+ purple_buddy_icon_data_uncache_file(filename);
+ g_hash_table_remove(icon_data_cache, filename);
- if (img == g_hash_table_lookup(icon_data_cache, filename))
- {
- purple_buddy_icon_data_uncache_file(filename);
- g_hash_table_remove(icon_data_cache, filename);
+ /* We could make this O(1) by using another hash table, but
+ * this is probably good enough. */
+ g_hash_table_foreach_remove(pointer_icon_cache, value_equals, (gpointer)img);
- /* We could make this O(1) by using another hash table, but
- * this is probably good enough. */
- g_hash_table_foreach_remove(pointer_icon_cache, value_equals, (gpointer)img);
- }
+ g_free(filename);
}
-static PurpleStoredImage *
+static PurpleImage *
purple_buddy_icon_data_new(guchar *icon_data, size_t icon_len)
{
- char *file;
- PurpleStoredImage *img;
+ PurpleImage *newimg, *oldimg;
+ const gchar *filename;
g_return_val_if_fail(icon_data != NULL, NULL);
g_return_val_if_fail(icon_len > 0, NULL);
- file = purple_util_get_image_filename(icon_data, icon_len);
+ newimg = purple_image_new_from_data(icon_data, icon_len);
+ filename = purple_image_generate_filename(newimg);
- img = g_hash_table_lookup(icon_data_cache, file);
- if (img) {
- g_free(file);
- g_free(icon_data);
- return purple_imgstore_ref(img);
+ oldimg = g_hash_table_lookup(icon_data_cache, filename);
+ if (oldimg) {
+ g_warn_if_fail(PURPLE_IS_IMAGE(oldimg));
+ g_object_unref(newimg);
+ g_object_ref(oldimg);
+ return oldimg;
}
- img = purple_imgstore_new(icon_data, icon_len, file);
-
/* This will take ownership of file and free it as needed */
- g_hash_table_insert(icon_data_cache, file, img);
+ g_hash_table_insert(icon_data_cache, g_strdup(filename), newimg);
+ g_object_set_data_full(G_OBJECT(newimg), "purple-buddyicon-filename",
+ g_strdup(filename), image_deleting_cb);
- purple_buddy_icon_data_cache(img);
+ purple_buddy_icon_data_cache(newimg);
- return img;
+ return newimg;
}
/*
@@ -356,7 +363,7 @@ purple_buddy_icon_unref(PurpleBuddyIcon *icon)
g_free(icon->username);
g_free(icon->checksum);
- purple_imgstore_unref(icon->img);
+ g_object_unref(icon->img);
PURPLE_DBUS_UNREGISTER_POINTER(icon);
g_slice_free(PurpleBuddyIcon, icon);
@@ -398,7 +405,8 @@ purple_buddy_icon_update(PurpleBuddyIcon *icon)
"buddy_icon"));
if (icon->img && purple_buddy_icons_is_caching())
{
- const char *filename = purple_imgstore_get_filename(icon->img);
+ const char *filename = image_get_filename(icon->img);
+ g_warn_if_fail(filename != NULL);
purple_blist_node_set_string((PurpleBlistNode *)buddy,
"buddy_icon",
filename);
@@ -440,7 +448,7 @@ void
purple_buddy_icon_set_data(PurpleBuddyIcon *icon, guchar *data,
size_t len, const char *checksum)
{
- PurpleStoredImage *old_img;
+ PurpleImage *old_img;
g_return_if_fail(icon != NULL);
@@ -460,7 +468,8 @@ purple_buddy_icon_set_data(PurpleBuddyIcon *icon, guchar *data,
purple_buddy_icon_update(icon);
- purple_imgstore_unref(old_img);
+ if (old_img)
+ g_object_unref(old_img);
}
PurpleAccount *
@@ -495,9 +504,9 @@ purple_buddy_icon_get_data(const PurpleBuddyIcon *icon, size_t *len)
if (icon->img)
{
if (len != NULL)
- *len = purple_imgstore_get_size(icon->img);
+ *len = purple_image_get_size(icon->img);
- return purple_imgstore_get_data(icon->img);
+ return purple_image_get_data(icon->img);
}
return NULL;
@@ -507,7 +516,7 @@ const char *
purple_buddy_icon_get_extension(const PurpleBuddyIcon *icon)
{
if (icon->img != NULL)
- return purple_imgstore_get_extension(icon->img);
+ return purple_image_get_extension(icon->img);
return NULL;
}
@@ -563,20 +572,19 @@ purple_buddy_icons_set_for_user(PurpleAccount *account, const char *username,
}
}
-char *purple_buddy_icon_get_full_path(PurpleBuddyIcon *icon)
+const gchar *
+purple_buddy_icon_get_full_path(PurpleBuddyIcon *icon)
{
- char *path;
+ const gchar *path;
g_return_val_if_fail(icon != NULL, NULL);
if (icon->img == NULL)
return NULL;
- path = g_build_filename(purple_buddy_icons_get_cache_dir(),
- purple_imgstore_get_filename(icon->img), NULL);
+ path = purple_image_get_path(icon->img);
if (!g_file_test(path, G_FILE_TEST_EXISTS))
{
- g_free(path);
return NULL;
}
return path;
@@ -667,10 +675,10 @@ purple_buddy_icons_find(PurpleAccount *account, const char *username)
return (icon ? purple_buddy_icon_ref(icon) : NULL);
}
-PurpleStoredImage *
+PurpleImage *
purple_buddy_icons_find_account_icon(PurpleAccount *account)
{
- PurpleStoredImage *img;
+ PurpleImage *img;
const char *account_icon_file;
const char *dirname;
char *path;
@@ -679,9 +687,10 @@ purple_buddy_icons_find_account_icon(PurpleAccount *account)
g_return_val_if_fail(account != NULL, NULL);
- if ((img = g_hash_table_lookup(pointer_icon_cache, account)))
- {
- return purple_imgstore_ref(img);
+ img = g_hash_table_lookup(pointer_icon_cache, account);
+ if (img) {
+ g_object_ref(img);
+ return img;
}
account_icon_file = purple_account_get_string(account, "buddy_icon", NULL);
@@ -692,23 +701,23 @@ purple_buddy_icons_find_account_icon(PurpleAccount *account)
dirname = purple_buddy_icons_get_cache_dir();
path = g_build_filename(dirname, account_icon_file, NULL);
- if (read_icon_file(path, &data, &len))
- {
+ if (read_icon_file(path, &data, &len)) {
g_free(path);
img = purple_buddy_icons_set_account_icon(account, data, len);
- return purple_imgstore_ref(img);
+ g_object_ref(img);
+ return img;
}
g_free(path);
return NULL;
}
-PurpleStoredImage *
+PurpleImage *
purple_buddy_icons_set_account_icon(PurpleAccount *account,
guchar *icon_data, size_t icon_len)
{
- PurpleStoredImage *old_img;
- PurpleStoredImage *img = NULL;
+ PurpleImage *old_img;
+ PurpleImage *img = NULL;
char *old_icon;
if (icon_data != NULL && icon_len > 0) {
@@ -718,7 +727,8 @@ purple_buddy_icons_set_account_icon(PurpleAccount *account,
old_icon = g_strdup(purple_account_get_string(account, "buddy_icon", NULL));
if (img && purple_buddy_icons_is_caching())
{
- const char *filename = purple_imgstore_get_filename(img);
+ const char *filename = image_get_filename(img);
+ g_warn_if_fail(filename != NULL);
purple_account_set_string(account, "buddy_icon", filename);
purple_account_set_int(account, "buddy_icon_timestamp", time(NULL));
ref_filename(filename);
@@ -750,7 +760,7 @@ purple_buddy_icons_set_account_icon(PurpleAccount *account,
}
if (old_img)
- purple_imgstore_unref(old_img);
+ g_object_unref(old_img);
else if (old_icon)
{
/* The old icon may not have been loaded into memory. In that
@@ -790,20 +800,21 @@ purple_buddy_icons_node_has_custom_icon(PurpleBlistNode *node)
return (purple_blist_node_get_string(node, "custom_buddy_icon") != NULL);
}
-PurpleStoredImage *
+PurpleImage *
purple_buddy_icons_node_find_custom_icon(PurpleBlistNode *node)
{
char *path;
size_t len;
guchar *data;
- PurpleStoredImage *img;
+ PurpleImage *img;
const char *custom_icon_file, *dirname;
g_return_val_if_fail(node != NULL, NULL);
- if ((img = g_hash_table_lookup(pointer_icon_cache, node)))
- {
- return purple_imgstore_ref(img);
+ img = g_hash_table_lookup(pointer_icon_cache, node);
+ if (img) {
+ g_object_ref(img);
+ return img;
}
custom_icon_file = purple_blist_node_get_string(node,
@@ -815,24 +826,24 @@ purple_buddy_icons_node_find_custom_icon(PurpleBlistNode *node)
dirname = purple_buddy_icons_get_cache_dir();
path = g_build_filename(dirname, custom_icon_file, NULL);
- if (read_icon_file(path, &data, &len))
- {
+ if (read_icon_file(path, &data, &len)) {
g_free(path);
img = purple_buddy_icons_node_set_custom_icon(node, data, len);
- return purple_imgstore_ref(img);
+ g_object_ref(img);
+ return img;
}
g_free(path);
return NULL;
}
-PurpleStoredImage *
+PurpleImage *
purple_buddy_icons_node_set_custom_icon(PurpleBlistNode *node,
guchar *icon_data, size_t icon_len)
{
char *old_icon;
- PurpleStoredImage *old_img;
- PurpleStoredImage *img = NULL;
+ PurpleImage *old_img;
+ PurpleImage *img = NULL;
PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
g_return_val_if_fail(node != NULL, NULL);
@@ -852,7 +863,8 @@ purple_buddy_icons_node_set_custom_icon(PurpleBlistNode *node,
old_icon = g_strdup(purple_blist_node_get_string(node,
"custom_buddy_icon"));
if (img && purple_buddy_icons_is_caching()) {
- const char *filename = purple_imgstore_get_filename(img);
+ const char *filename = image_get_filename(img);
+ g_warn_if_fail(filename);
purple_blist_node_set_string(node, "custom_buddy_icon",
filename);
ref_filename(filename);
@@ -903,7 +915,7 @@ purple_buddy_icons_node_set_custom_icon(PurpleBlistNode *node,
ops->update(purple_blist_get_buddy_list(), node);
if (old_img) {
- purple_imgstore_unref(old_img);
+ g_object_unref(old_img);
} else if (old_icon) {
/* The old icon may not have been loaded into memory. In that
* case, we'll need to uncache the filename. The filenames
@@ -915,7 +927,7 @@ purple_buddy_icons_node_set_custom_icon(PurpleBlistNode *node,
return img;
}
-PurpleStoredImage *
+PurpleImage *
purple_buddy_icons_node_set_custom_icon_from_file(PurpleBlistNode *node,
const gchar *filename)
{
@@ -1078,10 +1090,6 @@ purple_buddy_icons_init()
if (!cache_dir)
cache_dir = g_build_filename(purple_user_dir(), "icons", NULL);
-
- purple_signal_connect(purple_imgstore_get_handle(), "image-deleting",
- purple_buddy_icons_get_handle(),
- G_CALLBACK(image_deleting_cb), NULL);
}
void
diff --git a/libpurple/buddyicon.h b/libpurple/buddyicon.h
index 042352430d..e46d1e8069 100644
--- a/libpurple/buddyicon.h
+++ b/libpurple/buddyicon.h
@@ -42,7 +42,6 @@ typedef struct _PurpleBuddyIcon PurpleBuddyIcon;
#include "account.h"
#include "buddylist.h"
-#include "imgstore.h"
#include "prpl.h"
#include "util.h"
@@ -188,9 +187,10 @@ const char *purple_buddy_icon_get_extension(const PurpleBuddyIcon *icon);
* directly. If you find yourself wanting to use this function, think
* very long and hard about it, and then don't.
*
- * Returns: A full path to the file, or %NULL under various conditions.
+ * Returns: (transfer none): A full path to the file, or %NULL under various conditions.
*/
-char *purple_buddy_icon_get_full_path(PurpleBuddyIcon *icon);
+const gchar *
+purple_buddy_icon_get_full_path(PurpleBuddyIcon *icon);
/**************************************************************************/
/* Buddy Icon Subsystem API */
@@ -245,8 +245,8 @@ purple_buddy_icons_find(PurpleAccount *account, const char *username);
*
* Returns the buddy icon image for an account.
*
- * The caller owns a reference to the image in the store, and must dereference
- * the image with purple_imgstore_unref() for it to be freed.
+ * The caller owns a reference to the image, and must dereference
+ * the image with g_object_unref() for it to be freed.
*
* This function deals with loading the icon from the cache, if
* needed, so it should be called in any case where you want the
@@ -254,7 +254,7 @@ purple_buddy_icons_find(PurpleAccount *account, const char *username);
*
* Returns: The account's buddy icon image.
*/
-PurpleStoredImage *
+PurpleImage *
purple_buddy_icons_find_account_icon(PurpleAccount *account);
/**
@@ -270,10 +270,10 @@ purple_buddy_icons_find_account_icon(PurpleAccount *account);
* caching the data, etc.
*
* Returns: The icon that was set. The caller does NOT own
- * a reference to this, and must call purple_imgstore_ref()
+ * a reference to this, and must call g_object_ref()
* if it wants one.
*/
-PurpleStoredImage *
+PurpleImage *
purple_buddy_icons_set_account_icon(PurpleAccount *account,
guchar *icon_data, size_t icon_len);
@@ -308,8 +308,8 @@ purple_buddy_icons_node_has_custom_icon(PurpleBlistNode *node);
*
* Returns the custom buddy icon image for a blist node.
*
- * The caller owns a reference to the image in the store, and must dereference
- * the image with purple_imgstore_unref() for it to be freed.
+ * The caller owns a reference to the image, and must dereference
+ * the image with g_object_unref() for it to be freed.
*
* This function deals with loading the icon from the cache, if
* needed, so it should be called in any case where you want the
@@ -317,7 +317,7 @@ purple_buddy_icons_node_has_custom_icon(PurpleBlistNode *node);
*
* Returns: The custom buddy icon.
*/
-PurpleStoredImage *
+PurpleImage *
purple_buddy_icons_node_find_custom_icon(PurpleBlistNode *node);
/**
@@ -333,9 +333,9 @@ purple_buddy_icons_node_find_custom_icon(PurpleBlistNode *node);
* etc.
*
* Returns: The icon that was set. The caller does NOT own a reference to this,
- * and must call purple_imgstore_ref() if it wants one.
+ * and must call g_object_ref() if it wants one.
*/
-PurpleStoredImage *
+PurpleImage *
purple_buddy_icons_node_set_custom_icon(PurpleBlistNode *node,
guchar *icon_data, size_t icon_len);
@@ -351,9 +351,9 @@ purple_buddy_icons_node_set_custom_icon(PurpleBlistNode *node,
* See purple_buddy_icons_node_set_custom_icon().
*
* Returns: The icon that was set. The caller does NOT own a reference to this,
- * and must call purple_imgstore_ref() if it wants one.
+ * and must call g_object_ref() if it wants one.
*/
-PurpleStoredImage *
+PurpleImage *
purple_buddy_icons_node_set_custom_icon_from_file(PurpleBlistNode *node,
const gchar *filename);
diff --git a/libpurple/image.c b/libpurple/image.c
index d8a903f62d..7d5da5f0ad 100644
--- a/libpurple/image.c
+++ b/libpurple/image.c
@@ -34,6 +34,7 @@ typedef struct {
const gchar *extension;
const gchar *mime;
+ gchar *gen_filename;
gboolean is_ready;
gboolean has_failed;
@@ -54,6 +55,7 @@ enum
SIG_LAST
};
+static GObjectClass *parent_class;
static guint signals[SIG_LAST];
static GParamSpec *properties[PROP_LAST];
@@ -153,18 +155,17 @@ fill_data(PurpleImage *image)
PurpleImage *
purple_image_new_from_file(const gchar *path, gboolean be_eager)
{
+ PurpleImagePrivate *priv;
PurpleImage *img;
g_return_val_if_fail(path != NULL, NULL);
g_return_val_if_fail(g_file_test(path, G_FILE_TEST_EXISTS), NULL);
- img = g_object_new(PURPLE_TYPE_IMAGE,
- "path", path,
- NULL);
+ img = g_object_new(PURPLE_TYPE_IMAGE, NULL);
+ priv = PURPLE_IMAGE_GET_PRIVATE(img);
+ priv->path = g_strdup(path);
if (be_eager) {
- PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(img);
-
fill_data(img);
if (!priv->contents) {
g_object_unref(img);
@@ -194,6 +195,31 @@ purple_image_new_from_data(gpointer data, gsize length)
return img;
}
+gboolean
+purple_image_save(PurpleImage *image, const gchar *path)
+{
+ PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image);
+ gpointer data;
+ gsize len;
+ gboolean succ;
+
+ g_return_val_if_fail(priv != NULL, FALSE);
+ g_return_val_if_fail(path != NULL, FALSE);
+ g_return_val_if_fail(path[0] != '\0', FALSE);
+
+ data = purple_image_get_data(image);
+ len = purple_image_get_size(image);
+
+ g_return_val_if_fail(data != NULL, FALSE);
+ g_return_val_if_fail(len > 0, FALSE);
+
+ succ = purple_util_write_data_to_file_absolute(path, data, len);
+ if (succ && priv->path == NULL)
+ priv->path = g_strdup(path);
+
+ return succ;
+}
+
const gchar *
purple_image_get_path(PurpleImage *image)
{
@@ -254,7 +280,7 @@ purple_image_get_data(PurpleImage *image)
}
const gchar *
-purple_image_get_extenstion(PurpleImage *image)
+purple_image_get_extension(PurpleImage *image)
{
PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image);
gpointer data;
@@ -292,7 +318,7 @@ const gchar *
purple_image_get_mimetype(PurpleImage *image)
{
PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image);
- const gchar *ext = purple_image_get_extenstion(image);
+ const gchar *ext = purple_image_get_extension(image);
g_return_val_if_fail(priv != NULL, NULL);
@@ -317,6 +343,35 @@ purple_image_get_mimetype(PurpleImage *image)
return NULL;
}
+const gchar *
+purple_image_generate_filename(PurpleImage *image)
+{
+ PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image);
+ gpointer data;
+ gsize len;
+ const gchar *ext;
+ gchar *checksum;
+
+ g_return_val_if_fail(priv != NULL, NULL);
+
+ if (priv->gen_filename)
+ return priv->gen_filename;
+
+ ext = purple_image_get_extension(image);
+ data = purple_image_get_data(image);
+ len = purple_image_get_size(image);
+
+ g_return_val_if_fail(ext != NULL, NULL);
+ g_return_val_if_fail(data != NULL, NULL);
+ g_return_val_if_fail(len > 0, NULL);
+
+ checksum = g_compute_checksum_for_data(G_CHECKSUM_SHA1, data, len);
+ priv->gen_filename = g_strdup_printf("%s.%s", checksum, ext);
+ g_free(checksum);
+
+ return priv->gen_filename;
+}
+
PurpleImage *
purple_image_transfer_new(void)
{
@@ -410,6 +465,9 @@ purple_image_finalize(GObject *obj)
if (priv->contents)
g_string_free(priv->contents, TRUE);
g_free(priv->path);
+ g_free(priv->gen_filename);
+
+ G_OBJECT_CLASS(parent_class)->finalize(obj);
}
static void
@@ -437,10 +495,11 @@ purple_image_class_init(PurpleImageClass *klass)
{
GObjectClass *gobj_class = G_OBJECT_CLASS(klass);
+ parent_class = g_type_class_peek_parent(klass);
+
g_type_class_add_private(klass, sizeof(PurpleImagePrivate));
gobj_class->finalize = purple_image_finalize;
-
gobj_class->get_property = purple_image_get_property;
properties[PROP_IS_READY] = g_param_spec_boolean("is-ready",
diff --git a/libpurple/image.h b/libpurple/image.h
index 7b138309e2..abee213575 100644
--- a/libpurple/image.h
+++ b/libpurple/image.h
@@ -86,6 +86,9 @@ purple_image_new_from_file(const gchar *path, gboolean be_eager);
PurpleImage *
purple_image_new_from_data(gpointer data, gsize length);
+gboolean
+purple_image_save(PurpleImage *image, const gchar *path);
+
const gchar *
purple_image_get_path(PurpleImage *image);
@@ -102,11 +105,14 @@ gpointer
purple_image_get_data(PurpleImage *image);
const gchar *
-purple_image_get_extenstion(PurpleImage *image);
+purple_image_get_extension(PurpleImage *image);
const gchar *
purple_image_get_mimetype(PurpleImage *image);
+const gchar *
+purple_image_generate_filename(PurpleImage *image);
+
PurpleImage *
purple_image_transfer_new(void);
diff --git a/libpurple/imgstore.c b/libpurple/imgstore.c
index 65dad80ac9..66843f943b 100644
--- a/libpurple/imgstore.c
+++ b/libpurple/imgstore.c
@@ -75,7 +75,7 @@ const char *purple_imgstore_get_filename(const PurpleStoredImage *img)
const char *purple_imgstore_get_extension(PurpleStoredImage *img)
{
- return purple_image_get_extenstion(img);
+ return purple_image_get_extension(img);
}
void purple_imgstore_ref_by_id(int id)
@@ -107,6 +107,11 @@ purple_imgstore_ref(PurpleStoredImage *img)
void
purple_imgstore_unref(PurpleStoredImage *img)
{
+ if (img == NULL) {
+ purple_debug_warning("imgstore",
+ "purple_imgstore_unref: img empty");
+ return;
+ }
g_object_unref(img);
}
diff --git a/valgrind-suppressions b/valgrind-suppressions
index 159fa59585..7eba582a4e 100644
--- a/valgrind-suppressions
+++ b/valgrind-suppressions
@@ -233,3 +233,11 @@
fun:rsvg_handle_get_pixbuf
obj:*
}
+{
+ TODO temporary: gg prpl bug, fixit
+ Memcheck:Addr4
+ fun:memcpy
+ fun:ggp_resolver_purple_cb
+ fun:purple_dnsquery_resolved
+ ...
+}