diff src/protocols/msn/msg.c @ 9193:502707ca1836

[gaim-migrate @ 9988] Patch by Felipe Contreras to add MSN file transfer and buddy icons. Please test and report any bugs! committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Sun, 06 Jun 2004 02:39:08 +0000
parents c30d81b4dd22
children ab6636c5a136
line wrap: on
line diff
--- a/src/protocols/msn/msg.c	Sun Jun 06 02:16:08 2004 +0000
+++ b/src/protocols/msn/msg.c	Sun Jun 06 02:39:08 2004 +0000
@@ -22,38 +22,6 @@
 #include "msn.h"
 #include "msg.h"
 
-#define GET_NEXT(tmp) \
-	while (*(tmp) && *(tmp) != ' ' && *(tmp) != '\r') \
-		(tmp)++; \
-	if (*(tmp) != '\0') *(tmp)++ = '\0'; \
-	if (*(tmp) == '\n') (tmp)++; \
-	while (*(tmp) && *(tmp) == ' ') \
-		(tmp)++
-
-#define GET_NEXT_LINE(tmp) \
-	while (*(tmp) && *(tmp) != '\r') \
-		(tmp)++; \
-	if (*(tmp) != '\0') *(tmp)++ = '\0'; \
-	if (*(tmp) == '\n') (tmp)++
-
-
-#define msn_put16(buf, data) ( \
-		(*(buf) = (unsigned char)((data)>>8)&0xff), \
-		(*((buf)+1) = (unsigned char)(data)&0xff),  \
-		2)
-#define msn_get16(buf) ((((*(buf))<<8)&0xff00) + ((*((buf)+1)) & 0xff))
-#define msn_put32(buf, data) ( \
-		(*((buf)) = (unsigned char)((data)>>24)&0xff), \
-		(*((buf)+1) = (unsigned char)((data)>>16)&0xff), \
-		(*((buf)+2) = (unsigned char)((data)>>8)&0xff), \
-		(*((buf)+3) = (unsigned char)(data)&0xff), \
-		4)
-#define msn_get32(buf) ((((*(buf))<<24)&0xff000000) + \
-		(((*((buf)+1))<<16)&0x00ff0000) + \
-		(((*((buf)+2))<< 8)&0x0000ff00) + \
-		(((*((buf)+3)    )&0x000000ff)))
-
-
 MsnMessage *
 msn_message_new(void)
 {
@@ -107,27 +75,36 @@
 	return msg;
 }
 
-MsnMessage *
-msn_message_new_msnslp_ack(MsnMessage *acked_msg)
+void
+msn_message_parse_slp_body(MsnMessage *msg, const char *body, size_t len)
 {
-	MsnMessage *msg;
+	MsnSlpHeader header;
+	const char *tmp;
 
-	g_return_val_if_fail(acked_msg != NULL, NULL);
-	g_return_val_if_fail(acked_msg->msnslp_message, NULL);
+	tmp = body;
 
-	msg = msn_message_new_msnslp();
+	/* Import the header. */
+	memcpy(&header, tmp, sizeof(header));
+	tmp += sizeof(header);
 
-	msg->msnslp_ack_message = TRUE;
-	msg->acked_msg = msn_message_ref(acked_msg);
+	msg->msnslp_header.session_id = GUINT32_FROM_LE(header.session_id);
+	msg->msnslp_header.id         = GUINT32_FROM_LE(header.id);
+	msg->msnslp_header.offset     = GUINT64_FROM_LE(header.offset);
+	msg->msnslp_header.total_size = GUINT64_FROM_LE(header.total_size);
+	msg->msnslp_header.length     = GUINT32_FROM_LE(header.length);
+	msg->msnslp_header.flags      = GUINT32_FROM_LE(header.flags);
+	msg->msnslp_header.ack_id     = GUINT32_FROM_LE(header.ack_id);
+	msg->msnslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id);
+	msg->msnslp_header.ack_size   = GUINT64_FROM_LE(header.ack_size);
+	
+	/* Import the body. */
+	/* msg->body_len = msg->msnslp_header.length; */
+	msg->body_len = len - (tmp - body);
+	
+	if (msg->body_len > 0)
+		msg->body = g_memdup(tmp, msg->body_len);
 
