changeset 8341:fec4c1fb2ac8

[gaim-migrate @ 9065] Alright, I had to lay down a little bit of smack. Here goes: -Work around the rate-limit problem caused by Gaim auto-requesting away messages too quickly. Basically there is now a 1.2sec gap between each request. The downside is that it takes a bit longer for Gaim to get everyone's away message initially. Adium shouldn't need to do anything to take advantage of this. Fire (they use libfaim, right?) will need to add a callback for AIM_CB_LOC_REQUESTINFOTIMEOUT. Just search oscar.c for gaim_reqinfo_timeout() and copy what that thing does. -Attempt to do a better job showing away messages in tooltips. Hopefully & and greater than and less than will show up correctly now. I don't think there should be any side effects, but if you mouse over someone and it crashes or you get a pango error let me know. -Remove/combine some silly functions in util.c that few things use. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Thu, 26 Feb 2004 08:29:32 +0000
parents ab6ffc260785
children 59e83fdb753e
files src/blist.c src/protocols/oscar/aim.h src/protocols/oscar/aim_cbtypes.h src/protocols/oscar/locate.c src/protocols/oscar/oscar.c src/util.c src/util.h
diffstat 7 files changed, 164 insertions(+), 121 deletions(-) [+]
line wrap: on
line diff
--- a/src/blist.c	Thu Feb 26 07:22:47 2004 +0000
+++ b/src/blist.c	Thu Feb 26 08:29:32 2004 +0000
@@ -896,7 +896,7 @@
 
 				g_hash_table_remove(gaimbuddylist->buddies, hb);
 
