# HG changeset patch # User Eric Warmenhoven # Date 977195286 0 # Node ID 4c5c2fcb83cd0cc2bdd9e6a6212a771a016552a7 # Parent e973ef7a8a87ecbb411f8713a51d7d83086dde29 [gaim-migrate @ 1312] libfaim stuff committer: Tailor Script diff -r e973ef7a8a87 -r 4c5c2fcb83cd libfaim/CHANGES --- a/libfaim/CHANGES Tue Dec 19 01:29:13 2000 +0000 +++ b/libfaim/CHANGES Tue Dec 19 03:08:06 2000 +0000 @@ -1,6 +1,30 @@ No release numbers ------------------ + - Sun Dec 17 07:19:04 UTC 2000 + - Update the capability block list + + - Sat Dec 16 01:34:19 UTC 2000 + - Rename paramid to rateclass + - Add a long comment about the rate system + - Add a few other comments + - Clean up aim_bos_clientready(). + + - Fri Dec 15 23:35:01 UTC 2000 + - Add genericerr callback/middle. + - This is for catching the errors that come back, for instance, from + sending a SNAC that isn't supported by the host (such as the + Watcher Request SNAC). + + - Fri Dec 15 21:51:32 UTC 2000 + - Add more info to evilnotify callback + - Add a few values to aim_cbtypes.h + + - Fri Dec 15 20:41:15 UTC 2000 + - Revise README + - Make aimdebugd compile + - Typos + - Fri Dec 15 02:04:12 UTC 2000 - Parse rate changes *properly* - Add sample code to faimtest demonstrating my approximations diff -r e973ef7a8a87 -r 4c5c2fcb83cd libfaim/README --- a/libfaim/README Tue Dec 19 01:29:13 2000 +0000 +++ b/libfaim/README Tue Dec 19 03:08:06 2000 +0000 @@ -4,7 +4,7 @@ This is libfaim, the purpose of which is to implement as much as the AOL AIM/OSCAR protocol as possible (which should be all of it). After -over a year of development, its still nowhere close. +over two years of development, its still nowhere close. This is not a full client and never will be. libfaim only implements the routines to implement a client (ie, there's no user interface). @@ -16,7 +16,11 @@ beta-quality and I know it leaks memory quite badly. It seems fairly stable, however. YMMV, YAYOR, etc. I suppose I should say regardless of that warning, that several clients use it and people use those clients -on a daily basis (in particular, me). +on a daily basis (in particular, me). Also, you're probably reading this +from a CVS version, since I haven't made a release in a very long time. +The CVS version changes fairly rapidly when I'm in the mood, so a version +you checked out an hour ago may be better or worse than a version you +check out now. Building diff -r e973ef7a8a87 -r 4c5c2fcb83cd libfaim/README.gaim --- a/libfaim/README.gaim Tue Dec 19 01:29:13 2000 +0000 +++ b/libfaim/README.gaim Tue Dec 19 03:08:06 2000 +0000 @@ -67,7 +67,8 @@ KNOWN ISSUES ============ - Oscar doesn't do whispering in chat rooms any more (and hasn't for quite a -while, evidently). So if you want to "whisper" to someone, just IM them. +while, evidently). So if you want to "whisper" to someone, just IM them. (TOC +doesn't either?) - Gaim/TOC can do some RVOUS actions, and Gaim/Faim can do others. This is not because there is any difference in the protocols as far as the actual transfer @@ -77,12 +78,8 @@ - What *is* protocol-dependent about the RVOUS stuff is that only Oscar can request RVOUS actions, though both can receive them. -- Temporarily removed Direct IM pending a UI change - - Getting Dir Info is not in libfaim yet, and so is not in Gaim/Faim yet. -- Warnings are there now. Yes, I know it says the wrong value. - - There are also FIXME's scattered about gaim. Grep around for those, figure out what needs to be fixed, do that sort of thing. :) (Fixing the things listed in KNOWN ISSUES above, or any other bugs you happen to find, is a very good use diff -r e973ef7a8a87 -r 4c5c2fcb83cd libfaim/aim_info.c --- a/libfaim/aim_info.c Tue Dec 19 01:29:13 2000 +0000 +++ b/libfaim/aim_info.c Tue Dec 19 03:08:06 2000 +0000 @@ -94,7 +94,7 @@ /* * Capability blocks. */ -u_char aim_caps[6][16] = { +u_char aim_caps[8][16] = { /* Buddy icon */ {0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1, @@ -118,7 +118,15 @@ /* Send file */ {0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}, + + /* Saves stock portfolios */ + {0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}, + + /* Games */ + {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1, + 0x22, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}, }; faim_internal unsigned short aim_getcap(unsigned char *capblock, int buflen) @@ -126,21 +134,29 @@ u_short ret = 0; int y; int offset = 0; + int identified; while (offset < buflen) { + identified = 0; for(y=0; y < (sizeof(aim_caps)/0x10); y++) { if (memcmp(&aim_caps[y], capblock+offset, 0x10) == 0) { switch(y) { - case 0: ret |= AIM_CAPS_BUDDYICON; break; - case 1: ret |= AIM_CAPS_VOICE; break; - case 2: ret |= AIM_CAPS_IMIMAGE; break; - case 3: ret |= AIM_CAPS_CHAT; break; - case 4: ret |= AIM_CAPS_GETFILE; break; - case 5: ret |= AIM_CAPS_SENDFILE; break; - default: ret |= 0xff00; break; + case 0: ret |= AIM_CAPS_BUDDYICON; identified++; break; + case 1: ret |= AIM_CAPS_VOICE; identified++; break; + case 2: ret |= AIM_CAPS_IMIMAGE; identified++; break; + case 3: ret |= AIM_CAPS_CHAT; identified++; break; + case 4: ret |= AIM_CAPS_GETFILE; identified++; break; + case 5: ret |= AIM_CAPS_SENDFILE; identified++; break; + case 6: ret |= AIM_CAPS_GAMES; identified++; break; + case 7: ret |= AIM_CAPS_SAVESTOCKS; identified++; break; } } } + if (!identified) { + printf("faim: unknown capability!\n"); + ret |= 0xff00; + } + offset += 0x10; } return ret; @@ -177,6 +193,14 @@ memcpy(capblock+offset, aim_caps[5], sizeof(aim_caps[5])); offset += sizeof(aim_caps[5]); } + if ((caps & AIM_CAPS_GAMES) && (offset < buflen)) { + memcpy(capblock+offset, aim_caps[6], sizeof(aim_caps[6])); + offset += sizeof(aim_caps[6]); + } + if ((caps & AIM_CAPS_SAVESTOCKS) && (offset < buflen)) { + memcpy(capblock+offset, aim_caps[7], sizeof(aim_caps[7])); + offset += sizeof(aim_caps[7]); + } return offset; } diff -r e973ef7a8a87 -r 4c5c2fcb83cd libfaim/aim_login.c --- a/libfaim/aim_login.c Tue Dec 19 01:29:13 2000 +0000 +++ b/libfaim/aim_login.c Tue Dec 19 03:08:06 2000 +0000 @@ -361,6 +361,14 @@ /* * The registration status. (Not real sure what it means.) * Not available for ICQ logins. + * + * 1 = No disclosure + * 2 = Limited disclosure + * 3 = Full disclosure + * + * This has to do with whether your email address is available + * to other users or not. AFAIK, this feature is no longer used. + * */ if (aim_gettlv(tlvlist, 0x0013, 1)) regstatus = aim_gettlv16(tlvlist, 0x0013, 1); diff -r e973ef7a8a87 -r 4c5c2fcb83cd libfaim/aim_misc.c --- a/libfaim/aim_misc.c Tue Dec 19 01:29:13 2000 +0000 +++ b/libfaim/aim_misc.c Tue Dec 19 03:08:06 2000 +0000 @@ -301,79 +301,57 @@ * * Send Client Ready. * - * TODO: Dynamisize. - * */ faim_export unsigned long aim_bos_clientready(struct aim_session_t *sess, struct aim_conn_t *conn) { - u_char command_2[] = { - /* placeholders for dynamic data */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, - /* real data */ - 0x00, 0x01, - 0x00, 0x03, - 0x00, 0x04, - 0x06, 0x86, /* the good ones */ -#if 0 - 0x07, 0xda, /* DUPLE OF DEATH! */ -#endif +#define AIM_TOOL_JAVA 0x0001 +#define AIM_TOOL_MAC 0x0002 +#define AIM_TOOL_WIN16 0x0003 +#define AIM_TOOL_WIN32 0x0004 +#define AIM_TOOL_MAC68K 0x0005 +#define AIM_TOOL_MACPPC 0x0006 + struct aim_tool_version { + unsigned short group; + unsigned short version; + unsigned short tool; + unsigned short toolversion; + } tools[] = { + {0x0001, 0x0003, AIM_TOOL_WIN32, 0x0686}, + {0x0002, 0x0001, AIM_TOOL_WIN32, 0x0001}, + {0x0003, 0x0001, AIM_TOOL_WIN32, 0x0001}, + {0x0004, 0x0001, AIM_TOOL_WIN32, 0x0001}, + {0x0006, 0x0001, AIM_TOOL_WIN32, 0x0001}, + {0x0008, 0x0001, AIM_TOOL_WIN32, 0x0001}, + {0x0009, 0x0001, AIM_TOOL_WIN32, 0x0001}, + {0x000a, 0x0001, AIM_TOOL_WIN32, 0x0001}, + {0x000b, 0x0001, AIM_TOOL_WIN32, 0x0001} + }; + int i,j; + struct command_tx_struct *newpacket; + int toolcount = sizeof(tools)/sizeof(struct aim_tool_version); - 0x00, 0x02, - 0x00, 0x01, - 0x00, 0x04, - 0x00, 0x01, - - 0x00, 0x03, - 0x00, 0x01, - 0x00, 0x04, - 0x00, 0x01, - - 0x00, 0x04, - 0x00, 0x01, - 0x00, 0x04, - 0x00, 0x01, - - 0x00, 0x06, - 0x00, 0x01, - 0x00, 0x04, - 0x00, 0x01, - 0x00, 0x08, - 0x00, 0x01, - 0x00, 0x04, - 0x00, 0x01, - - 0x00, 0x09, - 0x00, 0x01, - 0x00, 0x04, - 0x00, 0x01, - 0x00, 0x0a, - 0x00, 0x01, - 0x00, 0x04, - 0x00, 0x01, - - 0x00, 0x0b, - 0x00, 0x01, - 0x00, 0x04, - 0x00, 0x01 - }; - int command_2_len = 0x52; - struct command_tx_struct *newpacket; - - if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, command_2_len))) + if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 1152))) return -1; newpacket->lock = 1; - memcpy(newpacket->data, command_2, command_2_len); - - /* This write over the dynamic parts of the byte block */ - aim_putsnac(newpacket->data, 0x0001, 0x0002, 0x0000, sess->snac_nextid); + i = aim_putsnac(newpacket->data, 0x0001, 0x0002, 0x0000, sess->snac_nextid); + aim_cachesnac(sess, 0x0001, 0x0002, 0x0000, NULL, 0); + + for (j = 0; j < toolcount; j++) { + i += aimutil_put16(newpacket->data+i, tools[j].group); + i += aimutil_put16(newpacket->data+i, tools[j].version); + i += aimutil_put16(newpacket->data+i, tools[j].tool); + i += aimutil_put16(newpacket->data+i, tools[j].toolversion); + } + + newpacket->commandlen = i; + newpacket->lock = 0; aim_tx_enqueue(sess, newpacket); - return (sess->snac_nextid++); + return sess->snac_nextid; } /* diff -r e973ef7a8a87 -r 4c5c2fcb83cd libfaim/aim_rxhandlers.c --- a/libfaim/aim_rxhandlers.c Tue Dec 19 01:29:13 2000 +0000 +++ b/libfaim/aim_rxhandlers.c Tue Dec 19 03:08:06 2000 +0000 @@ -480,7 +480,7 @@ workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr); } break; - case 0x0004: /* Family: Messeging */ + case 0x0004: /* Family: Messaging */ switch (subtype) { case 0x0001: workingPtr->handled = aim_parse_msgerror_middle(sess, workingPtr); @@ -533,6 +533,10 @@ workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr); break; } + case 0x0013: { + printf("lalala: 0x%04x/0x%04x\n", family, subtype); + break; + } case AIM_CB_FAM_SPECIAL: workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr); break; @@ -655,13 +659,62 @@ return ret; } +/* + * The Rate Limiting System, An Abridged Guide to Nonsense. + * + * OSCAR defines several 'rate classes'. Each class has seperate + * rate limiting properties (limit level, alert level, disconnect + * level, etc), and a set of SNAC family/type pairs associated with + * it. The rate classes, their limiting properties, and the definitions + * of which SNACs are belong to which class, are defined in the + * Rate Response packet at login to each host. + * + * Logically, all rate offenses within one class count against further + * offenses for other SNACs in the same class (ie, sending messages + * too fast will limit the number of user info requests you can send, + * since those two SNACs are in the same rate class). + * + * Since the rate classes are defined dynamically at login, the values + * below may change. But they seem to be fairly constant. + * + * Currently, BOS defines five rate classes, with the commonly used + * members as follows... + * + * Rate class 0x0001: + * - Everything thats not in any of the other classes + * + * Rate class 0x0002: + * - Buddy list add/remove + * - Permit list add/remove + * - Deny list add/remove + * + * Rate class 0x0003: + * - User information requests + * - Outgoing ICBMs + * + * Rate class 0x0004: + * - A few unknowns: 2/9, 2/b, and f/2 + * + * Rate class 0x0005: + * - Chat room create + * - Outgoing chat ICBMs + * + * The only other thing of note is that class 5 (chat) has slightly looser + * limiting properties than class 3 (normal messages). But thats just a + * small bit of trivia for you. + * + * The last thing that needs to be learned about the rate limiting + * system is how the actual numbers relate to the passing of time. This + * seems to be a big mystery. + * + */ faim_internal int aim_parse_ratechange_middle(struct aim_session_t *sess, struct command_rx_struct *command) { rxcallback_t userfunc = NULL; int ret = 1; int i; int code; - unsigned long parmid, windowsize, clear, alert, limit, disconnect; + unsigned long rateclass, windowsize, clear, alert, limit, disconnect; unsigned long currentavg, maxavg; i = 10; @@ -669,7 +722,7 @@ code = aimutil_get16(command->data+i); i += 2; - parmid = aimutil_get16(command->data+i); + rateclass = aimutil_get16(command->data+i); i += 2; windowsize = aimutil_get32(command->data+i); @@ -688,7 +741,7 @@ i += 4; if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x000a))) - ret = userfunc(sess, command, code, parmid, windowsize, clear, alert, limit, disconnect, currentavg, maxavg); + ret = userfunc(sess, command, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg); return ret; } @@ -696,25 +749,22 @@ faim_internal int aim_parse_evilnotify_middle(struct aim_session_t *sess, struct command_rx_struct *command) { rxcallback_t userfunc = NULL; - int ret = 1, pos; - char *sn = NULL; - - if(command->commandlen < 12) /* a warning level dec sends this */ - return 1; + int ret = 1; + int i; + unsigned short newevil; + struct aim_userinfo_s userinfo; - if ((pos = aimutil_get8(command->data+ 12)) > MAXSNLEN) - return 1; + i = 10; + newevil = aimutil_get16(command->data+10); + i += 2; - if(!(sn = (char *)calloc(1, pos+1))) - return 1; - - memcpy(sn, command->data+13, pos); + memset(&userinfo, 0, sizeof(struct aim_userinfo_s)); + if (command->commandlen-i) + i += aim_extractuserinfo(command->data+i, &userinfo); if ((userfunc = aim_callhandler(command->conn, 0x0001, 0x0010))) - ret = userfunc(sess, command, sn); + ret = userfunc(sess, command, newevil, &userinfo); - free(sn); - return ret; } @@ -906,20 +956,22 @@ faim_internal int aim_parse_generalerrs(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - u_short family; - u_short subtype; + unsigned short family; + unsigned short subtype; + int ret = 1; + int error = 0; + rxcallback_t userfunc = NULL; family = aimutil_get16(command->data+0); subtype= aimutil_get16(command->data+2); - switch(family) - { - default: - /* Unknown family */ - return aim_callhandler_noparam(sess, command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, command); - } + if (command->commandlen > 10) + error = aimutil_get16(command->data+10); - return 1; + if ((userfunc = aim_callhandler(command->conn, family, subtype))) + ret = userfunc(sess, command, error); + + return ret; } diff -r e973ef7a8a87 -r 4c5c2fcb83cd libfaim/faim/aim.h --- a/libfaim/faim/aim.h Tue Dec 19 01:29:13 2000 +0000 +++ b/libfaim/faim/aim.h Tue Dec 19 03:08:06 2000 +0000 @@ -620,8 +620,10 @@ #define AIM_CAPS_CHAT 0x08 #define AIM_CAPS_GETFILE 0x10 #define AIM_CAPS_SENDFILE 0x20 +#define AIM_CAPS_GAMES 0x40 +#define AIM_CAPS_SAVESTOCKS 0x80 -extern u_char aim_caps[6][16]; +extern u_char aim_caps[8][16]; faim_internal unsigned short aim_getcap(unsigned char *capblock, int buflen); faim_internal int aim_putcap(unsigned char *capblock, int buflen, u_short caps); diff -r e973ef7a8a87 -r 4c5c2fcb83cd libfaim/faim/aim_cbtypes.h --- a/libfaim/faim/aim_cbtypes.h Tue Dec 19 01:29:13 2000 +0000 +++ b/libfaim/faim/aim_cbtypes.h Tue Dec 19 03:08:06 2000 +0000 @@ -128,6 +128,8 @@ * SNAC Family: Misc BOS Services. */ #define AIM_CB_BOS_ERROR 0x0001 +#define AIM_CB_BOS_RIGHTSQUERY 0x0002 +#define AIM_CB_BOS_RIGHTS 0x0003 #define AIM_CB_BOS_DEFAULT 0xffff /* diff -r e973ef7a8a87 -r 4c5c2fcb83cd plugins/yay/yay.c --- a/plugins/yay/yay.c Tue Dec 19 01:29:13 2000 +0000 +++ b/plugins/yay/yay.c Tue Dec 19 03:08:06 2000 +0000 @@ -401,6 +401,7 @@ ret->name = yahoo_name; ret->list_icon = yahoo_list_icon; ret->action_menu = yahoo_action_menu; + ret->user_opts = NULL; ret->login = yahoo_login; ret->close = yahoo_close; ret->send_im = yahoo_send_im; diff -r e973ef7a8a87 -r 4c5c2fcb83cd src/oscar.c --- a/src/oscar.c Tue Dec 19 01:29:13 2000 +0000 +++ b/src/oscar.c Tue Dec 19 03:08:06 2000 +0000 @@ -56,7 +56,8 @@ #define USEROPT_SOCKSPORT 3 int gaim_caps = AIM_CAPS_CHAT | AIM_CAPS_SENDFILE | AIM_CAPS_GETFILE | - AIM_CAPS_VOICE | AIM_CAPS_IMIMAGE | AIM_CAPS_BUDDYICON; + AIM_CAPS_VOICE | AIM_CAPS_IMIMAGE | AIM_CAPS_BUDDYICON | + AIM_CAPS_GAMES | AIM_CAPS_SAVESTOCKS; struct oscar_data { struct aim_session_t *sess; @@ -248,6 +249,7 @@ static int gaim_parse_msgerr (struct aim_session_t *, struct command_rx_struct *, ...); static int gaim_parse_buddyrights(struct aim_session_t *, struct command_rx_struct *, ...); static int gaim_parse_locerr (struct aim_session_t *, struct command_rx_struct *, ...); +static int gaim_parse_genericerr (struct aim_session_t *, struct command_rx_struct *, ...); static int gaim_directim_initiate (struct aim_session_t *, struct command_rx_struct *, ...); static int gaim_directim_incoming (struct aim_session_t *, struct command_rx_struct *, ...); @@ -561,6 +563,9 @@ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_CTN, AIM_CB_CTN_DEFAULT, aim_parse_unknown, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, gaim_parse_motd, 0); + aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, gaim_parse_genericerr, 0); + aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, gaim_parse_genericerr, 0); + aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, gaim_parse_genericerr, 0); aim_auth_sendcookie(sess, bosconn, cookie); ((struct oscar_data *)gc->proto_data)->conn = bosconn; @@ -1224,6 +1229,20 @@ return 1; } +int gaim_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...) { + va_list ap; + unsigned short reason; + + va_start(ap, command); + reason = va_arg(ap, int); + va_end(ap); + + debug_printf("snac threw error (reason 0x%04x: %s\n", reason, + (reason < msgerrreasonlen) ? msgerrreason[reason] : "unknown"); + + return 1; +} + int gaim_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...) { va_list ap; @@ -1519,12 +1538,12 @@ "limit cleared"}; va_list ap; int code; - unsigned long parmid, windowsize, clear, alert, limit, disconnect; + unsigned long rateclass, windowsize, clear, alert, limit, disconnect; unsigned long currentavg, maxavg; va_start(ap, command); code = va_arg(ap, int); - parmid = va_arg(ap, int); + rateclass= va_arg(ap, int); windowsize = va_arg(ap, unsigned long); clear = va_arg(ap, unsigned long); alert = va_arg(ap, unsigned long); @@ -1537,7 +1556,7 @@ debug_printf("rate %s (paramid 0x%04lx): curavg = %ld, maxavg = %ld, alert at %ld, " "clear warning at %ld, limit at %ld, disconnect at %ld (window size = %ld)\n", (code < 5) ? codes[code] : codes[0], - parmid, + rateclass, currentavg, maxavg, alert, clear, limit, disconnect, @@ -1559,14 +1578,16 @@ int gaim_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...) { va_list ap; - char *sn; + int newevil; + struct aim_userinfo_s *userinfo; struct gaim_connection *gc = find_gaim_conn_by_aim_sess(sess); va_start(ap, command); - sn = va_arg(ap, char *); + newevil = va_arg(ap, int); + userinfo = va_arg(ap, struct aim_userinfo_s *); va_end(ap); - serv_got_eviled(gc, sn, 0); + serv_got_eviled(gc, (userinfo && userinfo->sn[0]) ? userinfo->sn : NULL, newevil / 10); return 1; }