Gadu-Gadu: reimplementation of receiving messages

Wed, 12 Sep 2012 16:19:14 +0200

author
Tomasz Wasilczyk <tomkiewicz@cpw.pidgin.im>
date
Wed, 12 Sep 2012 16:19:14 +0200
changeset 34356
5d59fd4d5b2d
parent 34355
8a5eea657b82
child 34357
74dff2310289

Gadu-Gadu: reimplementation of receiving messages

libpurple/protocols/gg/Makefile.am file | annotate | diff | comparison | revisions
libpurple/protocols/gg/gg.c file | annotate | diff | comparison | revisions
libpurple/protocols/gg/gg.h file | annotate | diff | comparison | revisions
libpurple/protocols/gg/message-prpl.c file | annotate | diff | comparison | revisions
libpurple/protocols/gg/message-prpl.h file | annotate | diff | comparison | revisions
libpurple/protocols/gg/multilogon.c file | annotate | diff | comparison | revisions
libpurple/protocols/gg/multilogon.h file | annotate | diff | comparison | revisions
--- a/libpurple/protocols/gg/Makefile.am	Wed Sep 12 14:13:46 2012 +0200
+++ b/libpurple/protocols/gg/Makefile.am	Wed Sep 12 16:19:14 2012 +0200
@@ -70,6 +70,8 @@
 	libgadu-events.c \
 	libgaduw.h \
 	libgaduw.c \
+	message-prpl.h \
+	message-prpl.c \
 	multilogon.c \
 	multilogon.h \
 	pubdir-prpl.c \
--- a/libpurple/protocols/gg/gg.c	Wed Sep 12 14:13:46 2012 +0200
+++ b/libpurple/protocols/gg/gg.c	Wed Sep 12 16:19:14 2012 +0200
@@ -52,6 +52,7 @@
 #include "status.h"
 #include "servconn.h"
 #include "pubdir-prpl.h"
+#include "message-prpl.h"
 
 /* ---------------------------------------------------------------------- */
 
@@ -196,174 +197,6 @@
 /* ----- INTERNAL CALLBACKS --------------------------------------------- */
 /* ---------------------------------------------------------------------- */
 