-	msg->msnslp_header.session_id  = acked_msg->msnslp_header.session_id;
-	msg->msnslp_header.total_size  = acked_msg->msnslp_header.total_size;
-	msg->msnslp_header.flags       = 0x02;
-	msg->msnslp_header.ack_id      = acked_msg->msnslp_header.id;
-	msg->msnslp_header.ack_sub_id  = acked_msg->msnslp_header.ack_id;
-	msg->msnslp_header.ack_size    = acked_msg->msnslp_header.total_size;
-
-	return msg;
+	tmp += msg->body_len;
 }
 
 void
@@ -136,33 +113,36 @@
 {
 	char *tmp_base, *tmp;
 	const char *content_type;
+	char *end;
+	char **elems, **cur, **tokens;
 
 	g_return_if_fail(payload != NULL);
 
-	tmp_base = tmp = g_memdup(payload, payload_len);
+	tmp_base = tmp = g_memdup(payload, payload_len + 1);
+	tmp[payload_len] = '\0';
 
-	/* Back to the parsination. */
-	while (*tmp != '\r')
-	{
-		char *key, *value, *c;
+	/* Parse the attributes. */
+	end = strstr(tmp, "\r\n\r\n");
+	g_return_if_fail(end != NULL);
+	*end = '\0';
 
-		key = tmp;
+	elems = g_strsplit(tmp, "\r\n", 0);
 
-		GET_NEXT(tmp); /* Key */
-
-		value = tmp;
+	for (cur = elems; *cur != NULL; cur++)
+	{
+		const char *key, *value;
 
-		GET_NEXT_LINE(tmp); /* Value */
+		tokens = g_strsplit(*cur, ": ", 2);
 
-		if ((c = strchr(key, ':')) != NULL)
-			*c = '\0';
+		key = tokens[0];
+		value = tokens[1];
 
-		if (!g_ascii_strcasecmp(key, "MIME-Version"))
+		if (!strcmp(key, "MIME-Version"))
 			continue;
 
-		if (!g_ascii_strcasecmp(key, "Content-Type"))
+		if (!strcmp(key, "Content-Type"))
 		{
-			char *charset;
+			char *charset, *c;
 
 			if ((c = strchr(value, ';')) != NULL)
 			{
@@ -178,11 +158,16 @@
 			msn_message_set_content_type(msg, value);
 		}
 		else
+		{
 			msn_message_set_attr(msg, key, value);
+		}
+
+		g_strfreev(tokens);
 	}
 
-	/* "\r\n" */
-	tmp += 2;
+	g_strfreev(elems);
+
+	tmp = end + 4;
 
 	/* Now we *should* be at the body. */
 	content_type = msn_message_get_content_type(msg);
@@ -200,9 +185,9 @@
 		tmp += sizeof(header);
 
 		msg->msnslp_header.session_id = GUINT32_FROM_LE(header.session_id);
-		msg->msnslp_header.id         = GUINT64_FROM_LE(header.id);
+		msg->msnslp_header.id         = GUINT32_FROM_LE(header.id);
 		msg->msnslp_header.offset     = GUINT64_FROM_LE(header.offset);
-		msg->msnslp_header.total_size = GUINT32_FROM_LE(header.total_size);
+		msg->msnslp_header.total_size = GUINT64_FROM_LE(header.total_size);
 		msg->msnslp_header.length     = GUINT32_FROM_LE(header.length);
 		msg->msnslp_header.flags      = GUINT32_FROM_LE(header.flags);
 		msg->msnslp_header.ack_id     = GUINT32_FROM_LE(header.ack_id);
@@ -230,8 +215,22 @@
 	}
 
 	g_free(tmp_base);
+}
 
-	/* Done! */
+MsnMessage *
+msn_message_new_from_cmd(MsnSession *session, MsnCommand *cmd)
+{
+	MsnMessage *msg;
+
+	g_return_val_if_fail(cmd != NULL, NULL);
+
+	msg = msn_message_new();
+
+	msg->remote_user = g_strdup(cmd->params[0]);
+	/* msg->size = atoi(cmd->params[2]); */
+	msg->cmd = cmd;
+
+	return msg;
 }
 
 void
@@ -246,6 +245,9 @@
 		return;
 	}
 
+	if (msg->remote_user != NULL)
+		g_free(msg->remote_user);
+
 	if (msg->body != NULL)
 		g_free(msg->body);
 
@@ -258,9 +260,6 @@
 	g_hash_table_destroy(msg->attr_table);
 	g_list_free(msg->attr_list);
 
-	if (msg->msnslp_ack_message)
-		msn_message_unref(msg->acked_msg);
-
 	g_free(msg);
 }
 
