Changeset 862371b for libfaim/chat.c


Ignore:
Timestamp:
Jun 29, 2003, 1:47:04 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:
e016fc2
Parents:
03ad7b2
Message:
*** empty log message ***
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libfaim/chat.c

    r5e53c4a r862371b  
    11/*
    2  * aim_chat.c
    3  *
    4  * Routines for the Chat service.
     2 * Family 0x000e - Routines for the Chat service.
    53 *
    64 */
     
    1614};
    1715
    18 static void dumpbox(aim_session_t *sess, unsigned char *buf, int len)
    19 {
    20         int i;
    21 
    22         if (!sess || !buf || !len)
    23                 return;
    24 
    25         faimdprintf(sess, 1, "\nDump of %d bytes at %p:", len, buf);
    26 
    27         for (i = 0; i < len; i++) {
    28                 if ((i % 8) == 0)
    29                         faimdprintf(sess, 1, "\n\t");
    30 
    31                 faimdprintf(sess, 1, "0x%2x ", buf[i]);
    32         }
    33 
    34         faimdprintf(sess, 1, "\n\n");
    35 
    36         return;
    37 }
    38 
    3916faim_internal void aim_conn_kill_chat(aim_session_t *sess, aim_conn_t *conn)
    4017{
     
    10784}
    10885
     86static int aim_addtlvtochain_chatroom(aim_tlvlist_t **list, fu16_t type, fu16_t exchange, const char *roomname, fu16_t instance)
     87{
     88        fu8_t *buf;
     89        int buflen;
     90        aim_bstream_t bs;
     91
     92        buflen = 2 + 1 + strlen(roomname) + 2;
     93       
     94        if (!(buf = malloc(buflen)))
     95                return 0;
     96
     97        aim_bstream_init(&bs, buf, buflen);
     98
     99        aimbs_put16(&bs, exchange);
     100        aimbs_put8(&bs, strlen(roomname));
     101        aimbs_putraw(&bs, roomname, strlen(roomname));
     102        aimbs_put16(&bs, instance);
     103
     104        aim_addtlvtochain_raw(list, type, aim_bstream_curpos(&bs), buf);
     105
     106        free(buf);
     107
     108        return 0;
     109}
     110
    109111/*
    110  * Send a Chat Message.
     112 * Join a room of name roomname.  This is the first step to joining an
     113 * already created room.  It's basically a Service Request for
     114 * family 0x000e, with a little added on to specify the exchange and room
     115 * name.
     116 */
     117faim_export int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, fu16_t exchange, const char *roomname, fu16_t instance)
     118{
     119        aim_frame_t *fr;
     120        aim_snacid_t snacid;
     121        aim_tlvlist_t *tl = NULL;
     122        struct chatsnacinfo csi;
     123       
     124        if (!sess || !conn || !roomname || !strlen(roomname))
     125                return -EINVAL;
     126
     127        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512)))
     128                return -ENOMEM;
     129
     130        memset(&csi, 0, sizeof(csi));
     131        csi.exchange = exchange;
     132        strncpy(csi.name, roomname, sizeof(csi.name));
     133        csi.instance = instance;
     134
     135        snacid = aim_cachesnac(sess, 0x0001, 0x0004, 0x0000, &csi, sizeof(csi));
     136        aim_putsnac(&fr->data, 0x0001, 0x0004, 0x0000, snacid);
     137
     138        /*
     139         * Requesting service chat (0x000e)
     140         */
     141        aimbs_put16(&fr->data, 0x000e);
     142
     143        aim_addtlvtochain_chatroom(&tl, 0x0001, exchange, roomname, instance);
     144        aim_writetlvchain(&fr->data, &tl);
     145        aim_freetlvchain(&tl);
     146
     147        aim_tx_enqueue(sess, fr);
     148
     149        return 0;
     150}
     151
     152faim_internal int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo)
     153{
     154        int namelen;
     155
     156        if (!bs || !outinfo)
     157                return 0;
     158
     159        outinfo->exchange = aimbs_get16(bs);
     160        namelen = aimbs_get8(bs);
     161        outinfo->name = aimbs_getstr(bs, namelen);
     162        outinfo->instance = aimbs_get16(bs);
     163
     164        return 0;
     165}
     166
     167faim_export int aim_chat_leaveroom(aim_session_t *sess, const char *name)
     168{
     169        aim_conn_t *conn;
     170
     171        if (!(conn = aim_chat_getconn(sess, name)))
     172                return -ENOENT;
     173
     174        aim_conn_close(conn);
     175
     176        return 0;
     177}
     178
     179/*
     180 * conn must be a BOS connection!
     181 */
     182faim_export int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *msg, fu16_t exchange, const char *roomname, fu16_t instance)
     183{
     184        int i;
     185        aim_frame_t *fr;
     186        aim_msgcookie_t *cookie;
     187        struct aim_invite_priv *priv;
     188        fu8_t ckstr[8];
     189        aim_snacid_t snacid;
     190        aim_tlvlist_t *otl = NULL, *itl = NULL;
     191        fu8_t *hdr;
     192        int hdrlen;
     193        aim_bstream_t hdrbs;
     194       
     195        if (!sess || !conn || !sn || !msg || !roomname)
     196                return -EINVAL;
     197
     198        if (conn->type != AIM_CONN_TYPE_BOS)
     199                return -EINVAL;
     200
     201        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152+strlen(sn)+strlen(roomname)+strlen(msg))))
     202                return -ENOMEM;
     203
     204        snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, sn, strlen(sn)+1);
     205        aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
     206
     207
     208        /*
     209         * Cookie
     210         */
     211        for (i = 0; i < sizeof(ckstr); i++)
     212                aimutil_put8(ckstr, (fu8_t) rand());
     213
     214        /* XXX should be uncached by an unwritten 'invite accept' handler */
     215        if ((priv = malloc(sizeof(struct aim_invite_priv)))) {
     216                priv->sn = strdup(sn);
     217                priv->roomname = strdup(roomname);
     218                priv->exchange = exchange;
     219                priv->instance = instance;
     220        }
     221
     222        if ((cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_INVITE, priv)))
     223                aim_cachecookie(sess, cookie);
     224        else
     225                free(priv);
     226
     227        for (i = 0; i < sizeof(ckstr); i++)
     228                aimbs_put8(&fr->data, ckstr[i]);
     229
     230
     231        /*
     232         * Channel (2)
     233         */
     234        aimbs_put16(&fr->data, 0x0002);
     235
     236        /*
     237         * Dest sn
     238         */
     239        aimbs_put8(&fr->data, strlen(sn));
     240        aimbs_putraw(&fr->data, sn, strlen(sn));
     241
     242        /*
     243         * TLV t(0005)
     244         *
     245         * Everything else is inside this TLV.
     246         *
     247         * Sigh.  AOL was rather inconsistent right here.  So we have
     248         * to play some minor tricks.  Right inside the type 5 is some
     249         * raw data, followed by a series of TLVs. 
     250         *
     251         */
     252        hdrlen = 2+8+16+6+4+4+strlen(msg)+4+2+1+strlen(roomname)+2;
     253        hdr = malloc(hdrlen);
     254        aim_bstream_init(&hdrbs, hdr, hdrlen);
     255       
     256        aimbs_put16(&hdrbs, 0x0000); /* Unknown! */
     257        aimbs_putraw(&hdrbs, ckstr, sizeof(ckstr)); /* I think... */
     258        aim_putcap(&hdrbs, AIM_CAPS_CHAT);
     259
     260        aim_addtlvtochain16(&itl, 0x000a, 0x0001);
     261        aim_addtlvtochain_noval(&itl, 0x000f);
     262        aim_addtlvtochain_raw(&itl, 0x000c, strlen(msg), msg);
     263        aim_addtlvtochain_chatroom(&itl, 0x2711, exchange, roomname, instance);
     264        aim_writetlvchain(&hdrbs, &itl);
     265       
     266        aim_addtlvtochain_raw(&otl, 0x0005, aim_bstream_curpos(&hdrbs), hdr);
     267
     268        aim_writetlvchain(&fr->data, &otl);
     269
     270        free(hdr);
     271        aim_freetlvchain(&itl);
     272        aim_freetlvchain(&otl);
     273       
     274        aim_tx_enqueue(sess, fr);
     275
     276        return 0;
     277}
     278
     279/*
     280 * Subtype 0x0002 - General room information.  Lots of stuff.
     281 *
     282 * Values I know are in here but I havent attached
     283 * them to any of the 'Unknown's:
     284 *      - Language (English)
     285 *
     286 */
     287static int infoupdate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
     288{
     289        aim_userinfo_t *userinfo = NULL;
     290        aim_rxcallback_t userfunc;
     291        int ret = 0;
     292        int usercount = 0;
     293        fu8_t detaillevel = 0;
     294        char *roomname = NULL;
     295        struct aim_chat_roominfo roominfo;
     296        fu16_t tlvcount = 0;
     297        aim_tlvlist_t *tlvlist;
     298        char *roomdesc = NULL;
     299        fu16_t flags = 0;
     300        fu32_t creationtime = 0;
     301        fu16_t maxmsglen = 0, maxvisiblemsglen = 0;
     302        fu16_t unknown_d2 = 0, unknown_d5 = 0;
     303
     304        aim_chat_readroominfo(bs, &roominfo);
     305
     306        detaillevel = aimbs_get8(bs);
     307
     308        if (detaillevel != 0x02) {
     309                faimdprintf(sess, 0, "faim: chat_roomupdateinfo: detail level %d not supported\n", detaillevel);
     310                return 1;
     311        }
     312
     313        tlvcount = aimbs_get16(bs);
     314
     315        /*
     316         * Everything else are TLVs.
     317         */
     318        tlvlist = aim_readtlvchain(bs);
     319
     320        /*
     321         * TLV type 0x006a is the room name in Human Readable Form.
     322         */
     323        if (aim_gettlv(tlvlist, 0x006a, 1))
     324                roomname = aim_gettlv_str(tlvlist, 0x006a, 1);
     325
     326        /*
     327         * Type 0x006f: Number of occupants.
     328         */
     329        if (aim_gettlv(tlvlist, 0x006f, 1))
     330                usercount = aim_gettlv16(tlvlist, 0x006f, 1);
     331
     332        /*
     333         * Type 0x0073:  Occupant list.
     334         */
     335        if (aim_gettlv(tlvlist, 0x0073, 1)) {   
     336                int curoccupant = 0;
     337                aim_tlv_t *tmptlv;
     338                aim_bstream_t occbs;
     339
     340                tmptlv = aim_gettlv(tlvlist, 0x0073, 1);
     341
     342                /* Allocate enough userinfo structs for all occupants */
     343                userinfo = calloc(usercount, sizeof(aim_userinfo_t));
     344
     345                aim_bstream_init(&occbs, tmptlv->value, tmptlv->length);
     346
     347                while (curoccupant < usercount)
     348                        aim_extractuserinfo(sess, &occbs, &userinfo[curoccupant++]);
     349        }
     350
     351        /*
     352         * Type 0x00c9: Flags. (AIM_CHATROOM_FLAG)
     353         */
     354        if (aim_gettlv(tlvlist, 0x00c9, 1))
     355                flags = aim_gettlv16(tlvlist, 0x00c9, 1);
     356
     357        /*
     358         * Type 0x00ca: Creation time (4 bytes)
     359         */
     360        if (aim_gettlv(tlvlist, 0x00ca, 1))
     361                creationtime = aim_gettlv32(tlvlist, 0x00ca, 1);
     362
     363        /*
     364         * Type 0x00d1: Maximum Message Length
     365         */
     366        if (aim_gettlv(tlvlist, 0x00d1, 1))
     367                maxmsglen = aim_gettlv16(tlvlist, 0x00d1, 1);
     368
     369        /*
     370         * Type 0x00d2: Unknown. (2 bytes)
     371         */
     372        if (aim_gettlv(tlvlist, 0x00d2, 1))
     373                unknown_d2 = aim_gettlv16(tlvlist, 0x00d2, 1);
     374
     375        /*
     376         * Type 0x00d3: Room Description
     377         */
     378        if (aim_gettlv(tlvlist, 0x00d3, 1))
     379                roomdesc = aim_gettlv_str(tlvlist, 0x00d3, 1);
     380
     381        /*
     382         * Type 0x000d4: Unknown (flag only)
     383         */
     384        if (aim_gettlv(tlvlist, 0x000d4, 1))
     385                ;
     386
     387        /*
     388         * Type 0x00d5: Unknown. (1 byte)
     389         */
     390        if (aim_gettlv(tlvlist, 0x00d5, 1))
     391                unknown_d5 = aim_gettlv8(tlvlist, 0x00d5, 1);
     392
     393
     394        /*
     395         * Type 0x00d6: Encoding 1 ("us-ascii")
     396         */
     397        if (aim_gettlv(tlvlist, 0x000d6, 1))
     398                ;
     399       
     400        /*
     401         * Type 0x00d7: Language 1 ("en")
     402         */
     403        if (aim_gettlv(tlvlist, 0x000d7, 1))
     404                ;
     405
     406        /*
     407         * Type 0x00d8: Encoding 2 ("us-ascii")
     408         */
     409        if (aim_gettlv(tlvlist, 0x000d8, 1))
     410                ;
     411       
     412        /*
     413         * Type 0x00d9: Language 2 ("en")
     414         */
     415        if (aim_gettlv(tlvlist, 0x000d9, 1))
     416                ;
     417
     418        /*
     419         * Type 0x00da: Maximum visible message length
     420         */
     421        if (aim_gettlv(tlvlist, 0x000da, 1))
     422                maxvisiblemsglen = aim_gettlv16(tlvlist, 0x00da, 1);
     423
     424        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
     425                ret = userfunc(sess,
     426                                rx,
     427                                &roominfo,
     428                                roomname,
     429                                usercount,
     430                                userinfo,       
     431                                roomdesc,
     432                                flags,
     433                                creationtime,
     434                                maxmsglen,
     435                                unknown_d2,
     436                                unknown_d5,
     437                                maxvisiblemsglen);
     438        }
     439
     440        free(roominfo.name);
     441        free(userinfo);
     442        free(roomname);
     443        free(roomdesc);
     444        aim_freetlvchain(&tlvlist);
     445
     446        return ret;
     447}
     448
     449/* Subtypes 0x0003 and 0x0004 */
     450static int userlistchange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
     451{
     452        aim_userinfo_t *userinfo = NULL;
     453        aim_rxcallback_t userfunc;
     454        int curcount = 0, ret = 0;
     455
     456        while (aim_bstream_empty(bs)) {
     457                curcount++;
     458                userinfo = realloc(userinfo, curcount * sizeof(aim_userinfo_t));
     459                aim_extractuserinfo(sess, bs, &userinfo[curcount-1]);
     460        }
     461
     462        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
     463                ret = userfunc(sess, rx, curcount, userinfo);
     464
     465        free(userinfo);
     466
     467        return ret;
     468}
     469
     470/*
     471 * Subtype 0x0005 - Send a Chat Message.
    111472 *
    112473 * Possible flags:
     
    204565}
    205566
    206 static int aim_addtlvtochain_chatroom(aim_tlvlist_t **list, fu16_t type, fu16_t exchange, const char *roomname, fu16_t instance)
    207 {
    208         fu8_t *buf;
    209         int buflen;
    210         aim_bstream_t bs;
    211 
    212         buflen = 2 + 1 + strlen(roomname) + 2;
    213        
    214         if (!(buf = malloc(buflen)))
    215                 return 0;
    216 
    217         aim_bstream_init(&bs, buf, buflen);
    218 
    219         aimbs_put16(&bs, exchange);
    220         aimbs_put8(&bs, strlen(roomname));
    221         aimbs_putraw(&bs, roomname, strlen(roomname));
    222         aimbs_put16(&bs, instance);
    223 
    224         aim_addtlvtochain_raw(list, type, aim_bstream_curpos(&bs), buf);
    225 
    226         free(buf);
    227 
    228         return 0;
    229 }
    230 
    231567/*
    232  * Join a room of name roomname.  This is the first step to joining an
    233  * already created room.  It's basically a Service Request for
    234  * family 0x000e, with a little added on to specify the exchange and room
    235  * name.
    236  */
    237 faim_export int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, fu16_t exchange, const char *roomname, fu16_t instance)
    238 {
    239         aim_frame_t *fr;
    240         aim_snacid_t snacid;
    241         aim_tlvlist_t *tl = NULL;
    242         struct chatsnacinfo csi;
    243        
    244         if (!sess || !conn || !roomname || !strlen(roomname))
    245                 return -EINVAL;
    246 
    247         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512)))
    248                 return -ENOMEM;
    249 
    250         memset(&csi, 0, sizeof(csi));
    251         csi.exchange = exchange;
    252         strncpy(csi.name, roomname, sizeof(csi.name));
    253         csi.instance = instance;
    254 
    255         snacid = aim_cachesnac(sess, 0x0001, 0x0004, 0x0000, &csi, sizeof(csi));
    256         aim_putsnac(&fr->data, 0x0001, 0x0004, 0x0000, snacid);
    257 
    258         /*
    259          * Requesting service chat (0x000e)
    260          */
    261         aimbs_put16(&fr->data, 0x000e);
    262 
    263         aim_addtlvtochain_chatroom(&tl, 0x0001, exchange, roomname, instance);
    264         aim_writetlvchain(&fr->data, &tl);
    265         aim_freetlvchain(&tl);
    266 
    267         aim_tx_enqueue(sess, fr);
    268 
    269         return 0;
    270 }
    271 
    272 faim_internal int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo)
    273 {
    274         int namelen;
    275 
    276         if (!bs || !outinfo)
    277                 return 0;
    278 
    279         outinfo->exchange = aimbs_get16(bs);
    280         namelen = aimbs_get8(bs);
    281         outinfo->name = aimbs_getstr(bs, namelen);
    282         outinfo->instance = aimbs_get16(bs);
    283 
    284         return 0;
    285 }
    286 
    287 faim_export int aim_chat_leaveroom(aim_session_t *sess, const char *name)
    288 {
    289         aim_conn_t *conn;
    290 
    291         if (!(conn = aim_chat_getconn(sess, name)))
    292                 return -ENOENT;
    293 
    294         aim_conn_close(conn);
    295 
    296         return 0;
    297 }
    298 
    299 /*
    300  * conn must be a BOS connection!
    301  */
    302 faim_export int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *msg, fu16_t exchange, const char *roomname, fu16_t instance)
    303 {
    304         int i;
    305         aim_frame_t *fr;
    306         aim_msgcookie_t *cookie;
    307         struct aim_invite_priv *priv;
    308         fu8_t ckstr[8];
    309         aim_snacid_t snacid;
    310         aim_tlvlist_t *otl = NULL, *itl = NULL;
    311         fu8_t *hdr;
    312         int hdrlen;
    313         aim_bstream_t hdrbs;
    314        
    315         if (!sess || !conn || !sn || !msg || !roomname)
    316                 return -EINVAL;
    317 
    318         if (conn->type != AIM_CONN_TYPE_BOS)
    319                 return -EINVAL;
    320 
    321         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152+strlen(sn)+strlen(roomname)+strlen(msg))))
    322                 return -ENOMEM;
    323 
    324         snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, sn, strlen(sn)+1);
    325         aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
    326 
    327 
    328         /*
    329          * Cookie
    330          */
    331         for (i = 0; i < sizeof(ckstr); i++)
    332                 aimutil_put8(ckstr, (fu8_t) rand());
    333 
    334         /* XXX should be uncached by an unwritten 'invite accept' handler */
    335         if ((priv = malloc(sizeof(struct aim_invite_priv)))) {
    336                 priv->sn = strdup(sn);
    337                 priv->roomname = strdup(roomname);
    338                 priv->exchange = exchange;
    339                 priv->instance = instance;
    340         }
    341 
    342         if ((cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_INVITE, priv)))
    343                 aim_cachecookie(sess, cookie);
    344         else
    345                 free(priv);
    346 
    347         for (i = 0; i < sizeof(ckstr); i++)
    348                 aimbs_put8(&fr->data, ckstr[i]);
    349 
    350 
    351         /*
    352          * Channel (2)
    353          */
    354         aimbs_put16(&fr->data, 0x0002);
    355 
    356         /*
    357          * Dest sn
    358          */
    359         aimbs_put8(&fr->data, strlen(sn));
    360         aimbs_putraw(&fr->data, sn, strlen(sn));
    361 
    362         /*
    363          * TLV t(0005)
    364          *
    365          * Everything else is inside this TLV.
    366          *
    367          * Sigh.  AOL was rather inconsistent right here.  So we have
    368          * to play some minor tricks.  Right inside the type 5 is some
    369          * raw data, followed by a series of TLVs. 
    370          *
    371          */
    372         hdrlen = 2+8+16+6+4+4+strlen(msg)+4+2+1+strlen(roomname)+2;
    373         hdr = malloc(hdrlen);
    374         aim_bstream_init(&hdrbs, hdr, hdrlen);
    375        
    376         aimbs_put16(&hdrbs, 0x0000); /* Unknown! */
    377         aimbs_putraw(&hdrbs, ckstr, sizeof(ckstr)); /* I think... */
    378         aim_putcap(&hdrbs, AIM_CAPS_CHAT);
    379 
    380         aim_addtlvtochain16(&itl, 0x000a, 0x0001);
    381         aim_addtlvtochain_noval(&itl, 0x000f);
    382         aim_addtlvtochain_raw(&itl, 0x000c, strlen(msg), msg);
    383         aim_addtlvtochain_chatroom(&itl, 0x2711, exchange, roomname, instance);
    384         aim_writetlvchain(&hdrbs, &itl);
    385        
    386         aim_addtlvtochain_raw(&otl, 0x0005, aim_bstream_curpos(&hdrbs), hdr);
    387 
    388         aim_writetlvchain(&fr->data, &otl);
    389 
    390         free(hdr);
    391         aim_freetlvchain(&itl);
    392         aim_freetlvchain(&otl);
    393        
    394         aim_tx_enqueue(sess, fr);
    395 
    396         return 0;
    397 }
    398 
    399 /*
    400  * General room information.  Lots of stuff.
     568 * Subtype 0x0006
    401569 *
    402  * Values I know are in here but I havent attached
    403  * them to any of the 'Unknown's:
    404  *      - Language (English)
    405  *
    406  * SNAC 000e/0002
    407  */
    408 static int infoupdate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    409 {
    410         aim_userinfo_t *userinfo = NULL;
    411         aim_rxcallback_t userfunc;
    412         int ret = 0;
    413         int usercount = 0;
    414         fu8_t detaillevel = 0;
    415         char *roomname = NULL;
    416         struct aim_chat_roominfo roominfo;
    417         fu16_t tlvcount = 0;
    418         aim_tlvlist_t *tlvlist;
    419         char *roomdesc = NULL;
    420         fu16_t flags = 0;
    421         fu32_t creationtime = 0;
    422         fu16_t maxmsglen = 0, maxvisiblemsglen = 0;
    423         fu16_t unknown_d2 = 0, unknown_d5 = 0;
    424 
    425         dumpbox(sess, bs->data + bs->offset, aim_bstream_empty(bs));
    426 
    427         aim_chat_readroominfo(bs, &roominfo);
    428 
    429         detaillevel = aimbs_get8(bs);
    430 
    431         if (detaillevel != 0x02) {
    432                 faimdprintf(sess, 0, "faim: chat_roomupdateinfo: detail level %d not supported\n", detaillevel);
    433                 return 1;
    434         }
    435 
    436         tlvcount = aimbs_get16(bs);
    437 
    438         /*
    439          * Everything else are TLVs.
    440          */
    441         tlvlist = aim_readtlvchain(bs);
    442 
    443         /*
    444          * TLV type 0x006a is the room name in Human Readable Form.
    445          */
    446         if (aim_gettlv(tlvlist, 0x006a, 1))
    447                 roomname = aim_gettlv_str(tlvlist, 0x006a, 1);
    448 
    449         /*
    450          * Type 0x006f: Number of occupants.
    451          */
    452         if (aim_gettlv(tlvlist, 0x006f, 1))
    453                 usercount = aim_gettlv16(tlvlist, 0x006f, 1);
    454 
    455         /*
    456          * Type 0x0073:  Occupant list.
    457          */
    458         if (aim_gettlv(tlvlist, 0x0073, 1)) {   
    459                 int curoccupant = 0;
    460                 aim_tlv_t *tmptlv;
    461                 aim_bstream_t occbs;
    462 
    463                 tmptlv = aim_gettlv(tlvlist, 0x0073, 1);
    464 
    465                 /* Allocate enough userinfo structs for all occupants */
    466                 userinfo = calloc(usercount, sizeof(aim_userinfo_t));
    467 
    468                 aim_bstream_init(&occbs, tmptlv->value, tmptlv->length);
    469 
    470                 while (curoccupant < usercount)
    471                         aim_extractuserinfo(sess, &occbs, &userinfo[curoccupant++]);
    472         }
    473 
    474         /*
    475          * Type 0x00c9: Flags. (AIM_CHATROOM_FLAG)
    476          */
    477         if (aim_gettlv(tlvlist, 0x00c9, 1))
    478                 flags = aim_gettlv16(tlvlist, 0x00c9, 1);
    479 
    480         /*
    481          * Type 0x00ca: Creation time (4 bytes)
    482          */
    483         if (aim_gettlv(tlvlist, 0x00ca, 1))
    484                 creationtime = aim_gettlv32(tlvlist, 0x00ca, 1);
    485 
    486         /*
    487          * Type 0x00d1: Maximum Message Length
    488          */
    489         if (aim_gettlv(tlvlist, 0x00d1, 1))
    490                 maxmsglen = aim_gettlv16(tlvlist, 0x00d1, 1);
    491 
    492         /*
    493          * Type 0x00d2: Unknown. (2 bytes)
    494          */
    495         if (aim_gettlv(tlvlist, 0x00d2, 1))
    496                 unknown_d2 = aim_gettlv16(tlvlist, 0x00d2, 1);
    497 
    498         /*
    499          * Type 0x00d3: Room Description
    500          */
    501         if (aim_gettlv(tlvlist, 0x00d3, 1))
    502                 roomdesc = aim_gettlv_str(tlvlist, 0x00d3, 1);
    503 
    504         /*
    505          * Type 0x000d4: Unknown (flag only)
    506          */
    507         if (aim_gettlv(tlvlist, 0x000d4, 1))
    508                 ;
    509 
    510         /*
    511          * Type 0x00d5: Unknown. (1 byte)
    512          */
    513         if (aim_gettlv(tlvlist, 0x00d5, 1))
    514                 unknown_d5 = aim_gettlv8(tlvlist, 0x00d5, 1);
    515 
    516 
    517         /*
    518          * Type 0x00d6: Encoding 1 ("us-ascii")
    519          */
    520         if (aim_gettlv(tlvlist, 0x000d6, 1))
    521                 ;
    522        
    523         /*
    524          * Type 0x00d7: Language 1 ("en")
    525          */
    526         if (aim_gettlv(tlvlist, 0x000d7, 1))
    527                 ;
    528 
    529         /*
    530          * Type 0x00d8: Encoding 2 ("us-ascii")
    531          */
    532         if (aim_gettlv(tlvlist, 0x000d8, 1))
    533                 ;
    534        
    535         /*
    536          * Type 0x00d9: Language 2 ("en")
    537          */
    538         if (aim_gettlv(tlvlist, 0x000d9, 1))
    539                 ;
    540 
    541         /*
    542          * Type 0x00da: Maximum visible message length
    543          */
    544         if (aim_gettlv(tlvlist, 0x000da, 1))
    545                 maxvisiblemsglen = aim_gettlv16(tlvlist, 0x00da, 1);
    546 
    547         if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
    548                 ret = userfunc(sess,
    549                                 rx,
    550                                 &roominfo,
    551                                 roomname,
    552                                 usercount,
    553                                 userinfo,       
    554                                 roomdesc,
    555                                 flags,
    556                                 creationtime,
    557                                 maxmsglen,
    558                                 unknown_d2,
    559                                 unknown_d5,
    560                                 maxvisiblemsglen);
    561         }
    562 
    563         free(roominfo.name);
    564         free(userinfo);
    565         free(roomname);
    566         free(roomdesc);
    567         aim_freetlvchain(&tlvlist);
    568 
    569         return ret;
    570 }
    571 
    572 static int userlistchange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    573 {
    574         aim_userinfo_t *userinfo = NULL;
    575         aim_rxcallback_t userfunc;
    576         int curcount = 0, ret = 0;
    577 
    578         while (aim_bstream_empty(bs)) {
    579                 curcount++;
    580                 userinfo = realloc(userinfo, curcount * sizeof(aim_userinfo_t));
    581                 aim_extractuserinfo(sess, bs, &userinfo[curcount-1]);
    582         }
    583 
    584         if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    585                 ret = userfunc(sess, rx, curcount, userinfo);
    586 
    587         free(userinfo);
    588 
    589         return ret;
    590 }
    591 
    592 /*
    593570 * We could probably include this in the normal ICBM parsing
    594571 * code as channel 0x0003, however, since only the start
     
    734711        return 0;
    735712}
    736 
    737 
Note: See TracChangeset for help on using the changeset viewer.