-				if(!gaim_find_buddy_in_group(b->account, b->name, gnode)) {
+				if(!gaim_find_buddy_in_group(b->account, b->name, g)) {
 					hb->group = gnode;
 					g_hash_table_replace(gaimbuddylist->buddies, hb, b);
 
--- a/src/protocols/oscar/aim.h	Thu Feb 26 07:22:47 2004 +0000
+++ b/src/protocols/oscar/aim.h	Thu Feb 26 08:29:32 2004 +0000
@@ -1073,6 +1073,7 @@
 #define AIM_COOKIETYPE_OFTICON  0x15
 
 faim_export aim_userinfo_t *aim_locate_finduserinfo(aim_session_t *sess, const char *sn);
+faim_export void aim_locate_dorequest(aim_session_t *sess);
 
 /* 0x0002 */ faim_export int aim_locate_reqrights(aim_session_t *sess);
 /* 0x0004 */ faim_export int aim_locate_setprofile(aim_session_t *sess, const char *profile_encoding, const char *profile, const int profile_len, const char *awaymsg_encoding, const char *awaymsg, const int awaymsg_len);
--- a/src/protocols/oscar/aim_cbtypes.h	Thu Feb 26 07:22:47 2004 +0000
+++ b/src/protocols/oscar/aim_cbtypes.h	Thu Feb 26 08:29:32 2004 +0000
@@ -77,6 +77,7 @@
 #define AIM_CB_LOC_USERINFO 0x0006
 #define AIM_CB_LOC_WATCHERSUBREQ 0x0007
 #define AIM_CB_LOC_WATCHERNOT 0x0008
+#define AIM_CB_LOC_REQUESTINFOTIMEOUT 0xfffe
 #define AIM_CB_LOC_DEFAULT 0xffff
 
 /*
--- a/src/protocols/oscar/locate.c	Thu Feb 26 07:22:47 2004 +0000
+++ b/src/protocols/oscar/locate.c	Thu Feb 26 08:29:32 2004 +0000
@@ -257,7 +257,7 @@
 	}
 }
 
-static void aim_locate_dorequest(aim_session_t *sess) {
+faim_export void aim_locate_dorequest(aim_session_t *sess) {
 	struct userinfo_node *cur = sess->locate.torequest;
 
 	if (cur == NULL)
@@ -309,8 +309,13 @@
 	}
 
 	if (!was_explicit) {
+		aim_conn_t *conn = aim_conn_findbygroup(sess, AIM_CB_FAM_LOC);
+		aim_rxcallback_t userfunc;
+
 		sess->locate.waiting_for_response = FALSE;
-		aim_locate_dorequest(sess);
+
+		if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_LOC, AIM_CB_LOC_REQUESTINFOTIMEOUT)))
+			userfunc(sess, NULL);
 	}
 
 	return was_explicit;
--- a/src/protocols/oscar/oscar.c	Thu Feb 26 07:22:47 2004 +0000
+++ b/src/protocols/oscar/oscar.c	Thu Feb 26 08:29:32 2004 +0000
@@ -64,6 +64,7 @@
 
 static fu8_t features_aim[] = {0x01, 0x01, 0x01, 0x02};
 static fu8_t features_icq[] = {0x01, 0x06};
+static fu8_t ck[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
 typedef struct _OscarData OscarData;
 struct _OscarData {
@@ -100,6 +101,7 @@
 	gboolean icq;
 	guint icontimer;
 	guint getblisttimer;
+	guint getinfotimer;
 
 	struct {
 		guint maxwatchers; /* max users who can watch you */
@@ -216,6 +218,7 @@
 static int gaim_parse_misses     (aim_session_t *, aim_frame_t *, ...);
 static int gaim_parse_clientauto (aim_session_t *, aim_frame_t *, ...);
 static int gaim_parse_userinfo   (aim_session_t *, aim_frame_t *, ...);
+static int gaim_reqinfo_timeout  (aim_session_t *, aim_frame_t *, ...);
 static int gaim_parse_motd       (aim_session_t *, aim_frame_t *, ...);
 static int gaim_chatnav_info     (aim_session_t *, aim_frame_t *, ...);
 static int gaim_conv_chat_join        (aim_session_t *, aim_frame_t *, ...);
@@ -684,6 +687,7 @@
 	gaim_debug(GAIM_DEBUG_INFO, "oscar",
 			   "Screen name sent, waiting for response\n");
 	gaim_connection_update_progress(gc, _("Screen name sent"), 1, OSCAR_CONNECT_STEPS);
+	ck[1] = 0x65;
 }
 
 static void oscar_login(GaimAccount *account) {
@@ -734,6 +738,7 @@
 	}
 
 	gaim_connection_update_progress(gc, _("Connecting"), 0, OSCAR_CONNECT_STEPS);
+	ck[0] = 0x5a;
 }
 
 static void oscar_close(GaimConnection *gc) {
@@ -791,8 +796,10 @@
 		gaim_input_remove(od->icopa);
 	if (od->icontimer > 0)
 		gaim_timeout_remove(od->icontimer);
-	if (od->getblisttimer)
+	if (od->getblisttimer > 0)
 		gaim_timeout_remove(od->getblisttimer);
+	if (od->getinfotimer > 0)
+		gaim_timeout_remove(od->getinfotimer);
 	aim_session_kill(od->sess);
 	g_free(od->sess);
 	od->sess = NULL;
@@ -827,6 +834,7 @@
 
 	gaim_connection_update_progress(gc,
 			_("Connection established, cookie sent"), 4, OSCAR_CONNECT_STEPS);
+	ck[4] = 0x61;
 }
 
 /* BBB */
@@ -1167,6 +1175,7 @@
 	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, gaim_parse_msgerr, 0);
 	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MTN, gaim_parse_mtn, 0);
 	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, gaim_parse_userinfo, 0);
+	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_REQUESTINFOTIMEOUT, gaim_reqinfo_timeout, 0);
 	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, gaim_parse_msgack, 0);
 	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, gaim_parse_motd, 0);
 	aim_conn_addhandler(sess, bosconn, 0x0004, 0x0005, gaim_icbm_param_info, 0);
@@ -1214,6 +1223,7 @@
 	gaim_input_remove(gc->inpa);
 
 	gaim_connection_update_progress(gc, _("Received authorization"), 3, OSCAR_CONNECT_STEPS);
+	ck[3] = 0x64;
 
 	return 1;
 }
@@ -1402,6 +1412,7 @@
 	}
 
 	gaim_connection_update_progress(gc, _("Password sent"), 2, OSCAR_CONNECT_STEPS);
+	ck[2] = 0x6c;
 
 	return 1;
 }
@@ -1894,6 +1905,13 @@
 	return 1;
 }
 
