changeset 11255:1b1d63602d77

[gaim-migrate @ 13429] sf patch #1247984, from Ilya Konstantinov Retrieve ICQ away messages with i18n support committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sat, 13 Aug 2005 18:40:40 +0000
parents ce3b9969b399
children bb0d7b719af2
files COPYRIGHT src/protocols/oscar/im.c src/protocols/oscar/locate.c
diffstat 3 files changed, 151 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Sat Aug 13 15:53:29 2005 +0000
+++ b/COPYRIGHT	Sat Aug 13 18:40:40 2005 +0000
@@ -104,6 +104,7 @@
 Henry Jen
 Benjamin Kahn
 Akuke Kok
+Ilya Konstantinov
 Cole Kowalski
 Gary Kramlich
 Patrik Kullman
--- a/src/protocols/oscar/im.c	Sat Aug 13 15:53:29 2005 +0000
+++ b/src/protocols/oscar/im.c	Sat Aug 13 18:40:40 2005 +0000
@@ -972,10 +972,10 @@
 		aimbs_put16(&fr->data, 0x0036);
 		{ /* V */
 			aimbs_putle16(&fr->data, 0x001b); /* L */
-			aimbs_putle16(&fr->data, 0x0008); /* XXX - Protocol version */
+			aimbs_putle16(&fr->data, 0x0009); /* Protocol version */
 			aim_putcap(&fr->data, AIM_CAPS_EMPTY);
 			aimbs_putle16(&fr->data, 0x0000); /* Unknown */
-			aimbs_putle16(&fr->data, 0x0003); /* Client features? */
+			aimbs_putle16(&fr->data, 0x0001); /* Client features? */
 			aimbs_putle16(&fr->data, 0x0000); /* Unknown */
 			aimbs_putle8(&fr->data, 0x00); /* Unkizown */
 			aimbs_putle16(&fr->data, 0xffff); /* Sequence number?  XXX - This should decrement by 1 with each request */
@@ -988,15 +988,19 @@
 
 			/* The type of status message being requested */
 			if (type & AIM_ICQ_STATE_CHAT)
-				aimbs_putle16(&fr->data, 0x03ec);
+				aimbs_putle8(&fr->data, 0xec);
 			else if(type & AIM_ICQ_STATE_DND)
-				aimbs_putle16(&fr->data, 0x03eb);
+				aimbs_putle8(&fr->data, 0xeb);
 			else if(type & AIM_ICQ_STATE_OUT)
-				aimbs_putle16(&fr->data, 0x03ea);
+				aimbs_putle8(&fr->data, 0xea);
 			else if(type & AIM_ICQ_STATE_BUSY)
-				aimbs_putle16(&fr->data, 0x03e9);
+				aimbs_putle8(&fr->data, 0xe9);
 			else if(type & AIM_ICQ_STATE_AWAY)
-				aimbs_putle16(&fr->data, 0x03e8);
+				aimbs_putle8(&fr->data, 0xe8);
+			else
+				/* This should not happen */
+				aimbs_putle8(&fr->data, 0x00);
+			aimbs_putle8(&fr->data, 0x03); /* Message Flags */
 
 			aimbs_putle16(&fr->data, 0x0000); /* Status? */
 			aimbs_putle16(&fr->data, 0x0001); /* Priority of this message? */
@@ -2194,11 +2198,106 @@
 	sn = aimbs_getstr(bs, snlen);
 	reason = aimbs_get16(bs);
 
-	if (channel == 0x0002) { /* File transfer declined */
-		aimbs_get16(bs); /* Unknown */
-		aimbs_get16(bs); /* Unknown */
-		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-			ret = userfunc(sess, rx, channel, sn, reason, ck);
+	if (channel == 0x0002) {
+		switch (reason) {
+			case 0x0003: {
+				/* This is exactly like the Extended Data TLV (2711) */
+				fu16_t len;
+				fu16_t version;
+				fu8_t plugin_uuid[16];
+
+				len = aimbs_getle16(bs); /* Usually 0x001b */
+				version = aimbs_getle16(bs);
+				aimbs_getrawbuf(bs, plugin_uuid, sizeof(plugin_uuid));
+				aim_bstream_advance(bs, len - sizeof(version) - sizeof(plugin_uuid)); /* Rest is unknown */
+
+				len = aimbs_getle16(bs); /* Usually 0x000e */
+				aim_bstream_advance(bs, len); /* Unknown */
+
+				if (plugin_uuid[0] == 0 &&
+				    plugin_uuid[1] == 0 &&
+				    plugin_uuid[2] == 0 &&
+				    plugin_uuid[3] == 0 &&
+				    plugin_uuid[4] == 0 &&
+				    plugin_uuid[5] == 0 &&
+				    plugin_uuid[6] == 0 &&
+				    plugin_uuid[7] == 0 &&
+				    plugin_uuid[8] == 0 &&
+				    plugin_uuid[9] == 0 &&
+				    plugin_uuid[10] == 0 &&
+				    plugin_uuid[11] == 0 &&
+				    plugin_uuid[12] == 0 &&
+				    plugin_uuid[13] == 0 &&
+				    plugin_uuid[14] == 0 &&
+				    plugin_uuid[15] == 0)
+				{
+					fu8_t msg_type, msg_flags, *msg;
+					fu16_t status_code, priority_code, msg_length;
+					fu32_t state;
+
+					msg_type = aimbs_getle8(bs);
+					switch (msg_type) {
+						case 0xe8:
+							state = AIM_ICQ_STATE_AWAY;
+							break;
+						case 0xe9:
+							state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY;
+							break;
+						case 0xea:
+							state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_OUT;
+							break;
+						case 0xeb:
+							state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY;
+							break;
+						case 0xec:
+							state = AIM_ICQ_STATE_CHAT;
+							break;
+						default:
+							state = 0;
+							break;
+					}
+					msg_flags = aimbs_getle8(bs); /* would usually have 0x03 == auto msg */
+					status_code = aimbs_getle16(bs);
+					priority_code = aimbs_getle16(bs);
+
+					msg_length = aimbs_getle16(bs);
+					msg = aimbs_getraw(bs, msg_length);
+
+					if (state & AIM_ICQ_STATE_AWAY)
+					{
+						aim_userinfo_t *userinfo = aim_locate_finduserinfo(sess, sn);
+						free(userinfo->away);
+						free(userinfo->away_encoding);
+						if (msg_length > 0)
+						{
+							userinfo->away = (char *)malloc(msg_length);
+							memcpy(userinfo->away, msg, msg_length);
+						}
+						else
+						{
+							userinfo->away = NULL;
+						}
+						userinfo->away_len = msg_length - 1; /* msg_length includes a terminating '\0' */
+						userinfo->away_encoding = strdup("text/x-aolrtf; charset=\"utf-8\"");
+					}
+
+					if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+						ret = userfunc(sess, rx, channel, sn, reason, state, msg);
+				}
+				else
+				{
+					if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+						ret = userfunc(sess, rx, channel, sn, reason, ck);
+				}
+				break;
+			}
+
+			default: {
+				/* File transfer declined? */
+				if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+					ret = userfunc(sess, rx, channel, sn, reason, ck);
+			}
+		}
 	} else if (channel == 0x0004) { /* ICQ message */
 		switch (reason) {
 			case 0x0003: { /* ICQ status message.  Maybe other stuff too, you never know with these people. */
--- a/src/protocols/oscar/locate.c	Sat Aug 13 15:53:29 2005 +0000
+++ b/src/protocols/oscar/locate.c	Sat Aug 13 18:40:40 2005 +0000
@@ -67,8 +67,8 @@
 	  0x82, 0x22, 0x44, 0x45, 0x45, 0x53, 0x54, 0x00}},
 
 	/*
-	 * Not really sure about this one.  In an email from 
-	 * 26 Sep 2003, Matthew Sachs suggested that, "this 
+	 * Not really sure about this one.  In an email from
+	 * 26 Sep 2003, Matthew Sachs suggested that, "this
 	 * is probably the capability for the SMS features."
 	 */
 	{AIM_CAPS_SMS,
@@ -124,9 +124,9 @@
 	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
 
 	/*
-	 * Indeed, there are two of these.  The former appears to be correct, 
-	 * but in some versions of winaim, the second one is set.  Either they 
-	 * forgot to fix endianness, or they made a typo. It really doesn't 
+	 * Indeed, there are two of these.  The former appears to be correct,
+	 * but in some versions of winaim, the second one is set.  Either they
+	 * forgot to fix endianness, or they made a typo. It really doesn't
 	 * matter which.
 	 */
 	{AIM_CAPS_GAMES,
@@ -141,12 +141,12 @@
 	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
 
 	/*
-	 * Setting this lets AIM users receive messages from ICQ users, and ICQ 
-	 * users receive messages from AIM users.  It also lets ICQ users show 
-	 * up in buddy lists for AIM users, and AIM users show up in buddy lists 
-	 * for ICQ users.  And ICQ privacy/invisibility acts like AIM privacy, 
-	 * in that if you add a user to your deny list, you will not be able to 
-	 * see them as online (previous you could still see them, but they 
+	 * Setting this lets AIM users receive messages from ICQ users, and ICQ
+	 * users receive messages from AIM users.  It also lets ICQ users show
+	 * up in buddy lists for AIM users, and AIM users show up in buddy lists
+	 * for ICQ users.  And ICQ privacy/invisibility acts like AIM privacy,
+	 * in that if you add a user to your deny list, you will not be able to
+	 * see them as online (previous you could still see them, but they
 	 * couldn't see you.
 	 */
 	{AIM_CAPS_INTEROPERATE,
@@ -183,7 +183,7 @@
 	 {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34,
 	  0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x09}},
 
-	{AIM_CAPS_APINFO, 
+	{AIM_CAPS_APINFO,
 	 {0xaa, 0x4a, 0x32, 0xb5, 0xf8, 0x84, 0x48, 0xc6,
 	  0xa3, 0xd7, 0x8c, 0x50, 0x97, 0x19, 0xfd, 0x5b}},
 
@@ -199,7 +199,7 @@
 };
 
 /*
- * Add the userinfo to our linked list.  If we already have userinfo 
+ * Add the userinfo to our linked list.  If we already have userinfo
  * for this buddy, then just overwrite parts of the old data.
  *
  * @param userinfo Contains the new information for the buddy.
@@ -295,12 +295,12 @@
 }
 
 /**
- * Remove this screen name from our queue.  If this info was requested 
+ * Remove this screen name from our queue.  If this info was requested
  * by our info request queue, then pop the next element off of the queue.
  *
  * @param sess The aim session.
  * @param sn Screen name of the info we just received.
- * @return True if the request was explicit (client requested the info), 
+ * @return True if the request was explicit (client requested the info),
  *         false if the request was implicit (libfaim request the info).
  */
 static int aim_locate_gotuserinfo(aim_session_t *sess, const char *sn) {
@@ -497,7 +497,7 @@
 }
 
 /*
- * AIM is fairly regular about providing user info.  This is a generic 
+ * AIM is fairly regular about providing user info.  This is a generic
  * routine to extract it in its standard form.
  */
 faim_internal int aim_info_extract(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *outinfo)
@@ -512,7 +512,7 @@
 	memset(outinfo, 0x00, sizeof(aim_userinfo_t));
 
 	/*
-	 * Screen name.  Stored as an unterminated string prepended with a 
+	 * Screen name.  Stored as an unterminated string prepended with a
 	 * byte containing its length.
 	 */
 	snlen = aimbs_get8(bs);
@@ -524,12 +524,12 @@
 	outinfo->warnlevel = aimbs_get16(bs);
 
 	/*
-	 * TLV Count. Unsigned short representing the number of 
+	 * TLV Count. Unsigned short representing the number of
 	 * Type-Length-Value triples that follow.
 	 */
 	tlvcnt = aimbs_get16(bs);
 
-	/* 
+	/*
 	 * Parse out the Type-Length-Value triples as they're found.
 	 */
 	for (curtlv = 0; curtlv < tlvcnt; curtlv++) {
@@ -1135,6 +1135,19 @@
 		userinfo->away = (char *)malloc(tlv->length);
 		memcpy(userinfo->away, tlv->value, tlv->length);
 		userinfo->away_len = tlv->length;
+		/*
+		 * ICQ cannot be trusted with non-Latin-1 away messages
+		 * delivered in 0x02,0x06; see SF issue 1175975.
+		 * Therefore, we try to get its Away information
+		 * in an alternative fashion -- same as used
+		 * by the official client.
+		 */
+		if (((userinfo->icqinfo.status & AIM_ICQ_STATE_AWAY) ||
+		     (userinfo->icqinfo.status & AIM_ICQ_STATE_CHAT)) &&
+		    (userinfo->sn != NULL) && aim_sn_is_icq(userinfo->sn))
+		{
+			aim_im_sendch2_geticqaway(sess, userinfo->sn, userinfo->icqinfo.status);
+		}
 	}
 
 	/* Caps will be 5 */
@@ -1152,8 +1165,8 @@
 	free(userinfo);
 
 	/*
-	 * Remove this screen name from our queue.  If the client requested 
-	 * this buddy's info explicitly, then notify them that we have info 
+	 * Remove this screen name from our queue.  If the client requested
+	 * this buddy's info explicitly, then notify them that we have info
 	 * for this buddy.
 	 */
 	was_explicit = aim_locate_gotuserinfo(sess, userinfo2->sn);
@@ -1164,14 +1177,14 @@
 	return ret;
 }
 
-/* 
+/*
  * Subtype 0x0009 - Set directory profile data.
  *
  * This is not the same as aim_location_setprofile!
  * privacy: 1 to allow searching, 0 to disallow.
  *
  */
-faim_export int aim_locate_setdirinfo(aim_session_t *sess, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, fu16_t privacy) 
+faim_export int aim_locate_setdirinfo(aim_session_t *sess, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, fu16_t privacy)
 {
 	aim_conn_t *conn;
 	aim_frame_t *fr;
@@ -1237,7 +1250,7 @@
 		return -ENOMEM;
 
 	snacid = aim_cachesnac(sess, 0x0002, 0x000b, 0x0000, NULL, 0);
-	
+
 	aim_putsnac(&fr->data, 0x0002, 0x000b, 0x0000, snacid);
 	aimbs_put8(&fr->data, strlen(sn));
 	aimbs_putstr(&fr->data, sn);
@@ -1249,7 +1262,7 @@
 
 /*
  * Subtype 0x000f
- * 
+ *
  * XXX pass these in better
  *
  */
@@ -1292,7 +1305,7 @@
 }
 
 /*
- * Subtype 0x0015 - Request the info a user using the short method.  This is 
+ * Subtype 0x0015 - Request the info a user using the short method.  This is
  * what iChat uses.  It normally is VERY leniently rate limited.
  *
  * @param sn The screen name whose info you wish to request.