changeset 4853:fbfdacf7c611

[gaim-migrate @ 5180] This is better auto-getting of icons for oscar. Ethan made me write a tobase16 fucntion and a from16 function (and he done gave me some good advice for that, too) which convert to and from arbitrary data and a null terminated string of hex. I use these to get and store the md5 checksum for each icon sent to you. This way, Gaim will request the icon when the md5sum differs. Er, so the md5sum is stored in blist.xml. Previously, Gaim would only request the icon if you did not have any buddy icon for the other person. Now it will request it if the local md5sum differs from the server md5sum. To sum it up again, if their icon changes, gaim will request the new one. I tried using the base64 functions, but they look like they want to work with null terminated strings, rather than arbitrary data. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sat, 22 Mar 2003 07:29:34 +0000
parents d1c17e81055e
children 3755ec4e3951
files src/gaim.h src/protocols/oscar/aim.h src/protocols/oscar/icon.c src/protocols/oscar/info.c src/protocols/oscar/oscar.c src/util.c
diffstat 6 files changed, 125 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/src/gaim.h	Sat Mar 22 06:11:12 2003 +0000
+++ b/src/gaim.h	Sat Mar 22 07:29:34 2003 +0000
@@ -428,6 +428,8 @@
 extern char *normalize(const char *);
 extern char *tobase64(const char *);
 extern void frombase64(const char *, char **, int *);
+extern char *tobase16(const char *, int);
+extern int frombase16(const char *, char **);
 extern void clean_pid();
 extern char *date();
 extern gint linkify_text(char *);
--- a/src/protocols/oscar/aim.h	Sat Mar 22 06:11:12 2003 +0000
+++ b/src/protocols/oscar/aim.h	Sat Mar 22 07:29:34 2003 +0000
@@ -478,8 +478,8 @@
 		fu8_t crap[0x25]; /* until we figure it out... */
 	} icqinfo;
 	fu32_t present;
-	fu16_t iconstrlen;
-	fu8_t iconstr[30];
+	fu16_t iconcsumlen;
+	fu8_t iconcsum[30];
 } aim_userinfo_t;
 
 #define AIM_USERINFO_PRESENT_FLAGS        0x00000001
--- a/src/protocols/oscar/icon.c	Sat Mar 22 06:11:12 2003 +0000
+++ b/src/protocols/oscar/icon.c	Sat Mar 22 07:29:34 2003 +0000
@@ -16,16 +16,16 @@
  * @param conn The icon connection for this session.
  * @return Return 0 if no errors, otherwise return the error number.
  */
-faim_export int aim_icon_requesticon(aim_session_t *sess, const char *sn, const fu8_t *iconstr, fu16_t iconstrlen)
+faim_export int aim_icon_requesticon(aim_session_t *sess, const char *sn, const fu8_t *iconcsum, fu16_t iconcsumlen)
 {
 	aim_conn_t *conn;
 	aim_frame_t *fr;
 	aim_snacid_t snacid;
 
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0010)) || !sn || !strlen(sn) || !iconstr || !iconstrlen)
+	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0010)) || !sn || !strlen(sn) || !iconcsum || !iconcsumlen)
 		return -EINVAL;
 
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 1+strlen(sn) + 4 + 1+iconstrlen)))
+	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 1+strlen(sn) + 4 + 1+iconcsumlen)))
 		return -ENOMEM;
 	snacid = aim_cachesnac(sess, 0x0010, 0x0004, 0x0000, NULL, 0);
 	aim_putsnac(&fr->data, 0x0010, 0x0004, 0x0000, snacid);
@@ -40,8 +40,8 @@
 	aimbs_put8(&fr->data, 0x01);
 
 	/* Icon string */
-	aimbs_put8(&fr->data, iconstrlen);
-	aimbs_putraw(&fr->data, iconstr, iconstrlen);
+	aimbs_put8(&fr->data, iconcsumlen);
+	aimbs_putraw(&fr->data, iconcsum, iconcsumlen);
 
 	aim_tx_enqueue(sess, fr);
 
@@ -59,24 +59,21 @@
 	aim_rxcallback_t userfunc;
 	int i;
 	char *sn;
-	fu16_t iconstrlen, iconlen;
-	fu8_t iconstr[30], *icon;
+	fu16_t flags, iconlen;
+	fu8_t number, iconcsumlen, *iconcsum, *icon;
 
 	sn = aimbs_getstr(bs, aimbs_get8(bs));