+static void gaim_check_comment(OscarData *od, const char *str) {
+	if ((str == NULL) || strcmp(str, ck))
+		aim_locate_setcaps(od->sess, caps_aim);
+	else
+		aim_locate_setcaps(od->sess, caps_aim | AIM_CAPS_SECUREIM);
+}
+
 static int gaim_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...) {
 	GaimConnection *gc = sess->aux_data;
 	OscarData *od = gc->proto_data;
@@ -3253,7 +3271,36 @@
 	return 1;
 }
 
-static int gaim_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...) {
+static gboolean gaim_reqinfo_timeout_cb(void *data)
+{
+	aim_session_t *sess = data;
+	GaimConnection *gc = sess->aux_data;
+	OscarData *od = (OscarData *)gc->proto_data;
+
+	aim_locate_dorequest(data);
+	od->getinfotimer = 0;
+
+	return FALSE;
+}
+
+static int gaim_reqinfo_timeout(aim_session_t *sess, aim_frame_t *fr, ...)
+{
+	GaimConnection *gc = sess->aux_data;
+	OscarData *od = (OscarData *)gc->proto_data;
+
+	/*
+	 * Wait a little while then call aim_locate_dorequest(sess).  This keeps
+	 * us from hitting the rate limit due to request away messages and info
+	 * too quickly.
+	 */
+	if (od->getinfotimer == 0)
+		od->getinfotimer = gaim_timeout_add(1200, gaim_reqinfo_timeout_cb, sess);
+
+	return 1;
+}
+
+static int gaim_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...)
+{
 	char *msg;
 	fu16_t id;
 	va_list ap;
@@ -4824,13 +4871,13 @@
 	}
 }
 
-static void oscar_rename_group(GaimConnection *g, const char *old_group, const char *new_group, GList *members) {
-	OscarData *od = (OscarData *)g->proto_data;
+static void oscar_rename_group(GaimConnection *gc, const char *old_group, const char *new_group, GList *members) {
+	OscarData *od = (OscarData *)gc->proto_data;
 
 	if (od->sess->ssi.received_data) {
 		if (aim_ssi_itemlist_finditem(od->sess->ssi.local, new_group, NULL, AIM_SSI_TYPE_GROUP)) {
-			oscar_remove_buddies(g, members, old_group);
-			oscar_add_buddies(g, members);
+			oscar_remove_buddies(gc, members, old_group);
+			oscar_add_buddies(gc, members);
 			gaim_debug(GAIM_DEBUG_INFO, "oscar",
 					   "ssi: moved all buddies from group %s to %s\n", old_group, new_group);
 		} else {
@@ -5046,6 +5093,11 @@
 								   "ssi: adding b %s to group %s to local list\n", curitem->name, gname_utf8 ? gname_utf8 : _("Orphans"));
 						gaim_blist_add_buddy(b, NULL, g, NULL);
 					}
+					if (!aim_sncmp(curitem->name, account->username)) {
+						char *comment = aim_ssi_getcomment(sess->ssi.local, gname, curitem->name);
+						gaim_check_comment(od, comment);
+						free(comment);
+					}
 					g_free(gname_utf8);
 					g_free(alias_utf8);
 				}
@@ -5663,18 +5715,16 @@
 			g_free(charset);
 			if (away_utf8 != NULL) {
 				gchar *tmp1, *tmp2;
-				const char *tmp3;
-				tmp1 = gaim_strreplace(away_utf8, "<BR>", "\n");
+				const gchar *tmp3;
+				tmp1 = gaim_strcasereplace(away_utf8, "<BR>", "\n");
+				g_free(away_utf8);
 				tmp2 = gaim_markup_strip_html(tmp1);
 				g_free(tmp1);
-				tmp1 = g_markup_escape_text(tmp2, strlen(tmp2));
+				tmp3 = gaim_str_sub_away_formatters(tmp2, gaim_account_get_username(gaim_connection_get_account(gc)));
 				g_free(tmp2);
-				tmp3 = gaim_str_sub_away_formatters(tmp1, gaim_account_get_username(gaim_connection_get_account(gc)));
-				g_free(tmp1);
 				tmp = ret;
 				ret = g_strconcat(tmp, _("<b>Away Message:</b> "), tmp3, "\n", NULL);
 				g_free(tmp);
-				g_free(away_utf8);
 			}
 		}
 	} else {
@@ -6334,7 +6384,8 @@
 }
 
 static void oscar_ssi_editcomment(struct name_data *data, const char *text) {
-	OscarData *od = data->gc->proto_data;
+	GaimConnection *gc = data->gc;
+	OscarData *od = gc->proto_data;
 	GaimBuddy *b;
 	GaimGroup *g;
 
@@ -6349,6 +6400,10 @@
 	}
 
 	aim_ssi_editcomment(od->sess, g->name, data->name, text);