-/**
- * Dispatch a message received from a buddy.
- *
- * @param gc PurpleConnection.
- * @param ev Gadu-Gadu event structure.
- *
- * Image receiving, some code borrowed from Kadu http://www.kadu.net
- */
-void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event_msg *ev, gboolean multilogon)
-{
-	GGPInfo *info = purple_connection_get_protocol_data(gc);
-	gchar *from;
-	gchar *msg;
-	gchar *tmp;
-	time_t mtime;
-	uin_t sender = ev->sender;
-
-	if (ev->message == NULL)
-	{
-		purple_debug_warning("gg", "ggp_recv_message_handler: NULL as message pointer\n");
-		return;
-	}
-
-	from = g_strdup_printf("%lu", (unsigned long int)ev->sender);
-
-	tmp = g_strdup_printf("%s", ev->message);
-	purple_str_strip_char(tmp, '\r');
-	msg = g_markup_escape_text(tmp, -1);
-	g_free(tmp);
-
-	if (ev->msgclass & GG_CLASS_QUEUED)
-		mtime = ev->time;
-	else
-		mtime = time(NULL);
-
-	/* We got richtext message */
-	if (ev->formats_length)
-	{
-		gboolean got_image = FALSE, bold = FALSE, italic = FALSE, under = FALSE;
-		char *cformats = (char *)ev->formats;
-		char *cformats_end = cformats + ev->formats_length;
-		gint increased_len = 0;
-		struct gg_msg_richtext_format *actformat;
-		struct gg_msg_richtext_image *actimage;
-		GString *message = g_string_new(msg);
-
-		purple_debug_info("gg", "ggp_recv_message_handler: richtext msg from (%s): %s %i formats\n", from, msg, ev->formats_length);
-
-		while (cformats < cformats_end)
-		{
-			gint byteoffset;
-			actformat = (struct gg_msg_richtext_format *)cformats;
-			cformats += sizeof(struct gg_msg_richtext_format);
-			byteoffset = g_utf8_offset_to_pointer(message->str, actformat->position + increased_len) - message->str;
-
-			if(actformat->position == 0 && actformat->font == 0) {
-				purple_debug_warning("gg", "ggp_recv_message_handler: bogus formatting (inc: %i)\n", increased_len);
-				continue;
-			}
-			purple_debug_info("gg", "ggp_recv_message_handler: format at pos: %i, image:%i, bold:%i, italic: %i, under:%i (inc: %i)\n",
-				actformat->position,
-				(actformat->font & GG_FONT_IMAGE) != 0,
-				(actformat->font & GG_FONT_BOLD) != 0,
-				(actformat->font & GG_FONT_ITALIC) != 0,
-				(actformat->font & GG_FONT_UNDERLINE) != 0,
-				increased_len);
-
-			if (actformat->font & GG_FONT_IMAGE)
-			{
-				const char *placeholder;
-			
-				got_image = TRUE;
-				actimage = (struct gg_msg_richtext_image*)(cformats);
-				cformats += sizeof(struct gg_msg_richtext_image);
-				purple_debug_info("gg", "ggp_recv_message_handler: image received, size: %d, crc32: %i\n", actimage->size, actimage->crc32);
-
-				/* Checking for errors, image size shouldn't be
-				 * larger than 255.000 bytes */
-				if (actimage->size > 255000) {
-					purple_debug_warning("gg", "ggp_recv_message_handler: received image large than 255 kb\n");
-					continue;
-				}
-
-				gg_image_request(info->session, ev->sender,
-					actimage->size, actimage->crc32);
-
-				placeholder = ggp_image_pending_placeholder(actimage->crc32);
-				g_string_insert(message, byteoffset, placeholder);
-				increased_len += strlen(placeholder);
-				continue;
-			}
-
-			if (actformat->font & GG_FONT_BOLD) {
-				if (bold == FALSE) {
-					g_string_insert(message, byteoffset, "<b>");
-					increased_len += 3;
-					bold = TRUE;
-				}
-			} else if (bold) {
-				g_string_insert(message, byteoffset, "</b>");
-				increased_len += 4;
-				bold = FALSE;
-			}
-
-			if (actformat->font & GG_FONT_ITALIC) {
-				if (italic == FALSE) {
-					g_string_insert(message, byteoffset, "<i>");
-					increased_len += 3;
-					italic = TRUE;
-				}
-			} else if (italic) {
-				g_string_insert(message, byteoffset, "</i>");
-				increased_len += 4;
-				italic = FALSE;
-			}
-
-			if (actformat->font & GG_FONT_UNDERLINE) {
-				if (under == FALSE) {
-					g_string_insert(message, byteoffset, "<u>");
-					increased_len += 3;
-					under = TRUE;
-				}
-			} else if (under) {
-				g_string_insert(message, byteoffset, "</u>");
-				increased_len += 4;
-				under = FALSE;
-			}
-
-			if (actformat->font & GG_FONT_COLOR) {
-				cformats += sizeof(struct gg_msg_richtext_color);
-			}
-		}
-
-		msg = message->str;
-		g_string_free(message, FALSE);
-
-		if (got_image)
-		{
-			ggp_image_got_im(gc, sender, msg, mtime);
-			return;
-		}
-	}
-
-	purple_debug_info("gg", "ggp_recv_message_handler: msg from (%s): %s (class = %d; rcpt_count = %d; multilogon = %d; chat_id = %llu)\n",
-			from, msg, ev->msgclass,
-			ev->recipients_count,
-			multilogon, ev->chat_id);
-
-	if (ev->chat_id != 0) {
-		ggp_chat_got_message(gc, ev->chat_id, msg, mtime, ev->sender);
-	} else if (multilogon) {
-		PurpleAccount *account = purple_connection_get_account(gc);
-		PurpleConversation *conv;
-		const gchar *who = ggp_uin_to_str(ev->sender); // not really sender
-		conv = purple_find_conversation_with_account(
-			PURPLE_CONV_TYPE_IM, who, account);
-		if (conv == NULL)
-			conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, who);
-		purple_conversation_write(conv, purple_account_get_username(account), msg, PURPLE_MESSAGE_SEND, mtime);
-	} else if (ev->recipients_count == 0) {
-		serv_got_im(gc, from, msg, 0, mtime);
-	} else {
-		purple_debug_fatal("gg", "ggp_recv_message_handler: not handled\n");
-	}
-	g_free(msg);
-	g_free(from);
-}
-
 static void ggp_typing_notification_handler(PurpleConnection *gc, uin_t uin, int length) {
 	gchar *from;
 
@@ -468,7 +301,7 @@
 			/* Nothing happened. */
 			break;
 		case GG_EVENT_MSG:
-			ggp_recv_message_handler(gc, &ev->event.msg, FALSE);
+			ggp_message_got(gc, &ev->event.msg);
 			break;
 		case GG_EVENT_ACK:
 			/* Changing %u to %i fixes compiler warning */
@@ -505,7 +338,7 @@
 			ggp_roster_reply(gc, &ev->event.userlist100_reply);
 			break;
 		case GG_EVENT_MULTILOGON_MSG:
-			ggp_multilogon_msg(gc, &ev->event.multilogon_msg);
+			ggp_message_got_multilogon(gc, &ev->event.multilogon_msg);
 			break;
 		case GG_EVENT_MULTILOGON_INFO:
 			ggp_multilogon_info(gc, &ev->event.multilogon_info);
--- a/libpurple/protocols/gg/gg.h	Wed Sep 12 14:13:46 2012 +0200
+++ b/libpurple/protocols/gg/gg.h	Wed Sep 12 16:19:14 2012 +0200
@@ -58,8 +58,6 @@
 	gboolean blocked;
 } ggp_buddy_data;
 
