changeset 7590:3a48ade4f510

[gaim-migrate @ 8208] The MSNSLP stuff pretty much works. I have it disabled in this commit just in case, but I should have the rest done tonight. Also, client IDs are now sent (which was part of the problem), as are the MSNObjects (the other half of the problem). committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Sat, 22 Nov 2003 00:47:24 +0000
parents 59c1cee97cbb
children 24b9b6405f36
files src/protocols/msn/msg.c src/protocols/msn/msn.c src/protocols/msn/msn.h src/protocols/msn/msnslp.c src/protocols/msn/notification.c src/protocols/msn/session.c src/protocols/msn/session.h src/protocols/msn/user.c src/protocols/msn/user.h
diffstat 9 files changed, 209 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/msn/msg.c	Fri Nov 21 18:12:55 2003 +0000
+++ b/src/protocols/msn/msg.c	Sat Nov 22 00:47:24 2003 +0000
@@ -157,11 +157,14 @@
 	GET_NEXT(tmp); /* Skip the username or flag */
 	msg->size = atoi(tmp);
 
+#if 0
+	/* Put this back when we intelligently handle binary strings. */
 	if (msg->size != strlen(strchr(str, '\n') + 1)) {
 		gaim_debug(GAIM_DEBUG_ERROR, "msn",
 				   "Incoming message size (%d) and string length (%d) "
 				   "do not match!\n", msg->size, strlen(str));
 	}
+#endif
 
 	/*
 	 * We're going to make sure this is incoming by checking field1.
--- a/src/protocols/msn/msn.c	Fri Nov 21 18:12:55 2003 +0000
+++ b/src/protocols/msn/msn.c	Sat Nov 22 00:47:24 2003 +0000
@@ -608,16 +608,19 @@
 	MsnSession *session = gc->proto_data;
 	const char *away;
 
-	if (gc->away != NULL) {
+	if (gc->away != NULL)
+	{
 		g_free(gc->away);
 		gc->away = NULL;
 	}
 
-	if (msg != NULL) {
+	if (msg != NULL)
+	{
 		gc->away = g_strdup("");
 		away = "AWY";
 	}
-	else if (state) {
+	else if (state)
+	{
 		gc->away = g_strdup("");
 
 		if (!strcmp(state, _("Away From Computer")))
@@ -632,7 +635,8 @@
 			away = "LUN";
 		else if (!strcmp(state, _("Hidden")))
 			away = "HDN";
-		else {
+		else
+		{
 			g_free(gc->away);
 			gc->away = NULL;
 			away = "NLN";
@@ -643,10 +647,7 @@
 	else
 		away = "NLN";
 
-	if (!msn_servconn_send_command(session->notification_conn, "CHG", away)) {
-		gaim_connection_error(gc, _("Write error"));
-		return;
-	}
+	msn_session_change_status(session, away);
 }
 
 static void
@@ -657,12 +658,7 @@
 	if (gc->away != NULL)
 		return;
 
-	if (!msn_servconn_send_command(session->notification_conn, "CHG",
-								   (idle ? "IDL" : "NLN"))) {
-
-		gaim_connection_error(gc, _("Write error"));
-		return;
-	}
+	msn_session_change_status(session, (idle ? "IDL" : "NLN"));
 }
 
 static void
@@ -1234,6 +1230,17 @@
 }
 
 static void
+msn_set_buddy_icon(GaimConnection *gc, const char *filename)
+{
+	MsnSession *session = (MsnSession *)gc->proto_data;
+	MsnUser *user = session->user;
+
+	msn_user_set_buddy_icon(user, filename);
+
+	msn_session_change_status(session, session->away_state);
+}
+
+static void
 msn_remove_group(GaimConnection *gc, const char *name)
 {
 	MsnSession *session = (MsnSession *)gc->proto_data;
@@ -1605,7 +1612,7 @@
 	msn_buddy_free,
 	msn_convo_closed,
 	msn_normalize,
-	NULL,
+	msn_set_buddy_icon,
 	msn_remove_group
 };
 
--- a/src/protocols/msn/msn.h	Fri Nov 21 18:12:55 2003 +0000
+++ b/src/protocols/msn/msn.h	Sat Nov 22 00:47:24 2003 +0000
@@ -37,6 +37,7 @@
 #include "prpl.h"
 #include "request.h"
 #include "server.h"
+#include "sha.h"
 #include "sslconn.h"
 #include "util.h"
 
@@ -83,4 +84,36 @@
 
 } MsnListOp;
 
+typedef enum
+{
+	MSN_CLIENT_CAP_WIN_MOBILE = 0x01,
+	MSN_CLIENT_CAP_UNKNOWN_1  = 0x02,
+	MSN_CLIENT_CAP_VIEW_INK   = 0x04,
+	MSN_CLIENT_CAP_SEND_INK   = 0x08,
+	MSN_CLIENT_CAP_VIDEO_CHAT = 0x10,
+	MSN_CLIENT_CAP_BASE       = 0x20,
+	MSN_CLIENT_CAP_UNKNOWN_2  = 0x40,
+	MSN_CLIENT_CAP_UNKNOWN_3  = 0x80
+
+} MsnClientCaps;
+
+typedef enum
+{
+	MSN_CLIENT_VER_5_0 = 0x00,
+	MSN_CLIENT_VER_6_0 = 0x10,
+	MSN_CLIENT_VER_6_1 = 0x20
+
+} MsnClientVerId;
+
+#define MSN_CLIENT_ID_VERSION      MSN_CLIENT_VER_6_0
+#define MSN_CLIENT_ID_RESERVED_1   0x00
+#define MSN_CLIENT_ID_RESERVED_2   0x00
+#define MSN_CLIENT_ID_CAPABILITIES (MSN_CLIENT_CAP_BASE | MSN_CLIENT_CAP_VIEW_INK)
+
+#define MSN_CLIENT_ID \
+	((MSN_CLIENT_ID_VERSION    << 24) | \
+	 (MSN_CLIENT_ID_RESERVED_1 << 16) | \
+	 (MSN_CLIENT_ID_RESERVED_2 <<  8) | \
+	 (MSN_CLIENT_ID_CAPABILITIES))
+
 #endif /* _MSN_H_ */
