# HG changeset patch # User Eric Warmenhoven # Date 998857305 0 # Node ID edf8c5a70e5b6ff4c23c2c2cb360ccd083cb20df # Parent dbd74f49dabb1fbf23e0aed890115a042adac7df [gaim-migrate @ 2177] limiting chat message lengths committer: Tailor Script diff -r dbd74f49dabb -r edf8c5a70e5b src/conversation.c --- a/src/conversation.c Sun Aug 26 19:18:39 2001 +0000 +++ b/src/conversation.c Sun Aug 26 20:21:45 2001 +0000 @@ -865,7 +865,7 @@ play_sound(SEND); } } else { - serv_chat_send(c->gc, c->id, buf); + err = serv_chat_send(c->gc, c->id, buf); /* no sound because we do that when we receive our message */ } diff -r dbd74f49dabb -r edf8c5a70e5b src/gaim.h --- a/src/gaim.h Sun Aug 26 19:18:39 2001 +0000 +++ b/src/gaim.h Sun Aug 26 20:21:45 2001 +0000 @@ -677,7 +677,7 @@ extern void serv_chat_invite(struct gaim_connection *, int, char *, char *); extern void serv_chat_leave(struct gaim_connection *, int); extern void serv_chat_whisper(struct gaim_connection *, int, char *, char *); -extern void serv_chat_send(struct gaim_connection *, int, char *); +extern int serv_chat_send(struct gaim_connection *, int, char *); extern void serv_chat_set_topic(struct gaim_connection *, int, char *); extern void update_keepalive(struct gaim_connection *, gboolean); diff -r dbd74f49dabb -r edf8c5a70e5b src/protocols/irc/irc.c --- a/src/protocols/irc/irc.c Sun Aug 26 19:18:39 2001 +0000 +++ b/src/protocols/irc/irc.c Sun Aug 26 20:21:45 2001 +0000 @@ -308,7 +308,7 @@ } static void irc_chat_leave(struct gaim_connection *gc, int id); -static void irc_chat_send(struct gaim_connection *gc, int id, char *message) +static int irc_chat_send(struct gaim_connection *gc, int id, char *message) { struct irc_data *idata = (struct irc_data *)gc->proto_data; @@ -323,7 +323,7 @@ if (!channel) { /* If for some reason we've lost our channel, let's bolt */ g_free(buf); - return; + return -EINVAL; } @@ -416,7 +416,7 @@ irc_chat_leave(gc, id); is_command = TRUE; - return; + return 0; } @@ -431,7 +431,7 @@ irc_join_chat(gc, 0, temp); g_free(temp); is_command = TRUE; - return; + return 0; } else if (!g_strncasecmp(message, "/raw ", 5) && (strlen(message) > 5)) { @@ -524,8 +524,9 @@ g_free(buf); - + return 0; } + static struct conversation *find_conversation_by_id(struct gaim_connection *gc, int id) { GSList *bc = gc->buddy_chats; diff -r dbd74f49dabb -r edf8c5a70e5b src/protocols/jabber/jabber.c --- a/src/protocols/jabber/jabber.c Sun Aug 26 19:18:39 2001 +0000 +++ b/src/protocols/jabber/jabber.c Sun Aug 26 20:21:45 2001 +0000 @@ -1447,7 +1447,7 @@ jc->b = NULL; } -static void jabber_chat_send(struct gaim_connection *gc, int id, char *message) +static int jabber_chat_send(struct gaim_connection *gc, int id, char *message) { GSList *bcs = gc->buddy_chats; struct conversation *b; @@ -1463,7 +1463,7 @@ bcs = bcs->next; } if (!bcs) - return; + return -EINVAL; bcs = jd->existing_chats; while (bcs) { @@ -1473,7 +1473,7 @@ bcs = bcs->next; } if (!bcs) - return; + return -EINVAL; x = xmlnode_new_tag("message"); xmlnode_put_attrib(x, "from", jid_full(jc->Jid)); @@ -1491,6 +1491,7 @@ gjab_send(((struct jabber_data *)gc->proto_data)->jc, x); xmlnode_free(x); + return 0; } static void jabber_chat_set_topic(struct gaim_connection *gc, int id, char *topic) diff -r dbd74f49dabb -r edf8c5a70e5b src/protocols/msn/msn.c --- a/src/protocols/msn/msn.c Sun Aug 26 19:18:39 2001 +0000 +++ b/src/protocols/msn/msn.c Sun Aug 26 20:21:45 2001 +0000 @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -1170,13 +1171,13 @@ return 0; } -static void msn_chat_send(struct gaim_connection *gc, int id, char *message) +static int msn_chat_send(struct gaim_connection *gc, int id, char *message) { struct msn_switchboard *ms = msn_find_switch_by_id(gc, id); char buf[MSN_BUF_LEN]; if (!ms) - return; + return -EINVAL; g_snprintf(buf, sizeof(buf), "MSG %d N %d\r\n%s%s", ++ms->trId, strlen(MIME_HEADER) + strlen(message), @@ -1185,6 +1186,7 @@ msn_kill_switch(ms); debug_printf("\n"); serv_got_chat_in(gc, id, gc->username, 0, message, time(NULL)); + return 0; } static void msn_chat_invite(struct gaim_connection *gc, int id, char *msg, char *who) diff -r dbd74f49dabb -r edf8c5a70e5b src/protocols/napster/napster.c --- a/src/protocols/napster/napster.c Sun Aug 26 19:18:39 2001 +0000 +++ b/src/protocols/napster/napster.c Sun Aug 26 20:21:45 2001 +0000 @@ -952,7 +952,7 @@ } -static void nap_chat_send(struct gaim_connection *gc, int id, char *message) +static int nap_chat_send(struct gaim_connection *gc, int id, char *message) { struct nap_channel *channel = NULL; gchar buf[NAP_BUF_LEN]; @@ -961,12 +961,12 @@ if (!channel) { /* This shouldn't happen */ - return; + return -EINVAL; } g_snprintf(buf, NAP_BUF_LEN, "%s %s", channel->name, message); nap_write_packet(gc, 0x192, buf); - + return 0; } static void nap_add_buddy(struct gaim_connection *gc, char *name) diff -r dbd74f49dabb -r edf8c5a70e5b src/protocols/oscar/CHANGES --- a/src/protocols/oscar/CHANGES Sun Aug 26 19:18:39 2001 +0000 +++ b/src/protocols/oscar/CHANGES Sun Aug 26 20:21:45 2001 +0000 @@ -1,6 +1,39 @@ No release numbers ------------------ + - Sat Aug 25 19:46:38 PDT 2001 + - Pass "Maximum visible message length" to client in chat info update + - This is the real maximum message length now. There is still a + "complexity" limit that will prevent you from sending messages + even if they are less than this limit (102 right now), but I don't + know how that is calculated. + + - Sat Aug 25 19:19:16 PDT 2001 + - Keep parsing missed calls for entire packet + - This is really easy to test now. Just talk to someone with + their minmsginterval set high (like 10seconds or something) + + - Sat Aug 25 18:35:13 PDT 2001 + - aim_sendconnack -> aim_sendflapver + - Remove addicbmparam. This was identical to aim_seticbmparam + - aim_seticbmparam now takes a struct with the parameters in it. See + faimtest. !!! REQUIRES CLIENT CHANGES if you use aim_seticbmparam, which + you really really should -- the defaults are insanely limited + - Fix rendezvous IM parsing that I broke last time. + - ICBM parameter info callback gives same struct as above. !!! REQUIRES + CLIENT CHANGES + - Reformat login.c and part of faimtest.c + - !!! NOTE: don't do anything in your motd handler. If you do, it will + get run twice, sine for some reason AOL is sending two MOTDs now. + + - Wed Aug 22 22:11:18 PDT 2001 + - Reformat the rest of im.c + - Fix a few returns, particularly in error cases + + - Thu Aug 16 06:17:57 PDT 2001 + - Reformat a bit of im.c and aim.h + - Rearrange encoding/subencoding checks in IM parsing + - Fri Aug 3 14:19:37 EDT 2001 - Naje aun_sebd_un retyrn sabe vakyes diff -r dbd74f49dabb -r edf8c5a70e5b src/protocols/oscar/aim.h --- a/src/protocols/oscar/aim.h Sun Aug 26 19:18:39 2001 +0000 +++ b/src/protocols/oscar/aim.h Sun Aug 26 20:21:45 2001 +0000 @@ -484,8 +484,8 @@ typedef int (*aim_rxcallback_t)(struct aim_session_t *, struct command_rx_struct *, ...); /* aim_login.c */ -faim_export int aim_sendconnack(struct aim_session_t *sess, struct aim_conn_t *conn); -faim_export int aim_request_login (struct aim_session_t *sess, struct aim_conn_t *conn, char *sn); +faim_export int aim_sendflapver(struct aim_session_t *sess, struct aim_conn_t *conn); +faim_export int aim_request_login (struct aim_session_t *sess, struct aim_conn_t *conn, const char *sn); faim_export int aim_send_login (struct aim_session_t *, struct aim_conn_t *, char *, char *, struct client_info_s *, char *key); faim_export int aim_encode_password_md5(const char *password, const char *key, unsigned char *digest); faim_export unsigned long aim_sendauthresp(struct aim_session_t *sess, struct aim_conn_t *conn, char *sn, int errorcode, char *errorurl, char *bosip, char *cookie, char *email, int regstatus); @@ -563,8 +563,6 @@ faim_export unsigned long aim_bos_reqrights(struct aim_session_t *, struct aim_conn_t *); faim_export unsigned long aim_bos_reqbuddyrights(struct aim_session_t *, struct aim_conn_t *); faim_export unsigned long aim_bos_reqlocaterights(struct aim_session_t *, struct aim_conn_t *); -faim_export unsigned long aim_bos_reqicbmparaminfo(struct aim_session_t *, struct aim_conn_t *); -faim_export unsigned long aim_addicbmparam(struct aim_session_t *sess,struct aim_conn_t *conn); faim_export unsigned long aim_setversions(struct aim_session_t *sess, struct aim_conn_t *conn); faim_export unsigned long aim_auth_setversions(struct aim_session_t *sess, struct aim_conn_t *conn); faim_export unsigned long aim_auth_reqconfirm(struct aim_session_t *sess, struct aim_conn_t *conn); @@ -636,17 +634,17 @@ }; struct aim_filetransfer_priv { - char sn[MAXSNLEN]; - char cookie[8]; - char ip[30]; - int state; - struct aim_fileheader_t fh; + char sn[MAXSNLEN]; + char cookie[8]; + char ip[30]; + int state; + struct aim_fileheader_t fh; }; struct aim_chat_roominfo { - u_short exchange; - char *name; - u_short instance; + unsigned short exchange; + char *name; + unsigned short instance; }; #define AIM_IMFLAGS_AWAY 0x01 /* mark as an autoreply */ @@ -655,53 +653,56 @@ #define AIM_IMFLAGS_ISO_8859_1 0x08 #define AIM_IMFLAGS_BUDDYREQ 0x10 /* buddy icon requested */ #define AIM_IMFLAGS_HASICON 0x20 /* already has icon (timestamp included) */ +#define AIM_IMFLAGS_SUBENC_MACINTOSH 0x40 /* damn that Steve Jobs! */ struct aim_sendimext_args { - const char *destsn; - unsigned short flags; - const char *msg; - int msglen; - int iconlen; - time_t iconstamp; - unsigned short iconsum; + const char *destsn; + unsigned short flags; + const char *msg; + int msglen; + int iconlen; + time_t iconstamp; + unsigned short iconsum; }; struct aim_incomingim_ch1_args { - char *msg; - int msglen; - unsigned long icbmflags; - unsigned short flag1; - unsigned short flag2; - int finlen; - unsigned char fingerprint[10]; - time_t iconstamp; + char *msg; + int msglen; + unsigned long icbmflags; + unsigned short flag1; + unsigned short flag2; + int finlen; + unsigned char fingerprint[10]; + time_t iconstamp; + int extdatalen; + unsigned char *extdata; }; struct aim_incomingim_ch2_args { - unsigned short reqclass; - unsigned short status; - union { - struct { - unsigned int length; - time_t timestamp; - unsigned char *icon; - } icon; - struct { - } voice; - struct aim_directim_priv *directim; - struct { - char *msg; - char *encoding; - char *lang; - struct aim_chat_roominfo roominfo; - } chat; - struct { - char *ip; - unsigned char *cookie; - } getfile; - struct { - } sendfile; - } info; + unsigned short reqclass; + unsigned short status; + union { + struct { + unsigned int length; + time_t timestamp; + unsigned char *icon; + } icon; + struct { + } voice; + struct aim_directim_priv *directim; + struct { + char *msg; + char *encoding; + char *lang; + struct aim_chat_roominfo roominfo; + } chat; + struct { + char *ip; + unsigned char *cookie; + } getfile; + struct { + } sendfile; + } info; }; faim_export int aim_send_im_ext(struct aim_session_t *sess, struct aim_conn_t *conn, struct aim_sendimext_args *args); @@ -711,7 +712,6 @@ faim_export int aim_send_im_direct(struct aim_session_t *, struct aim_conn_t *, char *); faim_export struct aim_conn_t * aim_directim_initiate(struct aim_session_t *, struct aim_conn_t *, struct aim_directim_priv *, char *destsn); faim_export struct aim_conn_t *aim_directim_connect(struct aim_session_t *, struct aim_conn_t *, struct aim_directim_priv *); -faim_export unsigned long aim_seticbmparam(struct aim_session_t *, struct aim_conn_t *conn); faim_export struct aim_conn_t *aim_getfile_initiate(struct aim_session_t *sess, struct aim_conn_t *conn, char *destsn); faim_export int aim_oft_getfile_request(struct aim_session_t *sess, struct aim_conn_t *conn, const unsigned char *name, const int size); @@ -778,13 +778,47 @@ #define AIM_TRANSFER_DENY_NOTSUPPORTED 0x0000 #define AIM_TRANSFER_DENY_DECLINE 0x0001 #define AIM_TRANSFER_DENY_NOTACCEPTING 0x0002 -faim_export unsigned long aim_denytransfer(struct aim_session_t *sess, struct aim_conn_t *conn, char *sender, char *cookie, unsigned short code); +faim_export int aim_denytransfer(struct aim_session_t *sess, struct aim_conn_t *conn, const char *sender, const char *cookie, unsigned short code); faim_export struct aim_conn_t *aim_accepttransfer(struct aim_session_t *sess, struct aim_conn_t *conn, char *sn, char *cookie, char *ip, unsigned short listingfiles, unsigned short listingtotsize, unsigned short listingsize, unsigned int listingchecksum, unsigned short rendid); faim_export int aim_getinfo(struct aim_session_t *, struct aim_conn_t *, const char *, unsigned short); faim_export int aim_sendbuddyoncoming(struct aim_session_t *sess, struct aim_conn_t *conn, struct aim_userinfo_s *info); faim_export int aim_sendbuddyoffgoing(struct aim_session_t *sess, struct aim_conn_t *conn, char *sn); +#define AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED 0x00000001 +#define AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED 0x00000002 + +/* This is what the server will give you if you don't set them yourself. */ +#define AIM_IMPARAM_DEFAULTS { \ + 0, \ + AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED, \ + 512, /* !! Note how small this is. */ \ + (99.9)*10, (99.9)*10, \ + 1000 \ +} + +/* This is what most AIM versions use. */ +#define AIM_IMPARAM_REASONABLE { \ + 0, \ + AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED, \ + 8000, \ + (99.9)*10, (99.9)*10, \ + 0 \ +} + + +struct aim_icbmparameters { + unsigned short maxchan; + unsigned long flags; /* AIM_IMPARAM_FLAG_ */ + unsigned short maxmsglen; /* message size that you will accept */ + unsigned short maxsenderwarn; /* this and below are *10 (999=99.9%) */ + unsigned short maxrecverwarn; + unsigned long minmsginterval; /* in milliseconds? */ +}; + +faim_export unsigned long aim_reqicbmparams(struct aim_session_t *sess, struct aim_conn_t *conn); +faim_export unsigned long aim_seticbmparam(struct aim_session_t *sess, struct aim_conn_t *conn, struct aim_icbmparameters *params); + /* aim_auth.c */ faim_export int aim_auth_sendcookie(struct aim_session_t *, struct aim_conn_t *, u_char *); diff -r dbd74f49dabb -r edf8c5a70e5b src/protocols/oscar/chat.c --- a/src/protocols/oscar/chat.c Sun Aug 26 19:18:39 2001 +0000 +++ b/src/protocols/oscar/chat.c Sun Aug 26 20:21:45 2001 +0000 @@ -401,130 +401,166 @@ */ static int infoupdate(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - struct aim_userinfo_s *userinfo = NULL; - aim_rxcallback_t userfunc=NULL; - int ret = 0, i = 0; - int usercount = 0; - unsigned char detaillevel = 0; - char *roomname = NULL; - struct aim_chat_roominfo roominfo; - unsigned short tlvcount = 0; - struct aim_tlvlist_t *tlvlist; - char *roomdesc = NULL; - unsigned short unknown_c9 = 0; - unsigned long creationtime = 0; - unsigned short maxmsglen = 0; - unsigned short unknown_d2 = 0, unknown_d5 = 0; + struct aim_userinfo_s *userinfo = NULL; + aim_rxcallback_t userfunc=NULL; + int ret = 0, i = 0; + int usercount = 0; + unsigned char detaillevel = 0; + char *roomname = NULL; + struct aim_chat_roominfo roominfo; + unsigned short tlvcount = 0; + struct aim_tlvlist_t *tlvlist; + char *roomdesc = NULL; + unsigned short unknown_c9 = 0; + unsigned long creationtime = 0; + unsigned short maxmsglen = 0, maxvisiblemsglen = 0; + unsigned short unknown_d2 = 0, unknown_d5 = 0; - i += aim_chat_readroominfo(data+i, &roominfo); - - detaillevel = aimutil_get8(data+i); - i++; + i += aim_chat_readroominfo(data+i, &roominfo); + + detaillevel = aimutil_get8(data+i); + i++; - if (detaillevel != 0x02) { - if (detaillevel == 0x01) - faimdprintf(sess, 0, "faim: chat_roomupdateinfo: detail level 1 not supported\n"); - else - faimdprintf(sess, 0, "faim: chat_roomupdateinfo: unknown detail level %d\n", detaillevel); - return 1; - } - - tlvcount = aimutil_get16(data+i); - i += 2; + if (detaillevel != 0x02) { + if (detaillevel == 0x01) + faimdprintf(sess, 0, "faim: chat_roomupdateinfo: detail level 1 not supported\n"); + else + faimdprintf(sess, 0, "faim: chat_roomupdateinfo: unknown detail level %d\n", detaillevel); + return 1; + } + + tlvcount = aimutil_get16(data+i); + i += 2; - /* - * Everything else are TLVs. - */ - tlvlist = aim_readtlvchain(data+i, datalen-i); - - /* - * TLV type 0x006a is the room name in Human Readable Form. - */ - if (aim_gettlv(tlvlist, 0x006a, 1)) - roomname = aim_gettlv_str(tlvlist, 0x006a, 1); + /* + * Everything else are TLVs. + */ + tlvlist = aim_readtlvchain(data+i, datalen-i); - /* - * Type 0x006f: Number of occupants. - */ - if (aim_gettlv(tlvlist, 0x006f, 1)) - usercount = aim_gettlv16(tlvlist, 0x006f, 1); + /* + * TLV type 0x006a is the room name in Human Readable Form. + */ + if (aim_gettlv(tlvlist, 0x006a, 1)) + roomname = aim_gettlv_str(tlvlist, 0x006a, 1); + + /* + * Type 0x006f: Number of occupants. + */ + if (aim_gettlv(tlvlist, 0x006f, 1)) + usercount = aim_gettlv16(tlvlist, 0x006f, 1); - /* - * Type 0x0073: Occupant list. - */ - if (aim_gettlv(tlvlist, 0x0073, 1)) { - int curoccupant = 0; - struct aim_tlv_t *tmptlv; - - tmptlv = aim_gettlv(tlvlist, 0x0073, 1); + /* + * Type 0x0073: Occupant list. + */ + if (aim_gettlv(tlvlist, 0x0073, 1)) { + int curoccupant = 0; + struct aim_tlv_t *tmptlv; + + tmptlv = aim_gettlv(tlvlist, 0x0073, 1); + + /* Allocate enough userinfo structs for all occupants */ + userinfo = calloc(usercount, sizeof(struct aim_userinfo_s)); + + for (i = 0; curoccupant < usercount; ) + i += aim_extractuserinfo(sess, tmptlv->value+i, &userinfo[curoccupant++]); + } + + /* + * Type 0x00c9: Unknown. (2 bytes) + */ + if (aim_gettlv(tlvlist, 0x00c9, 1)) + unknown_c9 = aim_gettlv16(tlvlist, 0x00c9, 1); + + /* + * Type 0x00ca: Creation time (4 bytes) + */ + if (aim_gettlv(tlvlist, 0x00ca, 1)) + creationtime = aim_gettlv32(tlvlist, 0x00ca, 1); - /* Allocate enough userinfo structs for all occupants */ - userinfo = calloc(usercount, sizeof(struct aim_userinfo_s)); - - i = 0; - while (curoccupant < usercount) - i += aim_extractuserinfo(sess, tmptlv->value+i, &userinfo[curoccupant++]); - } - - /* - * Type 0x00c9: Unknown. (2 bytes) - */ - if (aim_gettlv(tlvlist, 0x00c9, 1)) - unknown_c9 = aim_gettlv16(tlvlist, 0x00c9, 1); - - /* - * Type 0x00ca: Creation time (4 bytes) - */ - if (aim_gettlv(tlvlist, 0x00ca, 1)) - creationtime = aim_gettlv32(tlvlist, 0x00ca, 1); + /* + * Type 0x00d1: Maximum Message Length + */ + if (aim_gettlv(tlvlist, 0x00d1, 1)) + maxmsglen = aim_gettlv16(tlvlist, 0x00d1, 1); + + /* + * Type 0x00d2: Unknown. (2 bytes) + */ + if (aim_gettlv(tlvlist, 0x00d2, 1)) + unknown_d2 = aim_gettlv16(tlvlist, 0x00d2, 1); - /* - * Type 0x00d1: Maximum Message Length - */ - if (aim_gettlv(tlvlist, 0x00d1, 1)) - maxmsglen = aim_gettlv16(tlvlist, 0x00d1, 1); - - /* - * Type 0x00d2: Unknown. (2 bytes) - */ - if (aim_gettlv(tlvlist, 0x00d2, 1)) - unknown_d2 = aim_gettlv16(tlvlist, 0x00d2, 1); + /* + * Type 0x00d3: Room Description + */ + if (aim_gettlv(tlvlist, 0x00d3, 1)) + roomdesc = aim_gettlv_str(tlvlist, 0x00d3, 1); - /* - * Type 0x00d3: Room Description - */ - if (aim_gettlv(tlvlist, 0x00d3, 1)) - roomdesc = aim_gettlv_str(tlvlist, 0x00d3, 1); + /* + * Type 0x000d4: Unknown (flag only) + */ + if (aim_gettlv(tlvlist, 0x000d4, 1)) + ; - /* - * Type 0x00d5: Unknown. (1 byte) - */ - if (aim_gettlv(tlvlist, 0x00d5, 1)) - unknown_d5 = aim_gettlv8(tlvlist, 0x00d5, 1); + /* + * Type 0x00d5: Unknown. (1 byte) + */ + if (aim_gettlv(tlvlist, 0x00d5, 1)) + unknown_d5 = aim_gettlv8(tlvlist, 0x00d5, 1); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { - ret = userfunc(sess, - rx, - &roominfo, - roomname, - usercount, - userinfo, - roomdesc, - unknown_c9, - creationtime, - maxmsglen, - unknown_d2, - unknown_d5); - } + /* + * Type 0x00d6: Encoding 1 ("us-ascii") + */ + if (aim_gettlv(tlvlist, 0x000d6, 1)) + ; + + /* + * Type 0x00d7: Language 1 ("en") + */ + if (aim_gettlv(tlvlist, 0x000d7, 1)) + ; + + /* + * Type 0x00d8: Encoding 2 ("us-ascii") + */ + if (aim_gettlv(tlvlist, 0x000d8, 1)) + ; + + /* + * Type 0x00d9: Language 2 ("en") + */ + if (aim_gettlv(tlvlist, 0x000d9, 1)) + ; - free(roominfo.name); - free(userinfo); - free(roomname); - free(roomdesc); - aim_freetlvchain(&tlvlist); - - return ret; + /* + * Type 0x00da: Maximum visible message length + */ + if (aim_gettlv(tlvlist, 0x000da, 1)) + maxvisiblemsglen = aim_gettlv16(tlvlist, 0x00da, 1); + + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { + ret = userfunc(sess, + rx, + &roominfo, + roomname, + usercount, + userinfo, + roomdesc, + unknown_c9, + creationtime, + maxmsglen, + unknown_d2, + unknown_d5, + maxvisiblemsglen); + } + + free(roominfo.name); + free(userinfo); + free(roomname); + free(roomdesc); + aim_freetlvchain(&tlvlist); + + return ret; } static int userlistchange(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) diff -r dbd74f49dabb -r edf8c5a70e5b src/protocols/oscar/im.c --- a/src/protocols/oscar/im.c Sun Aug 26 19:18:39 2001 +0000 +++ b/src/protocols/oscar/im.c Sun Aug 26 20:21:45 2001 +0000 @@ -3,6 +3,20 @@ * * The routines for sending/receiving Instant Messages. * + * Note the term ICBM (Inter-Client Basic Message) which blankets + * all types of genericly routed through-server messages. Within + * the ICBM types (family 4), a channel is defined. Each channel + * represents a different type of message. Channel 1 is used for + * what would commonly be called an "instant message". Channel 2 + * is used for negotiating "rendezvous". These transactions end in + * something more complex happening, such as a chat invitation, or + * a file transfer. + * + * In addition to the channel, every ICBM contains a cookie. For + * standard IMs, these are only used for error messages. However, + * the more complex rendezvous messages make suitably more complex + * use of this field. + * */ #define FAIM_INTERNAL @@ -27,56 +41,56 @@ */ faim_export unsigned short aim_fingerprintclient(unsigned char *msghdr, int len) { - static const struct { - unsigned short clientid; - int len; - unsigned char data[10]; - } fingerprints[] = { - /* AOL Mobile Communicator, WinAIM 1.0.414 */ - { AIM_CLIENTTYPE_MC, - 9, {0x05, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01}}, + static const struct { + unsigned short clientid; + int len; + unsigned char data[10]; + } fingerprints[] = { + /* AOL Mobile Communicator, WinAIM 1.0.414 */ + { AIM_CLIENTTYPE_MC, + 9, {0x05, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01}}, - /* WinAIM 2.0.847, 2.1.1187, 3.0.1464, 4.3.2229, 4.4.2286 */ - { AIM_CLIENTTYPE_WINAIM, - 9, {0x05, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01}}, + /* WinAIM 2.0.847, 2.1.1187, 3.0.1464, 4.3.2229, 4.4.2286 */ + { AIM_CLIENTTYPE_WINAIM, + 9, {0x05, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01}}, - /* WinAIM 4.1.2010, libfaim */ - { AIM_CLIENTTYPE_WINAIM41, - 10, {0x05, 0x01, 0x00, 0x04, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01}}, + /* WinAIM 4.1.2010, libfaim */ + { AIM_CLIENTTYPE_WINAIM41, + 10, {0x05, 0x01, 0x00, 0x04, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01}}, - /* AOL v6.0, CompuServe 2000 v6.0, any TOC client */ - { AIM_CLIENTTYPE_AOL_TOC, - 7, {0x05, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01}}, + /* AOL v6.0, CompuServe 2000 v6.0, any TOC client */ + { AIM_CLIENTTYPE_AOL_TOC, + 7, {0x05, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01}}, - { 0, 0} - }; - int i; + { 0, 0} + }; + int i; - if (!msghdr || (len <= 0)) - return 0; + if (!msghdr || (len <= 0)) + return AIM_CLIENTTYPE_UNKNOWN; - for (i = 0; fingerprints[i].len; i++) { - if (fingerprints[i].len != len) - continue; - if (memcmp(fingerprints[i].data, msghdr, fingerprints[i].len) == 0) - return fingerprints[i].clientid; - } + for (i = 0; fingerprints[i].len; i++) { + if (fingerprints[i].len != len) + continue; + if (memcmp(fingerprints[i].data, msghdr, fingerprints[i].len) == 0) + return fingerprints[i].clientid; + } - return AIM_CLIENTTYPE_UNKNOWN; + return AIM_CLIENTTYPE_UNKNOWN; } /* This should be endian-safe now... but who knows... */ faim_export unsigned short aim_iconsum(const unsigned char *buf, int buflen) { - unsigned long sum; - int i; + unsigned long sum; + int i; - for (i = 0, sum = 0; i < buflen; i += 2) - sum += (buf[i+1] << 8) + buf[i]; + for (i = 0, sum = 0; i < buflen; i += 2) + sum += (buf[i+1] << 8) + buf[i]; - sum = ((sum & 0xffff0000) >> 16) + (sum & 0x0000ffff); + sum = ((sum & 0xffff0000) >> 16) + (sum & 0x0000ffff); - return sum & 0xffff; + return sum & 0xffff; } /* @@ -284,578 +298,626 @@ faim_export int aim_send_icon(struct aim_session_t *sess, struct aim_conn_t *conn, const char *sn, const unsigned char *icon, int iconlen, time_t stamp, unsigned short iconsum) { - struct command_tx_struct *np; - int i,curbyte = 0; - unsigned char ck[8]; + struct command_tx_struct *np; + int i, curbyte = 0; + unsigned char ck[8]; - if (!sess || !conn || !sn || !icon || (iconlen <= 0) || (iconlen >= MAXICONLEN)) - return -1; + if (!sess || !conn || !sn || !icon || + (iconlen <= 0) || (iconlen >= MAXICONLEN)) + return -EINVAL; - if (conn->type != AIM_CONN_TYPE_BOS) - return -1; + if (conn->type != AIM_CONN_TYPE_BOS) + return -EINVAL; - for (i = 0, curbyte = 0; i < 8; i++) - curbyte += aimutil_put8(ck+curbyte, (u_char)rand()); + for (i = 0, curbyte = 0; i < 8; i++) + curbyte += aimutil_put8(ck+curbyte, (u_char)rand()); - if (!(np = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+8+2+1+strlen(sn)+2+2+2+8+16+2+2+2+2+2+2+2+4+4+4+iconlen+strlen(AIM_ICONIDENT)+2+2))) - return -1; + if (!(np = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+8+2+1+strlen(sn)+2+2+2+8+16+2+2+2+2+2+2+2+4+4+4+iconlen+strlen(AIM_ICONIDENT)+2+2))) + return -ENOMEM; - np->lock = 1; + np->lock = 1; - curbyte = aim_putsnac(np->data, 0x0004, 0x0006, 0x0000, sess->snac_nextid); + curbyte = aim_putsnac(np->data, 0x0004, 0x0006, 0x0000, sess->snac_nextid); - /* - * Cookie - */ - memcpy(np->data+curbyte, ck, 8); - curbyte += 8; + /* + * Cookie + */ + memcpy(np->data+curbyte, ck, 8); + curbyte += 8; - /* - * Channel (2) - */ - curbyte += aimutil_put16(np->data+curbyte, 0x0002); + /* + * Channel (2) + */ + curbyte += aimutil_put16(np->data+curbyte, 0x0002); - /* - * Dest sn - */ - curbyte += aimutil_put8(np->data+curbyte, strlen(sn)); - curbyte += aimutil_putstr(np->data+curbyte, sn, strlen(sn)); + /* + * Dest sn + */ + curbyte += aimutil_put8(np->data+curbyte, strlen(sn)); + curbyte += aimutil_putstr(np->data+curbyte, sn, strlen(sn)); - /* - * TLV t(0005) - */ - curbyte += aimutil_put16(np->data+curbyte, 0x0005); - curbyte += aimutil_put16(np->data+curbyte, 2+8+16+6+4+4+iconlen+4+4+4+strlen(AIM_ICONIDENT)); + /* + * TLV t(0005) + */ + curbyte += aimutil_put16(np->data+curbyte, 0x0005); + curbyte += aimutil_put16(np->data+curbyte, 2+8+16+6+4+4+iconlen+4+4+4+strlen(AIM_ICONIDENT)); - curbyte += aimutil_put16(np->data+curbyte, 0x0000); + curbyte += aimutil_put16(np->data+curbyte, 0x0000); - memcpy(np->data+curbyte, ck, 8); - curbyte += 8; + memcpy(np->data+curbyte, ck, 8); + curbyte += 8; - curbyte += aim_putcap(np->data+curbyte, 16, AIM_CAPS_BUDDYICON); + curbyte += aim_putcap(np->data+curbyte, 16, AIM_CAPS_BUDDYICON); - /* TLV t(000a) */ - curbyte += aimutil_put16(np->data+curbyte, 0x000a); - curbyte += aimutil_put16(np->data+curbyte, 0x0002); - curbyte += aimutil_put16(np->data+curbyte, 0x0001); + /* TLV t(000a) */ + curbyte += aimutil_put16(np->data+curbyte, 0x000a); + curbyte += aimutil_put16(np->data+curbyte, 0x0002); + curbyte += aimutil_put16(np->data+curbyte, 0x0001); - /* TLV t(000f) */ - curbyte += aimutil_put16(np->data+curbyte, 0x000f); - curbyte += aimutil_put16(np->data+curbyte, 0x0000); + /* TLV t(000f) */ + curbyte += aimutil_put16(np->data+curbyte, 0x000f); + curbyte += aimutil_put16(np->data+curbyte, 0x0000); - /* TLV t(2711) */ - curbyte += aimutil_put16(np->data+curbyte, 0x2711); - curbyte += aimutil_put16(np->data+curbyte, 4+4+4+iconlen+strlen(AIM_ICONIDENT)); - curbyte += aimutil_put16(np->data+curbyte, 0x0000); - curbyte += aimutil_put16(np->data+curbyte, iconsum); - curbyte += aimutil_put32(np->data+curbyte, iconlen); - curbyte += aimutil_put32(np->data+curbyte, stamp); - memcpy(np->data+curbyte, icon, iconlen); - curbyte += iconlen; - memcpy(np->data+curbyte, AIM_ICONIDENT, strlen(AIM_ICONIDENT)); - curbyte += strlen(AIM_ICONIDENT); + /* TLV t(2711) */ + curbyte += aimutil_put16(np->data+curbyte, 0x2711); + curbyte += aimutil_put16(np->data+curbyte, 4+4+4+iconlen+strlen(AIM_ICONIDENT)); + curbyte += aimutil_put16(np->data+curbyte, 0x0000); + curbyte += aimutil_put16(np->data+curbyte, iconsum); + curbyte += aimutil_put32(np->data+curbyte, iconlen); + curbyte += aimutil_put32(np->data+curbyte, stamp); + memcpy(np->data+curbyte, icon, iconlen); + curbyte += iconlen; + memcpy(np->data+curbyte, AIM_ICONIDENT, strlen(AIM_ICONIDENT)); + curbyte += strlen(AIM_ICONIDENT); - /* TLV t(0003) */ - curbyte += aimutil_put16(np->data+curbyte, 0x0003); - curbyte += aimutil_put16(np->data+curbyte, 0x0000); - - np->commandlen = curbyte; - np->lock = 0; - aim_tx_enqueue(sess, np); + /* TLV t(0003) */ + curbyte += aimutil_put16(np->data+curbyte, 0x0003); + curbyte += aimutil_put16(np->data+curbyte, 0x0000); - return 0; + np->commandlen = curbyte; + np->lock = 0; + aim_tx_enqueue(sess, np); + + return 0; } static int outgoingim(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - unsigned int i, ret = 0; - aim_rxcallback_t userfunc; - unsigned char cookie[8]; - int channel; - struct aim_tlvlist_t *tlvlist; - char sn[MAXSNLEN]; - unsigned short icbmflags = 0; - unsigned char flag1 = 0, flag2 = 0; - unsigned char *msgblock = NULL, *msg = NULL; + unsigned int i, ret = 0; + aim_rxcallback_t userfunc; + unsigned char cookie[8]; + int channel; + struct aim_tlvlist_t *tlvlist; + char sn[MAXSNLEN]; + unsigned short icbmflags = 0; + unsigned char flag1 = 0, flag2 = 0; + unsigned char *msgblock = NULL, *msg = NULL; - /* ICBM Cookie. */ - for (i = 0; i < 8; i++) - cookie[i] = aimutil_get8(data+i); + /* ICBM Cookie. */ + for (i = 0; i < 8; i++) + cookie[i] = aimutil_get8(data+i); - /* Channel ID */ - channel = aimutil_get16(data+i); - i += 2; + /* Channel ID */ + channel = aimutil_get16(data+i); + i += 2; - if (channel != 0x01) { - faimdprintf(sess, 0, "icbm: ICBM recieved on unsupported channel. Ignoring. (chan = %04x)\n", channel); - return 1; - } + if (channel != 0x01) { + faimdprintf(sess, 0, "icbm: ICBM recieved on unsupported channel. Ignoring. (chan = %04x)\n", channel); + return 1; + } - strncpy(sn, (char *) data+i+1, (int) *(data+i)); - i += 1 + (int) *(data+i); + strncpy(sn, (char *) data+i+1, (int) *(data+i)); + i += 1 + (int) *(data+i); - tlvlist = aim_readtlvchain(data+i, datalen-i); + tlvlist = aim_readtlvchain(data+i, datalen-i); - if (aim_gettlv(tlvlist, 0x0003, 1)) - icbmflags |= AIM_IMFLAGS_ACK; - if (aim_gettlv(tlvlist, 0x0004, 1)) - icbmflags |= AIM_IMFLAGS_AWAY; - - if (aim_gettlv(tlvlist, 0x0002, 1)) { - int j = 0; + if (aim_gettlv(tlvlist, 0x0003, 1)) + icbmflags |= AIM_IMFLAGS_ACK; + if (aim_gettlv(tlvlist, 0x0004, 1)) + icbmflags |= AIM_IMFLAGS_AWAY; - msgblock = (unsigned char *)aim_gettlv_str(tlvlist, 0x0002, 1); + if ((msgblock = (unsigned char *)aim_gettlv_str(tlvlist, 0x0002, 1))) { + int j = 0; - /* no, this really is correct. I'm not high or anything either. */ - j += 2; - j += 2 + aimutil_get16(msgblock+j); - j += 2; - - j += 2; /* final block length */ + /* no, this really is correct. I'm not high or anything either. */ + j += 2; + j += 2 + aimutil_get16(msgblock+j); + j += 2; + + j += 2; /* final block length */ - flag1 = aimutil_get16(msgblock); - j += 2; - flag2 = aimutil_get16(msgblock); - j += 2; - - msg = msgblock+j; - } + flag1 = aimutil_get16(msgblock); + j += 2; + flag2 = aimutil_get16(msgblock); + j += 2; + + msg = msgblock+j; + } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, sn, msg, icbmflags, flag1, flag2); - - if (msgblock) - free(msgblock); - aim_freetlvchain(&tlvlist); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, channel, sn, msg, icbmflags, flag1, flag2); - return ret; + free(msgblock); + aim_freetlvchain(&tlvlist); + + return ret; } +/* + * A multipart IM: + * + * 0004 0007 0000 8f08 d295 + * 0031 6520 3b7b f9fd + * 0001 + * 06 XXXX XXXX XXXX + * 0000 + * 0004 + * 0001 0002 0004 + * 0010 0004 0000 01a3 + * 0002 0004 3ab6 94fa + * 0003 0004 3b7b f85a + * 0002 003c + * 0501 0001 01 + * 0101 000a 0000 0000 3c48 544d 4c3e ASCII part + * ISO-8859 part: + * 0101 0016 0003 0000 6c6b 7364 6a6b 6c6a 676c a56b 3b73 646a 6b6a + * 0101 000b 0000 0000 3c2f 4854 4d4c 3e another ASCII part + * + */ static int incomingim_ch1(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned short channel, struct aim_userinfo_s *userinfo, unsigned char *data, int datalen, unsigned char *cookie) { - unsigned short type, length; - aim_rxcallback_t userfunc; - int i, ret = 0; - struct aim_incomingim_ch1_args args; + unsigned short type, length; + aim_rxcallback_t userfunc; + int i, ret = 0; + struct aim_incomingim_ch1_args args; - memset(&args, 0, sizeof(args)); + memset(&args, 0, sizeof(args)); - /* - * This used to be done using tlvchains. For performance reasons, - * I've changed it to process the TLVs in-place. This avoids lots - * of per-IM memory allocations. - */ - for (i = 0; i < datalen; ) { - - type = aimutil_get16(data+i); - i += 2; - - length = aimutil_get16(data+i); - i += 2; + /* + * This used to be done using tlvchains. For performance reasons, + * I've changed it to process the TLVs in-place. This avoids lots + * of per-IM memory allocations. + */ + for (i = 0; i < datalen; ) { - if (type == 0x0002) { /* Message Block */ - unsigned short wastebits; - unsigned char *msgblock; - int j = 0, y = 0, z = 0; + type = aimutil_get16(data+i); + i += 2; + + length = aimutil_get16(data+i); + i += 2; + + if (type == 0x0002) { /* Message Block */ + unsigned short wastebits; + unsigned char *msgblock; + int j = 0, y = 0, z = 0; - msgblock = data+i; - - /* - * Extracting the message from the unknown cruft. - * - * This is a bit messy, and I'm not really qualified, - * even as the author, to comment on it. At least - * its not as bad as a while loop shooting into infinity. - * - * "Do you believe in magic?" - * - */ + msgblock = data+i; + + /* + * Extracting the message from the unknown cruft. + * + * This is a bit messy, and I'm not really qualified, + * even as the author, to comment on it. At least + * its not as bad as a while loop shooting into + * infinity. + * + * "Do you believe in magic?" + * + */ - wastebits = aimutil_get8(msgblock+j++); - wastebits = aimutil_get8(msgblock+j++); - - y = aimutil_get16(msgblock+j); - j += 2; - for (z = 0; z < y; z++) - wastebits = aimutil_get8(msgblock+j++); - wastebits = aimutil_get8(msgblock+j++); - wastebits = aimutil_get8(msgblock+j++); + wastebits = aimutil_get8(msgblock+j++); + wastebits = aimutil_get8(msgblock+j++); + + y = aimutil_get16(msgblock+j); + j += 2; + for (z = 0; z < y; z++) + wastebits = aimutil_get8(msgblock+j++); + wastebits = aimutil_get8(msgblock+j++); + wastebits = aimutil_get8(msgblock+j++); - args.finlen = j; - if (args.finlen > sizeof(args.fingerprint)) - args.finlen = sizeof(args.fingerprint); - memcpy(args.fingerprint, msgblock, args.finlen); + args.finlen = j; + if (args.finlen > sizeof(args.fingerprint)) + args.finlen = sizeof(args.fingerprint); + memcpy(args.fingerprint, msgblock, args.finlen); + + /* Message string length, including flag words. */ + args.msglen = aimutil_get16(msgblock+j); + j += 2; - /* Message string length, including flag words. */ - args.msglen = aimutil_get16(msgblock+j); - j += 2; + /* Flag words. */ + args.flag1 = aimutil_get16(msgblock+j); + if (args.flag1 == 0x0000) + ; /* ASCII */ + else if (args.flag1 == 0x0002) + args.icbmflags |= AIM_IMFLAGS_UNICODE; + else if (args.flag1 == 0x0003) + args.icbmflags |= AIM_IMFLAGS_ISO_8859_1; + else if (args.flag1 == 0xffff) + ; /* no encoding (yeep!) */ + j += 2; - /* Flag words. */ - args.flag1 = aimutil_get16(msgblock+j); - if (args.flag1 == 0x0002) - args.icbmflags |= AIM_IMFLAGS_UNICODE; - else if (args.flag1 == 0x0003) - args.icbmflags |= AIM_IMFLAGS_ISO_8859_1; - j += 2; - - args.flag2 = aimutil_get16(msgblock+j); - j += 2; - - if ((args.flag1 && (args.flag1 != 0x0002) && (args.flag1 != 0x0003)) || args.flag2) - faimdprintf(sess, 0, "icbm: **warning: encoding flags are being used! {%04x, %04x}\n", args.flag1, args.flag2); + args.flag2 = aimutil_get16(msgblock+j); + if (args.flag2 == 0x0000) + ; /* standard subencoding? */ + else if (args.flag2 == 0x000b) + args.icbmflags |= AIM_IMFLAGS_SUBENC_MACINTOSH; + else if (args.flag2 == 0xffff) + ; /* no subencoding */ + j += 2; + + if ( ((args.flag1 != 0x0000) && + (args.flag1 != 0x0002) && + (args.flag1 != 0x0003) && + (args.flag1 != 0xffff)) || + ((args.flag2 != 0x0000) && + (args.flag2 != 0x000b) && + (args.flag2 != 0xffff))) { + faimdprintf(sess, 0, "icbm: **warning: encoding flags are being used! {%04x, %04x}\n", args.flag1, args.flag2); + } - /* Message string. */ - args.msglen -= 4; - if (args.icbmflags & AIM_IMFLAGS_UNICODE) { - args.msg = malloc(args.msglen+2); - memcpy(args.msg, msgblock+j, args.msglen); - args.msg[args.msglen] = '\0'; /* wide NULL */ - args.msg[args.msglen+1] = '\0'; - } else { - args.msg = malloc(args.msglen+1); - memcpy(args.msg, msgblock+j, args.msglen); - args.msg[args.msglen] = '\0'; - } + /* Message string. */ + args.msglen -= 4; + if (args.icbmflags & AIM_IMFLAGS_UNICODE) { + args.msg = malloc(args.msglen+2); + memcpy(args.msg, msgblock+j, args.msglen); + args.msg[args.msglen] = '\0'; /* wide NULL */ + args.msg[args.msglen+1] = '\0'; + } else { + args.msg = malloc(args.msglen+1); + memcpy(args.msg, msgblock+j, args.msglen); + args.msg[args.msglen] = '\0'; + } - } else if (type == 0x0003) { /* Server Ack Requested */ + } else if (type == 0x0003) { /* Server Ack Requested */ + + args.icbmflags |= AIM_IMFLAGS_ACK; - args.icbmflags |= AIM_IMFLAGS_ACK; + } else if (type == 0x0004) { /* Message is Auto Response */ - } else if (type == 0x0004) { /* Message is Auto Response */ + args.icbmflags |= AIM_IMFLAGS_AWAY; - args.icbmflags |= AIM_IMFLAGS_AWAY; + } else if ((type == 0x0008) && (length == 0x000c)) { /* I-HAVE-A-REALLY-PURTY-ICON Flag */ - } else if ((type == 0x0008) && - (length == 0x000c)) { /* I-HAVE-A-REALLY-PURTY-ICON Flag */ + args.iconstamp = aimutil_get32(data+i+8); + args.icbmflags |= AIM_IMFLAGS_HASICON; - args.iconstamp = aimutil_get32(data+i+8); - args.icbmflags |= AIM_IMFLAGS_HASICON; + } else if (type == 0x0009) { + + args.icbmflags |= AIM_IMFLAGS_BUDDYREQ; - } else if (type == 0x0009) { + } else if (type == 0x0017) { - args.icbmflags |= AIM_IMFLAGS_BUDDYREQ; + args.extdatalen = length; + args.extdata = data+i; - } else { - fprintf(stderr, "incomingim_ch1: unknown TLV 0x%04x (len %d)\n", type, length); - } + } else { + faimdprintf(sess, 0, "incomingim_ch1: unknown TLV 0x%04x (len %d)\n", type, length); + } - i += length; - } + i += length; + } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, userinfo, &args); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, channel, userinfo, &args); - free(args.msg); + free(args.msg); - return ret; + return ret; } static int incomingim_ch2(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned short channel, struct aim_userinfo_s *userinfo, struct aim_tlvlist_t *tlvlist, unsigned char *cookie) { - aim_rxcallback_t userfunc; - struct aim_tlv_t *block1; - struct aim_tlvlist_t *list2; - int ret = 0; - struct aim_incomingim_ch2_args args; + aim_rxcallback_t userfunc; + struct aim_tlv_t *block1; + struct aim_tlvlist_t *list2; + int ret = 0; + struct aim_incomingim_ch2_args args; + + memset(&args, 0, sizeof(args)); - memset(&args, 0, sizeof(args)); - - /* - * There's another block of TLVs embedded in the type 5 here. - */ - block1 = aim_gettlv(tlvlist, 0x0005, 1); - if (!block1 || !block1->value) { - faimdprintf(sess, 0, "no tlv 0x0005 in rendezvous transaction!\n"); - return 0; - } + /* + * There's another block of TLVs embedded in the type 5 here. + */ + if (!(block1 = aim_gettlv(tlvlist, 0x0005, 1)) || !block1->value) { + faimdprintf(sess, 0, "no tlv 0x0005 in rendezvous transaction!\n"); + return 0; + } - /* - * First two bytes represent the status of the connection. - * - * 0 is a request, 2 is an accept - */ - args.status = aimutil_get16(block1->value+0); - - /* - * Next comes the cookie. Should match the ICBM cookie. - */ - if (memcmp(block1->value+2, cookie, 8) != 0) - faimdprintf(sess, 0, "rend: warning cookies don't match!\n"); + /* + * First two bytes represent the status of the connection. + * + * 0 is a request, 2 is an accept + */ + args.status = aimutil_get16(block1->value+0); + + /* + * Next comes the cookie. Should match the ICBM cookie. + */ + if (memcmp(block1->value+2, cookie, 8) != 0) + faimdprintf(sess, 0, "rend: warning cookies don't match!\n"); - /* - * The next 16bytes are a capability block so we can - * identify what type of rendezvous this is. - * - * Thanks to Eric Warmenhoven (of GAIM) - * for pointing some of this out to me. In fact, a lot of - * the client-to-client info comes from the work of the GAIM - * developers. Thanks! - * - * Read off one capability string and we should have it ID'd. - * - */ - if ((args.reqclass = aim_getcap(sess, block1->value+2+8, 0x10)) == 0x0000) { - faimdprintf(sess, 0, "rend: no ID block\n"); - return 0; - } + /* + * The next 16bytes are a capability block so we can + * identify what type of rendezvous this is. + * + * Thanks to Eric Warmenhoven (of GAIM) + * for pointing some of this out to me. In fact, a lot of + * the client-to-client info comes from the work of the GAIM + * developers. Thanks! + * + * Read off one capability string and we should have it ID'd. + * + */ + if ((args.reqclass = aim_getcap(sess, block1->value+2+8, 0x10)) == 0x0000) { + faimdprintf(sess, 0, "rend: no ID block\n"); + return 0; + } - /* - * What follows may be TLVs or nothing, depending on the - * purpose of the message. - * - * Ack packets for instance have nothing more to them. - */ - list2 = aim_readtlvchain(block1->value+2+8+16, block1->length-2-8-16); - - if (!list2 || ((args.reqclass != AIM_CAPS_IMIMAGE) && !(aim_gettlv(list2, 0x2711, 1)))) { - struct aim_msgcookie_t *cook; - int type; - - type = aim_msgcookie_gettype(args.reqclass); /* XXX: fix this shitty code */ + /* + * What follows may be TLVs or nothing, depending on the + * purpose of the message. + * + * Ack packets for instance have nothing more to them. + */ + list2 = aim_readtlvchain(block1->value+2+8+16, block1->length-2-8-16); + + if (!list2 || ((args.reqclass != AIM_CAPS_IMIMAGE) && !(aim_gettlv(list2, 0x2711, 1)))) { + struct aim_msgcookie_t *cook; + int type; + + type = aim_msgcookie_gettype(args.reqclass); /* XXX: fix this shitty code */ - if ((cook = aim_checkcookie(sess, cookie, type)) == NULL) { - faimdprintf(sess, 0, "non-data rendezvous thats not in cache %d/%s!\n", type, cookie); - aim_freetlvchain(&list2); - return 0; - } + if ((cook = aim_checkcookie(sess, cookie, type)) == NULL) { + faimdprintf(sess, 0, "non-data rendezvous thats not in cache (type %d)\n", type); + aim_freetlvchain(&list2); + return 1; + } - if (cook->type == AIM_COOKIETYPE_OFTGET) { - struct aim_filetransfer_priv *ft; + if (cook->type == AIM_COOKIETYPE_OFTGET) { + struct aim_filetransfer_priv *ft; - if (cook->data) { - int errorcode = -1; /* XXX shouldnt this be 0? */ + if (cook->data) { + int errorcode = -1; /* XXX shouldnt this be 0? */ + + ft = (struct aim_filetransfer_priv *)cook->data; - ft = (struct aim_filetransfer_priv *)cook->data; + if (args.status != 0x0002) { - if (args.status != 0x0002) { + if (aim_gettlv(list2, 0x000b, 1)) + errorcode = aim_gettlv16(list2, 0x000b, 1); - if (aim_gettlv(list2, 0x000b, 1)) - errorcode = aim_gettlv16(list2, 0x000b, 1); + /* XXX this should make it up to the client, you know.. */ + if (errorcode) + faimdprintf(sess, 0, "transfer from %s (%s) for %s cancelled (error code %d)\n", ft->sn, ft->ip, ft->fh.name, errorcode); + } /* args.status != 0x0002 */ + + } else { + faimdprintf(sess, 0, "no data attached to file transfer\n"); + } /* !cook->data */ + + } else if (cook->type == AIM_CAPS_VOICE) { - /* XXX this should make it up to the client, you know.. */ - if (errorcode) - faimdprintf(sess, 0, "transfer from %s (%s) for %s cancelled (error code %d)\n", ft->sn, ft->ip, ft->fh.name, errorcode); + faimdprintf(sess, 0, "voice request cancelled\n"); + + } else { + + faimdprintf(sess, 0, "unknown cookie cache type %d\n", cook->type); + } + + aim_freetlvchain(&list2); + + return 1; } - } else { - faimdprintf(sess, 0, "no data attached to file transfer\n"); - } - } else if (cook->type == AIM_CAPS_VOICE) { - faimdprintf(sess, 0, "voice request cancelled\n"); - } else { - faimdprintf(sess, 0, "unknown cookie cache type %d\n", cook->type); - } - - aim_freetlvchain(&list2); - return 1; - } + /* + * The rest of the handling depends on what type it is. + */ + if (args.reqclass & AIM_CAPS_BUDDYICON) { + struct aim_tlv_t *miscinfo; + int curpos = 0; - /* - * The rest of the handling depends on what type it is. - */ - if (args.reqclass & AIM_CAPS_BUDDYICON) { - struct aim_tlv_t *miscinfo; - int curpos = 0; - - miscinfo = aim_gettlv(list2, 0x2711, 1); + miscinfo = aim_gettlv(list2, 0x2711, 1); - /* aimutil_get32(miscinfo->value+curpos); i don't know what this is */ - curpos += 4; - args.info.icon.length = aimutil_get32(miscinfo->value+curpos); - curpos += 4; - args.info.icon.timestamp = aimutil_get32(miscinfo->value+curpos); - curpos += 4; - args.info.icon.icon = malloc(args.info.icon.length); - memcpy(args.info.icon.icon, miscinfo->value+curpos, args.info.icon.length); + /* aimutil_get32(miscinfo->value+curpos); i don't know what this is */ + curpos += 4; + args.info.icon.length = aimutil_get32(miscinfo->value+curpos); + curpos += 4; + args.info.icon.timestamp = aimutil_get32(miscinfo->value+curpos); + curpos += 4; + args.info.icon.icon = malloc(args.info.icon.length); + memcpy(args.info.icon.icon, miscinfo->value+curpos, args.info.icon.length); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, userinfo, &args); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, channel, userinfo, &args); - free(args.info.icon.icon); + free(args.info.icon.icon); - } else if (args.reqclass & AIM_CAPS_VOICE) { - struct aim_msgcookie_t *cachedcook; + } else if (args.reqclass & AIM_CAPS_VOICE) { + struct aim_msgcookie_t *cachedcook; - faimdprintf(sess, 0, "rend: voice!\n"); + faimdprintf(sess, 1, "rend: voice!\n"); - if(!(cachedcook = (struct aim_msgcookie_t*)calloc(1, sizeof(struct aim_msgcookie_t)))) { - aim_freetlvchain(&list2); - return 0; - } + if(!(cachedcook = (struct aim_msgcookie_t*)calloc(1, sizeof(struct aim_msgcookie_t)))) { + aim_freetlvchain(&list2); + return 0; + } - memcpy(cachedcook->cookie, cookie, 8); - cachedcook->type = AIM_COOKIETYPE_OFTVOICE; - cachedcook->data = NULL; + memcpy(cachedcook->cookie, cookie, 8); + cachedcook->type = AIM_COOKIETYPE_OFTVOICE; + cachedcook->data = NULL; - if (aim_cachecookie(sess, cachedcook) == -1) - faimdprintf(sess, 0, "ERROR caching message cookie\n"); + if (aim_cachecookie(sess, cachedcook) == -1) + faimdprintf(sess, 0, "ERROR caching message cookie\n"); - /* XXX: implement all this */ + /* XXX: implement all this */ - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, userinfo, &args); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, channel, userinfo, &args); - } else if (args.reqclass & AIM_CAPS_IMIMAGE) { - char ip[30]; - struct aim_directim_priv *priv; + } else if (args.reqclass & AIM_CAPS_IMIMAGE) { + char ip[30]; + struct aim_directim_priv *priv; - memset(ip, 0, sizeof(ip)); - - if (aim_gettlv(list2, 0x0003, 1) && aim_gettlv(list2, 0x0005, 1)) { - struct aim_tlv_t *iptlv, *porttlv; - - iptlv = aim_gettlv(list2, 0x0003, 1); - porttlv = aim_gettlv(list2, 0x0005, 1); + memset(ip, 0, sizeof(ip)); + + if (aim_gettlv(list2, 0x0003, 1) && aim_gettlv(list2, 0x0005, 1)) { + struct aim_tlv_t *iptlv, *porttlv; + + iptlv = aim_gettlv(list2, 0x0003, 1); + porttlv = aim_gettlv(list2, 0x0005, 1); - snprintf(ip, 30, "%d.%d.%d.%d:%d", - aimutil_get8(iptlv->value+0), - aimutil_get8(iptlv->value+1), - aimutil_get8(iptlv->value+2), - aimutil_get8(iptlv->value+3), - 4443 /*aimutil_get16(porttlv->value)*/); - } + snprintf(ip, 30, "%d.%d.%d.%d:%d", + aimutil_get8(iptlv->value+0), + aimutil_get8(iptlv->value+1), + aimutil_get8(iptlv->value+2), + aimutil_get8(iptlv->value+3), + 4443 /*aimutil_get16(porttlv->value)*/); + } - faimdprintf(sess, 0, "rend: directIM request from %s (%s)\n", - userinfo->sn, ip); + faimdprintf(sess, 1, "rend: directIM request from %s (%s)\n", + userinfo->sn, ip); - /* - * XXX: there are a couple of different request packets for - * different things - */ + /* + * XXX: there are a couple of different request packets for + * different things + */ - args.info.directim = priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv)); - memcpy(priv->ip, ip, sizeof(priv->ip)); - memcpy(priv->sn, userinfo->sn, sizeof(priv->sn)); - memcpy(priv->cookie, cookie, sizeof(priv->cookie)); + args.info.directim = priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv)); /* XXX error */ + memcpy(priv->ip, ip, sizeof(priv->ip)); + memcpy(priv->sn, userinfo->sn, sizeof(priv->sn)); + memcpy(priv->cookie, cookie, sizeof(priv->cookie)); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, userinfo, &args); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, channel, userinfo, &args); - } else if (args.reqclass & AIM_CAPS_CHAT) { - struct aim_tlv_t *miscinfo; + } else if (args.reqclass & AIM_CAPS_CHAT) { + struct aim_tlv_t *miscinfo; - miscinfo = aim_gettlv(list2, 0x2711, 1); - aim_chat_readroominfo(miscinfo->value, &args.info.chat.roominfo); - - if (aim_gettlv(list2, 0x000c, 1)) - args.info.chat.msg = aim_gettlv_str(list2, 0x000c, 1); - - if (aim_gettlv(list2, 0x000d, 1)) - args.info.chat.encoding = aim_gettlv_str(list2, 0x000d, 1); - - if (aim_gettlv(list2, 0x000e, 1)) - args.info.chat.lang = aim_gettlv_str(list2, 0x000e, 1); - - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, userinfo, &args); + miscinfo = aim_gettlv(list2, 0x2711, 1); + aim_chat_readroominfo(miscinfo->value, &args.info.chat.roominfo); + + if (aim_gettlv(list2, 0x000c, 1)) + args.info.chat.msg = aim_gettlv_str(list2, 0x000c, 1); + + if (aim_gettlv(list2, 0x000d, 1)) + args.info.chat.encoding = aim_gettlv_str(list2, 0x000d, 1); + + if (aim_gettlv(list2, 0x000e, 1)) + args.info.chat.lang = aim_gettlv_str(list2, 0x000e, 1); + + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, channel, userinfo, &args); - free(args.info.chat.roominfo.name); - free(args.info.chat.msg); - free(args.info.chat.encoding); - free(args.info.chat.lang); + free(args.info.chat.roominfo.name); + free(args.info.chat.msg); + free(args.info.chat.encoding); + free(args.info.chat.lang); - } else if (args.reqclass & AIM_CAPS_GETFILE) { - char ip[30]; - struct aim_msgcookie_t *cachedcook; - struct aim_tlv_t *miscinfo; - struct aim_tlv_t *iptlv, *porttlv; + } else if (args.reqclass & AIM_CAPS_GETFILE) { + char ip[30]; + struct aim_msgcookie_t *cachedcook; + struct aim_tlv_t *miscinfo; + struct aim_tlv_t *iptlv, *porttlv; - memset(ip, 0, 30); + memset(ip, 0, 30); - if (!(cachedcook = calloc(1, sizeof(struct aim_msgcookie_t)))) { - aim_freetlvchain(&list2); - return 0; - } + if (!(cachedcook = calloc(1, sizeof(struct aim_msgcookie_t)))) { + aim_freetlvchain(&list2); + return 0; + } - if (!(miscinfo = aim_gettlv(list2, 0x2711, 1)) || - !(iptlv = aim_gettlv(list2, 0x0003, 1)) || - !(porttlv = aim_gettlv(list2, 0x0005, 1))) { - faimdprintf(sess, 0, "rend: badly damaged file get request from %s...\n", userinfo->sn); - aim_cookie_free(sess, cachedcook); - aim_freetlvchain(&list2); - return 0; - } + if (!(miscinfo = aim_gettlv(list2, 0x2711, 1)) || + !(iptlv = aim_gettlv(list2, 0x0003, 1)) || + !(porttlv = aim_gettlv(list2, 0x0005, 1))) { + + faimdprintf(sess, 0, "rend: badly damaged file get request from %s...\n", userinfo->sn); + aim_cookie_free(sess, cachedcook); + aim_freetlvchain(&list2); + + return 0; + } - snprintf(ip, 30, "%d.%d.%d.%d:%d", - aimutil_get8(iptlv->value+0), - aimutil_get8(iptlv->value+1), - aimutil_get8(iptlv->value+2), - aimutil_get8(iptlv->value+3), - aimutil_get16(porttlv->value)); + snprintf(ip, 30, "%d.%d.%d.%d:%d", + aimutil_get8(iptlv->value+0), + aimutil_get8(iptlv->value+1), + aimutil_get8(iptlv->value+2), + aimutil_get8(iptlv->value+3), + aimutil_get16(porttlv->value)); - faimdprintf(sess, 0, "rend: file get request from %s (%s)\n", userinfo->sn, ip); + faimdprintf(sess, 0, "rend: file get request from %s (%s)\n", userinfo->sn, ip); - args.info.getfile.ip = ip; - args.info.getfile.cookie = cookie; + args.info.getfile.ip = ip; + args.info.getfile.cookie = cookie; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, userinfo, &args); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, channel, userinfo, &args); - } else if (args.reqclass & AIM_CAPS_SENDFILE) { -#if 0 - char ip[30]; - struct aim_msgcookie_t *cachedcook; - struct aim_tlv_t *miscinfo; - struct aim_tlv_t *iptlv, *porttlv; + } else if (args.reqclass & AIM_CAPS_SENDFILE) { +#if 0 + char ip[30]; + struct aim_msgcookie_t *cachedcook; + struct aim_tlv_t *miscinfo; + struct aim_tlv_t *iptlv, *porttlv; - memset(ip, 0, 30); + memset(ip, 0, 30); - if (!(cachedcook = calloc(1, sizeof(struct aim_msgcookie_t)))) { - aim_freetlvchain(&list2); - return 0; - } + if (!(cachedcook = calloc(1, sizeof(struct aim_msgcookie_t)))) { + aim_freetlvchain(&list2); + return 0; + } - if (!(miscinfo = aim_gettlv(list2, 0x2711, 1)) || - !(iptlv = aim_gettlv(list2, 0x0003, 1)) || - !(porttlv = aim_gettlv(list2, 0x0005, 1))) { - faimdprintf(sess, 0, "rend: badly damaged file get request from %s...\n", userinfo->sn); - aim_cookie_free(sess, cachedcook); - aim_freetlvchain(&list2); - return 0; - } + if (!(miscinfo = aim_gettlv(list2, 0x2711, 1)) || + !(iptlv = aim_gettlv(list2, 0x0003, 1)) || + !(porttlv = aim_gettlv(list2, 0x0005, 1))) { + + faimdprintf(sess, 0, "rend: badly damaged file get request from %s...\n", userinfo->sn); + aim_cookie_free(sess, cachedcook); + aim_freetlvchain(&list2); - snprintf(ip, 30, "%d.%d.%d.%d:%d", - aimutil_get8(iptlv->value+0), - aimutil_get8(iptlv->value+1), - aimutil_get8(iptlv->value+2), - aimutil_get8(iptlv->value+3), - aimutil_get16(porttlv->value)); + return 0; + } - if (aim_gettlv(list2, 0x000c, 1)) - desc = aim_gettlv_str(list2, 0x000c, 1); + snprintf(ip, 30, "%d.%d.%d.%d:%d", + aimutil_get8(iptlv->value+0), + aimutil_get8(iptlv->value+1), + aimutil_get8(iptlv->value+2), + aimutil_get8(iptlv->value+3), + aimutil_get16(porttlv->value)); + + if (aim_gettlv(list2, 0x000c, 1)) + desc = aim_gettlv_str(list2, 0x000c, 1); - faimdprintf(sess, 0, "rend: file transfer request from %s for %s: %s (%s)\n", - userinfo->sn, miscinfo->value+8, - desc, ip); - - memcpy(cachedcook->cookie, cookie, 8); - - ft = malloc(sizeof(struct aim_filetransfer_priv)); - strncpy(ft->sn, userinfo.sn, sizeof(ft->sn)); - strncpy(ft->ip, ip, sizeof(ft->ip)); - strncpy(ft->fh.name, miscinfo->value+8, sizeof(ft->fh.name)); - cachedcook->type = AIM_COOKIETYPE_OFTSEND; - cachedcook->data = ft; + faimdprintf(sess, 0, "rend: file transfer request from %s: %s (%s)\n", + userinfo->sn, desc, ip); + + memcpy(cachedcook->cookie, cookie, 8); - if (aim_cachecookie(sess, cachedcook) == -1) - faimdprintf(sess, 0, "ERROR caching message cookie\n"); + ft = malloc(sizeof(struct aim_filetransfer_priv)); /* XXX */ + strncpy(ft->sn, userinfo.sn, sizeof(ft->sn)); + strncpy(ft->ip, ip, sizeof(ft->ip)); + strncpy(ft->fh.name, miscinfo->value+8, sizeof(ft->fh.name)); + cachedcook->type = AIM_COOKIETYPE_OFTSEND; + cachedcook->data = ft; - aim_accepttransfer(sess, rx->conn, ft->sn, cookie, AIM_CAPS_SENDFILE); - - if (desc) - free(desc); + if (aim_cachecookie(sess, cachedcook) == -1) + faimdprintf(sess, 0, "ERROR caching message cookie\n"); + + aim_accepttransfer(sess, rx->conn, ft->sn, cookie, AIM_CAPS_SENDFILE); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, userinfo, &args); + if (desc) + free(desc); + + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, channel, userinfo, &args); #endif - } else - faimdprintf(sess, 0, "rend: unknown rendezvous 0x%04x\n", args.reqclass); + } else + faimdprintf(sess, 0, "rend: unknown rendezvous 0x%04x\n", args.reqclass); - aim_freetlvchain(&list2); + aim_freetlvchain(&list2); - return ret; + return ret; } /* @@ -871,90 +933,90 @@ */ static int incomingim(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - int i, ret = 0; - unsigned char cookie[8]; - int channel; - struct aim_userinfo_s userinfo; + int i, ret = 0; + unsigned char cookie[8]; + int channel; + struct aim_userinfo_s userinfo; + + memset(&userinfo, 0x00, sizeof(struct aim_userinfo_s)); + + /* + * Read ICBM Cookie. And throw away. + */ + for (i = 0; i < 8; i++) + cookie[i] = aimutil_get8(data+i); - memset(&userinfo, 0x00, sizeof(struct aim_userinfo_s)); - - /* - * Read ICBM Cookie. And throw away. - */ - for (i = 0; i < 8; i++) - cookie[i] = aimutil_get8(data+i); - - /* - * Channel ID. - * - * Channel 0x0001 is the message channel. There are - * other channels for things called "rendevous" - * which represent chat and some of the other new - * features of AIM2/3/3.5. - * - * Channel 0x0002 is the Rendevous channel, which - * is where Chat Invitiations and various client-client - * connection negotiations come from. - * - */ - channel = aimutil_get16(data+i); - i += 2; - - /* - * - */ - if ((channel != 0x01) && (channel != 0x02)) { - faimdprintf(sess, 0, "icbm: ICBM received on an unsupported channel. Ignoring.\n (chan = %04x)", channel); - return 1; - } + /* + * Channel ID. + * + * Channel 0x0001 is the message channel. There are + * other channels for things called "rendevous" + * which represent chat and some of the other new + * features of AIM2/3/3.5. + * + * Channel 0x0002 is the Rendevous channel, which + * is where Chat Invitiations and various client-client + * connection negotiations come from. + * + */ + channel = aimutil_get16(data+i); + i += 2; + + /* + * Technically Channel 3 in chat could be done here too. + */ + if ((channel != 0x01) && (channel != 0x02)) { + faimdprintf(sess, 0, "icbm: ICBM received on an unsupported channel. Ignoring.\n (chan = %04x)", channel); + return 1; + } - /* - * Extract the standard user info block. - * - * Note that although this contains TLVs that appear contiguous - * 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. - * - * 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. - * - */ - i += aim_extractuserinfo(sess, data+i, &userinfo); - - /* - * From here on, its depends on what channel we're on. - * - * Technically all channels have a TLV list have this, however, - * for the common channel 1 case, in-place parsing is used for - * performance reasons (less memory allocation). - */ - if (channel == 1) { + /* + * Extract the standard user info block. + * + * Note that although this contains TLVs that appear contiguous + * 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. + * + * 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. + * + */ + i += aim_extractuserinfo(sess, data+i, &userinfo); - ret = incomingim_ch1(sess, mod, rx, snac, channel, &userinfo, data+i, datalen-i, cookie); + /* + * From here on, its depends on what channel we're on. + * + * Technically all channels have a TLV list have this, however, + * for the common channel 1 case, in-place parsing is used for + * performance reasons (less memory allocation). + */ + if (channel == 1) { - } else if (channel == 0x0002) { - struct aim_tlvlist_t *tlvlist; + ret = incomingim_ch1(sess, mod, rx, snac, channel, &userinfo, data+i, datalen-i, cookie); + + } else if (channel == 0x0002) { + struct aim_tlvlist_t *tlvlist; - /* - * Read block of TLVs (not including the userinfo data). All - * further data is derived from what is parsed here. - */ - tlvlist = aim_readtlvchain(data+i, datalen-i); + /* + * Read block of TLVs (not including the userinfo data). All + * further data is derived from what is parsed here. + */ + tlvlist = aim_readtlvchain(data+i, datalen-i); - ret = incomingim_ch2(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie); + ret = incomingim_ch2(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie); - /* - * Free up the TLV chain. - */ - aim_freetlvchain(&tlvlist); - } + /* + * Free up the TLV chain. + */ + aim_freetlvchain(&tlvlist); + } - return ret; + return ret; } /* @@ -964,184 +1026,190 @@ * AIM_TRANSFER_DENY_NOTACCEPTING -- "client is not accepting transfers" * */ -faim_export unsigned long aim_denytransfer(struct aim_session_t *sess, - struct aim_conn_t *conn, - char *sender, - char *cookie, - unsigned short code) +faim_export int aim_denytransfer(struct aim_session_t *sess, + struct aim_conn_t *conn, + const char *sender, + const char *cookie, + unsigned short code) { - struct command_tx_struct *newpacket; - int curbyte, i; + struct command_tx_struct *newpacket; + int curbyte, i; - if(!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+8+2+1+strlen(sender)+6))) - return -1; + if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+8+2+1+strlen(sender)+6))) + return -ENOMEM; - newpacket->lock = 1; + newpacket->lock = 1; - curbyte = aim_putsnac(newpacket->data, 0x0004, 0x000b, 0x0000, sess->snac_nextid); - for (i = 0; i < 8; i++) - curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); - curbyte += aimutil_put8(newpacket->data+curbyte, strlen(sender)); - curbyte += aimutil_putstr(newpacket->data+curbyte, sender, strlen(sender)); - curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0003, code); + curbyte = aim_putsnac(newpacket->data, 0x0004, 0x000b, 0x0000, sess->snac_nextid++); + for (i = 0; i < 8; i++) + curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); + curbyte += aimutil_put8(newpacket->data+curbyte, strlen(sender)); + curbyte += aimutil_putstr(newpacket->data+curbyte, sender, strlen(sender)); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0003, code); - newpacket->lock = 0; - aim_tx_enqueue(sess, newpacket); + newpacket->lock = 0; + aim_tx_enqueue(sess, newpacket); - return (sess->snac_nextid++); + return 0; } /* - * Not real sure what this does, nor does anyone I've talk to. + * aim_reqicbmparaminfo() + * + * Request ICBM parameter information. * - * Didn't use to send it. But now I think it might be a good - * idea. + */ +faim_export unsigned long aim_reqicbmparams(struct aim_session_t *sess, struct aim_conn_t *conn) +{ + return aim_genericreq_n(sess, conn, 0x0004, 0x0004); +} + +/* * */ -faim_export unsigned long aim_seticbmparam(struct aim_session_t *sess, - struct aim_conn_t *conn) +faim_export unsigned long aim_seticbmparam(struct aim_session_t *sess, struct aim_conn_t *conn, struct aim_icbmparameters *params) { - struct command_tx_struct *newpacket; - int curbyte; + struct command_tx_struct *newpacket; + int curbyte; + + if (!sess || !conn || !params) + return -EINVAL; - if(!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+16))) - return -1; + if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+16))) + return -ENOMEM; - newpacket->lock = 1; + newpacket->lock = 1; + + curbyte = aim_putsnac(newpacket->data, 0x0004, 0x0002, 0x0000, sess->snac_nextid++); - curbyte = aim_putsnac(newpacket->data, 0x0004, 0x0002, 0x0000, sess->snac_nextid); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); - curbyte += aimutil_put32(newpacket->data+curbyte, 0x00000003); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x1f40); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x03e7); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x03e7); - curbyte += aimutil_put32(newpacket->data+curbyte, 0x00000000); + /* This is read-only (in Parameter Reply). Must be set to zero here. */ + curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); - newpacket->lock = 0; - aim_tx_enqueue(sess, newpacket); + /* These are all read-write */ + curbyte += aimutil_put32(newpacket->data+curbyte, params->flags); + curbyte += aimutil_put16(newpacket->data+curbyte, params->maxmsglen); + curbyte += aimutil_put16(newpacket->data+curbyte, params->maxsenderwarn); + curbyte += aimutil_put16(newpacket->data+curbyte, params->maxrecverwarn); + curbyte += aimutil_put32(newpacket->data+curbyte, params->minmsginterval); - return (sess->snac_nextid++); + newpacket->lock = 0; + aim_tx_enqueue(sess, newpacket); + + return 0; } static int paraminfo(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - unsigned long defflags, minmsginterval; - unsigned short maxicbmlen, maxsenderwarn, maxrecverwarn, maxchannel; - aim_rxcallback_t userfunc; - int i = 0; + struct aim_icbmparameters params; + aim_rxcallback_t userfunc; + int i = 0; - maxchannel = aimutil_get16(data+i); - i += 2; + params.maxchan = aimutil_get16(data+i); + i += 2; - defflags = aimutil_get32(data+i); - i += 4; + params.flags = aimutil_get32(data+i); + i += 4; - maxicbmlen = aimutil_get16(data+i); - i += 2; + params.maxmsglen = aimutil_get16(data+i); + i += 2; - maxsenderwarn = aimutil_get16(data+i); - i += 2; + params.maxsenderwarn = aimutil_get16(data+i); + i += 2; - maxrecverwarn = aimutil_get16(data+i); - i += 2; + params.maxrecverwarn = aimutil_get16(data+i); + i += 2; - minmsginterval = aimutil_get32(data+i); - i += 4; + params.minmsginterval = aimutil_get32(data+i); + i += 4; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - return userfunc(sess, rx, maxchannel, defflags, maxicbmlen, maxsenderwarn, maxrecverwarn, minmsginterval); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + return userfunc(sess, rx, ¶ms); - return 0; + return 0; } static int missedcall(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - int i = 0; - aim_rxcallback_t userfunc; - unsigned short channel, nummissed, reason; - struct aim_userinfo_s userinfo; - - /* - * XXX: supposedly, this entire packet can repeat as many times - * as necessary. Should implement that. - */ + int i, ret = 0; + aim_rxcallback_t userfunc; + unsigned short channel, nummissed, reason; + struct aim_userinfo_s userinfo; + + for (i = 0; i < datalen; ) { + + /* Channel ID. */ + channel = aimutil_get16(data+i); + i += 2; - /* - * Channel ID. - */ - channel = aimutil_get16(data+i); - i += 2; - - /* - * Extract the standard user info block. - */ - i += aim_extractuserinfo(sess, data+i, &userinfo); - - nummissed = aimutil_get16(data+i); - i += 2; - - reason = aimutil_get16(data+i); - i += 2; + /* Extract the standard user info block. */ + i += aim_extractuserinfo(sess, data+i, &userinfo); + + nummissed = aimutil_get16(data+i); + i += 2; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - return userfunc(sess, rx, channel, &userinfo, nummissed, reason); - - return 0; + reason = aimutil_get16(data+i); + i += 2; + + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, channel, &userinfo, nummissed, reason); + } + + return ret; } static int msgack(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - aim_rxcallback_t userfunc; - char sn[MAXSNLEN]; - unsigned char ck[8]; - unsigned short type; - int i = 0; - unsigned char snlen; + aim_rxcallback_t userfunc; + char sn[MAXSNLEN]; + unsigned char ck[8]; + unsigned short type; + int i = 0; + unsigned char snlen; - memcpy(ck, data, 8); - i += 8; + memcpy(ck, data, 8); + i += 8; - type = aimutil_get16(data+i); - i += 2; + type = aimutil_get16(data+i); + i += 2; - snlen = aimutil_get8(data+i); - i++; + snlen = aimutil_get8(data+i); + i++; - memset(sn, 0, sizeof(sn)); - strncpy(sn, (char *)data+i, snlen); + memset(sn, 0, sizeof(sn)); + strncpy(sn, (char *)data+i, snlen); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - return userfunc(sess, rx, type, sn); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + return userfunc(sess, rx, type, sn); - return 0; + return 0; } static int snachandler(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - if (snac->subtype == 0x0005) - return paraminfo(sess, mod, rx, snac, data, datalen); - else if (snac->subtype == 0x0006) - return outgoingim(sess, mod, rx, snac, data, datalen); - else if (snac->subtype == 0x0007) - return incomingim(sess, mod, rx, snac, data, datalen); - else if (snac->subtype == 0x000a) - return missedcall(sess, mod, rx, snac, data, datalen); - else if (snac->subtype == 0x000c) - return msgack(sess, mod, rx, snac, data, datalen); + if (snac->subtype == 0x0005) + return paraminfo(sess, mod, rx, snac, data, datalen); + else if (snac->subtype == 0x0006) + return outgoingim(sess, mod, rx, snac, data, datalen); + else if (snac->subtype == 0x0007) + return incomingim(sess, mod, rx, snac, data, datalen); + else if (snac->subtype == 0x000a) + return missedcall(sess, mod, rx, snac, data, datalen); + else if (snac->subtype == 0x000c) + return msgack(sess, mod, rx, snac, data, datalen); - return 0; + return 0; } faim_internal int msg_modfirst(struct aim_session_t *sess, aim_module_t *mod) { - mod->family = 0x0004; - mod->version = 0x0000; - mod->flags = 0; - strncpy(mod->name, "messaging", sizeof(mod->name)); - mod->snachandler = snachandler; + mod->family = 0x0004; + mod->version = 0x0000; + mod->flags = 0; + strncpy(mod->name, "messaging", sizeof(mod->name)); + mod->snachandler = snachandler; - return 0; + return 0; } diff -r dbd74f49dabb -r edf8c5a70e5b src/protocols/oscar/login.c --- a/src/protocols/oscar/login.c Sun Aug 26 19:18:39 2001 +0000 +++ b/src/protocols/oscar/login.c Sun Aug 26 20:21:45 2001 +0000 @@ -12,23 +12,23 @@ static int aim_encode_password(const char *password, unsigned char *encoded); -faim_export int aim_sendconnack(struct aim_session_t *sess, - struct aim_conn_t *conn) +faim_export int aim_sendflapver(struct aim_session_t *sess, struct aim_conn_t *conn) { - int curbyte=0; - - struct command_tx_struct *newpacket; + int curbyte=0; + + struct command_tx_struct *newpacket; + + if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0001, 4))) + return -ENOMEM; - if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0001, 4))) - return -1; + newpacket->lock = 1; - newpacket->lock = 1; - - curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001); - newpacket->lock = 0; - return aim_tx_enqueue(sess, newpacket); + newpacket->lock = 0; + + return aim_tx_enqueue(sess, newpacket); } /* @@ -39,81 +39,82 @@ * a 0017/0007 comes back, which is the signal to send * it the main login command (0017/0002). */ -faim_export int aim_request_login(struct aim_session_t *sess, - struct aim_conn_t *conn, - char *sn) +faim_export int aim_request_login(struct aim_session_t *sess, struct aim_conn_t *conn, const char *sn) { - int curbyte; - struct command_tx_struct *newpacket; + int curbyte; + struct command_tx_struct *newpacket; - if (!sess || !conn || !sn) - return -1; + if (!sess || !conn || !sn) + return -EINVAL; - /* - * For ICQ, we enable the ancient horrible login and stuff - * a key packet into the queue to make it look like we got - * a reply back. This is so the client doesn't know we're - * really not doing MD5 login. - * - * This may sound stupid, but I'm not in the best of moods and - * I don't plan to keep support for this crap around much longer. - * Its all AOL's fault anyway, really. I hate AOL. Really. They - * always seem to be able to piss me off by doing the dumbest little - * things. Like disabling MD5 logins for ICQ UINs, or adding purposefully - * wrong TLV lengths, or adding superfluous information to host strings, - * or... I'll stop. - * - */ - if ((sn[0] >= '0') && (sn[0] <= '9')) { - struct command_rx_struct *newrx; - int i; + /* + * For ICQ, we enable the ancient horrible login and stuff + * a key packet into the queue to make it look like we got + * a reply back. This is so the client doesn't know we're + * really not doing MD5 login. + * + * This may sound stupid, but I'm not in the best of moods and + * I don't plan to keep support for this crap around much longer. + * Its all AOL's fault anyway, really. I hate AOL. Really. They + * always seem to be able to piss me off by doing the dumbest little + * things. Like disabling MD5 logins for ICQ UINs, or adding + * purposefully wrong TLV lengths, or adding superfluous information + * to host strings, or... I'll stop. + * + */ + if ((sn[0] >= '0') && (sn[0] <= '9')) { + struct command_rx_struct *newrx; + int i; + + /* XXX Uhm why doesn't this use aim_tx_new? */ + if (!(newrx = (struct command_rx_struct *)malloc(sizeof(struct command_rx_struct)))) + return -ENOMEM; - if (!(newrx = (struct command_rx_struct *)malloc(sizeof(struct command_rx_struct)))) - return -1; - memset(newrx, 0x00, sizeof(struct command_rx_struct)); - newrx->lock = 1; - newrx->hdrtype = AIM_FRAMETYPE_OSCAR; - newrx->hdr.oscar.type = 0x02; - newrx->hdr.oscar.seqnum = 0; - newrx->commandlen = 10+2+1; - newrx->nofree = 0; - if (!(newrx->data = malloc(newrx->commandlen))) { - free(newrx); - return -1; - } + memset(newrx, 0x00, sizeof(struct command_rx_struct)); + newrx->lock = 1; + newrx->hdrtype = AIM_FRAMETYPE_OSCAR; + newrx->hdr.oscar.type = 0x02; + newrx->hdr.oscar.seqnum = 0; + newrx->commandlen = 10+2+1; + newrx->nofree = 0; - i = aim_putsnac(newrx->data, 0x0017, 0x0007, 0x0000, 0x0000); - i += aimutil_put16(newrx->data+i, 0x01); - i += aimutil_putstr(newrx->data+i, "0", 1); + if (!(newrx->data = malloc(newrx->commandlen))) { + free(newrx); + return -ENOMEM; + } - newrx->conn = conn; + i = aim_putsnac(newrx->data, 0x0017, 0x0007, 0x0000, 0x0000); + i += aimutil_put16(newrx->data+i, 0x01); + i += aimutil_putstr(newrx->data+i, "0", 1); - newrx->next = sess->queue_incoming; - sess->queue_incoming = newrx; + newrx->conn = conn; + + newrx->next = sess->queue_incoming; + sess->queue_incoming = newrx; - newrx->lock = 0; + newrx->lock = 0; - sess->flags &= ~AIM_SESS_FLAGS_SNACLOGIN; + sess->flags &= ~AIM_SESS_FLAGS_SNACLOGIN; - return 0; - } + return 0; + } - sess->flags |= AIM_SESS_FLAGS_SNACLOGIN; + sess->flags |= AIM_SESS_FLAGS_SNACLOGIN; - aim_sendconnack(sess, conn); + aim_sendflapver(sess, conn); - if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+2+2+strlen(sn)))) - return -1; + if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+2+2+strlen(sn)))) + return -ENOMEM; + + newpacket->lock = 1; - newpacket->lock = 1; - - curbyte = aim_putsnac(newpacket->data, 0x0017, 0x0006, 0x0000, 0x00010000); - curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); + curbyte = aim_putsnac(newpacket->data, 0x0017, 0x0006, 0x0000, 0x00010000); + curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); - newpacket->commandlen = curbyte; - newpacket->lock = 0; + newpacket->commandlen = curbyte; + newpacket->lock = 0; - return aim_tx_enqueue(sess, newpacket); + return aim_tx_enqueue(sess, newpacket); } /* @@ -175,93 +176,89 @@ * serverstore = 0x01 * */ -faim_export int aim_send_login (struct aim_session_t *sess, - struct aim_conn_t *conn, - char *sn, char *password, - struct client_info_s *clientinfo, - char *key) +faim_export int aim_send_login (struct aim_session_t *sess, struct aim_conn_t *conn, char *sn, char *password, struct client_info_s *clientinfo, char *key) { - int curbyte=0; - struct command_tx_struct *newpacket; + int curbyte=0; + struct command_tx_struct *newpacket; + + if (!clientinfo || !sn || !password) + return -EINVAL; - if (!clientinfo || !sn || !password) - return -1; + if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152))) + return -ENOMEM; - if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152))) - return -1; + newpacket->lock = 1; - newpacket->lock = 1; + newpacket->hdr.oscar.type = (sess->flags & AIM_SESS_FLAGS_SNACLOGIN)?0x02:0x01; - newpacket->hdr.oscar.type = (sess->flags & AIM_SESS_FLAGS_SNACLOGIN)?0x02:0x01; - - if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) - curbyte = aim_putsnac(newpacket->data, 0x0017, 0x0002, 0x0000, 0x00010000); - else { - curbyte = aimutil_put16(newpacket->data, 0x0000); - curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001); - } + if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) + curbyte = aim_putsnac(newpacket->data, 0x0017, 0x0002, 0x0000, 0x00010000); + else { + curbyte = aimutil_put16(newpacket->data, 0x0000); + curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001); + } - curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); - - if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) { - unsigned char digest[16]; + curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); + + if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) { + unsigned char digest[16]; - aim_encode_password_md5(password, key, digest); - curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0025, 16, (char *)digest); - } else { - char *password_encoded; + aim_encode_password_md5(password, key, digest); + curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0025, 16, (char *)digest); + } else { + char *password_encoded; - password_encoded = (char *) malloc(strlen(password)); - aim_encode_password(password, password_encoded); - curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0002, strlen(password), password_encoded); - free(password_encoded); - } + password_encoded = (char *) malloc(strlen(password)); + aim_encode_password(password, password_encoded); + curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0002, strlen(password), password_encoded); + free(password_encoded); + } + + curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0003, strlen(clientinfo->clientstring), clientinfo->clientstring); - curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0003, strlen(clientinfo->clientstring), clientinfo->clientstring); + if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) { - if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) { + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, (unsigned short)clientinfo->major2); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, (unsigned short)clientinfo->major); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, (unsigned short)clientinfo->minor); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, (unsigned short)clientinfo->minor2); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, (unsigned short)clientinfo->build); - curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, (unsigned short)clientinfo->major2); - curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, (unsigned short)clientinfo->major); - curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, (unsigned short)clientinfo->minor); - curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, (unsigned short)clientinfo->minor2); - curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, (unsigned short)clientinfo->build); - - } else { - /* Use very specific version numbers, to further indicate the hack. */ - curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, 0x010a); - curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, 0x0004); - curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, 0x003c); - curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, 0x0001); - curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, 0x0cce); - curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, 0x00000055); - } + } else { + /* Use very specific version numbers, to further indicate the hack. */ + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, 0x010a); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, 0x0004); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, 0x003c); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, 0x0001); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, 0x0cce); + curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, 0x00000055); + } - curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000e, strlen(clientinfo->country), clientinfo->country); - curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000f, strlen(clientinfo->lang), clientinfo->lang); - - if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) { - curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, clientinfo->unknown); - curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0009, 0x0015); - } + curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000e, strlen(clientinfo->country), clientinfo->country); + curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000f, strlen(clientinfo->lang), clientinfo->lang); - newpacket->commandlen = curbyte; + if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) { + curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, clientinfo->unknown); + curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0009, 0x0015); + } - newpacket->lock = 0; - return aim_tx_enqueue(sess, newpacket); + newpacket->commandlen = curbyte; + newpacket->lock = 0; + + return aim_tx_enqueue(sess, newpacket); } faim_export int aim_encode_password_md5(const char *password, const char *key, unsigned char *digest) { - md5_state_t state; + md5_state_t state; - md5_init(&state); - md5_append(&state, (const md5_byte_t *)key, strlen(key)); - md5_append(&state, (const md5_byte_t *)password, strlen(password)); - md5_append(&state, (const md5_byte_t *)AIM_MD5_STRING, strlen(AIM_MD5_STRING)); - md5_finish(&state, (md5_byte_t *)digest); + md5_init(&state); + md5_append(&state, (const md5_byte_t *)key, strlen(key)); + md5_append(&state, (const md5_byte_t *)password, strlen(password)); + md5_append(&state, (const md5_byte_t *)AIM_MD5_STRING, strlen(AIM_MD5_STRING)); + md5_finish(&state, (md5_byte_t *)digest); - return 0; + return 0; } /** @@ -283,26 +280,25 @@ */ static int aim_encode_password(const char *password, unsigned char *encoded) { - u_char encoding_table[] = { + unsigned char encoding_table[] = { #if 0 /* old v1 table */ - 0xf3, 0xb3, 0x6c, 0x99, - 0x95, 0x3f, 0xac, 0xb6, - 0xc5, 0xfa, 0x6b, 0x63, - 0x69, 0x6c, 0xc3, 0x9f + 0xf3, 0xb3, 0x6c, 0x99, + 0x95, 0x3f, 0xac, 0xb6, + 0xc5, 0xfa, 0x6b, 0x63, + 0x69, 0x6c, 0xc3, 0x9f #else /* v2.1 table, also works for ICQ */ - 0xf3, 0x26, 0x81, 0xc4, - 0x39, 0x86, 0xdb, 0x92, - 0x71, 0xa3, 0xb9, 0xe6, - 0x53, 0x7a, 0x95, 0x7c + 0xf3, 0x26, 0x81, 0xc4, + 0x39, 0x86, 0xdb, 0x92, + 0x71, 0xa3, 0xb9, 0xe6, + 0x53, 0x7a, 0x95, 0x7c #endif - }; + }; + int i; - int i; - - for (i = 0; i < strlen(password); i++) - encoded[i] = (password[i] ^ encoding_table[i]); + for (i = 0; i < strlen(password); i++) + encoded[i] = (password[i] ^ encoding_table[i]); - return 0; + return 0; } /* @@ -318,33 +314,33 @@ char *cookie, char *email, int regstatus) { - struct command_tx_struct *tx; - struct aim_tlvlist_t *tlvlist = NULL; + struct command_tx_struct *tx; + struct aim_tlvlist_t *tlvlist = NULL; + + if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0004, 1152))) + return -ENOMEM; - if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0004, 1152))) - return -1; - - tx->lock = 1; + tx->lock = 1; - if (sn) - aim_addtlvtochain_str(&tlvlist, 0x0001, sn, strlen(sn)); - else - aim_addtlvtochain_str(&tlvlist, 0x0001, sess->sn, strlen(sess->sn)); + if (sn) + aim_addtlvtochain_str(&tlvlist, 0x0001, sn, strlen(sn)); + else + aim_addtlvtochain_str(&tlvlist, 0x0001, sess->sn, strlen(sess->sn)); - if (errorcode) { - aim_addtlvtochain16(&tlvlist, 0x0008, errorcode); - aim_addtlvtochain_str(&tlvlist, 0x0004, errorurl, strlen(errorurl)); - } else { - aim_addtlvtochain_str(&tlvlist, 0x0005, bosip, strlen(bosip)); - aim_addtlvtochain_str(&tlvlist, 0x0006, cookie, AIM_COOKIELEN); - aim_addtlvtochain_str(&tlvlist, 0x0011, email, strlen(email)); - aim_addtlvtochain16(&tlvlist, 0x0013, (unsigned short)regstatus); - } + if (errorcode) { + aim_addtlvtochain16(&tlvlist, 0x0008, errorcode); + aim_addtlvtochain_str(&tlvlist, 0x0004, errorurl, strlen(errorurl)); + } else { + aim_addtlvtochain_str(&tlvlist, 0x0005, bosip, strlen(bosip)); + aim_addtlvtochain_str(&tlvlist, 0x0006, cookie, AIM_COOKIELEN); + aim_addtlvtochain_str(&tlvlist, 0x0011, email, strlen(email)); + aim_addtlvtochain16(&tlvlist, 0x0013, (unsigned short)regstatus); + } - tx->commandlen = aim_writetlvchain(tx->data, tx->commandlen, &tlvlist); - tx->lock = 0; + tx->commandlen = aim_writetlvchain(tx->data, tx->commandlen, &tlvlist); + tx->lock = 0; - return aim_tx_enqueue(sess, tx); + return aim_tx_enqueue(sess, tx); } /* @@ -352,14 +348,14 @@ */ faim_export int aim_gencookie(unsigned char *buf) { - int i; + int i; - srand(time(NULL)); + srand(time(NULL)); - for (i=0; i < AIM_COOKIELEN; i++) - buf[i] = 1+(int) (256.0*rand()/(RAND_MAX+0.0)); + for (i=0; i < AIM_COOKIELEN; i++) + buf[i] = 1+(int) (256.0*rand()/(RAND_MAX+0.0)); - return i; + return i; } /* @@ -367,135 +363,132 @@ */ faim_export int aim_sendserverready(struct aim_session_t *sess, struct aim_conn_t *conn) { - struct command_tx_struct *tx; - int i = 0; + struct command_tx_struct *tx; + int i; - if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+0x22))) - return -1; + if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+0x22))) + return -ENOMEM; - tx->lock = 1; + tx->lock = 1; + + i = aim_putsnac(tx->data, 0x0001, 0x0003, 0x0000, sess->snac_nextid++); - i += aim_putsnac(tx->data, 0x0001, 0x0003, 0x0000, sess->snac_nextid++); - - i += aimutil_put16(tx->data+i, 0x0001); - i += aimutil_put16(tx->data+i, 0x0002); - i += aimutil_put16(tx->data+i, 0x0003); - i += aimutil_put16(tx->data+i, 0x0004); - i += aimutil_put16(tx->data+i, 0x0006); - i += aimutil_put16(tx->data+i, 0x0008); - i += aimutil_put16(tx->data+i, 0x0009); - i += aimutil_put16(tx->data+i, 0x000a); - i += aimutil_put16(tx->data+i, 0x000b); - i += aimutil_put16(tx->data+i, 0x000c); - i += aimutil_put16(tx->data+i, 0x0013); - i += aimutil_put16(tx->data+i, 0x0015); + i += aimutil_put16(tx->data+i, 0x0001); + i += aimutil_put16(tx->data+i, 0x0002); + i += aimutil_put16(tx->data+i, 0x0003); + i += aimutil_put16(tx->data+i, 0x0004); + i += aimutil_put16(tx->data+i, 0x0006); + i += aimutil_put16(tx->data+i, 0x0008); + i += aimutil_put16(tx->data+i, 0x0009); + i += aimutil_put16(tx->data+i, 0x000a); + i += aimutil_put16(tx->data+i, 0x000b); + i += aimutil_put16(tx->data+i, 0x000c); + i += aimutil_put16(tx->data+i, 0x0013); + i += aimutil_put16(tx->data+i, 0x0015); - tx->commandlen = i; - tx->lock = 0; - return aim_tx_enqueue(sess, tx); + tx->commandlen = i; + tx->lock = 0; + + return aim_tx_enqueue(sess, tx); } /* * Send service redirect. (Non-Client) */ -faim_export unsigned long aim_sendredirect(struct aim_session_t *sess, - struct aim_conn_t *conn, - unsigned short servid, - char *ip, - char *cookie) +faim_export unsigned long aim_sendredirect(struct aim_session_t *sess, struct aim_conn_t *conn, unsigned short servid, char *ip, char *cookie) { - struct command_tx_struct *tx; - struct aim_tlvlist_t *tlvlist = NULL; - int i = 0; + struct command_tx_struct *tx; + struct aim_tlvlist_t *tlvlist = NULL; + int i; - if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152))) - return -1; + if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152))) + return -ENOMEM; + + tx->lock = 1; - tx->lock = 1; + i = aim_putsnac(tx->data, 0x0001, 0x0005, 0x0000, 0x00000000); + + aim_addtlvtochain16(&tlvlist, 0x000d, servid); + aim_addtlvtochain_str(&tlvlist, 0x0005, ip, strlen(ip)); + aim_addtlvtochain_str(&tlvlist, 0x0006, cookie, AIM_COOKIELEN); - i += aim_putsnac(tx->data+i, 0x0001, 0x0005, 0x0000, 0x00000000); - - aim_addtlvtochain16(&tlvlist, 0x000d, servid); - aim_addtlvtochain_str(&tlvlist, 0x0005, ip, strlen(ip)); - aim_addtlvtochain_str(&tlvlist, 0x0006, cookie, AIM_COOKIELEN); + tx->commandlen = aim_writetlvchain(tx->data+i, tx->commandlen-i, &tlvlist)+i; + aim_freetlvchain(&tlvlist); - tx->commandlen = aim_writetlvchain(tx->data+i, tx->commandlen-i, &tlvlist)+i; - aim_freetlvchain(&tlvlist); + tx->lock = 0; - tx->lock = 0; - return aim_tx_enqueue(sess, tx); + return aim_tx_enqueue(sess, tx); } static int hostonline(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - aim_rxcallback_t userfunc; - int ret = 0; - unsigned short *families; - int famcount, i; + aim_rxcallback_t userfunc; + int ret = 0; + unsigned short *families; + int famcount, i; - famcount = datalen/2; + famcount = datalen/2; - if (!(families = malloc(datalen))) - return 0; + if (!(families = malloc(datalen))) + return 0; - for (i = 0; i < famcount; i++) - families[i] = aimutil_get16(data+(i*2)); + for (i = 0; i < famcount; i++) + families[i] = aimutil_get16(data+(i*2)); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, famcount, families); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, famcount, families); - free(families); + free(families); - return ret; + return ret; } static int redirect(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - int serviceid; - unsigned char *cookie; - char *ip; - aim_rxcallback_t userfunc; - struct aim_tlvlist_t *tlvlist; - char *chathack = NULL; - int chathackex = 0; - int ret = 0; - - tlvlist = aim_readtlvchain(data, datalen); + int serviceid; + unsigned char *cookie; + char *ip; + aim_rxcallback_t userfunc; + struct aim_tlvlist_t *tlvlist; + char *chathack = NULL; + int chathackex = 0; + int ret = 0; - if (!aim_gettlv(tlvlist, 0x000d, 1) || - !aim_gettlv(tlvlist, 0x0005, 1) || - !aim_gettlv(tlvlist, 0x0006, 1)) { - aim_freetlvchain(&tlvlist); - return 0; - } + tlvlist = aim_readtlvchain(data, datalen); - serviceid = aim_gettlv16(tlvlist, 0x000d, 1); - ip = aim_gettlv_str(tlvlist, 0x0005, 1); - cookie = aim_gettlv_str(tlvlist, 0x0006, 1); + if (!aim_gettlv(tlvlist, 0x000d, 1) || + !aim_gettlv(tlvlist, 0x0005, 1) || + !aim_gettlv(tlvlist, 0x0006, 1)) { + aim_freetlvchain(&tlvlist); + return 0; + } - /* - * Chat hack. - * - */ - if ((serviceid == AIM_CONN_TYPE_CHAT) && sess->pendingjoin) { - chathack = sess->pendingjoin; - chathackex = sess->pendingjoinexchange; - sess->pendingjoin = NULL; - sess->pendingjoinexchange = 0; - } + serviceid = aim_gettlv16(tlvlist, 0x000d, 1); + ip = aim_gettlv_str(tlvlist, 0x0005, 1); + cookie = aim_gettlv_str(tlvlist, 0x0006, 1); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, serviceid, ip, cookie, chathack, chathackex); + /* + * Chat hack. + */ + if ((serviceid == AIM_CONN_TYPE_CHAT) && sess->pendingjoin) { + chathack = sess->pendingjoin; + chathackex = sess->pendingjoinexchange; + sess->pendingjoin = NULL; + sess->pendingjoinexchange = 0; + } - free(ip); - free(cookie); - free(chathack); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, serviceid, ip, cookie, chathack, chathackex); - aim_freetlvchain(&tlvlist); + free(ip); + free(cookie); + free(chathack); - return ret; + aim_freetlvchain(&tlvlist); + + return ret; } /* @@ -551,127 +544,127 @@ /* XXX parse this */ static int rateresp(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - aim_rxcallback_t userfunc; + aim_rxcallback_t userfunc; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - return userfunc(sess, rx); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + return userfunc(sess, rx); - return 0; + return 0; } static int ratechange(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - aim_rxcallback_t userfunc; - int i = 0, code; - unsigned long currentavg, maxavg; - unsigned long rateclass, windowsize, clear, alert, limit, disconnect; + aim_rxcallback_t userfunc; + int i = 0, code; + unsigned long currentavg, maxavg; + unsigned long rateclass, windowsize, clear, alert, limit, disconnect; - code = aimutil_get16(data+i); - i += 2; + code = aimutil_get16(data+i); + i += 2; - rateclass = aimutil_get16(data+i); - i += 2; + rateclass = aimutil_get16(data+i); + i += 2; - windowsize = aimutil_get32(data+i); - i += 4; - clear = aimutil_get32(data+i); - i += 4; - alert = aimutil_get32(data+i); - i += 4; - limit = aimutil_get32(data+i); - i += 4; - disconnect = aimutil_get32(data+i); - i += 4; - currentavg = aimutil_get32(data+i); - i += 4; - maxavg = aimutil_get32(data+i); - i += 4; + windowsize = aimutil_get32(data+i); + i += 4; + clear = aimutil_get32(data+i); + i += 4; + alert = aimutil_get32(data+i); + i += 4; + limit = aimutil_get32(data+i); + i += 4; + disconnect = aimutil_get32(data+i); + i += 4; + currentavg = aimutil_get32(data+i); + i += 4; + maxavg = aimutil_get32(data+i); + i += 4; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - return userfunc(sess, rx, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + return userfunc(sess, rx, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg); - return 0; + return 0; } /* XXX parse this */ static int selfinfo(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - aim_rxcallback_t userfunc; + aim_rxcallback_t userfunc; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - return userfunc(sess, rx); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + return userfunc(sess, rx); - return 0; + return 0; } static int evilnotify(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - aim_rxcallback_t userfunc = NULL; - int i = 0; - unsigned short newevil; - struct aim_userinfo_s userinfo; + aim_rxcallback_t userfunc = NULL; + int i = 0; + unsigned short newevil; + struct aim_userinfo_s userinfo; - newevil = aimutil_get16(data); - i += 2; + newevil = aimutil_get16(data); + i += 2; - memset(&userinfo, 0, sizeof(struct aim_userinfo_s)); + memset(&userinfo, 0, sizeof(struct aim_userinfo_s)); - if (datalen-i) - i += aim_extractuserinfo(sess, data+i, &userinfo); + if (datalen-i) + i += aim_extractuserinfo(sess, data+i, &userinfo); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - return userfunc(sess, rx, newevil, &userinfo); - - return 0; + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + return userfunc(sess, rx, newevil, &userinfo); + + return 0; } static int motd(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - aim_rxcallback_t userfunc; - char *msg = NULL; - int ret = 0; - struct aim_tlvlist_t *tlvlist; - unsigned short id; + aim_rxcallback_t userfunc; + char *msg = NULL; + int ret = 0; + struct aim_tlvlist_t *tlvlist; + unsigned short id; - /* - * Code. - * - * Valid values: - * 1 Mandatory upgrade - * 2 Advisory upgrade - * 3 System bulletin - * 4 Nothing's wrong ("top o the world" -- normal) - * - */ - id = aimutil_get16(data); + /* + * Code. + * + * Valid values: + * 1 Mandatory upgrade + * 2 Advisory upgrade + * 3 System bulletin + * 4 Nothing's wrong ("top o the world" -- normal) + * + */ + id = aimutil_get16(data); - /* - * TLVs follow - */ - if ((tlvlist = aim_readtlvchain(data+2, datalen-2))) - msg = aim_gettlv_str(tlvlist, 0x000b, 1); - - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, id, msg); + /* + * TLVs follow + */ + if ((tlvlist = aim_readtlvchain(data+2, datalen-2))) + msg = aim_gettlv_str(tlvlist, 0x000b, 1); - free(msg); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + ret = userfunc(sess, rx, id, msg); - aim_freetlvchain(&tlvlist); + free(msg); - return ret; + aim_freetlvchain(&tlvlist); + + return ret; } static int hostversions(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - aim_rxcallback_t userfunc; - int vercount; + aim_rxcallback_t userfunc; + int vercount; + + vercount = datalen/4; - vercount = datalen/4; - - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - return userfunc(sess, rx, vercount, data); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + return userfunc(sess, rx, vercount, data); - return 0; + return 0; } /* @@ -713,175 +706,174 @@ */ static int memrequest(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - aim_rxcallback_t userfunc; - unsigned long offset, len; - int i = 0; - struct aim_tlvlist_t *list; - char *modname = NULL; + aim_rxcallback_t userfunc; + unsigned long offset, len; + int i = 0; + struct aim_tlvlist_t *list; + char *modname = NULL; - offset = aimutil_get32(data); - i += 4; + offset = aimutil_get32(data); + i += 4; - len = aimutil_get32(data+4); - i += 4; + len = aimutil_get32(data+4); + i += 4; - list = aim_readtlvchain(data+i, datalen-i); + list = aim_readtlvchain(data+i, datalen-i); - if (aim_gettlv(list, 0x0001, 1)) - modname = aim_gettlv_str(list, 0x0001, 1); + if (aim_gettlv(list, 0x0001, 1)) + modname = aim_gettlv_str(list, 0x0001, 1); - faimdprintf(sess, 1, "data at 0x%08lx (%d bytes) of requested\n", offset, len, modname?modname:"aim.exe"); + faimdprintf(sess, 1, "data at 0x%08lx (%d bytes) of requested\n", offset, len, modname ? modname : "aim.exe"); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - return userfunc(sess, rx, offset, len, modname); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + return userfunc(sess, rx, offset, len, modname); - free(modname); - aim_freetlvchain(&list); + free(modname); + aim_freetlvchain(&list); - return 0; + return 0; } static void dumpbox(struct aim_session_t *sess, unsigned char *buf, int len) { - int i = 0; + int i; - if (!sess || !buf || !len) - return; + if (!sess || !buf || !len) + return; - faimdprintf(sess, 1, "\nDump of %d bytes at %p:", len, buf); + faimdprintf(sess, 1, "\nDump of %d bytes at %p:", len, buf); - for (i = 0; i < len; i++) - { - if ((i % 8) == 0) - faimdprintf(sess, 1, "\n\t"); + for (i = 0; i < len; i++) { + if ((i % 8) == 0) + faimdprintf(sess, 1, "\n\t"); - faimdprintf(sess, 1, "0x%2x ", buf[i]); - } - - faimdprintf(sess, 1, "\n\n"); + faimdprintf(sess, 1, "0x%2x ", buf[i]); + } - return; + faimdprintf(sess, 1, "\n\n"); + + return; } faim_export int aim_sendmemblock(struct aim_session_t *sess, struct aim_conn_t *conn, unsigned long offset, unsigned long len, const unsigned char *buf, unsigned char flag) { - struct command_tx_struct *tx; - int i = 0; + struct command_tx_struct *tx; + int i = 0; - if (!sess || !conn) - return 0; + if (!sess || !conn) + return -EINVAL; - if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+2+16))) - return -1; + if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+2+16))) + return -ENOMEM; - tx->lock = 1; + tx->lock = 1; - i = aim_putsnac(tx->data, 0x0001, 0x0020, 0x0000, sess->snac_nextid++); - i += aimutil_put16(tx->data+i, 0x0010); /* md5 is always 16 bytes */ + i = aim_putsnac(tx->data, 0x0001, 0x0020, 0x0000, sess->snac_nextid++); + i += aimutil_put16(tx->data+i, 0x0010); /* md5 is always 16 bytes */ - if ((flag == AIM_SENDMEMBLOCK_FLAG_ISHASH) && - buf && (len == 0x10)) { /* we're getting a hash */ + if ((flag == AIM_SENDMEMBLOCK_FLAG_ISHASH) && buf && (len == 0x10)) { /* we're getting a hash */ - memcpy(tx->data+i, buf, 0x10); - i += 0x10; + memcpy(tx->data+i, buf, 0x10); + i += 0x10; - } else if (buf && (len > 0)) { /* use input buffer */ - md5_state_t state; + } else if (buf && (len > 0)) { /* use input buffer */ + md5_state_t state; - md5_init(&state); - md5_append(&state, (const md5_byte_t *)buf, len); - md5_finish(&state, (md5_byte_t *)(tx->data+i)); - i += 0x10; + md5_init(&state); + md5_append(&state, (const md5_byte_t *)buf, len); + md5_finish(&state, (md5_byte_t *)(tx->data+i)); + i += 0x10; - } else if (len == 0) { /* no length, just hash NULL (buf is optional) */ - md5_state_t state; - unsigned char nil = '\0'; + } else if (len == 0) { /* no length, just hash NULL (buf is optional) */ + md5_state_t state; + unsigned char nil = '\0'; - /* - * These MD5 routines are stupid in that you have to have - * at least one append. So thats why this doesn't look - * real logical. - */ - md5_init(&state); - md5_append(&state, (const md5_byte_t *)&nil, 0); - md5_finish(&state, (md5_byte_t *)(tx->data+i)); - i += 0x10; + /* + * These MD5 routines are stupid in that you have to have + * at least one append. So thats why this doesn't look + * real logical. + */ + md5_init(&state); + md5_append(&state, (const md5_byte_t *)&nil, 0); + md5_finish(&state, (md5_byte_t *)(tx->data+i)); + i += 0x10; - } else { + } else { - /* - * This data is correct for AIM 3.5.1670. - * - * Using these blocks is as close to "legal" as you can get without - * using an AIM binary. - * - */ - if ((offset == 0x03ffffff) && (len == 0x03ffffff)) { + /* + * This data is correct for AIM 3.5.1670. + * + * Using these blocks is as close to "legal" as you can get + * without using an AIM binary. + * + */ + if ((offset == 0x03ffffff) && (len == 0x03ffffff)) { #if 1 /* with "AnrbnrAqhfzcd" */ - i += aimutil_put32(tx->data+i, 0x44a95d26); - i += aimutil_put32(tx->data+i, 0xd2490423); - i += aimutil_put32(tx->data+i, 0x93b8821f); - i += aimutil_put32(tx->data+i, 0x51c54b01); + i += aimutil_put32(tx->data+i, 0x44a95d26); + i += aimutil_put32(tx->data+i, 0xd2490423); + i += aimutil_put32(tx->data+i, 0x93b8821f); + i += aimutil_put32(tx->data+i, 0x51c54b01); #else /* no filename */ - i += aimutil_put32(tx->data+i, 0x1df8cbae); - i += aimutil_put32(tx->data+i, 0x5523b839); - i += aimutil_put32(tx->data+i, 0xa0e10db3); - i += aimutil_put32(tx->data+i, 0xa46d3b39); + i += aimutil_put32(tx->data+i, 0x1df8cbae); + i += aimutil_put32(tx->data+i, 0x5523b839); + i += aimutil_put32(tx->data+i, 0xa0e10db3); + i += aimutil_put32(tx->data+i, 0xa46d3b39); #endif - } else if ((offset == 0x00001000) && (len == 0x00000000)) { + } else if ((offset == 0x00001000) && (len == 0x00000000)) { - i += aimutil_put32(tx->data+i, 0xd41d8cd9); - i += aimutil_put32(tx->data+i, 0x8f00b204); - i += aimutil_put32(tx->data+i, 0xe9800998); - i += aimutil_put32(tx->data+i, 0xecf8427e); + i += aimutil_put32(tx->data+i, 0xd41d8cd9); + i += aimutil_put32(tx->data+i, 0x8f00b204); + i += aimutil_put32(tx->data+i, 0xe9800998); + i += aimutil_put32(tx->data+i, 0xecf8427e); - } else - faimdprintf(sess, 0, "sendmemblock: WARNING: unknown hash request\n"); + } else + faimdprintf(sess, 0, "sendmemblock: WARNING: unknown hash request\n"); - } + } - tx->commandlen = i; - tx->lock = 0; - aim_tx_enqueue(sess, tx); + tx->commandlen = i; + tx->lock = 0; + aim_tx_enqueue(sess, tx); - return 0; + return 0; } static int snachandler(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) { - if (snac->subtype == 0x0003) - return hostonline(sess, mod, rx, snac, data, datalen); - else if (snac->subtype == 0x0005) - return redirect(sess, mod, rx, snac, data, datalen); - else if (snac->subtype == 0x0007) - return rateresp(sess, mod, rx, snac, data, datalen); - else if (snac->subtype == 0x000a) - return ratechange(sess, mod, rx, snac, data, datalen); - else if (snac->subtype == 0x000f) - return selfinfo(sess, mod, rx, snac, data, datalen); - else if (snac->subtype == 0x0010) - return evilnotify(sess, mod, rx, snac, data, datalen); - else if (snac->subtype == 0x0013) - return motd(sess, mod, rx, snac, data, datalen); - else if (snac->subtype == 0x0018) - return hostversions(sess, mod, rx, snac, data, datalen); - else if (snac->subtype == 0x001f) - return memrequest(sess, mod, rx, snac, data, datalen); + if (snac->subtype == 0x0003) + return hostonline(sess, mod, rx, snac, data, datalen); + else if (snac->subtype == 0x0005) + return redirect(sess, mod, rx, snac, data, datalen); + else if (snac->subtype == 0x0007) + return rateresp(sess, mod, rx, snac, data, datalen); + else if (snac->subtype == 0x000a) + return ratechange(sess, mod, rx, snac, data, datalen); + else if (snac->subtype == 0x000f) + return selfinfo(sess, mod, rx, snac, data, datalen); + else if (snac->subtype == 0x0010) + return evilnotify(sess, mod, rx, snac, data, datalen); + else if (snac->subtype == 0x0013) + return motd(sess, mod, rx, snac, data, datalen); + else if (snac->subtype == 0x0018) + return hostversions(sess, mod, rx, snac, data, datalen); + else if (snac->subtype == 0x001f) + return memrequest(sess, mod, rx, snac, data, datalen); - return 0; + return 0; } faim_internal int general_modfirst(struct aim_session_t *sess, aim_module_t *mod) { - mod->family = 0x0001; - mod->version = 0x0000; - mod->flags = 0; - strncpy(mod->name, "general", sizeof(mod->name)); - mod->snachandler = snachandler; + mod->family = 0x0001; + mod->version = 0x0000; + mod->flags = 0; + strncpy(mod->name, "general", sizeof(mod->name)); + mod->snachandler = snachandler; - return 0; + return 0; } + diff -r dbd74f49dabb -r edf8c5a70e5b src/protocols/oscar/misc.c --- a/src/protocols/oscar/misc.c Sun Aug 26 19:18:39 2001 +0000 +++ b/src/protocols/oscar/misc.c Sun Aug 26 20:21:45 2001 +0000 @@ -669,48 +669,6 @@ return aim_genericreq_n(sess, conn, 0x0002, 0x0002); } -/* -* aim_bos_reqicbmparaminfo() - * - * Request ICBM parameter information. - * - */ -faim_export unsigned long aim_bos_reqicbmparaminfo(struct aim_session_t *sess, - struct aim_conn_t *conn) -{ - return aim_genericreq_n(sess, conn, 0x0004, 0x0004); -} - -/* - * Add ICBM parameter? Huh? - */ -faim_export unsigned long aim_addicbmparam(struct aim_session_t *sess, - struct aim_conn_t *conn) -{ - struct command_tx_struct *newpacket; - int packlen = 10+16, i=0; - - if(!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, packlen))) - return (sess->snac_nextid); - - newpacket->lock = 1; - - i = aim_putsnac(newpacket->data, 0x0004, 0x0002, 0x0000, 0x00000000); - - i += aimutil_put16(newpacket->data+i, 0x0000); - i += aimutil_put16(newpacket->data+i, 0x0000); - i += aimutil_put16(newpacket->data+i, 0x0003); - i += aimutil_put16(newpacket->data+i, 0x1f40); - i += aimutil_put16(newpacket->data+i, 0x03e7); - i += aimutil_put16(newpacket->data+i, 0x03e7); - i += aimutil_put16(newpacket->data+i, 0x0000); - i += aimutil_put16(newpacket->data+i, 0x0000); - - aim_tx_enqueue(sess, newpacket); - - return sess->snac_nextid; -} - /* * Set directory profile data (not the same as aim_bos_setprofile!) */ diff -r dbd74f49dabb -r edf8c5a70e5b src/protocols/oscar/oscar.c --- a/src/protocols/oscar/oscar.c Sun Aug 26 19:18:39 2001 +0000 +++ b/src/protocols/oscar/oscar.c Sun Aug 26 20:21:45 2001 +0000 @@ -106,6 +106,8 @@ int id; struct gaim_connection *gc; /* i hate this. */ struct conversation *cnv; /* bah. */ + int maxlen; + int maxvis; }; struct direct_im { @@ -281,6 +283,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_icbm_param_info (struct aim_session_t *, struct command_rx_struct *, ...); static int gaim_parse_genericerr (struct aim_session_t *, struct command_rx_struct *, ...); static int gaim_memrequest (struct aim_session_t *, struct command_rx_struct *, ...); @@ -692,6 +695,7 @@ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, gaim_parse_user_info, 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); 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); @@ -1915,18 +1919,63 @@ va_end(ap); switch(reason) { + case 0: + /* Invalid (0) */ + g_snprintf(buf, + sizeof(buf), + _("You missed %d message%s from %s because %s invalid."), + nummissed, + nummissed == 1 ? "" : "s", + nummissed == 1 ? "it was" : "they were", + userinfo->sn); + break; case 1: - /* message too large */ - sprintf(buf, _("You missed a message from %s because it was too large."), userinfo->sn); - do_error_dialog(buf, _("Gaim - Error")); - plugin_event(event_error, (void *)961, 0, 0, 0); + /* Message too large */ + g_snprintf(buf, + sizeof(buf), + _("You missed %d message%s from %s because %s too large."), + nummissed, + nummissed == 1 ? "" : "s", + nummissed == 1 ? "it was" : "they were", + userinfo->sn); + break; + case 2: + /* Rate exceeded */ + g_snprintf(buf, + sizeof(buf), + _("You missed %d message%s from %s because the rate limit has been exceeded."), + nummissed, + nummissed == 1 ? "" : "s", + userinfo->sn); + break; + case 3: + /* Evil Sender */ + g_snprintf(buf, + sizeof(buf), + _("You missed %d message%s from %s because they are too evil."), + nummissed, + nummissed == 1 ? "" : "s", + userinfo->sn); + break; + case 4: + /* Evil Receiver */ + g_snprintf(buf, + sizeof(buf), + _("You missed %d message%s from %s because you are too evil."), + nummissed, + nummissed == 1 ? "" : "s", + userinfo->sn); break; default: - sprintf(buf, _("You missed a message from %s for unknown reasons."), userinfo->sn); - do_error_dialog(buf, _("Gaim - Error")); - plugin_event(event_error, (void *)970, 0, 0, 0); + g_snprintf(buf, + sizeof(buf), + _("You missed %d message%s from %s for unknown reasons."), + nummissed, + nummissed == 1 ? "" : "s", + userinfo->sn); break; } + do_error_dialog(buf, _("Gaim - Error")); return 1; } @@ -2194,7 +2243,37 @@ int gaim_chat_info_update(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - debug_printf("inside chat_info_update\n"); + va_list ap; + struct aim_userinfo_s *userinfo; + struct aim_chat_roominfo *roominfo; + char *roomname; + int usercount; + char *roomdesc; + unsigned short unknown_c9, unknown_d2, unknown_d5, maxmsglen, maxvisiblemsglen; + unsigned long creationtime; + struct gaim_connection *gc = sess->aux_data; + struct chat_connection *ccon = find_oscar_chat_by_conn(gc, command->conn); + + va_start(ap, command); + roominfo = va_arg(ap, struct aim_chat_roominfo *); + roomname = va_arg(ap, char *); + usercount= va_arg(ap, int); + userinfo = va_arg(ap, struct aim_userinfo_s *); + roomdesc = va_arg(ap, char *); + unknown_c9 = va_arg(ap, int); + creationtime = va_arg(ap, unsigned long); + maxmsglen = va_arg(ap, int); + unknown_d2 = va_arg(ap, int); + unknown_d5 = va_arg(ap, int); + maxvisiblemsglen = va_arg(ap, int); + va_end(ap); + + debug_printf("inside chat_info_update (maxmsglen = %d, maxvislen = %d)\n", + maxmsglen, maxvisiblemsglen); + + ccon->maxlen = maxmsglen; + ccon->maxvis = maxvisiblemsglen; + return 1; } @@ -2317,8 +2396,7 @@ debug_printf("buddy list loaded\n"); - aim_addicbmparam(sess, command->conn); - aim_bos_reqicbmparaminfo(sess, command->conn); + aim_reqicbmparams(sess, command->conn); aim_bos_reqrights(sess, command->conn); aim_bos_setgroupperm(sess, command->conn, AIM_FLAG_ALLUSERS); @@ -2340,11 +2418,40 @@ return 1; } +int gaim_icbm_param_info(struct aim_session_t *sess, struct command_rx_struct *command, ...) { + struct aim_icbmparameters *params; + va_list ap; + + va_start(ap, command); + params = va_arg(ap, struct aim_icbmparameters *); + va_end(ap); + + debug_printf("ICBM Parameters: maxchannel = %d, default flags = 0x%08lx, max msg len = %d, " + "max sender evil = %f, max receiver evil = %f, min msg interval = %ld\n", + params->maxchan, params->flags, params->maxmsglen, + ((float)params->maxsenderwarn)/10.0, ((float)params->maxrecverwarn)/10.0, + params->minmsginterval); + + params->maxmsglen = 8000; + params->minmsginterval = 0; + + aim_seticbmparam(sess, command->conn, params); + + return 1; +} + int gaim_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - if (command->data) { - debug_printf("minimum report interval: %d (seconds?)\n", aimutil_get16(command->data+10)); - } else - debug_printf("NULL minimum report interval!\n"); + va_list ap; + unsigned short interval = 0; + + va_start(ap, command); + interval = va_arg(ap, int); + va_end(ap); + + debug_printf("minimum report interval: %d (seconds?)\n", interval); + + aim_reqicbmparams(sess, command->conn); + return 1; } @@ -2713,12 +2820,12 @@ serv_got_chat_left(g, b->id); } -static void oscar_chat_send(struct gaim_connection *g, int id, char *message) { +static int oscar_chat_send(struct gaim_connection *g, int id, char *message) { struct oscar_data *odata = (struct oscar_data *)g->proto_data; GSList *bcs = g->buddy_chats; struct conversation *b = NULL; struct chat_connection *c = NULL; - char *buf; + char *buf, *buf2; int i, j; while (bcs) { @@ -2729,7 +2836,7 @@ b = NULL; } if (!b) - return; + return -EINVAL; bcs = odata->oscar_chats; while (bcs) { @@ -2740,7 +2847,7 @@ c = NULL; } if (!c) - return; + return -EINVAL; buf = g_malloc(strlen(message) * 4 + 1); for (i = 0, j = 0; i < strlen(message); i++) { @@ -2754,8 +2861,20 @@ } } buf[j] = '\0'; + + if (strlen(buf) > c->maxlen) + return -E2BIG; + + buf2 = strip_html(buf); + if (strlen(buf2) > c->maxvis) { + g_free(buf2); + return -E2BIG; + } + g_free(buf2); + aim_chat_send_im(odata->sess, c->conn, 0, buf, strlen(buf)); g_free(buf); + return 0; } static char **oscar_list_icon(int uc) { diff -r dbd74f49dabb -r edf8c5a70e5b src/protocols/toc/toc.c --- a/src/protocols/toc/toc.c Sun Aug 26 19:18:39 2001 +0000 +++ b/src/protocols/toc/toc.c Sun Aug 26 20:21:45 2001 +0000 @@ -945,12 +945,15 @@ sflap_send(g, buf2, -1, TYPE_DATA); } -static void toc_chat_send(struct gaim_connection *g, int id, char *message) +static int toc_chat_send(struct gaim_connection *g, int id, char *message) { char buf[BUF_LEN * 2]; escape_text(message); + if (strlen(message) > 2000) + return -E2BIG; g_snprintf(buf, sizeof(buf), "toc_chat_send %d \"%s\"", id, message); sflap_send(g, buf, -1, TYPE_DATA); + return 0; } static void toc_keepalive(struct gaim_connection *gc) diff -r dbd74f49dabb -r edf8c5a70e5b src/protocols/zephyr/zephyr.c --- a/src/protocols/zephyr/zephyr.c Sun Aug 26 19:18:39 2001 +0000 +++ b/src/protocols/zephyr/zephyr.c Sun Aug 26 20:21:45 2001 +0000 @@ -30,6 +30,7 @@ #include #include #include +#include #include "gaim.h" #include "prpl.h" #include "zephyr/zephyr.h" @@ -683,7 +684,7 @@ static void zephyr_add_buddy(struct gaim_connection *gc, char *buddy) { } static void zephyr_remove_buddy(struct gaim_connection *gc, char *buddy) { } -static void zephyr_chat_send(struct gaim_connection *gc, int id, char *im) +static int zephyr_chat_send(struct gaim_connection *gc, int id, char *im) { ZNotice_t notice; zephyr_triple *zt; @@ -693,7 +694,7 @@ zt = find_sub_by_id(id); if (!zt) /* this should never happen. */ - return; + return -EINVAL; sig = ZGetVariable("zwrite-signature"); if (!sig) { @@ -720,6 +721,7 @@ notice.z_message = buf; ZSendNotice(¬ice, ZAUTH); g_free(buf); + return 0; } static int zephyr_send_im(struct gaim_connection *gc, char *who, char *im, int away) { diff -r dbd74f49dabb -r edf8c5a70e5b src/prpl.h --- a/src/prpl.h Sun Aug 26 19:18:39 2001 +0000 +++ b/src/prpl.h Sun Aug 26 20:21:45 2001 +0000 @@ -135,7 +135,7 @@ void (* chat_invite) (struct gaim_connection *, int id, char *who, char *message); void (* chat_leave) (struct gaim_connection *, int id); void (* chat_whisper) (struct gaim_connection *, int id, char *who, char *message); - void (* chat_send) (struct gaim_connection *, int id, char *message); + int (* chat_send) (struct gaim_connection *, int id, char *message); void (* keepalive) (struct gaim_connection *); void (* chat_set_topic) (struct gaim_connection *, int id, char *topic); diff -r dbd74f49dabb -r edf8c5a70e5b src/server.c --- a/src/server.c Sun Aug 26 19:18:39 2001 +0000 +++ b/src/server.c Sun Aug 26 20:21:45 2001 +0000 @@ -327,11 +327,13 @@ (*g->prpl->chat_set_topic)(g, id, topic); } -void serv_chat_send(struct gaim_connection *g, int id, char *message) +int serv_chat_send(struct gaim_connection *g, int id, char *message) { + int val = -EINVAL; if (g->prpl && g->prpl->chat_send) - (*g->prpl->chat_send)(g, id, message); + val = (*g->prpl->chat_send)(g, id, message); serv_touch_idle(g); + return val; } int find_queue_row_by_name(char *name)