# HG changeset patch # User Mark Doliner # Date 1077784172 0 # Node ID fec4c1fb2ac83d62db8cc18e3eb175c98e718d55 # Parent ab6ffc2607854d8664d854de21eb86ac3bd1516a [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 diff -r ab6ffc260785 -r fec4c1fb2ac8 src/blist.c --- 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); diff -r ab6ffc260785 -r fec4c1fb2ac8 src/protocols/oscar/aim.h --- 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); diff -r ab6ffc260785 -r fec4c1fb2ac8 src/protocols/oscar/aim_cbtypes.h --- 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 /* diff -r ab6ffc260785 -r fec4c1fb2ac8 src/protocols/oscar/locate.c --- 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; diff -r ab6ffc260785 -r fec4c1fb2ac8 src/protocols/oscar/oscar.c --- 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, "
", "\n"); + const gchar *tmp3; + tmp1 = gaim_strcasereplace(away_utf8, "
", "\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, _("Away Message: "), 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); } diff -r ab6ffc260785 -r fec4c1fb2ac8 src/util.c --- 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
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, "
")) != NULL) { - /* replace
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, "
"); - 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 "
" 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], "
"); + 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) { diff -r ab6ffc260785 -r fec4c1fb2ac8 src/util.h --- 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