-	iconstr[0] = aimbs_get8(bs);
-	iconstr[1] = aimbs_get8(bs);
-	iconstr[2] = aimbs_get8(bs);
-	iconstr[3] = aimbs_get8(bs);
-	iconstrlen = iconstr[3] + 4;
-	for (i = 4; i < iconstrlen; i++)
-		iconstr[i] = aimbs_get8(bs);
+	flags = aimbs_get16(bs);
+	number = aimbs_get8(bs);
+	iconcsumlen = aimbs_get8(bs);
+	iconcsum = aimbs_getraw(bs, iconcsumlen);
 	iconlen = aimbs_get16(bs);
 	icon = aimbs_getraw(bs, iconlen);
 
 	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		return userfunc(sess, rx, sn, iconstr, iconstrlen, icon, iconlen);
+		return userfunc(sess, rx, sn, iconcsum, iconcsumlen, icon, iconlen);
 
-	free(iconstr);
+	free(iconcsum);
 	free(icon);
 
 	return 0;
--- a/src/protocols/oscar/info.c	Sat Mar 22 06:11:12 2003 +0000
+++ b/src/protocols/oscar/info.c	Sat Mar 22 07:29:34 2003 +0000
@@ -633,24 +633,20 @@
 			 * about the buddy icon that the user has stored on 
 			 * the server.
 			 */
-			int type, subtype, len;
-			char *iconstr;
+			int flags, number, len;
+			fu8_t *csum;
+
 			while (aim_bstream_curpos(bs) < endpos) {
-				type = aimbs_get16(bs);
-				subtype = aimbs_get8(bs);
-				if ((type != 0x0001) || (subtype != 0x01)) {
-					aim_bstream_advance(bs, aimbs_get8(bs));
-				} else {
-					len = aimbs_get8(bs);
-					if (len < 30) {
-						iconstr = aimbs_getraw(bs, len);
-						memcpy(outinfo->iconstr, iconstr, len);
-						outinfo->iconstrlen = len;
-						free(iconstr);
-					} else {
-						aim_bstream_advance(bs, len);
-					}
-				}
+				flags = aimbs_get16(bs);
+				number = aimbs_get8(bs);
+				len = aimbs_get8(bs);
+				if ((flags & 0x0001) && (number == 0x01) && (len < 30)) {
+					csum = aimbs_getraw(bs, len);
+					memcpy(outinfo->iconcsum, csum, len);
+					outinfo->iconcsumlen = len;
+					free(csum);
+				} else
+					aim_bstream_advance(bs, len);
 			}
 
 		} else if (type == 0x001e) {
--- a/src/protocols/oscar/oscar.c	Sat Mar 22 06:11:12 2003 +0000
+++ b/src/protocols/oscar/oscar.c	Sat Mar 22 07:29:34 2003 +0000
@@ -188,8 +188,8 @@
 	time_t ico_me_time;
 	gboolean ico_informed;
 
-	fu16_t iconstrlen;
-	fu8_t iconstr[30];
+	fu16_t iconcsumlen;
+	fu8_t iconcsum[30];
 };
 
 struct name_data {
@@ -1759,17 +1759,31 @@
 	bi->ico_informed = FALSE;
 
 	/* Server stored icon stuff */
-	if (info->iconstrlen) {
-		od->requesticon = g_slist_append(od->requesticon, strdup(normalize(info->sn)));
-		if (od->icontimer)
-			g_source_remove(od->icontimer);
-		od->icontimer = g_timeout_add(500, gaim_icon_timerfunc, gc);
-		memcpy(bi->iconstr, info->iconstr, info->iconstrlen);
-		bi->iconstrlen = info->iconstrlen;
-	}
-
-	serv_got_update(gc, info->sn, 1, info->warnlevel/10, signon,
-			time_idle, type);
+	if (info->iconcsumlen) {
+		char *b16, *saved_b16;
+		struct buddy *b;
+
+		memcpy(bi->iconcsum, info->iconcsum, info->iconcsumlen);
+		bi->iconcsumlen = info->iconcsumlen;
+		b16 = tobase16(bi->iconcsum, bi->iconcsumlen);
+		b = gaim_find_buddy(gc->account, info->sn);
+		saved_b16 = gaim_buddy_get_setting(b, "icon_checksum");
+		if (!b16 || !saved_b16 || strcmp(b16, saved_b16)) {
+			GSList *cur = od->requesticon;
+			while (cur && aim_sncmp((char *)cur->data, info->sn))
+				cur = cur->next;
+			if (!cur) {
+				od->requesticon = g_slist_append(od->requesticon, strdup(normalize(info->sn)));
+				if (od->icontimer)
+					g_source_remove(od->icontimer);
+				od->icontimer = g_timeout_add(500, gaim_icon_timerfunc, gc);
+			}
+		}
+		free(saved_b16);
+		free(b16);
+	}
+
+	serv_got_update(gc, info->sn, 1, info->warnlevel/10, signon, time_idle, type);
 
 	return 1;
 }