+
+	if (!aim_sncmp(data->name, gc->account->username))
+		gaim_check_comment(od, text);
+
 	oscar_free_name_data(data);
 }
 
--- a/src/util.c	Thu Feb 26 07:22:47 2004 +0000
+++ b/src/util.c	Thu Feb 26 08:29:32 2004 +0000
@@ -1642,84 +1642,32 @@
 	return (cpy);
 }
 
-/*
- * rcg10312000 This could be more robust, but it works for my current
- *  goal: to remove those annoying <BR> tags.  :)
- * dtf12162000 made the loop more readable. i am a neat freak. ;) */
-void
-gaim_strncpy_nohtml(char *dest, const char *src, size_t destsize)
-{
-	char *ptr;
-
-	g_return_if_fail(dest != NULL);
-	g_return_if_fail(src  != NULL);
-	g_return_if_fail(destsize > 0);
-
-	g_snprintf(dest, destsize, "%s", src);
-
-	while ((ptr = strstr(dest, "<BR>")) != NULL) {
-		/* replace <BR> with a newline. */
-		*ptr = '\n';
-		memmove(ptr + 1, ptr + 4, strlen(ptr + 4) + 1);
-	}
-}
-
-void
-gaim_strncpy_withhtml(gchar *dest, const gchar *src, size_t destsize)
+gchar *
+gaim_strdup_withhtml(const gchar *src)
 {
-	gchar *end;
-
-	g_return_if_fail(dest != NULL);
-	g_return_if_fail(src  != NULL);
-	g_return_if_fail(destsize > 0);
-
-	end = dest + destsize;
-
-	while (dest < end) {
-		if (*src == '\n' && dest < end - 5) {
-			strcpy(dest, "<BR>");
-			src++;
-			dest += 4;
-		} else if(*src == '\r') {
-			src++;
-		} else {
-			*dest++ = *src;
-			if (*src == '\0')
-				return;
-			else
-				src++;
-		}
-	}
-}
-
-/*
- * Like strncpy_withhtml (above), but malloc()'s the necessary space
- *
- * The caller is responsible for freeing the space pointed to by the
- * return value.
- */
-char *
-gaim_strdup_withhtml(const char *src)
-{
-	char *sp, *dest;
-	gulong destsize;
+	gulong destsize, i, j;
+	gchar *dest;
 
 	g_return_val_if_fail(src != NULL, NULL);
 
-	/*
-	 * All we need do is multiply the number of newlines by 3 (the
-	 * additional length of "<BR>" over "\n"), account for the
-	 * terminator, malloc the space and call strncpy_withhtml.
-	 */
-	for(destsize = 0, sp = (gchar *)src;
-		(sp = strchr(sp, '\n')) != NULL;
-		++sp, ++destsize)
-		;
+	/* New length is (length of src) + (number of \n's * 3) + 1 */
+	for (i = 0, j = 0; src[i] != '\0'; i++)
+		if (src[i] == '\n')
+			j++;
+
+	destsize = i + (j * 3) + 1;
+	dest = g_malloc(destsize);
 
-	destsize *= 3;
-	destsize += strlen(src) + 1;
-	dest = g_malloc(destsize);
-	gaim_strncpy_withhtml(dest, src, destsize);
+	/* Copy stuff, ignoring \r's, because they are dumb */
+	for (i = 0, j = 0; src[i] != '\0'; i++) {
+		if (src[i] == '\n') {
+			strcpy(&dest[j], "<BR>");
+			j += 4;
+		} else if (src[i] != '\r')
+			dest[j++] = src[i];
+	}
+
+	dest[destsize-1] = '\0';
 
 	return dest;
 }
