/soc/2012/tomkiewicz/gg: 3f18ba8aed0f: Gadu-Gadu sending images ...
Tomasz Wasilczyk
tomkiewicz at cpw.pidgin.im
Thu Jul 5 13:31:51 EDT 2012
Changeset: 3f18ba8aed0fc12d15a098a27205000aa08c2a80
Author: Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date: 2012-06-27 23:25 +0200
Branch: soc.2012.gg
URL: http://hg.pidgin.im/soc/2012/tomkiewicz/gg/rev/3f18ba8aed0f
Description:
Gadu-Gadu sending images refactoring; notify about too large images
diffstat:
libpurple/protocols/gg/gg.c | 110 ++++++++++++++++------------------------
libpurple/protocols/gg/image.c | 96 ++++++++++++++++++++++++++++++++++-
libpurple/protocols/gg/image.h | 13 ++++
3 files changed, 150 insertions(+), 69 deletions(-)
diffs (truncated from 305 to 300 lines):
diff --git a/libpurple/protocols/gg/gg.c b/libpurple/protocols/gg/gg.c
--- a/libpurple/protocols/gg/gg.c
+++ b/libpurple/protocols/gg/gg.c
@@ -1631,32 +1631,6 @@
g_free(from);
}
-/* TODO: image */
-static void ggp_send_image_handler(PurpleConnection *gc, const struct gg_event *ev)
-{
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- PurpleStoredImage *image;
- gint imgid = GPOINTER_TO_INT(g_hash_table_lookup(info->image_data.pending_images, GINT_TO_POINTER(ev->event.image_request.crc32)));
-
- purple_debug_info("gg", "ggp_send_image_handler: image request received, crc32: %u, imgid: %d\n", ev->event.image_request.crc32, imgid);
-
- if(imgid)
- {
- if((image = purple_imgstore_find_by_id(imgid))) {
- gint image_size = purple_imgstore_get_size(image);
- gconstpointer image_bin = purple_imgstore_get_data(image);
- const char *image_filename = purple_imgstore_get_filename(image);
-
- purple_debug_info("gg", "ggp_send_image_handler: sending image imgid: %i, crc: %u\n", imgid, ev->event.image_request.crc32);
- gg_image_reply(info->session, (unsigned long int)ev->event.image_request.sender, image_filename, image_bin, image_size);
- purple_imgstore_unref(image);
- } else {
- purple_debug_error("gg", "ggp_send_image_handler: image imgid: %i, crc: %u in hash but not found in imgstore!\n", imgid, ev->event.image_request.crc32);
- }
- g_hash_table_remove(info->image_data.pending_images, GINT_TO_POINTER(ev->event.image_request.crc32));
- }
-}
-
static void ggp_typing_notification_handler(PurpleConnection *gc, uin_t uin, int length) {
gchar *from;
@@ -1771,7 +1745,7 @@
ggp_image_recv(gc, &ev->event.image_reply);
break;
case GG_EVENT_IMAGE_REQUEST:
- ggp_send_image_handler(gc, ev);
+ ggp_image_send(gc, &ev->event.image_request);
break;
case GG_EVENT_NOTIFY:
case GG_EVENT_NOTIFY_DESCR:
@@ -2383,54 +2357,58 @@
GString *string_buffer = g_string_new(NULL);
struct gg_msg_richtext fmt;
- do {
- PurpleStoredImage *image;
- const char *id;
+ do
+ {
+ const char *id = g_datalist_get_data(&attribs, "id");
+ struct gg_msg_richtext_format actformat;
+ struct gg_msg_richtext_image actimage;
+ ggp_image_prepare_result prepare_result;
/* Add text before the image */
- if(start - last) {
+ if(start - last)
+ {
pos = pos + g_utf8_strlen(last, start - last);
- g_string_append_len(string_buffer, last, start - last);
+ g_string_append_len(string_buffer, last,
+ start - last);
}
-
- /* TODO: image */
- if((id = g_datalist_get_data(&attribs, "id")) && (image = purple_imgstore_find_by_id(atoi(id)))) {
- struct gg_msg_richtext_format actformat;
- struct gg_msg_richtext_image actimage;
- gint image_size = purple_imgstore_get_size(image);
- gconstpointer image_bin = purple_imgstore_get_data(image);
- const char *image_filename = purple_imgstore_get_filename(image);
- uint32_t crc32 = gg_crc32(0, image_bin, image_size);
-
- g_hash_table_insert(info->image_data.pending_images, GINT_TO_POINTER(crc32), GINT_TO_POINTER(atoi(id)));
- purple_imgstore_ref(image);
- purple_debug_info("gg", "ggp_send_im_richtext: got crc: %u for imgid: %i\n", crc32, atoi(id));
-
+ last = end + 1;
+
+ if (id == NULL)
+ {
+ g_datalist_clear(&attribs);
+ continue;
+ }
+
+ /* add the image itself */
+ prepare_result = ggp_image_prepare(
+ gc, atoi(id), &actimage);
+ if (prepare_result == GGP_IMAGE_PREPARE_OK)
+ {
actformat.font = GG_FONT_IMAGE;
actformat.position = pos;
- actimage.unknown1 = 0x0109;
- actimage.size = gg_fix32(image_size);
- actimage.crc32 = gg_fix32(crc32);
-
- if (actimage.size > 255000) {
- purple_debug_warning("gg", "ggp_send_im_richtext: image over 255kb!\n");
- } else {
- purple_debug_info("gg", "ggp_send_im_richtext: adding images to richtext, size: %i, crc32: %u, name: %s\n", actimage.size, actimage.crc32, image_filename);
-
- memcpy(format + format_length, &actformat, sizeof(actformat));
- format_length += sizeof(actformat);
- memcpy(format + format_length, &actimage, sizeof(actimage));
- format_length += sizeof(actimage);
- }
- } else {
- purple_debug_error("gg", "ggp_send_im_richtext: image not found in the image store!");
+ memcpy(format + format_length, &actformat,
+ sizeof(actformat));
+ format_length += sizeof(actformat);
+ memcpy(format + format_length, &actimage,
+ sizeof(actimage));
+ format_length += sizeof(actimage);
}
-
- last = end + 1;
+ else if (prepare_result == GGP_IMAGE_PREPARE_TOO_BIG)
+ {
+ PurpleConversation *conv =
+ purple_find_conversation_with_account(
+ PURPLE_CONV_TYPE_IM, who,
+ purple_connection_get_account(gc));
+ purple_conversation_write(conv, "",
+ _("Image is too large, please try "
+ "smaller one."), PURPLE_MESSAGE_ERROR,
+ time(NULL));
+ }
+
g_datalist_clear(&attribs);
-
- } while(purple_markup_find_tag("img", last, &start, &end, &attribs));
+ } while (purple_markup_find_tag("img", last, &start, &end,
+ &attribs));
/* Add text after the images */
if(last && *last) {
diff --git a/libpurple/protocols/gg/image.c b/libpurple/protocols/gg/image.c
--- a/libpurple/protocols/gg/image.c
+++ b/libpurple/protocols/gg/image.c
@@ -34,8 +34,7 @@
ggp_image_connection_data *imgdata = ggp_image_get_imgdata(gc);
imgdata->pending_messages = NULL;
- imgdata->pending_images =
- g_hash_table_new(g_direct_hash, g_direct_equal);
+ imgdata->pending_images = g_hash_table_new(NULL, NULL);
}
void ggp_image_free(PurpleConnection *gc)
@@ -44,7 +43,7 @@
g_list_free_full(imgdata->pending_messages,
&ggp_image_pending_message_free);
- g_hash_table_destroy(imgdata->pending_images); // TODO: remove content
+ g_hash_table_destroy(imgdata->pending_images);
}
const char * ggp_image_pending_placeholder(uint32_t id)
@@ -75,6 +74,50 @@
pending_message);
}
+ggp_image_prepare_result ggp_image_prepare(PurpleConnection *gc, const int id,
+ struct gg_msg_richtext_image *image_info)
+{
+ ggp_image_connection_data *imgdata = ggp_image_get_imgdata(gc);
+ PurpleStoredImage *image = purple_imgstore_find_by_id(id);
+ size_t image_size;
+ gconstpointer image_data;
+ const char *image_filename;
+ uint32_t image_crc;
+
+ if (!image)
+ {
+ purple_debug_error("gg", "ggp_image_prepare_to_send: image %d "
+ "not found in image store\n", id);
+ return GGP_IMAGE_PREPARE_FAILURE;
+ }
+
+ image_size = purple_imgstore_get_size(image);
+
+ if (image_size > GGP_IMAGE_SIZE_MAX)
+ {
+ purple_debug_warning("gg", "ggp_image_prepare_to_send: image "
+ "is too big (max bytes: %d)\n", GGP_IMAGE_SIZE_MAX);
+ return GGP_IMAGE_PREPARE_TOO_BIG;
+ }
+
+ purple_imgstore_ref(image);
+ image_data = purple_imgstore_get_data(image);
+ image_filename = purple_imgstore_get_filename(image);
+ image_crc = gg_crc32(0, image_data, image_size);
+
+ purple_debug_info("gg", "ggp_image_prepare_to_send: image prepared "
+ "[id=%d, crc=%u, size=%d, filename=%s]\n",
+ id, image_crc, image_size, image_filename);
+ g_hash_table_insert(imgdata->pending_images, GINT_TO_POINTER(image_crc),
+ GINT_TO_POINTER(id));
+
+ image_info->unknown1 = 0x0109;
+ image_info->size = gg_fix32(image_size);
+ image_info->crc32 = gg_fix32(image_crc);
+
+ return GGP_IMAGE_PREPARE_OK;
+}
+
void ggp_image_recv(PurpleConnection *gc,
const struct gg_event_image_reply *image_reply)
{
@@ -140,3 +183,50 @@
}
g_free(imgtag_replace);
}
+
+void ggp_image_send(PurpleConnection *gc,
+ const struct gg_event_image_request *image_request)
+{
+ GGPInfo *accdata = purple_connection_get_protocol_data(gc);
+ ggp_image_connection_data *imgdata = ggp_image_get_imgdata(gc);
+ int stored_id;
+ PurpleStoredImage *image;
+
+ stored_id = GPOINTER_TO_INT(g_hash_table_lookup(imgdata->pending_images,
+ GINT_TO_POINTER(image_request->crc32)));
+
+ purple_debug_info("gg", "ggp_image_send: got image request "
+ "[id=%d, uin=%u, crc=%u, size=%u]\n",
+ stored_id,
+ image_request->sender,
+ image_request->crc32,
+ image_request->size);
+
+ if (!stored_id)
+ {
+ purple_debug_warning("gg", "ggp_image_send: requested image "
+ "not found\n");
+ return;
+ }
+
+ g_hash_table_remove(imgdata->pending_images,
+ GINT_TO_POINTER(image_request->crc32));
+
+ image = purple_imgstore_find_by_id(stored_id);
+
+ if (!image)
+ {
+ purple_debug_error("gg", "ggp_image_send: requested image "
+ "found, but doesn't exists in image store\n");
+ return;
+ }
+
+ //TODO: check sender
+ gg_image_reply(accdata->session, image_request->sender,
+ purple_imgstore_get_filename(image),
+ purple_imgstore_get_data(image),
+ purple_imgstore_get_size(image));
+ purple_imgstore_unref(image);
+
+ purple_debug_misc("gg", "ggp_image_send: image sent\n");
+}
diff --git a/libpurple/protocols/gg/image.h b/libpurple/protocols/gg/image.h
--- a/libpurple/protocols/gg/image.h
+++ b/libpurple/protocols/gg/image.h
@@ -4,12 +4,21 @@
#include <internal.h>
#include <libgadu.h>
+#define GGP_IMAGE_SIZE_MAX 255000
+
typedef struct
{
GList *pending_messages;
GHashTable *pending_images;
} ggp_image_connection_data;
+typedef enum
+{
+ GGP_IMAGE_PREPARE_OK = 0,
+ GGP_IMAGE_PREPARE_FAILURE,
+ GGP_IMAGE_PREPARE_TOO_BIG
+} ggp_image_prepare_result;
+
void ggp_image_setup(PurpleConnection *gc);
void ggp_image_free(PurpleConnection *gc);
@@ -17,8 +26,12 @@
void ggp_image_got_im(PurpleConnection *gc, uin_t from, gchar *msg,
time_t mtime);
+ggp_image_prepare_result ggp_image_prepare(PurpleConnection *gc, const int id,
+ struct gg_msg_richtext_image *image_info);
void ggp_image_recv(PurpleConnection *gc,
More information about the Commits
mailing list