Mercurial > pidgin
changeset 5836:09f7f23dc83a
[gaim-migrate @ 6267]
I think I've fixed the negative online time for real, now. Or, at least
reduced the frequency of it happening. Also added the ability to see
iChat's "available" messages.
Sean, I ended up changing more than I thought I would have to, but that's
partially because I like to change things a lot.
If it conflicts or whatever feel free to back it out and I can re-patch it
back in when you're done with your stuff.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 12 Jun 2003 03:27:58 +0000 |
parents | 9a08899192ee |
children | a48c338dff6c |
files | ChangeLog src/protocols/oscar/aim.h src/protocols/oscar/aim_internal.h src/protocols/oscar/buddylist.c src/protocols/oscar/chat.c src/protocols/oscar/im.c src/protocols/oscar/info.c src/protocols/oscar/oscar.c src/protocols/oscar/service.c |
diffstat | 9 files changed, 171 insertions(+), 70 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Wed Jun 11 22:46:38 2003 +0000 +++ b/ChangeLog Thu Jun 12 03:27:58 2003 +0000 @@ -16,6 +16,7 @@ * Added Trepia support. * New Send IM buddy icon merged from Ximian Desktop 2 * Fixed "Sort by Status" crash + * Ability to view iChat "Available" messages version 0.64 (05/29/2003): * Buddy list sorting in buddy list preferences.
--- a/src/protocols/oscar/aim.h Wed Jun 11 22:46:38 2003 +0000 +++ b/src/protocols/oscar/aim.h Thu Jun 12 03:27:58 2003 +0000 @@ -929,8 +929,18 @@ #define AIM_FLAG_ACTIVEBUDDY 0x0400 #define AIM_FLAG_UNKNOWN800 0x0800 #define AIM_FLAG_ABINTERNAL 0x1000 +#define AIM_FLAG_ALLUSERS 0x001f -#define AIM_FLAG_ALLUSERS 0x001f +#define AIM_USERINFO_PRESENT_FLAGS 0x00000001 +#define AIM_USERINFO_PRESENT_MEMBERSINCE 0x00000002 +#define AIM_USERINFO_PRESENT_ONLINESINCE 0x00000004 +#define AIM_USERINFO_PRESENT_IDLE 0x00000008 +#define AIM_USERINFO_PRESENT_ICQEXTSTATUS 0x00000010 +#define AIM_USERINFO_PRESENT_ICQIPADDR 0x00000020 +#define AIM_USERINFO_PRESENT_ICQDATA 0x00000040 +#define AIM_USERINFO_PRESENT_CAPABILITIES 0x00000080 +#define AIM_USERINFO_PRESENT_SESSIONLEN 0x00000100 +#define AIM_USERINFO_PRESENT_CREATETIME 0x00000200 typedef struct { char sn[MAXSNLEN+1]; @@ -949,20 +959,10 @@ } icqinfo; fu32_t present; fu16_t iconcsumlen; - fu8_t iconcsum[30]; + fu8_t *iconcsum; + char *availablemsg; } aim_userinfo_t; -#define AIM_USERINFO_PRESENT_FLAGS 0x00000001 -#define AIM_USERINFO_PRESENT_MEMBERSINCE 0x00000002 -#define AIM_USERINFO_PRESENT_ONLINESINCE 0x00000004 -#define AIM_USERINFO_PRESENT_IDLE 0x00000008 -#define AIM_USERINFO_PRESENT_ICQEXTSTATUS 0x00000010 -#define AIM_USERINFO_PRESENT_ICQIPADDR 0x00000020 -#define AIM_USERINFO_PRESENT_ICQDATA 0x00000040 -#define AIM_USERINFO_PRESENT_CAPABILITIES 0x00000080 -#define AIM_USERINFO_PRESENT_SESSIONLEN 0x00000100 -#define AIM_USERINFO_PRESENT_CREATETIME 0x00000200 - faim_export const char *aim_userinfo_sn(aim_userinfo_t *ui); faim_export fu16_t aim_userinfo_flags(aim_userinfo_t *ui); faim_export fu16_t aim_userinfo_idle(aim_userinfo_t *ui);
--- a/src/protocols/oscar/aim_internal.h Wed Jun 11 22:46:38 2003 +0000 +++ b/src/protocols/oscar/aim_internal.h Thu Jun 12 03:27:58 2003 +0000 @@ -199,7 +199,8 @@ faim_internal int aim_msgcookie_gettype(int reqclass); faim_internal int aim_cookie_free(aim_session_t *sess, aim_msgcookie_t *cookie); -faim_internal int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *); +faim_internal void aim_info_free(aim_userinfo_t *); +faim_internal int aim_info_extract(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *); faim_internal int aim_putuserinfo(aim_bstream_t *bs, aim_userinfo_t *info); faim_internal int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo);
--- a/src/protocols/oscar/buddylist.c Wed Jun 11 22:46:38 2003 +0000 +++ b/src/protocols/oscar/buddylist.c Thu Jun 12 03:27:58 2003 +0000 @@ -232,11 +232,11 @@ * Subtypes 0x000b and 0x000c - Change in buddy status * * Oncoming Buddy notifications contain a subset of the - * user information structure. Its close enough to run - * through aim_extractuserinfo() however. + * user information structure. It's close enough to run + * through aim_info_extract() however. * * Although the offgoing notification contains no information, - * it is still in a format parsable by extractuserinfo. + * it is still in a format parsable by aim_info_extract(). * */ static int buddychange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) @@ -245,11 +245,13 @@ aim_userinfo_t userinfo; aim_rxcallback_t userfunc; - aim_extractuserinfo(sess, bs, &userinfo); + aim_info_extract(sess, bs, &userinfo); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, &userinfo); + aim_info_free(&userinfo); + return ret; }
--- a/src/protocols/oscar/chat.c Wed Jun 11 22:46:38 2003 +0000 +++ b/src/protocols/oscar/chat.c Thu Jun 12 03:27:58 2003 +0000 @@ -335,7 +335,7 @@ aim_bstream_init(&occbs, tmptlv->value, tmptlv->length); while (curoccupant < usercount) - aim_extractuserinfo(sess, &occbs, &userinfo[curoccupant++]); + aim_info_extract(sess, &occbs, &userinfo[curoccupant++]); } /* @@ -413,11 +413,11 @@ if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, - rx, + rx, &roominfo, roomname, usercount, - userinfo, + userinfo, roomdesc, flags, creationtime, @@ -428,6 +428,10 @@ } free(roominfo.name); + + while (usercount > 0) + aim_info_free(&userinfo[--usercount]); + free(userinfo); free(roomname); free(roomdesc); @@ -446,12 +450,13 @@ while (aim_bstream_empty(bs)) { curcount++; userinfo = realloc(userinfo, curcount * sizeof(aim_userinfo_t)); - aim_extractuserinfo(sess, bs, &userinfo[curcount-1]); + aim_info_extract(sess, bs, &userinfo[curcount-1]); } if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, curcount, userinfo); + aim_info_free(userinfo); free(userinfo); return ret; @@ -625,7 +630,7 @@ userinfotlv = aim_gettlv(otl, 0x0003, 1); aim_bstream_init(&tbs, userinfotlv->value, userinfotlv->length); - aim_extractuserinfo(sess, &tbs, &userinfo); + aim_info_extract(sess, &tbs, &userinfo); } /* @@ -659,6 +664,7 @@ if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, &userinfo, msg); + aim_info_free(&userinfo); free(cookie); free(msg); aim_freetlvchain(&otl);
--- a/src/protocols/oscar/im.c Wed Jun 11 22:46:38 2003 +0000 +++ b/src/protocols/oscar/im.c Thu Jun 12 03:27:58 2003 +0000 @@ -1919,16 +1919,15 @@ * with the TLVs read below, they are two different pieces. The * userinfo block contains the number of TLVs that contain user * information, the rest are not even though there is no seperation. - * aim_extractuserinfo() returns the number of bytes used by the - * userinfo tlvs, so you can start reading the rest of them right - * afterward. + * You can start reading the message TLVs after aim_info_extract() + * parses out the standard userinfo block. * * That also means that TLV types can be duplicated between the * userinfo block and the rest of the message, however there should * never be two TLVs of the same type in one block. * */ - aim_extractuserinfo(sess, bs, &userinfo); + aim_info_extract(sess, bs, &userinfo); /* * From here on, its depends on what channel we're on. @@ -1962,11 +1961,10 @@ aim_freetlvchain(&tlvlist); } else { - - faimdprintf(sess, 0, "icbm: ICBM received on an unsupported channel. Ignoring.\n (chan = %04x)", channel); + faimdprintf(sess, 0, "icbm: ICBM received on an unsupported channel. Ignoring. (chan = %04x)\n", channel); + } - return 0; - } + aim_info_free(&userinfo); return ret; } @@ -2014,12 +2012,14 @@ while (aim_bstream_empty(bs)) { channel = aimbs_get16(bs); - aim_extractuserinfo(sess, bs, &userinfo); + aim_info_extract(sess, bs, &userinfo); nummissed = aimbs_get16(bs); reason = aimbs_get16(bs); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, channel, &userinfo, nummissed, reason); + + aim_info_free(&userinfo); } return ret;
--- a/src/protocols/oscar/info.c Wed Jun 11 22:46:38 2003 +0000 +++ b/src/protocols/oscar/info.c Thu Jun 12 03:27:58 2003 +0000 @@ -443,11 +443,17 @@ return; } +faim_internal void aim_info_free(aim_userinfo_t *info) +{ + free(info->iconcsum); + free(info->availablemsg); +} + /* * AIM is fairly regular about providing user info. This is a generic * routine to extract it in its standard form. */ -faim_internal int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *outinfo) +faim_internal int aim_info_extract(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *outinfo) { int curtlv, tlvcnt; fu8_t snlen; @@ -636,24 +642,54 @@ /* * Type = 0x001d * - * Buddy icon information. This contains the info - * about the buddy icon that the user has stored on - * the server. + * Buddy icon information and available messages. + * + * This almost seems like the AIM protocol guys gave + * the iChat guys a Type, and the iChat guys tried to + * cram as much cool shit into it as possible. Then + * the Windows AIM guys were like, "hey, that's + * pretty neat, let's copy those prawns." + * + * In that spirit, this can contain a custom message, + * kind of like an away message, but you're not away + * (it's called an "available" message). Or it can + * contain information about the buddy icon the user + * has stored on the server. */ - int flags, number, len; - fu8_t *csum; + int type2, number, length2; while (aim_bstream_curpos(bs) < endpos) { - flags = aimbs_get16(bs); + type2 = 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); + length2 = aimbs_get8(bs); + + switch (type2) { + case 0x0000: { /* This is an official buddy icon? */ + /* This is always 5 bytes? */ + aim_bstream_advance(bs, length2); + } break; + + case 0x0001: { /* A buddy icon checksum */ + if ((length2 > 0) && (number == 0x01)) { + free(outinfo->iconcsum); + outinfo->iconcsum = aimbs_getraw(bs, length2); + outinfo->iconcsumlen = length2; + } else + aim_bstream_advance(bs, length2); + } break; + + case 0x0002: { /* An available message */ + if (length2 > 4) { + free(outinfo->availablemsg); + outinfo->availablemsg = aimbs_getstr(bs, aimbs_get16(bs)); + } else + aim_bstream_advance(bs, length2); + } break; + + default: { + aim_bstream_advance(bs, length2); + } break; + } } } else if (type == 0x001e) { @@ -686,7 +722,7 @@ } /* - * Inverse of aim_extractuserinfo() + * Inverse of aim_info_extract() */ faim_internal int aim_putuserinfo(aim_bstream_t *bs, aim_userinfo_t *info) { @@ -816,7 +852,7 @@ return 0; } - aim_extractuserinfo(sess, bs, &userinfo); + aim_info_extract(sess, bs, &userinfo); tlvlist = aim_readtlvchain(bs); @@ -854,10 +890,9 @@ if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, &userinfo, inforeq->infotype, text_encoding, text, textlen); + aim_info_free(&userinfo); free(text_encoding); - aim_freetlvchain(&tlvlist); - if (origsnac) free(origsnac->data); free(origsnac);
--- a/src/protocols/oscar/oscar.c Wed Jun 11 22:46:38 2003 +0000 +++ b/src/protocols/oscar/oscar.c Thu Jun 12 03:27:58 2003 +0000 @@ -159,19 +159,20 @@ time_t signon; int caps; gboolean typingnot; + gchar *availablemsg; + + unsigned long ico_me_len; + unsigned long ico_me_csum; + time_t ico_me_time; + gboolean ico_informed; unsigned long ico_len; unsigned long ico_csum; time_t ico_time; gboolean ico_need; - unsigned long ico_me_len; - unsigned long ico_me_csum; - time_t ico_me_time; - gboolean ico_informed; - fu16_t iconcsumlen; - fu8_t iconcsum[30]; + fu8_t *iconcsum; }; struct name_data { @@ -286,12 +287,19 @@ /* prpl actions - remove this at some point */ static void oscar_set_info(GaimConnection *gc, char *text); -static void gaim_free_name_data(struct name_data *data) { +static void oscar_free_name_data(struct name_data *data) { g_free(data->name); g_free(data->nick); g_free(data); } +static void oscar_free_buddyinfo(void *data) { + struct buddyinfo *bi = data; + g_free(bi->availablemsg); + g_free(bi->iconcsum); + g_free(bi); +} + static fu32_t oscar_encoding_check(const char *utf8) { int i = 0; @@ -654,7 +662,7 @@ gc->flags |= OPT_CONN_HTML; gc->flags |= OPT_CONN_AUTO_RESP; } - od->buddyinfo = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + od->buddyinfo = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, oscar_free_buddyinfo); sess = g_new0(aim_session_t, 1); @@ -1787,7 +1795,9 @@ time_idle -= info->idletime*60; } - if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) + if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE) + signon = info->onlinesince; + else if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) signon = time(NULL) - info->sessionlen; if (!aim_sncmp(gaim_account_get_username(gaim_connection_get_account(gc)), info->sn)) @@ -1803,12 +1813,18 @@ bi->caps = caps; bi->typingnot = FALSE; bi->ico_informed = FALSE; + if (info->availablemsg) { + free(bi->availablemsg); + bi->availablemsg = g_strdup(info->availablemsg); + } /* Server stored icon stuff */ if (info->iconcsumlen) { char *b16, *saved_b16; struct buddy *b; + free(bi->iconcsum); + bi->iconcsum = malloc(info->iconcsumlen); memcpy(bi->iconcsum, info->iconcsum, info->iconcsumlen); bi->iconcsumlen = info->iconcsumlen; b16 = tobase16(bi->iconcsum, bi->iconcsumlen); @@ -2424,7 +2440,7 @@ gaim_request_input(data->gc, NULL, _("Authorization Request Message:"), NULL, _("Please authorize me!"), TRUE, _("OK"), G_CALLBACK(gaim_auth_request), - _("Cancel"), G_CALLBACK(gaim_free_name_data), + _("Cancel"), G_CALLBACK(oscar_free_name_data), data); } @@ -2436,7 +2452,7 @@ /* XXX - Take the buddy out of our buddy list */ } - gaim_free_name_data(data); + oscar_free_name_data(data); } static void gaim_auth_sendrequest(GaimConnection *gc, const char *name) { @@ -2483,7 +2499,7 @@ #endif } - gaim_free_name_data(data); + oscar_free_name_data(data); } /* When other people ask you for authorization */ @@ -2504,7 +2520,7 @@ gaim_request_input(data->gc, NULL, _("Authorization Denied Message:"), NULL, _("No reason given."), TRUE, _("OK"), G_CALLBACK(gaim_auth_dontgrant), - _("Cancel"), G_CALLBACK(gaim_free_name_data), + _("Cancel"), G_CALLBACK(oscar_free_name_data), data); } @@ -2516,7 +2532,7 @@ show_add_buddy(gc, data->name, NULL, data->nick); } - gaim_free_name_data(data); + oscar_free_name_data(data); } static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch4_args *args, time_t t) { @@ -2656,7 +2672,7 @@ "to your Buddy List?"), 0, data, 2, _("Add"), G_CALLBACK(gaim_icq_contactadd), - _("Decline"), G_CALLBACK(gaim_free_name_data)); + _("Decline"), G_CALLBACK(oscar_free_name_data)); g_free(message); } g_strfreev(text); @@ -5000,7 +5016,7 @@ gaim_request_yes_no(gc, NULL, _("Authorization Given"), dialog_msg, 0, data, G_CALLBACK(gaim_icq_contactadd), - G_CALLBACK(gaim_free_name_data)); + G_CALLBACK(oscar_free_name_data)); g_free(dialog_msg); g_free(nombre); @@ -5353,6 +5369,12 @@ yay = g_strconcat(tmp, _("<b>Capabilities:</b> "), caps, "\n", NULL); free(tmp); } + + if (bi->availablemsg) { + tmp = yay; + yay = g_strconcat(tmp, _("<b>Available:</b> "), bi->availablemsg, "\n", NULL); + free(tmp); + } } } else { char *gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, b->name); @@ -5383,7 +5405,11 @@ ret = gaim_icq_status((b->uc & 0xffff0000) >> 16); else ret = g_strdup(_("Away")); - } else if (!GAIM_BUDDY_IS_ONLINE(b)) { + } else if (GAIM_BUDDY_IS_ONLINE(b)) { + struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, normalize(b->name)); + if (bi->availablemsg) + ret = g_strdup(bi->availablemsg); + } else { char *gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, b->name); if (aim_ssi_waitingforauth(od->sess->ssi.local, gname, b->name)) ret = g_strdup(_("Not Authorized"));
--- a/src/protocols/oscar/service.c Wed Jun 11 22:46:38 2003 +0000 +++ b/src/protocols/oscar/service.c Thu Jun 12 03:27:58 2003 +0000 @@ -501,11 +501,13 @@ aim_rxcallback_t userfunc; aim_userinfo_t userinfo; - aim_extractuserinfo(sess, bs, &userinfo); + aim_info_extract(sess, bs, &userinfo); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, &userinfo); + aim_info_free(&userinfo); + return ret; } @@ -522,11 +524,13 @@ newevil = aimbs_get16(bs); if (aim_bstream_empty(bs)) - aim_extractuserinfo(sess, bs, &userinfo); + aim_info_extract(sess, bs, &userinfo); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, newevil, &userinfo); + aim_info_free(&userinfo); + return ret; } @@ -938,6 +942,30 @@ return 0; } +/* + * Subtype 0x0021 - Receive our extended status + * + * This is used for MAC non-away "away" messages, and maybe ICQ extended status messages? + */ +static int aim_parse_extstatus(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) +{ + int ret = 0; + aim_rxcallback_t userfunc; + char *msg = NULL; + fu16_t id; + + aimbs_get16(bs); /* 0x0002 */ + aimbs_get16(bs); /* 0x0404 or 0x0407? Maybe 0x04 and then a length? */ + msg = aimbs_getstr(bs, aimbs_get16(bs)); + + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, msg); + + free(msg); + + return ret; +} + static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { @@ -965,6 +993,8 @@ return hostversions(sess, mod, rx, snac, bs); else if (snac->subtype == 0x001f) return memrequest(sess, mod, rx, snac, bs); + else if (snac->subtype == 0x0021) + return aim_parse_extstatus(sess, mod, rx, snac, bs); return 0; }