/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