@@ -284,7 +283,8 @@
 
 	msg->ref_count--;
 
-	if (msg->ref_count == 0) {
+	if (msg->ref_count == 0) 
+	{
 		msn_message_destroy(msg);
 
 		return NULL;
@@ -294,7 +294,49 @@
 }
 
 char *
-msn_message_gen_payload(const MsnMessage *msg, size_t *ret_size)
+msn_message_gen_slp_body(MsnMessage *msg, size_t *ret_size)
+{
+	MsnSlpHeader header;
+
+	char *tmp, *base;
+	const void *body;
+	size_t len, body_len;
+
+	g_return_val_if_fail(msg != NULL, NULL);
+
+	len = MSN_BUF_LEN;
+
+	base = tmp = g_malloc(len + 1);
+
+	body = msn_message_get_bin_data(msg, &body_len);
+
+	header.session_id = GUINT32_TO_LE(msg->msnslp_header.session_id);
+	header.id         = GUINT32_TO_LE(msg->msnslp_header.id);
+	header.offset     = GUINT64_TO_LE(msg->msnslp_header.offset);
+	header.total_size = GUINT64_TO_LE(msg->msnslp_header.total_size);
+	header.length     = GUINT32_TO_LE(msg->msnslp_header.length);
+	header.flags      = GUINT32_TO_LE(msg->msnslp_header.flags);
+	header.ack_id     = GUINT32_TO_LE(msg->msnslp_header.ack_id);
+	header.ack_sub_id = GUINT32_TO_LE(msg->msnslp_header.ack_sub_id);
+	header.ack_size   = GUINT64_TO_LE(msg->msnslp_header.ack_size);
+
+	memcpy(tmp, &header, 48);
+	tmp += 48;
+
+	if (body != NULL)
+	{
+		memcpy(tmp, body, body_len);
+		tmp += body_len;
+	}
+
+	if (ret_size != NULL)
+		*ret_size = tmp - base;
+	
+	return base;
+}
+
+char *
+msn_message_gen_payload(MsnMessage *msg, size_t *ret_size)
 {
 	GList *l;
 	char *n, *base, *end;
@@ -349,9 +391,9 @@
 		MsnSlpFooter footer;
 
 		header.session_id = GUINT32_TO_LE(msg->msnslp_header.session_id);
-		header.id         = GUINT64_TO_LE(msg->msnslp_header.id);
+		header.id         = GUINT32_TO_LE(msg->msnslp_header.id);
 		header.offset     = GUINT64_TO_LE(msg->msnslp_header.offset);
-		header.total_size = GUINT32_TO_LE(msg->msnslp_header.total_size);
+		header.total_size = GUINT64_TO_LE(msg->msnslp_header.total_size);
 		header.length     = GUINT32_TO_LE(msg->msnslp_header.length);
 		header.flags      = GUINT32_TO_LE(msg->msnslp_header.flags);
 		header.ack_id     = GUINT32_TO_LE(msg->msnslp_header.ack_id);
@@ -364,6 +406,7 @@
 		if (body != NULL)
 		{
 			memcpy(n, body, body_len);
+
 			n += body_len;
 		}
 
@@ -383,10 +426,10 @@
 
 	if (ret_size != NULL)
 	{
-		*ret_size = n - base;
-
 		if (*ret_size > 1664)
 			*ret_size = 1664;
+
+		*ret_size = n - base;
 	}
 
 	return base;
@@ -452,10 +495,7 @@
 	if (msg->content_type != NULL)
 		g_free(msg->content_type);
 
-	if (type != NULL)
-		msg->content_type = g_strdup(type);
-	else
-		msg->content_type = NULL;
+	msg->content_type = (type != NULL) ? g_strdup(type) : NULL;
 }
 
 const char *
@@ -474,10 +514,7 @@
 	if (msg->charset != NULL)
 		g_free(msg->charset);
 
-	if (charset != NULL)
-		msg->charset = g_strdup(charset);
-	else
-		msg->charset = NULL;
+	msg->charset = (charset != NULL) ? g_strdup(charset) : NULL;
 }
 
 const char *