--- a/src/protocols/msn/msnslp.c	Fri Nov 21 18:12:55 2003 +0000
+++ b/src/protocols/msn/msnslp.c	Sat Nov 22 00:47:24 2003 +0000
@@ -214,6 +214,7 @@
 	char *branch;
 	char *content;
 	char *body;
+	char *c;
 
 	g_return_if_fail(slpsession  != NULL);
 	g_return_if_fail(local_user  != NULL);
@@ -224,10 +225,8 @@
 	msnobj_base64 = gaim_base64_encode(msnobj_data, strlen(msnobj_data));
 	g_free(msnobj_data);
 
-#if 0
 	if ((c = strchr(msnobj_base64, '=')) != NULL)
 		*c = '\0';
-#endif
 
 	session_id = rand() % 0xFFFFFF00 + 4;
 
--- a/src/protocols/msn/notification.c	Fri Nov 21 18:12:55 2003 +0000
+++ b/src/protocols/msn/notification.c	Sat Nov 22 00:47:24 2003 +0000
@@ -1278,12 +1278,11 @@
 
 		if (session->num_users == session->total_users)
 		{
-			if (!msn_servconn_send_command(servconn, "CHG", "NLN"))
-			{
-				gaim_connection_error(gc, _("Unable to write"));
-
+			msn_user_set_buddy_icon(session->user,
+				gaim_account_get_buddy_icon(session->account));
+
+			if (!msn_session_change_status(session, "NLN"))
 				return FALSE;
-			}
 
 			gaim_connection_set_state(gc, GAIM_CONNECTED);
 			serv_finish_login(gc);
@@ -1446,12 +1445,8 @@
 			/* Now we're at the last one, so we can do final work. */
 			if (!session->lists_synced)
 			{
-				if (!msn_servconn_send_command(servconn, "CHG", "NLN"))
-				{
-					gaim_connection_error(gc, _("Unable to write"));
-
+				if (!msn_session_change_status(session, "NLN"))
 					return FALSE;
-				}
 
 				gaim_connection_set_state(gc, GAIM_CONNECTED);
 				serv_finish_login(gc);
--- a/src/protocols/msn/session.c	Fri Nov 21 18:12:55 2003 +0000
+++ b/src/protocols/msn/session.c	Sat Nov 22 00:47:24 2003 +0000
@@ -37,6 +37,8 @@
 	session->dispatch_server = g_strdup(server);
 	session->dispatch_port   = port;
 
+	session->away_state = NULL;
+
 	session->users  = msn_users_new();
 	session->groups = msn_groups_new();
 
@@ -93,6 +95,9 @@
 	if (session->passport_info.file != NULL)
 		g_free(session->passport_info.file);
 
+	if (session->away_state != NULL)
+		g_free(session->away_state);
+
 	g_free(session);
 }
 
@@ -155,8 +160,8 @@
 
 	g_return_val_if_fail(session != NULL, NULL);
 
-	if (msn_servconn_send_command(session->notification_conn,
-								  "XFR", "SB") < 0) {
+	if (msn_servconn_send_command(session->notification_conn, "XFR", "SB") < 0)
+	{
 		return NULL;
 	}
 
@@ -165,6 +170,49 @@
 	return swboard;
 }
 
+gboolean
+msn_session_change_status(MsnSession *session, const char *state)
+{
+	MsnUser *user = session->user;
+	MsnObject *msnobj;
+	char buf[MSN_BUF_LEN];
+
+	g_return_val_if_fail(session != NULL, FALSE);
+	g_return_val_if_fail(state   != NULL, FALSE);
+
+	msnobj = msn_user_get_object(user);
+
+	if (state != session->away_state)
+	{
+		if (session->away_state != NULL)
+			g_free(session->away_state);
+
+		session->away_state = g_strdup(state);
+	}
+
+	if (msnobj == NULL)
+		g_snprintf(buf, sizeof(buf), "%s %d", state, MSN_CLIENT_ID);
+	else
+	{
+		char *msnobj_str = msn_object_to_string(msnobj);
+
+		g_snprintf(buf, sizeof(buf), "%s %d %s", state, MSN_CLIENT_ID,
+				   gaim_url_encode(msnobj_str));
+
+		g_free(msnobj_str);
+	}
+
+	if (!msn_servconn_send_command(session->notification_conn, "CHG", buf))
+	{
+		gaim_connection_error(gaim_account_get_connection(session->account),
+							  _("Write error"));
+
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 MsnSwitchBoard *
 msn_session_find_switch_with_passport(const MsnSession *session,
 									  const char *passport)
@@ -224,4 +272,3 @@
 
 	return NULL;
 }
-
--- a/src/protocols/msn/session.h	Fri Nov 21 18:12:55 2003 +0000
+++ b/src/protocols/msn/session.h	Sat Nov 22 00:47:24 2003 +0000
@@ -35,6 +35,7 @@
 {
 	GaimAccount *account;
 	MsnUser *user;
+	char *away_state;
 
 	int protocol_ver;
 
@@ -150,6 +151,14 @@
 MsnSwitchBoard *msn_session_open_switchboard(MsnSession *session);
 
 /**
+ * Changes the status of the user.
+ *
+ * @param session The MSN session.
+ * @param state   The new state.
+ */
+gboolean msn_session_change_status(MsnSession *session, const char *state);
+
+/**
  * Finds a switch with the given passport.
  *
  * @param session  The MSN session.
--- a/src/protocols/msn/user.c	Fri Nov 21 18:12:55 2003 +0000
+++ b/src/protocols/msn/user.c	Sat Nov 22 00:47:24 2003 +0000
@@ -29,7 +29,8 @@
 
 	user = msn_users_find_with_passport(session->users, passport);
 
-	if (user == NULL) {
+	if (user == NULL)
+	{
 		user = g_new0(MsnUser, 1);
 
 		user->session = session;
@@ -138,6 +139,82 @@
 }
 
 void
+msn_user_set_buddy_icon(MsnUser *user, const char *filename)
+{
+	struct stat st;
+	FILE *fp;
+	MsnObject *msnobj = msn_user_get_object(user);
+
+	g_return_if_fail(user != NULL);
+
+	if (filename == NULL || stat(filename, &st) == -1)
+		msn_user_set_object(user, NULL);
+	else if ((fp = fopen(filename, "rb")) != NULL)
+	{
+		unsigned char *buf;
+		SHA_CTX ctx;
+		size_t len;
+		char *base64;
+		unsigned char digest[20];
+
+		if (msnobj == NULL)
+		{
+			msnobj = msn_object_new();
+			msn_object_set_type(msnobj, MSN_OBJECT_EMOTICON);
+			msn_object_set_location(msnobj, "TFR2C.tmp");
+			msn_object_set_creator(msnobj, msn_user_get_passport(user));
+
+			msn_user_set_object(user, msnobj);
+		}
+
+		buf = g_malloc(st.st_size);
+		len = fread(buf, 1, st.st_size, fp);
+
+		fclose(fp);
+
+		/* Compute the SHA1D field. */
+		memset(digest, 0, sizeof(digest));
+
+		shaInit(&ctx);
+		shaUpdate(&ctx, buf, st.st_size);
+		shaFinal(&ctx, digest);
+		g_free(buf);
+
+		base64 = gaim_base64_encode(digest, sizeof(digest));
+		msn_object_set_sha1d(msnobj, base64);
+		g_free(base64);
+
+		msn_object_set_size(msnobj, st.st_size);
+
+		/* Compute the SHA1C field. */
+		buf = g_strdup_printf(
+			"Creator%sSize%dType%dLocation%sFriendly%sSHA1D%s",
+			msn_object_get_creator(msnobj),
+			msn_object_get_size(msnobj),
+			msn_object_get_type(msnobj),
+			msn_object_get_location(msnobj),
+			msn_object_get_friendly(msnobj),
+			msn_object_get_sha1d(msnobj));
+
+		memset(digest, 0, sizeof(digest));
+
+		shaInit(&ctx);
+		shaUpdate(&ctx, buf, strlen(buf));
+		shaFinal(&ctx, digest);
+		g_free(buf);
+
+		base64 = gaim_base64_encode(digest, sizeof(digest));
+		msn_object_set_sha1c(msnobj, base64);
+		g_free(base64);
+	}
+	else
+	{
+		gaim_debug_error("msn", "Unable to open buddy icon %s!\n", filename);
+		msn_user_set_object(user, NULL);
+	}
+}
+
+void
 msn_user_set_group_ids(MsnUser *user, GList *ids)
 {
 	g_return_if_fail(user != NULL);
--- a/src/protocols/msn/user.h	Fri Nov 21 18:12:55 2003 +0000
+++ b/src/protocols/msn/user.h	Sat Nov 22 00:47:24 2003 +0000
@@ -129,6 +129,14 @@
 void msn_user_set_name(MsnUser *user, const char *name);
 
 /**
+ * Sets the buddy icon for a local user.
+ *
+ * @param user     The user.
+ * @param filename The path to the buddy icon.
+ */
+void msn_user_set_buddy_icon(MsnUser *user, const char *filename);
+
+/**
  * Sets the group ID list for a user.
  *
  * @param user The user.