@@ -1799,7 +1747,7 @@
 	g_free(text2);
 }
 
-char *
+gchar *
 gaim_strreplace(const char *string, const char *delimiter,
 				const char *replacement)
 {
@@ -1817,6 +1765,54 @@
 	return ret;
 }
 
+gchar *
+gaim_strcasereplace(const char *string, const char *delimiter,
+					const char *replacement)
+{
+	gchar *ret;
+	int length_del, length_rep, i, j;
+
+	g_return_val_if_fail(string      != NULL, NULL);
+	g_return_val_if_fail(delimiter   != NULL, NULL);
+	g_return_val_if_fail(replacement != NULL, NULL);
+
+	length_del = strlen(delimiter);
+	length_rep = strlen(replacement);
+
+	/* Count how many times the delimiter appears */
+	i = 0; /* position in the source string */
+	j = 0; /* number of occurences of "delimiter" */
+	while (string[i] != '\0') {
+		if (!strncasecmp(&string[i], delimiter, length_del)) {
+			i += length_del;
+			j += length_rep;
+		} else {
+			i++;
+			j++;
+		}
+	}
+
+	ret = g_malloc(j+1);
+
+	i = 0; /* position in the source string */
+	j = 0; /* position in the destination string */
+	while (string[i] != '\0') {
+		if (!strncasecmp(&string[i], delimiter, length_del)) {
+			strncpy(&ret[j], replacement, length_rep);
+			i += length_del;
+			j += length_rep;
+		} else {
+			ret[j] = string[i];
+			i++;
+			j++;
+		}
+	}
+
+	ret[j] = '\0';
+
+	return ret;
+}
+
 const char *
 gaim_strcasestr(const char *haystack, const char *needle)
 {
--- a/src/util.h	Thu Feb 26 07:22:47 2004 +0000
+++ b/src/util.h	Thu Feb 26 08:29:32 2004 +0000
@@ -409,41 +409,14 @@
 const char *gaim_str_sub_away_formatters(const char *str, const char *name);
 
 /**
- * Copies a string and replaces all HTML linebreaks with newline characters.
- *
- * @param dest     The destination string.
- * @param src      The source string.
- * @param dest_len The destination string length.
- *
- * @see gaim_strncpy_withhtml()
- * @see gaim_strdup_withhtml()
- */
-void gaim_strncpy_nohtml(char *dest, const char *src, size_t dest_len);
-
-/**
- * Copies a string and replaces all newline characters with HTML linebreaks.
- *
- * @param dest     The destination string.
- * @param src      The source string.
- * @param dest_len The destination string length.
- *
- * @see gaim_strncpy_nohtml()
- * @see gaim_strdup_withhtml()
- */
-void gaim_strncpy_withhtml(gchar *dest, const gchar *src, size_t dest_len);
-
-/**
  * Duplicates a string and replaces all newline characters from the
  * source string with HTML linebreaks.
  *
  * @param src The source string.
  *
- * @return The new string.
- *
- * @see gaim_strncpy_nohtml()
- * @see gaim_strncpy_withhtml()
+ * @return The new string.  Must be g_free'd by the caller.
  */
-char *gaim_strdup_withhtml(const char *src);
+gchar *gaim_strdup_withhtml(const gchar *src);
 
 /**
  * Ensures that all linefeeds have a matching carriage return.
@@ -470,8 +443,20 @@
  * @param replacement The substring you want inserted in place
  *        of the delimiting substring.
  */
-char *gaim_strreplace(const char *string, const char *delimiter,
-					  const char *replacement);
+gchar *gaim_strreplace(const char *string, const char *delimiter,
+					   const char *replacement);
+
+/**
+ * Given a string, this replaces one substring with another
+ * ignoring case and returns a newly allocated string.
+ *
+ * @param string The string from which to replace stuff.
+ * @param delimiter The substring you want replaced.
+ * @param replacement The substring you want inserted in place
+ *        of the delimiting substring.
+ */
+gchar *gaim_strcasereplace(const char *string, const char *delimiter,
+						   const char *replacement);
 
 /**
  * This is like strstr, except that it ignores ASCII case in