-void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event_msg *ev, gboolean multilogon);
-
 ggp_buddy_data * ggp_buddy_get_data(PurpleBuddy *buddy);
 
 #endif /* _PURPLE_GG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/gg/message-prpl.c	Wed Sep 12 16:19:14 2012 +0200
@@ -0,0 +1,140 @@
+#include "message-prpl.h"
+
+#include <debug.h>
+
+#include "chat.h"
+#include "utils.h"
+
+#define GGP_GG10_DEFAULT_FORMAT "<span style=\"color:#000000; " \
+	"font-family:'MS Shell Dlg 2'; font-size:9pt; \">"
+#define GGP_GG10_DEFAULT_FORMAT_REPLACEMENT "<span>"
+
+typedef struct
+{
+	enum
+	{
+		GGP_MESSAGE_GOT_TYPE_IM,
+		GGP_MESSAGE_GOT_TYPE_CHAT,
+		GGP_MESSAGE_GOT_TYPE_MULTILOGON
+	} type;
+
+	uin_t user;
+	gchar *text;
+	time_t time;
+	uint64_t chat_id;
+} ggp_message_got_data;
+
+static PurpleConversation * ggp_message_get_conv(PurpleConnection *gc,
+	uin_t uin);
+static void ggp_message_got_data_free(ggp_message_got_data *msg);
+static void ggp_message_got_display(PurpleConnection *gc,
+	ggp_message_got_data *msg);
+static void ggp_message_format_from_gg(ggp_message_got_data *msg,
+	const gchar *text);
+
+/**************/
+
+static PurpleConversation * ggp_message_get_conv(PurpleConnection *gc,
+	uin_t uin)
+{
+	PurpleAccount *account = purple_connection_get_account(gc);
+	PurpleConversation *conv;
+	const gchar *who = ggp_uin_to_str(uin);
+
+	conv = purple_find_conversation_with_account(
+		PURPLE_CONV_TYPE_IM, who, account);
+	if (conv)
+		return conv;
+	conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, who);
+	return conv;
+}
+
+static void ggp_message_got_data_free(ggp_message_got_data *msg)
+{
+	g_free(msg->text);
+	g_free(msg);
+}
+
+void ggp_message_got(PurpleConnection *gc, const struct gg_event_msg *ev)
+{
+	ggp_message_got_data *msg = g_new(ggp_message_got_data, 1);
+	ggp_message_format_from_gg(msg, ev->xhtml_message);
+
+	msg->time = ev->time;
+	msg->user = ev->sender;
+
+	if (ev->chat_id != 0)
+	{
+		msg->type = GGP_MESSAGE_GOT_TYPE_CHAT;
+		msg->chat_id = ev->chat_id;
+	}
+	else
+	{
+		msg->type = GGP_MESSAGE_GOT_TYPE_IM;
+	}
+
+	ggp_message_got_display(gc, msg);
+	ggp_message_got_data_free(msg);
+}
+
+void ggp_message_got_multilogon(PurpleConnection *gc, const struct gg_event_msg *ev)
+{
+	ggp_message_got_data *msg = g_new(ggp_message_got_data, 1);
+	ggp_message_format_from_gg(msg, ev->xhtml_message);
+
+	msg->time = ev->time;
+	msg->user = ev->sender; /* not really a sender*/
+	msg->type = GGP_MESSAGE_GOT_TYPE_MULTILOGON;
+
+	ggp_message_got_display(gc, msg);
+	ggp_message_got_data_free(msg);
+}
+
+static void ggp_message_got_display(PurpleConnection *gc,
+	ggp_message_got_data *msg)
+{
+	if (msg->type == GGP_MESSAGE_GOT_TYPE_IM)
+	{
+		serv_got_im(gc, ggp_uin_to_str(msg->user), msg->text,
+			PURPLE_MESSAGE_RECV, msg->time);
+	}
+	else if (msg->type == GGP_MESSAGE_GOT_TYPE_CHAT)
+	{
+		ggp_chat_got_message(gc, msg->chat_id, msg->text, msg->time,
+			msg->user);
+	}
+	else if (msg->type == GGP_MESSAGE_GOT_TYPE_MULTILOGON)
+	{
+		PurpleConversation *conv = ggp_message_get_conv(gc, msg->user);
+		const gchar *me = purple_account_get_username(
+			purple_connection_get_account(gc));
+
+		purple_conversation_write(conv, me, msg->text,
+			PURPLE_MESSAGE_SEND, msg->time);
+	}
+	else
+		purple_debug_error("gg", "ggp_message_got_display: "
+			"unexpected message type: %d\n", msg->type);
+}
+
+static void ggp_message_format_from_gg(ggp_message_got_data *msg,
+	const gchar *text)
+{
+	gchar *text_new, *tmp;
+
+	if (text == NULL)
+	{
+		msg->text = g_strdup("");
+		return;
+	}
+
+	text_new = g_strdup(text);
+	purple_str_strip_char(text_new, '\r');
+
+	tmp = text_new;
+	text_new = purple_strreplace(text_new, GGP_GG10_DEFAULT_FORMAT,
+		GGP_GG10_DEFAULT_FORMAT_REPLACEMENT);
+	g_free(tmp);
+
+	msg->text = text_new;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/gg/message-prpl.h	Wed Sep 12 16:19:14 2012 +0200
@@ -0,0 +1,11 @@
+#ifndef _GGP_MESSAGE_PRPL_H
+#define _GGP_MESSAGE_PRPL_H
+
+#include <internal.h>
+#include <libgadu.h>
+
+void ggp_message_got(PurpleConnection *gc, const struct gg_event_msg *ev);
+void ggp_message_got_multilogon(PurpleConnection *gc,
+	const struct gg_event_msg *ev);
+
+#endif /* _GGP_MESSAGE_PRPL_H */
--- a/libpurple/protocols/gg/multilogon.c	Wed Sep 12 14:13:46 2012 +0200
+++ b/libpurple/protocols/gg/multilogon.c	Wed Sep 12 16:19:14 2012 +0200
@@ -24,7 +24,7 @@
  *
  * 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301 USA
  */
 
 #include "multilogon.h"
@@ -32,6 +32,8 @@
 #include <debug.h>
 
 #include "gg.h"
+#include "utils.h"
+#include "message-prpl.h"
 
 struct _ggp_multilogon_session_data
 {
@@ -54,7 +56,8 @@
 {
 	GGPInfo *accdata = purple_connection_get_protocol_data(gc);
 	
-	ggp_multilogon_session_data *mldata = g_new0(ggp_multilogon_session_data, 1);
+	ggp_multilogon_session_data *mldata =
+		g_new0(ggp_multilogon_session_data, 1);
 	accdata->multilogon_data = mldata;
 }
 
@@ -64,11 +67,6 @@
 	g_free(mldata);
 }
 
-void ggp_multilogon_msg(PurpleConnection *gc, struct gg_event_msg *msg)
-{
-	ggp_recv_message_handler(gc, msg, TRUE);
-}
-
 void ggp_multilogon_info(PurpleConnection *gc,
 	struct gg_event_multilogon_info *info)
 {
--- a/libpurple/protocols/gg/multilogon.h	Wed Sep 12 14:13:46 2012 +0200
+++ b/libpurple/protocols/gg/multilogon.h	Wed Sep 12 16:19:14 2012 +0200
@@ -38,7 +38,6 @@
 void ggp_multilogon_setup(PurpleConnection *gc);
 void ggp_multilogon_cleanup(PurpleConnection *gc);
 
-void ggp_multilogon_msg(PurpleConnection *gc, struct gg_event_msg *msg);
 void ggp_multilogon_info(PurpleConnection *gc,
 	struct gg_event_multilogon_info *msg);
 

mercurial