im.pidgin.pidgin: b7875f81b48bb1a776ac4b2473cc7376cb35b0f9

markdoliner at pidgin.im markdoliner at pidgin.im
Wed Feb 27 04:20:48 EST 2008


-----------------------------------------------------------------
Revision: b7875f81b48bb1a776ac4b2473cc7376cb35b0f9
Ancestor: 64e9bf80895d2671f0a42fecc17e3ba895b41426
Author: markdoliner at pidgin.im
Date: 2008-02-27T09:18:06
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/b7875f81b48bb1a776ac4b2473cc7376cb35b0f9

Modified files:
        ChangeLog libpurple/protocols/oscar/family_icbm.c
        libpurple/protocols/oscar/family_icq.c
        libpurple/protocols/oscar/oscar.c
        libpurple/protocols/oscar/oscar.h

ChangeLog: 

Add support for offline messages for AIM, thanks to some info from
Matthew Goldstein.  The new protocol bits used for offline messaging
for AIM are very nice.  It fits in with the rest of the oscar protocol
very well (the old, ICQ-style offline messages were a bit of a hack).
The offline messages arrive in the same way as every other message
(except that they have a timestamp), so we can use the same message
parsing that we use for all other IMs.  This means that all our
encoding stuff works just as well with offline messages.

AND the new offline message stuff works for ICQ accounts, too.  So I
switched ICQ over to use it, which fixes offline message timestamps
(if that was still a problem, I'm not sure) and offline message encoding
bugs.

Fixes #1229 (feature request for AIM offline messages)
Fixes #1761 (ICQ offline message timestamp is wrong)
Fixes #4300 (crash when receiving offline messages)
Fixes #4464 (can't send IMs to invisible users)

-------------- next part --------------
============================================================
--- ChangeLog	7090a02e873870980f5227853c9f5f882495adb6
+++ ChangeLog	f85d782c7e64973bb8eacd68888ce47307c958af
@@ -1,7 +1,9 @@ version 2.4.0 (??/??/2008):
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
 version 2.4.0 (??/??/2008):
 	libpurple:
+	* Added support for offline messages for AIM accounts (thanks to
+	  Matthew Goldstein)
 	* Fixed various problems with loss of status messages when going
 	  or returning from idle on MySpaceIM.
 	* Eliminated unmaintained Howl backend implementation for the
============================================================
--- libpurple/protocols/oscar/family_icbm.c	a46859abee60456355c915cabd1ef39ad9ba7435
+++ libpurple/protocols/oscar/family_icbm.c	8e6c3080d5c77f8fd82bc13bc1e23662cc43a384
@@ -221,7 +221,7 @@ static int aim_im_paraminfo(OscarData *o
 	params.maxrecverwarn = byte_stream_get16(bs);
 	params.minmsginterval = byte_stream_get32(bs);
 
-	params.flags = 0x0000000b;
+	params.flags = 0x0000000b | AIM_IMPARAM_FLAG_SUPPORT_OFFLINEMSGS;
 	params.maxmsglen = 8000;
 	params.minmsginterval = 0;
 
@@ -1626,7 +1626,10 @@ static int incomingim_ch1(OscarData *od,
 
 		} else if (type == 0x0006) { /* Message was received offline. */
 
-			/* XXX - not sure if this actually gets sent. */
+			/*
+			 * This flag is set on incoming offline messages for both
+			 * AIM and ICQ accounts.
+			 */
 			args.icbmflags |= AIM_IMFLAGS_OFFLINE;
 
 		} else if (type == 0x0008) { /* I-HAVE-A-REALLY-PURTY-ICON Flag */
@@ -1657,6 +1660,14 @@ static int incomingim_ch1(OscarData *od,
 
 			args.icbmflags |= AIM_IMFLAGS_TYPINGNOT;
 
+		} else if (type == 0x0016) {
+
+			/*
+			 * UTC timestamp for when the message was sent.  Only
+			 * provided for offline messages.
+			 */
+			args.timestamp = byte_stream_get32(bs);
+
 		} else if (type == 0x0017) {
 
 			if (length > byte_stream_empty(bs))
@@ -2589,6 +2600,30 @@ static int msgack(OscarData *od, FlapCon
 }
 
 /*
+ * Subtype 0x0010 - Request any offline messages that are waiting for
+ * us.  This is the "new" way of handling offline messages which is
+ * used for both AIM and ICQ.  The old way is to use the ugly
+ * aim_icq_reqofflinemsgs() function, but that is no longer necessary.
+ *
+ * We set the 0x00000100 flag on the ICBM message parameters, which
+ * tells the oscar servers that we support offline messages.  When we
+ * set that flag the servers do not automatically send us offline
+ * messages.  Instead we must request them using this function.  This
+ * should happen after sending the 0x0001/0x0002 "client online" SNAC.
+ */
+int aim_im_reqofflinemsgs(OscarData *od)
+{
+	FlapConnection *conn;
+
+	if (!od || !(conn = flap_connection_findbygroup(od, 0x0002)))
+		return -EINVAL;
+
+	aim_genericreq_n(od, conn, 0x0004, 0x0010);
+
+	return 0;
+}
+
+/*
  * Subtype 0x0014 - Send a mini typing notification (mtn) packet.
  *
  * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer,
============================================================
--- libpurple/protocols/oscar/family_icq.c	b9f665b30fd9fcf2136e0dfba1a0f301f2f869b1
+++ libpurple/protocols/oscar/family_icq.c	36960db6d17bdb9549b1eae60bc955af110c074f
@@ -25,6 +25,7 @@
 
 #include "oscar.h"
 
+#ifdef OLDSTYLE_ICQ_OFFLINEMSGS
 int aim_icq_reqofflinemsgs(OscarData *od)
 {
 	FlapConnection *conn;
@@ -86,6 +87,7 @@ int aim_icq_ackofflinemsgs(OscarData *od
 
 	return 0;
 }
+#endif /* OLDSTYLE_ICQ_OFFLINEMSGS */
 
 int
 aim_icq_setsecurity(OscarData *od, gboolean auth_required, gboolean webaware)
@@ -559,6 +561,7 @@ icqresponse(OscarData *od, FlapConnectio
 	purple_debug_misc("oscar", "icq response: %d bytes, %ld, 0x%04x, 0x%04x\n", cmdlen, ouruin, cmd, reqid);
 
 	if (cmd == 0x0041) { /* offline message */
+#ifdef OLDSTYLE_ICQ_OFFLINEMSGS
 		struct aim_icq_offlinemsg msg;
 		aim_rxcallback_t userfunc;
 
@@ -585,6 +588,7 @@ icqresponse(OscarData *od, FlapConnectio
 
 		if ((userfunc = aim_callhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_OFFLINEMSGCOMPLETE)))
 			ret = userfunc(od, conn, frame);
+#endif /* OLDSTYLE_ICQ_OFFLINEMSGS */
 
 	} else if (cmd == 0x07da) { /* information */
 		guint16 subtype;
============================================================
--- libpurple/protocols/oscar/oscar.c	3f9ab0ed0ed3f899ddc1032fea48391b9b04e4cb
+++ libpurple/protocols/oscar/oscar.c	e3e4d4bae3c68d1a29c3189a993257f5929a026a
@@ -180,8 +180,10 @@ static int purple_selfinfo         (Osca
 static int purple_parse_genericerr (OscarData *, FlapConnection *, FlapFrame *, ...);
 static int purple_memrequest       (OscarData *, FlapConnection *, FlapFrame *, ...);
 static int purple_selfinfo         (OscarData *, FlapConnection *, FlapFrame *, ...);
+#ifdef OLDSTYLE_ICQ_OFFLINEMSGS
 static int purple_offlinemsg       (OscarData *, FlapConnection *, FlapFrame *, ...);
 static int purple_offlinemsgdone   (OscarData *, FlapConnection *, FlapFrame *, ...);
+#endif /* OLDSTYLE_ICQ_OFFLINEMSGS */
 static int purple_icqalias         (OscarData *, FlapConnection *, FlapFrame *, ...);
 static int purple_icqinfo          (OscarData *, FlapConnection *, FlapFrame *, ...);
 static int purple_popup            (OscarData *, FlapConnection *, FlapFrame *, ...);
@@ -1275,8 +1277,10 @@ oscar_login(PurpleAccount *account)
 	oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_ERROR, purple_parse_msgerr, 0);
 	oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_MTN, purple_parse_mtn, 0);
 	oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_ACK, purple_parse_msgack, 0);
+#ifdef OLDSTYLE_ICQ_OFFLINEMSGS
 	oscar_data_addhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_OFFLINEMSG, purple_offlinemsg, 0);
 	oscar_data_addhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_OFFLINEMSGCOMPLETE, purple_offlinemsgdone, 0);
+#endif /* OLDSTYLE_ICQ_OFFLINEMSGS */
 	oscar_data_addhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_ALIAS, purple_icqalias, 0);
 	oscar_data_addhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_INFO, purple_icqinfo, 0);
 	oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_RIGHTSINFO, purple_parse_locaterights, 0);
