From: mid Date: Tue, 6 Jun 2000 02:52:55 +0000 (+0000) Subject: - Tue Jun 6 01:36:48 UTC 2000 X-Git-Tag: rel_0_99_2~151 X-Git-Url: http://andersk.mit.edu/gitweb/libfaim.git/commitdiff_plain/040457cc47af3fd2ed743bda700e28a603d39eb6 - Tue Jun 6 01:36:48 UTC 2000 - Inverted gethostbyname2() check. Not sure how that ended up in that state. - Added some of the initial framework to support file transfers - Added in a few checks for that - Can currently parse and send a denial message. - Added cookie caching. (Sorry, I just like saying that.) - Rearranged channel 2 ICBM parsing (detects the different rendezvous types better and hopefully accuratly). - Killed the connection array. Now a list. (Suits the upcoming features better.) --- REQUIRES CLIENT CHANGES... - In most cases, you need to change aim_conn_close() calls to aim_conn_kill(). This will free them as well as close them. If you don't do this, you'll pollute the connection list and leak memory. - Possibly a few other minor things (some cleanups to faimtest for one) --- diff --git a/CHANGES b/CHANGES index 8007e7d..268afdb 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,23 @@ No release numbers ------------------ + - Tue Jun 6 01:36:48 UTC 2000 + - Inverted gethostbyname2() check. Not sure how that ended up + in that state. + - Added some of the initial framework to support file transfers + - Added in a few checks for that + - Can currently parse and send a denial message. + - Added cookie caching. (Sorry, I just like saying that.) + - Rearranged channel 2 ICBM parsing (detects the different + rendezvous types better and hopefully accuratly). + - Killed the connection array. Now a list. (Suits the + upcoming features better.) --- REQUIRES CLIENT CHANGES... + - In most cases, you need to change aim_conn_close() calls + to aim_conn_kill(). This will free them as well as + close them. If you don't do this, you'll pollute the + connection list and leak memory. + - Possibly a few other minor things (some cleanups to faimtest for one) + - Fri Jun 2 23:27:28 UTC 2000 - Cleaned up aim_send_login slightly - Added aimicq_encode_password to support the new hash diff --git a/Makefile b/Makefile index 150a156..937f844 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,8 @@ LIBFAIM_OBJECTS = \ aim_chat.o \ aim_chatnav.o \ aim_util.o \ - aim_meta.o + aim_meta.o \ + aim_msgcookie.o all: libfaim allutils diff --git a/aim_chat.c b/aim_chat.c index 85cf215..0543ade 100644 --- a/aim_chat.c +++ b/aim_chat.c @@ -19,20 +19,18 @@ char *aim_chat_getname(struct aim_conn_t *conn) struct aim_conn_t *aim_chat_getconn(struct aim_session_t *sess, char *name) { - int i; + struct aim_conn_t *cur; + + faim_mutex_lock(&sess->connlistlock); + for (cur = sess->connlist; cur; cur = cur->next) { + if (cur->type != AIM_CONN_TYPE_CHAT) + continue; + if (strcmp((char *)cur->priv, name) == 0) + break; + } + faim_mutex_unlock(&sess->connlistlock); - for (i=0;iconns[i].type == AIM_CONN_TYPE_CHAT) - { - if (sess->conns[i].priv) - if (!strcmp((char *)sess->conns[i].priv, name)) - { - return &sess->conns[i]; - } - } - } - return NULL; + return cur; } int aim_chat_attachname(struct aim_conn_t *conn, char *roomname) @@ -542,21 +540,14 @@ u_long aim_chat_clientready(struct aim_session_t *sess, int aim_chat_leaveroom(struct aim_session_t *sess, char *name) { - int i; + struct aim_conn_t *conn; - for (i=0;iconns[i].type == AIM_CONN_TYPE_CHAT) - { - if (sess->conns[i].priv) - if (!strcmp((char *)sess->conns[i].priv, name)) - { - aim_conn_close(&sess->conns[i]); - return 0; - } - } - } - return -1; + if ((conn = aim_chat_getconn(sess, name))) + aim_conn_kill(sess, &conn); + + if (!conn) + return -1; + return 0; } /* diff --git a/aim_conn.c b/aim_conn.c index ff81277..061409f 100644 --- a/aim_conn.c +++ b/aim_conn.c @@ -8,21 +8,83 @@ #include +/* + * Clears out connection list, killing remaining connections. + */ void aim_connrst(struct aim_session_t *sess) { - int i; - for (i = 0; i < AIM_CONN_MAX; i++) { - aim_conn_close(&sess->conns[i]); + faim_mutex_init(&sess->connlistlock, NULL); + if (sess->connlist) { + struct aim_conn_t *cur = sess->connlist, *tmp; + + while(cur) { + tmp = cur->next; + aim_conn_close(cur); + free(cur); + cur = tmp; + } } + sess->connlist = NULL; + return; } +/* + * Gets a new connection structure. + */ struct aim_conn_t *aim_conn_getnext(struct aim_session_t *sess) { - int i; - for (i=0;iconns[i].fd == -1) - return &(sess->conns[i]); - return NULL; + struct aim_conn_t *newconn, *cur; + + if (!(newconn = malloc(sizeof(struct aim_conn_t)))) + return NULL; + + memset(newconn, 0, sizeof(struct aim_conn_t)); + aim_conn_close(newconn); + newconn->next = NULL; + + faim_mutex_lock(&sess->connlistlock); + if (sess->connlist == NULL) + sess->connlist = newconn; + else { + for (cur = sess->connlist; cur->next; cur = cur->next) + ; + cur->next = newconn; + } + faim_mutex_unlock(&sess->connlistlock); + + return newconn; +} + +void aim_conn_kill(struct aim_session_t *sess, struct aim_conn_t **deadconn) +{ + struct aim_conn_t *cur; + + if (!deadconn || !*deadconn) + return; + + faim_mutex_lock(&sess->connlistlock); + if (sess->connlist == NULL) + ; + else if (sess->connlist->next == NULL) { + if (sess->connlist == *deadconn) + sess->connlist = NULL; + } else { + cur = sess->connlist; + while (cur->next) { + if (cur->next == *deadconn) { + cur->next = cur->next->next; + break; + } + cur = cur->next; + } + } + faim_mutex_unlock(&sess->connlistlock); + + aim_conn_close(*deadconn); + free(*deadconn); + deadconn = NULL; + + return; } void aim_conn_close(struct aim_conn_t *deadconn) @@ -47,11 +109,15 @@ void aim_conn_close(struct aim_conn_t *deadconn) struct aim_conn_t *aim_getconn_type(struct aim_session_t *sess, int type) { - int i; - for (i=0; iconns[i].type == type) - return &(sess->conns[i]); - return NULL; + struct aim_conn_t *cur; + + faim_mutex_lock(&sess->connlistlock); + for (cur = sess->connlist; cur; cur = cur->next) { + if (cur->type == type) + break; + } + faim_mutex_unlock(&sess->connlistlock); + return cur; } /* @@ -73,15 +139,18 @@ struct aim_conn_t *aim_newconn(struct aim_session_t *sess, u_short port = FAIM_LOGIN_PORT; char *host = NULL; int i=0; - + if ((connstruct=aim_conn_getnext(sess))==NULL) return NULL; + faim_mutex_lock(&connstruct->active); + connstruct->type = type; if (!dest) { /* just allocate a struct */ connstruct->fd = -1; connstruct->status = 0; + faim_mutex_unlock(&connstruct->active); return connstruct; } @@ -104,11 +173,12 @@ struct aim_conn_t *aim_newconn(struct aim_session_t *sess, strncpy(host, dest, i); host[i] = '\0'; - hp = gethostbyname2(host, AF_INET); + hp = gethostbyname(host); free(host); if (hp == NULL) { connstruct->status = (h_errno | AIM_CONN_STATUS_RESOLVERR); + faim_mutex_unlock(&connstruct->active); return connstruct; } @@ -122,29 +192,40 @@ struct aim_conn_t *aim_newconn(struct aim_session_t *sess, if(ret < 0) { connstruct->fd = -1; connstruct->status = (errno | AIM_CONN_STATUS_CONNERR); + faim_mutex_unlock(&connstruct->active); return connstruct; } + faim_mutex_unlock(&connstruct->active); + return connstruct; } int aim_conngetmaxfd(struct aim_session_t *sess) { - int i,j; + int j = 0; + struct aim_conn_t *cur; + + faim_mutex_lock(&sess->connlistlock); + for (cur = sess->connlist; cur; cur = cur->next) { + if (cur->fd > j) + j = cur->fd; + } + faim_mutex_unlock(&sess->connlistlock); - for (i=0,j=0;iconns[i].fd > j) - j = sess->conns[i].fd; return j; } int aim_countconn(struct aim_session_t *sess) { - int i,cnt; + int cnt = 0; + struct aim_conn_t *cur; + + faim_mutex_lock(&sess->connlistlock); + for (cur = sess->connlist; cur; cur = cur->next) + cnt++; + faim_mutex_unlock(&sess->connlistlock); - for (i=0,cnt=0;iconns[i].fd > -1) - cnt++; return cnt; } @@ -160,15 +241,23 @@ int aim_countconn(struct aim_session_t *sess) * 1 outgoing data pending (NULL returned) * 2 incoming data pending (connection with pending data returned) * + * XXX: we could probably stand to do a little courser locking here. + * */ struct aim_conn_t *aim_select(struct aim_session_t *sess, struct timeval *timeout, int *status) { + struct aim_conn_t *cur; fd_set fds; + int maxfd = 0; int i; - if (aim_countconn(sess) <= 0) + faim_mutex_lock(&sess->connlistlock); + if (sess->connlist == NULL) { + faim_mutex_unlock(&sess->connlistlock); return 0; + } + faim_mutex_unlock(&sess->connlistlock); /* * If we have data waiting to be sent, return immediatly @@ -179,24 +268,28 @@ struct aim_conn_t *aim_select(struct aim_session_t *sess, } FD_ZERO(&fds); - - for(i=0;iconns[i].fd>-1) - FD_SET(sess->conns[i].fd, &fds); - - if ((i = select(aim_conngetmaxfd(sess)+1, &fds, NULL, NULL, timeout))>=1) { - int j; - for (j=0;jconns[j].fd > -1) { - if ((FD_ISSET(sess->conns[j].fd, &fds))) { - *status = 2; - return &(sess->conns[j]); /* return the first waiting struct */ - } - } - } - /* should never get here */ + maxfd = 0; + + faim_mutex_lock(&sess->connlistlock); + for (cur = sess->connlist; cur; cur = cur->next) { + FD_SET(cur->fd, &fds); + if (cur->fd > maxfd) + maxfd = cur->fd; + } + faim_mutex_unlock(&sess->connlistlock); + + if ((i = select(maxfd+1, &fds, NULL, NULL, timeout))>=1) { + faim_mutex_lock(&sess->connlistlock); + for (cur = sess->connlist; cur; cur = cur->next) { + if (FD_ISSET(cur->fd, &fds)) { + *status = 2; + faim_mutex_unlock(&sess->connlistlock); + return cur; + } + } } + faim_mutex_unlock(&sess->connlistlock); *status = i; /* may be 0 or -1 */ return NULL; /* no waiting or error, return */ } @@ -205,25 +298,31 @@ int aim_conn_isready(struct aim_conn_t *conn) { if (conn) return (conn->status & 0x0001); - else - return -1; + return -1; } int aim_conn_setstatus(struct aim_conn_t *conn, int status) { - if (conn) - return (conn->status ^= status); - else + int val; + + if (!conn) return -1; + + faim_mutex_lock(&conn->active); + val = conn->status ^= status; + faim_mutex_unlock(&conn->active); + return val; } int aim_conn_setlatency(struct aim_conn_t *conn, int newval) { if (!conn) return -1; - + + faim_mutex_lock(&conn->active); conn->forcedlatency = newval; conn->lastactivity = 0; /* reset this just to make sure */ + faim_mutex_unlock(&conn->active); return 0; } @@ -233,15 +332,8 @@ void aim_session_init(struct aim_session_t *sess) if (!sess) return; - memset(sess->logininfo.screen_name, 0x00, MAXSNLEN); - sess->logininfo.BOSIP = NULL; - memset(sess->logininfo.cookie, 0x00, AIM_COOKIELEN); - sess->logininfo.email = NULL; - sess->logininfo.regstatus = 0x00; - - memset(sess->conns, 0, sizeof(struct aim_conn_t)*AIM_CONN_MAX); + memset(sess, 0, sizeof(struct aim_session_t)); aim_connrst(sess); - sess->queue_outgoing = NULL; sess->queue_incoming = NULL; sess->pendingjoin = NULL; diff --git a/aim_im.c b/aim_im.c index d39a3ae..3be7e40 100644 --- a/aim_im.c +++ b/aim_im.c @@ -350,10 +350,11 @@ int aim_parse_incoming_im_middle(struct aim_session_t *sess, } else if (channel == 0x0002) { - int rendtype; struct aim_tlv_t *block1; struct aim_tlvlist_t *list2; struct aim_tlv_t *tmptlv; + struct aim_tlv_t *miscinfo; + unsigned short reqclass = 0; int a; /* Class. */ @@ -376,8 +377,11 @@ int aim_parse_incoming_im_middle(struct aim_session_t *sess, * There's another block of TLVs embedded in the type 5 here. */ block1 = aim_gettlv(tlvlist, 0x0005, 1); - if (!block1) + if (!block1) { + printf("faim: no tlv 0x0005 in rendezvous transaction!\n"); + aim_freetlvchain(&tlvlist); return 1; /* major problem */ + } a = 0x1a; /* skip -- not sure what this information is! */ @@ -387,77 +391,187 @@ int aim_parse_incoming_im_middle(struct aim_session_t *sess, * Its probably just an accepted invitation or something. * */ - if (block1->length <= 0x1a) - { + if (block1->length <= 0x1a) { + aim_freetlvchain(&tlvlist); + return 1; + } + + list2 = aim_readtlvchain(block1->value+a, block1->length-a); + + if (!(miscinfo = aim_gettlv(list2, 0x2711, 1))) { + struct aim_msgcookie_t *cook; + + if ((cook = aim_uncachecookie(sess, cookie)) == NULL) { + printf("faim: no 0x2711 info TLV in rendezvous and its not in cache!\n"); + aim_freetlvchain(&list2); aim_freetlvchain(&tlvlist); return 1; } - list2 = aim_readtlvchain(block1->value+a, block1->length-a); + if (cook->type == 1) { + struct aim_filetransfer_t *ft; - if (aim_gettlv(list2, 0x0004, 1) /* start connection */ || - aim_gettlv(list2, 0x000b, 1) /* close conncetion */) - { - rendtype = 1; /* voice request */ - - /* - * Call client. - */ - userfunc = aim_callhandler(command->conn, 0x0004, 0x0007); - if (userfunc) - i = userfunc(sess, - command, - channel, - rendtype, - &userinfo); - else - i = 0; - } - else - { - struct aim_chat_roominfo roominfo; - char *msg=NULL,*encoding=NULL,*lang=NULL; - - rendtype = 0; /* chat invite */ - if (aim_gettlv(list2, 0x2711, 1)) - { - struct aim_tlv_t *nametlv; - - nametlv = aim_gettlv(list2, 0x2711, 1); - aim_chat_readroominfo(nametlv->value, &roominfo); + if (cook->data) { + struct aim_tlv_t *errortlv; + int errorcode = -1; + + ft = (struct aim_filetransfer_t *)cook->data; + + if ((errortlv = aim_gettlv(list2, 0x000b, 1))) { + errorcode = aimutil_get16(errortlv->value); } + printf("faim: transfer from %s (%s) for %s cancelled (error code %d)\n", ft->sender, ft->ip, ft->filename, errorcode); + free(cook->data); + } else { + printf("faim: not data attached to file transfer\n"); + } + + } else { + printf("faim: unknown cookie cache type %d\n", cook->type); + } + + free(cook); + return 1; + } + + + /* + * Parse the first two bytes of the 0x2711 TLV. + * + * This can be interpretted in a couple ways. + * + * It could be said that its a service type or some such and + * that voice is 0, file transfer is 1, and chat is 4 (and 5). + * + * Or it could be said that its an exchange value. Exchanges + * four and five are for chat, voice is on exchange zero and + * file transfer is done on exchange 1. + * + * It should work out the same no how its thought of. + * + */ + reqclass = aimutil_get16(miscinfo->value+0); + + switch (reqclass) { + case AIM_RENDEZVOUS_VOICE: { + + /* XXX: implement all this */ + + /* + * Call client. + */ + userfunc = aim_callhandler(command->conn, 0x0004, 0x0007); + if (userfunc || (i = 0)) { + i = userfunc(sess, + command, + channel, + reqclass, + &userinfo); + } + break; + } + case AIM_RENDEZVOUS_FILETRANSFER: { + char ip[30]; + char *desc = NULL; + struct aim_msgcookie_t cachedcook; + struct aim_filetransfer_t *ft; + + memset(ip, 0, sizeof(ip)); + + if (aim_gettlv(list2, 0x0003, 1) && aim_gettlv(list2, 0x0003, 1)) { + struct aim_tlv_t *iptlv, *porttlv; - if (aim_gettlv(list2, 0x000c, 1)) - msg = aim_gettlv_str(list2, 0x000c, 1); + iptlv = aim_gettlv(list2, 0x0003, 1); + porttlv = aim_gettlv(list2, 0x0005, 1); + + snprintf(ip, sizeof(ip)-1, "%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); + } + + printf("faim: rend: file transfer request from %s for %s: %s (%s)\n", + userinfo.sn, + miscinfo->value+8, + desc, + ip); + + memcpy(cachedcook.cookie, cookie, 8); + memcpy(cachedcook.extended, block1->value+10, 16); + + ft = malloc(sizeof(struct aim_filetransfer_t)); + strncpy(ft->sender, userinfo.sn, sizeof(ft->sender)); + strncpy(ft->ip, ip, sizeof(ft->ip)); + ft->filename = strdup(miscinfo->value+8); + cachedcook.type = 1; + cachedcook.data = ft; + + if (aim_cachecookie(sess, &cachedcook) != 0) + printf("faim: ERROR caching message cookie\n"); + + + aim_denytransfer(sess, command->conn, ft->sender, cookie, 0); + + free(desc); + + i = 1; + break; + } + case AIM_RENDEZVOUS_FILETRANSFER_GET: { + printf("faim: file get request (unsupported)\n"); + i = 1; + break; + } + case AIM_RENDEZVOUS_CHAT_EX3: + case AIM_RENDEZVOUS_CHAT_EX4: + case AIM_RENDEZVOUS_CHAT_EX5: { + struct aim_chat_roominfo roominfo; + char *msg=NULL,*encoding=NULL,*lang=NULL; + + aim_chat_readroominfo(miscinfo->value, &roominfo); + + if (aim_gettlv(list2, 0x000c, 1)) + msg = aim_gettlv_str(list2, 0x000c, 1); - if (aim_gettlv(list2, 0x000d, 1)) - encoding = aim_gettlv_str(list2, 0x000d, 1); + if (aim_gettlv(list2, 0x000d, 1)) + encoding = aim_gettlv_str(list2, 0x000d, 1); - if (aim_gettlv(list2, 0x000e, 1)) - lang = aim_gettlv_str(list2, 0x000e, 1); - - /* - * Call client. - */ - userfunc = aim_callhandler(command->conn, 0x0004, 0x0007); - if (userfunc) - i = userfunc(sess, - command, - channel, - rendtype, - &userinfo, - &roominfo, - msg, - encoding?encoding+1:NULL, - lang?lang+1:NULL); - else - i = 0; + if (aim_gettlv(list2, 0x000e, 1)) + lang = aim_gettlv_str(list2, 0x000e, 1); + /* + * Call client. + */ + userfunc = aim_callhandler(command->conn, 0x0004, 0x0007); + if (userfunc || (i = 0)) + i = userfunc(sess, + command, + channel, + reqclass, /* == roominfo->exchange */ + &userinfo, + &roominfo, + msg, + encoding?encoding+1:NULL, + lang?lang+1:NULL); free(roominfo.name); free(msg); free(encoding); free(lang); - } + break; + } + default: { + printf("faim: rendezvous: unknown rend class 0x%04x\n", reqclass); + i = 1; + break; + } + } /* switch */ + aim_freetlvchain(&list2); } @@ -470,6 +584,41 @@ int aim_parse_incoming_im_middle(struct aim_session_t *sess, return i; } +/* + * Possible codes: + * AIM_TRANSFER_DENY_NOTSUPPORTED -- "client does not support" + * AIM_TRANSFER_DENY_DECLINE -- "client has declined transfer" + * AIM_TRANSFER_DENY_NOTACCEPTING -- "client is not accepting transfers" + * + */ +u_long aim_denytransfer(struct aim_session_t *sess, + struct aim_conn_t *conn, + char *sender, + char *cookie, + unsigned short code) +{ + struct command_tx_struct *newpacket; + int curbyte, i; + + if(!(newpacket = aim_tx_new(0x0002, conn, 10+8+2+1+strlen(sender)+6))) + return -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); + + newpacket->lock = 0; + aim_tx_enqueue(sess, newpacket); + + return (sess->snac_nextid++); +} + /* * Not real sure what this does, nor does anyone I've talk to. * diff --git a/aim_logoff.c b/aim_logoff.c index b16eef1..f5d0375 100644 --- a/aim_logoff.c +++ b/aim_logoff.c @@ -14,13 +14,6 @@ */ int aim_logoff(struct aim_session_t *sess) { - int i = AIM_CONN_MAX-1; - while (i > -1) - { - if (sess->conns[i].fd>-1) - aim_conn_close(&(sess->conns[i])); - i--; - } aim_connrst(sess); /* in case we want to connect again */ return 0; diff --git a/aim_msgcookie.c b/aim_msgcookie.c new file mode 100644 index 0000000..3481162 --- /dev/null +++ b/aim_msgcookie.c @@ -0,0 +1,99 @@ + +/* + * + * + */ + +#include + +int aim_cachecookie(struct aim_session_t *sess, + struct aim_msgcookie_t *cookie) +{ + struct aim_msgcookie_t *newcook = NULL, *cur = NULL; + + if (!cookie) + return -1; + + if (!(newcook = malloc(sizeof(struct aim_msgcookie_t)))) + return -1; + memcpy(newcook, cookie, sizeof(struct aim_msgcookie_t)); + newcook->addtime = time(NULL); + newcook->next = NULL; + + cur = sess->msgcookies; + + if (cur == NULL) { + sess->msgcookies = newcook; + return 0; + } + while (cur->next != NULL) + cur = cur->next; + cur->next = newcook; + + return 0; +} + +struct aim_msgcookie_t *aim_uncachecookie(struct aim_session_t *sess, + char *cookie) +{ + struct aim_msgcookie_t *cur; + + if (!cookie) + return NULL; + + if (!sess->msgcookies) + return NULL; + + if (memcmp(sess->msgcookies->cookie, cookie, 8) == 0) { + cur = sess->msgcookies; + sess->msgcookies = cur->next; + return cur; + } + + cur = sess->msgcookies; + while (cur->next) { + if (memcmp(cur->next->cookie, cookie, 8) == 0) { + struct aim_msgcookie_t *tmp; + + tmp = cur->next; + cur->next = cur->next->next; + return tmp; + } + cur = cur->next; + } + return NULL; +} + +/* + */ +int aim_purgecookies(struct aim_session_t *sess) +{ + int maxage = 5*60; + struct aim_msgcookie_t *cur; + struct aim_msgcookie_t *remed = NULL; + time_t curtime; + + cur = sess->msgcookies; + + curtime = time(&curtime); + + while (cur) { + if ( (cur) && (((cur->addtime) + maxage) < curtime)) { +#if DEBUG > 1 + printf("aimmsgcookie: WARNING purged obsolete message cookie %x%x%x%x %x%x%x%x\n", + cur->cookie[0], cur->cookie[1], cur->cookie[2], cur->cookie[3], + cur->cookie[4], cur->cookie[5], cur->cookie[6], cur->cookie[7]); +#endif + remed = aim_uncachecookie(sess, cur->cookie); + if (remed) { + if (remed->data) + free(remed->data); + free(remed); + } + } + cur = cur->next; + } + + return 0; +} + diff --git a/aim_rxqueue.c b/aim_rxqueue.c index d82d6f4..481e49b 100644 --- a/aim_rxqueue.c +++ b/aim_rxqueue.c @@ -23,6 +23,13 @@ int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn) if (conn->fd < 3) /* can happen when people abuse the interface */ return 0; + /* + * Rendezvous (client-client) connections do not speak + * FLAP, so this function will break on them. + */ + if (conn->type > 0x01000) + return 0; + /* * Read FLAP header. Six bytes: * diff --git a/faim/aim.h b/faim/aim.h index 24cb4ce..d0d2da4 100644 --- a/faim/aim.h +++ b/faim/aim.h @@ -52,9 +52,9 @@ #define strlen(x) (int)strlen(x) /* win32 has a unsigned size_t */ #endif -#if defined(_WIN32) || (defined(mach) && defined(__APPLE__)) -#define gethostbyname2(x,y) gethostbyname(x) /* revert to IPv4 */ -#endif +#if defined(mach) && defined(__APPLE__) +#define gethostbyname(x) gethostbyname2(x, AF_INET) +#endif /* * Current Maximum Length for Screen Names (not including NULL) @@ -144,6 +144,7 @@ struct client_info_s { #define AIM_CONN_TYPE_BOS 0x0002 #define AIM_CONN_TYPE_CHAT 0x000e #define AIM_CONN_TYPE_CHATNAV 0x000d +#define AIM_CONN_TYPE_RENDEZVOUS 0x0101 /* these do not speak OSCAR! */ /* * Status values returned from aim_conn_new(). ORed together. @@ -164,6 +165,7 @@ struct aim_conn_t { struct aim_rxcblist_t *handlerlist; faim_mutex_t active; /* lock around read/writes */ faim_mutex_t seqnum_lock; /* lock around ->seqnum changes */ + struct aim_conn_t *next; }; /* struct for incoming commands */ @@ -218,7 +220,8 @@ struct aim_session_t { /* * Connection information */ - struct aim_conn_t conns[AIM_CONN_MAX]; + struct aim_conn_t *connlist; + faim_mutex_t connlistlock; /* * TX/RX queues @@ -245,6 +248,8 @@ struct aim_session_t { **/ struct aim_snac_t *outstanding_snacs; u_long snac_nextid; + + struct aim_msgcookie_t *msgcookies; }; @@ -316,6 +321,7 @@ int aim_rxdispatch(struct aim_session_t *); int aim_logoff(struct aim_session_t *); +void aim_conn_kill(struct aim_session_t *sess, struct aim_conn_t **deadconn); typedef int (*rxcallback_t)(struct aim_session_t *, struct command_rx_struct *, ...); int aim_register_callbacks(rxcallback_t *); @@ -457,6 +463,36 @@ extern u_char aim_caps[6][16]; #define AIM_GETINFO_GENERALINFO 0x00001 #define AIM_GETINFO_AWAYMESSAGE 0x00003 +#define AIM_RENDEZVOUS_VOICE 0x0000 +#define AIM_RENDEZVOUS_FILETRANSFER 0x0001 +#define AIM_RENDEZVOUS_CHAT_EX3 0x0003 +#define AIM_RENDEZVOUS_CHAT_EX4 0x0004 +#define AIM_RENDEZVOUS_CHAT_EX5 0x0005 +#define AIM_RENDEZVOUS_FILETRANSFER_GET 0x0012 + +struct aim_msgcookie_t { + unsigned char cookie[8]; + unsigned char extended[16]; + int type; + void *data; + time_t addtime; + struct aim_msgcookie_t *next; +}; + +struct aim_filetransfer_t { + char sender[MAXSNLEN]; + char ip[30]; + char *filename; +}; +int aim_cachecookie(struct aim_session_t *sess, struct aim_msgcookie_t *cookie); +struct aim_msgcookie_t *aim_uncachecookie(struct aim_session_t *sess, char *cookie); +int aim_purgecookies(struct aim_session_t *sess); + +#define AIM_TRANSFER_DENY_NOTSUPPORTED 0x0000 +#define AIM_TRANSFER_DENY_DECLINE 0x0001 +#define AIM_TRANSFER_DENY_NOTACCEPTING 0x0002 +u_long aim_denytransfer(struct aim_session_t *sess, struct aim_conn_t *conn, char *sender, char *cookie, unsigned short code); + u_long aim_getinfo(struct aim_session_t *, struct aim_conn_t *, const char *, unsigned short); int aim_extractuserinfo(u_char *, struct aim_userinfo_s *); int aim_parse_userinfo_middle(struct aim_session_t *, struct command_rx_struct *); diff --git a/mkbuildinfo.sh b/mkbuildinfo.sh index ed36c5a..2c4fc97 100755 --- a/mkbuildinfo.sh +++ b/mkbuildinfo.sh @@ -2,9 +2,9 @@ rm -rf aim_meta.o aim_buildcode.h echo -n "#define AIM_BUILDDATE \"" > aim_buildcode.h -echo -n `date +%Y%m%e` >> aim_buildcode.h +echo -n `date +%Y%m%d` >> aim_buildcode.h echo "\"" >> aim_buildcode.h echo -n "#define AIM_BUILDTIME \"" >> aim_buildcode.h echo -n `date +%H%M%S` >> aim_buildcode.h -echo "\"" >> aim_buildcode.h \ No newline at end of file +echo "\"" >> aim_buildcode.h diff --git a/utils/faimtest/faimtest.c b/utils/faimtest/faimtest.c index 2ac66ec..1bf7414 100644 --- a/utils/faimtest/faimtest.c +++ b/utils/faimtest/faimtest.c @@ -101,35 +101,30 @@ int main(void) enter: authconn = aim_newconn(&aimsess, AIM_CONN_TYPE_AUTH, server?server:FAIM_LOGIN_SERVER); - if (authconn == NULL) - { - fprintf(stderr, "faimtest: internal connection error while in aim_login. bailing out.\n"); - return -1; - } - else if (authconn->fd == -1) - { - if (authconn->status & AIM_CONN_STATUS_RESOLVERR) - fprintf(stderr, "faimtest: could not resolve authorizer name\n"); - else if (authconn->status & AIM_CONN_STATUS_CONNERR) - fprintf(stderr, "faimtest: could not connect to authorizer\n"); - return -1; - } - else - { + if (authconn == NULL) { + fprintf(stderr, "faimtest: internal connection error while in aim_login. bailing out.\n"); + return -1; + } else if (authconn->fd == -1) { + if (authconn->status & AIM_CONN_STATUS_RESOLVERR) + fprintf(stderr, "faimtest: could not resolve authorizer name\n"); + else if (authconn->status & AIM_CONN_STATUS_CONNERR) + fprintf(stderr, "faimtest: could not connect to authorizer\n"); + aim_conn_kill(&aimsess, &authconn); + return -1; + } else { #ifdef SNACLOGIN - /* new login code -- not default -- pending new password encryption algo */ - aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0007, faimtest_parse_login, 0); - aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0003, faimtest_parse_authresp, 0); - - aim_sendconnack(&aimsess, authconn); - aim_request_login(&aimsess, authconn, FAIMTEST_SCREENNAME); + /* new login code -- not default -- pending new password encryption algo */ + aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0007, faimtest_parse_login, 0); + aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0003, faimtest_parse_authresp, 0); + + aim_sendconnack(&aimsess, authconn); + aim_request_login(&aimsess, authconn, FAIMTEST_SCREENNAME); #else - aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_AUTHSUCCESS, faimtest_parse_authresp, 0); - aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_authsvrready, 0); - aim_send_login(&aimsess, authconn, screenname, password, &info); - + aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_AUTHSUCCESS, faimtest_parse_authresp, 0); + aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_authsvrready, 0); + aim_send_login(&aimsess, authconn, screenname, password, &info); #endif - } + } while (keepgoing) { waitingconn = aim_select(&aimsess, NULL, &selstat); @@ -297,11 +292,11 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct { struct aim_conn_t *tstconn = NULL; tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, ip); - if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR)) - { - fprintf(stderr, "faimtest: unable to connect to chatnav server\n"); - return 1; - } + if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR)) { + fprintf(stderr, "faimtest: unable to connect to chatnav server\n"); + if (tstconn) aim_conn_kill(sess, &tstconn); + return 1; + } #if 0 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_CTN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0); aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0); @@ -322,6 +317,7 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR)) { fprintf(stderr, "faimtest: unable to connect to chat server\n"); + if (tstconn) aim_conn_kill(sess, &tstconn); return 1; } printf("faimtest: chat: connected\n"); @@ -359,7 +355,7 @@ int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct { printf("Login Error Code 0x%04x\n", sess->logininfo.errorcode); printf("Error URL: %s\n", sess->logininfo.errorurl); - aim_conn_close(command->conn); + aim_conn_kill(sess, &command->conn); exit(0); /* XXX: should return in order to let the above things get free()'d. */ } @@ -368,40 +364,36 @@ int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct printf("BOS IP: %s\n", sess->logininfo.BOSIP); printf("Closing auth connection...\n"); - aim_conn_close(command->conn); + aim_conn_kill(sess, &command->conn); bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, sess->logininfo.BOSIP); - if (bosconn == NULL) - { - fprintf(stderr, "faimtest: could not connect to BOS: internal error\n"); - } - else if (bosconn->status != 0) - { - fprintf(stderr, "faimtest: could not connect to BOS\n"); - } - else - { - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, NULL, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_misses, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_misses, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_misses, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0); - - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_CTN, AIM_CB_CTN_DEFAULT, aim_parse_unknown, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0); - - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0); - - aim_auth_sendcookie(sess, bosconn, sess->logininfo.cookie); - } + if (bosconn == NULL) { + fprintf(stderr, "faimtest: could not connect to BOS: internal error\n"); + } else if (bosconn->status != 0) { + fprintf(stderr, "faimtest: could not connect to BOS\n"); + aim_conn_kill(sess, &bosconn); + } else { + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, NULL, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_misses, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_misses, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_misses, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0); + + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_CTN, AIM_CB_CTN_DEFAULT, aim_parse_unknown, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0); + + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0); + + aim_auth_sendcookie(sess, bosconn, sess->logininfo.cookie); + } return 1; } @@ -446,6 +438,8 @@ int faimtest_parse_userinfo(struct aim_session_t *sess, struct command_rx_struct printf("UNKNOWN_BIT4 "); if (userinfo->class & 0x0010) printf("FREE "); + if (userinfo->class & 0x0040) + printf("ICQ? "); printf("\n"); printf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince); @@ -490,24 +484,97 @@ int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_str /* * Channel 1: Standard Message */ - if (channel == 1) - { - struct aim_userinfo_s *userinfo; - char *msg = NULL; - u_int icbmflags = 0; - char *tmpstr = NULL; - u_short flag1, flag2; - + if (channel == 1) { + struct aim_userinfo_s *userinfo; + char *msg = NULL; + u_int icbmflags = 0; + char *tmpstr = NULL; + u_short flag1, flag2; + + userinfo = va_arg(ap, struct aim_userinfo_s *); + msg = va_arg(ap, char *); + icbmflags = va_arg(ap, u_int); + flag1 = va_arg(ap, u_short); + flag2 = va_arg(ap, u_short); + va_end(ap); + + printf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn); + printf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel); + printf("faimtest: icbm: class = 0x%04x ", userinfo->class); + if (userinfo->class & 0x0010) + printf("(FREE) "); + if (userinfo->class & 0x0001) + printf("(TRIAL) "); + if (userinfo->class & 0x0004) + printf("(AOL) "); + printf("\n"); + printf("faimtest: icbm: membersince = %lu\n", userinfo->membersince); + printf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince); + printf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime); + + printf("faimtest: icbm: icbmflags = "); + if (icbmflags & AIM_IMFLAGS_AWAY) + printf("away "); + if (icbmflags & AIM_IMFLAGS_ACK) + printf("ackrequest "); + printf("\n"); + + printf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2); + + printf("faimtest: icbm: message: %s\n", msg); + + if (msg) { + tmpstr = index(msg, '>'); + if (tmpstr != NULL) + tmpstr+=1; + else + tmpstr = msg; + + if ( (strlen(tmpstr) >= 10) && + (!strncmp(tmpstr, "disconnect", 10)) ) { + aim_send_im(sess, command->conn, "midendian", 0, "ta ta..."); + aim_logoff(sess); + } else if (strstr(tmpstr, "goodday")) { + printf("faimtest: icbm: sending response\n"); + aim_send_im(sess, command->conn, userinfo->sn, 0, "Good day to you too."); + } else if (!strncmp(tmpstr, "open chatnav", 12)) { + aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV); + //aim_chat_join(sess, command->conn, "thishereisaname2_chat85"); + } else if (!strncmp(tmpstr, "create", 6)) { + aim_chatnav_createroom(sess, aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), "WorldDomination", 0x0004); + } else if (!strncmp(tmpstr, "close chatnav", 13)) { + struct aim_conn_t *chatnavconn; + chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV); + aim_conn_kill(sess, &chatnavconn); + } else if (!strncmp(tmpstr, "join", 4)) { + aim_chat_join(sess, command->conn, 0x0004, "worlddomination"); + } else if (!strncmp(tmpstr, "leave", 5)) + aim_chat_leaveroom(sess, "worlddomination"); + else if (!strncmp(tmpstr, "getinfo", 7)) { + aim_getinfo(sess, command->conn, "75784102", AIM_GETINFO_GENERALINFO); + aim_getinfo(sess, command->conn, "15853637", AIM_GETINFO_AWAYMESSAGE); + } else { + printf("unknown command.\n"); + } + + } + } + /* + * Channel 2: Rendevous Request + */ + else if (channel == 2) { + struct aim_userinfo_s *userinfo; + unsigned short reqclass; + + reqclass = va_arg(ap, unsigned short); + switch (reqclass) { + case AIM_RENDEZVOUS_VOICE: { userinfo = va_arg(ap, struct aim_userinfo_s *); - msg = va_arg(ap, char *); - icbmflags = va_arg(ap, u_int); - flag1 = va_arg(ap, u_short); - flag2 = va_arg(ap, u_short); va_end(ap); - printf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn); - printf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel); - printf("faimtest: icbm: class = 0x%04x ", userinfo->class); + printf("faimtest: voice invitation: source sn = %s\n", userinfo->sn); + printf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel); + printf("faimtest: voice invitation: \tclass = 0x%04x ", userinfo->class); if (userinfo->class & 0x0010) printf("(FREE) "); if (userinfo->class & 0x0001) @@ -515,143 +582,60 @@ int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_str if (userinfo->class & 0x0004) printf("(AOL) "); printf("\n"); - printf("faimtest: icbm: membersince = %lu\n", userinfo->membersince); - printf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince); - printf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime); + /* we dont get membersince on chat invites! */ + printf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince); + printf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime); - printf("faimtest: icbm: icbmflags = "); - if (icbmflags & AIM_IMFLAGS_AWAY) - printf("away "); - if (icbmflags & AIM_IMFLAGS_ACK) - printf("ackrequest "); - printf("\n"); + break; + } + case AIM_RENDEZVOUS_FILETRANSFER: { + printf("faimtset: file transfer!\n"); + break; + } + case AIM_RENDEZVOUS_CHAT_EX3: + case AIM_RENDEZVOUS_CHAT_EX4: + case AIM_RENDEZVOUS_CHAT_EX5: { + char *msg,*encoding,*lang; + struct aim_chat_roominfo *roominfo; - printf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2); + userinfo = va_arg(ap, struct aim_userinfo_s *); + roominfo = va_arg(ap, struct aim_chat_roominfo *); + msg = va_arg(ap, char *); + encoding = va_arg(ap, char *); + lang = va_arg(ap, char *); + va_end(ap); - printf("faimtest: icbm: message: %s\n", msg); + printf("faimtest: chat invitation: source sn = %s\n", userinfo->sn); + printf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel); + printf("faimtest: chat invitation: \tclass = 0x%04x ", userinfo->class); + if (userinfo->class & 0x0010) + printf("(FREE) "); + if (userinfo->class & 0x0001) + printf("(TRIAL) "); + if (userinfo->class & 0x0004) + printf("(AOL) "); + printf("\n"); + /* we dont get membersince on chat invites! */ + printf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince); + printf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime); - if (msg) - { - tmpstr = index(msg, '>'); - if (tmpstr != NULL) - tmpstr+=1; - else - tmpstr = msg; - - if ( (strlen(tmpstr) >= 10) && - (!strncmp(tmpstr, "disconnect", 10)) ) - { - aim_send_im(sess, command->conn, "midendian", 0, "ta ta..."); - aim_logoff(sess); - } - else if (strstr(tmpstr, "goodday")) - { - printf("faimtest: icbm: sending response\n"); - aim_send_im(sess, command->conn, userinfo->sn, 0, "Good day to you too."); - } - else if (!strncmp(tmpstr, "open chatnav", 12)) - { - aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV); - //aim_chat_join(sess, command->conn, "thishereisaname2_chat85"); - } - else if (!strncmp(tmpstr, "create", 6)) - { - aim_chatnav_createroom(sess, aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), "WorldDomination", 0x0004); - } - else if (!strncmp(tmpstr, "close chatnav", 13)) - aim_conn_close(aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV)); - else if (!strncmp(tmpstr, "join", 4)) - { - aim_chat_join(sess, command->conn, 0x0004, "worlddomination"); - } - else if (!strncmp(tmpstr, "leave", 5)) - aim_chat_leaveroom(sess, "worlddomination"); - else if (!strncmp(tmpstr, "getinfo", 7)) { - aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_GENERALINFO); - aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_AWAYMESSAGE); - } else - { -#if 0 - printf("faimtest: icbm: starting chat...\n"); - aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV); -#else - aim_bos_setidle(sess, command->conn, 0x0ffffffe); -#endif - } - - } - } - /* - * Channel 2: Rendevous Request - */ - else if (channel == 2) - { - struct aim_userinfo_s *userinfo; - int rendtype = 0; - - rendtype = va_arg(ap, int); - if (rendtype == 0) - { - char *msg,*encoding,*lang; - struct aim_chat_roominfo *roominfo; - - userinfo = va_arg(ap, struct aim_userinfo_s *); - roominfo = va_arg(ap, struct aim_chat_roominfo *); - msg = va_arg(ap, char *); - encoding = va_arg(ap, char *); - lang = va_arg(ap, char *); - va_end(ap); - - printf("faimtest: chat invitation: source sn = %s\n", userinfo->sn); - printf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel); - printf("faimtest: chat invitation: \tclass = 0x%04x ", userinfo->class); - if (userinfo->class & 0x0010) - printf("(FREE) "); - if (userinfo->class & 0x0001) - printf("(TRIAL) "); - if (userinfo->class & 0x0004) - printf("(AOL) "); - printf("\n"); - /* we dont get membersince on chat invites! */ - printf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince); - printf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime); - - printf("faimtest: chat invitation: message = %s\n", msg); - printf("faimtest: chat invitation: room name = %s\n", roominfo->name); - printf("faimtest: chat invitation: encoding = %s\n", encoding); - printf("faimtest: chat invitation: language = %s\n", lang); - printf("faimtest: chat invitation: exchange = 0x%04x\n", roominfo->exchange); - printf("faimtest: chat invitation: instance = 0x%04x\n", roominfo->instance); - printf("faimtest: chat invitiation: autojoining %s...\n", roominfo->name); - /* - * Automatically join room... - */ - aim_chat_join(sess, command->conn, 0x0004, roominfo->name); - } - else if (rendtype == 1) - { - userinfo = va_arg(ap, struct aim_userinfo_s *); - va_end(ap); - - printf("faimtest: voice invitation: source sn = %s\n", userinfo->sn); - printf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel); - printf("faimtest: voice invitation: \tclass = 0x%04x ", userinfo->class); - if (userinfo->class & 0x0010) - printf("(FREE) "); - if (userinfo->class & 0x0001) - printf("(TRIAL) "); - if (userinfo->class & 0x0004) - printf("(AOL) "); - printf("\n"); - /* we dont get membersince on chat invites! */ - printf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince); - printf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime); - - } - else - printf("faimtest: icbm: unknown rendtype (%d)\n", rendtype); - } - else + printf("faimtest: chat invitation: message = %s\n", msg); + printf("faimtest: chat invitation: room name = %s\n", roominfo->name); + printf("faimtest: chat invitation: encoding = %s\n", encoding); + printf("faimtest: chat invitation: language = %s\n", lang); + printf("faimtest: chat invitation: exchange = 0x%04x\n", roominfo->exchange); + printf("faimtest: chat invitation: instance = 0x%04x\n", roominfo->instance); + printf("faimtest: chat invitiation: autojoining %s...\n", roominfo->name); + /* + * Automatically join room... + */ + aim_chat_join(sess, command->conn, 0x0004, roominfo->name); + break; + } + default: + printf("faimtest: icbm: unknown reqclass (%d)\n", reqclass); + } /* switch */ + } else printf("faimtest does not support channels > 2 (chan = %02x)\n", channel); printf("faimtest: icbm: done with ICBM handling\n");