@@ -542,37 +579,135 @@
 msn_message_get_hashtable_from_body(const MsnMessage *msg)
 {
 	GHashTable *table;
-	char *body, *s, *c;
+	const char *body;
+	char **elems, **cur, **tokens;
 
 	g_return_val_if_fail(msg != NULL, NULL);
 
-	s = body = g_strdup(msn_message_get_bin_data(msg, NULL));
-
-	g_return_val_if_fail(body != NULL, NULL);
-
 	table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
 
-	while (*s != '\r' && *s != '\0')
+	body = msn_message_get_bin_data(msg, NULL);
+
+	g_return_val_if_fail(body != NULL, NULL);
+
+	elems = g_strsplit(body, "\r\n", 0);
+
+	for (cur = elems; *cur != NULL; cur++)
 	{
-		char *key, *value;
+		if (**cur == '\0')
+			break;
+
+		tokens = g_strsplit(*cur, ": ", 2);
+
+		if (tokens[0] != NULL && tokens[1] != NULL)
+			g_hash_table_insert(table, tokens[0], tokens[1]);
+
+		g_free(tokens);
+	}
+
+	g_strfreev(elems);
+
+	return table;
+}
 
-		key = s;
+void
+msn_message_show_readable(MsnMessage *msg, const char *info,
+						  gboolean text_body)
+{
+	GString *str;
+	size_t body_len;
+	const char *body;
+	GList *l;
+
+	g_return_if_fail(msg != NULL);
+
+	str = g_string_new(NULL);
 
-		GET_NEXT(s);
+	/* Standard header. */
+	if (msg->charset == NULL)
+	{
+		g_string_append_printf(str,
+				   "MIME-Version: 1.0\r\n"
+				   "Content-Type: %s\r\n",
+				   msg->content_type);
+	}
+	else
+	{
+		g_string_append_printf(str,
+				   "MIME-Version: 1.0\r\n"
+				   "Content-Type: %s; charset=%s\r\n",
+				   msg->content_type, msg->charset);
+	}
+
+	for (l = msg->attr_list; l; l = l->next)
+	{
+		char *key;
+		const char *value;
 
-		value = s;
+		key = l->data;
+		value = msn_message_get_attr(msg, key);
+
+		g_string_append_printf(str, "%s: %s\r\n", key, value);
+	}
+
+	g_string_append(str, "\r\n");
+	
+	body = msn_message_get_bin_data(msg, &body_len);
 
-		GET_NEXT_LINE(s);
+	if (msg->msnslp_message)
+	{
+		g_string_append_printf(str, "%u ", msg->msnslp_header.session_id);
+		g_string_append_printf(str, "%u ", msg->msnslp_header.id);
+		g_string_append_printf(str, "%llu ", msg->msnslp_header.offset);
+		g_string_append(str, "\r\n");
+		g_string_append_printf(str, "%llu ",
+							   msg->msnslp_header.total_size);
+		g_string_append_printf(str, "%u ", msg->msnslp_header.length);
+		g_string_append_printf(str, "%u ", msg->msnslp_header.flags);
+		g_string_append(str, "\r\n");
+		g_string_append_printf(str, "%u ", msg->msnslp_header.ack_id);
+		g_string_append_printf(str, "%u ", msg->msnslp_header.ack_sub_id);
+		g_string_append_printf(str, "%lld ", msg->msnslp_header.ack_size);
+		g_string_append(str, "\r\n");
 
-		if ((c = strchr(key, ':')) != NULL)
+		if (body != NULL)
 		{
-			*c = '\0';
-
-			g_hash_table_insert(table, g_strdup(key), g_strdup(value));
+			if (text_body)
+			{
+				g_string_append_len(str, body, body_len);
+				if (body[body_len - 1] == '\0')
+				{
+					str->len--;
+					g_string_append(str, " 0x00");
+				}
+				g_string_append(str, "\r\n");
+			}
+			else
+			{
+				int i;
+				for (i = 0; i < msg->body_len; i++)
+				{
+					g_string_append_printf(str, "%.2hhX ", body[i]);
+					if ((i % 16) == 15)
+						g_string_append(str, "\r\n");
+				}
+				g_string_append(str, "\r\n");
+			}
+		}
+		
+		g_string_append_printf(str, "%u ", msg->msnslp_footer.value);
+		g_string_append(str, "\r\n");
+	}
+	else
+	{
+		if (body != NULL)
+		{
+			g_string_append_len(str, body, body_len);
+			g_string_append(str, "\r\n");
 		}
 	}
 
-	g_free(body);
-
-	return table;
+	gaim_debug_info("msn", "Message %s:\n{%s}\n", info, str->str);
+	
+	g_string_free(str, TRUE);
 }