Changeset e374dee for libfaim/im.c


Ignore:
Timestamp:
Oct 10, 2003, 5:12:30 PM (18 years ago)
Author:
James M. Kretchmar <kretch@mit.edu>
Branches:
master, barnowl_perlaim, debian, owl, release-1.4, release-1.5, release-1.6, release-1.7, release-1.8, release-1.9
Children:
fe6f1d3
Parents:
f4d0975
Message:
*** empty log message ***
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libfaim/im.c

    r862371b re374dee  
    11/*
    2  *  Family 0x0004 - Routines for sending/receiving Instant Messages.
    3  *
    4  *  Note the term ICBM (Inter-Client Basic Message) which blankets
    5  *  all types of genericly routed through-server messages.  Within
    6  *  the ICBM types (family 4), a channel is defined.  Each channel
    7  *  represents a different type of message.  Channel 1 is used for
    8  *  what would commonly be called an "instant message".  Channel 2
    9  *  is used for negotiating "rendezvous".  These transactions end in
    10  *  something more complex happening, such as a chat invitation, or
    11  *  a file transfer.  Channel 3 is used for chat messages (not in
    12  *  the same family as these channels).  Channel 4 is used for
    13  *  various ICQ messages.  Examples are normal messages, URLs, and
    14  *  old-style authorization.
    15  *
    16  *  In addition to the channel, every ICBM contains a cookie.  For
    17  *  standard IMs, these are only used for error messages.  However,
    18  *  the more complex rendezvous messages make suitably more complex
    19  *  use of this field.
    20  *
     2 * Family 0x0004 - Routines for sending/receiving Instant Messages.
     3 *
     4 * Note the term ICBM (Inter-Client Basic Message) which blankets
     5 * all types of genericly routed through-server messages.  Within
     6 * the ICBM types (family 4), a channel is defined.  Each channel
     7 * represents a different type of message.  Channel 1 is used for
     8 * what would commonly be called an "instant message".  Channel 2
     9 * is used for negotiating "rendezvous".  These transactions end in
     10 * something more complex happening, such as a chat invitation, or
     11 * a file transfer.  Channel 3 is used for chat messages (not in
     12 * the same family as these channels).  Channel 4 is used for
     13 * various ICQ messages.  Examples are normal messages, URLs, and
     14 * old-style authorization.
     15 *
     16 * In addition to the channel, every ICBM contains a cookie.  For
     17 * standard IMs, these are only used for error messages.  However,
     18 * the more complex rendezvous messages make suitably more complex
     19 * use of this field.
     20 *
     21 * TODO: Split this up into an im.c file an an icbm.c file.  It
     22 *       will be beautiful, you'll see.
     23 *
     24 *       Need to rename all the mpmsg messages to aim_im_bleh.
     25 *
     26 *       Make sure aim_conn_findbygroup is used by all functions.
    2127 */
    2228
     
    2733#include "win32dep.h"
    2834#endif
     35
     36/**
     37 * Add a standard ICBM header to the given bstream with the given
     38 * information.
     39 *
     40 * @param bs The bstream to write the ICBM header to.
     41 * @param c c is for cookie, and cookie is for me.
     42 * @param ch The ICBM channel (1 through 4).
     43 * @param sn Null-terminated scrizeen nizame.
     44 * @return The number of bytes written.  It's really not useful.
     45 */
     46static int aim_im_puticbm(aim_bstream_t *bs, const fu8_t *c, fu16_t ch, const char *sn)
     47{
     48        aimbs_putraw(bs, c, 8);
     49        aimbs_put16(bs, ch);
     50        aimbs_put8(bs, strlen(sn));
     51        aimbs_putraw(bs, sn, strlen(sn));
     52        return 8+2+1+strlen(sn);
     53}
    2954
    3055/*
     
    3863 *
    3964 * Heres the current collection:
    40  *  0501 0003 0101 0101 01       AOL Mobile Communicator, WinAIM 1.0.414
    41  *  0501 0003 0101 0201 01       WinAIM 2.0.847, 2.1.1187, 3.0.1464,
    42  *                                      4.3.2229, 4.4.2286
    43  *  0501 0004 0101 0102 0101     WinAIM 4.1.2010, libfaim (right here)
    44  *  0501 0003 0101 02            WinAIM 5
    45  *  0501 0001 01                 iChat x.x
    46  *  0501 0001 0101 01            AOL v6.0, CompuServe 2000 v6.0, any
    47  *                                      TOC client
     65 *  0501 0003 0101 0101 01              AOL Mobile Communicator, WinAIM 1.0.414
     66 *  0501 0003 0101 0201 01              WinAIM 2.0.847, 2.1.1187, 3.0.1464,
     67 *                                      4.3.2229, 4.4.2286
     68 *  0501 0004 0101 0102 0101            WinAIM 4.1.2010, libfaim (right here)
     69 *  0501 0003 0101 02                   WinAIM 5
     70 *  0501 0001 01                        iChat x.x, mobile buddies
     71 *  0501 0001 0101 01                   AOL v6.0, CompuServe 2000 v6.0, any TOC client
     72 *  0501 0002 0106                      WinICQ 5.45.1.3777.85
    4873 *
    4974 * Note that in this function, only the feature bytes are tested, since
     
    5176 *
    5277 */
    53 faim_export fu16_t aim_fingerprintclient(fu8_t *msghdr, int len)
     78faim_export fu16_t aim_im_fingerprint(const fu8_t *msghdr, int len)
    5479{
    5580        static const struct {
     
    91116}
    92117
    93 /*
    94  * Subtype 0x0002
     118/**
     119 * Subtype 0x0002 - Set ICBM parameters.
    95120 *
    96121 * I definitly recommend sending this.  If you don't, you'll be stuck
    97  * with the rather unreasonable defaults.  You don't want those.  Send this.
     122 * with the rather unreasonable defaults.
    98123 *
    99124 */
    100 faim_export int aim_seticbmparam(aim_session_t *sess, struct aim_icbmparameters *params)
     125faim_export int aim_im_setparams(aim_session_t *sess, struct aim_icbmparameters *params)
    101126{
    102127        aim_conn_t *conn;
     
    131156}
    132157
    133 /* Subtype 0x0004 - Request ICBM parameter information. */
    134 faim_export int aim_reqicbmparams(aim_session_t *sess)
     158/**
     159 * Subtype 0x0004 - Request ICBM parameter information.
     160 *
     161 */
     162faim_export int aim_im_reqparams(aim_session_t *sess)
    135163{
    136164        aim_conn_t *conn;
     
    142170}
    143171
    144 /* Subtype 0x0005 */
    145 static int paraminfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    146 {
     172/**
     173 * Subtype 0x0005 - Receive parameter information.
     174 *
     175 */
     176static int aim_im_paraminfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
     177{
     178        aim_rxcallback_t userfunc;
    147179        struct aim_icbmparameters params;
    148         aim_rxcallback_t userfunc;
    149180
    150181        params.maxchan = aimbs_get16(bs);
     
    161192}
    162193
    163 /* This should be endian-safe now... but who knows... */
    164 faim_export fu16_t aim_iconsum(const fu8_t *buf, int buflen)
    165 {
    166         fu32_t sum;
    167         int i;
    168 
    169         for (i = 0, sum = 0; i + 1 < buflen; i += 2)
    170                 sum += (buf[i+1] << 8) + buf[i];
    171         if (i < buflen)
    172                 sum += buf[i];
    173 
    174         sum = ((sum & 0xffff0000) >> 16) + (sum & 0x0000ffff);
    175 
    176         return (fu16_t)sum;
    177 }
    178 
    179 /*
     194/**
    180195 * Subtype 0x0006 - Send an ICBM (instant message). 
    181196 *
     
    220235 * instead of writing out the bytes manually.
    221236 *
    222  * XXX more precise verification that we never send SNACs larger than 8192
    223  * XXX check SNAC size for multipart
    224  *
    225  */
    226 faim_export int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args)
    227 {
    228         static const fu8_t deffeatures[] = {
    229                 0x01, 0x01, 0x01, 0x02
    230         };
     237 * XXX - more precise verification that we never send SNACs larger than 8192
     238 * XXX - check SNAC size for multipart
     239 *
     240 */
     241faim_export int aim_im_sendch1_ext(aim_session_t *sess, struct aim_sendimext_args *args)
     242{
    231243        aim_conn_t *conn;
    232         int i, msgtlvlen;
    233244        aim_frame_t *fr;
    234245        aim_snacid_t snacid;
     246        fu8_t ck[8];
     247        int i, msgtlvlen;
     248        static const fu8_t deffeatures[] = { 0x01, 0x01, 0x01, 0x02 };
    235249
    236250        if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))
     
    275289                return -ENOMEM;
    276290
    277         /* XXX should be optional */   
     291        /* XXX - should be optional */ 
    278292        snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, args->destsn, strlen(args->destsn)+1);
    279293        aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
    280294
    281295        /*
    282          * Generate a random message cookie 
     296         * Generate a random message cookie
    283297         *
    284298         * We could cache these like we do SNAC IDs.  (In fact, it
     
    289303         */
    290304        for (i = 0; i < 8; i++)
    291                 aimbs_put8(&fr->data, (fu8_t) rand());
    292 
    293         /*
    294          * Channel ID
    295          */
    296         aimbs_put16(&fr->data, 0x0001);
    297 
    298         /*
    299          * Destination SN (prepended with byte length)
    300          */
    301         aimbs_put8(&fr->data, strlen(args->destsn));
    302         aimbs_putraw(&fr->data, args->destsn, strlen(args->destsn));
    303 
    304         /*
    305          * Message TLV (type 2).
    306          */
     305                ck[i] = (fu8_t)rand();
     306
     307        /* ICBM header */
     308        aim_im_puticbm(&fr->data, ck, 0x0001, args->destsn);
     309
     310        /* Message TLV (type 0x0002) */
    307311        aimbs_put16(&fr->data, 0x0002);
    308312        aimbs_put16(&fr->data, msgtlvlen);
    309313
    310         /*
    311          * Features
    312          *
    313          */
    314         aimbs_put8(&fr->data, 0x05);
    315         aimbs_put8(&fr->data, 0x01);
    316 
     314        /* Features TLV (type 0x0501) */
     315        aimbs_put16(&fr->data, 0x0501);
    317316        if (args->flags & AIM_IMFLAGS_CUSTOMFEATURES) {
    318317                aimbs_put16(&fr->data, args->featureslen);
     
    326325                aim_mpmsg_section_t *sec;
    327326
     327                /* Insert each message part in a TLV (type 0x0101) */
    328328                for (sec = args->mpmsg->parts; sec; sec = sec->next) {
    329329                        aimbs_put16(&fr->data, 0x0101);
     
    336336        } else {
    337337
     338                /* Insert message text in a TLV (type 0x0101) */
    338339                aimbs_put16(&fr->data, 0x0101);
    339340
    340                 /*
    341                  * Message block length.
    342                  */
     341                /* Message block length */
    343342                aimbs_put16(&fr->data, args->msglen + 0x04);
    344343
    345                 /*
    346                  * Character set.
    347                  */
    348                 if (args->flags & AIM_IMFLAGS_CUSTOMCHARSET) {
    349 
    350                         aimbs_put16(&fr->data, args->charset);
    351                         aimbs_put16(&fr->data, args->charsubset);
    352 
    353                 } else {
    354                         if (args->flags & AIM_IMFLAGS_UNICODE)
    355                                 aimbs_put16(&fr->data, 0x0002);
    356                         else if (args->flags & AIM_IMFLAGS_ISO_8859_1)
    357                                 aimbs_put16(&fr->data, 0x0003);
    358                         else
    359                                 aimbs_put16(&fr->data, 0x0000);
    360 
    361                         aimbs_put16(&fr->data, 0x0000);
    362                 }
    363 
    364                 /*
    365                  * Message.  Not terminated.
    366                  */
     344                /* Character set */
     345                aimbs_put16(&fr->data, args->charset);
     346                aimbs_put16(&fr->data, args->charsubset);
     347
     348                /* Message.  Not terminated */
    367349                aimbs_putraw(&fr->data, args->msg, args->msglen);
    368350        }
    369351
    370         /*
    371          * Set the Request Acknowledge flag. 
    372          */
    373         if (args->flags & AIM_IMFLAGS_ACK) {
    374                 aimbs_put16(&fr->data, 0x0003);
    375                 aimbs_put16(&fr->data, 0x0000);
    376         }
    377 
    378         /*
    379          * Set the Autoresponse flag.
    380          */
     352        /* Set the Autoresponse flag */
    381353        if (args->flags & AIM_IMFLAGS_AWAY) {
    382354                aimbs_put16(&fr->data, 0x0004);
     355                aimbs_put16(&fr->data, 0x0000);
     356        } else if (args->flags & AIM_IMFLAGS_ACK) {
     357                /* Set the Request Acknowledge flag */
     358                aimbs_put16(&fr->data, 0x0003);
    383359                aimbs_put16(&fr->data, 0x0000);
    384360        }
     
    414390        aim_tx_enqueue(sess, fr);
    415391
     392        /* Move this to receive aim_flap_nop and send aim_flap_nop */
    416393        if (!(sess->flags & AIM_SESS_FLAGS_DONTTIMEOUTONICBM))
    417394                aim_cleansnacs(sess, 60); /* clean out SNACs over 60sec old */
     
    421398
    422399/*
    423  * Simple wrapper for aim_send_im_ext()
     400 * Simple wrapper for aim_im_sendch1_ext()
    424401 *
    425402 * You cannot use aim_send_im if you need the HASICON flag.  You must
    426  * use aim_send_im_ext directly for that.
     403 * use aim_im_sendch1_ext directly for that.
    427404 *
    428405 * aim_send_im also cannot be used if you require UNICODE messages, because
    429  * that requires an explicit message length.  Use aim_send_im_ext().
    430  *
    431  */
    432 faim_export int aim_send_im(aim_session_t *sess, const char *destsn, fu16_t flags, const char *msg)
     406 * that requires an explicit message length.  Use aim_im_sendch1_ext().
     407 *
     408 */
     409faim_export int aim_im_sendch1(aim_session_t *sess, const char *sn, fu16_t flags, const char *msg)
    433410{
    434411        struct aim_sendimext_args args;
    435412
    436         args.destsn = destsn;
     413        args.destsn = sn;
    437414        args.flags = flags;
    438415        args.msg = msg;
    439416        args.msglen = strlen(msg);
    440 
    441         /* Make these don't get set by accident -- they need aim_send_im_ext */
     417        args.charset = 0x0000;
     418        args.charsubset = 0x0000;
     419
     420        /* Make these don't get set by accident -- they need aim_im_sendch1_ext */
    442421        args.flags &= ~(AIM_IMFLAGS_CUSTOMFEATURES | AIM_IMFLAGS_HASICON | AIM_IMFLAGS_MULTIPART);
    443422
    444         return aim_send_im_ext(sess, &args);
    445 }
    446 
    447 /*
    448  * Subtype 0x0006
     423        return aim_im_sendch1_ext(sess, &args);
     424}
     425
     426/**
     427 * Subtype 0x0006 - Send your icon to a given user.
    449428 *
    450429 * This is also performance sensitive. (If you can believe it...)
    451430 *
    452431 */
    453 faim_export int aim_send_icon(aim_session_t *sess, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu16_t iconsum)
     432faim_export int aim_im_sendch2_icon(aim_session_t *sess, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu16_t iconsum)
    454433{
    455434        aim_conn_t *conn;
    456         int i;
    457         fu8_t ck[8];
    458435        aim_frame_t *fr;
    459436        aim_snacid_t snacid;
     437        fu8_t ck[8];
     438        int i;
    460439
    461440        if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))
     
    466445
    467446        for (i = 0; i < 8; i++)
    468                 aimutil_put8(ck+i, (fu8_t) rand());
     447                ck[i] = (fu8_t)rand();
    469448
    470449        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 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)))
     
    474453        aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
    475454
    476         /*
    477          * Cookie
    478          */
    479         aimbs_putraw(&fr->data, ck, 8);
    480 
    481         /*
    482          * Channel (2)
    483          */
    484         aimbs_put16(&fr->data, 0x0002);
    485 
    486         /*
    487          * Dest sn
    488          */
    489         aimbs_put8(&fr->data, strlen(sn));
    490         aimbs_putraw(&fr->data, sn, strlen(sn));
     455        /* ICBM header */
     456        aim_im_puticbm(&fr->data, ck, 0x0002, sn);
    491457
    492458        /*
     
    531497
    532498/*
    533  * Subtype 0x0006
     499 * Subtype 0x0006 - Send a rich text message.
    534500 *
    535501 * This only works for ICQ 2001b (thats 2001 not 2000).  Better, only
     
    545511 *
    546512 */
    547 faim_export int aim_send_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args)
    548 {
    549         const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* AIM_CAPS_ICQRTF capability in string form */
     513faim_export int aim_im_sendch2_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args)
     514{
    550515        aim_conn_t *conn;
    551         int i;
    552         fu8_t ck[8];
    553516        aim_frame_t *fr;
    554517        aim_snacid_t snacid;
    555         int servdatalen;
     518        fu8_t ck[8];
     519        const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* AIM_CAPS_ICQRTF capability in string form */
     520        int i, servdatalen;
    556521
    557522        if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))
     
    564529
    565530        for (i = 0; i < 8; i++)
    566                 aimutil_put8(ck+i, (fu8_t) rand());
     531                ck[i] = (fu8_t)rand();
    567532
    568533        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+128+servdatalen)))
     
    572537        aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
    573538
    574         /*
    575          * Cookie
    576          */
    577         aimbs_putraw(&fr->data, ck, 8);
    578 
    579         /*
    580          * Channel (2)
    581          */
    582         aimbs_put16(&fr->data, 0x0002);
    583 
    584         /*
    585          * Dest sn
    586          */
    587         aimbs_put8(&fr->data, strlen(args->destsn));
    588         aimbs_putraw(&fr->data, args->destsn, strlen(args->destsn));
    589 
    590         /*
    591          * TLV t(0005)
    592          *
    593          * Encompasses everything below.
    594          */
     539        /* ICBM header */
     540        aim_im_puticbm(&fr->data, ck, 0x0002, args->destsn);
     541
     542        /* TLV t(0005) - Encompasses everything below. */
    595543        aimbs_put16(&fr->data, 0x0005);
    596544        aimbs_put16(&fr->data, 2+8+16  +  2+2+2  +  2+2  +  2+2+servdatalen);
     
    600548        aim_putcap(&fr->data, AIM_CAPS_ICQSERVERRELAY);
    601549
    602         /*
    603          * t(000a) l(0002) v(0001)
    604          */
     550        /* t(000a) l(0002) v(0001) */
    605551        aimbs_put16(&fr->data, 0x000a);
    606552        aimbs_put16(&fr->data, 0x0002);
    607553        aimbs_put16(&fr->data, 0x0001);
    608554
    609         /*
    610          * t(000f) l(0000) v()
    611          */
     555        /* t(000f) l(0000) v() */
    612556        aimbs_put16(&fr->data, 0x000f);
    613557        aimbs_put16(&fr->data, 0x0000);
    614558
    615         /*
    616          * Service Data TLV
    617          */
     559        /* Service Data TLV */
    618560        aimbs_put16(&fr->data, 0x2711);
    619561        aimbs_put16(&fr->data, servdatalen);
     
    648590}
    649591
    650 /* Subtype 0x0006 */
    651 faim_internal int aim_request_directim(aim_session_t *sess, const char *destsn, fu8_t *ip, fu16_t port, fu8_t *ckret)
     592/**
     593 * Subtype 0x0006 - Send an "I want to directly connect to you" message
     594 *
     595 */
     596faim_export int aim_im_sendch2_odcrequest(aim_session_t *sess, fu8_t *cookie, const char *sn, const fu8_t *ip, fu16_t port)
    652597{
    653598        aim_conn_t *conn;
    654         fu8_t ck[8];
    655599        aim_frame_t *fr;
    656600        aim_snacid_t snacid;
     601        fu8_t ck[8];
    657602        aim_tlvlist_t *tl = NULL, *itl = NULL;
    658603        int hdrlen, i;
     
    663608                return -EINVAL;
    664609
    665         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 256+strlen(destsn))))
     610        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 256+strlen(sn))))
    666611                return -ENOMEM;
    667612
     
    675620         * TOC-compatible.
    676621         *
    677          * XXX have I mentioned these should be generated in msgcookie.c?
     622         * XXX - have I mentioned these should be generated in msgcookie.c?
    678623         *
    679624         */
     
    682627        ck[7] = '\0';
    683628
    684         if (ckret)
    685                 memcpy(ckret, ck, 8);
    686 
    687         /* Cookie */
    688         aimbs_putraw(&fr->data, ck, 8);
    689 
    690         /* Channel */
    691         aimbs_put16(&fr->data, 0x0002);
    692 
    693         /* Destination SN */
    694         aimbs_put8(&fr->data, strlen(destsn));
    695         aimbs_putraw(&fr->data, destsn, strlen(destsn));
     629        if (cookie)
     630                memcpy(cookie, ck, 8);
     631
     632        /* ICBM header */
     633        aim_im_puticbm(&fr->data, ck, 0x0002, sn);
    696634
    697635        aim_addtlvtochain_noval(&tl, 0x0003);
     
    703641        aimbs_put16(&hdrbs, 0x0000);
    704642        aimbs_putraw(&hdrbs, ck, 8);
    705         aim_putcap(&hdrbs, AIM_CAPS_IMIMAGE);
     643        aim_putcap(&hdrbs, AIM_CAPS_DIRECTIM);
    706644
    707645        aim_addtlvtochain16(&itl, 0x000a, 0x0001);
     
    725663}
    726664
    727 /* Subtype 0x0006 */
    728 faim_internal int aim_request_sendfile(aim_session_t *sess, const char *sn, const char *filename, fu16_t numfiles, fu32_t totsize, fu8_t *ip, fu16_t port, fu8_t *ckret)
     665/**
     666 * Subtype 0x0006 - Send an "I want to send you this file" message
     667 *
     668 */
     669faim_export int aim_im_sendch2_sendfile_ask(aim_session_t *sess, struct aim_oft_info *oft_info)
    729670{
    730671        aim_conn_t *conn;
    731         int i;
    732         fu8_t ck[8];
    733672        aim_frame_t *fr;
    734673        aim_snacid_t snacid;
    735         struct aim_snac_destructor snacdest;
    736 
    737         if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))
     674        aim_tlvlist_t *tl=NULL, *subtl=NULL;
     675        int i;
     676
     677        if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !oft_info)
    738678                return -EINVAL;
    739679
    740         if (!sn || !filename)
     680        /* XXX - Should be like "21CBF95" and null terminated */
     681        for (i = 0; i < 7; i++)
     682                oft_info->cookie[i] = 0x30 + ((fu8_t)rand() % 10);
     683        oft_info->cookie[7] = '\0';
     684
     685        { /* Create the subTLV chain */
     686                fu8_t *buf;
     687                int buflen;
     688                aim_bstream_t bs;
     689
     690                aim_addtlvtochain16(&subtl, 0x000a, 0x0001);
     691                aim_addtlvtochain_noval(&subtl, 0x000f);
     692/*              aim_addtlvtochain_raw(&subtl, 0x000e, 2, "en");
     693                aim_addtlvtochain_raw(&subtl, 0x000d, 8, "us-ascii");
     694                aim_addtlvtochain_raw(&subtl, 0x000c, 24, "Please accept this file."); */
     695                if (oft_info->clientip) {
     696                        fu8_t ip[4];
     697                        char *nexttoken;
     698                        int i = 0;
     699                        nexttoken = strtok(oft_info->clientip, ".");
     700                        while (nexttoken && i<4) {
     701                                ip[i] = atoi(nexttoken);
     702                                nexttoken = strtok(NULL, ".");
     703                                i++;
     704                        }
     705                        aim_addtlvtochain_raw(&subtl, 0x0003, 4, ip);
     706                }
     707                aim_addtlvtochain16(&subtl, 0x0005, oft_info->port);
     708
     709                /* TLV t(2711) */
     710                buflen = 2+2+4+strlen(oft_info->fh.name)+1;
     711                buf = malloc(buflen);
     712                aim_bstream_init(&bs, buf, buflen);
     713                aimbs_put16(&bs, (oft_info->fh.totfiles > 1) ? 0x0002 : 0x0001);
     714                aimbs_put16(&bs, oft_info->fh.totfiles);
     715                aimbs_put32(&bs, oft_info->fh.totsize);
     716
     717                /* Filename - NULL terminated, for some odd reason */
     718                aimbs_putraw(&bs, oft_info->fh.name, strlen(oft_info->fh.name));
     719                aimbs_put8(&bs, 0x00);
     720
     721                aim_addtlvtochain_raw(&subtl, 0x2711, bs.len, bs.data);
     722                free(buf);
     723        }
     724
     725        { /* Create the main TLV chain */
     726                fu8_t *buf;
     727                int buflen;
     728                aim_bstream_t bs;
     729
     730                /* TLV t(0005) - Encompasses everything from above. Gee. */
     731                buflen = 2+8+16+aim_sizetlvchain(&subtl);
     732                buf = malloc(buflen);
     733                aim_bstream_init(&bs, buf, buflen);
     734                aimbs_put16(&bs, AIM_RENDEZVOUS_PROPOSE);
     735                aimbs_putraw(&bs, oft_info->cookie, 8);
     736                aim_putcap(&bs, AIM_CAPS_SENDFILE);
     737                aim_writetlvchain(&bs, &subtl);
     738                aim_freetlvchain(&subtl);
     739                aim_addtlvtochain_raw(&tl, 0x0005, bs.len, bs.data);
     740                free(buf);
     741
     742                /* TLV t(0003) - Request an ack */
     743                aim_addtlvtochain_noval(&tl, 0x0003);
     744        }
     745
     746        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + aim_sizetlvchain(&tl))))
     747                return -ENOMEM;
     748
     749        snacid = aim_cachesnac(sess, 0x0004, 0x0006, AIM_SNACFLAGS_DESTRUCTOR, oft_info->cookie, sizeof(oft_info->cookie));
     750        aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
     751
     752        /* ICBM header */
     753        aim_im_puticbm(&fr->data, oft_info->cookie, 0x0002, oft_info->sn);
     754
     755        /* All that crap from above (the 0x0005 TLV and the 0x0003 TLV) */
     756        aim_writetlvchain(&fr->data, &tl);
     757        aim_freetlvchain(&tl);
     758
     759        aim_tx_enqueue(sess, fr);
     760
     761        return 0;
     762}
     763
     764/**
     765 * Subtype 0x0006 - Send an "I will accept this file" message?
     766 *
     767 * @param rendid Capability type (AIM_CAPS_GETFILE or AIM_CAPS_SENDFILE)
     768 */
     769faim_export int aim_im_sendch2_sendfile_accept(aim_session_t *sess, struct aim_oft_info *oft_info)
     770{
     771        aim_conn_t *conn;
     772        aim_frame_t *fr;
     773        aim_snacid_t snacid;
     774
     775        if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !oft_info)
    741776                return -EINVAL;
    742777
    743         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn)+2+2+2+8+16+6+8+6+4+2+2+2+2+4+strlen(filename)+4)))
     778        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + 4+2+8+16)))
    744779                return -ENOMEM;
    745780
    746         for (i = 0; i < 7; i++)
    747                 aimutil_put8(ck+i, 0x30 + ((fu8_t) rand() % 10));
    748         ck[7] = '\0';
    749 
    750         if (ckret)
    751                 memcpy(ckret, ck, 8);
    752 
    753         /* Fill in the snac destructor so we know if the request
    754          * times out.  Use the cookie in the data field, so we
    755          * know what request to cancel if there is an error.
    756          */
    757         snacdest.data = malloc(8);
    758         memcpy(snacdest.data, ck, 8);
    759         snacdest.conn = conn;
    760         snacid = aim_cachesnac(sess, 0x0004, 0x0006, AIM_SNACFLAGS_DESTRUCTOR, &snacdest, sizeof(snacdest));
     781        snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);
    761782        aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
    762783
    763         /*
    764          * Cookie
    765          */
    766         aimbs_putraw(&fr->data, ck, 8);
    767 
    768         /*
    769          * Channel (2)
    770          */
    771         aimbs_put16(&fr->data, 0x0002);
    772 
    773         /*
    774          * Dest sn
    775          */
    776         aimbs_put8(&fr->data, strlen(sn));
    777         aimbs_putraw(&fr->data, sn, strlen(sn));
    778 
    779         /*
    780          * TLV t(0005)
    781          *
    782          * Encompasses everything below. Gee.
    783          */
     784        /* ICBM header */
     785        aim_im_puticbm(&fr->data, oft_info->cookie, 0x0002, oft_info->sn);
     786
    784787        aimbs_put16(&fr->data, 0x0005);
    785         aimbs_put16(&fr->data, 2+8+16+6+8+6+4+2+2+2+2+4+strlen(filename)+4);
    786 
    787         aimbs_put16(&fr->data, 0x0000);
    788         aimbs_putraw(&fr->data, ck, 8);
     788        aimbs_put16(&fr->data, 0x001a);
     789        aimbs_put16(&fr->data, AIM_RENDEZVOUS_ACCEPT);
     790        aimbs_putraw(&fr->data, oft_info->cookie, 8);
    789791        aim_putcap(&fr->data, AIM_CAPS_SENDFILE);
    790792
    791         /* TLV t(000a) */
    792         aimbs_put16(&fr->data, 0x000a);
    793         aimbs_put16(&fr->data, 0x0002);
    794         aimbs_put16(&fr->data, 0x0001);
    795 
    796         /* TLV t(0003) (IP) */
    797         aimbs_put16(&fr->data, 0x0003);
    798         aimbs_put16(&fr->data, 0x0004);
    799         aimbs_putraw(&fr->data, ip, 4);
    800 
    801         /* TLV t(0005) (port) */
     793        aim_tx_enqueue(sess, fr);
     794
     795        return 0;
     796}
     797
     798/**
     799 * Subtype 0x0006 - Send a "cancel this file transfer" message?
     800 *
     801 */
     802faim_export int aim_im_sendch2_sendfile_cancel(aim_session_t *sess, struct aim_oft_info *oft_info)
     803{
     804        aim_conn_t *conn;
     805        aim_frame_t *fr;
     806        aim_snacid_t snacid;
     807
     808        if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !oft_info)
     809                return -EINVAL;
     810
     811        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + 4+2+8+16)))
     812                return -ENOMEM;
     813
     814        snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);
     815        aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
     816
     817        /* ICBM header */
     818        aim_im_puticbm(&fr->data, oft_info->cookie, 0x0002, oft_info->sn);
     819
    802820        aimbs_put16(&fr->data, 0x0005);
    803         aimbs_put16(&fr->data, 0x0002);
    804         aimbs_put16(&fr->data, port);
    805 
    806         /* TLV t(000f) */
    807         aimbs_put16(&fr->data, 0x000f);
    808         aimbs_put16(&fr->data, 0x0000);
    809 
    810         /* TLV t(2711) */
    811         aimbs_put16(&fr->data, 0x2711);
    812         aimbs_put16(&fr->data, 2+2+4+strlen(filename)+4);
    813 
    814         /* ? */
    815         aimbs_put16(&fr->data, (numfiles > 1) ? 0x0002 : 0x0001);
    816         aimbs_put16(&fr->data, numfiles);
    817         aimbs_put32(&fr->data, totsize);
    818         aimbs_putraw(&fr->data, filename, strlen(filename));
    819 
    820         /* ? */
    821         aimbs_put32(&fr->data, 0x00000000);
    822 
    823 #if 0
    824         /* Newer clients seem to send this (?) -- wtm */
    825         aimbs_put32(&fr->data, 0x00030000);
    826 #endif
     821        aimbs_put16(&fr->data, 0x001a);
     822        aimbs_put16(&fr->data, AIM_RENDEZVOUS_CANCEL);
     823        aimbs_putraw(&fr->data, oft_info->cookie, 8);
     824        aim_putcap(&fr->data, AIM_CAPS_SENDFILE);
    827825
    828826        aim_tx_enqueue(sess, fr);
     
    840838 * @return Return 0 if no errors, otherwise return the error number.
    841839 */
    842 faim_export int aim_send_im_ch2_geticqmessage(aim_session_t *sess, const char *sn, int type)
     840faim_export int aim_im_sendch2_geticqaway(aim_session_t *sess, const char *sn, int type)
    843841{
    844842        aim_conn_t *conn;
     843        aim_frame_t *fr;
     844        aim_snacid_t snacid;
    845845        int i;
    846846        fu8_t ck[8];
    847         aim_frame_t *fr;
    848         aim_snacid_t snacid;
    849847
    850848        if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !sn)
     
    852850
    853851        for (i = 0; i < 8; i++)
    854                 aimutil_put8(ck+i, (fu8_t) rand());
     852                ck[i] = (fu8_t)rand();
    855853
    856854        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn) + 4+0x5e + 4)))
     
    860858        aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
    861859
    862         /* Cookie */
    863         aimbs_putraw(&fr->data, ck, 8);
    864 
    865         /* Channel (2) */
    866         aimbs_put16(&fr->data, 0x0002);
    867 
    868         /* Dest sn */
    869         aimbs_put8(&fr->data, strlen(sn));
    870         aimbs_putraw(&fr->data, sn, strlen(sn));
     860        /* ICBM header */
     861        aim_im_puticbm(&fr->data, ck, 0x0002, sn);
    871862
    872863        /* TLV t(0005) - Encompasses almost everything below. */
     
    897888                        aimbs_putle16(&fr->data, 0x001b); /* L */
    898889                        aimbs_putle16(&fr->data, 0x0008); /* XXX - Protocol version */
    899                         aimbs_putle32(&fr->data, 0x00000000); /* Unknown */
    900                         aimbs_putle32(&fr->data, 0x00000000); /* Unknown */
    901                         aimbs_putle32(&fr->data, 0x00000000); /* Unknown */
    902                         aimbs_putle32(&fr->data, 0x00000000); /* Unknown */
     890                        aim_putcap(&fr->data, AIM_CAPS_EMPTY);
    903891                        aimbs_putle16(&fr->data, 0x0000); /* Unknown */
    904892                        aimbs_putle16(&fr->data, 0x0003); /* Client features? */
     
    927915                        aimbs_putle16(&fr->data, 0x0000); /* Status? */
    928916                        aimbs_putle16(&fr->data, 0x0001); /* Priority of this message? */
    929                         aimbs_putle16(&fr->data, 0x0001); /* L? */
    930                         aimbs_putle8(&fr->data, 0x00); /* Null termination? */
     917                        aimbs_putle16(&fr->data, 0x0001); /* L */
     918                        aimbs_putle8(&fr->data, 0x00); /* String of length L */
    931919                } /* End TLV t(2711) */
    932920        } /* End TLV t(0005) */
     
    942930
    943931/**
    944  * Subtype 0x0006
     932 * Subtype 0x0006 - Send an ICQ-esque ICBM.
    945933 *
    946934 * This can be used to send an ICQ authorization reply (deny or grant).  It is the "old way." 
     
    955943 * @return Return 0 if no errors, otherwise return the error number.
    956944 */
    957 faim_export int aim_send_im_ch4(aim_session_t *sess, char *sn, fu16_t type, fu8_t *message)
     945faim_export int aim_im_sendch4(aim_session_t *sess, char *sn, fu16_t type, fu8_t *message)
    958946{
    959947        aim_conn_t *conn;
     
    961949        aim_snacid_t snacid;
    962950        int i;
     951        char ck[8];
    963952
    964953        if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0002)))
     
    974963        aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
    975964
    976         /*
    977          * Cookie
    978          */
     965        /* Cookie */
    979966        for (i=0; i<8; i++)
    980                 aimbs_put8(&fr->data, (fu8_t)rand());
    981 
    982         /*
    983          * Channel (4)
    984          */
    985         aimbs_put16(&fr->data, 0x0004);
    986 
    987         /*
    988          * Dest sn
    989          */
    990         aimbs_put8(&fr->data, strlen(sn));
    991         aimbs_putraw(&fr->data, sn, strlen(sn));
     967                ck[i] = (fu8_t)rand();
     968
     969        /* ICBM header */
     970        aim_im_puticbm(&fr->data, ck, 0x0004, sn);
    992971
    993972        /*
     
    10221001}
    10231002
     1003/*
     1004 * XXX - I don't see when this would ever get called...
     1005 */
    10241006static int outgoingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    10251007{
     
    11771159}
    11781160
    1179 /* XXX should provide a way of saying ISO-8859-1 specifically */
     1161/* XXX - should provide a way of saying ISO-8859-1 specifically */
    11801162faim_export int aim_mpmsg_addascii(aim_session_t *sess, aim_mpmsg_t *mpm, const char *ascii)
    11811163{
     
    12801262                 * the specified data length, which will not include the pad.
    12811263                 *
    1282                  * XXX There's an API bug here.  For sending, the UNICODE is
     1264                 * XXX - There's an API bug here.  For sending, the UNICODE is
    12831265                 * given in host byte order (aim_mpmsg_addunicode), but here
    12841266                 * the received messages are given in network byte order.
     
    13131295                        args->charset = sec->charset;
    13141296                        args->charsubset = sec->charsubset;
    1315                         args->icbmflags |= AIM_IMFLAGS_CUSTOMCHARSET;
    13161297
    13171298                        /* Set up the simple flags */
     
    13311312                        else if (args->charsubset == 0xffff)
    13321313                                ; /* no subencoding */
    1333 #if 0
    1334                         /* XXX this isn't really necesary... */
    1335                         if (    ((args.flag1 != 0x0000) &&
    1336                                  (args.flag1 != 0x0002) &&
    1337                                  (args.flag1 != 0x0003) &&
    1338                                  (args.flag1 != 0xffff)) ||
    1339                                 ((args.flag2 != 0x0000) &&
    1340                                  (args.flag2 != 0x000b) &&
    1341                                  (args.flag2 != 0xffff))) {
    1342                                 faimdprintf(sess, 0, "icbm: **warning: encoding flags are being used! {%04x, %04x}\n", args.flag1, args.flag2);
    1343                         }
    1344 #endif
    13451314
    13461315                        args->msg = sec->data;
     
    14191388                } else if (type == 0x0006) { /* Message was received offline. */
    14201389
    1421                         /* XXX not sure if this actually gets sent. */
     1390                        /* XXX - not sure if this actually gets sent. */
    14221391                        args.icbmflags |= AIM_IMFLAGS_OFFLINE;
    14231392
     
    15551524{
    15561525
    1557         /* XXX aim_chat_roominfo_free() */
     1526        /* XXX - aim_chat_roominfo_free() */
    15581527        free(args->info.chat.roominfo.name);
    15591528
     
    16161585        aim_bstream_advance(servdata, hdrlen);
    16171586
    1618         /* XXX This is such a hack. */
     1587        /* XXX - This is such a hack. */
    16191588        args->reqclass = AIM_CAPS_ICQRTF;
    16201589
     
    16341603        args->destructor = (void *)incomingim_ch2_sendfile_free;
    16351604
    1636         if (servdata) {
     1605        /* Maybe there is a better way to tell what kind of sendfile
     1606         * this is?  Maybe TLV t(000a)? */
     1607        if (servdata) { /* Someone is sending us a file */
    16371608                int flen;
    16381609
     
    16421613                args->info.sendfile.totsize = aimbs_get32(servdata);
    16431614
    1644                 /* XXX - create an aimbs_getnullstr function */
     1615                /*
     1616                 * I hope to God I'm right when I guess that there is a
     1617                 * 32 char max filename length for single files.  I think
     1618                 * OFT tends to do that.  Gotta love inconsistency.  I saw
     1619                 * a 26 byte filename?
     1620                 */
     1621                /* AAA - create an aimbs_getnullstr function (don't anymore)(maybe) */
    16451622                /* Use an inelegant way of getting the null-terminated filename,
    16461623                 * since there's no easy bstream routine. */
     
    16511628                /* There is sometimes more after the null-terminated filename,
    16521629                 * but I'm unsure of its format. */
     1630                /* I don't believe him. */
    16531631        }
    16541632
     
    16681646        int ret = 0;
    16691647
    1670         char clientip1[30] = {""};
    1671         char clientip2[30] = {""};
     1648        char proxyip[30] = {""};
     1649        char clientip[30] = {""};
    16721650        char verifiedip[30] = {""};
    16731651
     
    17111689
    17121690        /*
    1713          * IP address from the perspective of the client.
     1691         * IP address to proxy the file transfer through.
     1692         *
     1693         * XXX - I don't like this.  Maybe just read in an int?  Or inet_ntoa...
    17141694         */
    17151695        if (aim_gettlv(list2, 0x0002, 1)) {
     
    17171697
    17181698                iptlv = aim_gettlv(list2, 0x0002, 1);
    1719 
    1720                 snprintf(clientip1, sizeof(clientip1), "%d.%d.%d.%d",
    1721                                 aimutil_get8(iptlv->value+0),
    1722                                 aimutil_get8(iptlv->value+1),
    1723                                 aimutil_get8(iptlv->value+2),
    1724                                 aimutil_get8(iptlv->value+3));
    1725         }
    1726 
    1727         /*
    1728          * Secondary IP address from the perspective of the client.
     1699                if (iptlv->length == 4)
     1700                        snprintf(proxyip, sizeof(proxyip), "%hhd.%hhd.%hhd.%hhd",
     1701                                iptlv->value[0], iptlv->value[1],
     1702                                iptlv->value[2], iptlv->value[3]);
     1703        }
     1704
     1705        /*
     1706         * IP address from the perspective of the client.
    17291707         */
    17301708        if (aim_gettlv(list2, 0x0003, 1)) {
     
    17321710
    17331711                iptlv = aim_gettlv(list2, 0x0003, 1);
    1734 
    1735                 snprintf(clientip2, sizeof(clientip2), "%d.%d.%d.%d",
    1736                                 aimutil_get8(iptlv->value+0),
    1737                                 aimutil_get8(iptlv->value+1),
    1738                                 aimutil_get8(iptlv->value+2),
    1739                                 aimutil_get8(iptlv->value+3));
     1712                if (iptlv->length == 4)
     1713                        snprintf(clientip, sizeof(clientip), "%hhd.%hhd.%hhd.%hhd",
     1714                                iptlv->value[0], iptlv->value[1],
     1715                                iptlv->value[2], iptlv->value[3]);
    17401716        }
    17411717
     
    17491725
    17501726                iptlv = aim_gettlv(list2, 0x0004, 1);
    1751 
    1752                 snprintf(verifiedip, sizeof(verifiedip), "%d.%d.%d.%d",
    1753                                 aimutil_get8(iptlv->value+0),
    1754                                 aimutil_get8(iptlv->value+1),
    1755                                 aimutil_get8(iptlv->value+2),
    1756                                 aimutil_get8(iptlv->value+3));
     1727                if (iptlv->length == 4)
     1728                        snprintf(verifiedip, sizeof(verifiedip), "%hhd.%hhd.%hhd.%hhd",
     1729                                iptlv->value[0], iptlv->value[1],
     1730                                iptlv->value[2], iptlv->value[3]);
    17571731        }
    17581732
     
    17621736        if (aim_gettlv(list2, 0x0005, 1))
    17631737                args.port = aim_gettlv16(list2, 0x0005, 1);
     1738
     1739        /*
     1740         * Something to do with ft -- two bytes
     1741         * 0x0001 - "I want to send you this file"
     1742         * 0x0002 - "I will accept this file from you"
     1743         */
     1744        if (aim_gettlv(list2, 0x000a, 1))
     1745                ;
    17641746
    17651747        /*
     
    17871769                args.language = aim_gettlv_str(list2, 0x000e, 1);
    17881770
    1789         /* Unknown -- two bytes = 0x0001 */
    1790         if (aim_gettlv(list2, 0x000a, 1))
    1791                 ;
    1792 
    1793         /* Unknown -- no value */
     1771        /*
     1772         * Unknown -- no value
     1773         *
     1774         * Maybe means we should connect directly to transfer the file?
     1775        */
    17941776        if (aim_gettlv(list2, 0x000f, 1))
    17951777                ;
    17961778
    1797         if (strlen(clientip1))
    1798                 args.clientip = (char *)clientip1;
    1799         if (strlen(clientip2))
    1800                 args.clientip2 = (char *)clientip2;
     1779        /*
     1780         * Unknown -- no value
     1781         *
     1782         * Maybe means we should proxy the file transfer through an AIM server?
     1783         */
     1784        if (aim_gettlv(list2, 0x0010, 1))
     1785                ;
     1786
     1787        if (strlen(proxyip))
     1788                args.proxyip = (char *)proxyip;
     1789        if (strlen(clientip))
     1790                args.clientip = (char *)clientip;
    18011791        if (strlen(verifiedip))
    18021792                args.verifiedip = (char *)verifiedip;
    18031793
    18041794        /*
    1805          * This is must be present in PROPOSALs, but will probably not
     1795         * This must be present in PROPOSALs, but will probably not
    18061796         * exist in CANCELs and ACCEPTs.
    18071797         *
     
    18631853
    18641854        args.uin = aimbs_getle32(&meat);
    1865         args.type = aimbs_getle16(&meat);
    1866         args.msg = aimbs_getraw(&meat, aimbs_getle16(&meat));
     1855        args.type = aimbs_getle8(&meat);
     1856        args.flags = aimbs_getle8(&meat);
     1857        args.msglen = aimbs_getle16(&meat);
     1858        args.msg = aimbs_getraw(&meat, args.msglen);
    18671859
    18681860        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
     
    19051897         * Channel ID.
    19061898         *
    1907          * Channel 0x0001 is the message channel.  There are
    1908          * other channels for things called "rendevous"
    1909          * which represent chat and some of the other new
    1910          * features of AIM2/3/3.5.
     1899         * Channel 0x0001 is the message channel.  It is
     1900         * used to send basic ICBMs.
    19111901         *
    19121902         * Channel 0x0002 is the Rendevous channel, which
    19131903         * is where Chat Invitiations and various client-client
    19141904         * connection negotiations come from.
     1905         *
     1906         * Channel 0x0003 is used for chat messages.
    19151907         *
    19161908         * Channel 0x0004 is used for ICQ authorization, or
     
    19271919         * userinfo block contains the number of TLVs that contain user
    19281920         * information, the rest are not even though there is no seperation.
    1929          * aim_extractuserinfo() returns the number of bytes used by the
    1930          * userinfo tlvs, so you can start reading the rest of them right
    1931          * afterward. 
     1921         * You can start reading the message TLVs after aim_info_extract()
     1922         * parses out the standard userinfo block.
    19321923         *
    19331924         * That also means that TLV types can be duplicated between the
     
    19361927         *
    19371928         */
    1938         aim_extractuserinfo(sess, bs, &userinfo);
     1929        aim_info_extract(sess, bs, &userinfo);
    19391930
    19401931        /*
     
    19701961
    19711962        } else {
    1972 
    1973                 faimdprintf(sess, 0, "icbm: ICBM received on an unsupported channel.  Ignoring.\n (chan = %04x)", channel);
    1974 
    1975                 return 0;
    1976         }
     1963                faimdprintf(sess, 0, "icbm: ICBM received on an unsupported channel.  Ignoring.  (chan = %04x)\n", channel);
     1964        }
     1965
     1966        aim_info_free(&userinfo);
    19771967
    19781968        return ret;
     
    19801970
    19811971/*
    1982  * Subtype 0x0008 - Send a warning to destsn.
     1972 * Subtype 0x0008 - Send a warning to sn.
    19831973 *
    19841974 * Flags:
     
    19881978 *
    19891979 */
    1990 faim_export int aim_send_warning(aim_session_t *sess, aim_conn_t *conn, const char *destsn, fu32_t flags)
     1980faim_export int aim_im_warn(aim_session_t *sess, aim_conn_t *conn, const char *sn, fu32_t flags)
    19911981{
    19921982        aim_frame_t *fr;
    19931983        aim_snacid_t snacid;
    1994         fu16_t outflags = 0x0000;
    1995 
    1996         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, strlen(destsn)+13)))
     1984
     1985        if (!sess || !conn || !sn)
     1986                return -EINVAL;
     1987
     1988        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, strlen(sn)+13)))
    19971989                return -ENOMEM;
    19981990
    1999         snacid = aim_cachesnac(sess, 0x0004, 0x0008, 0x0000, destsn, strlen(destsn)+1);
    2000 
     1991        snacid = aim_cachesnac(sess, 0x0004, 0x0008, 0x0000, sn, strlen(sn)+1);
    20011992        aim_putsnac(&fr->data, 0x0004, 0x0008, 0x0000, snacid);
    20021993
    2003         if (flags & AIM_WARN_ANON)
    2004                 outflags |= 0x0001;
    2005 
    2006         aimbs_put16(&fr->data, outflags);
    2007         aimbs_put8(&fr->data, strlen(destsn));
    2008         aimbs_putraw(&fr->data, destsn, strlen(destsn));
     1994        aimbs_put16(&fr->data, (flags & AIM_WARN_ANON) ? 0x0001 : 0x0000);
     1995        aimbs_put8(&fr->data, strlen(sn));
     1996        aimbs_putraw(&fr->data, sn, strlen(sn));
    20091997
    20101998        aim_tx_enqueue(sess, fr);
     
    20242012
    20252013                channel = aimbs_get16(bs);
    2026                 aim_extractuserinfo(sess, bs, &userinfo);
     2014                aim_info_extract(sess, bs, &userinfo);
    20272015                nummissed = aimbs_get16(bs);
    20282016                reason = aimbs_get16(bs);
     
    20302018                if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    20312019                         ret = userfunc(sess, rx, channel, &userinfo, nummissed, reason);
     2020
     2021                aim_info_free(&userinfo);
    20322022        }
    20332023
     
    20442034 *
    20452035 */
    2046 faim_export int aim_denytransfer(aim_session_t *sess, const char *sender, const char *cookie, fu16_t code)
     2036faim_export int aim_im_denytransfer(aim_session_t *sess, const char *sender, const char *cookie, fu16_t code)
    20472037{
    20482038        aim_conn_t *conn;
     
    20962086
    20972087        if (channel == 0x0002) { /* File transfer declined */
     2088                aimbs_get16(bs); /* Unknown */
     2089                aimbs_get16(bs); /* Unknown */
    20982090                if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    20992091                        ret = userfunc(sess, rx, channel, sn, reason, ck);
     
    21592151}
    21602152
    2161 /* Subtype 0x000c */
     2153/*
     2154 * Subtype 0x000c - Receive an ack after sending an ICBM.
     2155 *
     2156 * You have to have send the message with the AIM_IMFLAGS_ACK flag set
     2157 * (TLV t(0003)).  The ack contains the ICBM header of the message you
     2158 * sent.
     2159 *
     2160 */
    21622161static int msgack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    21632162{
    21642163        aim_rxcallback_t userfunc;
    2165         fu16_t type;
    2166         fu8_t snlen, *ck;
     2164        fu16_t ch;
     2165        fu8_t *ck;
    21672166        char *sn;
    21682167        int ret = 0;
    21692168
    21702169        ck = aimbs_getraw(bs, 8);
    2171         type = aimbs_get16(bs);
    2172         snlen = aimbs_get8(bs);
    2173         sn = aimbs_getstr(bs, snlen);
     2170        ch = aimbs_get16(bs);
     2171        sn = aimbs_getstr(bs, aimbs_get8(bs));
    21742172
    21752173        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    2176                 ret = userfunc(sess, rx, type, sn);
     2174                ret = userfunc(sess, rx, ch, sn);
    21772175
    21782176        free(sn);
     
    21892187 *
    21902188 */
    2191 faim_export int aim_mtn_send(aim_session_t *sess, fu16_t type1, char *sn, fu16_t type2)
     2189faim_export int aim_im_sendmtn(aim_session_t *sess, fu16_t type1, const char *sn, fu16_t type2)
    21922190{
    21932191        aim_conn_t *conn;
     
    22702268
    22712269        if (snac->subtype == 0x0005)
    2272                 return paraminfo(sess, mod, rx, snac, bs);
     2270                return aim_im_paraminfo(sess, mod, rx, snac, bs);
    22732271        else if (snac->subtype == 0x0006)
    22742272                return outgoingim(sess, mod, rx, snac, bs);
     
    22872285}
    22882286
    2289 static int snacdestructor(aim_session_t *sess, aim_conn_t *conn, aim_modsnac_t *snac, void *data)
    2290 {
    2291         aim_rxcallback_t userfunc;
    2292         int ret = 0;
    2293 
    2294         if (snac->subtype == 0x0006) {
    2295                 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_MSGTIMEOUT)))
    2296                         ret = userfunc(sess, NULL, conn, data);
    2297         }
    2298         /* Note that we return 1 for success, 0 for failure. */
    2299         return ret;
    2300 }
    2301 
    23022287faim_internal int msg_modfirst(aim_session_t *sess, aim_module_t *mod)
    23032288{
     
    23062291        mod->version = 0x0001;
    23072292        mod->toolid = 0x0110;
    2308         mod->toolversion = 0x047b;
     2293        mod->toolversion = 0x0629;
    23092294        mod->flags = 0;
    23102295        strncpy(mod->name, "messaging", sizeof(mod->name));
    23112296        mod->snachandler = snachandler;
    2312         mod->snacdestructor = snacdestructor;
    23132297
    23142298        return 0;
Note: See TracChangeset for help on using the changeset viewer.