@@ -2079,7 +2083,8 @@ static int incomingim_chan1(OscarData *o
 		g_datalist_clear(&attribs);
 	}
 
-	serv_got_im(gc, userinfo->sn, tmp, flags, time(NULL));
+	serv_got_im(gc, userinfo->sn, tmp, flags,
+			(args->icbmflags & AIM_IMFLAGS_OFFLINE) ? args->timestamp : time(NULL));
 	g_free(tmp);
 
 	return 1;
@@ -2264,6 +2269,8 @@ purple_auth_request(struct name_data *da
 			}
 		}
 	}
+
+	oscar_free_name_data(data);
 }
 
 static void
@@ -3639,8 +3646,13 @@ static int purple_bosrights(OscarData *o
 	presence = purple_status_get_presence(status);
 	aim_srv_setidle(od, !purple_presence_is_idle(presence) ? 0 : time(NULL) - purple_presence_get_idle_time(presence));
 
+	/* Request offline messages for AIM and ICQ */
+	aim_im_reqofflinemsgs(od);
+
 	if (od->icq) {
+#ifdef OLDSTYLE_ICQ_OFFLINEMSGS
 		aim_icq_reqofflinemsgs(od);
+#endif
 		oscar_set_extendedstatus(gc);
 		aim_icq_setsecurity(od,
 			purple_account_get_bool(account, "authorization", OSCAR_DEFAULT_AUTHORIZATION),
@@ -3664,6 +3676,7 @@ static int purple_bosrights(OscarData *o
 	return 1;
 }
 
+#ifdef OLDSTYLE_ICQ_OFFLINEMSGS
 static int purple_offlinemsg(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
 	va_list ap;
 	struct aim_icq_offlinemsg *msg;
@@ -3692,6 +3705,7 @@ static int purple_offlinemsgdone(OscarDa
 	aim_icq_ackofflinemsgs(od);
 	return 1;
 }
+#endif /* OLDSTYLE_ICQ_OFFLINEMSGS */
 
 static int purple_icqinfo(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
 {
@@ -4258,7 +4272,7 @@ oscar_send_im(PurpleConnection *gc, cons
 			g_hash_table_insert(od->buddyinfo, g_strdup(purple_normalize(account, name)), bi);
 		}
 
-		args.flags = AIM_IMFLAGS_ACK | AIM_IMFLAGS_CUSTOMFEATURES;
+		args.flags = AIM_IMFLAGS_ACK | AIM_IMFLAGS_CUSTOMFEATURES | AIM_IMFLAGS_OFFLINE;
 		if (od->icq) {
 			/* We have to present different "features" (whose meaning
 			   is unclear and are merely a result of protocol inspection)
@@ -4275,7 +4289,6 @@ oscar_send_im(PurpleConnection *gc, cons
 				args.features = features_icq_offline;
 				args.featureslen = sizeof(features_icq_offline);
 			}
-			args.flags |= AIM_IMFLAGS_OFFLINE;
 		} else {
 			args.features = features_aim;
 			args.featureslen = sizeof(features_aim);
============================================================
--- libpurple/protocols/oscar/oscar.h	0c3d93c15966713667b84476fc9b56119a394b64
+++ libpurple/protocols/oscar/oscar.h	c717758ac587d55c4f78d02e0940fb3c3b1f2740
@@ -679,8 +679,9 @@ void aim_ads_requestads(OscarData *od, F
 #define AIM_TRANSFER_DENY_DECLINE	0x0001
 #define AIM_TRANSFER_DENY_NOTACCEPTING	0x0002
 
-#define AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED	0x00000001
-#define AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED	0x00000002
+#define AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED       0x00000001
+#define AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED    0x00000002
+#define AIM_IMPARAM_FLAG_SUPPORT_OFFLINEMSGS    0x00000100
 
 /* This is what the server will give you if you don't set them yourself. */
 #define AIM_IMPARAM_DEFAULTS { \
@@ -844,6 +845,7 @@ struct aim_incomingim_ch1_args
 	/* Always provided */
 	aim_mpmsg_t mpmsg;
 	guint32 icbmflags; /* some flags apply only to ->msg, not all mpmsg */
+	time_t timestamp; /* Only set for offline messages */
 
 	/* Only provided if message has a human-readable section */
 	gchar *msg;
@@ -948,6 +950,7 @@ struct aim_incomingim_ch4_args
 /* 0x0006 */ int aim_im_sendch4(OscarData *od, const char *sn, guint16 type, const char *message);
 /* 0x0008 */ int aim_im_warn(OscarData *od, FlapConnection *conn, const char *destsn, guint32 flags);
 /* 0x000b */ int aim_im_denytransfer(OscarData *od, const char *sn, const guchar *cookie, guint16 code);
+/* 0x0010 */ int aim_im_reqofflinemsgs(OscarData *od);
 /* 0x0014 */ int aim_im_sendmtn(OscarData *od, guint16 type1, const char *sn, guint16 type2);
 void aim_icbm_makecookie(guchar* cookie);
 gchar *oscar_encoding_extract(const char *encoding);
@@ -1256,6 +1259,7 @@ int aim_ssi_delicon(OscarData *od);
 #define AIM_ICQ_INFO_UNKNOWN	0x100
 #define AIM_ICQ_INFO_HAVEALL	0x1ff
 
+#ifdef OLDSTYLE_ICQ_OFFLINEMSGS
 struct aim_icq_offlinemsg
 {
 	guint32 sender;
@@ -1266,6 +1270,7 @@ struct aim_icq_offlinemsg
 	char *msg;
 	int msglen;
 };
+#endif /* OLDSTYLE_ICQ_OFFLINEMSGS */
 
 struct aim_icq_info
 {
@@ -1330,8 +1335,10 @@ struct aim_icq_info
 	char *status_note_title;
 };
 
+#ifdef OLDSTYLE_ICQ_OFFLINEMSGS
 int aim_icq_reqofflinemsgs(OscarData *od);
 int aim_icq_ackofflinemsgs(OscarData *od);
+#endif
 int aim_icq_setsecurity(OscarData *od, gboolean auth_required, gboolean webaware);
 int aim_icq_changepasswd(OscarData *od, const char *passwd);
 int aim_icq_getsimpleinfo(OscarData *od, const char *uin);


More information about the Commits mailing list