@@ -2899,6 +2913,7 @@
 	return 1;
 }
 
+/* CCC */
 static char *images(int flags) {
 	static char buf[1024];
 	g_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s",
@@ -3357,19 +3372,26 @@
 	GSList *cur;
 	va_list ap;
 	char *sn;
-	fu8_t *iconstr, *icon;
-	fu16_t iconstrlen, iconlen;
+	fu8_t *iconcsum, *icon;
+	fu16_t iconcsumlen, iconlen;
 
 	va_start(ap, fr);
 	sn = va_arg(ap, char *);
-	iconstr = va_arg(ap, fu8_t *);
-	iconstrlen = va_arg(ap, int);
+	iconcsum = va_arg(ap, fu8_t *);
+	iconcsumlen = va_arg(ap, int);
 	icon = va_arg(ap, fu8_t *);
 	iconlen = va_arg(ap, int);
 	va_end(ap);
 
-	if (iconlen > 0)
+	if (iconlen > 0) {
+		char *b16;
+		struct buddy *b;
 		set_icon_data(gc, sn, icon, iconlen);
+		b16 = tobase16(iconcsum, iconcsumlen);
+		b = gaim_find_buddy(gc->account, sn);
+		gaim_buddy_set_setting(b, "icon_checksum", b16);
+		free(b16);
+	}
 
 	cur = od->requesticon;
 	while (cur) {
@@ -3392,10 +3414,8 @@
 static gboolean gaim_icon_timerfunc(gpointer data) {
 	struct gaim_connection *gc = data;
 	struct oscar_data *od = gc->proto_data;
-	struct buddy *b;
 	struct buddyinfo *bi;
 	aim_conn_t *conn;
-	char *buddy_icon;
 
 	if (!od->requesticon) {
 		debug_printf("no more icons to request\n");
@@ -3410,17 +3430,14 @@
 	}
 
 	bi = g_hash_table_lookup(od->buddyinfo, (char *)od->requesticon->data);
-	b = gaim_find_buddy(gc->account, (char *)od->requesticon->data);
-	buddy_icon = gaim_buddy_get_setting(b, "buddy_icon");
-	if (bi && (bi->iconstrlen > 0) && !buddy_icon) {
-		aim_icon_requesticon(od->sess, od->requesticon->data, bi->iconstr, bi->iconstrlen);
+	if (bi && (bi->iconcsumlen > 0)) {
+		aim_icon_requesticon(od->sess, od->requesticon->data, bi->iconcsum, bi->iconcsumlen);
 		return FALSE;
 	} else {
 		char *sn = od->requesticon->data;
 		od->requesticon = g_slist_remove(od->requesticon, sn);
 		free(sn);
 	}
-	free(buddy_icon);
 
 	return TRUE;
 }
--- a/src/util.c	Sat Mar 22 06:11:12 2003 +0000
+++ b/src/util.c	Sat Mar 22 07:29:34 2003 +0000
@@ -466,6 +466,59 @@
 		*size = len;
 }
 
+/*
+ * Converts raw data to a pretty, null-terminated base16 string.
+ */
+char *tobase16(const char *data, int length)
+{
+	int i;
+	char *ascii = NULL;
+
+	if (!data || !length)
+		return NULL;
+
+	ascii = (char *)malloc(length*2 + 1);
+
+	for (i=0; i<length; i++)
+		snprintf(&ascii[i*2], 3, "%02hhx", data[i]);
+
+	return ascii;
+}
+
+/*
+ * Converts a null-terminated string of hexidecimal to raw data.
+ */
+int frombase16(const char *ascii, char **raw)
+{
+	int len, i, accumulator;
+	char *data;
+
+	if (!ascii || !(len = strlen(ascii)) || (len % 2))
+		return 0;
+
+	data = (char *)malloc((len/2)*sizeof(char));
+	for (i=0; i<len; i++) {
+		if (!(i % 2))
+			accumulator = 0;
+		else
+			accumulator = accumulator << 4;
+		if (isdigit(ascii[i]))
+			accumulator |= ascii[i]-48;
+		else switch(ascii[i]) {
+			case 'a':  case 'A':  accumulator|=10;  break;
+			case 'b':  case 'B':  accumulator|=11;  break;
+			case 'c':  case 'C':  accumulator|=12;  break;
+			case 'd':  case 'D':  accumulator|=13;  break;
+			case 'e':  case 'E':  accumulator|=14;  break;
+			case 'f':  case 'F':  accumulator|=15;  break;
+		}
+		if (i % 2)
+			data[(i-1)/2] = accumulator;
+	}
+
+	*raw = data;
+	return len/2;
+}
 
 char *normalize(const char *s)
 {