Merged pidgin/main into default
--- a/libpurple/buddyicon.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/buddyicon.c Sun May 28 13:26:27 2017 +0300
@@ -510,7 +510,7 @@
- *len = purple_image_get_size(icon->img);
+ *len = purple_image_get_data_size(icon->img); return purple_image_get_data(icon->img);
--- a/libpurple/conversation.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/conversation.c Sun May 28 13:26:27 2017 +0300
@@ -837,16 +837,14 @@
return purple_protocol_client_iface_get_max_message_size(protocol, conv);
-purple_conversation_add_remote_smiley(PurpleConversation *conv,
- PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv);
+purple_conversation_add_smiley(PurpleConversation *conv, PurpleSmiley *smiley) { + PurpleConversationPrivate *priv = NULL; - g_return_val_if_fail(priv != NULL, NULL);
- g_return_val_if_fail(shortcut != NULL, NULL);
- g_return_val_if_fail(shortcut[0] != '\0', NULL);
+ g_return_if_fail(PURPLE_IS_CONVERSATION(conv)); + g_return_if_fail(smiley); + priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); if (priv->remote_smileys == NULL) {
priv->remote_smileys = purple_smiley_list_new();
@@ -854,42 +852,33 @@
"drop-failed-remotes", TRUE, NULL);
- smiley = purple_smiley_list_get_by_shortcut(
- priv->remote_smileys, shortcut);
- /* smiley was already added */
- smiley = purple_smiley_new_remote(shortcut);
+ if(purple_smiley_list_get_by_shortcut( + purple_smiley_get_shortcut(smiley))) + /* smiley was already added */ if (!purple_smiley_list_add(priv->remote_smileys, smiley)) {
purple_debug_error("conversation", "failed adding remote "
- g_object_unref(smiley);
- /* priv->remote_smileys holds the only one ref */
- g_object_unref(smiley);
-purple_conversation_get_remote_smiley(PurpleConversation *conv,
- PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv);
+purple_conversation_get_smiley(PurpleConversation *conv, const gchar *shortcut) { + PurpleConversationPrivate *priv = NULL; - g_return_val_if_fail(priv != NULL, NULL);
- g_return_val_if_fail(shortcut != NULL, NULL);
- g_return_val_if_fail(shortcut[0] != '\0', NULL);
+ g_return_val_if_fail(PURPLE_IS_CONVERSATION(conv), NULL); + g_return_val_if_fail(shortcut, NULL); + priv = PURPLE_CONVERSATION_GET_PRIVATE(conv); if (priv->remote_smileys == NULL)
- return purple_smiley_list_get_by_shortcut(
- priv->remote_smileys, shortcut);
+ return purple_smiley_list_get_by_shortcut(priv->remote_smileys, shortcut); --- a/libpurple/conversation.h Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/conversation.h Sun May 28 13:26:27 2017 +0300
@@ -652,40 +652,24 @@
purple_conversation_get_max_message_size(PurpleConversation *conv);
- * purple_conversation_add_remote_smiley:
+ * purple_conversation_add_smiley: * @conv: The conversation that receives new smiley.
- * @shortcut: The shortcut for the new smiley.
- * Adds new smiley to the list of remote smileys for this conversation.
- * The smiley image have to be written and closed, when data is ready.
- * You can retrieve smiley's #PurpleImage object using #purple_smiley_get_image
- * and set its data with #purple_image_transfer_write
- * and #purple_image_transfer_close.
- * Returns: (transfer none): New smiley, or %NULL if it's already being
- * retrieved (or possibly, in case of error).
+ * Adds a smiley to the list of smileys that belong to this conversation.
-purple_conversation_add_remote_smiley(PurpleConversation *conv,
- const gchar *shortcut);
+void purple_conversation_add_smiley(PurpleConversation *conv, PurpleSmiley *smiley); - * purple_conversation_get_remote_smiley:
+ * purple_conversation_get_smiley: * @conv: The conversation.
* @shortcut: The shortcut.
- * Lookups for the remote smiley previously added to this conversation.
- * You may use this function when you receive the smiley data, but it's
- * better just to store and use the reference returned by
- * #purple_conversation_add_remote_smiley.
+ * Lookups for the smiley previously added to this conversation. * Returns: (transfer none): The smiley, or %NULL if it doesn't exists.
-purple_conversation_get_remote_smiley(PurpleConversation *conv,
- const gchar *shortcut);
+PurpleSmiley *purple_conversation_get_smiley(PurpleConversation *conv, const gchar *shortcut); * purple_conversation_get_remote_smileys:
--- a/libpurple/image-store.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/image-store.c Sun May 28 13:26:27 2017 +0300
@@ -194,16 +194,14 @@
purple_image_store_get_uri(PurpleImage *image)
g_return_val_if_fail(PURPLE_IS_IMAGE(image), NULL);
- is_ready = purple_image_is_ready(image);
path = purple_image_get_path(image);
return g_filename_to_uri(path, NULL, NULL);
img_id = purple_image_store_add_weak(image);
--- a/libpurple/image.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/image.c Sun May 28 13:26:27 2017 +0300
@@ -30,176 +30,186 @@
gchar *friendly_filename;
-static GObjectClass *parent_class;
-static guint signals[SIG_LAST];
static GParamSpec *properties[PROP_LAST];
/******************************************************************************
******************************************************************************/
+_purple_image_set_contents(PurpleImage *image, GBytes *bytes) { + PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image); + g_bytes_unref(priv->contents); + priv->contents = (bytes) ? g_bytes_ref(bytes) : NULL; +/****************************************************************************** + ******************************************************************************/ +G_DEFINE_TYPE_WITH_PRIVATE(PurpleImage, purple_image, G_TYPE_OBJECT); -has_failed(PurpleImage *image)
- gboolean ready_changed;
- PurpleImagePrivate *priv;
- priv = PURPLE_IMAGE_GET_PRIVATE(image);
- g_return_if_fail(!priv->has_failed);
- priv->has_failed = TRUE;
- ready_changed = (priv->is_ready != FALSE);
- priv->is_ready = FALSE;
- g_string_free(priv->contents, TRUE);
- g_object_notify_by_pspec(G_OBJECT(image),
- properties[PROP_IS_READY]);
- g_object_notify_by_pspec(G_OBJECT(image), properties[PROP_HAS_FAILED]);
- g_signal_emit(image, signals[SIG_FAILED], 0);
+purple_image_init(PurpleImage *image) { -became_ready(PurpleImage *image)
+purple_image_finalize(GObject *obj) { + PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(obj); + g_bytes_unref(priv->contents); + g_free(priv->gen_filename); + g_free(priv->friendly_filename); + G_OBJECT_CLASS(purple_image_parent_class)->finalize(obj); +purple_image_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) - PurpleImagePrivate *priv;
- priv = PURPLE_IMAGE_GET_PRIVATE(image);
+ PurpleImage *image = PURPLE_IMAGE(obj); - g_return_if_fail(!priv->has_failed);
- g_return_if_fail(!priv->is_ready);
+ _purple_image_set_contents(image, g_value_get_boxed(value)); + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+purple_image_get_property(GObject *obj, guint param_id, GValue *value, + PurpleImage *image = PURPLE_IMAGE(obj); - g_object_notify_by_pspec(G_OBJECT(image), properties[PROP_IS_READY]);
- g_signal_emit(image, signals[SIG_READY], 0);
+ g_value_set_boxed(value, purple_image_get_contents(image)); + g_value_set_uint64(value, purple_image_get_data_size(image)); + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); -steal_contents(PurpleImagePrivate *priv, gpointer data, gsize length)
- g_return_if_fail(priv != NULL);
- g_return_if_fail(priv->contents == NULL);
- g_return_if_fail(data != NULL);
- g_return_if_fail(length > 0);
+purple_image_class_init(PurpleImageClass *klass) { + GObjectClass *gobj_class = G_OBJECT_CLASS(klass); + gobj_class->finalize = purple_image_finalize; + gobj_class->get_property = purple_image_get_property; + gobj_class->set_property = purple_image_set_property; - priv->contents = g_string_new(NULL);
- g_free(priv->contents->str);
- priv->contents->str = data;
- priv->contents->len = priv->contents->allocated_len = length;
+ properties[PROP_CONTENTS] = g_param_spec_boxed( + "The contents of the image stored in a GBytes", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS + properties[PROP_SIZE] = g_param_spec_uint64( + "The size of the image in bytes", + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS + g_object_class_install_properties(gobj_class, PROP_LAST, properties);
-fill_data(PurpleImage *image)
- PurpleImagePrivate *priv;
- priv = PURPLE_IMAGE_GET_PRIVATE(image);
- g_return_if_fail(priv->path);
- (void)g_file_get_contents(priv->path, &contents, &length, &error);
- purple_debug_error("image", "failed to read '%s' image: %s",
- priv->path, error->message);
- steal_contents(priv, contents, length);
/******************************************************************************
******************************************************************************/
-purple_image_new_from_file(const gchar *path, gboolean be_eager)
- PurpleImagePrivate *priv;
- 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, NULL);
- purple_image_set_friendly_filename(img, path);
- priv = PURPLE_IMAGE_GET_PRIVATE(img);
- priv->path = g_strdup(path);
- g_assert(priv->is_ready && !priv->has_failed);
+purple_image_new_from_bytes(GBytes *bytes) { -purple_image_new_from_data(gpointer data, gsize length)
- PurpleImagePrivate *priv;
+purple_image_new_from_file(const gchar *path, GError **error) { + PurpleImage *image = NULL; + gchar *contents = NULL; + if(!g_file_get_contents(path, &contents, &length, error)) { + bytes = g_bytes_new_take(contents, length); + image = purple_image_new_from_bytes(bytes); - g_return_val_if_fail(data != NULL, NULL);
- g_return_val_if_fail(length > 0, NULL);
+purple_image_new_from_data(const guint8 *data, gsize length) { + bytes = g_bytes_new(data, length); + image = purple_image_new_from_bytes(bytes); - img = g_object_new(PURPLE_TYPE_IMAGE, NULL);
- priv = PURPLE_IMAGE_GET_PRIVATE(img);
+purple_image_new_take_data(guint8 *data, gsize length) { - steal_contents(priv, data, length);
+ bytes = g_bytes_new_take(data, length); + image = purple_image_new_from_bytes(bytes);
-purple_image_save(PurpleImage *image, const gchar *path)
+purple_image_save(PurpleImage *image, const gchar *path) { PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image);
@@ -210,7 +220,7 @@
g_return_val_if_fail(path[0] != '\0', FALSE);
data = purple_image_get_data(image);
- len = purple_image_get_size(image);
+ len = purple_image_get_data_size(image); g_return_val_if_fail(data != NULL, FALSE);
g_return_val_if_fail(len > 0, FALSE);
@@ -222,9 +232,22 @@
+purple_image_get_contents(const PurpleImage *image) { + PurpleImagePrivate *priv = NULL; + g_return_val_if_fail(PURPLE_IS_IMAGE(image), NULL); + priv = PURPLE_IMAGE_GET_PRIVATE(image); + return g_bytes_ref(priv->contents); -purple_image_get_path(PurpleImage *image)
+purple_image_get_path(PurpleImage *image) { PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image);
g_return_val_if_fail(priv != NULL, NULL);
@@ -232,58 +255,36 @@
-purple_image_is_ready(PurpleImage *image)
- PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image);
- g_return_val_if_fail(priv != NULL, FALSE);
+purple_image_get_data_size(PurpleImage *image) { + PurpleImagePrivate *priv;
-purple_image_has_failed(PurpleImage *image)
- PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image);
- g_return_val_if_fail(priv != NULL, TRUE);
+ g_return_val_if_fail(PURPLE_IS_IMAGE(image), 0); - return priv->has_failed;
-purple_image_get_size(PurpleImage *image)
- PurpleImagePrivate *priv;
priv = PURPLE_IMAGE_GET_PRIVATE(image);
- g_return_val_if_fail(priv != NULL, 0);
- g_return_val_if_fail(priv->is_ready, 0);
+ return g_bytes_get_size(priv->contents);
- g_return_val_if_fail(priv->contents, 0);
- return priv->contents->len;
-purple_image_get_data(PurpleImage *image)
- PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image);
+purple_image_get_data(PurpleImage *image) { + PurpleImagePrivate *priv = NULL; + g_return_val_if_fail(PURPLE_IS_IMAGE(image), NULL); - g_return_val_if_fail(priv != NULL, NULL);
- g_return_val_if_fail(priv->is_ready, NULL);
+ priv = PURPLE_IMAGE_GET_PRIVATE(image);
- g_return_val_if_fail(priv->contents, NULL);
+ return g_bytes_get_data(priv->contents, NULL); - return priv->contents->str;
-purple_image_get_extension(PurpleImage *image)
+purple_image_get_extension(PurpleImage *image) { PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image);
@@ -292,7 +293,7 @@
- if (purple_image_get_size(image) < 4)
+ if (purple_image_get_data_size(image) < 4) data = purple_image_get_data(image);
@@ -317,8 +318,7 @@
-purple_image_get_mimetype(PurpleImage *image)
+purple_image_get_mimetype(PurpleImage *image) { PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image);
const gchar *ext = purple_image_get_extension(image);
@@ -346,8 +346,7 @@
-purple_image_generate_filename(PurpleImage *image)
+purple_image_generate_filename(PurpleImage *image) { PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image);
@@ -361,7 +360,7 @@
ext = purple_image_get_extension(image);
data = purple_image_get_data(image);
- len = purple_image_get_size(image);
+ len = purple_image_get_data_size(image); g_return_val_if_fail(ext != NULL, NULL);
g_return_val_if_fail(data != NULL, NULL);
@@ -375,8 +374,7 @@
-purple_image_set_friendly_filename(PurpleImage *image, const gchar *filename)
+purple_image_set_friendly_filename(PurpleImage *image, const gchar *filename) { PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image);
@@ -400,223 +398,17 @@
-purple_image_get_friendly_filename(PurpleImage *image)
- PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image);
- g_return_val_if_fail(priv != NULL, NULL);
- if (G_UNLIKELY(!priv->friendly_filename)) {
- const gchar *newname = purple_image_generate_filename(image);
- gsize newname_len = strlen(newname);
- /* let's use last 6 characters from checksum + 4 characters
- newname += newname_len - 10;
- priv->friendly_filename = g_strdup(newname);
+purple_image_get_friendly_filename(PurpleImage *image) { + PurpleImagePrivate *priv = NULL; - if (G_UNLIKELY(priv->is_ready &&
- strchr(priv->friendly_filename, '.') == NULL))
- const gchar *ext = purple_image_get_extension(image);
- return priv->friendly_filename;
- tmp = g_strdup_printf("%s.%s", priv->friendly_filename, ext);
- g_free(priv->friendly_filename);
- priv->friendly_filename = tmp;
- return priv->friendly_filename;
-purple_image_transfer_new(void)
- PurpleImagePrivate *priv;
+ g_return_val_if_fail(PURPLE_IS_IMAGE(image), NULL); - img = g_object_new(PURPLE_TYPE_IMAGE, NULL);
- priv = PURPLE_IMAGE_GET_PRIVATE(img);
- priv->is_ready = FALSE;
- priv->contents = g_string_new(NULL);
-purple_image_transfer_write(PurpleImage *image, gconstpointer data,
- PurpleImagePrivate *priv =
- PURPLE_IMAGE_GET_PRIVATE(image);
- g_return_if_fail(priv != NULL);
- g_return_if_fail(!priv->has_failed);
- g_return_if_fail(!priv->is_ready);
- g_return_if_fail(priv->contents != NULL);
- g_return_if_fail(data != NULL || length == 0);
+ priv = PURPLE_IMAGE_GET_PRIVATE(image);
- g_string_append_len(priv->contents, (const gchar*)data, length);
-purple_image_transfer_close(PurpleImage *image)
- PurpleImagePrivate *priv =
- PURPLE_IMAGE_GET_PRIVATE(image);
- g_return_if_fail(priv != NULL);
- g_return_if_fail(!priv->has_failed);
- g_return_if_fail(!priv->is_ready);
- g_return_if_fail(priv->contents != NULL);
- if (priv->contents->len == 0) {
- purple_debug_error("image", "image is empty");
+ if(priv->friendly_filename) { + return priv->friendly_filename;
-purple_image_transfer_failed(PurpleImage *image)
- PurpleImagePrivate *priv =
- PURPLE_IMAGE_GET_PRIVATE(image);
- g_return_if_fail(priv != NULL);
- g_return_if_fail(!priv->has_failed);
- g_return_if_fail(!priv->is_ready);
-/******************************************************************************
- ******************************************************************************/
-purple_image_init(GTypeInstance *instance, gpointer klass)
- PurpleImage *image = PURPLE_IMAGE(instance);
- PurpleImagePrivate *priv =
- PURPLE_IMAGE_GET_PRIVATE(image);
- priv->has_failed = FALSE;
-purple_image_finalize(GObject *obj)
- PurpleImage *image = PURPLE_IMAGE(obj);
- PurpleImagePrivate *priv =
- PURPLE_IMAGE_GET_PRIVATE(image);
- g_string_free(priv->contents, TRUE);
- g_free(priv->gen_filename);
- g_free(priv->friendly_filename);
- G_OBJECT_CLASS(parent_class)->finalize(obj);
-purple_image_get_property(GObject *object, guint par_id, GValue *value,
- PurpleImage *image = PURPLE_IMAGE(object);
- PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image);
- g_value_set_boolean(value, priv->is_ready);
- g_value_set_boolean(value, priv->has_failed);
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
+ return purple_image_generate_filename(image);
-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",
- "Is ready", "The image is ready to be displayed. Image may "
- "change the state to failed in a single case: if it's backed "
- "by a file and that file fails to load",
- TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- properties[PROP_HAS_FAILED] = g_param_spec_boolean("has-failed",
- "Has hailed", "The remote host has failed to send the image",
- FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_properties(gobj_class, PROP_LAST, properties);
- * @image: a image that failed to transfer.
- * Called when a @image fails to be transferred. It's guaranteed to be
- * fired at most once for a particular @image.
- signals[SIG_FAILED] = g_signal_new("failed", G_OBJECT_CLASS_TYPE(klass),
- g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
- * @image: a image that became ready.
- * Called when a @image becames ready to be displayed. It's guaranteed to be
- * fired at most once for a particular @image.
- signals[SIG_READY] = g_signal_new("ready", G_OBJECT_CLASS_TYPE(klass),
- g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-purple_image_get_type(void)
- if (G_UNLIKELY(type == 0)) {
- static const GTypeInfo info = {
- .class_size = sizeof(PurpleImageClass),
- .class_init = (GClassInitFunc)purple_image_class_init,
- .instance_size = sizeof(PurpleImage),
- .instance_init = purple_image_init,
- type = g_type_register_static(G_TYPE_OBJECT,
- "PurpleImage", &info, 0);
--- a/libpurple/image.h Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/image.h Sun May 28 13:26:27 2017 +0300
@@ -19,8 +19,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#ifndef _PURPLE_IMAGE_H_
-#define _PURPLE_IMAGE_H_
@@ -39,13 +40,13 @@
-typedef struct _PurpleImage PurpleImage;
+typedef struct _PurpleImage PurpleImage; typedef struct _PurpleImageClass PurpleImageClass;
#define PURPLE_TYPE_IMAGE (purple_image_get_type())
-#define PURPLE_IMAGE(smiley) (G_TYPE_CHECK_INSTANCE_CAST((smiley), PURPLE_TYPE_IMAGE, PurpleImage))
+#define PURPLE_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_IMAGE, PurpleImage)) #define PURPLE_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_IMAGE, PurpleImageClass))
-#define PURPLE_IS_IMAGE(smiley) (G_TYPE_CHECK_INSTANCE_TYPE((smiley), PURPLE_TYPE_IMAGE))
+#define PURPLE_IS_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_IMAGE)) #define PURPLE_IS_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_IMAGE))
#define PURPLE_IMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_IMAGE, PurpleImageClass))
@@ -54,20 +55,12 @@
* An image data container.
- * Base class for #PurpleImage objects.
-struct _PurpleImageClass
+struct _PurpleImageClass { GObjectClass parent_class;
void (*purple_reserved1)(void);
@@ -83,13 +76,22 @@
* Returns: the #GType for an image.
-purple_image_get_type(void);
+GType purple_image_get_type(void); + * purple_image_new_from_bytes: + * @bytes: (transfer none) A #GBytes containing the raw image data. + * Loads a raw image data as a new #PurpleImage object. + * Returns: the new #PurpleImage. +PurpleImage *purple_image_new_from_bytes(GBytes *bytes); * purple_image_new_from_file:
* @path: the path to the image file.
- * @be_eager: %TRUE, if file should be loaded now, %FALSE when needed.
+ * @error: (optional) An optional return address for a #GError * Loads an image file as a new #PurpleImage object. The @path must exists, be
* readable and should point to a valid image file. If you don't set @be_eager
@@ -98,8 +100,7 @@
* Returns: the new #PurpleImage.
-purple_image_new_from_file(const gchar *path, gboolean be_eager);
+PurpleImage *purple_image_new_from_file(const gchar *path, GError **error); * purple_image_new_from_data:
@@ -113,8 +114,21 @@
* Returns: the new #PurpleImage.
-purple_image_new_from_data(gpointer data, gsize length);
+PurpleImage *purple_image_new_from_data(const guint8 *data, gsize length); + * purple_image_new_take_data: + * @data: (transfer full) the pointer to the image data buffer. + * @length: the length of @data. + * Creates a new #PurpleImage object with contents of @data buffer. + * The @data buffer is owned by #PurpleImage object, so you might want + * to #g_memdup it first. + * Returns: the new #PurpleImage. +PurpleImage *purple_image_new_take_data(guint8 *data, gsize length); @@ -125,8 +139,18 @@
* Returns: %TRUE if succeeded, %FALSE otherwise.
-purple_image_save(PurpleImage *image, const gchar *path);
+gboolean purple_image_save(PurpleImage *image, const gchar *path); + * purple_image_get_contents: + * @image: The #PurpleImage. + * Returns a new reference to the #GBytes that contains the image data. + * Returns: (transfer full): A #GBytes containing the image data. +GBytes *purple_image_get_contents(const PurpleImage *image); @@ -137,46 +161,17 @@
* Returns: the physical path of the @image, or %NULL.
-purple_image_get_path(PurpleImage *image);
+const gchar *purple_image_get_path(PurpleImage *image); - * purple_image_is_ready:
- * Checks, if the @image data is ready to be displayed. Remote image data may
- * not be accessible at the moment, so you should check it before using
- * #purple_image_get_data. If the image is not ready yet, you may wait for
- * #PurpleImage::ready signal.
- * Returns: %TRUE, if the @image is ready.
-purple_image_is_ready(PurpleImage *image);
- * purple_image_has_failed:
- * Checks, if the @image has failed to load its data. It can be caused either by
- * a remote failure (and #purple_image_transfer_failed call) or local file being
- * removed (see #purple_image_new_from_file).
- * Returns: %TRUE, if the @image has failed to load.
-purple_image_has_failed(PurpleImage *image);
- * purple_image_get_size:
+ * purple_image_get_data_size: * Returns the size of @image's data.
* Returns: the size of data, or 0 in case of failure.
-purple_image_get_size(PurpleImage *image);
+gsize purple_image_get_data_size(PurpleImage *image); @@ -186,8 +181,7 @@
* Returns: (transfer none): the @image data.
-purple_image_get_data(PurpleImage *image);
+gconstpointer purple_image_get_data(PurpleImage *image); * purple_image_get_extension:
@@ -197,8 +191,7 @@
* Returns: (transfer none): the file extension suitable for @image format.
-purple_image_get_extension(PurpleImage *image);
+const gchar *purple_image_get_extension(PurpleImage *image); * purple_image_get_mimetype:
@@ -208,8 +201,7 @@
* Returns: (transfer none): the mime-type suitable for @image format.
-purple_image_get_mimetype(PurpleImage *image);
+const gchar *purple_image_get_mimetype(PurpleImage *image); * purple_image_generate_filename:
@@ -221,8 +213,7 @@
* Returns: (transfer none): the generated file name.
-purple_image_generate_filename(PurpleImage *image);
+const gchar *purple_image_generate_filename(PurpleImage *image); * purple_image_set_friendly_filename:
@@ -236,8 +227,7 @@
* The provided @filename may either be a full path, or contain
* filesystem-unfriendly characters, because it will be reformatted.
-purple_image_set_friendly_filename(PurpleImage *image, const gchar *filename);
+void purple_image_set_friendly_filename(PurpleImage *image, const gchar *filename); * purple_image_get_friendly_filename:
@@ -252,54 +242,8 @@
* Returns: (transfer none): the friendly filename.
-purple_image_get_friendly_filename(PurpleImage *image);
- * purple_image_transfer_new:
- * Creates a new remote image, with a possibility to load data with
- * #purple_image_transfer_write and #purple_image_transfer_close. In case of
- * failure, you should call #urple_image_transfer_failed.
- * Returns: the new image object.
-purple_image_transfer_new(void);
- * purple_image_transfer_write:
- * @data: the incoming data buffer.
- * @length: the length of @data.
- * Adds a chunk of data to the internal receive buffer. Called when receiving
-purple_image_transfer_write(PurpleImage *image, gconstpointer data,
- * purple_image_transfer_close:
- * Marks a remote @image as ready to be displayed. Called when finishing
- * transfer of remote file. You may call this only once for a certain @image.
-purple_image_transfer_close(PurpleImage *image);
- * purple_image_transfer_failed:
- * Marks a remote @image as failed to transfer. Called on error in remote file
- * transfer. You may call this only once for a certain @image.
-purple_image_transfer_failed(PurpleImage *image);
+const gchar *purple_image_get_friendly_filename(PurpleImage *image); -#endif /* _PURPLE_IMAGE_H_ */
+#endif /* PURPLE_IMAGE_H */ --- a/libpurple/log.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/log.c Sun May 28 13:26:27 2017 +0300
@@ -845,7 +845,7 @@
image_data = purple_image_get_data(image);
- image_byte_count = purple_image_get_size(image);
+ image_byte_count = purple_image_get_data_size(image); dir = purple_log_get_log_dir(log->type, log->name, log->account);
new_filename = purple_image_generate_filename(image);
--- a/libpurple/protocols/bonjour/mdns_common.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/protocols/bonjour/mdns_common.c Sun May 28 13:26:27 2017 +0300
@@ -186,7 +186,7 @@
avatar_data = purple_image_get_data(img);
- avatar_len = purple_image_get_size(img);
+ avatar_len = purple_image_get_data_size(img); if (_mdns_set_buddy_icon_data(data, avatar_data, avatar_len)) {
--- a/libpurple/protocols/gg/avatar.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/protocols/gg/avatar.c Sun May 28 13:26:27 2017 +0300
@@ -354,7 +354,7 @@
img_data = purple_base64_encode(purple_image_get_data(img),
- purple_image_get_size(img));
+ purple_image_get_data_size(img)); img_data_e = g_uri_escape_string(img_data, NULL, FALSE);
request_data = g_strdup_printf("uin=%d&photo=%s", uin, img_data_e);
--- a/libpurple/protocols/gg/image-prpl.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/protocols/gg/image-prpl.c Sun May 28 13:26:27 2017 +0300
@@ -104,7 +104,7 @@
g_return_val_if_fail(image, GGP_IMAGE_PREPARE_FAILURE);
- image_size = purple_image_get_size(image);
+ image_size = purple_image_get_data_size(image); if (image_size > GGP_IMAGE_SIZE_MAX) {
purple_debug_warning("gg", "ggp_image_prepare: image "
@@ -153,12 +153,13 @@
image_reply->crc32, image_reply->size,
image_reply->filename, id);
+ img = purple_image_new_from_data( + (const guint8 *)image_reply->image, purple_image_set_friendly_filename(img, image_reply->filename);
- purple_image_transfer_write(img,
- g_memdup(image_reply->image, image_reply->size),
- purple_image_transfer_close(img);
+ g_hash_table_insert(sdata->recv_images, &id, img); void ggp_image_send(PurpleConnection *gc,
@@ -205,7 +206,7 @@
gg_image_reply(accdata->session, image_request->sender,
purple_image_get_data(sent_image->image),
- purple_image_get_size(sent_image->image));
+ purple_image_get_data_size(sent_image->image)); conv = purple_conversations_find_with_account(
@@ -247,8 +248,7 @@
- img = purple_image_transfer_new();
- g_hash_table_insert(sdata->recv_images, ggp_uint64dup(id), img);
+ g_hash_table_insert(sdata->recv_images, ggp_uint64dup(id), NULL); purple_debug_info("gg", "ggp_image_request: requesting image "
GGP_IMAGE_ID_FORMAT, id);
--- a/libpurple/protocols/jabber/buddy.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/protocols/jabber/buddy.c Sun May 28 13:26:27 2017 +0300
@@ -474,7 +474,9 @@
js->initial_avatar_hash = jabber_calculate_data_hash(
purple_image_get_data(image),
- purple_image_get_size(image), "sha1");
+ purple_image_get_data_size(image), js->initial_avatar_hash = NULL;
@@ -514,7 +516,7 @@
avatar_data = purple_image_get_data(img);
- avatar_len = purple_image_get_size(img);
+ avatar_len = purple_image_get_data_size(img); /* Get rid of an old PHOTO if one exists.
* TODO: This may want to be modified to remove all old PHOTO
* children, at the moment some people have managed to get
--- a/libpurple/protocols/jabber/jabber.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/protocols/jabber/jabber.c Sun May 28 13:26:27 2017 +0300
@@ -1137,7 +1137,9 @@
js->initial_avatar_hash = jabber_calculate_data_hash(
purple_image_get_data(image),
- purple_image_get_size(image), "sha1");
+ purple_image_get_data_size(image), --- a/libpurple/protocols/jabber/message.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/protocols/jabber/message.c Sun May 28 13:26:27 2017 +0300
@@ -41,6 +41,11 @@
+ PurpleConversation *conv; +} JabberMessageRemoteSmileyAddData; void jabber_message_free(JabberMessage *jm)
@@ -487,63 +492,75 @@
-jabber_message_remote_smiley_got(JabberData *data, gchar *alt, gpointer _smiley)
- PurpleSmiley *smiley = _smiley;
- PurpleImage *image = purple_smiley_get_image(smiley);
+jabber_message_remote_smiley_got(JabberData *jdata, gchar *alt, gpointer d) { + JabberMessageRemoteSmileyAddData *data = (JabberMessageRemoteSmileyAddData *)d; - g_free(alt); /* we really don't need it */
+ PurpleSmiley *smiley = NULL;
purple_debug_info("jabber",
"smiley data retrieved successfully");
- purple_image_transfer_write(image, jabber_data_get_data(data),
- jabber_data_get_size(data));
- purple_image_transfer_close(image);
+ smiley = purple_smiley_new_from_data( + jabber_data_get_data(jdata), + jabber_data_get_size(jdata) + purple_conversation_add_smiley(data->conv, smiley); + g_object_unref(G_OBJECT(smiley)); purple_debug_error("jabber", "failed retrieving smiley data");
- purple_image_transfer_failed(image);
- g_object_unref(smiley);
+ g_object_unref(G_OBJECT(data->conv)); + g_free(data->shortcut); + g_slice_free(JabberMessageRemoteSmileyAddData, data); jabber_message_remote_smiley_add(JabberStream *js, PurpleConversation *conv,
const gchar *from, const gchar *shortcut, const gchar *cid)
- const JabberData *jdata;
+ PurpleSmiley *smiley = NULL; + const JabberData *jdata = NULL; purple_debug_misc("jabber", "about to add remote smiley %s to the conv",
- smiley = purple_conversation_add_remote_smiley(conv, shortcut);
+ smiley = purple_conversation_get_smiley(conv, shortcut); + if(PURPLE_IS_SMILEY(smiley)) { purple_debug_misc("jabber", "smiley was already present");
/* TODO: cache lookup by "cid" */
jdata = jabber_data_find_remote_by_cid(js, from, cid);
- PurpleImage *image = purple_smiley_get_image(smiley);
purple_debug_info("jabber", "smiley data is already known");
- purple_image_transfer_write(image, jabber_data_get_data(jdata),
- jabber_data_get_size(jdata));
- purple_image_transfer_close(image);
+ smiley = purple_smiley_new_from_data( + jabber_data_get_data(jdata), + jabber_data_get_size(jdata) + purple_conversation_add_smiley(conv, smiley); + g_object_unref(G_OBJECT(smiley)); - gchar *alt = g_strdup(shortcut); /* it it really necessary? */
+ JabberMessageRemoteSmileyAddData *data = NULL; + data = g_slice_new(JabberMessageRemoteSmileyAddData); + data->conv = g_object_ref(G_OBJECT(conv)); + data->shortcut = g_strdup(shortcut); purple_debug_info("jabber", "smiley data is unknown, "
- jabber_data_request(js, cid, from, alt, FALSE,
- jabber_message_remote_smiley_got, smiley);
+ jabber_data_request(js, cid, from, NULL, FALSE, + jabber_message_remote_smiley_got, data); @@ -914,19 +931,11 @@
for (it = found_smileys; it; it = it_next) {
PurpleSmiley *smiley = it->data;
- PurpleImage *smiley_image;
it_next = g_list_next(it);
- smiley_image = purple_smiley_get_image(smiley);
- purple_debug_warning("jabber", "broken smiley %s",
- purple_smiley_get_shortcut(smiley));
- } else if (purple_image_get_size(smiley_image) >
+ if (purple_image_get_data_size(PURPLE_IMAGE(smiley)) > JABBER_DATA_MAX_SIZE) { has_too_large_smiley = TRUE;
purple_debug_warning("jabber", "Refusing to send "
@@ -950,7 +959,6 @@
for (it = found_smileys; it; it = g_list_next(it)) {
PurpleSmiley *smiley = it->data;
- PurpleImage *smiley_image;
const gchar *shortcut = purple_smiley_get_shortcut(smiley);
@@ -959,10 +967,7 @@
if (jabber_data_find_local_by_alt(shortcut))
- smiley_image = purple_smiley_get_image(smiley);
- g_assert(smiley_image != NULL);
- mimetype = purple_image_get_mimetype(smiley_image);
+ mimetype = purple_image_get_mimetype(PURPLE_IMAGE(smiley)); purple_debug_error("jabber",
"unknown mime type for image");
@@ -970,8 +975,8 @@
jdata = jabber_data_create_from_data(
- purple_image_get_data(smiley_image),
- purple_image_get_size(smiley_image),
+ purple_image_get_data(PURPLE_IMAGE(smiley)), + purple_image_get_data_size(PURPLE_IMAGE(smiley)), mimetype, FALSE, jm->js);
purple_debug_info("jabber", "cache local smiley alt=%s, cid=%s",
--- a/libpurple/protocols/jabber/useravatar.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/protocols/jabber/useravatar.c Sun May 28 13:26:27 2017 +0300
@@ -130,7 +130,7 @@
- if (purple_image_get_size(img) > sizeof(*png))
+ if (purple_image_get_data_size(img) > sizeof(*png)) png = purple_image_get_data(img);
/* check if the data is a valid png file (well, at least to some extent) */
@@ -156,10 +156,10 @@
/* compute the sha1 hash */
char *hash = jabber_calculate_data_hash(
purple_image_get_data(img),
- purple_image_get_size(img), "sha1");
+ purple_image_get_data_size(img), "sha1"); char *base64avatar = purple_base64_encode(
purple_image_get_data(img),
- purple_image_get_size(img));
+ purple_image_get_data_size(img)); publish = purple_xmlnode_new("publish");
purple_xmlnode_set_attrib(publish, "node", NS_AVATAR_1_1_DATA);
@@ -177,7 +177,7 @@
lengthstring = g_strdup_printf("%" G_GSIZE_FORMAT,
- purple_image_get_size(img));
+ purple_image_get_data_size(img)); widthstring = g_strdup_printf("%u", width);
heightstring = g_strdup_printf("%u", height);
--- a/libpurple/protocols/oscar/family_oservice.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/protocols/oscar/family_oservice.c Sun May 28 13:26:27 2017 +0300
@@ -928,7 +928,7 @@
"Uploading icon to icon server\n");
purple_image_get_data(img),
- purple_image_get_size(img));
+ purple_image_get_data_size(img)); --- a/libpurple/protocols/oscar/oscar.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/protocols/oscar/oscar.c Sun May 28 13:26:27 2017 +0300
@@ -1422,7 +1422,7 @@
(args->icbmflags & AIM_IMFLAGS_BUDDYREQ) && !bi->ico_sent && bi->ico_informed) {
gconstpointer data = purple_image_get_data(img);
- size_t len = purple_image_get_size(img);
+ size_t len = purple_image_get_data_size(img); purple_debug_info("oscar",
"Sending buddy icon to %s (%" G_GSIZE_FORMAT " bytes)\n",
@@ -2546,7 +2546,7 @@
purple_debug_info("oscar",
"Uploading icon to icon server");
aim_bart_upload(od, purple_image_get_data(img),
- purple_image_get_size(img));
+ purple_image_get_data_size(img)); @@ -3057,7 +3057,7 @@
/* ... if it refers to a valid purple image ... */
/* ... append the message from start to the tag ... */
- unsigned long size = purple_image_get_size(image);
+ unsigned long size = purple_image_get_data_size(image); const gchar *filename = purple_image_get_friendly_filename(image);
gconstpointer imgdata = purple_image_get_data(image);
@@ -3205,7 +3205,7 @@
img = purple_buddy_icons_find_account_icon(account);
gconstpointer data = purple_image_get_data(img);
- args.iconlen = purple_image_get_size(img);
+ args.iconlen = purple_image_get_data_size(img); args.iconsum = aimutil_iconsum(data, args.iconlen);
args.iconstamp = purple_buddy_icons_get_account_icon_timestamp(account);
@@ -5241,7 +5241,7 @@
gconstpointer data = purple_image_get_data(img);
- size_t len = purple_image_get_size(img);
+ size_t len = purple_image_get_data_size(img); hash = purple_md5_hash_new();
purple_hash_append(hash, data, len);
--- a/libpurple/protocols/sametime/sametime.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/protocols/sametime/sametime.c Sun May 28 13:26:27 2017 +0300
@@ -3878,7 +3878,7 @@
/* obtain and base64 encode the image data, and put it in the
- size = purple_image_get_size(img);
+ size = purple_image_get_data_size(img); data = purple_base64_encode(purple_image_get_data(img), size);
purple_mime_part_set_data(part, data);
--- a/libpurple/protocols/silc/buddy.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/protocols/silc/buddy.c Sun May 28 13:26:27 2017 +0300
@@ -1751,7 +1751,7 @@
silc_mime_add_field(mime, "Content-Type", type);
silc_mime_add_data(mime, purple_image_get_data(img),
- purple_image_get_size(img));
+ purple_image_get_data_size(img)); silc_client_attribute_add(client, conn, SILC_ATTRIBUTE_USER_ICON,
--- a/libpurple/protocols/silc/util.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/protocols/silc/util.c Sun May 28 13:26:27 2017 +0300
@@ -623,7 +623,7 @@
image = purple_image_store_get_from_uri(uri);
- unsigned long imglen = purple_image_get_size(image);
+ unsigned long imglen = purple_image_get_data_size(image); gconstpointer img = purple_image_get_data(image);
--- a/libpurple/smiley-custom.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/smiley-custom.c Sun May 28 13:26:27 2017 +0300
@@ -1,4 +1,4 @@
* Purple is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
@@ -133,7 +133,7 @@
purple_xmlnode_set_attrib(smiley_node, "shortcut",
purple_smiley_get_shortcut(smiley));
basename = g_path_get_basename(purple_image_get_path(
- purple_smiley_get_image(smiley)));
+ PURPLE_IMAGE(smiley))); purple_xmlnode_set_attrib(smiley_node, "filename", basename);
@@ -175,7 +175,7 @@
return g_compute_checksum_for_data(G_CHECKSUM_SHA1,
purple_image_get_data(img),
- purple_image_get_size(img));
+ purple_image_get_data_size(img)); @@ -262,14 +262,13 @@
purple_smiley_list_remove(smileys_list, smiley);
- path = purple_image_get_path(purple_smiley_get_image(smiley));
+ path = purple_image_get_path(PURPLE_IMAGE(smiley)); other_smileys = purple_smiley_list_get_unique(smileys_list);
for (it = other_smileys; it; it = g_list_next(it)) {
PurpleSmiley *other = it->data;
- const gchar *other_path = purple_image_get_path(
- purple_smiley_get_image(other));
+ const gchar *other_path = purple_image_get_path(PURPLE_IMAGE(other)); if (g_strcmp0(other_path, path) == 0) {
--- a/libpurple/smiley-list.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/smiley-list.c Sun May 28 13:26:27 2017 +0300
@@ -47,9 +47,106 @@
-static GObjectClass *parent_class;
static GParamSpec *properties[PROP_LAST];
+/******************************************************************************* + ******************************************************************************/ +G_DEFINE_TYPE_WITH_PRIVATE(PurpleSmileyList, purple_smiley_list, G_TYPE_OBJECT); +purple_smiley_list_init(PurpleSmileyList *list) { + PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(list); + priv->trie = purple_trie_new(); + priv->path_map = g_hash_table_new_full(g_str_hash, g_str_equal, + priv->shortcut_map = g_hash_table_new_full(g_str_hash, g_str_equal, + PURPLE_DBUS_REGISTER_POINTER(list, PurpleSmileyList); +purple_smiley_list_finalize(GObject *obj) { + PurpleSmileyList *sl = PURPLE_SMILEY_LIST(obj); + PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(sl); + g_object_unref(priv->trie); + g_hash_table_destroy(priv->path_map); + g_hash_table_destroy(priv->shortcut_map); + for (it = priv->smileys; it; it = g_list_next(it)) { + PurpleSmiley *smiley = it->data; + g_object_set_data(G_OBJECT(smiley), "purple-smiley-list", NULL); + g_object_set_data(G_OBJECT(smiley), "purple-smiley-list-elem", NULL); + g_object_unref(smiley); + g_list_free(priv->smileys); + PURPLE_DBUS_UNREGISTER_POINTER(sl); + G_OBJECT_CLASS(purple_smiley_list_parent_class)->finalize(obj); +purple_smiley_list_get_property(GObject *obj, guint param_id, GValue *value, + PurpleSmileyList *sl = PURPLE_SMILEY_LIST(obj); + PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(sl); + case PROP_DROP_FAILED_REMOTES: + g_value_set_boolean(value, priv->drop_failed_remotes); + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); +purple_smiley_list_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) + PurpleSmileyList *sl = PURPLE_SMILEY_LIST(obj); + PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(sl); + case PROP_DROP_FAILED_REMOTES: + priv->drop_failed_remotes = g_value_get_boolean(value); + /* XXX: we could scan for remote smiley's on our list + * and change the setting, but we don't care that much. + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); +purple_smiley_list_class_init(PurpleSmileyListClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + obj_class->get_property = purple_smiley_list_get_property; + obj_class->set_property = purple_smiley_list_set_property; + obj_class->finalize = purple_smiley_list_finalize; + properties[PROP_DROP_FAILED_REMOTES] = g_param_spec_boolean( + "drop-failed-remotes", "Drop failed PurpleRemoteSmileys", + "Watch added remote smileys and remove them from the list, " + "if they change their state to failed", FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties(obj_class, PROP_LAST, properties); +/****************************************************************************** + *****************************************************************************/ _list_append2(GList **head_p, GList **tail_p, gpointer data)
@@ -89,40 +186,20 @@
smiley_get_uniqid(PurpleSmiley *smiley)
- return purple_image_get_path(purple_smiley_get_image(smiley));
+ return purple_image_get_path(PURPLE_IMAGE(smiley)); /*******************************************************************************
******************************************************************************/
-purple_smiley_list_new(void)
+purple_smiley_list_new(void) { return g_object_new(PURPLE_TYPE_SMILEY_LIST, NULL);
-remote_smiley_failed(PurpleImage *smiley_img, gpointer _list)
- PurpleSmileyList *list = _list;
- smiley = g_object_get_data(G_OBJECT(smiley_img),
- "purple-smiley-list-smiley");
- purple_debug_info("smiley-list", "remote smiley '%s' has failed, "
- "removing it from the list...",
- purple_smiley_get_shortcut(smiley));
- purple_smiley_list_remove(list, smiley);
-purple_smiley_list_add(PurpleSmileyList *list, PurpleSmiley *smiley)
+purple_smiley_list_add(PurpleSmileyList *list, PurpleSmiley *smiley) { PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(list);
- PurpleImage *smiley_img;
const gchar *smiley_path;
@@ -168,14 +245,6 @@
g_hash_table_insert(priv->shortcut_map, g_strdup(shortcut), smiley);
- smiley_img = purple_smiley_get_image(smiley);
- if (priv->drop_failed_remotes && !purple_image_is_ready(smiley_img)) {
- g_object_set_data(G_OBJECT(smiley_img),
- "purple-smiley-list-smiley", smiley);
- g_signal_connect_object(smiley_img, "failed",
- G_CALLBACK(remote_smiley_failed), list, 0);
smiley_path = smiley_get_uniqid(smiley);
/* TODO: add to the table, when the smiley sets the path */
@@ -191,8 +260,7 @@
-purple_smiley_list_remove(PurpleSmileyList *list, PurpleSmiley *smiley)
+purple_smiley_list_remove(PurpleSmileyList *list, PurpleSmiley *smiley) { PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(list);
const gchar *shortcut, *path;
@@ -239,8 +307,7 @@
-purple_smiley_list_is_empty(PurpleSmileyList *list)
+purple_smiley_list_is_empty(const PurpleSmileyList *list) { PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(list);
g_return_val_if_fail(priv != NULL, TRUE);
@@ -250,7 +317,7 @@
purple_smiley_list_get_by_shortcut(PurpleSmileyList *list,
PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(list);
@@ -260,8 +327,7 @@
-purple_smiley_list_get_trie(PurpleSmileyList *list)
+purple_smiley_list_get_trie(PurpleSmileyList *list) { PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(list);
g_return_val_if_fail(priv != NULL, NULL);
@@ -270,8 +336,7 @@
-purple_smiley_list_get_unique(PurpleSmileyList *list)
+purple_smiley_list_get_unique(PurpleSmileyList *list) { GList *unique = NULL, *it;
PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(list);
@@ -300,134 +365,12 @@
-purple_smiley_list_get_all(PurpleSmileyList *list)
- PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(list);
+purple_smiley_list_get_all(PurpleSmileyList *list) { + PurpleSmileyListPrivate *priv = NULL; - g_return_val_if_fail(priv != NULL, NULL);
+ g_return_val_if_fail(PURPLE_IS_SMILEY_LIST(list), NULL); + priv = PURPLE_SMILEY_LIST_GET_PRIVATE(list); return g_hash_table_get_values(priv->shortcut_map);
-/*******************************************************************************
- ******************************************************************************/
-purple_smiley_list_init(GTypeInstance *instance, gpointer klass)
- PurpleSmileyList *sl = PURPLE_SMILEY_LIST(instance);
- PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(sl);
- priv->trie = purple_trie_new();
- priv->path_map = g_hash_table_new_full(g_str_hash, g_str_equal,
- priv->shortcut_map = g_hash_table_new_full(g_str_hash, g_str_equal,
- PURPLE_DBUS_REGISTER_POINTER(sl, PurpleSmileyList);
-purple_smiley_list_finalize(GObject *obj)
- PurpleSmileyList *sl = PURPLE_SMILEY_LIST(obj);
- PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(sl);
- g_object_unref(priv->trie);
- g_hash_table_destroy(priv->path_map);
- g_hash_table_destroy(priv->shortcut_map);
- for (it = priv->smileys; it; it = g_list_next(it)) {
- PurpleSmiley *smiley = it->data;
- g_object_set_data(G_OBJECT(smiley), "purple-smiley-list", NULL);
- g_object_set_data(G_OBJECT(smiley), "purple-smiley-list-elem", NULL);
- g_object_unref(smiley);
- g_list_free(priv->smileys);
- PURPLE_DBUS_UNREGISTER_POINTER(sl);
- G_OBJECT_CLASS(parent_class)->finalize(obj);
-purple_smiley_list_get_property(GObject *object, guint par_id, GValue *value,
- PurpleSmileyList *sl = PURPLE_SMILEY_LIST(object);
- PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(sl);
- case PROP_DROP_FAILED_REMOTES:
- g_value_set_boolean(value, priv->drop_failed_remotes);
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
-purple_smiley_list_set_property(GObject *object, guint par_id, const GValue *value,
- PurpleSmileyList *sl = PURPLE_SMILEY_LIST(object);
- PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(sl);
- case PROP_DROP_FAILED_REMOTES:
- priv->drop_failed_remotes = g_value_get_boolean(value);
- /* XXX: we could scan for remote smiley's on our list
- * and change the setting, but we don't care that much.
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
-purple_smiley_list_class_init(PurpleSmileyListClass *klass)
- GObjectClass *gobj_class = G_OBJECT_CLASS(klass);
- parent_class = g_type_class_peek_parent(klass);
- g_type_class_add_private(klass, sizeof(PurpleSmileyListPrivate));
- gobj_class->get_property = purple_smiley_list_get_property;
- gobj_class->set_property = purple_smiley_list_set_property;
- gobj_class->finalize = purple_smiley_list_finalize;
- properties[PROP_DROP_FAILED_REMOTES] = g_param_spec_boolean(
- "drop-failed-remotes", "Drop failed PurpleRemoteSmileys",
- "Watch added remote smileys and remove them from the list, "
- "if they change their state to failed", FALSE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
- g_object_class_install_properties(gobj_class, PROP_LAST, properties);
-purple_smiley_list_get_type(void)
- if (G_UNLIKELY(type == 0)) {
- static const GTypeInfo info = {
- .class_size = sizeof(PurpleSmileyListClass),
- .class_init = (GClassInitFunc)purple_smiley_list_class_init,
- .instance_size = sizeof(PurpleSmileyList),
- .instance_init = purple_smiley_list_init,
- type = g_type_register_static(G_TYPE_OBJECT,
- "PurpleSmileyList", &info, 0);
--- a/libpurple/smiley-list.h Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/smiley-list.h Sun May 28 13:26:27 2017 +0300
@@ -19,8 +19,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#ifndef _PURPLE_SMILEY_LIST_H_
-#define _PURPLE_SMILEY_LIST_H_
+#ifndef PURPLE_SMILEY_LIST_H +#define PURPLE_SMILEY_LIST_H @@ -42,9 +43,9 @@
typedef struct _PurpleSmileyListClass PurpleSmileyListClass;
#define PURPLE_TYPE_SMILEY_LIST (purple_smiley_list_get_type())
-#define PURPLE_SMILEY_LIST(smiley) (G_TYPE_CHECK_INSTANCE_CAST((smiley), PURPLE_TYPE_SMILEY_LIST, PurpleSmileyList))
+#define PURPLE_SMILEY_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_SMILEY_LIST, PurpleSmileyList)) #define PURPLE_SMILEY_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_SMILEY_LIST, PurpleSmileyListClass))
-#define PURPLE_IS_SMILEY_LIST(smiley) (G_TYPE_CHECK_INSTANCE_TYPE((smiley), PURPLE_TYPE_SMILEY_LIST))
+#define PURPLE_IS_SMILEY_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_SMILEY_LIST)) #define PURPLE_IS_SMILEY_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_SMILEY_LIST))
#define PURPLE_SMILEY_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_SMILEY_LIST, PurpleSmileyListClass))
@@ -53,19 +54,12 @@
* A container for #PurpleSmiley's.
-struct _PurpleSmileyList
+struct _PurpleSmileyList {
- * PurpleSmileyListClass:
- * Base class for #PurpleSmileyList objects.
-struct _PurpleSmileyListClass
+struct _PurpleSmileyListClass { GObjectClass parent_class;
@@ -82,8 +76,7 @@
* Returns: the #GType for a smiley list.
-purple_smiley_list_get_type(void);
+GType purple_smiley_list_get_type(void); * purple_smiley_list_new:
@@ -96,8 +89,7 @@
* Returns: newly created #PurpleSmileyList.
-purple_smiley_list_new(void);
+PurpleSmileyList *purple_smiley_list_new(void); * purple_smiley_list_add:
@@ -112,8 +104,7 @@
* Returns: %TRUE if the @smiley was successfully added to the list.
-purple_smiley_list_add(PurpleSmileyList *list, PurpleSmiley *smiley);
+gboolean purple_smiley_list_add(PurpleSmileyList *list, PurpleSmiley *smiley); * purple_smiley_list_remove:
@@ -123,8 +114,7 @@
* Removes a @smiley from the @list. If @smiley's reference count drops to zero,
-purple_smiley_list_remove(PurpleSmileyList *list, PurpleSmiley *smiley);
+void purple_smiley_list_remove(PurpleSmileyList *list, PurpleSmiley *smiley); * purple_smiley_list_is_empty:
@@ -134,8 +124,7 @@
* Returns: %TRUE if the @list is empty, %FALSE otherwise.
-purple_smiley_list_is_empty(PurpleSmileyList *list);
+gboolean purple_smiley_list_is_empty(const PurpleSmileyList *list); * purple_smiley_list_get_by_shortcut:
@@ -146,9 +135,7 @@
* Returns: a #PurpleSmiley if the smiley was found, %NULL otherwise.
-purple_smiley_list_get_by_shortcut(PurpleSmileyList *list,
- const gchar *shortcut);
+PurpleSmiley *purple_smiley_list_get_by_shortcut(PurpleSmileyList *list, const gchar *shortcut); * purple_smiley_list_get_trie:
@@ -161,8 +148,7 @@
* Returns: (transfer none): a #PurpleTrie for contained smileys.
-purple_smiley_list_get_trie(PurpleSmileyList *list);
+PurpleTrie *purple_smiley_list_get_trie(PurpleSmileyList *list); * purple_smiley_list_get_unique:
@@ -173,8 +159,7 @@
* Returns: (transfer container): the #GList of unique smileys. Use #g_list_free
-purple_smiley_list_get_unique(PurpleSmileyList *list_);
+GList *purple_smiley_list_get_unique(PurpleSmileyList *list_); * purple_smiley_list_get_all:
@@ -185,9 +170,8 @@
* Returns: (transfer container): the #GList of smileys. Use #g_list_free
-purple_smiley_list_get_all(PurpleSmileyList *list_);
+GList *purple_smiley_list_get_all(PurpleSmileyList *list_); -#endif /* _PURPLE_SMILEY_H_ */
+#endif /* PURPLE_SMILEY_LIST_H */ --- a/libpurple/smiley.c Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/smiley.c Sun May 28 13:26:27 2017 +0300
@@ -19,20 +19,14 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
#define PURPLE_SMILEY_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_SMILEY, PurpleSmileyPrivate))
@@ -42,175 +36,169 @@
-static GObjectClass *parent_class;
static GParamSpec *properties[PROP_LAST];
/*******************************************************************************
+ ******************************************************************************/ +_purple_smiley_set_shortcut(PurpleSmiley *smiley, const gchar *shortcut) { + PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + g_free(priv->shortcut); + priv->shortcut = g_strdup(shortcut); + g_object_notify(G_OBJECT(smiley), "shortcut"); +/******************************************************************************* ******************************************************************************/
+G_DEFINE_TYPE_WITH_PRIVATE(PurpleSmiley, purple_smiley, PURPLE_TYPE_IMAGE); +purple_smiley_init(PurpleSmiley *smiley) { + PURPLE_DBUS_REGISTER_POINTER(smiley, PurpleSmiley); +purple_smiley_finalize(GObject *obj) { + PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(obj); + g_free(priv->shortcut); + PURPLE_DBUS_UNREGISTER_POINTER(smiley); + G_OBJECT_CLASS(purple_smiley_parent_class)->finalize(obj); +purple_smiley_get_property(GObject *obj, guint param_id, GValue *value, + PurpleSmiley *smiley = PURPLE_SMILEY(obj); + g_value_set_string(value, purple_smiley_get_shortcut(smiley)); + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); +purple_smiley_set_property(GObject *obj, guint param_id, const GValue *value, + PurpleSmiley *smiley = PURPLE_SMILEY(obj); + _purple_smiley_set_shortcut(smiley, g_value_get_string(value)); + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); +purple_smiley_class_init(PurpleSmileyClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + obj_class->get_property = purple_smiley_get_property; + obj_class->set_property = purple_smiley_set_property; + obj_class->finalize = purple_smiley_finalize; + properties[PROP_SHORTCUT] = g_param_spec_string( + "A non-escaped textual representation of a smiley.", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS + g_object_class_install_properties(obj_class, PROP_LAST, properties); +/******************************************************************************* + ******************************************************************************/ purple_smiley_new(const gchar *shortcut, const gchar *path)
- PurpleSmileyPrivate *priv;
+ PurpleSmiley *smiley = NULL; + gchar *contents = NULL; g_return_val_if_fail(shortcut != NULL, NULL);
g_return_val_if_fail(path != NULL, NULL);
- smiley = g_object_new(PURPLE_TYPE_SMILEY,
- priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
- priv->image = purple_image_new_from_file(path, FALSE);
- purple_debug_error("smiley", "Couldn't load smiley data ");
- g_object_unref(smiley);
+ if(!g_file_get_contents(path, &contents, &length, NULL)) { + bytes = g_bytes_new_take(contents, length); -purple_smiley_new_remote(const gchar *shortcut)
+purple_smiley_new_from_data(const gchar *shortcut,
- PurpleSmileyPrivate *priv;
+ PurpleSmiley *smiley = NULL; g_return_val_if_fail(shortcut != NULL, NULL);
- smiley = g_object_new(PURPLE_TYPE_SMILEY,
+ bytes = g_bytes_new(data, length);
- priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
- priv->image = purple_image_transfer_new();
+purple_smiley_new_remote(const gchar *shortcut) { + g_return_val_if_fail(shortcut != NULL, NULL); -purple_smiley_get_shortcut(const PurpleSmiley *smiley)
- PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
+purple_smiley_get_shortcut(const PurpleSmiley *smiley) { + PurpleSmileyPrivate *priv = NULL; - g_return_val_if_fail(priv != NULL, NULL);
+ g_return_val_if_fail(PURPLE_IS_SMILEY(smiley), NULL); + priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
-purple_smiley_get_image(PurpleSmiley *smiley)
- PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
- g_return_val_if_fail(priv != NULL, NULL);
- g_return_val_if_fail(priv->image != NULL, NULL);
-/*******************************************************************************
- ******************************************************************************/
-purple_smiley_init(GTypeInstance *instance, gpointer klass)
- PurpleSmiley *smiley = PURPLE_SMILEY(instance);
- PURPLE_DBUS_REGISTER_POINTER(smiley, PurpleSmiley);
-purple_smiley_finalize(GObject *obj)
- PurpleSmiley *smiley = PURPLE_SMILEY(obj);
- PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
- g_free(priv->shortcut);
- g_object_unref(priv->image);
- PURPLE_DBUS_UNREGISTER_POINTER(smiley);
- G_OBJECT_CLASS(parent_class)->finalize(obj);
-purple_smiley_get_property(GObject *object, guint par_id, GValue *value,
- PurpleSmiley *smiley = PURPLE_SMILEY(object);
- PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
- g_value_set_string(value, priv->shortcut);
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
-purple_smiley_set_property(GObject *object, guint par_id, const GValue *value,
- PurpleSmiley *smiley = PURPLE_SMILEY(object);
- PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
- g_free(priv->shortcut);
- priv->shortcut = g_strdup(g_value_get_string(value));
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
-purple_smiley_class_init(PurpleSmileyClass *klass)
- GObjectClass *gobj_class = G_OBJECT_CLASS(klass);
- parent_class = g_type_class_peek_parent(klass);
- g_type_class_add_private(klass, sizeof(PurpleSmileyPrivate));
- gobj_class->get_property = purple_smiley_get_property;
- gobj_class->set_property = purple_smiley_set_property;
- gobj_class->finalize = purple_smiley_finalize;
- properties[PROP_SHORTCUT] = g_param_spec_string("shortcut", "Shortcut",
- "A non-escaped textual representation of a smiley.", NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_properties(gobj_class, PROP_LAST, properties);
-purple_smiley_get_type(void)
- if (G_UNLIKELY(type == 0)) {
- static const GTypeInfo info = {
- .class_size = sizeof(PurpleSmileyClass),
- .class_init = (GClassInitFunc)purple_smiley_class_init,
- .instance_size = sizeof(PurpleSmiley),
- .instance_init = purple_smiley_init,
- type = g_type_register_static(G_TYPE_OBJECT,
- "PurpleSmiley", &info, 0);
--- a/libpurple/smiley.h Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/smiley.h Sun May 28 13:26:27 2017 +0300
@@ -19,8 +19,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#ifndef _PURPLE_SMILEY_H_
-#define _PURPLE_SMILEY_H_
@@ -45,9 +46,9 @@
typedef struct _PurpleSmileyClass PurpleSmileyClass;
#define PURPLE_TYPE_SMILEY (purple_smiley_get_type())
-#define PURPLE_SMILEY(smiley) (G_TYPE_CHECK_INSTANCE_CAST((smiley), PURPLE_TYPE_SMILEY, PurpleSmiley))
+#define PURPLE_SMILEY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_SMILEY, PurpleSmiley)) #define PURPLE_SMILEY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_SMILEY, PurpleSmileyClass))
-#define PURPLE_IS_SMILEY(smiley) (G_TYPE_CHECK_INSTANCE_TYPE((smiley), PURPLE_TYPE_SMILEY))
+#define PURPLE_IS_SMILEY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_SMILEY)) #define PURPLE_IS_SMILEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_SMILEY))
#define PURPLE_SMILEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_SMILEY, PurpleSmileyClass))
@@ -56,10 +57,9 @@
* A generic smiley. It can either be a theme smiley, or a custom smiley.
@@ -67,10 +67,9 @@
* Base class for #PurpleSmiley objects.
-struct _PurpleSmileyClass
+struct _PurpleSmileyClass { - GObjectClass parent_class;
+ PurpleImageClass parent_class; void (*purple_reserved1)(void);
@@ -86,8 +85,7 @@
* Returns: the #GType for a smiley.
-purple_smiley_get_type(void);
+GType purple_smiley_get_type(void); @@ -99,8 +97,19 @@
* Returns: the new #PurpleSmiley.
-purple_smiley_new(const gchar *shortcut, const gchar *path);
+PurpleSmiley *purple_smiley_new(const gchar *shortcut, const gchar *path); + * purple_smiley_new_from_data: + * @shortcut: The smiley shortcut (unescaped). + * @data: The raw data of the image. + * @length: The length of @data in bytes. + * Creates new smiley from @data. + * Returns: A new #PurpleSmiley. +PurpleSmiley *purple_smiley_new_from_data(const gchar *shortcut, const guint8 *data, gsize length); * purple_smiley_new_remote:
@@ -112,8 +121,7 @@
* Returns: the new remote #PurpleSmiley.
-purple_smiley_new_remote(const gchar *shortcut);
+PurpleSmiley *purple_smiley_new_remote(const gchar *shortcut); * purple_smiley_get_shortcut:
@@ -124,23 +132,8 @@
* Returns: the unescaped shortcut.
-purple_smiley_get_shortcut(const PurpleSmiley *smiley);
- * purple_smiley_get_image:
- * Returns the image contents for a @smiley. It may not be ready for remote
- * smileys, so check it with #purple_image_is_ready.
- * If you want to save it, increase a ref count for the returned object.
- * Returns: (transfer none): the image contents for a @smiley.
-purple_smiley_get_image(PurpleSmiley *smiley);
+const gchar *purple_smiley_get_shortcut(const PurpleSmiley *smiley); -#endif /* _PURPLE_SMILEY_H_ */
+#endif /* PURPLE_SMILEY_H */ --- a/libpurple/tests/.hgignore Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/tests/.hgignore Sun May 28 13:26:27 2017 +0300
@@ -3,6 +3,8 @@
--- a/libpurple/tests/Makefile.am Thu Mar 23 19:11:37 2017 +0300
+++ b/libpurple/tests/Makefile.am Sun May 28 13:26:27 2017 +0300
@@ -9,15 +9,16 @@
test_des_SOURCES=test_des.c
test_des_LDADD=$(COMMON_LIBS)
@@ -27,6 +28,9 @@
test_hmac_SOURCES=test_hmac.c
test_hmac_LDADD=$(COMMON_LIBS)
+test_image_SOURCES=test_image.c +test_image_LDADD=$(COMMON_LIBS) test_md4_SOURCES=test_md4.c
test_md4_LDADD=$(COMMON_LIBS)
@@ -39,6 +43,9 @@
test_sha256_SOURCES=test_sha256.c
test_sha256_LDADD=$(COMMON_LIBS)
+test_smiley_SOURCES=test_smiley.c +test_smiley_LDADD=$(COMMON_LIBS) test_trie_SOURCES=test_trie.c
test_trie_LDADD=$(COMMON_LIBS)
@@ -51,9 +58,13 @@
-I$(top_srcdir)/libpurple \
-I$(top_builddir)/libpurple \
+ -DTEST_DATA_DIR=\"$(srcdir)/data\" \ Binary file libpurple/tests/data/test-image.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/tests/test_image.c Sun May 28 13:26:27 2017 +0300
@@ -0,0 +1,132 @@
+ * Purple is the legal property of its developers, whose names are too + * numerous to list here. Please refer to the COPYRIGHT file distributed + * with this source distribution + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA +// $ cat test-image.png | hexdump -v -e '1 1 "0x%02x," " "' | xargs -n 8 echo +static const gsize test_image_data_len = 160; +static const guint8 test_image_data[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, + 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x08, 0x02, 0x00, 0x00, 0x00, 0xfd, 0xd4, 0x9a, + 0x73, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, + 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, + 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, + 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xe0, + 0x0a, 0x02, 0x16, 0x30, 0x22, 0x28, 0xa4, 0xc9, + 0xdd, 0x00, 0x00, 0x00, 0x1d, 0x69, 0x54, 0x58, + 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, + 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x64, 0x2e, + 0x65, 0x07, 0x00, 0x00, 0x00, 0x16, 0x49, 0x44, + 0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0xff, 0xff, + 0x3f, 0x03, 0x03, 0x03, 0xe3, 0xb3, 0x4c, 0xb5, + 0x9b, 0x4e, 0x0b, 0x00, 0x2f, 0xa9, 0x06, 0x2f, + 0x8a, 0xd1, 0xc6, 0xb3, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, +/****************************************************************************** + *****************************************************************************/ +_test_image(PurpleImage *image, + const guint8 *adata = NULL; + g_assert(PURPLE_IS_IMAGE(image)); + bytes = purple_image_get_contents(image); + adata = g_bytes_get_data(bytes, &alen); + g_assert_cmpmem(adata, alen, edata, elen); + g_assert_cmpstr(purple_image_get_extension(image), ==, ext); + g_assert_cmpstr(purple_image_get_mimetype(image), ==, mimetype); + g_object_unref(G_OBJECT(image)); +test_image_new_from_data(void) { + PurpleImage *image = purple_image_new_from_data( +test_image_new_from_file(void) { + PurpleImage *image = NULL; + path = g_build_filename(TEST_DATA_DIR, "test-image.png", NULL); + image = purple_image_new_from_file(path, &error); + g_assert_no_error(error); + g_file_get_contents(path, &edata, &elen, &error); + g_assert_no_error(error); +/****************************************************************************** + *****************************************************************************/ +main(gint argc, gchar **argv) { + g_test_init(&argc, &argv, NULL); + g_test_add_func("/image/new-from-data", test_image_new_from_data); + g_test_add_func("/image/new-from-file", test_image_new_from_file); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/tests/test_smiley.c Sun May 28 13:26:27 2017 +0300
@@ -0,0 +1,145 @@
+ * Purple is the legal property of its developers, whose names are too + * numerous to list here. Please refer to the COPYRIGHT file distributed + * with this source distribution + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA +// $ cat test-image.png | hexdump -v -e '1 1 "0x%02x," " "' | xargs -n 8 echo +static const gsize test_image_data_len = 160; +static const guint8 test_image_data[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, + 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x08, 0x02, 0x00, 0x00, 0x00, 0xfd, 0xd4, 0x9a, + 0x73, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, + 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, + 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, + 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xe0, + 0x0a, 0x02, 0x16, 0x30, 0x22, 0x28, 0xa4, 0xc9, + 0xdd, 0x00, 0x00, 0x00, 0x1d, 0x69, 0x54, 0x58, + 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, + 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x64, 0x2e, + 0x65, 0x07, 0x00, 0x00, 0x00, 0x16, 0x49, 0x44, + 0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0xff, 0xff, + 0x3f, 0x03, 0x03, 0x03, 0xe3, 0xb3, 0x4c, 0xb5, + 0x9b, 0x4e, 0x0b, 0x00, 0x2f, 0xa9, 0x06, 0x2f, + 0x8a, 0xd1, 0xc6, 0xb3, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, +/****************************************************************************** + *****************************************************************************/ +_test_smiley(PurpleSmiley *smiley, + const guint8 *adata = NULL; + g_assert(PURPLE_IS_SMILEY(PURPLE_IMAGE(smiley))); + bytes = purple_image_get_contents(PURPLE_IMAGE(smiley)); + adata = g_bytes_get_data(bytes, &alen); + g_assert_cmpmem(adata, alen, edata, elen); + purple_image_get_extension(PURPLE_IMAGE(smiley)), + purple_image_get_mimetype(PURPLE_IMAGE(smiley)), + g_assert_cmpstr(purple_smiley_get_shortcut(smiley), ==, shortcut); + g_object_unref(G_OBJECT(smiley)); +test_smiley_new_from_data(void) { + PurpleSmiley *smiley = purple_smiley_new_from_data( +test_smiley_new_from_file(void) { + PurpleSmiley *smiley = NULL; + path = g_build_filename(TEST_DATA_DIR, "test-image.png", NULL); + smiley = purple_smiley_new("^_^", path); + g_assert_no_error(error); + g_file_get_contents(path, &edata, &elen, &error); + g_assert_no_error(error); +/****************************************************************************** + *****************************************************************************/ +main(gint argc, gchar **argv) { + g_test_init(&argc, &argv, NULL); + g_test_add_func("/smiley/new-from-data", test_smiley_new_from_data); + g_test_add_func("/smiley/new-from-file", test_smiley_new_from_file); --- a/pidgin/gtkaccount.c Thu Mar 23 19:11:37 2017 +0300
+++ b/pidgin/gtkaccount.c Sun May 28 13:26:27 2017 +0300
@@ -183,7 +183,7 @@
if (new_icon_path != NULL) {
- dialog->icon_img = purple_image_new_from_file(new_icon_path, TRUE);
+ dialog->icon_img = purple_image_new_from_file(new_icon_path, NULL); purple_debug_warning("gtkaccount", "data was not necessary");
} else if (data != NULL) {
@@ -735,7 +735,7 @@
img = purple_buddy_icons_find_account_icon(dialog->account);
- len = purple_image_get_size(img);
+ len = purple_image_get_data_size(img); data = g_memdup(purple_image_get_data(img), len);
set_dialog_icon(dialog, data, len,
@@ -1374,7 +1374,7 @@
- size_t len = purple_image_get_size(dialog->icon_img);
+ size_t len = purple_image_get_data_size(dialog->icon_img); purple_buddy_icons_set_account_icon(account,
g_memdup(purple_image_get_data(dialog->icon_img), len), len);
purple_account_set_buddy_icon_path(account,
@@ -2133,7 +2133,7 @@
path = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon");
if ((path != NULL) && (*path != '\0')) {
- img = purple_image_new_from_file(path, TRUE);
+ img = purple_image_new_from_file(path, NULL); --- a/pidgin/gtkblist.c Thu Mar 23 19:11:37 2017 +0300
+++ b/pidgin/gtkblist.c Sun May 28 13:26:27 2017 +0300
@@ -2692,7 +2692,7 @@
data = purple_image_get_data(custom_img);
- len = purple_image_get_size(custom_img);
+ len = purple_image_get_data_size(custom_img); @@ -2715,7 +2715,7 @@
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_image_get_size(custom_img) : 0);
+ custom_img ? purple_image_get_data_size(custom_img) : 0); g_object_unref(custom_img);
--- a/pidgin/gtkconv.c Thu Mar 23 19:11:37 2017 +0300
+++ b/pidgin/gtkconv.c Sun May 28 13:26:27 2017 +0300
@@ -4181,7 +4181,7 @@
g_snprintf(filename, sizeof(filename), "%s.png", stock_name);
path = g_build_filename(PURPLE_DATADIR, "pixmaps", "pidgin",
"e2ee", "16", filename, NULL);
- image = purple_image_new_from_file(path, FALSE);
+ image = purple_image_new_from_file(path, NULL); g_hash_table_insert(e2ee_stock, g_strdup(stock_name), image);
@@ -6536,14 +6536,12 @@
pidgin_conv_write_smiley(GString *out, PurpleSmiley *smiley,
PurpleConversation *conv, gpointer _proto_name)
escaped_shortcut = g_markup_escape_text(
purple_smiley_get_shortcut(smiley), -1);
- image = purple_smiley_get_image(smiley);
- uri = purple_image_store_get_uri(image);
+ uri = purple_image_store_get_uri(PURPLE_IMAGE(smiley)); g_string_append_printf(out,
"<img class=\"emoticon\" alt=\"%s\" title=\"%s\" "
@@ -6592,11 +6590,14 @@
full = g_match_info_fetch(info, 0);
if (purple_image_is_ready(image)) {
g_string_append(result, full);
alt = strstr(full, "alt=\"");
@@ -7859,7 +7860,7 @@
/* There is a custom icon for this user */
data = purple_image_get_data(custom_img);
- len = purple_image_get_size(custom_img);
+ len = purple_image_get_data_size(custom_img); --- a/pidgin/gtksmiley-manager.c Thu Mar 23 19:11:37 2017 +0300
+++ b/pidgin/gtksmiley-manager.c Sun May 28 13:26:27 2017 +0300
@@ -163,7 +163,7 @@
- image = purple_image_new_from_file(filename, TRUE);
+ image = purple_image_new_from_file(filename, NULL); @@ -249,8 +249,7 @@
if (edit_dialog->new_image == NULL) {
- edit_dialog->new_image =
- purple_smiley_get_image(edit_dialog->smiley);
+ edit_dialog->new_image = PURPLE_IMAGE(edit_dialog->smiley); g_return_if_fail(edit_dialog->new_image);
@@ -392,7 +391,7 @@
edit_dialog->filename = g_strdup(purple_image_get_path(
- purple_smiley_get_image(smiley)));
+ PURPLE_IMAGE(smiley))); gtk_entry_set_text(edit_dialog->shortcut,
purple_smiley_get_shortcut(smiley));
@@ -506,7 +505,7 @@
- image = purple_image_new_from_file(filename, TRUE);
+ image = purple_image_new_from_file(filename, NULL); purple_debug_warning("gtksmiley-manager",
"dropped file is not a valid image");
@@ -587,8 +586,7 @@
smiley_image = g_object_get_data(G_OBJECT(smiley),
"pidgin-smiley-manager-list-thumb");
if (smiley_image == NULL) {
- smiley_image = pidgin_pixbuf_from_image(
- purple_smiley_get_image(smiley));
+ smiley_image = pidgin_pixbuf_from_image(PURPLE_IMAGE(smiley)); smiley_image = pidgin_pixbuf_scale_down(smiley_image,
22, 22, GDK_INTERP_BILINEAR, TRUE);
g_object_set_data_full(G_OBJECT(smiley),
--- a/pidgin/gtkstatusbox.c Thu Mar 23 19:11:37 2017 +0300
+++ b/pidgin/gtkstatusbox.c Sun May 28 13:26:27 2017 +0300
@@ -412,7 +412,7 @@
if (filename && *filename)
- img = purple_image_new_from_file(filename, TRUE);
+ img = purple_image_new_from_file(filename, NULL); pidgin_status_box_set_buddy_icon(status_box, img);
@@ -1450,7 +1450,7 @@
/* Even if no accounts were processed, load the icon that was set. */
- img = purple_image_new_from_file(filename, TRUE);
+ img = purple_image_new_from_file(filename, NULL); pidgin_status_box_set_buddy_icon(box, img);
@@ -2191,12 +2191,12 @@
g_signal_connect(G_OBJECT(loader), "size-prepared", G_CALLBACK(pixbuf_size_prepared_cb), NULL);
if (!gdk_pixbuf_loader_write(loader,
purple_image_get_data(status_box->buddy_icon_img),
- purple_image_get_size(status_box->buddy_icon_img),
+ purple_image_get_data_size(status_box->buddy_icon_img), purple_debug_warning("gtkstatusbox",
"gdk_pixbuf_loader_write() failed with size=%"
- G_GSIZE_FORMAT ": %s", purple_image_get_size(
+ G_GSIZE_FORMAT ": %s", purple_image_get_data_size( status_box->buddy_icon_img),
error ? error->message : "(no error message)");
@@ -2205,7 +2205,7 @@
purple_debug_warning("gtkstatusbox",
"gdk_pixbuf_loader_close() failed for image of "
"size %" G_GSIZE_FORMAT ": %s",
- purple_image_get_size(status_box->buddy_icon_img),
+ purple_image_get_data_size(status_box->buddy_icon_img), error ? error->message : "(no error message)");
--- a/pidgin/gtkutils.c Thu Mar 23 19:11:37 2017 +0300
+++ b/pidgin/gtkutils.c Sun May 28 13:26:27 2017 +0300
@@ -3077,7 +3077,7 @@
pidgin_pixbuf_from_image(PurpleImage *image)
return pidgin_pixbuf_from_data(purple_image_get_data(image),
- purple_image_get_size(image));
+ purple_image_get_data_size(image)); GdkPixbuf *pidgin_pixbuf_new_from_file(const gchar *filename)
--- a/pidgin/gtkwebview.c Thu Mar 23 19:11:37 2017 +0300
+++ b/pidgin/gtkwebview.c Sun May 28 13:26:27 2017 +0300
@@ -206,7 +206,7 @@
b64 = purple_base64_encode(
purple_image_get_data(img),
- purple_image_get_size(img));
+ purple_image_get_data_size(img)); type = purple_image_get_mimetype(img);
src = g_strdup_printf("data:%s;base64,%s", type, b64);
--- a/pidgin/gtkwebviewtoolbar.c Thu Mar 23 19:11:37 2017 +0300
+++ b/pidgin/gtkwebviewtoolbar.c Sun May 28 13:26:27 2017 +0300
@@ -134,9 +134,14 @@
if (strcmp(str, "inherit") == 0) {
- return gdk_rgba_parse(color, str);
+ if (!gdk_rgba_parse(color, str)) { + /* FALSE for fully transparent color (same behavior as with "inherit") */ + return color->alpha > 0; @@ -562,7 +567,7 @@
- img = purple_image_new_from_file(filename, TRUE);
+ img = purple_image_new_from_file(filename, NULL); gchar *buf = g_strdup_printf(_("Failed to store image: %s"),
@@ -633,15 +638,13 @@
insert_smiley_text(GtkWidget *widget, PidginWebViewToolbar *toolbar)
gchar *escaped_smiley, *smiley_html;
const gchar *smiley_class;
smiley = g_object_get_data(G_OBJECT(widget), "smiley");
smiley_class = g_object_get_data(G_OBJECT(widget), "smiley-class");
- image = purple_smiley_get_image(smiley);
- image_id = purple_image_store_add(image);
+ image_id = purple_image_store_add(PURPLE_IMAGE(smiley)); escaped_smiley = g_markup_escape_text(
purple_smiley_get_shortcut(smiley), -1);
@@ -694,8 +697,7 @@
- pixbuf = pidgin_pixbuf_from_image(
- purple_smiley_get_image(smiley));
+ pixbuf = pidgin_pixbuf_from_image(PURPLE_IMAGE(smiley)); pixbuf = pidgin_pixbuf_scale_down(pixbuf,
24, 24, GDK_INTERP_BILINEAR, TRUE);
--- a/pidgin/plugins/imgupload.c Thu Mar 23 19:11:37 2017 +0300
+++ b/pidgin/plugins/imgupload.c Sun May 28 13:26:27 2017 +0300
@@ -122,7 +122,7 @@
/* TODO: make it a plain, multipart/form-data request */
img_data = purple_base64_encode(purple_image_get_data(image),
- purple_image_get_size(image));
+ purple_image_get_data_size(image)); img_data_e = g_uri_escape_string(img_data, NULL, FALSE);
req_data = g_strdup_printf("type=base64&image=%s", img_data_e);
--- a/pidgin/plugins/screencap.c Thu Mar 23 19:11:37 2017 +0300
+++ b/pidgin/plugins/screencap.c Sun May 28 13:26:27 2017 +0300
@@ -119,11 +119,11 @@
scrncap_pixbuf_to_image_cb(const gchar *buf, gsize count, GError **error,
- PurpleImage *image = PURPLE_IMAGE(_image);
+ PurpleImage *image = *(PurpleImage **)data; - purple_image_transfer_write(image, buf, count);
+ image = purple_image_new_from_data(buf, count); @@ -131,16 +131,12 @@
scrncap_pixbuf_to_image(GdkPixbuf *pixbuf)
+ PurpleImage *image = NULL; - image = purple_image_transfer_new();
- gdk_pixbuf_save_to_callback(pixbuf, scrncap_pixbuf_to_image_cb, image,
+ gdk_pixbuf_save_to_callback(pixbuf, scrncap_pixbuf_to_image_cb, &image, - purple_image_transfer_close(image);
purple_debug_error("screencap", "Failed saving an image: %s",
@@ -149,14 +145,8 @@
- if (purple_image_is_ready(image)) {
- if (purple_image_get_extension(image) == NULL) {
- purple_debug_error("screencap", "Invalid image format");
- purple_debug_error("screencap", "Image is not ready");
+ if (purple_image_get_extension(image) == NULL) { + purple_debug_error("screencap", "Invalid image format");