Changeset cf02dd6 for libfaim


Ignore:
Timestamp:
Dec 10, 2003, 3:20:45 PM (20 years ago)
Author:
James M. Kretchmar <kretch@mit.edu>
Branches:
master, barnowl_perlaim, debian, owl, release-1.10, release-1.4, release-1.5, release-1.6, release-1.7, release-1.8, release-1.9
Children:
b1fe407
Parents:
8c46404
Message:
*** empty log message ***
Location:
libfaim
Files:
3 deleted
25 edited

Legend:

Unmodified
Added
Removed
  • libfaim/Makefile.in

    r862371b rcf02dd6  
    55OBJS=admin.o adverts.o auth.o bos.o buddylist.o bstream.o \
    66     chat.o chatnav.o conn.o email.o ft.o icq.o im.o \
    7      info.o invite.o md5.o meta.o misc.o msgcookie.o newsearch.o \
     7     invite.o md5.o misc.o msgcookie.o locate.o \
    88     popups.o rxhandlers.o rxqueue.o search.o service.o \
    99     snac.o ssi.o stats.o tlv.o translate.o txqueue.o \
    10      util.o
     10     util.o odir.o bart.o
    1111CFLAGS=@CFLAGS@ -I. -DAIM_BUILDDATE=\"x\" -DAIM_BUILDTIME=\"x\"
    1212
  • libfaim/admin.c

    re374dee rcf02dd6  
    111111        aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid);
    112112
    113         aim_addtlvtochain_raw(&tl, 0x0001, strlen(newnick), newnick);
    114        
    115         aim_writetlvchain(&fr->data, &tl);
    116         aim_freetlvchain(&tl);
     113        aim_tlvlist_add_raw(&tl, 0x0001, strlen(newnick), newnick);
     114       
     115        aim_tlvlist_write(&fr->data, &tl);
     116        aim_tlvlist_free(&tl);
    117117       
    118118        aim_tx_enqueue(sess, fr);
     
    139139
    140140        /* new password TLV t(0002) */
    141         aim_addtlvtochain_raw(&tl, 0x0002, strlen(newpw), newpw);
     141        aim_tlvlist_add_raw(&tl, 0x0002, strlen(newpw), newpw);
    142142
    143143        /* current password TLV t(0012) */
    144         aim_addtlvtochain_raw(&tl, 0x0012, strlen(curpw), curpw);
    145 
    146         aim_writetlvchain(&fr->data, &tl);
    147         aim_freetlvchain(&tl);
     144        aim_tlvlist_add_raw(&tl, 0x0012, strlen(curpw), curpw);
     145
     146        aim_tlvlist_write(&fr->data, &tl);
     147        aim_tlvlist_free(&tl);
    148148
    149149        aim_tx_enqueue(sess, fr);
     
    168168        aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid);
    169169
    170         aim_addtlvtochain_raw(&tl, 0x0011, strlen(newemail), newemail);
    171        
    172         aim_writetlvchain(&fr->data, &tl);
    173         aim_freetlvchain(&tl);
     170        aim_tlvlist_add_raw(&tl, 0x0011, strlen(newemail), newemail);
     171       
     172        aim_tlvlist_write(&fr->data, &tl);
     173        aim_tlvlist_free(&tl);
    174174       
    175175        aim_tx_enqueue(sess, fr);
     
    205205        /* This is 0x0013 if unable to confirm at this time */
    206206
    207         tl = aim_readtlvchain(bs);
     207        tl = aim_tlvlist_read(bs);
    208208
    209209        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
  • libfaim/aim.h

    re374dee rcf02dd6  
    7878#ifndef TRUE
    7979#define TRUE (!FALSE)
     80#endif
     81
     82#ifndef bool
     83#define bool fu8_t
    8084#endif
    8185
     
    206210}
    207211
     212#define CLIENTINFO_AIM_5_5_3415 { \
     213        "AOL Instant Messenger, version 5.5.3415/WIN32", \
     214        0x0109, \
     215        0x0005, 0x0005, \
     216        0x0000, 0x0057, \
     217        0x000000ef, \
     218        "us", "en", \
     219}
     220
    208221#define CLIENTINFO_ICHAT_1_0 { \
    209222        "Apple iChat", \
     
    244257}
    245258
    246 #define CLIENTINFO_ICQBasic_14_3_1068 { \
     259#define CLIENTINFO_ICQBASIC_14_3_1068 { \
    247260        "ICQBasic", \
    248261        0x010a, \
     
    253266}
    254267
    255 #define CLIENTINFO_Netscape_7_0_1 { \
     268#define CLIENTINFO_NETSCAPE_7_0_1 { \
    256269        "Netscape 2000 an approved user of AOL Instant Messenger (SM)", \
    257270        0x1d0d, \
     
    366379} aim_msgcookie_t;
    367380
    368 /* Values for sess->flags */
    369 #define AIM_SESS_FLAGS_SNACLOGIN         0x00000001
    370 #define AIM_SESS_FLAGS_XORLOGIN          0x00000002
    371 #define AIM_SESS_FLAGS_NONBLOCKCONNECT   0x00000004
    372 #define AIM_SESS_FLAGS_DONTTIMEOUTONICBM 0x00000008
    373 
    374381/*
    375382 * AIM Session: The main client-data interface. 
     
    427434        } socksproxy;
    428435
    429         fu32_t flags; /* AIM_SESS_FLAGS_ */
     436        bool nonblocking;
    430437
    431438        int debug;
     
    445452        struct aim_authresp_info *authinfo;
    446453        struct aim_emailinfo *emailinfo;
     454
     455        struct {
     456                struct aim_userinfo_s *userinfo;
     457                struct userinfo_node *torequest;
     458                struct userinfo_node *requested;
     459                int waiting_for_response;
     460        } locate;
    447461
    448462        /* Server-stored information (ssi) */
     
    475489
    476490
     491
    477492/*
    478493 * Get command from connections
     
    540555faim_export int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn);
    541556faim_export int aim_send_login(aim_session_t *, aim_conn_t *, const char *, const char *, struct client_info_s *, const char *key);
    542 faim_export int aim_encode_password_md5(const char *password, const char *key, fu8_t *digest);
    543557faim_export void aim_purge_rxqueue(aim_session_t *);
    544558faim_export void aim_cleansnacs(aim_session_t *, int maxage);
     
    571585typedef void (*faim_debugging_callback_t)(aim_session_t *sess, int level, const char *format, va_list va);
    572586faim_export int aim_setdebuggingcb(aim_session_t *sess, faim_debugging_callback_t);
    573 faim_export void aim_session_init(aim_session_t *, fu32_t flags, int debuglevel);
     587faim_export void aim_session_init(aim_session_t *, bool nonblocking, int debuglevel);
    574588faim_export void aim_session_kill(aim_session_t *);
    575589faim_export void aim_setupproxy(aim_session_t *sess, const char *server, const char *username, const char *password);
     
    580594
    581595
    582 /* service.c */
     596/* 0x0001 - service.c */
    583597faim_export int aim_srv_setavailmsg(aim_session_t *sess, char *msg);
     598faim_export int aim_srv_setidle(aim_session_t *sess, fu32_t idletime);
    584599
    585600
     
    600615faim_export int aim_nop(aim_session_t *, aim_conn_t *);
    601616faim_export int aim_flap_nop(aim_session_t *sess, aim_conn_t *conn);
    602 faim_export int aim_bos_setidle(aim_session_t *, aim_conn_t *, fu32_t);
    603617faim_export int aim_bos_changevisibility(aim_session_t *, aim_conn_t *, int, const char *);
    604 faim_export int aim_bos_setbuddylist(aim_session_t *, aim_conn_t *, const char *);
    605 faim_export int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profile_encoding, const char *profile, const int profile_len, const char *awaymsg_encoding, const char *awaymsg, const int awaymsg_len, fu32_t caps);
    606618faim_export int aim_bos_setgroupperm(aim_session_t *, aim_conn_t *, fu32_t mask);
    607619faim_export int aim_bos_setprivacyflags(aim_session_t *, aim_conn_t *, fu32_t);
     
    609621faim_export int aim_reqservice(aim_session_t *, aim_conn_t *, fu16_t);
    610622faim_export int aim_bos_reqrights(aim_session_t *, aim_conn_t *);
    611 faim_export int aim_bos_reqbuddyrights(aim_session_t *, aim_conn_t *);
    612 faim_export int aim_bos_reqlocaterights(aim_session_t *, aim_conn_t *);
    613 faim_export int aim_setdirectoryinfo(aim_session_t *sess, aim_conn_t *conn, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, fu16_t privacy);
    614 faim_export int aim_setuserinterests(aim_session_t *sess, aim_conn_t *conn, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, fu16_t privacy);
    615623faim_export int aim_setextstatus(aim_session_t *sess, fu32_t status);
    616624
     
    936944
    937945
    938 /* info.c */
     946/* 0x0002 - locate.c */
    939947/*
    940948 * AIM User Info, Standard Form.
    941949 */
    942 #define AIM_FLAG_UNCONFIRMED    0x0001 /* "damned transients" */
     950#define AIM_FLAG_UNCONFIRMED    0x0001 /* "damned transients" */
    943951#define AIM_FLAG_ADMINISTRATOR  0x0002
    944 #define AIM_FLAG_AOL            0x0004
    945 #define AIM_FLAG_OSCAR_PAY      0x0008
    946 #define AIM_FLAG_FREE           0x0010
    947 #define AIM_FLAG_AWAY           0x0020
    948 #define AIM_FLAG_ICQ            0x0040
    949 #define AIM_FLAG_WIRELESS       0x0080
    950 #define AIM_FLAG_UNKNOWN100     0x0100
    951 #define AIM_FLAG_UNKNOWN200     0x0200
    952 #define AIM_FLAG_ACTIVEBUDDY    0x0400
    953 #define AIM_FLAG_UNKNOWN800     0x0800
    954 #define AIM_FLAG_ABINTERNAL     0x1000
    955 #define AIM_FLAG_ALLUSERS       0x001f
     952#define AIM_FLAG_AOL                    0x0004
     953#define AIM_FLAG_OSCAR_PAY              0x0008
     954#define AIM_FLAG_FREE                   0x0010
     955#define AIM_FLAG_AWAY                   0x0020
     956#define AIM_FLAG_ICQ                    0x0040
     957#define AIM_FLAG_WIRELESS               0x0080
     958#define AIM_FLAG_UNKNOWN100             0x0100
     959#define AIM_FLAG_UNKNOWN200             0x0200
     960#define AIM_FLAG_ACTIVEBUDDY    0x0400
     961#define AIM_FLAG_UNKNOWN800             0x0800
     962#define AIM_FLAG_ABINTERNAL             0x1000
     963#define AIM_FLAG_ALLUSERS               0x001f
    956964
    957965#define AIM_USERINFO_PRESENT_FLAGS        0x00000001
     
    966974#define AIM_USERINFO_PRESENT_CREATETIME   0x00000200
    967975
    968 typedef struct {
    969         char sn[MAXSNLEN+1];
     976struct userinfo_node {
     977        char *sn;
     978        struct userinfo_node *next;
     979};
     980
     981typedef struct aim_userinfo_s {
     982        char *sn;
    970983        fu16_t warnlevel; /* evil percent * 10 (999 = 99.9%) */
    971984        fu16_t idletime; /* in seconds */
     
    982995        } icqinfo;
    983996        fu32_t present;
     997
    984998        fu16_t iconcsumlen;
    985999        fu8_t *iconcsum;
    986         char *availmsg_encoding;
    987         char *availmsg;
    988         int availmsg_len;
     1000
     1001        char *info;
     1002        char *info_encoding;
     1003        fu16_t info_len;
     1004
     1005        char *avail;
     1006        char *avail_encoding;
     1007        fu16_t avail_len;
     1008
     1009        char *away;
     1010        char *away_encoding;
     1011        fu16_t away_len;
     1012
     1013        struct aim_userinfo_s *next;
    9891014} aim_userinfo_t;
    9901015
    991 faim_export const char *aim_userinfo_sn(aim_userinfo_t *ui);
    992 faim_export fu16_t aim_userinfo_flags(aim_userinfo_t *ui);
    993 faim_export fu16_t aim_userinfo_idle(aim_userinfo_t *ui);
    994 faim_export float aim_userinfo_warnlevel(aim_userinfo_t *ui);
    995 faim_export time_t aim_userinfo_createtime(aim_userinfo_t *ui);
    996 faim_export time_t aim_userinfo_membersince(aim_userinfo_t *ui);
    997 faim_export time_t aim_userinfo_onlinesince(aim_userinfo_t *ui);
    998 faim_export fu32_t aim_userinfo_sessionlen(aim_userinfo_t *ui);
    999 faim_export int aim_userinfo_hascap(aim_userinfo_t *ui, fu32_t cap);
    1000 
    1001 #define AIM_CAPS_BUDDYICON      0x00000001
    1002 #define AIM_CAPS_VOICE          0x00000002
    1003 #define AIM_CAPS_DIRECTIM       0x00000004
    1004 #define AIM_CAPS_CHAT           0x00000008
    1005 #define AIM_CAPS_GETFILE        0x00000010
    1006 #define AIM_CAPS_SENDFILE       0x00000020
    1007 #define AIM_CAPS_GAMES          0x00000040
    1008 #define AIM_CAPS_SAVESTOCKS     0x00000080
     1016#define AIM_CAPS_BUDDYICON              0x00000001
     1017#define AIM_CAPS_VOICE                  0x00000002
     1018#define AIM_CAPS_DIRECTIM               0x00000004
     1019#define AIM_CAPS_CHAT                   0x00000008
     1020#define AIM_CAPS_GETFILE                0x00000010
     1021#define AIM_CAPS_SENDFILE               0x00000020
     1022#define AIM_CAPS_GAMES                  0x00000040
     1023#define AIM_CAPS_SAVESTOCKS             0x00000080
    10091024#define AIM_CAPS_SENDBUDDYLIST  0x00000100
    1010 #define AIM_CAPS_GAMES2         0x00000200
    1011 #define AIM_CAPS_ICQ            0x00000400
    1012 #define AIM_CAPS_APINFO         0x00000800
    1013 #define AIM_CAPS_ICQRTF         0x00001000
    1014 #define AIM_CAPS_EMPTY          0x00002000
     1025#define AIM_CAPS_GAMES2                 0x00000200
     1026#define AIM_CAPS_ICQ_DIRECT             0x00000400
     1027#define AIM_CAPS_APINFO                 0x00000800
     1028#define AIM_CAPS_ICQRTF                 0x00001000
     1029#define AIM_CAPS_EMPTY                  0x00002000
    10151030#define AIM_CAPS_ICQSERVERRELAY 0x00004000
    1016 #define AIM_CAPS_ICQUTF8OLD     0x00008000
     1031#define AIM_CAPS_ICQUTF8OLD             0x00008000
    10171032#define AIM_CAPS_TRILLIANCRYPT  0x00010000
    1018 #define AIM_CAPS_ICQUTF8        0x00020000
     1033#define AIM_CAPS_ICQUTF8                0x00020000
    10191034#define AIM_CAPS_INTEROPERATE   0x00040000
    1020 #define AIM_CAPS_ICHAT          0x00080000
    1021 #define AIM_CAPS_HIPTOP         0x00100000
    1022 #define AIM_CAPS_SECUREIM       0x00200000
    1023 #define AIM_CAPS_LAST           0x00400000
    1024 
    1025 faim_export int aim_0002_000b(aim_session_t *sess, aim_conn_t *conn, const char *sn);
     1035#define AIM_CAPS_ICHAT                  0x00080000
     1036#define AIM_CAPS_HIPTOP                 0x00100000
     1037#define AIM_CAPS_SECUREIM               0x00200000
     1038#define AIM_CAPS_SMS                    0x00400000
     1039#define AIM_CAPS_GENERICUNKNOWN 0x00800000
     1040#define AIM_CAPS_VIDEO                  0x01000000
     1041#define AIM_CAPS_LAST                   0x02000000
    10261042
    10271043#define AIM_SENDMEMBLOCK_FLAG_ISREQUEST  0
     
    10291045
    10301046faim_export int aim_sendmemblock(aim_session_t *sess, aim_conn_t *conn, fu32_t offset, fu32_t len, const fu8_t *buf, fu8_t flag);
    1031 
    1032 #define AIM_GETINFO_GENERALINFO 0x00001
    1033 #define AIM_GETINFO_AWAYMESSAGE 0x00003
    1034 #define AIM_GETINFO_CAPABILITIES 0x0004
    10351047
    10361048struct aim_invite_priv {
     
    10581070#define AIM_COOKIETYPE_OFTICON  0x15
    10591071
    1060 /* 0x0005 */ faim_export int aim_getinfo(aim_session_t *, aim_conn_t *, const char *, fu16_t);
     1072faim_export aim_userinfo_t *aim_locate_finduserinfo(aim_session_t *sess, const char *sn);
     1073
     1074/* 0x0002 */ faim_export int aim_locate_reqrights(aim_session_t *sess);
     1075/* 0x0004 */ faim_export int aim_locate_setprofile(aim_session_t *sess, const char *profile_encoding, const char *profile, const int profile_len, const char *awaymsg_encoding, const char *awaymsg, const int awaymsg_len);
     1076/* 0x0004 */ faim_export int aim_locate_setcaps(aim_session_t *sess, fu32_t caps);
     1077/* 0x0005 */ faim_export int aim_locate_getinfo(aim_session_t *sess, const char *, fu16_t);
     1078/* 0x0009 */ faim_export int aim_locate_setdirinfo(aim_session_t *sess, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, fu16_t privacy);
     1079/* 0x000b */ faim_export int aim_locate_000b(aim_session_t *sess, const char *sn);
     1080/* 0x000f */ faim_export int aim_locate_setinterests(aim_session_t *sess, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, fu16_t privacy);
     1081/* 0x0015 */ faim_export int aim_locate_getinfoshort(aim_session_t *sess, const char *sn, fu32_t flags);
    10611082
    10621083
    10631084
    10641085/* 0x0003 - buddylist.c */
    1065 /* 0x0004 */ faim_export int aim_add_buddy(aim_session_t *, aim_conn_t *, const char *);
    1066 /* 0x0005 */ faim_export int aim_remove_buddy(aim_session_t *, aim_conn_t *, const char *);
    1067 /* 0x000b */ faim_export int aim_sendbuddyoncoming(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *info);
    1068 /* 0x000c */ faim_export int aim_sendbuddyoffgoing(aim_session_t *sess, aim_conn_t *conn, const char *sn);
     1086/* 0x0002 */ faim_export int aim_buddylist_reqrights(aim_session_t *, aim_conn_t *);
     1087/* 0x0004 */ faim_export int aim_buddylist_set(aim_session_t *, aim_conn_t *, const char *);
     1088/* 0x0004 */ faim_export int aim_buddylist_addbuddy(aim_session_t *, aim_conn_t *, const char *);
     1089/* 0x0005 */ faim_export int aim_buddylist_removebuddy(aim_session_t *, aim_conn_t *, const char *);
     1090/* 0x000b */ faim_export int aim_buddylist_oncoming(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *info);
     1091/* 0x000c */ faim_export int aim_buddylist_offgoing(aim_session_t *sess, aim_conn_t *conn, const char *sn);
    10691092
    10701093
     
    11941217faim_export fu32_t aim_ssi_getpresence(struct aim_ssi_item *list);
    11951218faim_export char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *sn);
     1219faim_export char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *sn);
    11961220faim_export int aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *sn);
    11971221
     
    12051229faim_export int aim_ssi_movebuddy(aim_session_t *sess, const char *oldgn, const char *newgn, const char *sn);
    12061230faim_export int aim_ssi_aliasbuddy(aim_session_t *sess, const char *gn, const char *sn, const char *alias);
     1231faim_export int aim_ssi_editcomment(aim_session_t *sess, const char *gn, const char *sn, const char *alias);
    12071232faim_export int aim_ssi_rename_group(aim_session_t *sess, const char *oldgn, const char *newgn);
    12081233faim_export int aim_ssi_cleanlist(aim_session_t *sess);
     
    12111236faim_export int aim_ssi_setpresence(aim_session_t *sess, fu32_t presence);
    12121237faim_export int aim_ssi_seticon(aim_session_t *sess, fu8_t *iconsum, fu16_t iconsumlen);
     1238faim_export int aim_ssi_delicon(aim_session_t *sess);
    12131239
    12141240
     
    13261352};
    13271353
    1328 faim_export int aim_email_sendcookies(aim_session_t *sess, aim_conn_t *conn);
    1329 faim_export int aim_email_activate(aim_session_t *sess, aim_conn_t *conn);
    1330 
    1331 
    1332 
     1354faim_export int aim_email_sendcookies(aim_session_t *sess);
     1355faim_export int aim_email_activate(aim_session_t *sess);
     1356
     1357
     1358
     1359#if defined(FAIM_INTERNAL) || defined(FAIM_NEED_TLV)
    13331360/* tlv.c - TLV handling */
    1334 #if defined(FAIM_INTERNAL) || defined(FAIM_NEED_TLV)
    1335 /* Generic TLV structure. */
     1361
     1362/* TLV structure */
    13361363typedef struct aim_tlv_s {
    13371364        fu16_t type;
     
    13401367} aim_tlv_t;
    13411368
    1342 /* List of above. */
     1369/* TLV List structure */
    13431370typedef struct aim_tlvlist_s {
    13441371        aim_tlv_t *tlv;
     
    13461373} aim_tlvlist_t;
    13471374
    1348 /* TLV-handling functions */
    1349 
    1350 #if 0
    1351 /* Very, very raw TLV handling. */
    1352 faim_internal int aim_puttlv_8(fu8_t *buf, const fu16_t t, const fu8_t v);
    1353 faim_internal int aim_puttlv_16(fu8_t *buf, const fu16_t t, const fu16_t v);
    1354 faim_internal int aim_puttlv_32(fu8_t *buf, const fu16_t t, const fu32_t v);
    1355 faim_internal int aim_puttlv_raw(fu8_t *buf, const fu16_t t, const fu16_t l, const fu8_t *v);
    1356 #endif
    1357 
    1358 /* TLV list handling. */
    1359 faim_internal aim_tlvlist_t *aim_readtlvchain(aim_bstream_t *bs);
    1360 faim_internal aim_tlvlist_t *aim_readtlvchain_num(aim_bstream_t *bs, fu16_t num);
    1361 faim_internal aim_tlvlist_t *aim_readtlvchain_len(aim_bstream_t *bs, fu16_t len);
     1375/* TLV handling functions */
     1376faim_internal aim_tlv_t *aim_tlv_gettlv(aim_tlvlist_t *list, fu16_t type, const int nth);
     1377faim_internal char *aim_tlv_getstr(aim_tlvlist_t *list, const fu16_t type, const int nth);
     1378faim_internal fu8_t aim_tlv_get8(aim_tlvlist_t *list, const fu16_t type, const int nth);
     1379faim_internal fu16_t aim_tlv_get16(aim_tlvlist_t *list, const fu16_t type, const int nth);
     1380faim_internal fu32_t aim_tlv_get32(aim_tlvlist_t *list, const fu16_t type, const int nth);
     1381
     1382/* TLV list handling functions */
     1383faim_internal aim_tlvlist_t *aim_tlvlist_read(aim_bstream_t *bs);
     1384faim_internal aim_tlvlist_t *aim_tlvlist_readnum(aim_bstream_t *bs, fu16_t num);
     1385faim_internal aim_tlvlist_t *aim_tlvlist_readlen(aim_bstream_t *bs, fu16_t len);
    13621386faim_internal aim_tlvlist_t *aim_tlvlist_copy(aim_tlvlist_t *orig);
     1387
     1388faim_internal int aim_tlvlist_count(aim_tlvlist_t **list);
     1389faim_internal int aim_tlvlist_size(aim_tlvlist_t **list);
    13631390faim_internal int aim_tlvlist_cmp(aim_tlvlist_t *one, aim_tlvlist_t *two);
    1364 faim_internal void aim_freetlvchain(aim_tlvlist_t **list);
    1365 faim_internal aim_tlv_t *aim_gettlv(aim_tlvlist_t *, fu16_t t, const int n);
    1366 faim_internal char *aim_gettlv_str(aim_tlvlist_t *, const fu16_t t, const int n);
    1367 faim_internal fu8_t aim_gettlv8(aim_tlvlist_t *list, const fu16_t type, const int num);
    1368 faim_internal fu16_t aim_gettlv16(aim_tlvlist_t *list, const fu16_t t, const int n);
    1369 faim_internal fu32_t aim_gettlv32(aim_tlvlist_t *list, const fu16_t t, const int n);
    1370 faim_internal int aim_writetlvchain(aim_bstream_t *bs, aim_tlvlist_t **list);
    1371 faim_internal int aim_addtlvtochain8(aim_tlvlist_t **list, const fu16_t t, const fu8_t v);
    1372 faim_internal int aim_addtlvtochain16(aim_tlvlist_t **list, const fu16_t t, const fu16_t v);
    1373 faim_internal int aim_addtlvtochain32(aim_tlvlist_t **list, const fu16_t type, const fu32_t v);
    1374 faim_internal int aim_addtlvtochain_raw(aim_tlvlist_t **list, const fu16_t t, const fu16_t l, const fu8_t *v);
    1375 faim_internal int aim_addtlvtochain_caps(aim_tlvlist_t **list, const fu16_t t, const fu32_t caps);
    1376 faim_internal int aim_addtlvtochain_noval(aim_tlvlist_t **list, const fu16_t type);
    1377 faim_internal int aim_addtlvtochain_userinfo(aim_tlvlist_t **list, fu16_t type, aim_userinfo_t *ui);
    1378 faim_internal int aim_addtlvtochain_frozentlvlist(aim_tlvlist_t **list, fu16_t type, aim_tlvlist_t **tl);
    1379 faim_internal int aim_counttlvchain(aim_tlvlist_t **list);
    1380 faim_internal int aim_sizetlvchain(aim_tlvlist_t **list);
     1391faim_internal int aim_tlvlist_write(aim_bstream_t *bs, aim_tlvlist_t **list);
     1392faim_internal void aim_tlvlist_free(aim_tlvlist_t **list);
     1393
     1394faim_internal int aim_tlvlist_add_raw(aim_tlvlist_t **list, const fu16_t type, const fu16_t length, const fu8_t *value);
     1395faim_internal int aim_tlvlist_add_noval(aim_tlvlist_t **list, const fu16_t type);
     1396faim_internal int aim_tlvlist_add_8(aim_tlvlist_t **list, const fu16_t type, const fu8_t value);
     1397faim_internal int aim_tlvlist_add_16(aim_tlvlist_t **list, const fu16_t type, const fu16_t value);
     1398faim_internal int aim_tlvlist_add_32(aim_tlvlist_t **list, const fu16_t type, const fu32_t value);
     1399faim_internal int aim_tlvlist_add_caps(aim_tlvlist_t **list, const fu16_t type, const fu32_t caps);
     1400faim_internal int aim_tlvlist_add_userinfo(aim_tlvlist_t **list, fu16_t type, aim_userinfo_t *userinfo);
     1401faim_internal int aim_tlvlist_add_frozentlvlist(aim_tlvlist_t **list, fu16_t type, aim_tlvlist_t **tl);
     1402
     1403faim_internal int aim_tlvlist_replace_raw(aim_tlvlist_t **list, const fu16_t type, const fu16_t lenth, const fu8_t *value);
     1404faim_internal int aim_tlvlist_replace_noval(aim_tlvlist_t **list, const fu16_t type);
     1405faim_internal int aim_tlvlist_replace_8(aim_tlvlist_t **list, const fu16_t type, const fu8_t value);
     1406faim_internal int aim_tlvlist_replace_16(aim_tlvlist_t **list, const fu16_t type, const fu16_t value);
     1407faim_internal int aim_tlvlist_replace_32(aim_tlvlist_t **list, const fu16_t type, const fu32_t value);
     1408
     1409faim_internal void aim_tlvlist_remove(aim_tlvlist_t **list, const fu16_t type);
    13811410#endif /* FAIM_INTERNAL */
    13821411
  • libfaim/aim_cbtypes.h

    ra0a5179 rcf02dd6  
    212212#define AIM_CB_SSI_REQDATA 0x0004
    213213#define AIM_CB_SSI_REQIFCHANGED 0x0005
    214 #define AIM_CB_SSI_REQLIST 0x0005
    215214#define AIM_CB_SSI_LIST 0x0006
    216215#define AIM_CB_SSI_ACTIVATE 0x0007
  • libfaim/aim_internal.h

    re374dee rcf02dd6  
    4747faim_internal int chat_modfirst(aim_session_t *sess, aim_module_t *mod);
    4848faim_internal int locate_modfirst(aim_session_t *sess, aim_module_t *mod);
    49 faim_internal int general_modfirst(aim_session_t *sess, aim_module_t *mod);
     49faim_internal int service_modfirst(aim_session_t *sess, aim_module_t *mod);
    5050faim_internal int invite_modfirst(aim_session_t *sess, aim_module_t *mod);
    5151faim_internal int translate_modfirst(aim_session_t *sess, aim_module_t *mod);
     
    189189faim_internal void aim_conn_addgroup(aim_conn_t *conn, fu16_t group);
    190190
    191 faim_internal fu32_t aim_getcap(aim_session_t *sess, aim_bstream_t *bs, int len);
    192 faim_internal int aim_putcap(aim_bstream_t *bs, fu32_t caps);
    193 
    194191faim_internal int aim_cachecookie(aim_session_t *sess, aim_msgcookie_t *cookie);
    195192faim_internal aim_msgcookie_t *aim_uncachecookie(aim_session_t *sess, fu8_t *cookie, int type);
     
    200197faim_internal int aim_cookie_free(aim_session_t *sess, aim_msgcookie_t *cookie);
    201198
     199/* 0x0002 - locate.c */
     200faim_internal void aim_locate_requestuserinfo(aim_session_t *sess, const char *sn);
     201faim_internal fu32_t aim_locate_getcaps(aim_session_t *sess, aim_bstream_t *bs, int len);
     202faim_internal fu32_t aim_locate_getcaps_short(aim_session_t *sess, aim_bstream_t *bs, int len);
     203faim_internal int aim_putcap(aim_bstream_t *bs, fu32_t caps);
    202204faim_internal void aim_info_free(aim_userinfo_t *);
    203205faim_internal int aim_info_extract(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *);
     
    205207
    206208faim_internal int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo);
    207 
    208 faim_internal void faimdprintf(aim_session_t *sess, int dlevel, const char *format, ...);
    209209
    210210faim_internal void aim_conn_kill_chat(aim_session_t *sess, aim_conn_t *conn);
     
    216216faim_internal int aim_rates_delparam(aim_session_t *, aim_conn_t *);
    217217
     218faim_internal void faimdprintf(aim_session_t *sess, int dlevel, const char *format, ...);
     219
    218220#ifndef FAIM_INTERNAL_INSANE
    219221#define printf() printf called inside libfaim
  • libfaim/auth.c

    re374dee rcf02dd6  
    1212#include "md5.h"
    1313
    14 static int aim_encode_password(const char *password, fu8_t *encoded);
    15 
    16 /*
     14#include <ctype.h>
     15
     16/**
     17 * Encode a password using old XOR method
     18 *
     19 * This takes a const pointer to a (null terminated) string
     20 * containing the unencoded password.  It also gets passed
     21 * an already allocated buffer to store the encoded password.
     22 * This buffer should be the exact length of the password without
     23 * the null.  The encoded password buffer /is not %NULL terminated/.
     24 *
     25 * The encoding_table seems to be a fixed set of values.  We'll
     26 * hope it doesn't change over time! 
     27 *
     28 * This is only used for the XOR method, not the better MD5 method.
     29 *
     30 * @param password Incoming password.
     31 * @param encoded Buffer to put encoded password.
     32 */
     33static int aim_encode_password(const char *password, fu8_t *encoded)
     34{
     35        fu8_t encoding_table[] = {
     36#if 0 /* old v1 table */
     37                0xf3, 0xb3, 0x6c, 0x99,
     38                0x95, 0x3f, 0xac, 0xb6,
     39                0xc5, 0xfa, 0x6b, 0x63,
     40                0x69, 0x6c, 0xc3, 0x9f
     41#else /* v2.1 table, also works for ICQ */
     42                0xf3, 0x26, 0x81, 0xc4,
     43                0x39, 0x86, 0xdb, 0x92,
     44                0x71, 0xa3, 0xb9, 0xe6,
     45                0x53, 0x7a, 0x95, 0x7c
     46#endif
     47        };
     48        int i;
     49
     50        for (i = 0; i < strlen(password); i++)
     51                encoded[i] = (password[i] ^ encoding_table[i]);
     52
     53        return 0;
     54}
     55
     56#ifdef USE_OLD_MD5
     57static int aim_encode_password_md5(const char *password, const char *key, fu8_t *digest)
     58{
     59        md5_state_t state;
     60
     61        md5_init(&state);       
     62        md5_append(&state, (const md5_byte_t *)key, strlen(key));
     63        md5_append(&state, (const md5_byte_t *)password, strlen(password));
     64        md5_append(&state, (const md5_byte_t *)AIM_MD5_STRING, strlen(AIM_MD5_STRING));
     65        md5_finish(&state, (md5_byte_t *)digest);
     66
     67        return 0;
     68}
     69#else
     70static int aim_encode_password_md5(const char *password, const char *key, fu8_t *digest)
     71{
     72        md5_state_t state;
     73        fu8_t passdigest[16];
     74
     75        md5_init(&state);
     76        md5_append(&state, (const md5_byte_t *)password, strlen(password));
     77        md5_finish(&state, (md5_byte_t *)&passdigest);
     78
     79        md5_init(&state);       
     80        md5_append(&state, (const md5_byte_t *)key, strlen(key));
     81        md5_append(&state, (const md5_byte_t *)&passdigest, 16);
     82        md5_append(&state, (const md5_byte_t *)AIM_MD5_STRING, strlen(AIM_MD5_STRING));
     83        md5_finish(&state, (md5_byte_t *)digest);
     84
     85        return 0;
     86}
     87#endif
     88
     89/*
     90 * The FLAP version is sent by itself at the beginning of authorization
     91 * connections.  The FLAP version is also sent before the cookie when connecting
     92 * for other services (BOS, chatnav, chat, etc.).
     93 */
     94faim_export int aim_sendflapver(aim_session_t *sess, aim_conn_t *conn)
     95{
     96        aim_frame_t *fr;
     97
     98        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 4)))
     99                return -ENOMEM;
     100
     101        aimbs_put32(&fr->data, 0x00000001);
     102
     103        aim_tx_enqueue(sess, fr);
     104
     105        return 0;
     106}
     107
     108/*
    17109 * This just pushes the passed cookie onto the passed connection, without
    18110 * the SNAC header or any of that.
     
    31123
    32124        aimbs_put32(&fr->data, 0x00000001);
    33         aim_addtlvtochain_raw(&tl, 0x0006, length, chipsahoy);
    34         aim_writetlvchain(&fr->data, &tl);
    35         aim_freetlvchain(&tl);
    36 
    37         aim_tx_enqueue(sess, fr);
    38 
    39         return 0;
    40 }
    41 
    42 /*
    43  * Normally the FLAP version is sent as the first few bytes of the cookie,
    44  * meaning you generally never call this.
    45  *
    46  * But there are times when something might want it seperate. Specifically,
    47  * libfaim sends this internally when doing SNAC login.
    48  *
    49  */
    50 faim_export int aim_sendflapver(aim_session_t *sess, aim_conn_t *conn)
    51 {
    52         aim_frame_t *fr;
    53 
    54         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 4)))
    55                 return -ENOMEM;
    56 
    57         aimbs_put32(&fr->data, 0x00000001);
    58 
    59         aim_tx_enqueue(sess, fr);
    60 
    61         return 0;
    62 }
    63 
    64 /*
    65  * This is a bit confusing.
    66  *
    67  * Normal SNAC login goes like this:
    68  *   - connect
    69  *   - server sends flap version
    70  *   - client sends flap version
    71  *   - client sends screen name (17/6)
    72  *   - server sends hash key (17/7)
    73  *   - client sends auth request (17/2 -- aim_send_login)
    74  *   - server yells
    75  *
    76  * XOR login (for ICQ) goes like this:
    77  *   - connect
    78  *   - server sends flap version
    79  *   - client sends auth request which contains flap version (aim_send_login)
    80  *   - server yells
    81  *
    82  * For the client API, we make them implement the most complicated version,
    83  * and for the simpler version, we fake it and make it look like the more
    84  * complicated process.
    85  *
    86  * This is done by giving the client a faked key, just so we can convince
    87  * them to call aim_send_login right away, which will detect the session
    88  * flag that says this is XOR login and ignore the key, sending an ICQ
    89  * login request instead of the normal SNAC one.
    90  *
    91  * As soon as AOL makes ICQ log in the same way as AIM, this is /gone/.
    92  *
    93  * XXX This may cause problems if the client relies on callbacks only
    94  * being called from the context of aim_rxdispatch()...
    95  *
    96  */
    97 static int goddamnicq(aim_session_t *sess, aim_conn_t *conn, const char *sn)
    98 {
    99         aim_frame_t fr;
    100         aim_rxcallback_t userfunc;
    101        
    102         sess->flags &= ~AIM_SESS_FLAGS_SNACLOGIN;
    103         sess->flags |= AIM_SESS_FLAGS_XORLOGIN;
    104 
    105         fr.conn = conn;
    106        
    107         if ((userfunc = aim_callhandler(sess, conn, 0x0017, 0x0007)))
    108                 userfunc(sess, &fr, "");
    109 
    110         return 0;
    111 }
    112 
    113 /*
    114  * In AIM 3.5 protocol, the first stage of login is to request login from the
    115  * Authorizer, passing it the screen name for verification.  If the name is
    116  * invalid, a 0017/0003 is spit back, with the standard error contents.  If
    117  * valid, a 0017/0007 comes back, which is the signal to send it the main
    118  * login command (0017/0002).
    119  *
    120  */
    121 faim_export int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn)
    122 {
    123         aim_frame_t *fr;
    124         aim_snacid_t snacid;
    125         aim_tlvlist_t *tl = NULL;
    126        
    127         if (!sess || !conn || !sn)
    128                 return -EINVAL;
    129 
    130         if ((sn[0] >= '0') && (sn[0] <= '9'))
    131                 return goddamnicq(sess, conn, sn);
    132 
    133         sess->flags |= AIM_SESS_FLAGS_SNACLOGIN;
    134 
    135         aim_sendflapver(sess, conn);
    136 
    137         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(sn))))
    138                 return -ENOMEM;
    139 
    140         snacid = aim_cachesnac(sess, 0x0017, 0x0006, 0x0000, NULL, 0);
    141         aim_putsnac(&fr->data, 0x0017, 0x0006, 0x0000, snacid);
    142 
    143         aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), sn);
    144         aim_writetlvchain(&fr->data, &tl);
    145         aim_freetlvchain(&tl);
     125        aim_tlvlist_add_raw(&tl, 0x0006, length, chipsahoy);
     126        aim_tlvlist_write(&fr->data, &tl);
     127        aim_tlvlist_free(&tl);
    146128
    147129        aim_tx_enqueue(sess, fr);
     
    174156
    175157        aimbs_put32(&fr->data, 0x00000001); /* FLAP Version */
    176         aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), sn);
    177         aim_addtlvtochain_raw(&tl, 0x0002, passwdlen, password_encoded);
     158        aim_tlvlist_add_raw(&tl, 0x0001, strlen(sn), sn);
     159        aim_tlvlist_add_raw(&tl, 0x0002, passwdlen, password_encoded);
    178160
    179161        if (ci->clientstring)
    180                 aim_addtlvtochain_raw(&tl, 0x0003, strlen(ci->clientstring), ci->clientstring);
    181         aim_addtlvtochain16(&tl, 0x0016, (fu16_t)ci->clientid);
    182         aim_addtlvtochain16(&tl, 0x0017, (fu16_t)ci->major);
    183         aim_addtlvtochain16(&tl, 0x0018, (fu16_t)ci->minor);
    184         aim_addtlvtochain16(&tl, 0x0019, (fu16_t)ci->point);
    185         aim_addtlvtochain16(&tl, 0x001a, (fu16_t)ci->build);
    186         aim_addtlvtochain32(&tl, 0x0014, (fu32_t)ci->distrib); /* distribution chan */
    187         aim_addtlvtochain_raw(&tl, 0x000f, strlen(ci->lang), ci->lang);
    188         aim_addtlvtochain_raw(&tl, 0x000e, strlen(ci->country), ci->country);
    189 
    190         aim_writetlvchain(&fr->data, &tl);
     162                aim_tlvlist_add_raw(&tl, 0x0003, strlen(ci->clientstring), ci->clientstring);
     163        aim_tlvlist_add_16(&tl, 0x0016, (fu16_t)ci->clientid);
     164        aim_tlvlist_add_16(&tl, 0x0017, (fu16_t)ci->major);
     165        aim_tlvlist_add_16(&tl, 0x0018, (fu16_t)ci->minor);
     166        aim_tlvlist_add_16(&tl, 0x0019, (fu16_t)ci->point);
     167        aim_tlvlist_add_16(&tl, 0x001a, (fu16_t)ci->build);
     168        aim_tlvlist_add_32(&tl, 0x0014, (fu32_t)ci->distrib); /* distribution chan */
     169        aim_tlvlist_add_raw(&tl, 0x000f, strlen(ci->lang), ci->lang);
     170        aim_tlvlist_add_raw(&tl, 0x000e, strlen(ci->country), ci->country);
     171
     172        aim_tlvlist_write(&fr->data, &tl);
    191173
    192174        free(password_encoded);
    193         aim_freetlvchain(&tl);
     175        aim_tlvlist_free(&tl);
    194176
    195177        aim_tx_enqueue(sess, fr);
     
    199181
    200182/*
    201  * send_login(int socket, char *sn, char *password)
    202  * 
     183 * Subtype 0x0002
     184 *
    203185 * This is the initial login request packet.
    204186 *
     
    237219                return -EINVAL;
    238220
    239         /*
    240          * What the XORLOGIN flag _really_ means is that its an ICQ login,
    241          * which is really stupid and painful, so its not done here.
    242          *
    243          */
    244         if (sess->flags & AIM_SESS_FLAGS_XORLOGIN)
     221        /* If we're signing on an ICQ account then use the older, XOR login method */
     222        if (isdigit(sn[0]))
    245223                return goddamnicq2(sess, conn, sn, password, ci);
    246 
    247224
    248225        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152)))
     
    252229        aim_putsnac(&fr->data, 0x0017, 0x0002, 0x0000, snacid);
    253230
    254         aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), sn);
     231        aim_tlvlist_add_raw(&tl, 0x0001, strlen(sn), sn);
    255232
    256233        aim_encode_password_md5(password, key, digest);
    257         aim_addtlvtochain_raw(&tl, 0x0025, 16, digest);
    258 
    259         /*
    260          * Newer versions of winaim have an empty type x004c TLV here.
    261          */
     234        aim_tlvlist_add_raw(&tl, 0x0025, 16, digest);
     235
     236#ifndef USE_OLD_MD5
     237        aim_tlvlist_add_noval(&tl, 0x004c);
     238#endif
    262239
    263240        if (ci->clientstring)
    264                 aim_addtlvtochain_raw(&tl, 0x0003, strlen(ci->clientstring), ci->clientstring);
    265         aim_addtlvtochain16(&tl, 0x0016, (fu16_t)ci->clientid);
    266         aim_addtlvtochain16(&tl, 0x0017, (fu16_t)ci->major);
    267         aim_addtlvtochain16(&tl, 0x0018, (fu16_t)ci->minor);
    268         aim_addtlvtochain16(&tl, 0x0019, (fu16_t)ci->point);
    269         aim_addtlvtochain16(&tl, 0x001a, (fu16_t)ci->build);
    270         aim_addtlvtochain32(&tl, 0x0014, (fu32_t)ci->distrib);
    271         aim_addtlvtochain_raw(&tl, 0x000e, strlen(ci->country), ci->country);
    272         aim_addtlvtochain_raw(&tl, 0x000f, strlen(ci->lang), ci->lang);
     241                aim_tlvlist_add_raw(&tl, 0x0003, strlen(ci->clientstring), ci->clientstring);
     242        aim_tlvlist_add_16(&tl, 0x0016, (fu16_t)ci->clientid);
     243        aim_tlvlist_add_16(&tl, 0x0017, (fu16_t)ci->major);
     244        aim_tlvlist_add_16(&tl, 0x0018, (fu16_t)ci->minor);
     245        aim_tlvlist_add_16(&tl, 0x0019, (fu16_t)ci->point);
     246        aim_tlvlist_add_16(&tl, 0x001a, (fu16_t)ci->build);
     247        aim_tlvlist_add_32(&tl, 0x0014, (fu32_t)ci->distrib);
     248        aim_tlvlist_add_raw(&tl, 0x000f, strlen(ci->lang), ci->lang);
     249        aim_tlvlist_add_raw(&tl, 0x000e, strlen(ci->country), ci->country);
    273250
    274251#ifndef NOSSI
     
    277254         * to use SSI.
    278255         */
    279         aim_addtlvtochain8(&tl, 0x004a, 0x01);
     256        aim_tlvlist_add_8(&tl, 0x004a, 0x01);
    280257#endif
    281258
    282         aim_writetlvchain(&fr->data, &tl);
    283 
    284         aim_freetlvchain(&tl);
     259        aim_tlvlist_write(&fr->data, &tl);
     260
     261        aim_tlvlist_free(&tl);
    285262       
    286263        aim_tx_enqueue(sess, fr);
    287 
    288         return 0;
    289 }
    290 
    291 faim_export int aim_encode_password_md5(const char *password, const char *key, fu8_t *digest)
    292 {
    293         md5_state_t state;
    294 
    295         md5_init(&state);       
    296         md5_append(&state, (const md5_byte_t *)key, strlen(key));
    297         md5_append(&state, (const md5_byte_t *)password, strlen(password));
    298         md5_append(&state, (const md5_byte_t *)AIM_MD5_STRING, strlen(AIM_MD5_STRING));
    299         md5_finish(&state, (md5_byte_t *)digest);
    300 
    301         return 0;
    302 }
    303 
    304 /**
    305  * aim_encode_password - Encode a password using old XOR method
    306  * @password: incoming password
    307  * @encoded: buffer to put encoded password
    308  *
    309  * This takes a const pointer to a (null terminated) string
    310  * containing the unencoded password.  It also gets passed
    311  * an already allocated buffer to store the encoded password.
    312  * This buffer should be the exact length of the password without
    313  * the null.  The encoded password buffer /is not %NULL terminated/.
    314  *
    315  * The encoding_table seems to be a fixed set of values.  We'll
    316  * hope it doesn't change over time! 
    317  *
    318  * This is only used for the XOR method, not the better MD5 method.
    319  *
    320  */
    321 static int aim_encode_password(const char *password, fu8_t *encoded)
    322 {
    323         fu8_t encoding_table[] = {
    324 #if 0 /* old v1 table */
    325                 0xf3, 0xb3, 0x6c, 0x99,
    326                 0x95, 0x3f, 0xac, 0xb6,
    327                 0xc5, 0xfa, 0x6b, 0x63,
    328                 0x69, 0x6c, 0xc3, 0x9f
    329 #else /* v2.1 table, also works for ICQ */
    330                 0xf3, 0x26, 0x81, 0xc4,
    331                 0x39, 0x86, 0xdb, 0x92,
    332                 0x71, 0xa3, 0xb9, 0xe6,
    333                 0x53, 0x7a, 0x95, 0x7c
    334 #endif
    335         };
    336         int i;
    337 
    338         for (i = 0; i < strlen(password); i++)
    339                 encoded[i] = (password[i] ^ encoding_table[i]);
    340264
    341265        return 0;
     
    349273 * The client should check the value passed as errorcode. If
    350274 * its nonzero, there was an error.
    351  *
    352275 */
    353276static int parse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
     
    365288         * from what is parsed here.
    366289         */
    367         tlvlist = aim_readtlvchain(bs);
     290        tlvlist = aim_tlvlist_read(bs);
    368291
    369292        /*
     
    371294         */
    372295        memset(sess->sn, 0, sizeof(sess->sn));
    373         if (aim_gettlv(tlvlist, 0x0001, 1)) {
    374                 info->sn = aim_gettlv_str(tlvlist, 0x0001, 1);
     296        if (aim_tlv_gettlv(tlvlist, 0x0001, 1)) {
     297                info->sn = aim_tlv_getstr(tlvlist, 0x0001, 1);
    375298                strncpy(sess->sn, info->sn, sizeof(sess->sn));
    376299        }
     
    380303         * have an error url.
    381304         */
    382         if (aim_gettlv(tlvlist, 0x0008, 1))
    383                 info->errorcode = aim_gettlv16(tlvlist, 0x0008, 1);
    384         if (aim_gettlv(tlvlist, 0x0004, 1))
    385                 info->errorurl = aim_gettlv_str(tlvlist, 0x0004, 1);
     305        if (aim_tlv_gettlv(tlvlist, 0x0008, 1))
     306                info->errorcode = aim_tlv_get16(tlvlist, 0x0008, 1);
     307        if (aim_tlv_gettlv(tlvlist, 0x0004, 1))
     308                info->errorurl = aim_tlv_getstr(tlvlist, 0x0004, 1);
    386309
    387310        /*
    388311         * BOS server address.
    389312         */
    390         if (aim_gettlv(tlvlist, 0x0005, 1))
    391                 info->bosip = aim_gettlv_str(tlvlist, 0x0005, 1);
     313        if (aim_tlv_gettlv(tlvlist, 0x0005, 1))
     314                info->bosip = aim_tlv_getstr(tlvlist, 0x0005, 1);
    392315
    393316        /*
    394317         * Authorization cookie.
    395318         */
    396         if (aim_gettlv(tlvlist, 0x0006, 1)) {
     319        if (aim_tlv_gettlv(tlvlist, 0x0006, 1)) {
    397320                aim_tlv_t *tmptlv;
    398321
    399                 tmptlv = aim_gettlv(tlvlist, 0x0006, 1);
     322                tmptlv = aim_tlv_gettlv(tlvlist, 0x0006, 1);
    400323
    401324                info->cookielen = tmptlv->length;
     
    410333         * XXX - Not really true!
    411334         */
    412         if (aim_gettlv(tlvlist, 0x0011, 1))
    413                 info->email = aim_gettlv_str(tlvlist, 0x0011, 1);
     335        if (aim_tlv_gettlv(tlvlist, 0x0011, 1))
     336                info->email = aim_tlv_getstr(tlvlist, 0x0011, 1);
    414337
    415338        /*
     
    427350         *
    428351         */
    429         if (aim_gettlv(tlvlist, 0x0013, 1))
    430                 info->regstatus = aim_gettlv16(tlvlist, 0x0013, 1);
    431 
    432         if (aim_gettlv(tlvlist, 0x0040, 1))
    433                 info->latestbeta.build = aim_gettlv32(tlvlist, 0x0040, 1);
    434         if (aim_gettlv(tlvlist, 0x0041, 1))
    435                 info->latestbeta.url = aim_gettlv_str(tlvlist, 0x0041, 1);
    436         if (aim_gettlv(tlvlist, 0x0042, 1))
    437                 info->latestbeta.info = aim_gettlv_str(tlvlist, 0x0042, 1);
    438         if (aim_gettlv(tlvlist, 0x0043, 1))
    439                 info->latestbeta.name = aim_gettlv_str(tlvlist, 0x0043, 1);
    440         if (aim_gettlv(tlvlist, 0x0048, 1))
    441                 ; /* no idea what this is */
    442 
    443         if (aim_gettlv(tlvlist, 0x0044, 1))
    444                 info->latestrelease.build = aim_gettlv32(tlvlist, 0x0044, 1);
    445         if (aim_gettlv(tlvlist, 0x0045, 1))
    446                 info->latestrelease.url = aim_gettlv_str(tlvlist, 0x0045, 1);
    447         if (aim_gettlv(tlvlist, 0x0046, 1))
    448                 info->latestrelease.info = aim_gettlv_str(tlvlist, 0x0046, 1);
    449         if (aim_gettlv(tlvlist, 0x0047, 1))
    450                 info->latestrelease.name = aim_gettlv_str(tlvlist, 0x0047, 1);
    451         if (aim_gettlv(tlvlist, 0x0049, 1))
    452                 ; /* no idea what this is */
     352        if (aim_tlv_gettlv(tlvlist, 0x0013, 1))
     353                info->regstatus = aim_tlv_get16(tlvlist, 0x0013, 1);
     354
     355        if (aim_tlv_gettlv(tlvlist, 0x0040, 1))
     356                info->latestbeta.build = aim_tlv_get32(tlvlist, 0x0040, 1);
     357        if (aim_tlv_gettlv(tlvlist, 0x0041, 1))
     358                info->latestbeta.url = aim_tlv_getstr(tlvlist, 0x0041, 1);
     359        if (aim_tlv_gettlv(tlvlist, 0x0042, 1))
     360                info->latestbeta.info = aim_tlv_getstr(tlvlist, 0x0042, 1);
     361        if (aim_tlv_gettlv(tlvlist, 0x0043, 1))
     362                info->latestbeta.name = aim_tlv_getstr(tlvlist, 0x0043, 1);
     363        if (aim_tlv_gettlv(tlvlist, 0x0048, 1))
     364                ; /* beta serial */
     365
     366        if (aim_tlv_gettlv(tlvlist, 0x0044, 1))
     367                info->latestrelease.build = aim_tlv_get32(tlvlist, 0x0044, 1);
     368        if (aim_tlv_gettlv(tlvlist, 0x0045, 1))
     369                info->latestrelease.url = aim_tlv_getstr(tlvlist, 0x0045, 1);
     370        if (aim_tlv_gettlv(tlvlist, 0x0046, 1))
     371                info->latestrelease.info = aim_tlv_getstr(tlvlist, 0x0046, 1);
     372        if (aim_tlv_gettlv(tlvlist, 0x0047, 1))
     373                info->latestrelease.name = aim_tlv_getstr(tlvlist, 0x0047, 1);
     374        if (aim_tlv_gettlv(tlvlist, 0x0049, 1))
     375                ; /* lastest release serial */
    453376
    454377        /*
    455378         * URL to change password.
    456379         */
    457         if (aim_gettlv(tlvlist, 0x0054, 1))
    458                 info->chpassurl = aim_gettlv_str(tlvlist, 0x0054, 1);
     380        if (aim_tlv_gettlv(tlvlist, 0x0054, 1))
     381                info->chpassurl = aim_tlv_getstr(tlvlist, 0x0054, 1);
    459382
    460383        /*
    461384         * Unknown.  Seen on an @mac.com screen name with value of 0x003f
    462385         */
    463         if (aim_gettlv(tlvlist, 0x0055, 1))
     386        if (aim_tlv_gettlv(tlvlist, 0x0055, 1))
    464387                ;
    465388
     
    469392                ret = userfunc(sess, rx, info);
    470393
    471         aim_freetlvchain(&tlvlist);
     394        aim_tlvlist_free(&tlvlist);
    472395
    473396        return ret;
     
    475398
    476399/*
     400 * Subtype 0x0007 (kind of) - Send a fake type 0x0007 SNAC to the client
     401 *
     402 * This is a bit confusing.
     403 *
     404 * Normal SNAC login goes like this:
     405 *   - connect
     406 *   - server sends flap version
     407 *   - client sends flap version
     408 *   - client sends screen name (17/6)
     409 *   - server sends hash key (17/7)
     410 *   - client sends auth request (17/2 -- aim_send_login)
     411 *   - server yells
     412 *
     413 * XOR login (for ICQ) goes like this:
     414 *   - connect
     415 *   - server sends flap version
     416 *   - client sends auth request which contains flap version (aim_send_login)
     417 *   - server yells
     418 *
     419 * For the client API, we make them implement the most complicated version,
     420 * and for the simpler version, we fake it and make it look like the more
     421 * complicated process.
     422 *
     423 * This is done by giving the client a faked key, just so we can convince
     424 * them to call aim_send_login right away, which will detect the session
     425 * flag that says this is XOR login and ignore the key, sending an ICQ
     426 * login request instead of the normal SNAC one.
     427 *
     428 * As soon as AOL makes ICQ log in the same way as AIM, this is /gone/.
     429 *
     430 * XXX This may cause problems if the client relies on callbacks only
     431 * being called from the context of aim_rxdispatch()...
     432 *
     433 */
     434static int goddamnicq(aim_session_t *sess, aim_conn_t *conn, const char *sn)
     435{
     436        aim_frame_t fr;
     437        aim_rxcallback_t userfunc;
     438       
     439        fr.conn = conn;
     440       
     441        if ((userfunc = aim_callhandler(sess, conn, 0x0017, 0x0007)))
     442                userfunc(sess, &fr, "");
     443
     444        return 0;
     445}
     446
     447/*
     448 * Subtype 0x0006
     449 *
     450 * In AIM 3.5 protocol, the first stage of login is to request login from the
     451 * Authorizer, passing it the screen name for verification.  If the name is
     452 * invalid, a 0017/0003 is spit back, with the standard error contents.  If
     453 * valid, a 0017/0007 comes back, which is the signal to send it the main
     454 * login command (0017/0002).
     455 *
     456 */
     457faim_export int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn)
     458{
     459        aim_frame_t *fr;
     460        aim_snacid_t snacid;
     461        aim_tlvlist_t *tl = NULL;
     462       
     463        if (!sess || !conn || !sn)
     464                return -EINVAL;
     465
     466        if (isdigit(sn[0]))
     467                return goddamnicq(sess, conn, sn);
     468
     469        aim_sendflapver(sess, conn);
     470
     471        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(sn) /*+8*/ )))
     472                return -ENOMEM;
     473
     474        snacid = aim_cachesnac(sess, 0x0017, 0x0006, 0x0000, NULL, 0);
     475        aim_putsnac(&fr->data, 0x0017, 0x0006, 0x0000, snacid);
     476
     477        aim_tlvlist_add_raw(&tl, 0x0001, strlen(sn), sn);
     478/*      aim_tlvlist_add_noval(&tl, 0x004b);
     479        aim_tlvlist_add_noval(&tl, 0x005a); */
     480        aim_tlvlist_write(&fr->data, &tl);
     481        aim_tlvlist_free(&tl);
     482
     483        aim_tx_enqueue(sess, fr);
     484
     485        return 0;
     486}
     487
     488/*
     489 * Subtype 0x0007
     490 *
    477491 * Middle handler for 0017/0007 SNACs.  Contains the auth key prefixed
    478492 * by only its length in a two byte word.
  • libfaim/bos.c

    re374dee rcf02dd6  
    1313faim_export int aim_bos_reqrights(aim_session_t *sess, aim_conn_t *conn)
    1414{
    15         return aim_genericreq_n(sess, conn, 0x0009, 0x0002);
     15        return aim_genericreq_n_snacid(sess, conn, 0x0009, 0x0002);
    1616}
    1717
     
    2727         * TLVs follow
    2828         */
    29         tlvlist = aim_readtlvchain(bs);
     29        tlvlist = aim_tlvlist_read(bs);
    3030
    3131        /*
    3232         * TLV type 0x0001: Maximum number of buddies on permit list.
    3333         */
    34         if (aim_gettlv(tlvlist, 0x0001, 1))
    35                 maxpermits = aim_gettlv16(tlvlist, 0x0001, 1);
     34        if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
     35                maxpermits = aim_tlv_get16(tlvlist, 0x0001, 1);
    3636
    3737        /*
    3838         * TLV type 0x0002: Maximum number of buddies on deny list.
    3939         */
    40         if (aim_gettlv(tlvlist, 0x0002, 1))
    41                 maxdenies = aim_gettlv16(tlvlist, 0x0002, 1);
     40        if (aim_tlv_gettlv(tlvlist, 0x0002, 1))
     41                maxdenies = aim_tlv_get16(tlvlist, 0x0002, 1);
    4242
    4343        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    4444                ret = userfunc(sess, rx, maxpermits, maxdenies);
    4545
    46         aim_freetlvchain(&tlvlist);
     46        aim_tlvlist_free(&tlvlist);
    4747
    4848        return ret; 
  • libfaim/buddylist.c

    re374dee rcf02dd6  
    1515 *
    1616 */
    17 faim_export int aim_bos_reqbuddyrights(aim_session_t *sess, aim_conn_t *conn)
    18 {
    19         return aim_genericreq_n(sess, conn, 0x0003, 0x0002);
     17faim_export int aim_buddylist_reqrights(aim_session_t *sess, aim_conn_t *conn)
     18{
     19        return aim_genericreq_n_snacid(sess, conn, 0x0003, 0x0002);
    2020}
    2121
     
    3434         * TLVs follow
    3535         */
    36         tlvlist = aim_readtlvchain(bs);
     36        tlvlist = aim_tlvlist_read(bs);
    3737
    3838        /*
    3939         * TLV type 0x0001: Maximum number of buddies.
    4040         */
    41         if (aim_gettlv(tlvlist, 0x0001, 1))
    42                 maxbuddies = aim_gettlv16(tlvlist, 0x0001, 1);
     41        if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
     42                maxbuddies = aim_tlv_get16(tlvlist, 0x0001, 1);
    4343
    4444        /*
     
    5050         *
    5151         */
    52         if (aim_gettlv(tlvlist, 0x0002, 1))
    53                 maxwatchers = aim_gettlv16(tlvlist, 0x0002, 1);
     52        if (aim_tlv_gettlv(tlvlist, 0x0002, 1))
     53                maxwatchers = aim_tlv_get16(tlvlist, 0x0002, 1);
    5454
    5555        /*
     
    6262                ret = userfunc(sess, rx, maxbuddies, maxwatchers);
    6363
    64         aim_freetlvchain(&tlvlist);
     64        aim_tlvlist_free(&tlvlist);
    6565
    6666        return ret; 
     
    7474 *
    7575 */
    76 faim_export int aim_add_buddy(aim_session_t *sess, aim_conn_t *conn, const char *sn)
     76faim_export int aim_buddylist_addbuddy(aim_session_t *sess, aim_conn_t *conn, const char *sn)
    7777{
    7878        aim_frame_t *fr;
     
    106106 *
    107107 */
    108 faim_export int aim_bos_setbuddylist(aim_session_t *sess, aim_conn_t *conn, const char *buddy_list)
     108faim_export int aim_buddylist_set(aim_session_t *sess, aim_conn_t *conn, const char *buddy_list)
    109109{
    110110        aim_frame_t *fr;
     
    154154 *
    155155 */
    156 faim_export int aim_remove_buddy(aim_session_t *sess, aim_conn_t *conn, const char *sn)
     156faim_export int aim_buddylist_removebuddy(aim_session_t *sess, aim_conn_t *conn, const char *sn)
    157157{
    158158        aim_frame_t *fr;
     
    182182 *
    183183 */
    184 faim_export int aim_sendbuddyoncoming(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *info)
     184faim_export int aim_buddylist_oncoming(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *info)
    185185{
    186186        aim_frame_t *fr;
     
    209209 *
    210210 */
    211 faim_export int aim_sendbuddyoffgoing(aim_session_t *sess, aim_conn_t *conn, const char *sn)
     211faim_export int aim_buddylist_offgoing(aim_session_t *sess, aim_conn_t *conn, const char *sn)
    212212{
    213213        aim_frame_t *fr;
     
    253253                ret = userfunc(sess, rx, &userinfo);
    254254
     255        if (snac->subtype == 0x000b)
     256                aim_locate_requestuserinfo(sess, userinfo.sn);
    255257        aim_info_free(&userinfo);
    256258
  • libfaim/chat.c

    re374dee rcf02dd6  
    104104        aimbs_put16(&bs, instance);
    105105
    106         aim_addtlvtochain_raw(list, type, aim_bstream_curpos(&bs), buf);
     106        aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf);
    107107
    108108        free(buf);
     
    144144
    145145        aim_addtlvtochain_chatroom(&tl, 0x0001, exchange, roomname, instance);
    146         aim_writetlvchain(&fr->data, &tl);
    147         aim_freetlvchain(&tl);
     146        aim_tlvlist_write(&fr->data, &tl);
     147        aim_tlvlist_free(&tl);
    148148
    149149        aim_tx_enqueue(sess, fr);
     
    250250        aim_putcap(&hdrbs, AIM_CAPS_CHAT);
    251251
    252         aim_addtlvtochain16(&itl, 0x000a, 0x0001);
    253         aim_addtlvtochain_noval(&itl, 0x000f);
    254         aim_addtlvtochain_raw(&itl, 0x000c, strlen(msg), msg);
     252        aim_tlvlist_add_16(&itl, 0x000a, 0x0001);
     253        aim_tlvlist_add_noval(&itl, 0x000f);
     254        aim_tlvlist_add_raw(&itl, 0x000c, strlen(msg), msg);
    255255        aim_addtlvtochain_chatroom(&itl, 0x2711, exchange, roomname, instance);
    256         aim_writetlvchain(&hdrbs, &itl);
    257        
    258         aim_addtlvtochain_raw(&otl, 0x0005, aim_bstream_curpos(&hdrbs), hdr);
    259 
    260         aim_writetlvchain(&fr->data, &otl);
     256        aim_tlvlist_write(&hdrbs, &itl);
     257       
     258        aim_tlvlist_add_raw(&otl, 0x0005, aim_bstream_curpos(&hdrbs), hdr);
     259
     260        aim_tlvlist_write(&fr->data, &otl);
    261261
    262262        free(hdr);
    263         aim_freetlvchain(&itl);
    264         aim_freetlvchain(&otl);
     263        aim_tlvlist_free(&itl);
     264        aim_tlvlist_free(&otl);
    265265       
    266266        aim_tx_enqueue(sess, fr);
     
    308308         * Everything else are TLVs.
    309309         */
    310         tlvlist = aim_readtlvchain(bs);
     310        tlvlist = aim_tlvlist_read(bs);
    311311
    312312        /*
    313313         * TLV type 0x006a is the room name in Human Readable Form.
    314314         */
    315         if (aim_gettlv(tlvlist, 0x006a, 1))
    316                 roomname = aim_gettlv_str(tlvlist, 0x006a, 1);
     315        if (aim_tlv_gettlv(tlvlist, 0x006a, 1))
     316                roomname = aim_tlv_getstr(tlvlist, 0x006a, 1);
    317317
    318318        /*
    319319         * Type 0x006f: Number of occupants.
    320320         */
    321         if (aim_gettlv(tlvlist, 0x006f, 1))
    322                 usercount = aim_gettlv16(tlvlist, 0x006f, 1);
     321        if (aim_tlv_gettlv(tlvlist, 0x006f, 1))
     322                usercount = aim_tlv_get16(tlvlist, 0x006f, 1);
    323323
    324324        /*
    325325         * Type 0x0073:  Occupant list.
    326326         */
    327         if (aim_gettlv(tlvlist, 0x0073, 1)) {   
     327        if (aim_tlv_gettlv(tlvlist, 0x0073, 1)) {       
    328328                int curoccupant = 0;
    329329                aim_tlv_t *tmptlv;
    330330                aim_bstream_t occbs;
    331331
    332                 tmptlv = aim_gettlv(tlvlist, 0x0073, 1);
     332                tmptlv = aim_tlv_gettlv(tlvlist, 0x0073, 1);
    333333
    334334                /* Allocate enough userinfo structs for all occupants */
     
    344344         * Type 0x00c9: Flags. (AIM_CHATROOM_FLAG)
    345345         */
    346         if (aim_gettlv(tlvlist, 0x00c9, 1))
    347                 flags = aim_gettlv16(tlvlist, 0x00c9, 1);
     346        if (aim_tlv_gettlv(tlvlist, 0x00c9, 1))
     347                flags = aim_tlv_get16(tlvlist, 0x00c9, 1);
    348348
    349349        /*
    350350         * Type 0x00ca: Creation time (4 bytes)
    351351         */
    352         if (aim_gettlv(tlvlist, 0x00ca, 1))
    353                 creationtime = aim_gettlv32(tlvlist, 0x00ca, 1);
     352        if (aim_tlv_gettlv(tlvlist, 0x00ca, 1))
     353                creationtime = aim_tlv_get32(tlvlist, 0x00ca, 1);
    354354
    355355        /*
    356356         * Type 0x00d1: Maximum Message Length
    357357         */
    358         if (aim_gettlv(tlvlist, 0x00d1, 1))
    359                 maxmsglen = aim_gettlv16(tlvlist, 0x00d1, 1);
     358        if (aim_tlv_gettlv(tlvlist, 0x00d1, 1))
     359                maxmsglen = aim_tlv_get16(tlvlist, 0x00d1, 1);
    360360
    361361        /*
    362362         * Type 0x00d2: Unknown. (2 bytes)
    363363         */
    364         if (aim_gettlv(tlvlist, 0x00d2, 1))
    365                 unknown_d2 = aim_gettlv16(tlvlist, 0x00d2, 1);
     364        if (aim_tlv_gettlv(tlvlist, 0x00d2, 1))
     365                unknown_d2 = aim_tlv_get16(tlvlist, 0x00d2, 1);
    366366
    367367        /*
    368368         * Type 0x00d3: Room Description
    369369         */
    370         if (aim_gettlv(tlvlist, 0x00d3, 1))
    371                 roomdesc = aim_gettlv_str(tlvlist, 0x00d3, 1);
     370        if (aim_tlv_gettlv(tlvlist, 0x00d3, 1))
     371                roomdesc = aim_tlv_getstr(tlvlist, 0x00d3, 1);
    372372
    373373        /*
    374374         * Type 0x000d4: Unknown (flag only)
    375375         */
    376         if (aim_gettlv(tlvlist, 0x000d4, 1))
     376        if (aim_tlv_gettlv(tlvlist, 0x000d4, 1))
    377377                ;
    378378
     
    380380         * Type 0x00d5: Unknown. (1 byte)
    381381         */
    382         if (aim_gettlv(tlvlist, 0x00d5, 1))
    383                 unknown_d5 = aim_gettlv8(tlvlist, 0x00d5, 1);
     382        if (aim_tlv_gettlv(tlvlist, 0x00d5, 1))
     383                unknown_d5 = aim_tlv_get8(tlvlist, 0x00d5, 1);
    384384
    385385
     
    387387         * Type 0x00d6: Encoding 1 ("us-ascii")
    388388         */
    389         if (aim_gettlv(tlvlist, 0x000d6, 1))
     389        if (aim_tlv_gettlv(tlvlist, 0x000d6, 1))
    390390                ;
    391391       
     
    393393         * Type 0x00d7: Language 1 ("en")
    394394         */
    395         if (aim_gettlv(tlvlist, 0x000d7, 1))
     395        if (aim_tlv_gettlv(tlvlist, 0x000d7, 1))
    396396                ;
    397397
     
    399399         * Type 0x00d8: Encoding 2 ("us-ascii")
    400400         */
    401         if (aim_gettlv(tlvlist, 0x000d8, 1))
     401        if (aim_tlv_gettlv(tlvlist, 0x000d8, 1))
    402402                ;
    403403       
     
    405405         * Type 0x00d9: Language 2 ("en")
    406406         */
    407         if (aim_gettlv(tlvlist, 0x000d9, 1))
     407        if (aim_tlv_gettlv(tlvlist, 0x000d9, 1))
    408408                ;
    409409
     
    411411         * Type 0x00da: Maximum visible message length
    412412         */
    413         if (aim_gettlv(tlvlist, 0x000da, 1))
    414                 maxvisiblemsglen = aim_gettlv16(tlvlist, 0x00da, 1);
     413        if (aim_tlv_gettlv(tlvlist, 0x000da, 1))
     414                maxvisiblemsglen = aim_tlv_get16(tlvlist, 0x00da, 1);
    415415
    416416        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
     
    438438        free(roomname);
    439439        free(roomdesc);
    440         aim_freetlvchain(&tlvlist);
     440        aim_tlvlist_free(&tlvlist);
    441441
    442442        return ret;
     
    516516         * Type 1: Flag meaning this message is destined to the room.
    517517         */
    518         aim_addtlvtochain_noval(&otl, 0x0001);
     518        aim_tlvlist_add_noval(&otl, 0x0001);
    519519
    520520        /*
     
    522522         */
    523523        if (!(flags & AIM_CHATFLAGS_NOREFLECT))
    524                 aim_addtlvtochain_noval(&otl, 0x0006);
     524                aim_tlvlist_add_noval(&otl, 0x0006);
    525525
    526526        /*
     
    528528         */
    529529        if (flags & AIM_CHATFLAGS_AWAY)
    530                 aim_addtlvtochain_noval(&otl, 0x0007);
     530                aim_tlvlist_add_noval(&otl, 0x0007);
    531531
    532532        /*
    533533         * SubTLV: Type 1: Message
    534534         */
    535         aim_addtlvtochain_raw(&itl, 0x0001, msglen, msg);
     535        aim_tlvlist_add_raw(&itl, 0x0001, msglen, msg);
    536536
    537537        /*
     
    542542         *
    543543         */
    544         aim_addtlvtochain_frozentlvlist(&otl, 0x0005, &itl);
    545 
    546         aim_writetlvchain(&fr->data, &otl);
    547        
    548         aim_freetlvchain(&itl);
    549         aim_freetlvchain(&otl);
     544        aim_tlvlist_add_frozentlvlist(&otl, 0x0005, &itl);
     545
     546        aim_tlvlist_write(&fr->data, &otl);
     547       
     548        aim_tlvlist_free(&itl);
     549        aim_tlvlist_free(&otl);
    550550       
    551551        aim_tx_enqueue(sess, fr);
     
    621621         * Start parsing TLVs right away.
    622622         */
    623         otl = aim_readtlvchain(bs);
     623        otl = aim_tlvlist_read(bs);
    624624
    625625        /*
    626626         * Type 0x0003: Source User Information
    627627         */
    628         if (aim_gettlv(otl, 0x0003, 1)) {
     628        if (aim_tlv_gettlv(otl, 0x0003, 1)) {
    629629                aim_tlv_t *userinfotlv;
    630630                aim_bstream_t tbs;
    631631
    632                 userinfotlv = aim_gettlv(otl, 0x0003, 1);
     632                userinfotlv = aim_tlv_gettlv(otl, 0x0003, 1);
    633633
    634634                aim_bstream_init(&tbs, userinfotlv->value, userinfotlv->length);
     
    640640         * room (as opposed to a whisper).
    641641         */
    642         if (aim_gettlv(otl, 0x0001, 1))
     642        if (aim_tlv_gettlv(otl, 0x0001, 1))
    643643                ;
    644644
     
    646646         * Type 0x0005: Message Block.  Conains more TLVs.
    647647         */
    648         if (aim_gettlv(otl, 0x0005, 1)) {
     648        if (aim_tlv_gettlv(otl, 0x0005, 1)) {
    649649                aim_tlvlist_t *itl;
    650650                aim_tlv_t *msgblock;
    651651                aim_bstream_t tbs;
    652652
    653                 msgblock = aim_gettlv(otl, 0x0005, 1);
     653                msgblock = aim_tlv_gettlv(otl, 0x0005, 1);
    654654                aim_bstream_init(&tbs, msgblock->value, msgblock->length);
    655                 itl = aim_readtlvchain(&tbs);
     655                itl = aim_tlvlist_read(&tbs);
    656656
    657657                /*
    658658                 * Type 0x0001: Message.
    659659                 */     
    660                 if (aim_gettlv(itl, 0x0001, 1))
    661                         msg = aim_gettlv_str(itl, 0x0001, 1);
    662 
    663                 aim_freetlvchain(&itl);
     660                if (aim_tlv_gettlv(itl, 0x0001, 1))
     661                        msg = aim_tlv_getstr(itl, 0x0001, 1);
     662
     663                aim_tlvlist_free(&itl);
    664664        }
    665665
     
    670670        free(cookie);
    671671        free(msg);
    672         aim_freetlvchain(&otl);
     672        aim_tlvlist_free(&otl);
    673673
    674674        return ret;
  • libfaim/chatnav.c

    re374dee rcf02dd6  
    6868        aimbs_put8(&fr->data, 0x01);
    6969
    70         aim_addtlvtochain_raw(&tl, 0x00d3, strlen(name), name);
    71         aim_addtlvtochain_raw(&tl, 0x00d6, strlen(charset), charset);
    72         aim_addtlvtochain_raw(&tl, 0x00d7, strlen(lang), lang);
     70        aim_tlvlist_add_raw(&tl, 0x00d3, strlen(name), name);
     71        aim_tlvlist_add_raw(&tl, 0x00d6, strlen(charset), charset);
     72        aim_tlvlist_add_raw(&tl, 0x00d7, strlen(lang), lang);
    7373
    7474        /* tlvcount */
    75         aimbs_put16(&fr->data, aim_counttlvchain(&tl));
    76         aim_writetlvchain(&fr->data, &tl);
    77 
    78         aim_freetlvchain(&tl);
     75        aimbs_put16(&fr->data, aim_tlvlist_count(&tl));
     76        aim_tlvlist_write(&fr->data, &tl);
     77
     78        aim_tlvlist_free(&tl);
    7979
    8080        aim_tx_enqueue(sess, fr);
     
    9393        aim_tlvlist_t *tlvlist, *innerlist;
    9494
    95         tlvlist = aim_readtlvchain(bs);
     95        tlvlist = aim_tlvlist_read(bs);
    9696
    9797        /*
    9898         * Type 0x0002: Maximum concurrent rooms.
    9999         */
    100         if (aim_gettlv(tlvlist, 0x0002, 1))
    101                 maxrooms = aim_gettlv8(tlvlist, 0x0002, 1);
     100        if (aim_tlv_gettlv(tlvlist, 0x0002, 1))
     101                maxrooms = aim_tlv_get8(tlvlist, 0x0002, 1);
    102102
    103103        /*
     
    108108         *
    109109         */
    110         for (curexchange = 0; ((exchangetlv = aim_gettlv(tlvlist, 0x0003, curexchange+1))); ) {
     110        for (curexchange = 0; ((exchangetlv = aim_tlv_gettlv(tlvlist, 0x0003, curexchange+1))); ) {
    111111                aim_bstream_t tbs;
    112112
     
    119119                /* exchange number */
    120120                exchanges[curexchange-1].number = aimbs_get16(&tbs);
    121                 innerlist = aim_readtlvchain(&tbs);
     121                innerlist = aim_tlvlist_read(&tbs);
    122122
    123123                /*
     
    127127                 *
    128128                 */
    129                 if (aim_gettlv(innerlist, 0x000a, 1))
     129                if (aim_tlv_gettlv(innerlist, 0x000a, 1))
    130130                        ;
    131131
     
    133133                 * Type 0x000d: Unknown.
    134134                 */
    135                 if (aim_gettlv(innerlist, 0x000d, 1))
     135                if (aim_tlv_gettlv(innerlist, 0x000d, 1))
    136136                        ;
    137137
     
    139139                 * Type 0x0004: Unknown
    140140                 */
    141                 if (aim_gettlv(innerlist, 0x0004, 1))
     141                if (aim_tlv_gettlv(innerlist, 0x0004, 1))
    142142                        ;
    143143
     
    145145                 * Type 0x0002: Unknown
    146146                 */
    147                 if (aim_gettlv(innerlist, 0x0002, 1)) {
     147                if (aim_tlv_gettlv(innerlist, 0x0002, 1)) {
    148148                        fu16_t classperms;
    149149
    150                         classperms = aim_gettlv16(innerlist, 0x0002, 1);
     150                        classperms = aim_tlv_get16(innerlist, 0x0002, 1);
    151151                       
    152152                        faimdprintf(sess, 1, "faim: class permissions %x\n", classperms);
     
    162162                 *
    163163                 */
    164                 if (aim_gettlv(innerlist, 0x00c9, 1))
    165                         exchanges[curexchange-1].flags = aim_gettlv16(innerlist, 0x00c9, 1);
     164                if (aim_tlv_gettlv(innerlist, 0x00c9, 1))
     165                        exchanges[curexchange-1].flags = aim_tlv_get16(innerlist, 0x00c9, 1);
    166166                     
    167167                /*
    168168                 * Type 0x00ca: Creation Date
    169169                 */
    170                 if (aim_gettlv(innerlist, 0x00ca, 1))
     170                if (aim_tlv_gettlv(innerlist, 0x00ca, 1))
    171171                        ;
    172172                     
     
    174174                 * Type 0x00d0: Mandatory Channels?
    175175                 */
    176                 if (aim_gettlv(innerlist, 0x00d0, 1))
     176                if (aim_tlv_gettlv(innerlist, 0x00d0, 1))
    177177                        ;
    178178
     
    180180                 * Type 0x00d1: Maximum Message length
    181181                 */
    182                 if (aim_gettlv(innerlist, 0x00d1, 1))
     182                if (aim_tlv_gettlv(innerlist, 0x00d1, 1))
    183183                        ;
    184184
     
    186186                 * Type 0x00d2: Maximum Occupancy?
    187187                 */
    188                 if (aim_gettlv(innerlist, 0x00d2, 1))   
     188                if (aim_tlv_gettlv(innerlist, 0x00d2, 1))       
    189189                        ;
    190190
     
    192192                 * Type 0x00d3: Exchange Description
    193193                 */
    194                 if (aim_gettlv(innerlist, 0x00d3, 1))   
    195                         exchanges[curexchange-1].name = aim_gettlv_str(innerlist, 0x00d3, 1);
     194                if (aim_tlv_gettlv(innerlist, 0x00d3, 1))       
     195                        exchanges[curexchange-1].name = aim_tlv_getstr(innerlist, 0x00d3, 1);
    196196                else
    197197                        exchanges[curexchange-1].name = NULL;
     
    200200                 * Type 0x00d4: Exchange Description URL
    201201                 */
    202                 if (aim_gettlv(innerlist, 0x00d4, 1))   
     202                if (aim_tlv_gettlv(innerlist, 0x00d4, 1))       
    203203                        ;
    204204
     
    211211                 *
    212212                 */
    213                 if (aim_gettlv(innerlist, 0x00d5, 1)) {
     213                if (aim_tlv_gettlv(innerlist, 0x00d5, 1)) {
    214214                        fu8_t createperms;
    215215
    216                         createperms = aim_gettlv8(innerlist, 0x00d5, 1);
     216                        createperms = aim_tlv_get8(innerlist, 0x00d5, 1);
    217217                }
    218218
     
    220220                 * Type 0x00d6: Character Set (First Time)
    221221                 */           
    222                 if (aim_gettlv(innerlist, 0x00d6, 1))   
    223                         exchanges[curexchange-1].charset1 = aim_gettlv_str(innerlist, 0x00d6, 1);
     222                if (aim_tlv_gettlv(innerlist, 0x00d6, 1))       
     223                        exchanges[curexchange-1].charset1 = aim_tlv_getstr(innerlist, 0x00d6, 1);
    224224                else
    225225                        exchanges[curexchange-1].charset1 = NULL;
     
    228228                 * Type 0x00d7: Language (First Time)
    229229                 */           
    230                 if (aim_gettlv(innerlist, 0x00d7, 1))   
    231                         exchanges[curexchange-1].lang1 = aim_gettlv_str(innerlist, 0x00d7, 1);
     230                if (aim_tlv_gettlv(innerlist, 0x00d7, 1))       
     231                        exchanges[curexchange-1].lang1 = aim_tlv_getstr(innerlist, 0x00d7, 1);
    232232                else
    233233                        exchanges[curexchange-1].lang1 = NULL;
     
    236236                 * Type 0x00d8: Character Set (Second Time)
    237237                 */           
    238                 if (aim_gettlv(innerlist, 0x00d8, 1))   
    239                         exchanges[curexchange-1].charset2 = aim_gettlv_str(innerlist, 0x00d8, 1);
     238                if (aim_tlv_gettlv(innerlist, 0x00d8, 1))       
     239                        exchanges[curexchange-1].charset2 = aim_tlv_getstr(innerlist, 0x00d8, 1);
    240240                else
    241241                        exchanges[curexchange-1].charset2 = NULL;
     
    244244                 * Type 0x00d9: Language (Second Time)
    245245                 */           
    246                 if (aim_gettlv(innerlist, 0x00d9, 1))   
    247                         exchanges[curexchange-1].lang2 = aim_gettlv_str(innerlist, 0x00d9, 1);
     246                if (aim_tlv_gettlv(innerlist, 0x00d9, 1))       
     247                        exchanges[curexchange-1].lang2 = aim_tlv_getstr(innerlist, 0x00d9, 1);
    248248                else
    249249                        exchanges[curexchange-1].lang2 = NULL;
     
    252252                 * Type 0x00da: Unknown
    253253                 */
    254                 if (aim_gettlv(innerlist, 0x00da, 1))   
    255                         ;
    256 
    257                 aim_freetlvchain(&innerlist);
     254                if (aim_tlv_gettlv(innerlist, 0x00da, 1))       
     255                        ;
     256
     257                aim_tlvlist_free(&innerlist);
    258258        }
    259259
     
    272272        }
    273273        free(exchanges);
    274         aim_freetlvchain(&tlvlist);
     274        aim_tlvlist_free(&tlvlist);
    275275
    276276        return ret;
     
    290290        aim_bstream_t bbbs;
    291291
    292         tlvlist = aim_readtlvchain(bs);
    293 
    294         if (!(bigblock = aim_gettlv(tlvlist, 0x0004, 1))) {
     292        tlvlist = aim_tlvlist_read(bs);
     293
     294        if (!(bigblock = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
    295295                faimdprintf(sess, 0, "no bigblock in top tlv in create room response\n");
    296                 aim_freetlvchain(&tlvlist);
     296                aim_tlvlist_free(&tlvlist);
    297297                return 0;
    298298        }
     
    308308        if (detaillevel != 0x02) {
    309309                faimdprintf(sess, 0, "unknown detaillevel in create room response (0x%02x)\n", detaillevel);
    310                 aim_freetlvchain(&tlvlist);
     310                aim_tlvlist_free(&tlvlist);
    311311                free(ck);
    312312                return 0;
     
    315315        unknown = aimbs_get16(&bbbs);
    316316
    317         innerlist = aim_readtlvchain(&bbbs);
    318 
    319         if (aim_gettlv(innerlist, 0x006a, 1))
    320                 fqcn = aim_gettlv_str(innerlist, 0x006a, 1);
    321 
    322         if (aim_gettlv(innerlist, 0x00c9, 1))
    323                 flags = aim_gettlv16(innerlist, 0x00c9, 1);
    324 
    325         if (aim_gettlv(innerlist, 0x00ca, 1))
    326                 createtime = aim_gettlv32(innerlist, 0x00ca, 1);
    327 
    328         if (aim_gettlv(innerlist, 0x00d1, 1))
    329                 maxmsglen = aim_gettlv16(innerlist, 0x00d1, 1);
    330 
    331         if (aim_gettlv(innerlist, 0x00d2, 1))
    332                 maxoccupancy = aim_gettlv16(innerlist, 0x00d2, 1);
    333 
    334         if (aim_gettlv(innerlist, 0x00d3, 1))
    335                 name = aim_gettlv_str(innerlist, 0x00d3, 1);
    336 
    337         if (aim_gettlv(innerlist, 0x00d5, 1))
    338                 createperms = aim_gettlv8(innerlist, 0x00d5, 1);
     317        innerlist = aim_tlvlist_read(&bbbs);
     318
     319        if (aim_tlv_gettlv(innerlist, 0x006a, 1))
     320                fqcn = aim_tlv_getstr(innerlist, 0x006a, 1);
     321
     322        if (aim_tlv_gettlv(innerlist, 0x00c9, 1))
     323                flags = aim_tlv_get16(innerlist, 0x00c9, 1);
     324
     325        if (aim_tlv_gettlv(innerlist, 0x00ca, 1))
     326                createtime = aim_tlv_get32(innerlist, 0x00ca, 1);
     327
     328        if (aim_tlv_gettlv(innerlist, 0x00d1, 1))
     329                maxmsglen = aim_tlv_get16(innerlist, 0x00d1, 1);
     330
     331        if (aim_tlv_gettlv(innerlist, 0x00d2, 1))
     332                maxoccupancy = aim_tlv_get16(innerlist, 0x00d2, 1);
     333
     334        if (aim_tlv_gettlv(innerlist, 0x00d3, 1))
     335                name = aim_tlv_getstr(innerlist, 0x00d3, 1);
     336
     337        if (aim_tlv_gettlv(innerlist, 0x00d5, 1))
     338                createperms = aim_tlv_get8(innerlist, 0x00d5, 1);
    339339
    340340        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
     
    345345        free(name);
    346346        free(fqcn);
    347         aim_freetlvchain(&innerlist);
    348         aim_freetlvchain(&tlvlist);
     347        aim_tlvlist_free(&innerlist);
     348        aim_tlvlist_free(&tlvlist);
    349349
    350350        return ret;
  • libfaim/conn.c

    re374dee rcf02dd6  
    192192
    193193/**
    194  * aim_connrst - Clears out connection list, killing remaining connections.
    195  * @sess: Session to be cleared
    196  *
    197  * Clears out the connection list and kills any connections left.
    198  *
     194 * Clears out connection list, killing remaining connections.
     195 *
     196 * @param sess Session to be cleared
    199197 */
    200198static void aim_connrst(aim_session_t *sess)
     
    218216
    219217/**
    220  * aim_conn_init - Reset a connection to default values.
    221  * @deadconn: Connection to be reset
    222  *
     218 * Reset a connection to default values.
    223219 * Initializes and/or resets a connection structure.
    224220 *
     221 * @param deadconn Connection to be reset
    225222 */
    226223static void aim_conn_init(aim_conn_t *deadconn)
     
    533530                fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
    534531
    535                 if (sess->flags & AIM_SESS_FLAGS_NONBLOCKCONNECT)
     532                if (sess->nonblocking)
    536533                        fcntl(fd, F_SETFL, O_NONBLOCK); /* XXX save flags */
    537534
    538535                if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) {
    539                         if (sess->flags & AIM_SESS_FLAGS_NONBLOCKCONNECT) {
     536                        if (sess->nonblocking) {
    540537                                if ((errno == EINPROGRESS) || (errno == EINTR)) {
    541538                                        if (statusret)
     
    853850
    854851/**
    855  * aim_session_init - Initializes a session structure
    856  * @sess: Session to initialize
    857  * @flags: Flags to use. Any of %AIM_SESS_FLAGS %OR'd together.
    858  * @debuglevel: Level of debugging output (zero is least)
    859  *
    860  * Sets up the initial values for a session.
    861  *
    862  */
    863 faim_export void aim_session_init(aim_session_t *sess, fu32_t flags, int debuglevel)
     852 * Initializes a session structure by setting the initial values
     853 * stuff in the aim_session_t struct.
     854 *
     855 * @param sess Session to initialize.
     856 * @param nonblocking Set to true if you want connections to be non-blocking.
     857 * @param debuglevel Level of debugging output (zero is least).
     858 */
     859faim_export void aim_session_init(aim_session_t *sess, bool nonblocking, int debuglevel)
    864860{
    865861
     
    873869        aim_initsnachash(sess);
    874870        sess->msgcookies = NULL;
    875         sess->icq_info = NULL;
    876         sess->oft_info = NULL;
    877         sess->snacid_next = 0x00000001;
    878 
    879         sess->flags = 0;
     871        sess->nonblocking = nonblocking;
    880872        sess->debug = debuglevel;
    881873        sess->debugcb = defaultdebugcb;
    882 
    883874        sess->modlistv = NULL;
    884 
     875        sess->snacid_next = 0x00000001;
     876
     877        sess->locate.userinfo = NULL;
     878        sess->locate.torequest = NULL;
     879        sess->locate.requested = NULL;
     880        sess->locate.waiting_for_response = FALSE;
    885881        sess->ssi.received_data = 0;
    886882        sess->ssi.numitems = 0;
     
    890886        sess->ssi.timestamp = (time_t)0;
    891887        sess->ssi.waiting_for_ack = 0;
    892 
     888        sess->icq_info = NULL;
    893889        sess->authinfo = NULL;
    894890        sess->emailinfo = NULL;
    895 
    896         /*
    897          * Default to SNAC login unless XORLOGIN is explicitly set.
    898          */
    899         if (!(flags & AIM_SESS_FLAGS_XORLOGIN))
    900                 sess->flags |= AIM_SESS_FLAGS_SNACLOGIN;
    901         sess->flags |= flags;
     891        sess->oft_info = NULL;
    902892
    903893        /*
     
    907897        aim_tx_setenqueue(sess, AIM_TX_QUEUED, NULL);
    908898
    909 
    910899        /*
    911900         * Register all the modules for this session...
    912901         */
    913902        aim__registermodule(sess, misc_modfirst); /* load the catch-all first */
    914         aim__registermodule(sess, general_modfirst);
     903        aim__registermodule(sess, service_modfirst);
    915904        aim__registermodule(sess, locate_modfirst);
    916905        aim__registermodule(sess, buddylist_modfirst);
     
    926915        aim__registermodule(sess, chatnav_modfirst);
    927916        aim__registermodule(sess, chat_modfirst);
    928         /*      aim__registermodule(sess, odir_modfirst); */ /* kretch */
    929         /*      aim__registermodule(sess, bart_modfirst); */ /* kretch */
     917        aim__registermodule(sess, odir_modfirst);
     918        aim__registermodule(sess, bart_modfirst);
    930919        /* missing 0x11 - 0x12 */
    931920        aim__registermodule(sess, ssi_modfirst);
     
    10581047        aim_tx_enqueue(sess, fr);
    10591048
     1049        /* clean out SNACs over 60sec old */
     1050        aim_cleansnacs(sess, 60);
     1051
    10601052        return 0;
    10611053}
  • libfaim/email.c

    re374dee rcf02dd6  
    1919 * @return Return 0 if no errors, otherwise return the error number.
    2020 */
    21 faim_export int aim_email_sendcookies(aim_session_t *sess, aim_conn_t *conn)
    22 {
     21faim_export int aim_email_sendcookies(aim_session_t *sess)
     22{
     23        aim_conn_t *conn;
    2324        aim_frame_t *fr;
    2425        aim_snacid_t snacid;
    2526
    26         if (!sess || !conn)
     27        if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_EML)))
    2728                return -EINVAL;
    2829
     
    8182        fu8_t *cookie8, *cookie16;
    8283        int tmp, havenewmail = 0; /* Used to tell the client we have _new_ mail */
     84
     85        char *alertitle = NULL, *alerturl = NULL;
    8386
    8487        cookie8 = aimbs_getraw(bs, 8); /* Possibly the code used to log you in to mail? */
     
    105108        new->cookie16 = cookie16;
    106109
    107         tlvlist = aim_readtlvchain_num(bs, aimbs_get16(bs));
    108 
    109         tmp = aim_gettlv16(tlvlist, 0x0080, 1);
     110        tlvlist = aim_tlvlist_readnum(bs, aimbs_get16(bs));
     111
     112        tmp = aim_tlv_get16(tlvlist, 0x0080, 1);
    110113        if (tmp) {
    111114                if (new->nummsgs < tmp)
     
    118121                new->nummsgs++; /* We know we have at least 1 new email */
    119122        }
    120         new->url = aim_gettlv_str(tlvlist, 0x0007, 1);
    121         if (!(new->unread = aim_gettlv8(tlvlist, 0x0081, 1))) {
     123        new->url = aim_tlv_getstr(tlvlist, 0x0007, 1);
     124        if (!(new->unread = aim_tlv_get8(tlvlist, 0x0081, 1))) {
    122125                havenewmail = 0;
    123126                new->nummsgs = 0;
    124127        }
    125         new->domain = aim_gettlv_str(tlvlist, 0x0082, 1);
    126         new->flag = aim_gettlv16(tlvlist, 0x0084, 1);
    127 
     128        new->domain = aim_tlv_getstr(tlvlist, 0x0082, 1);
     129        new->flag = aim_tlv_get16(tlvlist, 0x0084, 1);
     130
     131        alertitle = aim_tlv_getstr(tlvlist, 0x0005, 1);
     132        alerturl  = aim_tlv_getstr(tlvlist, 0x000d, 1);
     133       
    128134        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    129                 ret = userfunc(sess, rx, new, havenewmail);
    130 
    131         aim_freetlvchain(&tlvlist);
     135                ret = userfunc(sess, rx, new, havenewmail, alertitle, (alerturl ? alerturl + 2 : NULL));
     136
     137        aim_tlvlist_free(&tlvlist);
     138
     139        free(alertitle);
     140        free(alerturl);
    132141
    133142        return ret;
     
    141150 * @return Return 0 if no errors, otherwise return the error number.
    142151 */
    143 faim_export int aim_email_activate(aim_session_t *sess, aim_conn_t *conn)
    144 {
     152faim_export int aim_email_activate(aim_session_t *sess)
     153{
     154        aim_conn_t *conn;
    145155        aim_frame_t *fr;
    146156        aim_snacid_t snacid;
    147157
    148         if (!sess || !conn)
     158        if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_EML)))
    149159                return -EINVAL;
    150160
  • libfaim/ft.c

    re374dee rcf02dd6  
    259259                return 0; /* not an error */
    260260
    261         if (addr.sa_family != AF_INET) { /* just in case IPv6 really is happening */
     261        if ((addr.sa_family != AF_INET) && (addr.sa_family != AF_INET6)) { /* just in case IPv6 really is happening */
    262262                close(acceptfd);
    263263                aim_conn_close(cur);
  • libfaim/icq.c

    re374dee rcf02dd6  
    317317
    318318        aim_tx_enqueue(sess, fr);
     319
     320        return 0;
     321}
     322
     323/*
     324 * Send an SMS message.  This is the non-US way.  The US-way is to IM
     325 * their cell phone number (+19195551234).
     326 *
     327 * We basically construct and send an XML message.  The format is:
     328 * <icq_sms_message>
     329 *   <destination>full_phone_without_leading_+</destination>
     330 *   <text>message</text>
     331 *   <codepage>1252</codepage>
     332 *   <senders_UIN>self_uin</senders_UIN>
     333 *   <senders_name>self_name</senders_name>
     334 *   <delivery_receipt>Yes|No</delivery_receipt>
     335 *   <time>Wkd, DD Mmm YYYY HH:MM:SS TMZ</time>
     336 * </icq_sms_message>
     337 *
     338 * Yeah hi Peter, whaaaat's happening.  If there's any way to use
     339 * a codepage other than 1252 that would be great.  Thaaaanks.
     340 */
     341faim_export int aim_icq_sendsms(aim_session_t *sess, const char *name, const char *msg, const char *alias)
     342{
     343        aim_conn_t *conn;
     344        aim_frame_t *fr;
     345        aim_snacid_t snacid;
     346        int bslen, xmllen;
     347        char *xml, timestr[30];
     348        time_t t;
     349        struct tm *tm;
     350
     351        if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015)))
     352                return -EINVAL;
     353
     354        if (!name || !msg || !alias)
     355                return -EINVAL;
     356
     357        time(&t);
     358        tm = gmtime(&t);
     359        strftime(timestr, 30, "%a, %d %b %Y %T %Z", tm);
     360
     361        /* The length of xml included the null terminating character */
     362        xmllen = 225 + strlen(name) + strlen(msg) + strlen(sess->sn) + strlen(alias) + strlen(timestr) + 1;
     363
     364        if (!(xml = (char *)malloc(xmllen*sizeof(char))))
     365                return -ENOMEM;
     366        snprintf(xml, xmllen, "<icq_sms_message>\n"
     367                "\t<destination>%s</destination>\n"
     368                "\t<text>%s</text>\n"
     369                "\t<codepage>1252</codepage>\n"
     370                "\t<senders_UIN>%s</senders_UIN>\n"
     371                "\t<senders_name>%s</senders_name>\n"
     372                "\t<delivery_receipt>Yes</delivery_receipt>\n"
     373                "\t<time>%s</time>\n"
     374                "</icq_sms_message>\n",
     375                name, msg, sess->sn, alias, timestr);
     376
     377        bslen = 37 + xmllen;
     378
     379        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) {
     380                free(xml);
     381                return -ENOMEM;
     382        }
     383
     384        snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0);
     385        aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid);
     386
     387        /* For simplicity, don't bother using a tlvlist */
     388        aimbs_put16(&fr->data, 0x0001);
     389        aimbs_put16(&fr->data, bslen);
     390
     391        aimbs_putle16(&fr->data, bslen - 2);
     392        aimbs_putle32(&fr->data, atoi(sess->sn));
     393        aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */
     394        aimbs_putle16(&fr->data, snacid); /* eh. */
     395
     396        /* From libicq200-0.3.2/src/SNAC-SRV.cpp */
     397        aimbs_putle16(&fr->data, 0x8214);
     398        aimbs_put16(&fr->data, 0x0001);
     399        aimbs_put16(&fr->data, 0x0016);
     400        aimbs_put32(&fr->data, 0x00000000);
     401        aimbs_put32(&fr->data, 0x00000000);
     402        aimbs_put32(&fr->data, 0x00000000);
     403        aimbs_put32(&fr->data, 0x00000000);
     404
     405        aimbs_put16(&fr->data, 0x0000);
     406        aimbs_put16(&fr->data, xmllen);
     407        aimbs_putraw(&fr->data, xml, xmllen);
     408
     409        aim_tx_enqueue(sess, fr);
     410
     411        free(xml);
    319412
    320413        return 0;
     
    368461        fu16_t cmdlen, cmd, reqid;
    369462
    370         if (!(tl = aim_readtlvchain(bs)) || !(datatlv = aim_gettlv(tl, 0x0001, 1))) {
    371                 aim_freetlvchain(&tl);
     463        if (!(tl = aim_tlvlist_read(bs)) || !(datatlv = aim_tlv_gettlv(tl, 0x0001, 1))) {
     464                aim_tlvlist_free(&tl);
    372465                faimdprintf(sess, 0, "corrupt ICQ response\n");
    373466                return 0;
     
    549642        }
    550643
    551         aim_freetlvchain(&tl);
     644        aim_tlvlist_free(&tl);
    552645
    553646        return ret;
  • libfaim/im.c

    re374dee rcf02dd6  
    167167                return -EINVAL;
    168168
    169         return aim_genericreq_n(sess, conn, 0x0004, 0x0004);
     169        return aim_genericreq_n_snacid(sess, conn, 0x0004, 0x0004);
    170170}
    171171
     
    390390        aim_tx_enqueue(sess, fr);
    391391
    392         /* Move this to receive aim_flap_nop and send aim_flap_nop */
    393         if (!(sess->flags & AIM_SESS_FLAGS_DONTTIMEOUTONICBM))
    394                 aim_cleansnacs(sess, 60); /* clean out SNACs over 60sec old */
     392        /* clean out SNACs over 60sec old */
     393        aim_cleansnacs(sess, 60);
    395394
    396395        return 0;
     
    633632        aim_im_puticbm(&fr->data, ck, 0x0002, sn);
    634633
    635         aim_addtlvtochain_noval(&tl, 0x0003);
     634        aim_tlvlist_add_noval(&tl, 0x0003);
    636635
    637636        hdrlen = 2+8+16+6+8+6+4;
     
    643642        aim_putcap(&hdrbs, AIM_CAPS_DIRECTIM);
    644643
    645         aim_addtlvtochain16(&itl, 0x000a, 0x0001);
    646         aim_addtlvtochain_raw(&itl, 0x0003, 4, ip);
    647         aim_addtlvtochain16(&itl, 0x0005, port);
    648         aim_addtlvtochain_noval(&itl, 0x000f);
     644        aim_tlvlist_add_16(&itl, 0x000a, 0x0001);
     645        aim_tlvlist_add_raw(&itl, 0x0003, 4, ip);
     646        aim_tlvlist_add_16(&itl, 0x0005, port);
     647        aim_tlvlist_add_noval(&itl, 0x000f);
    649648       
    650         aim_writetlvchain(&hdrbs, &itl);
    651 
    652         aim_addtlvtochain_raw(&tl, 0x0005, aim_bstream_curpos(&hdrbs), hdr);
    653 
    654         aim_writetlvchain(&fr->data, &tl);
     649        aim_tlvlist_write(&hdrbs, &itl);
     650
     651        aim_tlvlist_add_raw(&tl, 0x0005, aim_bstream_curpos(&hdrbs), hdr);
     652
     653        aim_tlvlist_write(&fr->data, &tl);
    655654
    656655        free(hdr);
    657         aim_freetlvchain(&itl);
    658         aim_freetlvchain(&tl);
     656        aim_tlvlist_free(&itl);
     657        aim_tlvlist_free(&tl);
    659658
    660659        aim_tx_enqueue(sess, fr);
     
    688687                aim_bstream_t bs;
    689688
    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."); */
     689                aim_tlvlist_add_16(&subtl, 0x000a, 0x0001);
     690                aim_tlvlist_add_noval(&subtl, 0x000f);
     691/*              aim_tlvlist_add_raw(&subtl, 0x000e, 2, "en");
     692                aim_tlvlist_add_raw(&subtl, 0x000d, 8, "us-ascii");
     693                aim_tlvlist_add_raw(&subtl, 0x000c, 24, "Please accept this file."); */
    695694                if (oft_info->clientip) {
    696695                        fu8_t ip[4];
     
    703702                                i++;
    704703                        }
    705                         aim_addtlvtochain_raw(&subtl, 0x0003, 4, ip);
     704                        aim_tlvlist_add_raw(&subtl, 0x0003, 4, ip);
    706705                }
    707                 aim_addtlvtochain16(&subtl, 0x0005, oft_info->port);
     706                aim_tlvlist_add_16(&subtl, 0x0005, oft_info->port);
    708707
    709708                /* TLV t(2711) */
     
    719718                aimbs_put8(&bs, 0x00);
    720719
    721                 aim_addtlvtochain_raw(&subtl, 0x2711, bs.len, bs.data);
     720                aim_tlvlist_add_raw(&subtl, 0x2711, bs.len, bs.data);
    722721                free(buf);
    723722        }
     
    729728
    730729                /* TLV t(0005) - Encompasses everything from above. Gee. */
    731                 buflen = 2+8+16+aim_sizetlvchain(&subtl);
     730                buflen = 2+8+16+aim_tlvlist_size(&subtl);
    732731                buf = malloc(buflen);
    733732                aim_bstream_init(&bs, buf, buflen);
     
    735734                aimbs_putraw(&bs, oft_info->cookie, 8);
    736735                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);
     736                aim_tlvlist_write(&bs, &subtl);
     737                aim_tlvlist_free(&subtl);
     738                aim_tlvlist_add_raw(&tl, 0x0005, bs.len, bs.data);
    740739                free(buf);
    741740
    742741                /* 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))))
     742                aim_tlvlist_add_noval(&tl, 0x0003);
     743        }
     744
     745        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + aim_tlvlist_size(&tl))))
    747746                return -ENOMEM;
    748747
     
    754753
    755754        /* All that crap from above (the 0x0005 TLV and the 0x0003 TLV) */
    756         aim_writetlvchain(&fr->data, &tl);
    757         aim_freetlvchain(&tl);
     755        aim_tlvlist_write(&fr->data, &tl);
     756        aim_tlvlist_free(&tl);
    758757
    759758        aim_tx_enqueue(sess, fr);
     
    10331032        sn = aimbs_getstr(bs, snlen);
    10341033
    1035         tlvlist = aim_readtlvchain(bs);
    1036 
    1037         if (aim_gettlv(tlvlist, 0x0003, 1))
     1034        tlvlist = aim_tlvlist_read(bs);
     1035
     1036        if (aim_tlv_gettlv(tlvlist, 0x0003, 1))
    10381037                icbmflags |= AIM_IMFLAGS_ACK;
    1039         if (aim_gettlv(tlvlist, 0x0004, 1))
     1038        if (aim_tlv_gettlv(tlvlist, 0x0004, 1))
    10401039                icbmflags |= AIM_IMFLAGS_AWAY;
    10411040
    1042         if ((msgblock = aim_gettlv(tlvlist, 0x0002, 1))) {
     1041        if ((msgblock = aim_tlv_gettlv(tlvlist, 0x0002, 1))) {
    10431042                aim_bstream_t mbs;
    10441043                int featurelen, msglen;
     
    10651064
    10661065        free(sn);
    1067         aim_freetlvchain(&tlvlist);
     1066        aim_tlvlist_free(&tlvlist);
    10681067
    10691068        return ret;
     
    16551654         * There's another block of TLVs embedded in the type 5 here.
    16561655         */
    1657         block1 = aim_gettlv(tlvlist, 0x0005, 1);
     1656        block1 = aim_tlv_gettlv(tlvlist, 0x0005, 1);
    16581657        aim_bstream_init(&bbs, block1->value, block1->length);
    16591658
     
    16781677         * identify what type of rendezvous this is.
    16791678         */
    1680         args.reqclass = aim_getcap(sess, &bbs, 0x10);
     1679        args.reqclass = aim_locate_getcaps(sess, &bbs, 0x10);
    16811680
    16821681        /*
     
    16861685         * Ack packets for instance have nothing more to them.
    16871686         */
    1688         list2 = aim_readtlvchain(&bbs);
     1687        list2 = aim_tlvlist_read(&bbs);
    16891688
    16901689        /*
     
    16931692         * XXX - I don't like this.  Maybe just read in an int?  Or inet_ntoa...
    16941693         */
    1695         if (aim_gettlv(list2, 0x0002, 1)) {
     1694        if (aim_tlv_gettlv(list2, 0x0002, 1)) {
    16961695                aim_tlv_t *iptlv;
    16971696
    1698                 iptlv = aim_gettlv(list2, 0x0002, 1);
     1697                iptlv = aim_tlv_gettlv(list2, 0x0002, 1);
    16991698                if (iptlv->length == 4)
    1700                         snprintf(proxyip, sizeof(proxyip), "%hhd.%hhd.%hhd.%hhd",
     1699                        snprintf(proxyip, sizeof(proxyip), "%hhu.%hhu.%hhu.%hhu",
    17011700                                iptlv->value[0], iptlv->value[1],
    17021701                                iptlv->value[2], iptlv->value[3]);
     
    17061705         * IP address from the perspective of the client.
    17071706         */
    1708         if (aim_gettlv(list2, 0x0003, 1)) {
     1707        if (aim_tlv_gettlv(list2, 0x0003, 1)) {
    17091708                aim_tlv_t *iptlv;
    17101709
    1711                 iptlv = aim_gettlv(list2, 0x0003, 1);
     1710                iptlv = aim_tlv_gettlv(list2, 0x0003, 1);
    17121711                if (iptlv->length == 4)
    1713                         snprintf(clientip, sizeof(clientip), "%hhd.%hhd.%hhd.%hhd",
     1712                        snprintf(clientip, sizeof(clientip), "%hhu.%hhu.%hhu.%hhu",
    17141713                                iptlv->value[0], iptlv->value[1],
    17151714                                iptlv->value[2], iptlv->value[3]);
     
    17211720         * This is added by the server.
    17221721         */
    1723         if (aim_gettlv(list2, 0x0004, 1)) {
     1722        if (aim_tlv_gettlv(list2, 0x0004, 1)) {
    17241723                aim_tlv_t *iptlv;
    17251724
    1726                 iptlv = aim_gettlv(list2, 0x0004, 1);
     1725                iptlv = aim_tlv_gettlv(list2, 0x0004, 1);
    17271726                if (iptlv->length == 4)
    1728                         snprintf(verifiedip, sizeof(verifiedip), "%hhd.%hhd.%hhd.%hhd",
     1727                        snprintf(verifiedip, sizeof(verifiedip), "%hhu.%hhu.%hhu.%hhu",
    17291728                                iptlv->value[0], iptlv->value[1],
    17301729                                iptlv->value[2], iptlv->value[3]);
     
    17341733         * Port number for something.
    17351734         */
    1736         if (aim_gettlv(list2, 0x0005, 1))
    1737                 args.port = aim_gettlv16(list2, 0x0005, 1);
     1735        if (aim_tlv_gettlv(list2, 0x0005, 1))
     1736                args.port = aim_tlv_get16(list2, 0x0005, 1);
    17381737
    17391738        /*
     
    17421741         * 0x0002 - "I will accept this file from you"
    17431742         */
    1744         if (aim_gettlv(list2, 0x000a, 1))
     1743        if (aim_tlv_gettlv(list2, 0x000a, 1))
    17451744                ;
    17461745
     
    17481747         * Error code.
    17491748         */
    1750         if (aim_gettlv(list2, 0x000b, 1))
    1751                 args.errorcode = aim_gettlv16(list2, 0x000b, 1);
     1749        if (aim_tlv_gettlv(list2, 0x000b, 1))
     1750                args.errorcode = aim_tlv_get16(list2, 0x000b, 1);
    17521751
    17531752        /*
    17541753         * Invitation message / chat description.
    17551754         */
    1756         if (aim_gettlv(list2, 0x000c, 1))
    1757                 args.msg = aim_gettlv_str(list2, 0x000c, 1);
     1755        if (aim_tlv_gettlv(list2, 0x000c, 1))
     1756                args.msg = aim_tlv_getstr(list2, 0x000c, 1);
    17581757
    17591758        /*
    17601759         * Character set.
    17611760         */
    1762         if (aim_gettlv(list2, 0x000d, 1))
    1763                 args.encoding = aim_gettlv_str(list2, 0x000d, 1);
     1761        if (aim_tlv_gettlv(list2, 0x000d, 1))
     1762                args.encoding = aim_tlv_getstr(list2, 0x000d, 1);
    17641763       
    17651764        /*
    17661765         * Language.
    17671766         */
    1768         if (aim_gettlv(list2, 0x000e, 1))
    1769                 args.language = aim_gettlv_str(list2, 0x000e, 1);
     1767        if (aim_tlv_gettlv(list2, 0x000e, 1))
     1768                args.language = aim_tlv_getstr(list2, 0x000e, 1);
    17701769
    17711770        /*
     
    17741773         * Maybe means we should connect directly to transfer the file?
    17751774         */
    1776         if (aim_gettlv(list2, 0x000f, 1))
     1775        if (aim_tlv_gettlv(list2, 0x000f, 1))
    17771776                ;
    17781777
     
    17821781         * Maybe means we should proxy the file transfer through an AIM server?
    17831782         */
    1784         if (aim_gettlv(list2, 0x0010, 1))
     1783        if (aim_tlv_gettlv(list2, 0x0010, 1))
    17851784                ;
    17861785
     
    17981797         * Service Data blocks are module-specific in format.
    17991798         */
    1800         if ((servdatatlv = aim_gettlv(list2, 0x2711 /* 10001 */, 1))) {
     1799        if ((servdatatlv = aim_tlv_gettlv(list2, 0x2711 /* 10001 */, 1))) {
    18011800
    18021801                aim_bstream_init(&sdbs, servdatatlv->value, servdatatlv->length);
     
    18321831        free((char *)args.language);
    18331832
    1834         aim_freetlvchain(&list2);
     1833        aim_tlvlist_free(&list2);
    18351834
    18361835        return ret;
     
    18481847         * Make a bstream for the meaty part.  Yum.  Meat.
    18491848         */
    1850         if (!(block = aim_gettlv(tlvlist, 0x0005, 1)))
     1849        if (!(block = aim_tlv_gettlv(tlvlist, 0x0005, 1)))
    18511850                return -1;
    18521851        aim_bstream_init(&meat, block->value, block->length);
     
    19471946                 * further data is derived from what is parsed here.
    19481947                 */
    1949                 tlvlist = aim_readtlvchain(bs);
     1948                tlvlist = aim_tlvlist_read(bs);
    19501949
    19511950                ret = incomingim_ch2(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie);
    19521951
    1953                 aim_freetlvchain(&tlvlist);
     1952                aim_tlvlist_free(&tlvlist);
    19541953
    19551954        } else if (channel == 4) {
    19561955                aim_tlvlist_t *tlvlist;
    19571956
    1958                 tlvlist = aim_readtlvchain(bs);
     1957                tlvlist = aim_tlvlist_read(bs);
    19591958                ret = incomingim_ch4(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie);
    1960                 aim_freetlvchain(&tlvlist);
     1959                aim_tlvlist_free(&tlvlist);
    19611960
    19621961        } else {
     
    20562055        aimbs_putraw(&fr->data, sender, strlen(sender));
    20572056
    2058         aim_addtlvtochain16(&tl, 0x0003, code);
    2059         aim_writetlvchain(&fr->data, &tl);
    2060         aim_freetlvchain(&tl);
     2057        aim_tlvlist_add_16(&tl, 0x0003, code);
     2058        aim_tlvlist_write(&fr->data, &tl);
     2059        aim_tlvlist_free(&tl);
    20612060
    20622061        aim_tx_enqueue(sess, fr);
  • libfaim/misc.c

    r862371b rcf02dd6  
    1212/*
    1313 * Generic routine for sending commands.
    14  *
    1514 *
    1615 * I know I can do this in a smarter way...but I'm not thinking straight
  • libfaim/odir.c

    r07ab1cb rcf02dd6  
    3131
    3232        /* Create a TLV chain, write it to the outgoing frame, then free the chain */
    33         aim_addtlvtochain_raw(&tl, 0x001c, strlen(region), region);
    34         aim_addtlvtochain16(&tl, 0x000a, 0x0001); /* Type of search */
    35         aim_addtlvtochain_raw(&tl, 0x0005, strlen(email), email);
    36 
    37         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_sizetlvchain(&tl))))
     33        aim_tlvlist_add_raw(&tl, 0x001c, strlen(region), region);
     34        aim_tlvlist_add_16(&tl, 0x000a, 0x0001); /* Type of search */
     35        aim_tlvlist_add_raw(&tl, 0x0005, strlen(email), email);
     36
     37        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_tlvlist_size(&tl))))
    3838                return -ENOMEM;
    3939        snacid = aim_cachesnac(sess, 0x000f, 0x0002, 0x0000, NULL, 0);
    4040        aim_putsnac(&fr->data, 0x000f, 0x0002, 0x0000, snacid);
    4141
    42         aim_writetlvchain(&fr->data, &tl);
    43         aim_freetlvchain(&tl);
     42        aim_tlvlist_write(&fr->data, &tl);
     43        aim_tlvlist_free(&tl);
    4444
    4545        aim_tx_enqueue(sess, fr);
     
    8080
    8181        /* Create a TLV chain, write it to the outgoing frame, then free the chain */
    82         aim_addtlvtochain_raw(&tl, 0x001c, strlen(region), region);
    83         aim_addtlvtochain16(&tl, 0x000a, 0x0000); /* Type of search */
     82        aim_tlvlist_add_raw(&tl, 0x001c, strlen(region), region);
     83        aim_tlvlist_add_16(&tl, 0x000a, 0x0000); /* Type of search */
    8484        if (first)
    85                 aim_addtlvtochain_raw(&tl, 0x0001, strlen(first), first);
     85                aim_tlvlist_add_raw(&tl, 0x0001, strlen(first), first);
    8686        if (last)
    87                 aim_addtlvtochain_raw(&tl, 0x0002, strlen(last), last);
     87                aim_tlvlist_add_raw(&tl, 0x0002, strlen(last), last);
    8888        if (middle)
    89                 aim_addtlvtochain_raw(&tl, 0x0003, strlen(middle), middle);
     89                aim_tlvlist_add_raw(&tl, 0x0003, strlen(middle), middle);
    9090        if (maiden)
    91                 aim_addtlvtochain_raw(&tl, 0x0004, strlen(maiden), maiden);
     91                aim_tlvlist_add_raw(&tl, 0x0004, strlen(maiden), maiden);
    9292        if (country)
    93                 aim_addtlvtochain_raw(&tl, 0x0006, strlen(country), country);
     93                aim_tlvlist_add_raw(&tl, 0x0006, strlen(country), country);
    9494        if (state)
    95                 aim_addtlvtochain_raw(&tl, 0x0007, strlen(state), state);
     95                aim_tlvlist_add_raw(&tl, 0x0007, strlen(state), state);
    9696        if (city)
    97                 aim_addtlvtochain_raw(&tl, 0x0008, strlen(city), city);
     97                aim_tlvlist_add_raw(&tl, 0x0008, strlen(city), city);
    9898        if (nick)
    99                 aim_addtlvtochain_raw(&tl, 0x000c, strlen(nick), nick);
     99                aim_tlvlist_add_raw(&tl, 0x000c, strlen(nick), nick);
    100100        if (zip)
    101                 aim_addtlvtochain_raw(&tl, 0x000d, strlen(zip), zip);
     101                aim_tlvlist_add_raw(&tl, 0x000d, strlen(zip), zip);
    102102        if (address)
    103                 aim_addtlvtochain_raw(&tl, 0x0021, strlen(address), address);
    104 
    105         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_sizetlvchain(&tl))))
     103                aim_tlvlist_add_raw(&tl, 0x0021, strlen(address), address);
     104
     105        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_tlvlist_size(&tl))))
    106106                return -ENOMEM;
    107107        snacid = aim_cachesnac(sess, 0x000f, 0x0002, 0x0000, NULL, 0);
    108108        aim_putsnac(&fr->data, 0x000f, 0x0002, 0x0000, snacid);
    109109
    110         aim_writetlvchain(&fr->data, &tl);
    111         aim_freetlvchain(&tl);
     110        aim_tlvlist_write(&fr->data, &tl);
     111        aim_tlvlist_free(&tl);
    112112
    113113        aim_tx_enqueue(sess, fr);
     
    135135
    136136        /* Create a TLV chain, write it to the outgoing frame, then free the chain */
    137         aim_addtlvtochain_raw(&tl, 0x001c, strlen(region), region);
    138         aim_addtlvtochain16(&tl, 0x000a, 0x0001); /* Type of search */
     137        aim_tlvlist_add_raw(&tl, 0x001c, strlen(region), region);
     138        aim_tlvlist_add_16(&tl, 0x000a, 0x0001); /* Type of search */
    139139        if (interest)
    140                 aim_addtlvtochain_raw(&tl, 0x0001, strlen(interest), interest);
    141 
    142         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_sizetlvchain(&tl))))
     140                aim_tlvlist_add_raw(&tl, 0x0001, strlen(interest), interest);
     141
     142        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_tlvlist_size(&tl))))
    143143                return -ENOMEM;
    144144        snacid = aim_cachesnac(sess, 0x000f, 0x0002, 0x0000, NULL, 0);
    145145        aim_putsnac(&fr->data, 0x000f, 0x0002, 0x0000, snacid);
    146146
    147         aim_writetlvchain(&fr->data, &tl);
    148         aim_freetlvchain(&tl);
     147        aim_tlvlist_write(&fr->data, &tl);
     148        aim_tlvlist_free(&tl);
    149149
    150150        aim_tx_enqueue(sess, fr);
     
    174174        while (numresults) {
    175175                struct aim_odir *new;
    176                 aim_tlvlist_t *tl = aim_readtlvchain_num(bs, aimbs_get16(bs));
     176                aim_tlvlist_t *tl = aim_tlvlist_readnum(bs, aimbs_get16(bs));
    177177                new = (struct aim_odir *)malloc(sizeof(struct aim_odir));
    178                 new->first = aim_gettlv_str(tl, 0x0001, 1);
    179                 new->last = aim_gettlv_str(tl, 0x0002, 1);
    180                 new->middle = aim_gettlv_str(tl, 0x0003, 1);
    181                 new->maiden = aim_gettlv_str(tl, 0x0004, 1);
    182                 new->email = aim_gettlv_str(tl, 0x0005, 1);
    183                 new->country = aim_gettlv_str(tl, 0x0006, 1);
    184                 new->state = aim_gettlv_str(tl, 0x0007, 1);
    185                 new->city = aim_gettlv_str(tl, 0x0008, 1);
    186                 new->sn = aim_gettlv_str(tl, 0x0009, 1);
    187                 new->interest = aim_gettlv_str(tl, 0x000b, 1);
    188                 new->nick = aim_gettlv_str(tl, 0x000c, 1);
    189                 new->zip = aim_gettlv_str(tl, 0x000d, 1);
    190                 new->region = aim_gettlv_str(tl, 0x001c, 1);
    191                 new->address = aim_gettlv_str(tl, 0x0021, 1);
     178                new->first = aim_tlv_getstr(tl, 0x0001, 1);
     179                new->last = aim_tlv_getstr(tl, 0x0002, 1);
     180                new->middle = aim_tlv_getstr(tl, 0x0003, 1);
     181                new->maiden = aim_tlv_getstr(tl, 0x0004, 1);
     182                new->email = aim_tlv_getstr(tl, 0x0005, 1);
     183                new->country = aim_tlv_getstr(tl, 0x0006, 1);
     184                new->state = aim_tlv_getstr(tl, 0x0007, 1);
     185                new->city = aim_tlv_getstr(tl, 0x0008, 1);
     186                new->sn = aim_tlv_getstr(tl, 0x0009, 1);
     187                new->interest = aim_tlv_getstr(tl, 0x000b, 1);
     188                new->nick = aim_tlv_getstr(tl, 0x000c, 1);
     189                new->zip = aim_tlv_getstr(tl, 0x000d, 1);
     190                new->region = aim_tlv_getstr(tl, 0x001c, 1);
     191                new->address = aim_tlv_getstr(tl, 0x0021, 1);
    192192                new->next = results;
    193193                results = new;
  • libfaim/oscar.c

    r07ab1cb rcf02dd6  
    3131#include "buddyicon.h"
    3232#include "conversation.h"
     33#include "core.h"
    3334#include "debug.h"
    3435#include "ft.h"
     
    4142#include "request.h"
    4243#include "util.h"
    43 #include "html.h"
    4444
    4545#include "aim.h"
    4646#include "md5.h"
    47 
    48 /* XXX CORE/UI */
    49 #include "gtkinternal.h"
    50 #include "gaim.h"
    51 
    5247
    5348#define UC_AOL          0x02
     
    6156#define AIMHASHDATA "http://gaim.sourceforge.net/aim_data.php3"
    6257
     58#define OSCAR_CONNECT_STEPS 6
     59
    6360static GaimPlugin *my_protocol = NULL;
    6461
    65 static int caps_aim = AIM_CAPS_CHAT | AIM_CAPS_BUDDYICON | AIM_CAPS_DIRECTIM | AIM_CAPS_SENDFILE | AIM_CAPS_INTEROPERATE;
    66 static int caps_icq = AIM_CAPS_BUDDYICON | AIM_CAPS_DIRECTIM | AIM_CAPS_SENDFILE | AIM_CAPS_ICQUTF8 | AIM_CAPS_INTEROPERATE;
     62static int caps_aim = AIM_CAPS_CHAT | AIM_CAPS_BUDDYICON | AIM_CAPS_DIRECTIM | AIM_CAPS_SENDFILE | AIM_CAPS_INTEROPERATE | AIM_CAPS_ICHAT;
     63static int caps_icq = AIM_CAPS_BUDDYICON | AIM_CAPS_DIRECTIM | AIM_CAPS_SENDFILE | AIM_CAPS_ICQUTF8 | AIM_CAPS_INTEROPERATE | AIM_CAPS_ICHAT;
    6764
    6865static fu8_t features_aim[] = {0x01, 0x01, 0x01, 0x02};
    6966static fu8_t features_icq[] = {0x01, 0x06};
    7067
    71 struct oscar_data {
     68typedef struct _OscarData OscarData;
     69struct _OscarData {
    7270        aim_session_t *sess;
    7371        aim_conn_t *conn;
     
    10199        gboolean killme;
    102100        gboolean icq;
    103         GSList *evilhack;
    104101        guint icontimer;
    105102        guint getblisttimer;
     
    151148};
    152149
    153 /* Various PRPL-specific buddy info that we want to keep track of */
     150/*
     151 * Various PRPL-specific buddy info that we want to keep track of
     152 * Some other info is maintained by locate.c, and I'd like to move
     153 * the rest of this to libfaim, mostly im.c
     154 */
    154155struct buddyinfo {
    155         time_t signon;
    156         int caps;
    157156        gboolean typingnot;
    158157        gchar *availmsg;
     
    168167        time_t ico_time;
    169168        gboolean ico_need;
    170 
    171         fu16_t iconcsumlen;
    172         fu8_t *iconcsum;
     169        gboolean ico_sent;
    173170};
    174171
     
    219216static int gaim_parse_misses     (aim_session_t *, aim_frame_t *, ...);
    220217static int gaim_parse_clientauto (aim_session_t *, aim_frame_t *, ...);
    221 static int gaim_parse_user_info  (aim_session_t *, aim_frame_t *, ...);
     218static int gaim_parse_userinfo   (aim_session_t *, aim_frame_t *, ...);
    222219static int gaim_parse_motd       (aim_session_t *, aim_frame_t *, ...);
    223220static int gaim_chatnav_info     (aim_session_t *, aim_frame_t *, ...);
    224 static int gaim_chat_join        (aim_session_t *, aim_frame_t *, ...);
    225 static int gaim_chat_leave       (aim_session_t *, aim_frame_t *, ...);
    226 static int gaim_chat_info_update (aim_session_t *, aim_frame_t *, ...);
    227 static int gaim_chat_incoming_msg(aim_session_t *, aim_frame_t *, ...);
     221static int gaim_conv_chat_join        (aim_session_t *, aim_frame_t *, ...);
     222static int gaim_conv_chat_leave       (aim_session_t *, aim_frame_t *, ...);
     223static int gaim_conv_chat_info_update (aim_session_t *, aim_frame_t *, ...);
     224static int gaim_conv_chat_incoming_msg(aim_session_t *, aim_frame_t *, ...);
    228225static int gaim_email_parseupdate(aim_session_t *, aim_frame_t *, ...);
    229226static int gaim_icon_error       (aim_session_t *, aim_frame_t *, ...);
     
    284281
    285282/* prpl actions - remove this at some point */
     283/* Because I don't like forward declarations?  I think that was why... */
    286284static void oscar_set_info(GaimConnection *gc, const char *text);
    287285
     
    295293        struct buddyinfo *bi = data;
    296294        g_free(bi->availmsg);
    297         g_free(bi->iconcsum);
    298295        g_free(bi);
    299296}
     
    384381}
    385382
    386 static struct direct_im *find_direct_im(struct oscar_data *od, const char *who) {
     383static struct direct_im *find_direct_im(OscarData *od, const char *who) {
    387384        GSList *d = od->direct_ims;
    388385        struct direct_im *m = NULL;
     
    428425
    429426static struct chat_connection *find_oscar_chat(GaimConnection *gc, int id) {
    430         GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats;
     427        GSList *g = ((OscarData *)gc->proto_data)->oscar_chats;
    431428        struct chat_connection *c = NULL;
    432429
     
    444441static struct chat_connection *find_oscar_chat_by_conn(GaimConnection *gc,
    445442                                                        aim_conn_t *conn) {
    446         GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats;
     443        GSList *g = ((OscarData *)gc->proto_data)->oscar_chats;
    447444        struct chat_connection *c = NULL;
    448445
     
    460457static void gaim_odc_disconnect(aim_session_t *sess, aim_conn_t *conn) {
    461458        GaimConnection *gc = sess->aux_data;
    462         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     459        OscarData *od = (OscarData *)gc->proto_data;
    463460        GaimConversation *cnv;
    464461        struct direct_im *dim;
     
    496493        aim_session_t *sess = aim_conn_getsess(conn);
    497494        GaimConnection *gc = sess ? sess->aux_data : NULL;
    498         struct oscar_data *od;
     495        OscarData *od;
    499496
    500497        if (!gc) {
    501                 /* gc is null. we return, else we seg SIGSEG on next line. */
    502498                gaim_debug(GAIM_DEBUG_INFO, "oscar",
    503499                                   "oscar callback for closed connection (1).\n");
     
    505501        }
    506502     
    507         od = (struct oscar_data *)gc->proto_data;
     503        od = (OscarData *)gc->proto_data;
    508504
    509505        if (!g_list_find(gaim_connections_get_all(), gc)) {
     
    606602
    607603static void oscar_debug(aim_session_t *sess, int level, const char *format, va_list va) {
    608         char *s = g_strdup_vprintf(format, va);
    609         char buf[256];
    610         char *t;
    611604        GaimConnection *gc = sess->aux_data;
    612 
    613         g_snprintf(buf, sizeof(buf), "%s %d: ", gaim_account_get_username(gaim_connection_get_account(gc)), level);
    614         t = g_strconcat(buf, s, NULL);
    615         gaim_debug(GAIM_DEBUG_INFO, "oscar", t);
    616         if (t[strlen(t)-1] != '\n')
     605        gchar *s = g_strdup_vprintf(format, va);
     606        gchar *buf;
     607
     608        buf = g_strdup_printf("%s %d: %s", gaim_account_get_username(gaim_connection_get_account(gc)), level, s);
     609        gaim_debug(GAIM_DEBUG_INFO, "oscar", buf);
     610        if (buf[strlen(buf)-1] != '\n')
    617611                gaim_debug(GAIM_DEBUG_INFO, NULL, "\n");
    618         g_free(t);
     612        g_free(buf);
    619613        g_free(s);
    620614}
     
    623617{
    624618        GaimConnection *gc = data;
    625         struct oscar_data *od;
     619        OscarData *od;
    626620        aim_session_t *sess;
    627621        aim_conn_t *conn;
     
    635629        sess = od->sess;
    636630        conn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH);
    637        
    638631        conn->fd = source;
    639632
     
    645638        aim_conn_completeconnect(sess, conn);
    646639        gc->inpa = gaim_input_add(conn->fd, GAIM_INPUT_READ, oscar_callback, conn);
     640        aim_request_login(sess, conn, gaim_account_get_username(gaim_connection_get_account(gc)));
     641
    647642        gaim_debug(GAIM_DEBUG_INFO, "oscar",
    648                            "Password sent, waiting for response\n");
     643                           "Screen name sent, waiting for response\n");
     644        gaim_connection_update_progress(gc, _("Screen name sent"), 1, OSCAR_CONNECT_STEPS);
    649645}
    650646
     
    652648        aim_session_t *sess;
    653649        aim_conn_t *conn;
    654         char buf[256];
    655650        GaimConnection *gc = gaim_account_get_connection(account);
    656         struct oscar_data *od = gc->proto_data = g_new0(struct oscar_data, 1);
     651        OscarData *od = gc->proto_data = g_new0(OscarData, 1);
    657652
    658653        gaim_debug(GAIM_DEBUG_MISC, "oscar", "oscar_login: gc = %p\n", gc);
     
    667662
    668663        sess = g_new0(aim_session_t, 1);
    669 
    670         aim_session_init(sess, AIM_SESS_FLAGS_NONBLOCKCONNECT, 0);
     664        aim_session_init(sess, TRUE, 0);
    671665        aim_setdebuggingcb(sess, oscar_debug);
    672 
    673         /* we need an immediate queue because we don't use a while-loop to
    674          * see if things need to be sent. */
     666        /*
     667         * We need an immediate queue because we don't use a while-loop
     668         * to see if things need to be sent.
     669         */
    675670        aim_tx_setenqueue(sess, AIM_TX_IMMEDIATE, NULL);
    676671        od->sess = sess;
     
    685680        }
    686681
    687         g_snprintf(buf, sizeof(buf), _("Signon: %s"), gaim_account_get_username(account));
    688         gaim_connection_update_progress(gc, buf, 2, 5);
    689 
    690682        aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0);
    691683        aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0);
     
    699691                return;
    700692        }
    701         aim_request_login(sess, conn, gaim_account_get_username(account));
     693
     694        gaim_connection_update_progress(gc, _("Connecting"), 0, OSCAR_CONNECT_STEPS);
    702695}
    703696
    704697static void oscar_close(GaimConnection *gc) {
    705         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     698        OscarData *od = (OscarData *)gc->proto_data;
    706699
    707700        while (od->oscar_chats) {
     
    733726        }
    734727        g_hash_table_destroy(od->buddyinfo);
    735         while (od->evilhack) {
    736                 g_free(od->evilhack->data);
    737                 od->evilhack = g_slist_remove(od->evilhack, od->evilhack->data);
    738         }
    739728        while (od->create_rooms) {
    740729                struct create_room *cr = od->create_rooms->data;
     
    773762static void oscar_bos_connect(gpointer data, gint source, GaimInputCondition cond) {
    774763        GaimConnection *gc = data;
    775         struct oscar_data *od;
     764        OscarData *od;
    776765        aim_session_t *sess;
    777766        aim_conn_t *bosconn;
     
    794783        aim_conn_completeconnect(sess, bosconn);
    795784        gc->inpa = gaim_input_add(bosconn->fd, GAIM_INPUT_READ, oscar_callback, bosconn);
     785
    796786        gaim_connection_update_progress(gc,
    797                         _("Connection established, cookie sent"), 4, 5);
     787                        _("Connection established, cookie sent"), 4, OSCAR_CONNECT_STEPS);
    798788}
    799789
     
    834824        struct aim_oft_info *oft_info = xfer->data;
    835825        GaimConnection *gc = oft_info->sess->aux_data;
    836         struct oscar_data *od = gc->proto_data;
     826        OscarData *od = gc->proto_data;
    837827
    838828        if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) {
     
    900890        struct aim_oft_info *oft_info = xfer->data;
    901891        GaimConnection *gc = oft_info->sess->aux_data;
    902         struct oscar_data *od = gc->proto_data;
     892        OscarData *od = gc->proto_data;
    903893
    904894        gaim_debug(GAIM_DEBUG_INFO, "oscar", "AAA - in oscar_xfer_end\n");
     
    919909        struct aim_oft_info *oft_info = xfer->data;
    920910        GaimConnection *gc = oft_info->sess->aux_data;
    921         struct oscar_data *od = gc->proto_data;
     911        OscarData *od = gc->proto_data;
    922912
    923913        gaim_debug(GAIM_DEBUG_INFO, "oscar",
     
    936926        struct aim_oft_info *oft_info = xfer->data;
    937927        GaimConnection *gc = oft_info->sess->aux_data;
    938         struct oscar_data *od = gc->proto_data;
     928        OscarData *od = gc->proto_data;
    939929
    940930        gaim_debug(GAIM_DEBUG_INFO, "oscar",
     
    1007997
    1008998static void oscar_ask_sendfile(GaimConnection *gc, const char *destsn) {
    1009         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     999        OscarData *od = (OscarData *)gc->proto_data;
    10101000        GaimXfer *xfer;
    10111001        struct aim_oft_info *oft_info;
     
    10381028static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) {
    10391029        GaimConnection *gc = sess->aux_data;
    1040         struct oscar_data *od = gc->proto_data;
     1030        OscarData *od = gc->proto_data;
    10411031        GaimAccount *account = gc->account;
    10421032        aim_conn_t *bosconn;
     
    11361126        aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, gaim_parse_msgerr, 0);
    11371127        aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MTN, gaim_parse_mtn, 0);
    1138         aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, gaim_parse_user_info, 0);
     1128        aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, gaim_parse_userinfo, 0);
    11391129        aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, gaim_parse_msgack, 0);
    11401130        aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, gaim_parse_motd, 0);
     
    11631153#endif
    11641154
    1165         ((struct oscar_data *)gc->proto_data)->conn = bosconn;
     1155        od->conn = bosconn;
    11661156        for (i = 0; i < (int)strlen(info->bosip); i++) {
    11671157                if (info->bosip[i] == ':') {
     
    11821172        gaim_input_remove(gc->inpa);
    11831173
     1174        gaim_connection_update_progress(gc, _("Received authorization"), 3, OSCAR_CONNECT_STEPS);
     1175
    11841176        return 1;
    11851177}
    11861178
     1179/* XXX - Should use gaim_url_fetch for the below stuff */
    11871180struct pieceofcrap {
    11881181        GaimConnection *gc;
     
    11981191{
    11991192        struct pieceofcrap *pos = data;
    1200         struct oscar_data *od = pos->gc->proto_data;
     1193        OscarData *od = pos->gc->proto_data;
    12011194        char in = '\0';
    12021195        int x = 0;
     
    12171210                        "this is fixed.  Check %s for updates."), GAIM_WEBSITE);
    12181211                gaim_notify_warning(pos->gc, NULL,
    1219                                                         _("Gaim was Unable to get a valid AIM login hash."),
     1212                                                        _("Gaim was unable to get a valid AIM login hash."),
    12201213                                                        buf);
    12211214                gaim_input_remove(pos->inpa);
     
    12471240                        "this is fixed.  Check %s for updates."), GAIM_WEBSITE);
    12481241                gaim_notify_warning(pos->gc, NULL,
    1249                                                         _("Gaim was Unable to get a valid AIM login hash."),
     1242                                                        _("Gaim was unable to get a valid AIM login hash."),
    12501243                                                        buf);
    12511244                g_free(buf);
     
    13351328                        "this is fixed.  Check %s for updates."), GAIM_WEBSITE);
    13361329                gaim_notify_warning(pos->gc, NULL,
    1337                                                         _("Gaim was Unable to get a valid login hash."),
     1330                                                        _("Gaim was unable to get a valid login hash."),
    13381331                                                        buf);
    13391332        }
     
    13431336
    13441337static int gaim_parse_login(aim_session_t *sess, aim_frame_t *fr, ...) {
    1345         char *key;
    1346         va_list ap;
    13471338        GaimConnection *gc = sess->aux_data;
     1339        OscarData *od = gc->proto_data;
    13481340        GaimAccount *account = gaim_connection_get_account(gc);
    13491341        GaimAccount *ac = gaim_connection_get_account(gc);
    1350         struct oscar_data *od = gc->proto_data;
     1342#if 0
     1343        struct client_info_s info = {"gaim", 7, 3, 2003, "us", "en", 0x0004, 0x0000, 0x04b};
     1344#endif
     1345        va_list ap;
     1346        char *key;
    13511347
    13521348        va_start(ap, fr);
     
    13591355                                           gaim_account_get_password(account), &info, key);
    13601356        } else {
    1361 #if 0
    1362                 struct client_info_s info = {"gaim", 4, 1, 2010, "us", "en", 0x0004, 0x0000, 0x04b};
    1363 #endif
    13641357                struct client_info_s info = CLIENTINFO_AIM_KNOWNGOOD;
    13651358                aim_send_login(sess, fr->conn, gaim_account_get_username(ac),
    13661359                                           gaim_account_get_password(account), &info, key);
    13671360        }
     1361
     1362        gaim_connection_update_progress(gc, _("Password sent"), 2, OSCAR_CONNECT_STEPS);
    13681363
    13691364        return 1;
     
    13761371
    13771372        aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, 0x0001, gaim_parse_genericerr, 0);
    1378         aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, gaim_chat_join, 0);
    1379         aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, gaim_chat_leave, 0);
    1380         aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, gaim_chat_info_update, 0);
    1381         aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, gaim_chat_incoming_msg, 0);
     1373        aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, gaim_conv_chat_join, 0);
     1374        aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, gaim_conv_chat_leave, 0);
     1375        aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, gaim_conv_chat_info_update, 0);
     1376        aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, gaim_conv_chat_incoming_msg, 0);
    13821377
    13831378        aim_clientready(sess, fr->conn);
     
    14071402        aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_EML, AIM_CB_EML_MAILSTATUS, gaim_email_parseupdate, 0);
    14081403
    1409         aim_email_sendcookies(sess, fr->conn);
    1410         aim_email_activate(sess, fr->conn);
     1404        aim_email_sendcookies(sess);
     1405        aim_email_activate(sess);
    14111406        aim_clientready(sess, fr->conn);
    14121407
     
    14161411static int conninitdone_icon(aim_session_t *sess, aim_frame_t *fr, ...) {
    14171412        GaimConnection *gc = sess->aux_data;
    1418         struct oscar_data *od = gc->proto_data;
     1413        OscarData *od = gc->proto_data;
    14191414
    14201415        aim_conn_addhandler(sess, fr->conn, 0x0018, 0x0001, gaim_parse_genericerr, 0);
     
    14351430static void oscar_chatnav_connect(gpointer data, gint source, GaimInputCondition cond) {
    14361431        GaimConnection *gc = data;
    1437         struct oscar_data *od;
     1432        OscarData *od;
    14381433        aim_session_t *sess;
    14391434        aim_conn_t *tstconn;
     
    14641459{
    14651460        GaimConnection *gc = data;
    1466         struct oscar_data *od;
     1461        OscarData *od;
    14671462        aim_session_t *sess;
    14681463        aim_conn_t *tstconn;
     
    14941489        struct chat_connection *ccon = data;
    14951490        GaimConnection *gc = ccon->gc;
    1496         struct oscar_data *od;
     1491        OscarData *od;
    14971492        aim_session_t *sess;
    14981493        aim_conn_t *tstconn;
     
    15261521static void oscar_email_connect(gpointer data, gint source, GaimInputCondition cond) {
    15271522        GaimConnection *gc = data;
    1528         struct oscar_data *od;
     1523        OscarData *od;
    15291524        aim_session_t *sess;
    15301525        aim_conn_t *tstconn;
     
    15551550static void oscar_icon_connect(gpointer data, gint source, GaimInputCondition cond) {
    15561551        GaimConnection *gc = data;
    1557         struct oscar_data *od;
     1552        OscarData *od;
    15581553        aim_session_t *sess;
    15591554        aim_conn_t *tstconn;
     
    17481743static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) {
    17491744        GaimConnection *gc = sess->aux_data;
    1750         struct oscar_data *od = gc->proto_data;
     1745        OscarData *od = gc->proto_data;
    17511746        struct buddyinfo *bi;
    17521747        time_t time_idle = 0, signon = 0;
     
    17891784        }
    17901785
    1791         if (caps & AIM_CAPS_ICQ)
    1792                 caps ^= AIM_CAPS_ICQ;
     1786        if (caps & AIM_CAPS_ICQ_DIRECT)
     1787                caps ^= AIM_CAPS_ICQ_DIRECT;
    17931788
    17941789        if (info->present & AIM_USERINFO_PRESENT_IDLE) {
     
    18051800                gaim_connection_set_display_name(gc, info->sn);
    18061801
    1807         bi = g_hash_table_lookup(od->buddyinfo, normalize(info->sn));
     1802        bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(gc->account, info->sn));
    18081803        if (!bi) {
    18091804                bi = g_new0(struct buddyinfo, 1);
    1810                 g_hash_table_insert(od->buddyinfo, g_strdup(normalize(info->sn)), bi);
    1811         }
    1812         bi->signon = info->onlinesince ? info->onlinesince : (info->sessionlen + time(NULL));
    1813         if (caps)
    1814                 bi->caps = caps;
     1805                g_hash_table_insert(od->buddyinfo, g_strdup(gaim_normalize(gc->account, info->sn)), bi);
     1806        }
    18151807        bi->typingnot = FALSE;
    18161808        bi->ico_informed = FALSE;
     
    18191811        /* Available message stuff */
    18201812        free(bi->availmsg);
    1821         if (info->availmsg)
    1822                 if (info->availmsg_encoding) {
    1823                         gchar *enc = g_strdup_printf("charset=\"%s\"", info->availmsg_encoding);
    1824                         bi->availmsg = oscar_encoding_to_utf8(enc, info->availmsg, info->availmsg_len);
     1813        if (info->avail != NULL)
     1814                if (info->avail_encoding) {
     1815                        gchar *enc = g_strdup_printf("charset=\"%s\"", info->avail_encoding);
     1816                        bi->availmsg = oscar_encoding_to_utf8(enc, info->avail, info->avail_len);
    18251817                        g_free(enc);
    18261818                } else {
    18271819                        /* No explicit encoding means utf8.  Yay. */
    1828                         bi->availmsg = g_strdup(info->availmsg);
     1820                        bi->availmsg = g_strdup(info->avail);
    18291821                }
    18301822        else
     
    18331825        /* Server stored icon stuff */
    18341826        if (info->iconcsumlen) {
    1835                 char *b16, *saved_b16;
    1836                 GaimBuddy *b;
    1837 
    1838                 free(bi->iconcsum);
    1839                 bi->iconcsum = malloc(info->iconcsumlen);
    1840                 memcpy(bi->iconcsum, info->iconcsum, info->iconcsumlen);
    1841                 bi->iconcsumlen = info->iconcsumlen;
    1842                 b16 = tobase16(bi->iconcsum, bi->iconcsumlen);
     1827                const char *filename = NULL, *saved_b16 = NULL;
     1828                char *b16 = NULL;
     1829                GaimBuddy *b = NULL;
     1830
     1831                b16 = gaim_base16_encode(info->iconcsum, info->iconcsumlen);
    18431832                b = gaim_find_buddy(gc->account, info->sn);
    1844                 saved_b16 = gaim_buddy_get_setting(b, "icon_checksum");
     1833                /*
     1834                 * If for some reason the checksum is valid, but cached file is not..
     1835                 * we want to know.
     1836                 */
     1837                filename = gaim_buddy_get_setting(b, "buddy_icon");
     1838                if (filename != NULL) {
     1839                        if (g_file_test(filename, G_FILE_TEST_EXISTS))
     1840                                saved_b16 = gaim_buddy_get_setting(b, "icon_checksum");
     1841                } else
     1842                        saved_b16 = NULL;
     1843
    18451844                if (!b16 || !saved_b16 || strcmp(b16, saved_b16)) {
    18461845                        GSList *cur = od->requesticon;
     
    18481847                                cur = cur->next;
    18491848                        if (!cur) {
    1850                                 od->requesticon = g_slist_append(od->requesticon, strdup(normalize(info->sn)));
     1849                                od->requesticon = g_slist_append(od->requesticon, g_strdup(gaim_normalize(gc->account, info->sn)));
    18511850                                if (od->icontimer)
    18521851                                        g_source_remove(od->icontimer);
     
    18541853                        }
    18551854                }
    1856                 g_free(saved_b16);
    18571855                g_free(b16);
    18581856        }
     
    18651863static int gaim_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...) {
    18661864        GaimConnection *gc = sess->aux_data;
    1867         struct oscar_data *od = gc->proto_data;
     1865        OscarData *od = gc->proto_data;
    18681866        va_list ap;
    18691867        aim_userinfo_t *info;
     
    18751873        serv_got_update(gc, info->sn, 0, 0, 0, 0, 0);
    18761874
    1877         g_hash_table_remove(od->buddyinfo, normalize(info->sn));
     1875        g_hash_table_remove(od->buddyinfo, gaim_normalize(gc->account, info->sn));
    18781876
    18791877        return 1;
     
    18901888        struct direct_im *dim = data;
    18911889        GaimConnection *gc = dim->gc;
    1892         struct oscar_data *od = gc->proto_data;
     1890        OscarData *od = gc->proto_data;
    18931891        GaimConversation *cnv;
    18941892        char buf[256];
     
    19291927static int oscar_sendfile_estblsh(aim_session_t *sess, aim_frame_t *fr, ...) {
    19301928        GaimConnection *gc = sess->aux_data;
    1931         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     1929        OscarData *od = (OscarData *)gc->proto_data;
    19321930        GaimXfer *xfer;
    19331931        struct aim_oft_info *oft_info;
     
    20022000static int oscar_sendfile_prompt(aim_session_t *sess, aim_frame_t *fr, ...) {
    20032001        GaimConnection *gc = sess->aux_data;
    2004         struct oscar_data *od = gc->proto_data;
     2002        OscarData *od = gc->proto_data;
    20052003        GaimXfer *xfer;
    20062004        struct aim_oft_info *oft_info;
     
    20472045static int oscar_sendfile_ack(aim_session_t *sess, aim_frame_t *fr, ...) {
    20482046        GaimConnection *gc = sess->aux_data;
    2049         struct oscar_data *od = gc->proto_data;
     2047        OscarData *od = gc->proto_data;
    20502048        GaimXfer *xfer;
    20512049        va_list ap;
     
    20792077static int oscar_sendfile_done(aim_session_t *sess, aim_frame_t *fr, ...) {
    20802078        GaimConnection *gc = sess->aux_data;
    2081         struct oscar_data *od = gc->proto_data;
     2079        OscarData *od = gc->proto_data;
    20822080        GaimXfer *xfer;
    20832081        va_list ap;
     
    21042102static void accept_direct_im(struct ask_direct *d) {
    21052103        GaimConnection *gc = d->gc;
    2106         struct oscar_data *od;
     2104        OscarData *od;
    21072105        struct direct_im *dim;
    21082106        char *host; int port = 4443;
     
    21142112        }
    21152113
    2116         od = (struct oscar_data *)gc->proto_data;
     2114        od = (OscarData *)gc->proto_data;
    21172115        gaim_debug(GAIM_DEBUG_INFO, "oscar", "Accepted DirectIM.\n");
    21182116
     
    21632161static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args) {
    21642162        GaimConnection *gc = sess->aux_data;
    2165         struct oscar_data *od = gc->proto_data;
    2166         char *tmp;
    2167         GaimImFlags flags = 0;
     2163        OscarData *od = gc->proto_data;
     2164        gchar *tmp;
     2165        GaimConvImFlags flags = 0;
    21682166        gsize convlen;
    21692167        GError *err = NULL;
     
    21712169        const char *iconfile;
    21722170
    2173         bi = g_hash_table_lookup(od->buddyinfo, normalize(userinfo->sn));
     2171        bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(gc->account, userinfo->sn));
    21742172        if (!bi) {
    21752173                bi = g_new0(struct buddyinfo, 1);
    2176                 g_hash_table_insert(od->buddyinfo, g_strdup(normalize(userinfo->sn)), bi);
     2174                g_hash_table_insert(od->buddyinfo, g_strdup(gaim_normalize(gc->account, userinfo->sn)), bi);
    21772175        }
    21782176
    21792177        if (args->icbmflags & AIM_IMFLAGS_AWAY)
    2180                 flags |= GAIM_IM_AUTO_RESP;
     2178                flags |= GAIM_CONV_IM_AUTO_RESP;
    21812179
    21822180        if (args->icbmflags & AIM_IMFLAGS_TYPINGNOT)
     
    21972195
    21982196        if ((iconfile = gaim_account_get_buddy_icon(gaim_connection_get_account(gc))) &&
    2199             (args->icbmflags & AIM_IMFLAGS_BUDDYREQ)) {
     2197            (args->icbmflags & AIM_IMFLAGS_BUDDYREQ) && !bi->ico_sent && bi->ico_informed) {
    22002198                FILE *file;
    22012199                struct stat st;
     
    22412239                        gaim_debug(GAIM_DEBUG_INFO, "oscar",
    22422240                                           "Unicode IM conversion: %s\n", err->message);
    2243                         tmp = strdup(_("(There was an error receiving this message)"));
     2241                        tmp = g_strdup(_("(There was an error receiving this message)"));
    22442242                        g_error_free(err);
    22452243                }
     
    22632261                        gaim_debug(GAIM_DEBUG_INFO, "oscar",
    22642262                                           "ISO-8859-1 IM conversion: %s\n", err->message);
    2265                         tmp = strdup(_("(There was an error receiving this message)"));
     2263                        tmp = g_strdup(_("(There was an error receiving this message)"));
    22662264                        g_error_free(err);
    22672265                }
    22682266        }
    22692267
    2270         /* strip_linefeed(tmp); */
     2268        /* gaim_str_strip_cr(tmp); */
    22712269        serv_got_im(gc, userinfo->sn, tmp, flags, time(NULL));
    22722270        g_free(tmp);
     
    22772275static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args) {
    22782276        GaimConnection *gc = sess->aux_data;
    2279         struct oscar_data *od = gc->proto_data;
     2277        OscarData *od = gc->proto_data;
    22802278        const char *username = gaim_account_get_username(gaim_connection_get_account(gc));
    22812279
     
    24382436
    24392437        if (g_list_find(gaim_connections_get_all(), gc)) {
    2440                 struct oscar_data *od = gc->proto_data;
     2438                OscarData *od = gc->proto_data;
    24412439                GaimBuddy *buddy = gaim_find_buddy(gc->account, data->name);
    24422440                GaimGroup *group = gaim_find_buddys_group(buddy);
     
    24642462
    24652463        if (g_list_find(gaim_connections_get_all(), gc)) {
    2466                 /* struct oscar_data *od = gc->proto_data; */
     2464                /* OscarData *od = gc->proto_data; */
    24672465                /* XXX - Take the buddy out of our buddy list */
    24682466        }
     
    25022500
    25032501        if (g_list_find(gaim_connections_get_all(), gc)) {
    2504                 struct oscar_data *od = gc->proto_data;
     2502                OscarData *od = gc->proto_data;
    25052503#ifdef NOSSI
    25062504                GaimBuddy *buddy;
     
    25092507                buddy = gaim_find_buddy(gc->account, data->name);
    25102508                aim_im_sendch4(od->sess, data->name, AIM_ICQMSG_AUTHGRANTED, &message);
    2511                 show_got_added(gc, NULL, data->name, (buddy ? gaim_get_buddy_alias_only(buddy) : NULL), NULL);
     2509                gaim_account_notify_added(gc->account, NULL, data->name, (buddy ? gaim_get_buddy_alias_only(buddy) : NULL), NULL);
    25122510#else
    25132511                aim_ssi_sendauthreply(od->sess, data->name, 0x01, NULL);
     
    25232521
    25242522        if (g_list_find(gaim_connections_get_all(), gc)) {
    2525                 struct oscar_data *od = gc->proto_data;
     2523                OscarData *od = gc->proto_data;
    25262524#ifdef NOSSI
    25272525                aim_im_sendch4(od->sess, data->name, AIM_ICQMSG_AUTHDENIED, msg ? msg : _("No reason given."));
     
    25402538}
    25412539
    2542 /* When someone sends you contacts */
    2543 static void gaim_icq_contactadd(struct name_data *data) {
     2540/* When someone sends you buddies */
     2541static void gaim_icq_buddyadd(struct name_data *data) {
    25442542        GaimConnection *gc = data->gc;
    25452543
    25462544        if (g_list_find(gaim_connections_get_all(), gc)) {
    2547                 show_add_buddy(gc, data->name, NULL, data->nick);
     2545                gaim_blist_request_add_buddy(gaim_connection_get_account(gc), data->name, NULL, data->nick);
    25482546        }
    25492547
     
    25682566        msg2 = (gchar **)g_malloc((numtoks+1)*sizeof(gchar *));
    25692567        for (i=0; msg1[i]; i++) {
    2570                 strip_linefeed(msg1[i]);
     2568                gaim_str_strip_cr(msg1[i]);
    25712569                msg2[i] = g_convert(msg1[i], strlen(msg1[i]), "UTF-8", "ISO-8859-1", NULL, NULL, &err);
    25722570                if (err) {
     
    25952593                case 0x04: { /* Someone sent you a URL */
    25962594                        if (i >= 2) {
    2597                                 gchar *uin = g_strdup_printf("%u", args->uin);
    2598                                 gchar *message = g_strdup_printf("<A HREF=\"%s\">%s</A>", msg2[1], msg2[0]);
    2599                                 serv_got_im(gc, uin, message, 0, time(NULL));
    2600                                 g_free(uin);
    2601                                 g_free(message);
     2595                                if (msg2[1] != NULL) {
     2596                                        gchar *uin = g_strdup_printf("%u", args->uin);
     2597                                        gchar *message = g_strdup_printf("<A HREF=\"%s\">%s</A>",
     2598                                                                                                         msg2[1],
     2599                                                                                                         (msg2[0] && msg2[0][0]) ? msg2[0] : msg2[1]);
     2600                                        serv_got_im(gc, uin, message, 0, time(NULL));
     2601                                        g_free(uin);
     2602                                        g_free(message);
     2603                                }
    26022604                        }
    26032605                } break;
     
    26262628                case 0x07: { /* Someone has denied you authorization */
    26272629                        if (i >= 1) {
    2628                                 gchar *dialog_msg = g_strdup_printf(_("The user %u has denied your request to add them to your contact list for the following reason:\n%s"), args->uin, msg2[0] ? msg2[0] : _("No reason given."));
     2630                                gchar *dialog_msg = g_strdup_printf(_("The user %u has denied your request to add them to your buddy list for the following reason:\n%s"), args->uin, msg2[0] ? msg2[0] : _("No reason given."));
    26292631                                gaim_notify_info(gc, NULL, _("ICQ authorization denied."),
    26302632                                                                 dialog_msg);
     
    26342636
    26352637                case 0x08: { /* Someone has granted you authorization */
    2636                         gchar *dialog_msg = g_strdup_printf(_("The user %u has granted your request to add them to your contact list."), args->uin);
     2638                        gchar *dialog_msg = g_strdup_printf(_("The user %u has granted your request to add them to your buddy list."), args->uin);
    26372639                        gaim_notify_info(gc, NULL, "ICQ authorization accepted.",
    26382640                                                         dialog_msg);
     
    26662668                case 0x12: {
    26672669                        /* Ack for authorizing/denying someone.  Or possibly an ack for sending any system notice */
    2668                         /* Someone added you to their contact list? */
     2670                        /* Someone added you to their buddy list? */
    26692671                } break;
    26702672
    2671                 case 0x13: { /* Someone has sent you some ICQ contacts */
     2673                case 0x13: { /* Someone has sent you some ICQ buddies */
    26722674                        int i, num;
    26732675                        gchar **text;
     
    26792681                                for (i=0; i<num; i++) {
    26802682                                        struct name_data *data = g_new(struct name_data, 1);
    2681                                         gchar *message = g_strdup_printf(_("ICQ user %u has sent you a contact: %s (%s)"), args->uin, text[i*2+2], text[i*2+1]);
     2683                                        gchar *message = g_strdup_printf(_("ICQ user %u has sent you a buddy: %s (%s)"), args->uin, text[i*2+2], text[i*2+1]);
    26822684                                        data->gc = gc;
    26832685                                        data->name = g_strdup(text[i*2+1]);
     
    26852687
    26862688                                        gaim_request_action(gc, NULL, message,
    2687                                                                                 _("Do you want to add this contact "
    2688                                                                                   "to your Buddy List?"),
     2689                                                                                _("Do you want to add this buddy "
     2690                                                                                  "to your buddy list?"),
    26892691                                                                                0, data, 2,
    2690                                                                                 _("Add"), G_CALLBACK(gaim_icq_contactadd),
     2692                                                                                _("Add"), G_CALLBACK(gaim_icq_buddyadd),
    26912693                                                                                _("Decline"), G_CALLBACK(oscar_free_name_data));
    26922694                                        g_free(message);
     
    26962698                } break;
    26972699
    2698                 case 0x1a: { /* Someone has sent you a greeting card or requested contacts? */
     2700                case 0x1a: { /* Someone has sent you a greeting card or requested buddies? */
    26992701                        /* This is boring and silly. */
    27002702                } break;
     
    28512853static int gaim_parse_clientauto_ch2(aim_session_t *sess, const char *who, fu16_t reason, const char *cookie) {
    28522854        GaimConnection *gc = sess->aux_data;
    2853         struct oscar_data *od = gc->proto_data;
     2855        OscarData *od = gc->proto_data;
    28542856
    28552857/* BBB */
     
    28812883                        char *status_msg = gaim_icq_status(state);
    28822884                        char *dialog_msg, **splitmsg;
    2883                         struct oscar_data *od = gc->proto_data;
    2884                         GSList *l = od->evilhack;
    2885                         gboolean evilhack = FALSE;
    28862885
    28872886                        /* Split at (carriage return/newline)'s, then rejoin later with BRs between. */
    28882887                        splitmsg = g_strsplit(msg, "\r\n", 0);
    28892888
    2890                         /* If who is in od->evilhack, then we're just getting the away message, otherwise this
    2891                          * will just get appended to the info box (which is already showing). */
    2892                         while (l) {
    2893                                 char *x = l->data;
    2894                                 if (!strcmp(x, normalize(who))) {
    2895                                         evilhack = TRUE;
    2896                                         g_free(x);
    2897                                         od->evilhack = g_slist_remove(od->evilhack, x);
    2898                                         break;
    2899                                 }
    2900                                 l = l->next;
    2901                         }
    2902 
    2903                         if (evilhack)
    2904                                 dialog_msg = g_strdup_printf(_("<B>UIN:</B> %s<BR><B>Status:</B> %s<HR>%s"), who, status_msg, g_strjoinv("<BR>", splitmsg));
    2905                         else
    2906                                 dialog_msg = g_strdup_printf(_("<B>Status:</B> %s<HR>%s"), status_msg, g_strjoinv("<BR>", splitmsg));
    2907                         g_show_info_text(gc, who, 2, dialog_msg, NULL);
     2889                        dialog_msg = g_strdup_printf(_("<B>UIN:</B> %s<BR><B>Status:</B> %s<HR>%s"), who, status_msg, g_strjoinv("<BR>", splitmsg));
     2890                        gaim_notify_formatted(gc, NULL, _("Buddy Information"), NULL, dialog_msg, NULL, NULL);
    29082891
    29092892                        g_free(status_msg);
     
    29742957#if 0
    29752958        GaimConnection *gc = sess->aux_data;
    2976         struct oscar_data *od = gc->proto_data;
     2959        OscarData *od = gc->proto_data;
    29772960        GaimXfer *xfer;
    29782961#endif
     
    30403023}
    30413024
     3025/*
     3026 * We get this error when there was an error in the locate family.  This
     3027 * happens when you request info of someone who is offline.
     3028 */
    30423029static int gaim_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...) {
    3043         char *buf;
     3030        gchar *buf;
    30443031        va_list ap;
    30453032        fu16_t reason;
     
    30513038        va_end(ap);
    30523039
    3053         buf = g_strdup_printf(_("User information for %s unavailable:"), destn);
    3054         gaim_notify_error(sess->aux_data, NULL, buf,
    3055                                           (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("No reason given."));
    3056         g_free(buf);
     3040        if (destn != NULL) {
     3041                buf = g_strdup_printf(_("User information for %s unavailable:"), destn);
     3042                gaim_notify_error(sess->aux_data, NULL, buf,
     3043                                                  (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("No reason given."));
     3044                g_free(buf);
     3045        }
    30573046
    30583047        return 1;
     
    30923081                                break;
    30933082                        case AIM_CAPS_DIRECTIM:
    3094                                 tmp = _("Direct IM");
     3083                                tmp = _("AIM Direct IM");
    30953084                                break;
    30963085                        case AIM_CAPS_CHAT:
     
    31133102                                tmp = _("Send Buddy List");
    31143103                                break;
    3115                         case AIM_CAPS_ICQ:
    3116                                 tmp = _("EveryBuddy Bug");
     3104                        case AIM_CAPS_ICQ_DIRECT:
     3105                                tmp = _("ICQ Direct Connect");
    31173106                                break;
    31183107                        case AIM_CAPS_APINFO:
     
    31413130                                break;
    31423131                        case AIM_CAPS_SECUREIM:
    3143                                 tmp = _("Secure IM");
     3132                                tmp = _("Security Enabled");
     3133                                break;
     3134                        case AIM_CAPS_VIDEO:
     3135                                tmp = _("Video Chat");
    31443136                                break;
    31453137                        default:
     
    31573149}
    31583150
    3159 static int gaim_parse_user_info(aim_session_t *sess, aim_frame_t *fr, ...) {
     3151static int gaim_parse_userinfo(aim_session_t *sess, aim_frame_t *fr, ...) {
    31603152        GaimConnection *gc = sess->aux_data;
    3161         struct oscar_data *od = gc->proto_data;
    3162         gchar *header;
    3163         GSList *l = od->evilhack;
    3164         gboolean evilhack = FALSE;
    3165         gchar *membersince = NULL, *onlinesince = NULL, *idle = NULL;
     3153        GString *text;
     3154        gchar *info_utf8 = NULL, *away_utf8 = NULL;
     3155        const char *final = NULL;
    31663156        va_list ap;
    3167         aim_userinfo_t *info;
    3168         fu16_t infotype;
    3169         char *text_enc = NULL, *text = NULL, *utf8 = NULL;
    3170         int text_len;
    3171         const char *username = gaim_account_get_username(gaim_connection_get_account(gc));
     3157        aim_userinfo_t *userinfo;
    31723158
    31733159        va_start(ap, fr);
    3174         info = va_arg(ap, aim_userinfo_t *);
    3175         infotype = (fu16_t) va_arg(ap, unsigned int);
    3176         text_enc = va_arg(ap, char *);
    3177         text = va_arg(ap, char *);
    3178         text_len = va_arg(ap, int);
     3160        userinfo = va_arg(ap, aim_userinfo_t *);
    31793161        va_end(ap);
    31803162
    3181         if (text_len > 0) {
    3182                 if (!(utf8 = oscar_encoding_to_utf8(text_enc, text, text_len))) {
    3183                         utf8 = g_strdup(_("<i>Unable to display information because it was sent in an unknown encoding.</i>"));
    3184                         gaim_debug(GAIM_DEBUG_ERROR, "oscar",
    3185                                            "Encountered an unknown encoding while parsing userinfo\n");
    3186                 }
    3187         }
    3188 
    3189         if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE) {
    3190                 onlinesince = g_strdup_printf(_("Online Since : <b>%s</b><br>\n"),
    3191                                         asctime(localtime((time_t *)&info->onlinesince)));
    3192         }
    3193 
    3194         if (info->present & AIM_USERINFO_PRESENT_MEMBERSINCE) {
    3195                 membersince = g_strdup_printf(_("Member Since : <b>%s</b><br>\n"),
    3196                                         asctime(localtime((time_t *)&info->membersince)));
    3197         }
    3198 
    3199         if (info->present & AIM_USERINFO_PRESENT_IDLE) {
    3200                 gchar *itime = sec_to_text(info->idletime*60);
    3201                 idle = g_strdup_printf(_("Idle : <b>%s</b>"), itime);
     3163        text = g_string_new("");
     3164        g_string_append_printf(text, _("Username: <b>%s</b><br>\n"), userinfo->sn);
     3165        g_string_append_printf(text, _("Warning Level: <b>%d%%</b><br>\n"), (int)((userinfo->warnlevel/10.0) + 0.5));
     3166
     3167        if (userinfo->present & AIM_USERINFO_PRESENT_ONLINESINCE)
     3168                g_string_append_printf(text, _("Online Since: <b>%s</b><br>\n"),
     3169                                        asctime(localtime((time_t *)&userinfo->onlinesince)));
     3170
     3171        if (userinfo->present & AIM_USERINFO_PRESENT_MEMBERSINCE)
     3172                g_string_append_printf(text, _("Member Since: <b>%s</b><br>\n"),
     3173                                        asctime(localtime((time_t *)&userinfo->membersince)));
     3174
     3175        if (userinfo->present & AIM_USERINFO_PRESENT_IDLE) {
     3176                gchar *itime = gaim_str_seconds_to_string(userinfo->idletime*60);
     3177                g_string_append_printf(text, _("Idle: <b>%s</b>"), itime);
    32023178                g_free(itime);
    32033179        } else
    3204                 idle = g_strdup(_("Idle: <b>Active</b>"));
    3205 
    3206         header = g_strdup_printf(_("Username : <b>%s</b>  %s <br>\n"
    3207                         "Warning Level : <b>%d %%</b><br>\n"
    3208                         "%s"
    3209                         "%s"
    3210                         "%s\n"
    3211                         "<hr>\n"),
    3212                         info->sn,
    3213                         /* images(info->flags), */
    3214                         "",
    3215                         (int)((info->warnlevel/10.0) + 0.5),
    3216                         onlinesince ? onlinesince : "",
    3217                         membersince ? membersince : "",
    3218                         idle ? idle : "");
    3219 
    3220         g_free(onlinesince);
    3221         g_free(membersince);
    3222         g_free(idle);
    3223 
    3224         while (l) {
    3225                 char *x = l->data;
    3226                 if (!strcmp(x, normalize(info->sn))) {
    3227                         evilhack = TRUE;
    3228                         g_free(x);
    3229                         od->evilhack = g_slist_remove(od->evilhack, x);
    3230                         break;
    3231                 }
    3232                 l = l->next;
    3233         }
    3234 
    3235         if (infotype == AIM_GETINFO_AWAYMESSAGE) {
    3236                 if (evilhack) {
    3237                         g_show_info_text(gc, info->sn, 2,
    3238                                          header,
    3239                                          (utf8 && *utf8) ? away_subs(utf8, username) :
    3240                                          _("<i>User has no away message</i>"), NULL);
    3241                 } else {
    3242                         g_show_info_text(gc, info->sn, 0,
    3243                                          header,
    3244                                          (utf8 && *utf8) ? away_subs(utf8, username) : NULL,
    3245                                          (utf8 && *utf8) ? "<hr>" : NULL,
    3246                                          NULL);
    3247                 }
    3248         } else if (infotype == AIM_GETINFO_CAPABILITIES) {
    3249                 g_show_info_text(gc, info->sn, 2,
    3250                                 header,
    3251                                 "<i>", _("Client Capabilities: "),
    3252                                 caps_string(info->capabilities),
    3253                                 "</i>",
    3254                                 NULL);
    3255         } else {
    3256                 g_show_info_text(gc, info->sn, 1,
    3257                                  (utf8 && *utf8) ? away_subs(utf8, username) : _("<i>No Information Provided</i>"),
    3258                                  NULL);
    3259         }
    3260 
    3261         g_free(header);
    3262         g_free(utf8);
     3180                g_string_append_printf(text, _("Idle: <b>Active</b>"));
     3181
     3182        if ((userinfo->flags & AIM_FLAG_AWAY) && (userinfo->away_len > 0) && (userinfo->away != NULL) && (userinfo->away_encoding != NULL)) {
     3183                away_utf8 = oscar_encoding_to_utf8(userinfo->away_encoding, userinfo->away, userinfo->away_len);
     3184                if (away_utf8 != NULL) {
     3185                        g_string_append_printf(text, "<hr>%s", away_utf8);
     3186                        g_free(away_utf8);
     3187                }
     3188        }
     3189
     3190        if ((userinfo->info_len > 0) && (userinfo->info != NULL) && (userinfo->info_encoding != NULL)) {
     3191                info_utf8 = oscar_encoding_to_utf8(userinfo->info_encoding, userinfo->info, userinfo->info_len);
     3192                if (info_utf8 != NULL) {
     3193                        g_string_append_printf(text, "<hr>%s", info_utf8);
     3194                        g_free(info_utf8);
     3195                }
     3196        }
     3197
     3198        final = gaim_str_sub_away_formatters(text->str, gaim_account_get_username(gaim_connection_get_account(gc)));
     3199        g_string_free(text, TRUE);
     3200        gaim_notify_formatted(gc, NULL, _("Buddy Information"), NULL, final, NULL, NULL);
    32633201
    32643202        return 1;
     
    32883226        fu16_t type;
    32893227        GaimConnection *gc = sess->aux_data;
    3290         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     3228        OscarData *od = (OscarData *)gc->proto_data;
    32913229
    32923230        va_start(ap, fr);
     
    33633301}
    33643302
    3365 static int gaim_chat_join(aim_session_t *sess, aim_frame_t *fr, ...) {
     3303static int gaim_conv_chat_join(aim_session_t *sess, aim_frame_t *fr, ...) {
    33663304        va_list ap;
    33673305        int count, i;
     
    33813319
    33823320        for (i = 0; i < count; i++)
    3383                 gaim_chat_add_user(GAIM_CHAT(c->cnv), info[i].sn, NULL);
     3321                gaim_conv_chat_add_user(GAIM_CONV_CHAT(c->cnv), info[i].sn, NULL);
    33843322
    33853323        return 1;
    33863324}
    33873325
    3388 static int gaim_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...) {
     3326static int gaim_conv_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...) {
    33893327        va_list ap;
    33903328        int count, i;
     
    34043342
    34053343        for (i = 0; i < count; i++)
    3406                 gaim_chat_remove_user(GAIM_CHAT(c->cnv), info[i].sn, NULL);
     3344                gaim_conv_chat_remove_user(GAIM_CONV_CHAT(c->cnv), info[i].sn, NULL);
    34073345
    34083346        return 1;
    34093347}
    34103348
    3411 static int gaim_chat_info_update(aim_session_t *sess, aim_frame_t *fr, ...) {
     3349static int gaim_conv_chat_info_update(aim_session_t *sess, aim_frame_t *fr, ...) {
    34123350        va_list ap;
    34133351        aim_userinfo_t *userinfo;
     
    34453383}
    34463384
    3447 static int gaim_chat_incoming_msg(aim_session_t *sess, aim_frame_t *fr, ...) {
     3385static int gaim_conv_chat_incoming_msg(aim_session_t *sess, aim_frame_t *fr, ...) {
    34483386        GaimConnection *gc = sess->aux_data;
    34493387        va_list ap;
     
    34673405        struct aim_emailinfo *emailinfo;
    34683406        int havenewmail;
     3407        char *alertitle, *alerturl;
    34693408
    34703409        va_start(ap, fr);
    34713410        emailinfo = va_arg(ap, struct aim_emailinfo *);
    34723411        havenewmail = va_arg(ap, int);
     3412        alertitle = va_arg(ap, char *);
     3413        alerturl  = va_arg(ap, char *);
    34733414        va_end(ap);
    34743415
     
    34793420                g_free(to);
    34803421        }
     3422       
     3423        if (alertitle)
     3424                gaim_debug(GAIM_DEBUG_MISC, "oscar", "Got an alert '%s' %s\n", alertitle, alerturl ? alerturl : "");
    34813425
    34823426        return 1;
     
    34853429static int gaim_icon_error(aim_session_t *sess, aim_frame_t *fr, ...) {
    34863430        GaimConnection *gc = sess->aux_data;
    3487         struct oscar_data *od = gc->proto_data;
     3431        OscarData *od = gc->proto_data;
    34883432        char *sn;
    34893433
     
    35033447static int gaim_icon_parseicon(aim_session_t *sess, aim_frame_t *fr, ...) {
    35043448        GaimConnection *gc = sess->aux_data;
    3505         struct oscar_data *od = gc->proto_data;
     3449        OscarData *od = gc->proto_data;
    35063450        GSList *cur;
    35073451        va_list ap;
     
    35233467                gaim_buddy_icons_set_for_user(gaim_connection_get_account(gc),
    35243468                                                                          sn, icon, iconlen);
    3525                 b16 = tobase16(iconcsum, iconcsumlen);
     3469                b16 = gaim_base16_encode(iconcsum, iconcsumlen);
    35263470                if (b16) {
    35273471                        gaim_buddy_set_setting(b, "icon_checksum", b16);
    35283472                        gaim_blist_save();
    3529                         free(b16);
     3473                        g_free(b16);
    35303474                }
    35313475        }
     
    35513495static gboolean gaim_icon_timerfunc(gpointer data) {
    35523496        GaimConnection *gc = data;
    3553         struct oscar_data *od = gc->proto_data;
    3554         struct buddyinfo *bi;
     3497        OscarData *od = gc->proto_data;
     3498        aim_userinfo_t *userinfo;
    35553499        aim_conn_t *conn;
    35563500
     
    35953539        }
    35963540
    3597         bi = g_hash_table_lookup(od->buddyinfo, (char *)od->requesticon->data);
    3598         if (bi && (bi->iconcsumlen > 0)) {
    3599                 aim_bart_request(od->sess, od->requesticon->data, bi->iconcsum, bi->iconcsumlen);
     3541        userinfo = aim_locate_finduserinfo(od->sess, (char *)od->requesticon->data);
     3542        if ((userinfo != NULL) && (userinfo->iconcsumlen > 0)) {
     3543                aim_bart_request(od->sess, od->requesticon->data, userinfo->iconcsum, userinfo->iconcsumlen);
    36003544                return FALSE;
    36013545        } else {
     
    36903634        va_end(ap);
    36913635
    3692         serv_got_eviled(gc, (userinfo && userinfo->sn[0]) ? userinfo->sn : NULL, (newevil/10.0) + 0.5);
     3636        serv_got_eviled(gc, (userinfo && userinfo->sn) ? userinfo->sn : NULL, (newevil/10.0) + 0.5);
    36933637
    36943638        return 1;
     
    37143658static int gaim_connerr(aim_session_t *sess, aim_frame_t *fr, ...) {
    37153659        GaimConnection *gc = sess->aux_data;
    3716         struct oscar_data *od = gc->proto_data;
     3660        OscarData *od = gc->proto_data;
    37173661        va_list ap;
    37183662        fu16_t code;
     
    37403684
    37413685static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...) {
     3686        GaimConnection *gc = sess->aux_data;
    37423687
    37433688        aim_reqpersonalinfo(sess, fr->conn);
    37443689
    37453690#ifndef NOSSI
    3746         gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: requesting ssi list\n");
     3691        gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: requesting rights and list\n");
    37473692        aim_ssi_reqrights(sess);
    37483693        aim_ssi_reqdata(sess);
    37493694#endif
    37503695
    3751         aim_bos_reqlocaterights(sess, fr->conn);
    3752         aim_bos_reqbuddyrights(sess, fr->conn);
     3696        aim_locate_reqrights(sess);
     3697        aim_buddylist_reqrights(sess, fr->conn);
    37533698        aim_im_reqparams(sess);
    3754         aim_bos_reqrights(sess, fr->conn); /* XXX - Don't call this with ssi? */
     3699        aim_bos_reqrights(sess, fr->conn); /* XXX - Don't call this with ssi */
    37553700
    37563701#ifdef NOSSI
     3702        gaim_debug(GAIM_DEBUG_INFO, "oscar", "bos: requesting rights\n");
     3703        aim_bos_reqrights(sess, fr->conn);
    37573704        aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS);
    37583705        aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE | AIM_PRIVFLAGS_ALLOWMEMBERSINCE);
    37593706#endif
    37603707
     3708        gaim_connection_update_progress(gc, _("Finalizing connection"), 5, OSCAR_CONNECT_STEPS);
     3709
    37613710        return 1;
    37623711}
     
    37643713static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...) {
    37653714        GaimConnection *gc = sess->aux_data;
    3766         struct oscar_data *od = gc->proto_data;
     3715        OscarData *od = gc->proto_data;
    37673716
    37683717        aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_ADM, 0x0003, gaim_info_change, 0);
     
    38393788{
    38403789        GaimConnection *gc = sess->aux_data;
    3841         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     3790        OscarData *od = (OscarData *)gc->proto_data;
    38423791        va_list ap;
    38433792        fu16_t maxsiglen;
     
    38533802
    38543803        if (od->icq)
    3855                 aim_bos_setprofile(sess, fr->conn, NULL, NULL, 0, NULL, NULL, 0, caps_icq);
     3804                aim_locate_setcaps(od->sess, caps_icq);
    38563805        else
    3857                 oscar_set_info(gc, gc->account->user_info);
     3806                aim_locate_setcaps(od->sess, caps_aim);
     3807        oscar_set_info(gc, gc->account->user_info);
    38583808
    38593809        return 1;
     
    38643814        fu16_t maxbuddies, maxwatchers;
    38653815        GaimConnection *gc = sess->aux_data;
    3866         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     3816        OscarData *od = (OscarData *)gc->proto_data;
    38673817
    38683818        va_start(ap, fr);
     
    38813831
    38823832static int gaim_bosrights(aim_session_t *sess, aim_frame_t *fr, ...) {
     3833        GaimConnection *gc = sess->aux_data;
     3834        OscarData *od = (OscarData *)gc->proto_data;
     3835        va_list ap;
    38833836        fu16_t maxpermits, maxdenies;
    3884         va_list ap;
    3885         GaimConnection *gc = sess->aux_data;
    3886         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
    38873837
    38883838        va_start(ap, fr);
     
    39043854        aim_clientready(sess, fr->conn);
    39053855        aim_srv_setavailmsg(sess, NULL);
    3906         aim_bos_setidle(sess, fr->conn, 0);
     3856        aim_srv_setidle(sess, 0);
    39073857
    39083858        if (od->icq) {
     
    39353885        args.msglen = msg->msglen;
    39363886        args.msg = msg->msg;
    3937         t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0);
     3887        t = gaim_time_build(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0);
    39383888        incomingim_chan4(sess, fr->conn, NULL, &args, t);
    39393889
     
    39463896        return 1;
    39473897}
     3898
     3899#if 0
     3900/*
     3901 * Update, 2003-11-09:
     3902 * Joseph S. Myers, a gcc dude, fixed this for gcc 3.4!  Rock on!
     3903 *
     3904 * It may not be my place to do this, but...
     3905 * I feel pretty strongly that the "last 2 digits" warning is ridiculously
     3906 * stupid, and should not exist for % switches (%x in our case) that request
     3907 * a year in the preferred representation for the current locale.  For that
     3908 * reason I've chosen to not use this workaround (n., see kluge).
     3909 *
     3910 * I have a date.  I want to show it to the user in the "preferred" way. 
     3911 * Whether that displays a 2 digit year is perfectly fine--after all, it's
     3912 * what the locale wanted.
     3913 *
     3914 * If I have a necessity for a full representation of the year in the current
     3915 * locale, then I'll use a switch that returns a full representation of the
     3916 * year.
     3917 *
     3918 * If you think the preferred locale should show 4 digits instead of 2 digits
     3919 * (because you're anal, or whatever), then change the f***ing locale.
     3920 *
     3921 * I guess the bottom line is--I'm trying to show a date to the user how they
     3922 * prefer to see it, why the hell does gcc want me to change that?
     3923 *
     3924 * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=3190
     3925 * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=8714
     3926 */
     3927
     3928/*
     3929 * This function was recommended by the STRFTIME(3) man page to remove the
     3930 * "last 2 digits" warning.
     3931 */
     3932static size_t my_strftime(char *s, size_t max, const char  *fmt, 
     3933                        const struct tm *tm)
     3934{
     3935        return strftime(s, max, fmt, tm);
     3936}
     3937#endif
    39483938
    39493939static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...)
     
    39663956        g_snprintf(who, sizeof(who), "%u", info->uin);
    39673957        buf = g_strdup_printf("<b>%s:</b> %s", _("UIN"), who);
    3968         if (info->nick && info->nick[0] && (utf8 = gaim_try_conv_to_utf8(info->nick))) {
     3958        if (info->nick && info->nick[0] && (utf8 = gaim_utf8_try_convert(info->nick))) {
    39693959                tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Nick"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
    39703960        }
    3971         if (info->first && info->first[0] && (utf8 = gaim_try_conv_to_utf8(info->first))) {
     3961        if (info->first && info->first[0] && (utf8 = gaim_utf8_try_convert(info->first))) {
    39723962                tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("First Name"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
    39733963        }
    3974         if (info->last && info->last[0] && (utf8 = gaim_try_conv_to_utf8(info->last))) {
     3964        if (info->last && info->last[0] && (utf8 = gaim_utf8_try_convert(info->last))) {
    39753965                tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Last Name"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
    39763966        }
    3977         if (info->email && info->email[0] && (utf8 = gaim_try_conv_to_utf8(info->email))) {
     3967        if (info->email && info->email[0] && (utf8 = gaim_utf8_try_convert(info->email))) {
    39783968                tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Email Address"), ":</b> <a href=\"mailto:", utf8, "\">", utf8, "</a>", NULL);  g_free(tmp); g_free(utf8);
    39793969        }
     
    39813971                int i;
    39823972                for (i = 0; i < info->numaddresses; i++) {
    3983                         if (info->email2[i] && info->email2[i][0] && (utf8 = gaim_try_conv_to_utf8(info->email2[i]))) {
     3973                        if (info->email2[i] && info->email2[i][0] && (utf8 = gaim_utf8_try_convert(info->email2[i]))) {
    39843974                        tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Email Address"), ":</b> <a href=\"mailto:", utf8, "\">", utf8, "</a>", NULL);  g_free(tmp); g_free(utf8);
    39853975                        }
    39863976                }
    39873977        }
    3988         if (info->mobile && info->mobile[0] && (utf8 = gaim_try_conv_to_utf8(info->mobile))) {
     3978        if (info->mobile && info->mobile[0] && (utf8 = gaim_utf8_try_convert(info->mobile))) {
    39893979                tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Mobile Phone"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
    39903980        }
     
    40063996                tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Age"), ":</b> ", age, NULL);  g_free(tmp);
    40073997        }
    4008         if (info->personalwebpage && info->personalwebpage[0] && (utf8 = gaim_try_conv_to_utf8(info->personalwebpage))) {
     3998        if (info->personalwebpage && info->personalwebpage[0] && (utf8 = gaim_utf8_try_convert(info->personalwebpage))) {
    40093999                tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Personal Web Page"), ":</b> <a href=\"", utf8, "\">", utf8, "</a>", NULL);  g_free(tmp); g_free(utf8);
    40104000        }
    4011         if (info->info && info->info[0] && (utf8 = gaim_try_conv_to_utf8(info->info))) {
     4001        if (info->info && info->info[0] && (utf8 = gaim_utf8_try_convert(info->info))) {
    40124002                tmp = buf;  buf = g_strconcat(tmp, "<hr><b>", _("Additional Information"), ":</b><br>", utf8, NULL);  g_free(tmp); g_free(utf8);
    40134003        }
     
    40154005        if ((info->homeaddr && (info->homeaddr[0])) || (info->homecity && info->homecity[0]) || (info->homestate && info->homestate[0]) || (info->homezip && info->homezip[0])) {
    40164006                tmp = buf;  buf = g_strconcat(tmp, "<b>", _("Home Address"), ":</b>", NULL);  g_free(tmp);
    4017                 if (info->homeaddr && info->homeaddr[0] && (utf8 = gaim_try_conv_to_utf8(info->homeaddr))) {
     4007                if (info->homeaddr && info->homeaddr[0] && (utf8 = gaim_utf8_try_convert(info->homeaddr))) {
    40184008                        tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Address"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
    40194009                }
    4020                 if (info->homecity && info->homecity[0] && (utf8 = gaim_try_conv_to_utf8(info->homecity))) {
     4010                if (info->homecity && info->homecity[0] && (utf8 = gaim_utf8_try_convert(info->homecity))) {
    40214011                        tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("City"), ":</b> ", utf8,  NULL);  g_free(tmp); g_free(utf8);
    40224012                }
    4023                 if (info->homestate && info->homestate[0] && (utf8 = gaim_try_conv_to_utf8(info->homestate))) {
     4013                if (info->homestate && info->homestate[0] && (utf8 = gaim_utf8_try_convert(info->homestate))) {
    40244014                        tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("State"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
    40254015                }
    4026                 if (info->homezip && info->homezip[0] && (utf8 = gaim_try_conv_to_utf8(info->homezip))) {
     4016                if (info->homezip && info->homezip[0] && (utf8 = gaim_utf8_try_convert(info->homezip))) {
    40274017                        tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Zip Code"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
    40284018                }
     
    40314021        if ((info->workaddr && info->workaddr[0]) || (info->workcity && info->workcity[0]) || (info->workstate && info->workstate[0]) || (info->workzip && info->workzip[0])) {
    40324022                tmp = buf;  buf = g_strconcat(tmp, "<b>", _("Work Address"), ":</b>", NULL);  g_free(tmp);
    4033                 if (info->workaddr && info->workaddr[0] && (utf8 = gaim_try_conv_to_utf8(info->workaddr))) {
     4023                if (info->workaddr && info->workaddr[0] && (utf8 = gaim_utf8_try_convert(info->workaddr))) {
    40344024                        tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Address"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
    40354025                }
    4036                 if (info->workcity && info->workcity[0] && (utf8 = gaim_try_conv_to_utf8(info->workcity))) {
     4026                if (info->workcity && info->workcity[0] && (utf8 = gaim_utf8_try_convert(info->workcity))) {
    40374027                        tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("City"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
    40384028                }
    4039                 if (info->workstate && info->workstate[0] && (utf8 = gaim_try_conv_to_utf8(info->workstate))) {
     4029                if (info->workstate && info->workstate[0] && (utf8 = gaim_utf8_try_convert(info->workstate))) {
    40404030                        tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("State"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
    40414031                }
    4042                 if (info->workzip && info->workzip[0] && (utf8 = gaim_try_conv_to_utf8(info->workzip))) {
     4032                if (info->workzip && info->workzip[0] && (utf8 = gaim_utf8_try_convert(info->workzip))) {
    40434033                        tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Zip Code"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
    40444034                }
     
    40474037        if ((info->workcompany && info->workcompany[0]) || (info->workdivision && info->workdivision[0]) || (info->workposition && info->workposition[0]) || (info->workwebpage && info->workwebpage[0])) {
    40484038                tmp = buf;  buf = g_strconcat(tmp, "<b>", _("Work Information"), ":</b>", NULL);  g_free(tmp);
    4049                 if (info->workcompany && info->workcompany[0] && (utf8 = gaim_try_conv_to_utf8(info->workcompany))) {
     4039                if (info->workcompany && info->workcompany[0] && (utf8 = gaim_utf8_try_convert(info->workcompany))) {
    40504040                        tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Company"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
    40514041                }
    4052                 if (info->workdivision && info->workdivision[0] && (utf8 = gaim_try_conv_to_utf8(info->workdivision))) {
     4042                if (info->workdivision && info->workdivision[0] && (utf8 = gaim_utf8_try_convert(info->workdivision))) {
    40534043                        tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Division"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
    40544044                }
    4055                 if (info->workposition && info->workposition[0] && (utf8 = gaim_try_conv_to_utf8(info->workposition))) {
     4045                if (info->workposition && info->workposition[0] && (utf8 = gaim_utf8_try_convert(info->workposition))) {
    40564046                        tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Position"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
    40574047                }
    4058                 if (info->workwebpage && info->workwebpage[0] && (utf8 = gaim_try_conv_to_utf8(info->workwebpage))) {
     4048                if (info->workwebpage && info->workwebpage[0] && (utf8 = gaim_utf8_try_convert(info->workwebpage))) {
    40594049                        tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Web Page"), ":</b> <a href=\"", utf8, "\">", utf8, "</a>", NULL);  g_free(tmp); g_free(utf8);
    40604050                }
     
    40834073        va_end(ap);
    40844074
    4085         if (info->uin && info->nick && info->nick[0] && (utf8 = gaim_try_conv_to_utf8(info->nick))) {
     4075        if (info->uin && info->nick && info->nick[0] && (utf8 = gaim_utf8_try_convert(info->nick))) {
    40864076                g_snprintf(who, sizeof(who), "%u", info->uin);
    40874077                serv_got_alias(gc, who, utf8);
     
    40984088static int gaim_popup(aim_session_t *sess, aim_frame_t *fr, ...)
    40994089{
     4090        GaimConnection *gc = sess->aux_data;
     4091        gchar *text;
     4092        va_list ap;
    41004093        char *msg, *url;
    41014094        fu16_t wid, hei, delay;
    4102         va_list ap;
    41034095
    41044096        va_start(ap, fr);
     
    41104102        va_end(ap);
    41114103
    4112         serv_got_popup(msg, url, wid, hei);
     4104        text = g_strdup_printf("%s<br><a href=\"%s\">%s</a>", msg, url, url);
     4105        gaim_notify_formatted(gc, NULL, _("Pop-Up Message"), NULL, text, NULL, NULL);
     4106        g_free(text);
    41134107
    41144108        return 1;
    41154109}
    41164110
    4117 static int gaim_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...) {
     4111static int gaim_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...)
     4112{
    41184113        GaimConnection *gc = sess->aux_data;
    41194114        gchar *secondary;
     
    42484243
    42494244static void oscar_keepalive(GaimConnection *gc) {
    4250         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     4245        OscarData *od = (OscarData *)gc->proto_data;
    42514246        aim_flap_nop(od->sess, od->conn);
    42524247}
    42534248
    42544249static int oscar_send_typing(GaimConnection *gc, const char *name, int typing) {
    4255         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     4250        OscarData *od = (OscarData *)gc->proto_data;
    42564251        struct direct_im *dim = find_direct_im(od, name);
    42574252        if (dim)
     
    42674262                for (list=gc->account->deny; (list && aim_sncmp(name, list->data)); list=list->next);
    42684263                if (!list) {
    4269                         struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, normalize(name));
     4264                        struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(gc->account, name));
    42704265                        if (bi && bi->typingnot) {
    42714266                                if (typing == GAIM_TYPING)
     
    42814276}
    42824277static void oscar_ask_direct_im(GaimConnection *gc, const char *name);
    4283 static int gaim_odc_send_im(aim_session_t *, aim_conn_t *, const char *, GaimImFlags);
    4284 
    4285 static int oscar_send_im(GaimConnection *gc, const char *name, const char *message, GaimImFlags imflags) {
    4286         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     4278static int gaim_odc_send_im(aim_session_t *, aim_conn_t *, const char *, GaimConvImFlags);
     4279
     4280static int oscar_send_im(GaimConnection *gc, const char *name, const char *message, GaimConvImFlags imflags) {
     4281        OscarData *od = (OscarData *)gc->proto_data;
    42874282        struct direct_im *dim = find_direct_im(od, name);
    42884283        int ret = 0;
     
    42944289                /* If we're directly connected, send a direct IM */
    42954290                ret = gaim_odc_send_im(od->sess, dim->conn, message, imflags);
    4296         } else if (imflags & GAIM_IM_IMAGES) {
     4291        } else if (imflags & GAIM_CONV_IM_IMAGES) {
    42974292                /* Trying to send an IM image outside of a direct connection. */
    42984293                oscar_ask_direct_im(gc, name);
     
    43044299                gsize len;
    43054300
    4306                 bi = g_hash_table_lookup(od->buddyinfo, normalize(name));
     4301                bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(gc->account, name));
    43074302                if (!bi) {
    43084303                        bi = g_new0(struct buddyinfo, 1);
    4309                         g_hash_table_insert(od->buddyinfo, g_strdup(normalize(name)), bi);
     4304                        g_hash_table_insert(od->buddyinfo, g_strdup(gaim_normalize(gc->account, name)), bi);
    43104305                }
    43114306
     
    43194314                        args.featureslen = sizeof(features_aim);
    43204315
    4321                         if (imflags & GAIM_IM_AUTO_RESP)
     4316                        if (imflags & GAIM_CONV_IM_AUTO_RESP)
    43224317                                args.flags |= AIM_IMFLAGS_AWAY;
    43234318                }
     
    43414336                                args.iconstamp = st.st_mtime;
    43424337
    4343                                 if ((args.iconlen != bi->ico_me_len) || (args.iconsum != bi->ico_me_csum) || (args.iconstamp != bi->ico_me_time))
     4338                                if ((args.iconlen != bi->ico_me_len) || (args.iconsum != bi->ico_me_csum) || (args.iconstamp != bi->ico_me_time)) {
    43444339                                        bi->ico_informed = FALSE;
     4340                                        bi->ico_sent     = FALSE;
     4341                                }
    43454342
    43464343                                if (!bi->ico_informed) {
     
    43624359                /* For ICQ send newlines as CR/LF, for AIM send newlines as <BR> */
    43634360                if (isdigit(name[0]))
    4364                         tmpmsg = add_cr(message);
     4361                        tmpmsg = gaim_str_add_cr(message);
    43654362                else
    4366                         tmpmsg = strdup_withhtml(message);
     4363                        tmpmsg = gaim_strdup_withhtml(message);
    43674364                len = strlen(tmpmsg);
    43684365
     
    44214418}
    44224419
    4423 static void oscar_get_info(GaimConnection *g, const char *name) {
    4424         struct oscar_data *od = (struct oscar_data *)g->proto_data;
    4425         if (od->icq)
     4420static void oscar_get_info(GaimConnection *gc, const char *name) {
     4421        OscarData *od = (OscarData *)gc->proto_data;
     4422
     4423        if (od->icq && isdigit(name[0]))
    44264424                aim_icq_getallinfo(od->sess, name);
    44274425        else
    4428                 /* people want the away message on the top, so we get the away message
    4429                  * first and then get the regular info, since it's too difficult to
    4430                  * insert in the middle. i hate people. */
    4431                 aim_getinfo(od->sess, od->conn, name, AIM_GETINFO_AWAYMESSAGE);
    4432 }
    4433 
    4434 static void oscar_get_away(GaimConnection *g, const char *who) {
    4435         struct oscar_data *od = (struct oscar_data *)g->proto_data;
     4426                aim_locate_getinfoshort(od->sess, name, 0x00000003);
     4427}
     4428
     4429static void oscar_get_away(GaimConnection *gc, const char *who) {
     4430        OscarData *od = (OscarData *)gc->proto_data;
    44364431        if (od->icq) {
    4437                 GaimBuddy *budlight = gaim_find_buddy(g->account, who);
     4432                GaimBuddy *budlight = gaim_find_buddy(gc->account, who);
    44384433                if (budlight)
    44394434                        if ((budlight->uc & 0xffff0000) >> 16)
     
    44444439                else
    44454440                        gaim_debug(GAIM_DEBUG_ERROR, "oscar",
    4446                                            "Error: Could not find %s in local contact list, therefore unable to request status message.\n", who);
     4441                                           "Error: Could not find %s in local buddy list, therefore unable to request status message.\n", who);
    44474442        } else
    4448                 aim_getinfo(od->sess, od->conn, who, AIM_GETINFO_GENERALINFO);
    4449 }
    4450 
    4451 static void oscar_set_dir(GaimConnection *g, const char *first, const char *middle, const char *last,
     4443                aim_locate_getinfoshort(od->sess, who, 0x00000002);
     4444}
     4445
     4446static void oscar_set_dir(GaimConnection *gc, const char *first, const char *middle, const char *last,
    44524447                          const char *maiden, const char *city, const char *state, const char *country, int web) {
    44534448        /* XXX - some of these things are wrong, but i'm lazy */
    4454         struct oscar_data *od = (struct oscar_data *)g->proto_data;
    4455         aim_setdirectoryinfo(od->sess, od->conn, first, middle, last,
     4449        OscarData *od = (OscarData *)gc->proto_data;
     4450        aim_locate_setdirinfo(od->sess, first, middle, last,
    44564451                                maiden, NULL, NULL, city, state, NULL, 0, web);
    44574452}
    44584453
    44594454static void oscar_set_idle(GaimConnection *gc, int time) {
    4460         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
    4461         aim_bos_setidle(od->sess, od->conn, time);
     4455        OscarData *od = (OscarData *)gc->proto_data;
     4456        aim_srv_setidle(od->sess, time);
    44624457}
    44634458
    44644459static void oscar_set_info(GaimConnection *gc, const char *text) {
    4465         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     4460        OscarData *od = (OscarData *)gc->proto_data;
    44664461        fu32_t flags = 0;
    44674462        char *text_html = NULL;
     
    44764471                                                          "again when you are fully connected."));
    44774472
    4478         if (od->icq)
    4479                 aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, NULL, NULL, 0, caps_icq);
    4480         else {
    4481                 if (!text) {
    4482                         aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, NULL, NULL, 0, caps_aim);
    4483                         return;
    4484                 }
     4473        if (!text) {
     4474                aim_locate_setprofile(od->sess, NULL, "", 0, NULL, NULL, 0);
     4475                return;
     4476        }
    44854477               
    4486                 text_html = strdup_withhtml(text);
    4487                 flags = oscar_encoding_check(text_html);
    4488                 if (flags & AIM_IMFLAGS_UNICODE) {
    4489                         msg = g_convert(text_html, strlen(text_html), "UCS-2BE", "UTF-8", NULL, &msglen, NULL);
    4490                         aim_bos_setprofile(od->sess, od->conn, "unicode-2-0", msg, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0, caps_aim);
    4491                         g_free(msg);
    4492                 } else if (flags & AIM_IMFLAGS_ISO_8859_1) {
    4493                         msg = g_convert(text_html, strlen(text_html), "ISO-8859-1", "UTF-8", NULL, &msglen, NULL);
    4494                         aim_bos_setprofile(od->sess, od->conn, "iso-8859-1", msg, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0, caps_aim);
    4495                         g_free(msg);
    4496                 } else {
    4497                         msglen = strlen(text_html);
    4498                         aim_bos_setprofile(od->sess, od->conn, "us-ascii", text_html, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0, caps_aim);
    4499                 }
    4500 
    4501                 if (msglen > od->rights.maxsiglen) {
    4502                         gchar *errstr;
    4503                         errstr = g_strdup_printf(ngettext("The maximum profile length of %d byte "
    4504                                                                          "has been exceeded.  Gaim has truncated it for you.",
    4505                                                                          "The maximum profile length of %d bytes "
    4506                                                                          "has been exceeded.  Gaim has truncated it for you.",
    4507                                                                          od->rights.maxsiglen), od->rights.maxsiglen);
    4508                         gaim_notify_warning(gc, NULL, _("Profile too long."), errstr);
    4509                         g_free(errstr);
    4510                 }
    4511 
    4512                 g_free(text_html);
    4513 
    4514         }
     4478        text_html = gaim_strdup_withhtml(text);
     4479        flags = oscar_encoding_check(text_html);
     4480        if (flags & AIM_IMFLAGS_UNICODE) {
     4481                msg = g_convert(text_html, strlen(text_html), "UCS-2BE", "UTF-8", NULL, &msglen, NULL);
     4482                aim_locate_setprofile(od->sess, "unicode-2-0", msg, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0);
     4483                g_free(msg);
     4484        } else if (flags & AIM_IMFLAGS_ISO_8859_1) {
     4485                msg = g_convert(text_html, strlen(text_html), "ISO-8859-1", "UTF-8", NULL, &msglen, NULL);
     4486                aim_locate_setprofile(od->sess, "iso-8859-1", msg, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0);
     4487                g_free(msg);
     4488        } else {
     4489                msglen = strlen(text_html);
     4490                aim_locate_setprofile(od->sess, "us-ascii", text_html, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0);
     4491        }
     4492
     4493        if (msglen > od->rights.maxsiglen) {
     4494                gchar *errstr;
     4495                errstr = g_strdup_printf(ngettext("The maximum profile length of %d byte "
     4496                                                                 "has been exceeded.  Gaim has truncated it for you.",
     4497                                                                 "The maximum profile length of %d bytes "
     4498                                                                 "has been exceeded.  Gaim has truncated it for you.",
     4499                                                                 od->rights.maxsiglen), od->rights.maxsiglen);
     4500                gaim_notify_warning(gc, NULL, _("Profile too long."), errstr);
     4501                g_free(errstr);
     4502        }
     4503
     4504        g_free(text_html);
    45154505
    45164506        return;
    45174507}
    45184508
    4519 static void oscar_set_away_aim(GaimConnection *gc, struct oscar_data *od, const char *text)
     4509static void oscar_set_away_aim(GaimConnection *gc, OscarData *od, const char *text)
    45204510{
    45214511        fu32_t flags = 0;
     
    45384528
    45394529        if (!text) {
    4540                 aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, NULL, "", 0, caps_aim);
     4530                aim_locate_setprofile(od->sess, NULL, NULL, 0, NULL, "", 0);
    45414531                return;
    45424532        }
    45434533
    4544         text_html = strdup_withhtml(text);
     4534        text_html = gaim_strdup_withhtml(text);
    45454535        flags = oscar_encoding_check(text_html);
    45464536        if (flags & AIM_IMFLAGS_UNICODE) {
    45474537                msg = g_convert(text_html, strlen(text_html), "UCS-2BE", "UTF-8", NULL, &msglen, NULL);
    4548                 aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "unicode-2-0", msg,
    4549                         (msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen), caps_aim);
     4538                aim_locate_setprofile(od->sess, NULL, NULL, 0, "unicode-2-0", msg,
     4539                        (msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen));
    45504540                g_free(msg);
    45514541                gc->away = g_strndup(text, od->rights.maxawaymsglen/2);
    45524542        } else if (flags & AIM_IMFLAGS_ISO_8859_1) {
    45534543                msg = g_convert(text_html, strlen(text_html), "ISO-8859-1", "UTF-8", NULL, &msglen, NULL);
    4554                 aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "iso-8859-1", msg,
    4555                         (msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen), caps_aim);
     4544                aim_locate_setprofile(od->sess, NULL, NULL, 0, "iso-8859-1", msg,
     4545                        (msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen));
    45564546                g_free(msg);
    45574547                gc->away = g_strndup(text_html, od->rights.maxawaymsglen);
    45584548        } else {
    45594549                msglen = strlen(text_html);
    4560                 aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "us-ascii", text_html,
    4561                         (msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen), caps_aim);
     4550                aim_locate_setprofile(od->sess, NULL, NULL, 0, "us-ascii", text_html,
     4551                        (msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen));
    45624552                gc->away = g_strndup(text_html, od->rights.maxawaymsglen);
    45634553        }
     
    45794569}
    45804570
    4581 static void oscar_set_away_icq(GaimConnection *gc, struct oscar_data *od, const char *state, const char *message)
     4571static void oscar_set_away_icq(GaimConnection *gc, OscarData *od, const char *state, const char *message)
    45824572{
    45834573        GaimAccount *account = gaim_connection_get_account(gc);
     
    46314621static void oscar_set_away(GaimConnection *gc, const char *state, const char *message)
    46324622{
    4633         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     4623        OscarData *od = (OscarData *)gc->proto_data;
    46344624
    46354625        if (od->icq)
     
    46424632
    46434633static void oscar_warn(GaimConnection *gc, const char *name, int anon) {
    4644         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     4634        OscarData *od = (OscarData *)gc->proto_data;
    46454635        aim_im_warn(od->sess, od->conn, name, anon ? AIM_WARN_ANON : 0);
    46464636}
     
    46484638static void oscar_dir_search(GaimConnection *gc, const char *first, const char *middle, const char *last,
    46494639                             const char *maiden, const char *city, const char *state, const char *country, const char *email) {
    4650         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     4640        OscarData *od = (OscarData *)gc->proto_data;
    46514641        if (strlen(email))
    46524642                aim_search_address(od->sess, od->conn, email);
     
    46544644
    46554645static void oscar_add_buddy(GaimConnection *gc, const char *name, GaimGroup *g) {
    4656         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     4646        OscarData *od = (OscarData *)gc->proto_data;
    46574647#ifdef NOSSI
    46584648        aim_add_buddy(od->sess, od->conn, name);
     
    46734663
    46744664static void oscar_add_buddies(GaimConnection *gc, GList *buddies) {
    4675         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     4665        OscarData *od = (OscarData *)gc->proto_data;
    46764666#ifdef NOSSI
    46774667        char buf[MSG_LEN];
     
    46794669        while (buddies) {
    46804670                if (n > MSG_LEN - 18) {
    4681                         aim_bos_setbuddylist(od->sess, od->conn, buf);
     4671                        aim_buddylist_set(od->sess, od->conn, buf);
    46824672                        n = 0;
    46834673                }
     
    46854675                buddies = buddies->next;
    46864676        }
    4687         aim_bos_setbuddylist(od->sess, od->conn, buf);
     4677        aim_buddylist_set(od->sess, od->conn, buf);
    46884678#else
    46894679        if (od->sess->ssi.received_data) {
    46904680                while (buddies) {
    4691                         GaimBuddy *buddy = gaim_find_buddy(gc->account, (const char *)buddies->data);
    4692                         GaimGroup *group = gaim_find_buddys_group(buddy);
    4693                         if (buddy && group) {
    4694                                 gaim_debug(GAIM_DEBUG_INFO, "oscar",
    4695                                                    "ssi: adding buddy %s to group %s\n", (const char *)buddies->data, group->name);
    4696                                 aim_ssi_addbuddy(od->sess, buddy->name, group->name, gaim_get_buddy_alias_only(buddy), NULL, NULL, 0);
    4697                         }
     4681                        oscar_add_buddy(gc, (const char *)buddies->data, NULL);
    46984682                        buddies = buddies->next;
    46994683                }
     
    47034687
    47044688static void oscar_remove_buddy(GaimConnection *gc, const char *name, const char *group) {
    4705         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     4689        OscarData *od = (OscarData *)gc->proto_data;
    47064690#ifdef NOSSI
    47074691        aim_remove_buddy(od->sess, od->conn, name);
     
    47164700
    47174701static void oscar_remove_buddies(GaimConnection *gc, GList *buddies, const char *group) {
    4718         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     4702        OscarData *od = (OscarData *)gc->proto_data;
    47194703#ifdef NOSSI
    47204704        GList *cur;
     
    47354719#ifndef NOSSI
    47364720static void oscar_move_buddy(GaimConnection *gc, const char *name, const char *old_group, const char *new_group) {
    4737         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     4721        OscarData *od = (OscarData *)gc->proto_data;
    47384722        if (od->sess->ssi.received_data && strcmp(old_group, new_group)) {
    47394723                gaim_debug(GAIM_DEBUG_INFO, "oscar",
     
    47444728
    47454729static void oscar_alias_buddy(GaimConnection *gc, const char *name, const char *alias) {
    4746         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     4730        OscarData *od = (OscarData *)gc->proto_data;
    47474731        if (od->sess->ssi.received_data) {
    47484732                char *gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, name);
     
    47564740
    47574741static void oscar_rename_group(GaimConnection *g, const char *old_group, const char *new_group, GList *members) {
    4758         struct oscar_data *od = (struct oscar_data *)g->proto_data;
     4742        OscarData *od = (OscarData *)g->proto_data;
    47594743
    47604744        if (od->sess->ssi.received_data) {
     
    47804764static int gaim_ssi_parseerr(aim_session_t *sess, aim_frame_t *fr, ...) {
    47814765        GaimConnection *gc = sess->aux_data;
    4782         struct oscar_data *od = gc->proto_data;
     4766        OscarData *od = gc->proto_data;
    47834767        va_list ap;
    47844768        fu16_t reason;
     
    48074791static int gaim_ssi_parserights(aim_session_t *sess, aim_frame_t *fr, ...) {
    48084792        GaimConnection *gc = sess->aux_data;
    4809         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     4793        OscarData *od = (OscarData *)gc->proto_data;
    48104794        int numtypes, i;
    48114795        fu16_t *maxitems;
     
    48404824        GaimConnection *gc = sess->aux_data;
    48414825        GaimAccount *account = gaim_connection_get_account(gc);
    4842         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     4826        OscarData *od = (OscarData *)gc->proto_data;
    48434827        struct aim_ssi_item *curitem;
    48444828        int tmp;
     
    48624846        /* Add from server list to local list */
    48634847        for (curitem=sess->ssi.local; curitem; curitem=curitem->next) {
     4848                if ((curitem->name == NULL) || (g_utf8_validate(curitem->name, -1, NULL)))
    48644849                switch (curitem->type) {
    48654850                        case 0x0000: { /* Buddy */
    48664851                                if (curitem->name) {
    48674852                                        char *gname = aim_ssi_itemlist_findparentname(sess->ssi.local, curitem->name);
    4868                                         char *gname_utf8 = gaim_try_conv_to_utf8(gname);
     4853                                        char *gname_utf8 = gname ? gaim_utf8_try_convert(gname) : NULL;
    48694854                                        char *alias = aim_ssi_getalias(sess->ssi.local, gname, curitem->name);
    4870                                         char *alias_utf8 = gaim_try_conv_to_utf8(alias);
     4855                                        char *alias_utf8 = alias ? gaim_utf8_try_convert(alias) : NULL;
    48714856                                        GaimBuddy *buddy = gaim_find_buddy(gc->account, curitem->name);
    48724857                                        /* Should gname be freed here? -- elb */
     
    48934878                                                export = TRUE;
    48944879                                        }
    4895                                         free(gname_utf8);
    4896                                         free(alias_utf8);
     4880                                        g_free(gname_utf8);
     4881                                        g_free(alias_utf8);
    48974882                                }
    48984883                        } break;
     
    49584943                GaimGroup *group;
    49594944                GaimBuddy *buddy;
    4960                 struct gaim_buddy_list *blist;
     4945                GaimBuddyList *blist;
    49614946                GSList *cur;
    49624947
     
    49754960                                                buddy = (GaimBuddy *)bnode;
    49764961                                                if (buddy->account == gc->account) {
    4977                                                         gchar *servernick = gaim_buddy_get_setting(buddy, "servernick");
    4978                                                         if (servernick) {
     4962                                                        const char *servernick = gaim_buddy_get_setting(buddy, "servernick");
     4963                                                        if (servernick)
    49794964                                                                serv_got_alias(gc, buddy->name, servernick);
    4980                                                                 g_free(servernick);
    4981                                                         }
     4965
    49824966                                                        if (aim_ssi_itemlist_exists(sess->ssi.local, buddy->name)) {
    49834967                                                                /* Store local alias on server */
     
    50615045                        }
    50625046
    5063                         case 0x000e: { /* contact requires authorization */
     5047                        case 0x000e: { /* buddy requires authorization */
    50645048                                if ((retval->action == AIM_CB_SSI_ADD) && (retval->name))
    50655049                                        gaim_auth_sendrequest(gc, retval->name);
     
    51125096        gaim_request_yes_no(gc, NULL, _("Authorization Given"), dialog_msg,
    51135097                                                0, data,
    5114                                                 G_CALLBACK(gaim_icq_contactadd),
     5098                                                G_CALLBACK(gaim_icq_buddyadd),
    51155099                                                G_CALLBACK(oscar_free_name_data));
    51165100
     
    51855169        if (reply) {
    51865170                /* Granted */
    5187                 dialog_msg = g_strdup_printf(_("The user %s has granted your request to add them to your contact list."), nombre);
     5171                dialog_msg = g_strdup_printf(_("The user %s has granted your request to add them to your buddy list."), nombre);
    51885172                gaim_notify_info(gc, NULL, _("Authorization Granted"), dialog_msg);
    51895173        } else {
    51905174                /* Denied */
    5191                 dialog_msg = g_strdup_printf(_("The user %s has denied your request to add them to your contact list for the following reason:\n%s"), nombre, msg ? msg : _("No reason given."));
     5175                dialog_msg = g_strdup_printf(_("The user %s has denied your request to add them to your buddy list for the following reason:\n%s"), nombre, msg ? msg : _("No reason given."));
    51925176                gaim_notify_info(gc, NULL, _("Authorization Denied"), dialog_msg);
    51935177        }
     
    52115195        gaim_debug(GAIM_DEBUG_INFO, "oscar",
    52125196                           "ssi: %s added you to their buddy list\n", sn);
    5213         show_got_added(gc, NULL, sn, (buddy ? gaim_get_buddy_alias_only(buddy) : NULL), NULL);
     5197        gaim_account_notify_added(gc->account, NULL, sn, (buddy ? gaim_get_buddy_alias_only(buddy) : NULL), NULL);
    52145198
    52155199        return 1;
     
    52385222
    52395223static void oscar_join_chat(GaimConnection *g, GHashTable *data) {
    5240         struct oscar_data *od = (struct oscar_data *)g->proto_data;
     5224        OscarData *od = (OscarData *)g->proto_data;
    52415225        aim_conn_t *cur;
    52425226        char *name, *exchange;
     
    52645248
    52655249static void oscar_chat_invite(GaimConnection *g, int id, const char *message, const char *name) {
    5266         struct oscar_data *od = (struct oscar_data *)g->proto_data;
     5250        OscarData *od = (OscarData *)g->proto_data;
    52675251        struct chat_connection *ccon = find_oscar_chat(g, id);
    52685252       
     
    52755259
    52765260static void oscar_chat_leave(GaimConnection *g, int id) {
    5277         struct oscar_data *od = g ? (struct oscar_data *)g->proto_data : NULL;
     5261        OscarData *od = g ? (OscarData *)g->proto_data : NULL;
    52785262        GSList *bcs = g->buddy_chats;
    52795263        GaimConversation *b = NULL;
     
    52845268                count++;
    52855269                b = (GaimConversation *)bcs->data;
    5286                 if (id == gaim_chat_get_id(GAIM_CHAT(b)))
     5270                if (id == gaim_conv_chat_get_id(GAIM_CONV_CHAT(b)))
    52875271                        break;
    52885272                bcs = bcs->next;
     
    52965280                           "Attempting to leave room %s (currently in %d rooms)\n", b->name, count);
    52975281       
    5298         c = find_oscar_chat(g, gaim_chat_get_id(GAIM_CHAT(b)));
     5282        c = find_oscar_chat(g, gaim_conv_chat_get_id(GAIM_CONV_CHAT(b)));
    52995283        if (c != NULL) {
    53005284                if (od)
     
    53095293        }
    53105294        /* we do this because with Oscar it doesn't tell us we left */
    5311         serv_got_chat_left(g, gaim_chat_get_id(GAIM_CHAT(b)));
     5295        serv_got_chat_left(g, gaim_conv_chat_get_id(GAIM_CONV_CHAT(b)));
    53125296}
    53135297
    53145298static int oscar_chat_send(GaimConnection *g, int id, const char *message) {
    5315         struct oscar_data *od = (struct oscar_data *)g->proto_data;
     5299        OscarData *od = (OscarData *)g->proto_data;
    53165300        GSList *bcs = g->buddy_chats;
    53175301        GaimConversation *b = NULL;
     
    53225306        while (bcs) {
    53235307                b = (GaimConversation *)bcs->data;
    5324                 if (id == gaim_chat_get_id(GAIM_CHAT(b)))
     5308                if (id == gaim_conv_chat_get_id(GAIM_CONV_CHAT(b)))
    53255309                        break;
    53265310                bcs = bcs->next;
     
    53575341                return -E2BIG;
    53585342
    5359         buf2 = strip_html(buf);
     5343        buf2 = gaim_markup_strip_html(buf);
    53605344        if (strlen(buf2) > c->maxvis) {
    53615345                g_free(buf2);
     
    53845368static void oscar_list_emblems(GaimBuddy *b, char **se, char **sw, char **nw, char **ne)
    53855369{
     5370        GaimAccount *account = NULL;
     5371        GaimConnection *gc = NULL;
     5372        OscarData *od = NULL;
    53865373        char *emblems[4] = {NULL,NULL,NULL,NULL};
    53875374        int i = 0;
     5375        aim_userinfo_t *userinfo = NULL;
     5376
     5377        if (b != NULL)
     5378                account = b->account;
     5379        if (account != NULL)
     5380                gc = account->gc;
     5381        if (gc != NULL)
     5382                od = gc->proto_data;
    53885383
    53895384        if (!GAIM_BUDDY_IS_ONLINE(b)) {
    5390                 GaimAccount *account;
    5391                 GaimConnection *gc;
    5392                 struct oscar_data *od;
    53935385                char *gname;
    5394                 if ((b->name) && (account = b->account) && (gc = account->gc) &&
    5395                         (od = gc->proto_data) && (od->sess->ssi.received_data) &&
     5386                if ((b->name) && (od) && (od->sess->ssi.received_data) &&
    53965387                        (gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, b->name)) &&
    53975388                        (aim_ssi_waitingforauth(od->sess->ssi.local, gname, b->name))) {
     
    54325423/*      if (b->uc & UC_UNCONFIRMED && i < 4)
    54335424                emblems[i++] = "unconfirmed"; */
     5425
     5426        if ((i < 4) && (od != NULL)) {
     5427                userinfo = aim_locate_finduserinfo(od->sess, b->name);
     5428                if ((userinfo != NULL) && (userinfo->capabilities & AIM_CAPS_SECUREIM))
     5429                        emblems[i++] = "secure";
     5430        }
     5431
    54345432        *se = emblems[0];
    54355433        *sw = emblems[1];
     
    54405438static char *oscar_tooltip_text(GaimBuddy *b) {
    54415439        GaimConnection *gc = b->account->gc;
    5442         struct oscar_data *od = gc->proto_data;
    5443         struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, normalize(b->name));
    5444         gchar *tmp, *yay = g_strdup("");
     5440        OscarData *od = gc->proto_data;
     5441        struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(b->account, b->name));
     5442        aim_userinfo_t *userinfo = aim_locate_finduserinfo(od->sess, b->name);
     5443        gchar *tmp = NULL, *ret = g_strdup("");
    54455444
    54465445        if (GAIM_BUDDY_IS_ONLINE(b)) {
    54475446                if (isdigit(b->name[0])) {
    5448                         char *tmp, *status;
     5447                        char *status;
    54495448                        status = gaim_icq_status((b->uc & 0xffff0000) >> 16);
    5450                         tmp = yay;
    5451                         yay = g_strconcat(tmp, _("<b>Status:</b> "), status, "\n", NULL);
     5449                        tmp = ret;
     5450                        ret = g_strconcat(tmp, _("<b>Status:</b> "), status, "\n", NULL);
    54525451                        g_free(tmp);
    54535452                        g_free(status);
    54545453                }
    54555454
    5456                 if (bi) {
    5457                         char *tstr = sec_to_text(time(NULL) - bi->signon +
     5455                if (userinfo != NULL) {
     5456                        char *tstr = gaim_str_seconds_to_string(time(NULL) - userinfo->onlinesince +
    54585457                                (gc->login_time_official ? gc->login_time_official - gc->login_time : 0));
    5459                         tmp = yay;
    5460                         yay = g_strconcat(tmp, _("<b>Logged In:</b> "), tstr, "\n", NULL);
    5461                         free(tmp);
    5462                         free(tstr);
    5463 
    5464                         if (bi->ipaddr) {
    5465                                 char *tstr =  g_strdup_printf("%hhd.%hhd.%hhd.%hhd",
    5466                                                                 (bi->ipaddr & 0xff000000) >> 24,
    5467                                                                 (bi->ipaddr & 0x00ff0000) >> 16,
    5468                                                                 (bi->ipaddr & 0x0000ff00) >> 8,
    5469                                                                 (bi->ipaddr & 0x000000ff));
    5470                                 tmp = yay;
    5471                                 yay = g_strconcat(tmp, _("<b>IP Address:</b> "), tstr, "\n", NULL);
    5472                                 free(tmp);
    5473                                 free(tstr);
    5474                         }
    5475 
    5476                         if (bi->caps) {
    5477                                 char *caps = caps_string(bi->caps);
    5478                                 tmp = yay;
    5479                                 yay = g_strconcat(tmp, _("<b>Capabilities:</b> "), caps, "\n", NULL);
    5480                                 free(tmp);
    5481                         }
    5482 
    5483                         if (bi->availmsg && !(b->uc & UC_UNAVAILABLE)) {
    5484                                 gchar *escaped = g_markup_escape_text(bi->availmsg, strlen(bi->availmsg));
    5485                                 tmp = yay;
    5486                                 yay = g_strconcat(tmp, _("<b>Available:</b> "), escaped, "\n", NULL);
    5487                                 free(tmp);
    5488                                 g_free(escaped);
     5458                        tmp = ret;
     5459                        ret = g_strconcat(tmp, _("<b>Logged In:</b> "), tstr, "\n", NULL);
     5460                        g_free(tmp);
     5461                        g_free(tstr);
     5462                }
     5463
     5464                if ((bi != NULL) && (bi->ipaddr)) {
     5465                        char *tstr =  g_strdup_printf("%hhu.%hhu.%hhu.%hhu",
     5466                                                        (bi->ipaddr & 0xff000000) >> 24,
     5467                                                        (bi->ipaddr & 0x00ff0000) >> 16,
     5468                                                        (bi->ipaddr & 0x0000ff00) >> 8,
     5469                                                        (bi->ipaddr & 0x000000ff));
     5470                        tmp = ret;
     5471                        ret = g_strconcat(tmp, _("<b>IP Address:</b> "), tstr, "\n", NULL);
     5472                        g_free(tmp);
     5473                        g_free(tstr);
     5474                }
     5475
     5476                if ((userinfo != NULL) && (userinfo->capabilities)) {
     5477                        char *caps = caps_string(userinfo->capabilities);
     5478                        tmp = ret;
     5479                        ret = g_strconcat(tmp, _("<b>Capabilities:</b> "), caps, "\n", NULL);
     5480                        g_free(tmp);
     5481                }
     5482
     5483                if ((bi != NULL) && (bi->availmsg != NULL) && !(b->uc & UC_UNAVAILABLE)) {
     5484                        gchar *escaped = g_markup_escape_text(bi->availmsg, strlen(bi->availmsg));
     5485                        tmp = ret;
     5486                        ret = g_strconcat(tmp, _("<b>Available:</b> "), escaped, "\n", NULL);
     5487                        g_free(tmp);
     5488                        g_free(escaped);
     5489                }
     5490
     5491                if ((userinfo != NULL) && (userinfo->flags & AIM_FLAG_AWAY) && (userinfo->away_len > 0) && (userinfo->away != NULL) && (userinfo->away_encoding != NULL)) {
     5492                        gchar *away_utf8 = oscar_encoding_to_utf8(userinfo->away_encoding, userinfo->away, userinfo->away_len);
     5493                        if (away_utf8 != NULL) {
     5494                                gchar *tmp1, *tmp2;
     5495                                const char *tmp3;
     5496                                tmp1 = gaim_strreplace(away_utf8, "<BR>", "\n");
     5497                                tmp2 = gaim_markup_strip_html(tmp1);
     5498                                g_free(tmp1);
     5499                                tmp1 = g_markup_escape_text(tmp2, strlen(tmp2));
     5500                                g_free(tmp2);
     5501                                tmp3 = gaim_str_sub_away_formatters(tmp1, gaim_account_get_username(gaim_connection_get_account(gc)));
     5502                                g_free(tmp1);
     5503                                tmp = ret;
     5504                                ret = g_strconcat(tmp, _("<b>Away Message:</b> "), tmp3, "\n", NULL);
     5505                                g_free(tmp);
     5506                                g_free(away_utf8);
    54895507                        }
    54905508                }
     
    54925510                char *gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, b->name);
    54935511                if (aim_ssi_waitingforauth(od->sess->ssi.local, gname, b->name)) {
    5494                         tmp = yay;
    5495                         yay = g_strconcat(tmp, _("<b>Status:</b> Not Authorized"), "\n", NULL);
     5512                        tmp = ret;
     5513                        ret = g_strconcat(tmp, _("<b>Status:</b> Not Authorized"), "\n", NULL);
    54965514                        g_free(tmp);
    54975515                } else {
    5498                         tmp = yay;
    5499                         yay = g_strconcat(tmp, _("<b>Status:</b> Offline"), "\n", NULL);
     5516                        tmp = ret;
     5517                        ret = g_strconcat(tmp, _("<b>Status:</b> Offline"), "\n", NULL);
    55005518                        g_free(tmp);
    55015519                }
     
    55035521
    55045522        /* remove the trailing newline character */
    5505         if (yay)
    5506                 yay[strlen(yay)-1] = '\0';
    5507         return yay;
     5523        if (ret)
     5524                ret[strlen(ret)-1] = '\0';
     5525        return ret;
    55085526}
    55095527
    55105528static char *oscar_status_text(GaimBuddy *b) {
    55115529        GaimConnection *gc = b->account->gc;
    5512         struct oscar_data *od = gc->proto_data;
     5530        OscarData *od = gc->proto_data;
    55135531        gchar *ret = NULL;
    55145532
     
    55195537                        ret = g_strdup(_("Away"));
    55205538        } else if (GAIM_BUDDY_IS_ONLINE(b)) {
    5521                 struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, normalize(b->name));
     5539                struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(b->account, b->name));
    55225540                if (bi->availmsg)
    55235541                        ret = g_markup_escape_text(bi->availmsg, strlen(bi->availmsg));
     
    55365554static int oscar_icon_req(aim_session_t *sess, aim_frame_t *fr, ...) {
    55375555        GaimConnection *gc = sess->aux_data;
    5538         struct oscar_data *od = gc->proto_data;
     5556        OscarData *od = gc->proto_data;
    55395557        va_list ap;
    55405558        fu16_t type;
    55415559        fu8_t flags = 0, length = 0;
    55425560        char *md5 = NULL;
     5561
    55435562
    55445563        va_start(ap, fr);
     
    55985617static int gaim_odc_initiate(aim_session_t *sess, aim_frame_t *fr, ...) {
    55995618        GaimConnection *gc = sess->aux_data;
    5600         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     5619        OscarData *od = (OscarData *)gc->proto_data;
    56015620        GaimConversation *cnv;
    56025621        struct direct_im *dim;
     
    56465665        double percent;
    56475666        GaimConnection *gc = sess->aux_data;
    5648         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     5667        OscarData *od = (OscarData *)gc->proto_data;
    56495668        GaimConversation *c;
    56505669        struct direct_im *dim;
     
    56625681        }
    56635682        /* XXX is this really necessary? */
    5664         while (gtk_events_pending())
    5665                 gtk_main_iteration();
     5683        gaim_core_mainloop_finish_events();
    56665684
    56675685        c = gaim_find_conversation_with_account(sn, gaim_connection_get_account(gc));
     
    57055723static int gaim_odc_incoming(aim_session_t *sess, aim_frame_t *fr, ...) {
    57065724        GaimConnection *gc = sess->aux_data;
    5707         GaimImFlags imflags = 0;
     5725        GaimConvImFlags imflags = 0;
    57085726        GString *newmsg = g_string_new("");
    57095727        GSList *images = NULL;
     
    57265744
    57275745        if (isawaymsg)
    5728                 imflags |= GAIM_IM_AUTO_RESP;
     5746                imflags |= GAIM_CONV_IM_AUTO_RESP;
    57295747
    57305748        /* message has a binary trailer */
     
    57905808                /* set the flag if we caught any images */
    57915809                if (images)
    5792                         imflags |= GAIM_IM_IMAGES;
     5810                        imflags |= GAIM_CONV_IM_IMAGES;
    57935811        } else {
    57945812                g_string_append_len(newmsg, msg, len);
     
    58405858}
    58415859
    5842 static int gaim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *message, GaimImFlags imflags) {
     5860static int gaim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *message, GaimConvImFlags imflags) {
    58435861        char *buf;
    58445862        size_t len;
    58455863        int ret;
    58465864
    5847         if (imflags & GAIM_IM_IMAGES) {
     5865        if (imflags & GAIM_CONV_IM_IMAGES) {
    58485866                GString *msg = g_string_new("");
    58495867                GString *data = g_string_new("<BINARY>");
     
    58725890                                        g_string_append_printf(msg,
    58735891                                                "<IMG SRC=\"file://%s\" ID=\"%d\" DATASIZE=\"%d\">",
    5874                                                 image->filename, oscar_id, image->size);
     5892                                                image->filename, oscar_id, (int)image->size);
    58755893                                else
    58765894                                        g_string_append_printf(msg,
    58775895                                                "<IMG ID=\"%d\" DATASIZE=\"%d\">",
    5878                                                 oscar_id, image->size);
     5896                                                oscar_id, (int)image->size);
    58795897
    58805898                                /* ... and append the data to the binary section ... */
    58815899                                g_string_append_printf(data, "<DATA ID=\"%d\" SIZE=\"%d\">",
    5882                                         oscar_id, image->size);
     5900                                        oscar_id, (int)image->size);
    58835901                                data = g_string_append_len(data, image->data, image->size);
    58845902                                data = g_string_append(data, "</DATA>");
     
    59155933
    59165934        /* XXX - The last parameter below is the encoding.  Let Paco-Paco do something with it. */
    5917         if (imflags & GAIM_IM_AUTO_RESP)
     5935        if (imflags & GAIM_CONV_IM_AUTO_RESP)
    59185936                ret =  aim_odc_send_im(sess, conn, buf, len, 0, 1);
    59195937        else
     
    59375955static void oscar_direct_im(struct ask_do_dir_im *data) {
    59385956        GaimConnection *gc = data->gc;
    5939         struct oscar_data *od;
     5957        OscarData *od;
    59405958        struct direct_im *dim;
    59415959
     
    59465964        }
    59475965
    5948         od = (struct oscar_data *)gc->proto_data;
     5966        od = (OscarData *)gc->proto_data;
    59495967
    59505968        dim = find_direct_im(od, data->who);
     
    60026020static void oscar_set_permit_deny(GaimConnection *gc) {
    60036021        GaimAccount *account = gaim_connection_get_account(gc);
    6004         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     6022        OscarData *od = (OscarData *)gc->proto_data;
    60056023#ifdef NOSSI
    60066024        GSList *list, *g = gaim_blist_groups(), *g1;
     
    60666084                oscar_set_permit_deny(gc);
    60676085#else
    6068         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     6086        OscarData *od = (OscarData *)gc->proto_data;
    60696087        gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: About to add a permit\n");
    60706088        if (od->sess->ssi.received_data)
     
    60786096                oscar_set_permit_deny(gc);
    60796097#else
    6080         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     6098        OscarData *od = (OscarData *)gc->proto_data;
    60816099        gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: About to add a deny\n");
    60826100        if (od->sess->ssi.received_data)
     
    60906108                oscar_set_permit_deny(gc);
    60916109#else
    6092         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     6110        OscarData *od = (OscarData *)gc->proto_data;
    60936111        gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: About to delete a permit\n");
    60946112        if (od->sess->ssi.received_data)
     
    61026120                oscar_set_permit_deny(gc);
    61036121#else
    6104         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
     6122        OscarData *od = (OscarData *)gc->proto_data;
    61056123        gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: About to delete a deny\n");
    61066124        if (od->sess->ssi.received_data)
     
    61116129static GList *oscar_away_states(GaimConnection *gc)
    61126130{
    6113         struct oscar_data *od = gc->proto_data;
     6131        OscarData *od = gc->proto_data;
    61146132        GList *m = NULL;
    61156133
     
    61286146}
    61296147
     6148static void oscar_ssi_editcomment(struct name_data *data, const char *text) {
     6149        OscarData *od = data->gc->proto_data;
     6150        GaimBuddy *b;
     6151        GaimGroup *g;
     6152
     6153        if (!(b = gaim_find_buddy(gaim_connection_get_account(data->gc), data->name))) {
     6154                oscar_free_name_data(data);
     6155                return;
     6156        }
     6157
     6158        if (!(g = gaim_find_buddys_group(b))) {
     6159                oscar_free_name_data(data);
     6160                return;
     6161        }
     6162
     6163        aim_ssi_editcomment(od->sess, g->name, data->name, text);
     6164        oscar_free_name_data(data);
     6165}
     6166
     6167static void oscar_buddycb_edit_comment(GaimConnection *gc, const char *name) {
     6168        OscarData *od = gc->proto_data;
     6169        struct name_data *data = g_new(struct name_data, 1);
     6170        GaimBuddy *b;
     6171        GaimGroup *g;
     6172        char *comment;
     6173        gchar *comment_utf8;
     6174
     6175        if (!(b = gaim_find_buddy(gaim_connection_get_account(gc), name)))
     6176                return;
     6177        if (!(g = gaim_find_buddys_group(b)))
     6178                return;
     6179        comment = aim_ssi_getcomment(od->sess->ssi.local, g->name, name);
     6180        comment_utf8 = comment ? gaim_utf8_try_convert(comment) : NULL;
     6181
     6182        data->gc = gc;
     6183        data->name = g_strdup(name);
     6184        data->nick = NULL;
     6185
     6186        gaim_request_input(gc, NULL, _("Buddy Comment:"), NULL,
     6187                                           comment_utf8, TRUE, FALSE,
     6188                                           _("OK"), G_CALLBACK(oscar_ssi_editcomment),
     6189                                           _("Cancel"), G_CALLBACK(oscar_free_name_data),
     6190                                           data);
     6191
     6192        free(comment);
     6193        g_free(comment_utf8);
     6194}
     6195
    61306196static GList *oscar_buddy_menu(GaimConnection *gc, const char *who) {
    6131         struct oscar_data *od = gc->proto_data;
     6197        OscarData *od = gc->proto_data;
    61326198        GList *m = NULL;
    61336199        struct proto_buddy_menu *pbm;
     6200
     6201        pbm = g_new0(struct proto_buddy_menu, 1);
     6202        pbm->label = _("Edit Buddy Comment");
     6203        pbm->callback = oscar_buddycb_edit_comment;
     6204        pbm->gc = gc;
     6205        m = g_list_append(m, pbm);
    61346206
    61356207        if (od->icq) {
     
    61436215        } else {
    61446216                GaimBuddy *b = gaim_find_buddy(gc->account, who);
    6145                 struct buddyinfo *bi;
     6217                aim_userinfo_t *userinfo;
    61466218
    61476219                if (b)
    6148                         bi = g_hash_table_lookup(od->buddyinfo, normalize(b->name));
    6149 
    6150                 if (b && bi && aim_sncmp(gaim_account_get_username(gaim_connection_get_account(gc)), who) && GAIM_BUDDY_IS_ONLINE(b)) {
    6151                         if (bi->caps & AIM_CAPS_DIRECTIM) {
     6220                        userinfo = aim_locate_finduserinfo(od->sess, b->name);
     6221
     6222                if (b && userinfo && aim_sncmp(gaim_account_get_username(gaim_connection_get_account(gc)), who) && GAIM_BUDDY_IS_ONLINE(b)) {
     6223                        if (userinfo->capabilities & AIM_CAPS_DIRECTIM) {
    61526224                                pbm = g_new0(struct proto_buddy_menu, 1);
    61536225                                pbm->label = _("Direct IM");
     
    61576229                        }
    61586230
    6159                         if (bi->caps & AIM_CAPS_SENDFILE) {
     6231                        if (userinfo->capabilities & AIM_CAPS_SENDFILE) {
    61606232                                pbm = g_new0(struct proto_buddy_menu, 1);
    61616233                                pbm->label = _("Send File");
     
    61656237                        }
    61666238#if 0
    6167                         if (bi->caps & AIM_CAPS_GETFILE) {
     6239                        if (userinfo->capabilities & AIM_CAPS_GETFILE) {
    61686240                                pbm = g_new0(struct proto_buddy_menu, 1);
    61696241                                pbm->label = _("Get File");
     
    61916263
    61926264static void oscar_format_screenname(GaimConnection *gc, const char *nick) {
    6193         struct oscar_data *od = gc->proto_data;
     6265        OscarData *od = gc->proto_data;
    61946266        if (!aim_sncmp(gaim_account_get_username(gaim_connection_get_account(gc)), nick)) {
    61956267                if (!aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH)) {
     
    62176289static void oscar_confirm_account(GaimConnection *gc)
    62186290{
    6219         struct oscar_data *od = gc->proto_data;
     6291        OscarData *od = gc->proto_data;
    62206292        aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH);
    62216293
     
    62306302static void oscar_show_email(GaimConnection *gc)
    62316303{
    6232         struct oscar_data *od = gc->proto_data;
     6304        OscarData *od = gc->proto_data;
    62336305        aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH);
    62346306
     
    62436315static void oscar_change_email(GaimConnection *gc, const char *email)
    62446316{
    6245         struct oscar_data *od = gc->proto_data;
     6317        OscarData *od = gc->proto_data;
    62466318        aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH);
    62476319
     
    62666338static void oscar_show_awaitingauth(GaimConnection *gc)
    62676339{
    6268         struct oscar_data *od = gc->proto_data;
     6340        OscarData *od = gc->proto_data;
    62696341        gchar *nombre, *text, *tmp;
    62706342        GaimBlistNode *gnode, *cnode, *bnode;
     
    63126384}
    63136385
     6386static void search_by_email_cb(GaimConnection *gc, const char *email)
     6387{
     6388        serv_dir_search(gc, "", "", "", "", "", "", "", email);
     6389}
     6390
     6391static void oscar_show_find_email(GaimConnection *gc)
     6392{
     6393        gaim_request_input(gc, _("Find Buddy by E-mail"),
     6394                                           _("Search for a buddy by e-mail address"),
     6395                                           _("Type the e-mail address of the buddy you are "
     6396                                                 "searching for."),
     6397                                           NULL, FALSE, FALSE,
     6398                                           _("Search"), G_CALLBACK(search_by_email_cb),
     6399                                           _("Cancel"), NULL, gc);
     6400}
     6401
    63146402#if 0
    63156403static void oscar_setavailmsg(GaimConnection *gc, char *text) {
    6316         struct oscar_data *od = (struct oscar_data *)gc->proto_data;
    6317 
     6404        OscarData *od = (OscarData *)gc->proto_data;
     6405
     6406        aim_locate_setprofile(od->sess, NULL, NULL, 0, NULL, "", 0);
    63186407        aim_srv_setavailmsg(od->sess, text);
    63196408}
     
    63216410static void oscar_show_setavailmsg(GaimConnection *gc)
    63226411{
    6323         gaim_request_input(gc, NULL, _("Available Message:"),
    6324                                            NULL, _("Please talk to me, I'm lonely! (and single)"), TRUE, FALSE,
     6412        gaim_request_input(gc, NULL, _("Available Message:"), NULL,
     6413                                           _("I'm doing work and hoping for a distraction--IM me!"),
     6414                                           TRUE, FALSE,
    63256415                                           _("OK"), G_CALLBACK(oscar_setavailmsg),
    63266416                                           _("Cancel"), NULL,
     
    63296419#endif
    63306420
     6421static void oscar_show_set_info(GaimConnection *gc)
     6422{
     6423        gaim_account_request_change_user_info(gaim_connection_get_account(gc));
     6424}
     6425
     6426static void oscar_change_pass(GaimConnection *gc)
     6427{
     6428        gaim_account_request_change_password(gaim_connection_get_account(gc));
     6429}
     6430
    63316431static void oscar_show_chpassurl(GaimConnection *gc)
    63326432{
    6333         struct oscar_data *od = gc->proto_data;
     6433        OscarData *od = gc->proto_data;
    63346434        gchar *substituted = gaim_strreplace(od->sess->authinfo->chpassurl, "%s", gaim_account_get_username(gaim_connection_get_account(gc)));
    63356435        gaim_notify_uri(gc, substituted);
     
    63376437}
    63386438
     6439static void oscar_show_imforwardingurl(GaimConnection *gc)
     6440{
     6441        gaim_notify_uri(gc, "http://mymobile.aol.com/dbreg/register?action=imf&clientID=1");
     6442}
     6443
    63396444static void oscar_set_icon(GaimConnection *gc, const char *iconfile)
    63406445{
    6341         struct oscar_data *od = gc->proto_data;
     6446        OscarData *od = gc->proto_data;
    63426447        aim_session_t *sess = od->sess;
    63436448        FILE *file;
     
    63726477static GList *oscar_actions(GaimConnection *gc)
    63736478{
    6374         struct oscar_data *od = gc->proto_data;
     6479        OscarData *od = gc->proto_data;
    63756480        struct proto_actions_menu *pam;
    63766481        GList *m = NULL;
     
    63786483        pam = g_new0(struct proto_actions_menu, 1);
    63796484        pam->label = _("Set User Info");
    6380         pam->callback = show_set_info;
     6485        pam->callback = oscar_show_set_info;
    63816486        pam->gc = gc;
    63826487        m = g_list_append(m, pam);
     
    63926497        pam = g_new0(struct proto_actions_menu, 1);
    63936498        pam->label = _("Change Password");
    6394         pam->callback = show_change_passwd;
     6499        pam->callback = oscar_change_pass;
    63956500        pam->gc = gc;
    63966501        m = g_list_append(m, pam);
     
    64046509        }
    64056510
     6511        if (od->sess->authinfo->chpassurl) {
     6512                pam = g_new0(struct proto_actions_menu, 1);
     6513                pam->label = _("Configure IM Forwarding (URL)");
     6514                pam->callback = oscar_show_imforwardingurl;
     6515                pam->gc = gc;
     6516                m = g_list_append(m, pam);
     6517        }
     6518
    64066519        if (!od->icq) {
    64076520                /* AIM actions */
     
    64456558        pam = g_new0(struct proto_actions_menu, 1);
    64466559        pam->label = _("Search for Buddy by Email");
    6447         pam->callback = show_find_email;
     6560        pam->callback = oscar_show_find_email;
    64486561        pam->gc = gc;
    64496562        m = g_list_append(m, pam);
     
    64606573static void oscar_change_passwd(GaimConnection *gc, const char *old, const char *new)
    64616574{
    6462         struct oscar_data *od = gc->proto_data;
     6575        OscarData *od = gc->proto_data;
    64636576
    64646577        if (od->icq) {
     
    64796592static void oscar_convo_closed(GaimConnection *gc, const char *who)
    64806593{
    6481         struct oscar_data *od = gc->proto_data;
     6594        OscarData *od = gc->proto_data;
    64826595        struct direct_im *dim = find_direct_im(od, who);
    64836596
  • libfaim/popups.c

    r862371b rcf02dd6  
    2323        fu16_t width, height, delay;
    2424
    25         tl = aim_readtlvchain(bs);
     25        tl = aim_tlvlist_read(bs);
    2626
    27         msg = aim_gettlv_str(tl, 0x0001, 1);
    28         url = aim_gettlv_str(tl, 0x0002, 1);
    29         width = aim_gettlv16(tl, 0x0003, 1);
    30         height = aim_gettlv16(tl, 0x0004, 1);
    31         delay = aim_gettlv16(tl, 0x0005, 1);
     27        msg = aim_tlv_getstr(tl, 0x0001, 1);
     28        url = aim_tlv_getstr(tl, 0x0002, 1);
     29        width = aim_tlv_get16(tl, 0x0003, 1);
     30        height = aim_tlv_get16(tl, 0x0004, 1);
     31        delay = aim_tlv_get16(tl, 0x0005, 1);
    3232
    3333        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    3434                ret = userfunc(sess, rx, msg, url, width, height, delay);
    3535
    36         aim_freetlvchain(&tl);
     36        aim_tlvlist_free(&tl);
    3737        free(msg);
    3838        free(url);
  • libfaim/rxhandlers.c

    re374dee rcf02dd6  
    185185                return consumenonsnac(sess, fr, 0x0017, 0x0003);
    186186
    187         tlvlist = aim_readtlvchain(&fr->data);
    188 
    189         if (aim_gettlv(tlvlist, 0x0009, 1))
    190                 code = aim_gettlv16(tlvlist, 0x0009, 1);
    191 
    192         if (aim_gettlv(tlvlist, 0x000b, 1))
    193                 msg = aim_gettlv_str(tlvlist, 0x000b, 1);
     187        tlvlist = aim_tlvlist_read(&fr->data);
     188
     189        if (aim_tlv_gettlv(tlvlist, 0x0009, 1))
     190                code = aim_tlv_get16(tlvlist, 0x0009, 1);
     191
     192        if (aim_tlv_gettlv(tlvlist, 0x000b, 1))
     193                msg = aim_tlv_getstr(tlvlist, 0x000b, 1);
    194194
    195195        if ((userfunc = aim_callhandler(sess, fr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
    196196                ret = userfunc(sess, fr, code, msg);
    197197
    198         aim_freetlvchain(&tlvlist);
     198        aim_tlvlist_free(&tlvlist);
    199199
    200200        free(msg);
  • libfaim/search.c

    re374dee rcf02dd6  
    7878                searchaddr = (char *)snac2->data;
    7979
    80         tlvlist = aim_readtlvchain(bs);
    81         m = aim_counttlvchain(&tlvlist);
     80        tlvlist = aim_tlvlist_read(bs);
     81        m = aim_tlvlist_count(&tlvlist);
    8282
    83         /* XXX uhm. */
    84         while ((cur = aim_gettlv_str(tlvlist, 0x0001, j+1)) && j < m) {
     83        /* XXX uhm.
     84         * This is the only place that uses something other than 1 for the 3rd
     85         * parameter to aim_tlv_gettlv_whatever().
     86         */
     87        while ((cur = aim_tlv_getstr(tlvlist, 0x0001, j+1)) && j < m) {
    8588                buf = realloc(buf, (j+1) * (MAXSNLEN+1));
    8689
     
    9194        }
    9295
    93         aim_freetlvchain(&tlvlist);
     96        aim_tlvlist_free(&tlvlist);
    9497
    9598        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
  • libfaim/service.c

    re374dee rcf02dd6  
    109109        memset(&redir, 0, sizeof(redir));
    110110
    111         tlvlist = aim_readtlvchain(bs);
    112 
    113         if (!aim_gettlv(tlvlist, 0x000d, 1) ||
    114                         !aim_gettlv(tlvlist, 0x0005, 1) ||
    115                         !aim_gettlv(tlvlist, 0x0006, 1)) {
    116                 aim_freetlvchain(&tlvlist);
     111        tlvlist = aim_tlvlist_read(bs);
     112
     113        if (!aim_tlv_gettlv(tlvlist, 0x000d, 1) ||
     114                        !aim_tlv_gettlv(tlvlist, 0x0005, 1) ||
     115                        !aim_tlv_gettlv(tlvlist, 0x0006, 1)) {
     116                aim_tlvlist_free(&tlvlist);
    117117                return 0;
    118118        }
    119119
    120         redir.group = aim_gettlv16(tlvlist, 0x000d, 1);
    121         redir.ip = aim_gettlv_str(tlvlist, 0x0005, 1);
    122         redir.cookielen = aim_gettlv(tlvlist, 0x0006, 1)->length;
    123         redir.cookie = aim_gettlv_str(tlvlist, 0x0006, 1);
     120        redir.group = aim_tlv_get16(tlvlist, 0x000d, 1);
     121        redir.ip = aim_tlv_getstr(tlvlist, 0x0005, 1);
     122        redir.cookielen = aim_tlv_gettlv(tlvlist, 0x0006, 1)->length;
     123        redir.cookie = aim_tlv_getstr(tlvlist, 0x0006, 1);
    124124
    125125        /* Fetch original SNAC so we can get csi if needed */
     
    144144        free(origsnac);
    145145
    146         aim_freetlvchain(&tlvlist);
     146        aim_tlvlist_free(&tlvlist);
    147147
    148148        return ret;
     
    152152faim_internal int aim_reqrates(aim_session_t *sess, aim_conn_t *conn)
    153153{
    154         return aim_genericreq_n(sess, conn, 0x0001, 0x0006);
     154        return aim_genericreq_n_snacid(sess, conn, 0x0001, 0x0006);
    155155}
    156156
     
    492492faim_export int aim_reqpersonalinfo(aim_session_t *sess, aim_conn_t *conn)
    493493{
    494         return aim_genericreq_n(sess, conn, 0x0001, 0x000e);
     494        return aim_genericreq_n_snacid(sess, conn, 0x0001, 0x000e);
    495495}
    496496
     
    544544 *
    545545 */
    546 faim_export int aim_bos_setidle(aim_session_t *sess, aim_conn_t *conn, fu32_t idletime)
    547 {
     546faim_export int aim_srv_setidle(aim_session_t *sess, fu32_t idletime)
     547{
     548        aim_conn_t *conn;
     549
     550        if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_BOS)))
     551                return -EINVAL;
     552
    548553        return aim_genericreq_l(sess, conn, 0x0001, 0x0011, &idletime);
    549554}
     
    586591        }
    587592
    588         tl = aim_readtlvchain(bs);
    589 
    590         if (aim_gettlv(tl, 0x0005, 1))
    591                 ip = aim_gettlv_str(tl, 0x0005, 1);
    592 
    593         cktlv = aim_gettlv(tl, 0x0006, 1);
     593        tl = aim_tlvlist_read(bs);
     594
     595        if (aim_tlv_gettlv(tl, 0x0005, 1))
     596                ip = aim_tlv_getstr(tl, 0x0005, 1);
     597
     598        cktlv = aim_tlv_gettlv(tl, 0x0006, 1);
    594599
    595600        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    596601                ret = userfunc(sess, rx, ip, cktlv ? cktlv->value : NULL);
    597602
    598         aim_freetlvchain(&tl);
     603        aim_tlvlist_free(&tl);
    599604        free(ip);
    600605
     
    627632         * TLVs follow
    628633         */
    629         tlvlist = aim_readtlvchain(bs);
    630 
    631         msg = aim_gettlv_str(tlvlist, 0x000b, 1);
     634        tlvlist = aim_tlvlist_read(bs);
     635
     636        msg = aim_tlv_getstr(tlvlist, 0x000b, 1);
    632637
    633638        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
     
    636641        free(msg);
    637642
    638         aim_freetlvchain(&tlvlist);
     643        aim_tlvlist_free(&tlvlist);
    639644
    640645        return ret;
     
    661666 * really necessary.
    662667 *
     668 * Wha?  No?  Since when?  I think WinAIM sends an empty channel 3
     669 * SNAC as a no-op...
    663670 */
    664671faim_export int aim_nop(aim_session_t *sess, aim_conn_t *conn)
     
    761768        aim_putsnac(&fr->data, 0x0001, 0x001e, 0x0000, snacid);
    762769       
    763         aim_addtlvtochain32(&tl, 0x0006, data);
    764         aim_writetlvchain(&fr->data, &tl);
    765         aim_freetlvchain(&tl);
     770        aim_tlvlist_add_32(&tl, 0x0006, data);
     771        aim_tlvlist_write(&fr->data, &tl);
     772        aim_tlvlist_free(&tl);
    766773       
    767774        aim_tx_enqueue(sess, fr);
     
    788795                return -EINVAL;
    789796
    790         if (msg) {
     797        if (msg != NULL) {
    791798                if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + strlen(msg) + 8)))
    792799                        return -ENOMEM;
     
    795802                aim_putsnac(&fr->data, 0x0001, 0x001e, 0x0000, snacid);
    796803
    797                 aimbs_put16(&fr->data, 0x001d);
    798                 aimbs_put16(&fr->data, strlen(msg)+8);
     804                aimbs_put16(&fr->data, 0x001d); /* userinfo TLV type */
     805                aimbs_put16(&fr->data, strlen(msg)+8); /* total length of userinfo TLV data */
    799806                aimbs_put16(&fr->data, 0x0002);
    800807                aimbs_put8(&fr->data, 0x04);
     
    871878        offset = aimbs_get32(bs);
    872879        len = aimbs_get32(bs);
    873         list = aim_readtlvchain(bs);
    874 
    875         modname = aim_gettlv_str(list, 0x0001, 1);
     880        list = aim_tlvlist_read(bs);
     881
     882        modname = aim_tlv_getstr(list, 0x0001, 1);
    876883
    877884        faimdprintf(sess, 1, "data at 0x%08lx (%d bytes) of requested\n", offset, len, modname ? modname : "aim.exe");
     
    881888
    882889        free(modname);
    883         aim_freetlvchain(&list);
     890        aim_tlvlist_free(&list);
    884891
    885892        return ret;
     
    10681075}
    10691076
    1070 faim_internal int general_modfirst(aim_session_t *sess, aim_module_t *mod)
     1077faim_internal int service_modfirst(aim_session_t *sess, aim_module_t *mod)
    10711078{
    10721079
     
    10761083        mod->toolversion = 0x0629;
    10771084        mod->flags = 0;
    1078         strncpy(mod->name, "general", sizeof(mod->name));
     1085        strncpy(mod->name, "service", sizeof(mod->name));
    10791086        mod->snachandler = snachandler;
    10801087
  • libfaim/ssi.c

    ra0a5179 rcf02dd6  
    2222 * You don't know the half of it.
    2323 *
    24  * XXX - Preserve unknown data in TLV lists
    25  *
    2624 */
    2725
     
    3937static struct aim_ssi_item *aim_ssi_itemlist_rebuildgroup(struct aim_ssi_item *list, const char *name)
    4038{
    41   int newlen;
    42   struct aim_ssi_item *cur, *group;
    43 
    44   owl_function_debugmsg("aim_ssi_itemlist_rebuildgroup: in for group %s", name?name:"NULL");
    45  
    46   if (!list) return(NULL);
    47  
    48   /* Find the group */
    49   if (!(group = aim_ssi_itemlist_finditem(list, name, NULL, AIM_SSI_TYPE_GROUP))) return(NULL);
    50  
    51   /* Free the old data */
    52   aim_freetlvchain(&group->data);
    53   group->data = NULL;
    54  
    55   /* Find the length for the new additional data */
    56   newlen = 0;
    57   if (group->gid == 0x0000) {
    58     for (cur=list; cur; cur=cur->next)
    59       if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))
    60         newlen += 2;
    61   } else {
    62     for (cur=list; cur; cur=cur->next)
    63       if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
    64         newlen += 2;
    65   }
    66   owl_function_debugmsg("aim_ssi_itemlist_rebuildgroup: newlen is %i", newlen);
    67  
    68   /* Build the new TLV list */
    69   if (newlen > 0) {
    70     fu8_t *newdata;
    71    
    72     if (!(newdata = (fu8_t *)malloc((newlen)*sizeof(fu8_t)))) return NULL;
    73     newlen = 0;
    74     if (group->gid == 0x0000) {
    75       for (cur=list; cur; cur=cur->next)
    76         if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))
    77           newlen += aimutil_put16(newdata+newlen, cur->gid);
    78     } else {
    79       for (cur=list; cur; cur=cur->next)
    80         if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
    81           newlen += aimutil_put16(newdata+newlen, cur->bid);
    82     }
    83     aim_addtlvtochain_raw(&group->data, 0x00c8, newlen, newdata);
    84    
    85     free(newdata);
    86   }
    87 
    88   owl_function_debugmsg("aim_ssi_itemlist_rebuildgroup: exiting");
    89   return group;
     39        int newlen;
     40        struct aim_ssi_item *cur, *group;
     41
     42        if (!list)
     43                return NULL;
     44
     45        /* Find the group */
     46        if (!(group = aim_ssi_itemlist_finditem(list, name, NULL, AIM_SSI_TYPE_GROUP)))
     47                return NULL;
     48
     49        /* Find the length for the new additional data */
     50        newlen = 0;
     51        if (group->gid == 0x0000) {
     52                for (cur=list; cur; cur=cur->next)
     53                        if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))
     54                                newlen += 2;
     55        } else {
     56                for (cur=list; cur; cur=cur->next)
     57                        if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
     58                                newlen += 2;
     59        }
     60
     61        /* Build the new TLV list */
     62        if (newlen > 0) {
     63                fu8_t *newdata;
     64
     65                if (!(newdata = (fu8_t *)malloc((newlen)*sizeof(fu8_t))))
     66                        return NULL;
     67                newlen = 0;
     68                if (group->gid == 0x0000) {
     69                        for (cur=list; cur; cur=cur->next)
     70                                if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))
     71                                                newlen += aimutil_put16(newdata+newlen, cur->gid);
     72                } else {
     73                        for (cur=list; cur; cur=cur->next)
     74                                if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
     75                                                newlen += aimutil_put16(newdata+newlen, cur->bid);
     76                }
     77                aim_tlvlist_replace_raw(&group->data, 0x00c8, newlen, newdata);
     78
     79                free(newdata);
     80        }
     81
     82        return group;
    9083}
    9184
     
    10497static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_item **list, const char *name, fu16_t gid, fu16_t bid, fu16_t type, aim_tlvlist_t *data)
    10598{
    106   int i;
    107   struct aim_ssi_item *cur, *new;
    108  
    109   if (!list) return(NULL);
    110  
    111   if (!(new = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item)))) return(NULL);
    112  
    113   /* Set the name */
    114   if (name) {
    115     new->name = (char *)malloc((strlen(name)+1)*sizeof(char));
    116     strcpy(new->name, name);
    117   } else {
    118     new->name = NULL;
    119   }
    120  
    121   /* Set the group ID# and buddy ID# */
    122   new->gid = gid;
    123   new->bid = bid;
    124   if (type == AIM_SSI_TYPE_GROUP) {
    125     if ((new->gid == 0xFFFF) && name) {
    126       do {
    127         new->gid += 0x0001;
    128         for (cur=*list, i=0; ((cur) && (!i)); cur=cur->next)
    129           if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid == new->gid))
    130             i=1;
    131       } while (i);
    132     }
    133   } else {
    134     if (new->bid == 0xFFFF) {
    135       do {
    136         new->bid += 0x0001;
    137         for (cur=*list, i=0; ((cur) && (!i)); cur=cur->next)
    138           if ((cur->bid == new->bid) && (cur->gid == new->gid))
    139             i=1;
    140       } while (i);
    141     }
    142   }
    143  
    144   /* Set the type */
    145   new->type = type;
    146  
    147   /* Set the TLV list */
    148   new->data = aim_tlvlist_copy(data);
    149  
    150   /* Add the item to the list in the correct numerical position.  Fancy, eh? */
    151   if (*list) {
    152     if ((new->gid < (*list)->gid) || ((new->gid == (*list)->gid) && (new->bid < (*list)->bid))) {
    153       new->next = *list;
    154       *list = new;
    155     } else {
    156       struct aim_ssi_item *prev;
    157       for ((prev=*list, cur=(*list)->next); (cur && ((new->gid > cur->gid) || ((new->gid == cur->gid) && (new->bid > cur->bid)))); prev=cur, cur=cur->next);
    158       new->next = prev->next;
    159       prev->next = new;
    160     }
    161   } else {
    162     new->next = *list;
    163     *list = new;
    164   }
    165 
    166   return(new);
     99        int i;
     100        struct aim_ssi_item *cur, *new;
     101
     102        if (!list)
     103                return NULL;
     104
     105        if (!(new = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item))))
     106                return NULL;
     107
     108        /* Set the name */
     109        if (name) {
     110                new->name = (char *)malloc((strlen(name)+1)*sizeof(char));
     111                strcpy(new->name, name);
     112        } else
     113                new->name = NULL;
     114
     115        /* Set the group ID# and buddy ID# */
     116        new->gid = gid;
     117        new->bid = bid;
     118        if (type == AIM_SSI_TYPE_GROUP) {
     119                if ((new->gid == 0xFFFF) && name) {
     120                        do {
     121                                new->gid += 0x0001;
     122                                for (cur=*list, i=0; ((cur) && (!i)); cur=cur->next)
     123                                        if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid == new->gid))
     124                                                i=1;
     125                        } while (i);
     126                }
     127        } else {
     128                if (new->bid == 0xFFFF) {
     129                        do {
     130                                new->bid += 0x0001;
     131                                for (cur=*list, i=0; ((cur) && (!i)); cur=cur->next)
     132                                        if ((cur->bid == new->bid) && (cur->gid == new->gid))
     133                                                i=1;
     134                        } while (i);
     135                }
     136        }
     137
     138        /* Set the type */
     139        new->type = type;
     140
     141        /* Set the TLV list */
     142        new->data = aim_tlvlist_copy(data);
     143
     144        /* Add the item to the list in the correct numerical position.  Fancy, eh? */
     145        if (*list) {
     146                if ((new->gid < (*list)->gid) || ((new->gid == (*list)->gid) && (new->bid < (*list)->bid))) {
     147                        new->next = *list;
     148                        *list = new;
     149                } else {
     150                        struct aim_ssi_item *prev;
     151                        for ((prev=*list, cur=(*list)->next); (cur && ((new->gid > cur->gid) || ((new->gid == cur->gid) && (new->bid > cur->bid)))); prev=cur, cur=cur->next);
     152                        new->next = prev->next;
     153                        prev->next = new;
     154                }
     155        } else {
     156                new->next = *list;
     157                *list = new;
     158        }
     159
     160        return new;
    167161}
    168162
     
    176170static int aim_ssi_itemlist_del(struct aim_ssi_item **list, struct aim_ssi_item *del)
    177171{
    178   if (!list || !(*list) || !del) return -EINVAL;
    179 
    180   owl_function_debugmsg("aim_ssi_itemlist_del: in");
    181   /* Remove the item from the list */
    182   if (*list == del) {
    183     *list = (*list)->next;
    184     owl_function_debugmsg("aim_ssi_itemlist_del: deleted %s from beginning of list", del->name);
    185   } else {
    186     struct aim_ssi_item *cur;
    187     for (cur=*list; (cur->next && (cur->next!=del)); cur=cur->next);
    188     if (cur->next) cur->next=cur->next->next;
    189     owl_function_debugmsg("aim_ssi_itemlist_del: deleted %s from middle of list", del->name);
    190   }
    191 
    192   /* Free the deleted item */
    193   owl_function_debugmsg("aim_ssi_itemlist_del: freeing");
    194   free(del->name);
    195   aim_freetlvchain(&del->data);
    196   free(del);
    197 
    198   return(0);
     172        if (!list || !(*list) || !del)
     173                return -EINVAL;
     174
     175        /* Remove the item from the list */
     176        if (*list == del) {
     177                *list = (*list)->next;
     178        } else {
     179                struct aim_ssi_item *cur;
     180                for (cur=*list; (cur->next && (cur->next!=del)); cur=cur->next);
     181                if (cur->next)
     182                        cur->next = del->next;
     183        }
     184
     185        /* Free the removed item */
     186        free(del->name);
     187        aim_tlvlist_free(&del->data);
     188        free(del);
     189
     190        return 0;
    199191}
    200192
     
    208200static int aim_ssi_itemlist_cmp(struct aim_ssi_item *cur1, struct aim_ssi_item *cur2)
    209201{
    210   if (!cur1 || !cur2)
    211     return 1;
    212  
    213   if (cur1->data && !cur2->data)
    214     return 2;
    215  
    216   if (!cur1->data && cur2->data)
    217     return 3;
    218  
    219   if ((cur1->data && cur2->data) && (aim_tlvlist_cmp(cur1->data, cur2->data)))
    220     return 4;
    221  
    222   if (cur1->name && !cur2->name)
    223     return 5;
    224  
    225   if (!cur1->name && cur2->name)
    226     return 6;
    227  
    228   if (cur1->name && cur2->name && aim_sncmp(cur1->name, cur2->name))
    229     return 7;
    230  
    231   if (cur1->gid != cur2->gid)
    232     return 8;
    233  
    234   if (cur1->bid != cur2->bid)
    235     return 9;
    236  
    237   if (cur1->type != cur2->type)
    238     return 10;
    239  
    240   return 0;
     202        if (!cur1 || !cur2)
     203                return 1;
     204
     205        if (cur1->data && !cur2->data)
     206                return 2;
     207
     208        if (!cur1->data && cur2->data)
     209                return 3;
     210
     211        if ((cur1->data && cur2->data) && (aim_tlvlist_cmp(cur1->data, cur2->data)))
     212                        return 4;
     213
     214        if (cur1->name && !cur2->name)
     215                return 5;
     216
     217        if (!cur1->name && cur2->name)
     218                return 6;
     219
     220        if (cur1->name && cur2->name && aim_sncmp(cur1->name, cur2->name))
     221                return 7;
     222
     223        if (cur1->gid != cur2->gid)
     224                return 8;
     225
     226        if (cur1->bid != cur2->bid)
     227                return 9;
     228
     229        if (cur1->type != cur2->type)
     230                return 10;
     231
     232        return 0;
    241233}
    242234
    243235faim_export int aim_ssi_itemlist_valid(struct aim_ssi_item *list, struct aim_ssi_item *item)
    244236{
    245   struct aim_ssi_item *cur;
    246   for (cur=list; cur; cur=cur->next)
    247     if (cur == item)
    248       return 1;
    249   return 0;
     237        struct aim_ssi_item *cur;
     238        for (cur=list; cur; cur=cur->next)
     239                if (cur == item)
     240                        return 1;
     241        return 0;
    250242}
    251243
     
    260252faim_export struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, fu16_t gid, fu16_t bid)
    261253{
    262   struct aim_ssi_item *cur;
    263   for (cur=list; cur; cur=cur->next)
    264     if ((cur->gid == gid) && (cur->bid == bid))
    265       return cur;
    266   return NULL;
     254        struct aim_ssi_item *cur;
     255        for (cur=list; cur; cur=cur->next)
     256                if ((cur->gid == gid) && (cur->bid == bid))
     257                        return cur;
     258        return NULL;
    267259}
    268260
     
    279271faim_export struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *sn, fu16_t type)
    280272{
    281   struct aim_ssi_item *cur;
    282   if (!list)
    283     return NULL;
    284  
    285   if (gn && sn) { /* For finding buddies in groups */
    286     for (cur=list; cur; cur=cur->next)
    287       if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) {
    288         struct aim_ssi_item *curg;
    289         for (curg=list; curg; curg=curg->next)
    290           if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid) && (curg->name) && !(aim_sncmp(curg->name, gn)))
    291             return cur;
    292       }
    293    
    294   } else if (gn) { /* For finding groups */
    295     for (cur=list; cur; cur=cur->next) {
    296       if ((cur->type == type) && (cur->bid == 0x0000) && (cur->name) && !(aim_sncmp(cur->name, gn))) {
    297         return cur;
    298       }
    299     }
    300    
    301   } else if (sn) { /* For finding permits, denies, and ignores */
    302     for (cur=list; cur; cur=cur->next) {
    303       if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) {
    304         return cur;
    305       }
    306     }
    307    
    308     /* For stuff without names--permit deny setting, visibility mask, etc. */
    309   } else for (cur=list; cur; cur=cur->next) {
    310     if ((cur->type == type) && (!cur->name))
    311       return cur;
    312   }
    313  
    314   return NULL;
     273        struct aim_ssi_item *cur;
     274        if (!list)
     275                return NULL;
     276
     277        if (gn && sn) { /* For finding buddies in groups */
     278                for (cur=list; cur; cur=cur->next)
     279                        if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) {
     280                                struct aim_ssi_item *curg;
     281                                for (curg=list; curg; curg=curg->next)
     282                                        if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid) && (curg->name) && !(aim_sncmp(curg->name, gn)))
     283                                                return cur;
     284                        }
     285
     286        } else if (gn) { /* For finding groups */
     287                for (cur=list; cur; cur=cur->next) {
     288                        if ((cur->type == type) && (cur->bid == 0x0000) && (cur->name) && !(aim_sncmp(cur->name, gn))) {
     289                                return cur;
     290                        }
     291                }
     292
     293        } else if (sn) { /* For finding permits, denies, and ignores */
     294                for (cur=list; cur; cur=cur->next) {
     295                        if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) {
     296                                return cur;
     297                        }
     298                }
     299
     300        /* For stuff without names--permit deny setting, visibility mask, etc. */
     301        } else for (cur=list; cur; cur=cur->next) {
     302                if ((cur->type == type) && (!cur->name))
     303                        return cur;
     304        }
     305
     306        return NULL;
    315307}
    316308
     
    324316faim_export struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *sn)
    325317{
    326   struct aim_ssi_item *cur;
    327   if (!list || !sn)
    328     return NULL;
    329   for (cur=list; cur; cur=cur->next)
    330     if ((cur->type == AIM_SSI_TYPE_BUDDY) && (cur->name) && (!aim_sncmp(cur->name, sn)))
    331       return cur;
    332   return NULL;
     318        struct aim_ssi_item *cur;
     319        if (!list || !sn)
     320                return NULL;
     321        for (cur=list; cur; cur=cur->next)
     322                if ((cur->type == AIM_SSI_TYPE_BUDDY) && (cur->name) && (!aim_sncmp(cur->name, sn)))
     323                        return cur;
     324        return NULL;
    333325}
    334326
     
    342334faim_export char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *sn)
    343335{
    344   struct aim_ssi_item *cur, *curg;
    345   if (!list || !sn)
    346     return NULL;
    347   if (!(cur = aim_ssi_itemlist_exists(list, sn)))
    348     return NULL;
    349   if (!(curg = aim_ssi_itemlist_find(list, cur->gid, 0x0000)))
    350     return NULL;
    351   return curg->name;
     336        struct aim_ssi_item *cur, *curg;
     337        if (!list || !sn)
     338                return NULL;
     339        if (!(cur = aim_ssi_itemlist_exists(list, sn)))
     340                return NULL;
     341        if (!(curg = aim_ssi_itemlist_find(list, cur->gid, 0x0000)))
     342                return NULL;
     343        return curg->name;
    352344}
    353345
     
    360352faim_export int aim_ssi_getpermdeny(struct aim_ssi_item *list)
    361353{
    362   struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PDINFO);
    363   if (cur) {
    364     aim_tlvlist_t *tlvlist = cur->data;
    365     if (tlvlist) {
    366       aim_tlv_t *tlv = aim_gettlv(tlvlist, 0x00ca, 1);
    367       if (tlv && tlv->value)
    368         return aimutil_get8(tlv->value);
    369     }
    370   }
    371   return 0;
     354        struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PDINFO);
     355        if (cur) {
     356                aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00ca, 1);
     357                if (tlv && tlv->value)
     358                        return aimutil_get8(tlv->value);
     359        }
     360        return 0;
    372361}
    373362
     
    382371faim_export fu32_t aim_ssi_getpresence(struct aim_ssi_item *list)
    383372{
    384   struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS);
    385   if (cur) {
    386     aim_tlvlist_t *tlvlist = cur->data;
    387     if (tlvlist) {
    388       aim_tlv_t *tlv = aim_gettlv(tlvlist, 0x00c9, 1);
    389       if (tlv && tlv->length)
    390         return aimutil_get32(tlv->value);
    391     }
    392   }
    393   return 0xFFFFFFFF;
     373        struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS);
     374        if (cur) {
     375                aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00c9, 1);
     376                if (tlv && tlv->length)
     377                        return aimutil_get32(tlv->value);
     378        }
     379        return 0xFFFFFFFF;
    394380}
    395381
    396382/**
    397383 * Locally find the alias of the given buddy.
     384 *
     385 * @param list A pointer to the current list of items.
     386 * @param gn The group of the buddy.
     387 * @param sn The name of the buddy.
     388 * @return A pointer to a NULL terminated string that is the buddy's
     389 *         alias, or NULL if the buddy has no alias.  You should free
     390 *         this returned value!
     391 */
     392faim_export char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *sn)
     393{
     394        struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY);
     395        if (cur) {
     396                aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x0131, 1);
     397                if (tlv && tlv->length) {
     398                        char *alias = (char *)malloc((tlv->length+1)*sizeof(char));
     399                        strncpy(alias, tlv->value, tlv->length);
     400                        alias[tlv->length] = 0;
     401                        return alias;
     402                }
     403        }
     404        return NULL;
     405}
     406
     407/**
     408 * Locally find the comment of the given buddy.
     409 *
     410 * @param list A pointer to the current list of items.
     411 * @param gn The group of the buddy.
     412 * @param sn The name of the buddy.
     413 * @return A pointer to a NULL terminated string that is the buddy's
     414 *         comment, or NULL if the buddy has no comment.  You should free
     415 *         this returned value!
     416 */
     417faim_export char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *sn)
     418{
     419        struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY);
     420        if (cur) {
     421                aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x013c, 1);
     422                if (tlv && tlv->length) {
     423                        char *alias = (char *)malloc((tlv->length+1)*sizeof(char));
     424                        strncpy(alias, tlv->value, tlv->length);
     425                        alias[tlv->length] = 0;
     426                        return alias;
     427                }
     428        }
     429        return NULL;
     430}
     431
     432/**
     433 * Locally find if you are waiting for authorization for a buddy.
    398434 *
    399435 * @param list A pointer to the current list of items.
     
    404440 *         this returned value!
    405441 */
    406 faim_export char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *sn)
    407 {
    408   struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY);
    409   if (cur) {
    410     aim_tlvlist_t *tlvlist = cur->data;
    411     if (tlvlist) {
    412       aim_tlv_t *tlv = aim_gettlv(tlvlist, 0x0131, 1);
    413       if (tlv && tlv->length) {
    414         char *alias = (char *)malloc((tlv->length+1)*sizeof(char));
    415         strncpy(alias, tlv->value, tlv->length);
    416         alias[tlv->length] = 0;
    417         return alias;
    418       }
    419     }
    420   }
    421   return NULL;
    422 }
    423 
    424 /**
    425  * Locally find if you are waiting for authorization for a buddy.
    426  *
    427  * @param list A pointer to the current list of items.
    428  * @param gn The group of the buddy.
    429  * @param sn The name of the buddy.
    430  * @return A pointer to a NULL terminated string that is the buddies
    431  *         alias, or NULL if the buddy has no alias.  You should free
    432  *         this returned value!
    433  */
    434442faim_export int aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *sn)
    435443{
    436   struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY);
    437   if (cur) {
    438     aim_tlvlist_t *tlvlist = cur->data;
    439     if (tlvlist)
    440       if (aim_gettlv(tlvlist, 0x0066, 1))
    441         return 1;
    442   }
    443   return 0;
     444        struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY);
     445        if (cur) {
     446                if (aim_tlv_gettlv(cur->data, 0x0066, 1))
     447                        return 1;
     448        }
     449        return 0;
    444450}
    445451
     
    453459static int aim_ssi_sync(aim_session_t *sess)
    454460{
    455   struct aim_ssi_item *cur1, *cur2;
    456   struct aim_ssi_tmp *cur, *new;
    457 
    458   owl_function_debugmsg("aim_ssi_sync: beginning");
    459  
    460   if (!sess) return (-EINVAL);
    461 
    462   /* If we're waiting for an ack, we shouldn't do anything else */
    463   if (sess->ssi.waiting_for_ack) {
    464     owl_function_debugmsg("Aborting aim_ssi_sync, waiting for ack");
    465     return 0;
    466   }
    467  
    468   /*
    469    * Compare the 2 lists and create an aim_ssi_tmp for each difference. 
    470    * We should only send either additions, modifications, or deletions
    471    * before waiting for an acknowledgement.  So first do deletions, then
    472    * additions, then modifications.  Also, both the official and the local
    473    * list should be in ascending numerical order for the group ID#s and the
    474    * buddy ID#s, which makes things more efficient.  I think.
    475    */
    476 
    477   /* Additions */
    478   if (!sess->ssi.pending) {
    479     for (cur1=sess->ssi.local; cur1; cur1=cur1->next) {
    480       if (!aim_ssi_itemlist_find(sess->ssi.official, cur1->gid, cur1->bid)) {
    481         owl_function_debugmsg("aim_ssi_sync: doing addition");
    482         new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp));
    483         new->action = AIM_CB_SSI_ADD;
    484         new->ack = 0xffff;
    485         new->name = NULL;
    486         new->item = cur1;
    487         new->next = NULL;
    488         if (sess->ssi.pending) {
    489           for (cur=sess->ssi.pending; cur->next; cur=cur->next);
    490           cur->next = new;
    491         } else
    492           sess->ssi.pending = new;
    493       }
    494     }
    495   }
    496  
    497   /* Deletions */
    498   if (!sess->ssi.pending) {
    499     for (cur1=sess->ssi.official; cur1; cur1=cur1->next) {
    500       if (!aim_ssi_itemlist_find(sess->ssi.local, cur1->gid, cur1->bid)) {
    501         owl_function_debugmsg("aim_ssi_sync: doing deletion");
    502         new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp));
    503         new->action = AIM_CB_SSI_DEL;
    504         new->ack = 0xffff;
    505         new->name = NULL;
    506         new->item = cur1;
    507         new->next = NULL;
    508         if (sess->ssi.pending) {
    509           for (cur=sess->ssi.pending; cur->next; cur=cur->next);
    510           cur->next = new;
    511         } else
    512           sess->ssi.pending = new;
    513       }
    514     }
    515   }
    516  
    517   /* Modifications */
    518   if (!sess->ssi.pending) {
    519     for (cur1=sess->ssi.local; cur1; cur1=cur1->next) {
    520       cur2 = aim_ssi_itemlist_find(sess->ssi.official, cur1->gid, cur1->bid);
    521       if (cur2 && (aim_ssi_itemlist_cmp(cur1, cur2))) {
    522         owl_function_debugmsg("aim_ssi_sync: doing modification");
    523         new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp));
    524         new->action = AIM_CB_SSI_MOD;
    525         new->ack = 0xffff;
    526         new->name = NULL;
    527         new->item = cur1;
    528         new->next = NULL;
    529         if (sess->ssi.pending) {
    530           for (cur=sess->ssi.pending; cur->next; cur=cur->next);
    531           cur->next = new;
    532         } else
    533           sess->ssi.pending = new;
    534       }
    535     }
    536   }
    537  
    538   /* We're out of stuff to do, so tell the AIM servers we're done and exit */
    539   if (!sess->ssi.pending) {
    540     owl_function_debugmsg("aim_ssi_sync: telling server we're done modifying SSI data.");
    541     aim_ssi_modend(sess);
    542     return 0;
    543   }
    544  
    545   /* Make sure we don't send anything else between now
    546    * and when we receive the ack for the following operation */
    547   owl_function_debugmsg("aim_ssi_sync: setting SSI waiting_for_ack");
    548   sess->ssi.waiting_for_ack = 1;
    549  
    550   /* Now go mail off our data and wait 4 to 6 weeks */
    551   owl_function_debugmsg("aim_ssi_sync: about to call addmoddel to send SNACs to server");
    552   aim_ssi_addmoddel(sess);
    553  
    554   return 0;
     461        struct aim_ssi_item *cur1, *cur2;
     462        struct aim_ssi_tmp *cur, *new;
     463
     464        if (!sess)
     465                return -EINVAL;
     466
     467        /* If we're waiting for an ack, we shouldn't do anything else */
     468        if (sess->ssi.waiting_for_ack)
     469                return 0;
     470
     471        /*
     472         * Compare the 2 lists and create an aim_ssi_tmp for each difference. 
     473         * We should only send either additions, modifications, or deletions
     474         * before waiting for an acknowledgement.  So first do deletions, then
     475         * additions, then modifications.  Also, both the official and the local
     476         * list should be in ascending numerical order for the group ID#s and the
     477         * buddy ID#s, which makes things more efficient.  I think.
     478         */
     479
     480        /* Additions */
     481        if (!sess->ssi.pending) {
     482                for (cur1=sess->ssi.local; cur1; cur1=cur1->next) {
     483                        if (!aim_ssi_itemlist_find(sess->ssi.official, cur1->gid, cur1->bid)) {
     484                                new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp));
     485                                new->action = AIM_CB_SSI_ADD;
     486                                new->ack = 0xffff;
     487                                new->name = NULL;
     488                                new->item = cur1;
     489                                new->next = NULL;
     490                                if (sess->ssi.pending) {
     491                                        for (cur=sess->ssi.pending; cur->next; cur=cur->next);
     492                                        cur->next = new;
     493                                } else
     494                                        sess->ssi.pending = new;
     495                        }
     496                }
     497        }
     498
     499        /* Deletions */
     500        if (!sess->ssi.pending) {
     501                for (cur1=sess->ssi.official; cur1; cur1=cur1->next) {
     502                        if (!aim_ssi_itemlist_find(sess->ssi.local, cur1->gid, cur1->bid)) {
     503                                new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp));
     504                                new->action = AIM_CB_SSI_DEL;
     505                                new->ack = 0xffff;
     506                                new->name = NULL;
     507                                new->item = cur1;
     508                                new->next = NULL;
     509                                if (sess->ssi.pending) {
     510                                        for (cur=sess->ssi.pending; cur->next; cur=cur->next);
     511                                        cur->next = new;
     512                                } else
     513                                        sess->ssi.pending = new;
     514                        }
     515                }
     516        }
     517
     518        /* Modifications */
     519        if (!sess->ssi.pending) {
     520                for (cur1=sess->ssi.local; cur1; cur1=cur1->next) {
     521                        cur2 = aim_ssi_itemlist_find(sess->ssi.official, cur1->gid, cur1->bid);
     522                        if (cur2 && (aim_ssi_itemlist_cmp(cur1, cur2))) {
     523                                new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp));
     524                                new->action = AIM_CB_SSI_MOD;
     525                                new->ack = 0xffff;
     526                                new->name = NULL;
     527                                new->item = cur1;
     528                                new->next = NULL;
     529                                if (sess->ssi.pending) {
     530                                        for (cur=sess->ssi.pending; cur->next; cur=cur->next);
     531                                        cur->next = new;
     532                                } else
     533                                        sess->ssi.pending = new;
     534                        }
     535                }
     536        }
     537
     538        /* We're out of stuff to do, so tell the AIM servers we're done and exit */
     539        if (!sess->ssi.pending) {
     540                aim_ssi_modend(sess);
     541                return 0;
     542        }
     543
     544        /* Make sure we don't send anything else between now
     545         * and when we receive the ack for the following operation */
     546        sess->ssi.waiting_for_ack = 1;
     547
     548        /* Now go mail off our data and wait 4 to 6 weeks */
     549        aim_ssi_addmoddel(sess);
     550
     551        return 0;
    555552}
    556553
     
    565562static int aim_ssi_freelist(aim_session_t *sess)
    566563{
    567   struct aim_ssi_item *cur, *del;
    568   struct aim_ssi_tmp *curtmp, *deltmp;
    569  
    570   cur = sess->ssi.official;
    571   while (cur) {
    572     del = cur;
    573     cur = cur->next;
    574     free(del->name);
    575     aim_freetlvchain(&del->data);
    576     free(del);
    577   }
    578  
    579   cur = sess->ssi.local;
    580   while (cur) {
    581     del = cur;
    582     cur = cur->next;
    583     free(del->name);
    584     aim_freetlvchain(&del->data);
    585     free(del);
    586   }
    587  
    588   curtmp = sess->ssi.pending;
    589   while (curtmp) {
    590     deltmp = curtmp;
    591     curtmp = curtmp->next;
    592     free(deltmp);
    593   }
    594  
    595   sess->ssi.numitems = 0;
    596   sess->ssi.official = NULL;
    597   sess->ssi.local = NULL;
    598   sess->ssi.pending = NULL;
    599   sess->ssi.timestamp = (time_t)0;
    600  
    601   return 0;
     564        struct aim_ssi_item *cur, *del;
     565        struct aim_ssi_tmp *curtmp, *deltmp;
     566
     567        cur = sess->ssi.official;
     568        while (cur) {
     569                del = cur;
     570                cur = cur->next;
     571                free(del->name);
     572                aim_tlvlist_free(&del->data);
     573                free(del);
     574        }
     575
     576        cur = sess->ssi.local;
     577        while (cur) {
     578                del = cur;
     579                cur = cur->next;
     580                free(del->name);
     581                aim_tlvlist_free(&del->data);
     582                free(del);
     583        }
     584
     585        curtmp = sess->ssi.pending;
     586        while (curtmp) {
     587                deltmp = curtmp;
     588                curtmp = curtmp->next;
     589                free(deltmp);
     590        }
     591
     592        sess->ssi.numitems = 0;
     593        sess->ssi.official = NULL;
     594        sess->ssi.local = NULL;
     595        sess->ssi.pending = NULL;
     596        sess->ssi.timestamp = (time_t)0;
     597
     598        return 0;
    602599}
    603600
     
    610607faim_export int aim_ssi_deletelist(aim_session_t *sess)
    611608{
    612   struct aim_ssi_item *cur, *del;
    613  
    614   if (!sess) return (-EINVAL);
    615  
    616   /* Free the local list */
    617   cur = sess->ssi.local;
    618   while (cur) {
    619     del = cur;
    620     cur = cur->next;
    621     free(del->name);
    622     aim_freetlvchain(&del->data);
    623     free(del);
    624   }
    625   sess->ssi.local = NULL;
    626  
    627   /* Sync our local list with the server list */
    628   aim_ssi_sync(sess);
    629  
    630   return 0;
     609        struct aim_ssi_item *cur, *del;
     610
     611        if (!sess)
     612                return -EINVAL;
     613
     614        /* Free the local list */
     615        cur = sess->ssi.local;
     616        while (cur) {
     617                del = cur;
     618                cur = cur->next;
     619                free(del->name);
     620                aim_tlvlist_free(&del->data);
     621                free(del);
     622        }
     623        sess->ssi.local = NULL;
     624
     625        /* Sync our local list with the server list */
     626        aim_ssi_sync(sess);
     627
     628        return 0;
    631629}
    632630
     
    642640faim_export int aim_ssi_cleanlist(aim_session_t *sess)
    643641{
    644   struct aim_ssi_item *cur, *next;
    645  
    646   if (!sess) return -EINVAL;
    647 
    648   /* Delete any buddies, permits, or denies with empty names. */
    649   /* If there are any buddies directly in the master group, add them to a real group. */
    650   /* DESTROY any buddies that are directly in the master group. */
    651   /* Do the same for buddies that are in a non-existant group. */
    652   /* This will kind of mess up if you hit the item limit, but this function isn't too critical */
    653   cur = sess->ssi.local;
    654   while (cur) {
    655     next = cur->next;
    656     if (!cur->name) {
    657       if (cur->type == AIM_SSI_TYPE_BUDDY)
    658         aim_ssi_delbuddy(sess, NULL, NULL);
    659       else if (cur->type == AIM_SSI_TYPE_PERMIT)
    660         aim_ssi_delpermit(sess, NULL);
    661       else if (cur->type == AIM_SSI_TYPE_DENY)
    662         aim_ssi_deldeny(sess, NULL);
    663     } else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(sess->ssi.local, cur->gid, 0x0000)))) {
    664       aim_ssi_addbuddy(sess, cur->name, "orphans", NULL, NULL, NULL, 0);
    665       aim_ssi_delbuddy(sess, cur->name, NULL);
    666     }
    667     cur = next;
    668   }
    669  
    670   /* Check if there are empty groups and delete them */
    671   cur = sess->ssi.local;
    672   while (cur) {
    673     next = cur->next;
    674     if (cur->type == AIM_SSI_TYPE_GROUP) {
    675       aim_tlv_t *tlv = aim_gettlv(cur->data, 0x00c8, 1);
    676       if (!tlv || !tlv->length)
    677         aim_ssi_itemlist_del(&sess->ssi.local, cur);
    678     }
    679     cur = next;
    680   }
    681  
    682   /* Check if the master group is empty */
    683   if ((cur = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000)) && (!cur->data))
    684     aim_ssi_itemlist_del(&sess->ssi.local, cur);
    685  
    686   return 0;
     642        struct aim_ssi_item *cur, *next;
     643
     644        if (!sess)
     645                return -EINVAL;
     646
     647        /* Delete any buddies, permits, or denies with empty names. */
     648        /* If there are any buddies directly in the master group, add them to a real group. */
     649        /* DESTROY any buddies that are directly in the master group. */
     650        /* Do the same for buddies that are in a non-existant group. */
     651        /* This will kind of mess up if you hit the item limit, but this function isn't too critical */
     652        cur = sess->ssi.local;
     653        while (cur) {
     654                next = cur->next;
     655                if (!cur->name) {
     656                        if (cur->type == AIM_SSI_TYPE_BUDDY)
     657                                aim_ssi_delbuddy(sess, NULL, NULL);
     658                        else if (cur->type == AIM_SSI_TYPE_PERMIT)
     659                                aim_ssi_delpermit(sess, NULL);
     660                        else if (cur->type == AIM_SSI_TYPE_DENY)
     661                                aim_ssi_deldeny(sess, NULL);
     662                } else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(sess->ssi.local, cur->gid, 0x0000)))) {
     663                        aim_ssi_addbuddy(sess, cur->name, "orphans", NULL, NULL, NULL, 0);
     664                        aim_ssi_delbuddy(sess, cur->name, NULL);
     665                }
     666                cur = next;
     667        }
     668
     669        /* Check if there are empty groups and delete them */
     670        cur = sess->ssi.local;
     671        while (cur) {
     672                next = cur->next;
     673                if (cur->type == AIM_SSI_TYPE_GROUP) {
     674                        aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00c8, 1);
     675                        if (!tlv || !tlv->length)
     676                                aim_ssi_itemlist_del(&sess->ssi.local, cur);
     677                }
     678                cur = next;
     679        }
     680
     681        /* Check if the master group is empty */
     682        if ((cur = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000)) && (!cur->data))
     683                aim_ssi_itemlist_del(&sess->ssi.local, cur);
     684
     685        return 0;
    687686}
    688687
     
    700699faim_export int aim_ssi_addbuddy(aim_session_t *sess, const char *name, const char *group, const char *alias, const char *comment, const char *smsnum, int needauth)
    701700{
    702   struct aim_ssi_item *parent;
    703   aim_tlvlist_t *data = NULL;
    704  
    705   if (!sess || !name || !group) return (-EINVAL);
    706 
    707   /* Find the parent */
    708   if (!(parent = aim_ssi_itemlist_finditem(sess->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) {
    709     /* Find the parent's parent (the master group) */
    710     if (!(parent = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000))) {
    711       if (!(parent = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL))) {
    712         return -ENOMEM;
    713       }
    714     }
    715     /* Add the parent */
    716     if (!(parent = aim_ssi_itemlist_add(&sess->ssi.local, group, 0xFFFF, 0x0000, AIM_SSI_TYPE_GROUP, NULL))) {
    717       return -ENOMEM;
    718     }
    719    
    720     /* Modify the parent's parent (the master group) */
    721     aim_ssi_itemlist_rebuildgroup(sess->ssi.local, NULL);
    722   }
    723  
    724   /* Create a TLV list for the new buddy */
    725   if (needauth) aim_addtlvtochain_noval(&data, 0x0066);
    726   if (alias) aim_addtlvtochain_raw(&data, 0x0131, strlen(alias), alias);
    727   if (smsnum) aim_addtlvtochain_raw(&data, 0x013a, strlen(smsnum), smsnum);
    728   if (comment) aim_addtlvtochain_raw(&data, 0x013c, strlen(comment), comment);
    729  
    730   /* Add that bad boy */
    731   aim_ssi_itemlist_add(&sess->ssi.local, name, parent->gid, 0xFFFF, AIM_SSI_TYPE_BUDDY, data);
    732   aim_freetlvchain(&data);
    733  
    734   /* Modify the parent group */
    735   aim_ssi_itemlist_rebuildgroup(sess->ssi.local, group);
    736  
    737   /* Sync our local list with the server list */
    738   aim_ssi_sync(sess);
    739  
    740   return(0);
     701        struct aim_ssi_item *parent;
     702        aim_tlvlist_t *data = NULL;
     703
     704        if (!sess || !name || !group)
     705                return -EINVAL;
     706
     707        /* Find the parent */
     708        if (!(parent = aim_ssi_itemlist_finditem(sess->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) {
     709                /* Find the parent's parent (the master group) */
     710                if (!(parent = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000)))
     711                        if (!(parent = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL)))
     712                                return -ENOMEM;
     713                /* Add the parent */
     714                if (!(parent = aim_ssi_itemlist_add(&sess->ssi.local, group, 0xFFFF, 0x0000, AIM_SSI_TYPE_GROUP, NULL)))
     715                        return -ENOMEM;
     716
     717                /* Modify the parent's parent (the master group) */
     718                aim_ssi_itemlist_rebuildgroup(sess->ssi.local, NULL);
     719        }
     720
     721        /* Create a TLV list for the new buddy */
     722        if (needauth)
     723                aim_tlvlist_add_noval(&data, 0x0066);
     724        if (alias)
     725                aim_tlvlist_add_raw(&data, 0x0131, strlen(alias), alias);
     726        if (smsnum)
     727                aim_tlvlist_add_raw(&data, 0x013a, strlen(smsnum), smsnum);
     728        if (comment)
     729                aim_tlvlist_add_raw(&data, 0x013c, strlen(comment), comment);
     730
     731        /* Add that bad boy */
     732        aim_ssi_itemlist_add(&sess->ssi.local, name, parent->gid, 0xFFFF, AIM_SSI_TYPE_BUDDY, data);
     733        aim_tlvlist_free(&data);
     734
     735        /* Modify the parent group */
     736        aim_ssi_itemlist_rebuildgroup(sess->ssi.local, group);
     737
     738        /* Sync our local list with the server list */
     739        aim_ssi_sync(sess);
     740
     741        return 0;
    741742}
    742743
     
    751752{
    752753
    753   if (!sess || !name) return -EINVAL;
    754 
    755   /* Add that bad boy */
    756   aim_ssi_itemlist_add(&sess->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_PERMIT, NULL);
    757 
    758   /* Sync our local list with the server list */
    759   aim_ssi_sync(sess);
    760 
    761   return(0);
     754        if (!sess || !name)
     755                return -EINVAL;
     756
     757        /* Add that bad boy */
     758        aim_ssi_itemlist_add(&sess->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_PERMIT, NULL);
     759
     760        /* Sync our local list with the server list */
     761        aim_ssi_sync(sess);
     762
     763        return 0;
    762764}
    763765
     
    772774{
    773775
    774   if (!sess || !name) return (-EINVAL);
    775 
    776   /* Add that bad boy */
    777   aim_ssi_itemlist_add(&sess->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_DENY, NULL);
    778  
    779   /* Sync our local list with the server list */
    780   aim_ssi_sync(sess);
    781  
    782   return(0);
     776        if (!sess || !name)
     777                return -EINVAL;
     778
     779        /* Add that bad boy */
     780        aim_ssi_itemlist_add(&sess->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_DENY, NULL);
     781
     782        /* Sync our local list with the server list */
     783        aim_ssi_sync(sess);
     784
     785        return 0;
    783786}
    784787
     
    793796faim_export int aim_ssi_delbuddy(aim_session_t *sess, const char *name, const char *group)
    794797{
    795   struct aim_ssi_item *del;
    796 
    797   if (!sess) return -EINVAL;
    798  
    799   /* Find the buddy */
    800   del=aim_ssi_itemlist_finditem(sess->ssi.local, group, name, AIM_SSI_TYPE_BUDDY);
    801   if (!del) return(-EINVAL);
    802  
    803   /* Remove the item from the list */
    804   aim_ssi_itemlist_del(&sess->ssi.local, del);
    805 
    806   /* Modify the parent group */
    807   aim_ssi_itemlist_rebuildgroup(sess->ssi.local, group);
    808  
    809   /* Check if we should delete the parent group */
    810   if ((del = aim_ssi_itemlist_finditem(sess->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP)) && (!del->data)) {
    811     aim_ssi_itemlist_del(&sess->ssi.local, del);
    812    
    813     /* Modify the parent group */
    814     aim_ssi_itemlist_rebuildgroup(sess->ssi.local, NULL);
    815    
    816     /* Check if we should delete the parent's parent (the master group) */
    817     if ((del = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000)) && (!del->data)) {
    818       aim_ssi_itemlist_del(&sess->ssi.local, del);
    819     }
    820   }
    821  
    822   /* Sync our local list with the server list */
    823   owl_function_debugmsg("aim_ssi_delbuddy: about to sync");
    824   aim_ssi_sync(sess);
    825  
    826   return(0);
     798        struct aim_ssi_item *del;
     799
     800        if (!sess)
     801                return -EINVAL;
     802
     803        /* Find the buddy */
     804        if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, group, name, AIM_SSI_TYPE_BUDDY)))
     805                return -EINVAL;
     806
     807        /* Remove the item from the list */
     808        aim_ssi_itemlist_del(&sess->ssi.local, del);
     809
     810        /* Modify the parent group */
     811        aim_ssi_itemlist_rebuildgroup(sess->ssi.local, group);
     812
     813        /* Check if we should delete the parent group */
     814        if ((del = aim_ssi_itemlist_finditem(sess->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP)) && (!del->data)) {
     815                aim_ssi_itemlist_del(&sess->ssi.local, del);
     816
     817                /* Modify the parent group */
     818                aim_ssi_itemlist_rebuildgroup(sess->ssi.local, NULL);
     819
     820                /* Check if we should delete the parent's parent (the master group) */
     821                if ((del = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000)) && (!del->data)) {
     822                        aim_ssi_itemlist_del(&sess->ssi.local, del);
     823                }
     824        }
     825
     826        /* Sync our local list with the server list */
     827        aim_ssi_sync(sess);
     828
     829        return 0;
    827830}
    828831
     
    836839faim_export int aim_ssi_delpermit(aim_session_t *sess, const char *name)
    837840{
    838   struct aim_ssi_item *del;
    839  
    840   if (!sess)
    841     return -EINVAL;
    842  
    843   /* Find the item */
    844   if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, name, AIM_SSI_TYPE_PERMIT)))
    845     return -EINVAL;
    846  
    847   /* Remove the item from the list */
    848   aim_ssi_itemlist_del(&sess->ssi.local, del);
    849  
    850   /* Sync our local list with the server list */
    851   aim_ssi_sync(sess);
    852  
    853   return 0;
     841        struct aim_ssi_item *del;
     842
     843        if (!sess)
     844                return -EINVAL;
     845
     846        /* Find the item */
     847        if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, name, AIM_SSI_TYPE_PERMIT)))
     848                return -EINVAL;
     849
     850        /* Remove the item from the list */
     851        aim_ssi_itemlist_del(&sess->ssi.local, del);
     852
     853        /* Sync our local list with the server list */
     854        aim_ssi_sync(sess);
     855
     856        return 0;
    854857}
    855858
     
    863866faim_export int aim_ssi_deldeny(aim_session_t *sess, const char *name)
    864867{
    865   struct aim_ssi_item *del;
    866  
    867   if (!sess)
    868     return -EINVAL;
    869  
    870   /* Find the item */
    871   if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, name, AIM_SSI_TYPE_DENY)))
    872     return -EINVAL;
    873  
    874   /* Remove the item from the list */
    875   aim_ssi_itemlist_del(&sess->ssi.local, del);
    876  
    877   /* Sync our local list with the server list */
    878   aim_ssi_sync(sess);
    879  
    880   return 0;
     868        struct aim_ssi_item *del;
     869
     870        if (!sess)
     871                return -EINVAL;
     872
     873        /* Find the item */
     874        if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, name, AIM_SSI_TYPE_DENY)))
     875                return -EINVAL;
     876
     877        /* Remove the item from the list */
     878        aim_ssi_itemlist_del(&sess->ssi.local, del);
     879
     880        /* Sync our local list with the server list */
     881        aim_ssi_sync(sess);
     882
     883        return 0;
    881884}
    882885
     
    893896faim_export int aim_ssi_movebuddy(aim_session_t *sess, const char *oldgn, const char *newgn, const char *sn)
    894897{
    895   aim_ssi_addbuddy(sess, sn, newgn, aim_ssi_getalias(sess->ssi.local, oldgn, sn), NULL, NULL, aim_ssi_waitingforauth(sess->ssi.local, oldgn, sn));
    896   aim_ssi_delbuddy(sess, sn, oldgn);
    897   return 0;
     898        aim_ssi_addbuddy(sess, sn, newgn, aim_ssi_getalias(sess->ssi.local, oldgn, sn), NULL, NULL, aim_ssi_waitingforauth(sess->ssi.local, oldgn, sn));
     899        aim_ssi_delbuddy(sess, sn, oldgn);
     900        return 0;
    898901}
    899902
     
    904907 * @param gn The group that the buddy is currently in.
    905908 * @param sn The screen name of the buddy.
    906  * @param alias The new alias for the buddy.
     909 * @param alias The new alias for the buddy, or NULL if you want to remove
     910 *        a buddy's comment.
    907911 * @return Return 0 if no errors, otherwise return the error number.
    908912 */
    909913faim_export int aim_ssi_aliasbuddy(aim_session_t *sess, const char *gn, const char *sn, const char *alias)
    910914{
    911   struct aim_ssi_item *tmp;
    912   aim_tlvlist_t *data = NULL;
    913  
    914   if (!sess || !gn || !sn)
    915     return -EINVAL;
    916  
    917   if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, gn, sn, AIM_SSI_TYPE_BUDDY)))
    918     return -EINVAL;
    919  
    920   if (alias && !strlen(alias))
    921     alias = NULL;
    922  
    923   /* Need to add the x0131 TLV to the TLV chain */
    924   if (alias)
    925     aim_addtlvtochain_raw(&data, 0x0131, strlen(alias), alias);
    926  
    927   aim_freetlvchain(&tmp->data);
    928   tmp->data = data;
    929  
    930   /* Sync our local list with the server list */
    931   aim_ssi_sync(sess);
    932  
    933   return 0;
     915        struct aim_ssi_item *tmp;
     916
     917        if (!sess || !gn || !sn)
     918                return -EINVAL;
     919
     920        if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, gn, sn, AIM_SSI_TYPE_BUDDY)))
     921                return -EINVAL;
     922
     923        /* Either add or remove the 0x0131 TLV from the TLV chain */
     924        if ((alias != NULL) && (strlen(alias) > 0))
     925                aim_tlvlist_replace_raw(&tmp->data, 0x0131, strlen(alias), alias);
     926        else
     927                aim_tlvlist_remove(&tmp->data, 0x0131);
     928
     929        /* Sync our local list with the server list */
     930        aim_ssi_sync(sess);
     931
     932        return 0;
     933}
     934
     935/**
     936 * Change the comment stored on the server for a given buddy.
     937 *
     938 * @param sess The oscar session.
     939 * @param gn The group that the buddy is currently in.
     940 * @param sn The screen name of the buddy.
     941 * @param alias The new comment for the buddy, or NULL if you want to remove
     942 *        a buddy's comment.
     943 * @return Return 0 if no errors, otherwise return the error number.
     944 */
     945faim_export int aim_ssi_editcomment(aim_session_t *sess, const char *gn, const char *sn, const char *comment)
     946{
     947        struct aim_ssi_item *tmp;
     948
     949        if (!sess || !gn || !sn)
     950                return -EINVAL;
     951
     952        if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, gn, sn, AIM_SSI_TYPE_BUDDY)))
     953                return -EINVAL;
     954
     955        /* Either add or remove the 0x0131 TLV from the TLV chain */
     956        if ((comment != NULL) && (strlen(comment) > 0))
     957                aim_tlvlist_replace_raw(&tmp->data, 0x013c, strlen(comment), comment);
     958        else
     959                aim_tlvlist_remove(&tmp->data, 0x013c);
     960
     961        /* Sync our local list with the server list */
     962        aim_ssi_sync(sess);
     963
     964        return 0;
    934965}
    935966
     
    944975faim_export int aim_ssi_rename_group(aim_session_t *sess, const char *oldgn, const char *newgn)
    945976{
    946   struct aim_ssi_item *group;
    947  
    948   if (!sess || !oldgn || !newgn)
    949     return -EINVAL;
    950  
    951   if (!(group = aim_ssi_itemlist_finditem(sess->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP)))
    952     return -EINVAL;
    953  
    954   free(group->name);
    955   group->name = (char *)malloc((strlen(newgn)+1)*sizeof(char));
    956   strcpy(group->name, newgn);
    957  
    958   /* Sync our local list with the server list */
    959   aim_ssi_sync(sess);
    960  
    961   return 0;
     977        struct aim_ssi_item *group;
     978
     979        if (!sess || !oldgn || !newgn)
     980                return -EINVAL;
     981
     982        if (!(group = aim_ssi_itemlist_finditem(sess->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP)))
     983                return -EINVAL;
     984
     985        free(group->name);
     986        group->name = (char *)malloc((strlen(newgn)+1)*sizeof(char));
     987        strcpy(group->name, newgn);
     988
     989        /* Sync our local list with the server list */
     990        aim_ssi_sync(sess);
     991
     992        return 0;
    962993}
    963994
     
    9781009faim_export int aim_ssi_setpermdeny(aim_session_t *sess, fu8_t permdeny, fu32_t vismask)
    9791010{
    980   struct aim_ssi_item *tmp;
    981   aim_tlvlist_t *data = NULL;
    982  
    983   if (!sess)
    984     return -EINVAL;
    985  
    986   /* Need to add the x00ca TLV to the TLV chain */
    987   aim_addtlvtochain8(&data, 0x00ca, permdeny);
    988  
    989   /* Need to add the x00cb TLV to the TLV chain */
    990   aim_addtlvtochain32(&data, 0x00cb, vismask);
    991  
    992   if ((tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO))) {
    993     aim_freetlvchain(&tmp->data);
    994     tmp->data = data;
    995   } else {
    996     tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PDINFO, data);
    997     aim_freetlvchain(&data);
    998   }
    999  
    1000   /* Sync our local list with the server list */
    1001   aim_ssi_sync(sess);
    1002  
    1003   return 0;
     1011        struct aim_ssi_item *tmp;
     1012
     1013        if (!sess)
     1014                return -EINVAL;
     1015
     1016        /* Find the PDINFO item, or add it if it does not exist */
     1017        if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO)))
     1018                tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PDINFO, NULL);
     1019
     1020        /* Need to add the 0x00ca TLV to the TLV chain */
     1021        aim_tlvlist_replace_8(&tmp->data, 0x00ca, permdeny);
     1022
     1023        /* Need to add the 0x00cb TLV to the TLV chain */
     1024        aim_tlvlist_replace_32(&tmp->data, 0x00cb, vismask);
     1025
     1026        /* Sync our local list with the server list */
     1027        aim_ssi_sync(sess);
     1028
     1029        return 0;
    10041030}
    10051031
     
    10141040faim_export int aim_ssi_seticon(aim_session_t *sess, fu8_t *iconsum, fu16_t iconsumlen)
    10151041{
    1016   struct aim_ssi_item *tmp;
    1017   aim_tlvlist_t *data = NULL;
    1018   fu8_t *csumdata;
    1019  
    1020   if (!sess || !iconsum || !iconsumlen)
    1021     return -EINVAL;
    1022  
    1023   if (!(csumdata = (fu8_t *)malloc((iconsumlen+2)*sizeof(fu8_t))))
    1024     return -ENOMEM;
    1025   csumdata[0] = 0x00;
    1026   csumdata[1] = 0x10;
    1027   memcpy(&csumdata[2], iconsum, iconsumlen);
    1028  
    1029   /* Need to add the x00d5 TLV to the TLV chain */
    1030   aim_addtlvtochain_raw(&data, 0x00d5, (iconsumlen+2) * sizeof(fu8_t), csumdata);
    1031  
    1032   /* This TLV is added to cache the icon. */
    1033   aim_addtlvtochain_noval(&data, 0x0131);
    1034  
    1035   if ((tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) {
    1036     /* If the new tlvchain and oldtlvchain are the same, then do nothing */
    1037     if (!aim_tlvlist_cmp(tmp->data, data)) {
    1038       /* The new tlvlist is the identical to the old one */
    1039       aim_freetlvchain(&data);
    1040       free(csumdata);
    1041       return 0;
    1042     }
    1043     aim_freetlvchain(&tmp->data);
    1044     tmp->data = data;
    1045   } else {
    1046     tmp = aim_ssi_itemlist_add(&sess->ssi.local, "1", 0x0000, 0x51F4, AIM_SSI_TYPE_ICONINFO, data);
    1047     aim_freetlvchain(&data);
    1048   }
    1049  
    1050   /* Sync our local list with the server list */
    1051   aim_ssi_sync(sess);
    1052   free(csumdata);
    1053   return 0;
     1042        struct aim_ssi_item *tmp;
     1043        fu8_t *csumdata;
     1044
     1045        if (!sess || !iconsum || !iconsumlen)
     1046                return -EINVAL;
     1047
     1048        /* Find the ICONINFO item, or add it if it does not exist */
     1049        if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) {
     1050                tmp = aim_ssi_itemlist_add(&sess->ssi.local, "1", 0x0000, 0x51F4, AIM_SSI_TYPE_ICONINFO, NULL);
     1051        }
     1052
     1053        /* Need to add the 0x00d5 TLV to the TLV chain */
     1054        if (!(csumdata = (fu8_t *)malloc((iconsumlen+2)*sizeof(fu8_t))))
     1055                return -ENOMEM;
     1056        csumdata[0] = 0x00;
     1057        csumdata[1] = 0x10;
     1058        memcpy(&csumdata[2], iconsum, iconsumlen);
     1059        aim_tlvlist_replace_raw(&tmp->data, 0x00d5, (iconsumlen+2) * sizeof(fu8_t), csumdata);
     1060        free(csumdata);
     1061
     1062        /* Need to add the 0x0131 TLV to the TLV chain, used to cache the icon */
     1063        aim_tlvlist_replace_noval(&tmp->data, 0x0131);
     1064
     1065        /* Sync our local list with the server list */
     1066        aim_ssi_sync(sess);
     1067        return 0;
     1068}
     1069
     1070/**
     1071 * Remove a reference to a server stored buddy icon.  This will make your
     1072 * icon stop showing up to other people.
     1073 *
     1074 * @param sess The oscar session.
     1075 * @return Return 0 if no errors, otherwise return the error number.
     1076 */
     1077faim_export int aim_ssi_delicon(aim_session_t *sess)
     1078{
     1079        struct aim_ssi_item *tmp;
     1080
     1081        if (!sess)
     1082                return -EINVAL;
     1083
     1084        /* Find the ICONINFO item and delete it if it exists*/
     1085        if ((tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO)))
     1086                aim_ssi_itemlist_del(&sess->ssi.local, tmp);
     1087
     1088        /* Sync our local list with the server list */
     1089        aim_ssi_sync(sess);
     1090        return 0;
    10541091}
    10551092
     
    10591096 * @param sess The oscar session.
    10601097 * @param presence I think it's a bitmask, but I only know what one of the bits is:
     1098 *        0x00000002 - Hide wireless?
    10611099 *        0x00000400 - Allow others to see your idle time
    10621100 * @return Return 0 if no errors, otherwise return the error number.
    10631101 */
    10641102faim_export int aim_ssi_setpresence(aim_session_t *sess, fu32_t presence) {
    1065   struct aim_ssi_item *tmp;
    1066   aim_tlvlist_t *data = NULL;
    1067  
    1068   if (!sess)
    1069     return -EINVAL;
    1070  
    1071   /* Need to add the x00c9 TLV to the TLV chain */
    1072   aim_addtlvtochain32(&data, 0x00c9, presence);
    1073  
    1074   if ((tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) {
    1075     aim_freetlvchain(&tmp->data);
    1076     tmp->data = data;
    1077   } else {
    1078     tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PRESENCEPREFS, data);
    1079     aim_freetlvchain(&data);
    1080   }
    1081  
    1082   /* Sync our local list with the server list */
    1083   aim_ssi_sync(sess);
    1084  
    1085   return 0;
     1103        struct aim_ssi_item *tmp;
     1104
     1105        if (!sess)
     1106                return -EINVAL;
     1107
     1108        /* Find the PRESENCEPREFS item, or add it if it does not exist */
     1109        if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS)))
     1110                tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PRESENCEPREFS, NULL);
     1111
     1112        /* Need to add the x00c9 TLV to the TLV chain */
     1113        aim_tlvlist_replace_32(&tmp->data, 0x00c9, presence);
     1114
     1115        /* Sync our local list with the server list */
     1116        aim_ssi_sync(sess);
     1117
     1118        return 0;
    10861119}
    10871120
     
    10911124faim_export int aim_ssi_reqrights(aim_session_t *sess)
    10921125{
    1093   aim_conn_t *conn;
    1094  
    1095   if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
    1096     return -EINVAL;
    1097  
    1098   return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQRIGHTS);
     1126        aim_conn_t *conn;
     1127
     1128        if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
     1129                return -EINVAL;
     1130
     1131        return aim_genericreq_n_snacid(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQRIGHTS);
    10991132}
    11001133
     
    11041137static int parserights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    11051138{
    1106   int ret = 0, i;
    1107   aim_rxcallback_t userfunc;
    1108   aim_tlvlist_t *tlvlist;
    1109   aim_tlv_t *tlv;
    1110   aim_bstream_t bstream;
    1111   fu16_t *maxitems;
    1112  
    1113   /* This SNAC is made up of a bunch of TLVs */
    1114   tlvlist = aim_readtlvchain(bs);
    1115  
    1116   /* TLV 0x0004 contains the maximum number of each item */
    1117   if (!(tlv = aim_gettlv(tlvlist, 0x0004, 1))) {
    1118     aim_freetlvchain(&tlvlist);
    1119     return 0;
    1120   }
    1121  
    1122   aim_bstream_init(&bstream, tlv->value, tlv->length);
    1123  
    1124   if (!(maxitems = (fu16_t *)malloc((tlv->length/2)*sizeof(fu16_t)))) {
    1125     aim_freetlvchain(&tlvlist);
    1126     return 0;
    1127   }
    1128  
    1129   for (i=0; i<(tlv->length/2); i++)
    1130     maxitems[i] = aimbs_get16(&bstream);
    1131  
    1132   if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1133     ret = userfunc(sess, rx, tlv->length/2, maxitems);
    1134  
    1135   aim_freetlvchain(&tlvlist);
    1136   free(maxitems);
    1137  
    1138   return ret;
     1139        int ret = 0, i;
     1140        aim_rxcallback_t userfunc;
     1141        aim_tlvlist_t *tlvlist;
     1142        aim_tlv_t *tlv;
     1143        aim_bstream_t bstream;
     1144        fu16_t *maxitems;
     1145
     1146        /* This SNAC is made up of a bunch of TLVs */
     1147        tlvlist = aim_tlvlist_read(bs);
     1148
     1149        /* TLV 0x0004 contains the maximum number of each item */
     1150        if (!(tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
     1151                aim_tlvlist_free(&tlvlist);
     1152                return 0;
     1153        }
     1154
     1155        aim_bstream_init(&bstream, tlv->value, tlv->length);
     1156
     1157        if (!(maxitems = (fu16_t *)malloc((tlv->length/2)*sizeof(fu16_t)))) {
     1158                aim_tlvlist_free(&tlvlist);
     1159                return 0;
     1160        }
     1161
     1162        for (i=0; i<(tlv->length/2); i++)
     1163                maxitems[i] = aimbs_get16(&bstream);
     1164
     1165        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
     1166                ret = userfunc(sess, rx, tlv->length/2, maxitems);
     1167
     1168        aim_tlvlist_free(&tlvlist);
     1169        free(maxitems);
     1170
     1171        return ret;
    11391172}
    11401173
     
    11461179faim_export int aim_ssi_reqdata(aim_session_t *sess)
    11471180{
    1148   aim_conn_t *conn;
    1149  
    1150   if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
    1151     return -EINVAL;
    1152  
    1153   /* Free any current data, just in case */
    1154   aim_ssi_freelist(sess);
    1155  
    1156   return aim_genericreq_n_snacid(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQDATA);
     1181        aim_conn_t *conn;
     1182
     1183        if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
     1184                return -EINVAL;
     1185
     1186        /* Free any current data, just in case */
     1187        aim_ssi_freelist(sess);
     1188
     1189        return aim_genericreq_n_snacid(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQDATA);
    11571190}
    11581191
     
    11691202faim_export int aim_ssi_reqifchanged(aim_session_t *sess, time_t timestamp, fu16_t numitems)
    11701203{
    1171   aim_conn_t *conn;
    1172   aim_frame_t *fr;
    1173   aim_snacid_t snacid;
    1174  
    1175   if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
    1176     return -EINVAL;
    1177  
    1178   if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+2)))
    1179     return -ENOMEM;
    1180  
    1181   snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, NULL, 0);
    1182  
    1183   aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, snacid);
    1184   aimbs_put32(&fr->data, timestamp);
    1185   aimbs_put16(&fr->data, numitems);
    1186  
    1187   aim_tx_enqueue(sess, fr);
    1188  
    1189   /* Free any current data, just in case */
    1190   aim_ssi_freelist(sess);
    1191  
    1192   return 0;
     1204        aim_conn_t *conn;
     1205        aim_frame_t *fr;
     1206        aim_snacid_t snacid;
     1207
     1208        if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
     1209                return -EINVAL;
     1210
     1211        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+2)))
     1212                return -ENOMEM;
     1213
     1214        snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, NULL, 0);
     1215
     1216        aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, snacid);
     1217        aimbs_put32(&fr->data, timestamp);
     1218        aimbs_put16(&fr->data, numitems);
     1219
     1220        aim_tx_enqueue(sess, fr);
     1221
     1222        /* Free any current data, just in case */
     1223        aim_ssi_freelist(sess);
     1224
     1225        return 0;
    11931226}
    11941227
     
    11981231static int parsedata(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    11991232{
    1200   int ret = 0;
    1201   aim_rxcallback_t userfunc;
    1202   fu8_t fmtver; /* guess */
    1203   fu16_t namelen, gid, bid, type;
    1204   char *name;
    1205   aim_tlvlist_t *data;
    1206  
    1207   fmtver = aimbs_get8(bs); /* Version of ssi data.  Should be 0x00 */
    1208   sess->ssi.numitems += aimbs_get16(bs); /* # of items in this SSI SNAC */
    1209  
    1210   /* Read in the list */
    1211   while (aim_bstream_empty(bs) > 4) { /* last four bytes are timestamp */
    1212     if ((namelen = aimbs_get16(bs)))
    1213       name = aimbs_getstr(bs, namelen);
    1214     else
    1215       name = NULL;
    1216     gid = aimbs_get16(bs);
    1217     bid = aimbs_get16(bs);
    1218     type = aimbs_get16(bs);
    1219     data = aim_readtlvchain_len(bs, aimbs_get16(bs));
    1220     aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data);
    1221     free(name);
    1222     aim_freetlvchain(&data);
    1223   }
    1224  
    1225   /* Read in the timestamp */
    1226   sess->ssi.timestamp = aimbs_get32(bs);
    1227  
    1228   if (!(snac->flags & 0x0001)) {
    1229     /* Make a copy of the list */
    1230     struct aim_ssi_item *cur;
    1231     for (cur=sess->ssi.official; cur; cur=cur->next)
    1232       aim_ssi_itemlist_add(&sess->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data);
    1233    
    1234     sess->ssi.received_data = 1;
    1235    
    1236     if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1237       ret = userfunc(sess, rx, fmtver, sess->ssi.numitems, sess->ssi.official, sess->ssi.timestamp);
    1238   }
    1239  
    1240   return ret;
     1233        int ret = 0;
     1234        aim_rxcallback_t userfunc;
     1235        fu8_t fmtver; /* guess */
     1236        fu16_t namelen, gid, bid, type;
     1237        char *name;
     1238        aim_tlvlist_t *data;
     1239
     1240        fmtver = aimbs_get8(bs); /* Version of ssi data.  Should be 0x00 */
     1241        sess->ssi.numitems += aimbs_get16(bs); /* # of items in this SSI SNAC */
     1242
     1243        /* Read in the list */
     1244        while (aim_bstream_empty(bs) > 4) { /* last four bytes are timestamp */
     1245                if ((namelen = aimbs_get16(bs)))
     1246                        name = aimbs_getstr(bs, namelen);
     1247                else
     1248                        name = NULL;
     1249                gid = aimbs_get16(bs);
     1250                bid = aimbs_get16(bs);
     1251                type = aimbs_get16(bs);
     1252                data = aim_tlvlist_readlen(bs, aimbs_get16(bs));
     1253                aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data);
     1254                free(name);
     1255                aim_tlvlist_free(&data);
     1256        }
     1257
     1258        /* Read in the timestamp */
     1259        sess->ssi.timestamp = aimbs_get32(bs);
     1260
     1261        if (!(snac->flags & 0x0001)) {
     1262                /* Make a copy of the list */
     1263                struct aim_ssi_item *cur;
     1264                for (cur=sess->ssi.official; cur; cur=cur->next)
     1265                        aim_ssi_itemlist_add(&sess->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data);
     1266
     1267                sess->ssi.received_data = 1;
     1268
     1269                if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
     1270                        ret = userfunc(sess, rx, fmtver, sess->ssi.numitems, sess->ssi.official, sess->ssi.timestamp);
     1271        }
     1272
     1273        return ret;
    12411274}
    12421275
     
    12521285faim_export int aim_ssi_enable(aim_session_t *sess)
    12531286{
    1254   aim_conn_t *conn;
    1255  
    1256   if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
    1257     return -EINVAL;
    1258  
    1259   return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, 0x0007);
     1287        aim_conn_t *conn;
     1288
     1289        if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
     1290                return -EINVAL;
     1291
     1292        return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, 0x0007);
    12601293}
    12611294
     
    12701303faim_export int aim_ssi_addmoddel(aim_session_t *sess)
    12711304{
    1272   aim_conn_t *conn;
    1273   aim_frame_t *fr;
    1274   aim_snacid_t snacid;
    1275   int snaclen;
    1276   struct aim_ssi_tmp *cur;
    1277  
    1278   if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sess->ssi.pending || !sess->ssi.pending->item) {
    1279     owl_function_debugmsg("aim_ssi_addmoddel: aborting early");
    1280     return -EINVAL;
    1281   }
    1282  
    1283   /* Calculate total SNAC size */
    1284   snaclen = 10; /* For family, subtype, flags, and SNAC ID */
    1285   for (cur=sess->ssi.pending; cur; cur=cur->next) {
    1286     snaclen += 10; /* For length, GID, BID, type, and length */
    1287     if (cur->item->name) snaclen += strlen(cur->item->name);
    1288     if (cur->item->data) snaclen += aim_sizetlvchain(&cur->item->data);
    1289   }
    1290  
    1291   if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen))) return (-ENOMEM);
    1292  
    1293   snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, sess->ssi.pending->action, 0x0000, NULL, 0);
    1294   aim_putsnac(&fr->data, AIM_CB_FAM_SSI, sess->ssi.pending->action, 0x0000, snacid);
    1295  
    1296   for (cur=sess->ssi.pending; cur; cur=cur->next) {
    1297     aimbs_put16(&fr->data, cur->item->name ? strlen(cur->item->name) : 0);
    1298     if (cur->item->name) aimbs_putraw(&fr->data, cur->item->name, strlen(cur->item->name));
    1299     aimbs_put16(&fr->data, cur->item->gid);
    1300     aimbs_put16(&fr->data, cur->item->bid);
    1301     aimbs_put16(&fr->data, cur->item->type);
    1302     aimbs_put16(&fr->data, cur->item->data ? aim_sizetlvchain(&cur->item->data) : 0);
    1303     if (cur->item->data) aim_writetlvchain(&fr->data, &cur->item->data);
    1304   }
    1305  
    1306   aim_tx_enqueue(sess, fr);
    1307 
    1308   owl_function_debugmsg("aim_ssi_addmoddel: exiting normally");
    1309   return 0;
     1305        aim_conn_t *conn;
     1306        aim_frame_t *fr;
     1307        aim_snacid_t snacid;
     1308        int snaclen;
     1309        struct aim_ssi_tmp *cur;
     1310
     1311        if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sess->ssi.pending || !sess->ssi.pending->item)
     1312                return -EINVAL;
     1313
     1314        /* Calculate total SNAC size */
     1315        snaclen = 10; /* For family, subtype, flags, and SNAC ID */
     1316        for (cur=sess->ssi.pending; cur; cur=cur->next) {
     1317                snaclen += 10; /* For length, GID, BID, type, and length */
     1318                if (cur->item->name)
     1319                        snaclen += strlen(cur->item->name);
     1320                if (cur->item->data)
     1321                        snaclen += aim_tlvlist_size(&cur->item->data);
     1322        }
     1323
     1324        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen)))
     1325                return -ENOMEM;
     1326
     1327        snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, sess->ssi.pending->action, 0x0000, NULL, 0);
     1328        aim_putsnac(&fr->data, AIM_CB_FAM_SSI, sess->ssi.pending->action, 0x0000, snacid);
     1329
     1330        for (cur=sess->ssi.pending; cur; cur=cur->next) {
     1331                aimbs_put16(&fr->data, cur->item->name ? strlen(cur->item->name) : 0);
     1332                if (cur->item->name)
     1333                        aimbs_putraw(&fr->data, cur->item->name, strlen(cur->item->name));
     1334                aimbs_put16(&fr->data, cur->item->gid);
     1335                aimbs_put16(&fr->data, cur->item->bid);
     1336                aimbs_put16(&fr->data, cur->item->type);
     1337                aimbs_put16(&fr->data, cur->item->data ? aim_tlvlist_size(&cur->item->data) : 0);
     1338                if (cur->item->data)
     1339                        aim_tlvlist_write(&fr->data, &cur->item->data);
     1340        }
     1341
     1342        aim_tx_enqueue(sess, fr);
     1343
     1344        return 0;
    13101345}
    13111346
     
    13171352static int parseadd(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    13181353{
    1319   int ret = 0;
    1320   aim_rxcallback_t userfunc;
    1321   char *name;
    1322   fu16_t len, gid, bid, type;
    1323   aim_tlvlist_t *data;
    1324  
    1325   while (aim_bstream_empty(bs)) {
    1326     if ((len = aimbs_get16(bs)))
    1327       name = aimbs_getstr(bs, len);
    1328     else
    1329       name = NULL;
    1330     gid = aimbs_get16(bs);
    1331     bid = aimbs_get16(bs);
    1332     type = aimbs_get16(bs);
    1333     if ((len = aimbs_get16(bs)))
    1334       data = aim_readtlvchain_len(bs, len);
    1335     else
    1336       data = NULL;
    1337    
    1338     aim_ssi_itemlist_add(&sess->ssi.local, name, gid, bid, type, data);
    1339     aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data);
    1340     free(name);
    1341     aim_freetlvchain(&data);
    1342    
    1343     if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1344       ret = userfunc(sess, rx);
    1345    
    1346     free(name);
    1347   }
    1348  
    1349   return ret;
     1354        int ret = 0;
     1355        aim_rxcallback_t userfunc;
     1356        char *name;
     1357        fu16_t len, gid, bid, type;
     1358        aim_tlvlist_t *data;
     1359
     1360        while (aim_bstream_empty(bs)) {
     1361                if ((len = aimbs_get16(bs)))
     1362                        name = aimbs_getstr(bs, len);
     1363                else
     1364                        name = NULL;
     1365                gid = aimbs_get16(bs);
     1366                bid = aimbs_get16(bs);
     1367                type = aimbs_get16(bs);
     1368                if ((len = aimbs_get16(bs)))
     1369                        data = aim_tlvlist_readlen(bs, len);
     1370                else
     1371                        data = NULL;
     1372
     1373                aim_ssi_itemlist_add(&sess->ssi.local, name, gid, bid, type, data);
     1374                aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data);
     1375                free(name);
     1376                aim_tlvlist_free(&data);
     1377
     1378                if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
     1379                        ret = userfunc(sess, rx);
     1380
     1381                free(name);
     1382        }
     1383
     1384        return ret;
    13501385}
    13511386
     
    13571392static int parsemod(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    13581393{
    1359   int ret = 0;
    1360   aim_rxcallback_t userfunc;
    1361   char *name;
    1362   fu16_t len, gid, bid, type;
    1363   aim_tlvlist_t *data;
    1364   struct aim_ssi_item *item;
    1365  
    1366   while (aim_bstream_empty(bs)) {
    1367     if ((len = aimbs_get16(bs)))
    1368       name = aimbs_getstr(bs, len);
    1369     else
    1370       name = NULL;
    1371     gid = aimbs_get16(bs);
    1372     bid = aimbs_get16(bs);
    1373     type = aimbs_get16(bs);
    1374     if ((len = aimbs_get16(bs)))
    1375       data = aim_readtlvchain_len(bs, len);
    1376     else
    1377       data = NULL;
    1378    
    1379     /* Replace the 2 local items with the given one */
    1380     if ((item = aim_ssi_itemlist_find(sess->ssi.local, gid, bid))) {
    1381       item->type = type;
    1382       free(item->name);
    1383       if (name) {
    1384         item->name = (char *)malloc((strlen(name)+1)*sizeof(char));
    1385         strcpy(item->name, name);
    1386       } else
    1387         item->name = NULL;
    1388       aim_freetlvchain(&item->data);
    1389       item->data = aim_tlvlist_copy(data);
    1390     }
    1391    
    1392     if ((item = aim_ssi_itemlist_find(sess->ssi.official, gid, bid))) {
    1393       item->type = type;
    1394       free(item->name);
    1395       if (name) {
    1396         item->name = (char *)malloc((strlen(name)+1)*sizeof(char));
    1397         strcpy(item->name, name);
    1398       } else
    1399         item->name = NULL;
    1400       aim_freetlvchain(&item->data);
    1401       item->data = aim_tlvlist_copy(data);
    1402     }
    1403    
    1404     if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1405       ret = userfunc(sess, rx);
    1406    
    1407     free(name);
    1408     aim_freetlvchain(&data);
    1409   }
    1410  
    1411   return ret;
     1394        int ret = 0;
     1395        aim_rxcallback_t userfunc;
     1396        char *name;
     1397        fu16_t len, gid, bid, type;
     1398        aim_tlvlist_t *data;
     1399        struct aim_ssi_item *item;
     1400
     1401        while (aim_bstream_empty(bs)) {
     1402                if ((len = aimbs_get16(bs)))
     1403                        name = aimbs_getstr(bs, len);
     1404                else
     1405                        name = NULL;
     1406                gid = aimbs_get16(bs);
     1407                bid = aimbs_get16(bs);
     1408                type = aimbs_get16(bs);
     1409                if ((len = aimbs_get16(bs)))
     1410                        data = aim_tlvlist_readlen(bs, len);
     1411                else
     1412                        data = NULL;
     1413
     1414                /* Replace the 2 local items with the given one */
     1415                if ((item = aim_ssi_itemlist_find(sess->ssi.local, gid, bid))) {
     1416                        item->type = type;
     1417                        free(item->name);
     1418                        if (name) {
     1419                                item->name = (char *)malloc((strlen(name)+1)*sizeof(char));
     1420                                strcpy(item->name, name);
     1421                        } else
     1422                                item->name = NULL;
     1423                        aim_tlvlist_free(&item->data);
     1424                        item->data = aim_tlvlist_copy(data);
     1425                }
     1426
     1427                if ((item = aim_ssi_itemlist_find(sess->ssi.official, gid, bid))) {
     1428                        item->type = type;
     1429                        free(item->name);
     1430                        if (name) {
     1431                                item->name = (char *)malloc((strlen(name)+1)*sizeof(char));
     1432                                strcpy(item->name, name);
     1433                        } else
     1434                                item->name = NULL;
     1435                        aim_tlvlist_free(&item->data);
     1436                        item->data = aim_tlvlist_copy(data);
     1437                }
     1438
     1439                if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
     1440                        ret = userfunc(sess, rx);
     1441
     1442                free(name);
     1443                aim_tlvlist_free(&data);
     1444        }
     1445
     1446        return ret;
    14121447}
    14131448
     
    14191454static int parsedel(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    14201455{
    1421   int ret = 0;
    1422   aim_rxcallback_t userfunc;
    1423   fu16_t gid, bid;
    1424   struct aim_ssi_item *del;
    1425  
    1426   while (aim_bstream_empty(bs)) {
    1427     aim_bstream_advance(bs, aimbs_get16(bs));
    1428     gid = aimbs_get16(bs);
    1429     bid = aimbs_get16(bs);
    1430     aimbs_get16(bs);
    1431     aim_bstream_advance(bs, aimbs_get16(bs));
    1432    
    1433     if ((del = aim_ssi_itemlist_find(sess->ssi.local, gid, bid)))
    1434       aim_ssi_itemlist_del(&sess->ssi.local, del);
    1435     if ((del = aim_ssi_itemlist_find(sess->ssi.official, gid, bid)))
    1436       aim_ssi_itemlist_del(&sess->ssi.official, del);
    1437    
    1438     if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1439       ret = userfunc(sess, rx);
    1440   }
    1441  
    1442   return ret;
     1456        int ret = 0;
     1457        aim_rxcallback_t userfunc;
     1458        fu16_t gid, bid;
     1459        struct aim_ssi_item *del;
     1460
     1461        while (aim_bstream_empty(bs)) {
     1462                aim_bstream_advance(bs, aimbs_get16(bs));
     1463                gid = aimbs_get16(bs);
     1464                bid = aimbs_get16(bs);
     1465                aimbs_get16(bs);
     1466                aim_bstream_advance(bs, aimbs_get16(bs));
     1467
     1468                if ((del = aim_ssi_itemlist_find(sess->ssi.local, gid, bid)))
     1469                        aim_ssi_itemlist_del(&sess->ssi.local, del);
     1470                if ((del = aim_ssi_itemlist_find(sess->ssi.official, gid, bid)))
     1471                        aim_ssi_itemlist_del(&sess->ssi.official, del);
     1472
     1473                if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
     1474                        ret = userfunc(sess, rx);
     1475        }
     1476
     1477        return ret;
    14431478}
    14441479
     
    14511486static int parseack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    14521487{
    1453   int ret = 0;
    1454   aim_rxcallback_t userfunc;
    1455   struct aim_ssi_tmp *cur, *del;
    1456 
    1457   owl_function_debugmsg("Handling SNAC SSI ACK");
    1458  
    1459   /* Read in the success/failure flags from the ack SNAC */
    1460   cur = sess->ssi.pending;
    1461   while (cur && (aim_bstream_empty(bs)>0)) {
    1462     cur->ack = aimbs_get16(bs);
    1463     cur = cur->next;
    1464   }
    1465  
    1466   /*
    1467    * If outcome is 0, then add the item to the item list, or replace the other item,
    1468    * or remove the old item.  If outcome is non-zero, then remove the item from the
    1469    * local list, or unmodify it, or add it.
    1470    */
    1471   for (cur=sess->ssi.pending; (cur && (cur->ack != 0xffff)); cur=cur->next) {
    1472     owl_function_debugmsg("parseack: processing a change");
    1473     if (cur->item) {
    1474       if (cur->ack) {
    1475         /* Our action was unsuccessful, so change the local list back to how it was */
    1476         if (cur->action == AIM_CB_SSI_ADD) {
    1477           owl_function_debugmsg("parseack: unsuccesful add, reverting");
    1478           /* Remove the item from the local list */
    1479           /* Make sure cur->item is still valid memory */
    1480           if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) {
    1481             if (cur->item->name) {
    1482               cur->name = (char *)malloc((strlen(cur->item->name)+1)*sizeof(char));
    1483               strcpy(cur->name, cur->item->name);
    1484             }
    1485             aim_ssi_itemlist_del(&sess->ssi.local, cur->item);
    1486           }
    1487           cur->item = NULL;
    1488          
    1489         } else if (cur->action == AIM_CB_SSI_MOD) {
    1490           /* Replace the local item with the item from the official list */
    1491           owl_function_debugmsg("parseack: unsuccesful modify, reverting");
    1492           if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) {
    1493             struct aim_ssi_item *cur1;
    1494             if ((cur1 = aim_ssi_itemlist_find(sess->ssi.official, cur->item->gid, cur->item->bid))) {
    1495               free(cur->item->name);
    1496               if (cur1->name) {
    1497                 cur->item->name = (char *)malloc((strlen(cur1->name)+1)*sizeof(char));
    1498                 strcpy(cur->item->name, cur1->name);
    1499               } else
    1500                 cur->item->name = NULL;
    1501               aim_freetlvchain(&cur->item->data);
    1502               cur->item->data = aim_tlvlist_copy(cur1->data);
    1503             }
    1504           } else
    1505             cur->item = NULL;
    1506          
    1507         } else if (cur->action == AIM_CB_SSI_DEL) {
    1508           /* Add the item back into the local list */
    1509           owl_function_debugmsg("parseack: unsuccesful delete, reverting");
    1510           if (aim_ssi_itemlist_valid(sess->ssi.official, cur->item)) {
    1511             aim_ssi_itemlist_add(&sess->ssi.local, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data);
    1512           } else
    1513             cur->item = NULL;
    1514         }
    1515        
    1516       } else {
    1517         /* Do the exact opposite */
    1518         if (cur->action == AIM_CB_SSI_ADD) {
    1519           /* Add the local item to the official list */
    1520           owl_function_debugmsg("parseack: succesful add");
    1521           if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) {
    1522             aim_ssi_itemlist_add(&sess->ssi.official, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data);
    1523           } else
    1524             cur->item = NULL;
    1525          
    1526         } else if (cur->action == AIM_CB_SSI_MOD) {
    1527           /* Replace the official item with the item from the local list */
    1528           owl_function_debugmsg("parseack: succesful modify");
    1529           if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) {
    1530             struct aim_ssi_item *cur1;
    1531             if ((cur1 = aim_ssi_itemlist_find(sess->ssi.official, cur->item->gid, cur->item->bid))) {
    1532               free(cur1->name);
    1533               if (cur->item->name) {
    1534                 cur1->name = (char *)malloc((strlen(cur->item->name)+1)*sizeof(char));
    1535                 strcpy(cur1->name, cur->item->name);
    1536               } else
    1537                 cur1->name = NULL;
    1538               aim_freetlvchain(&cur1->data);
    1539               cur1->data = aim_tlvlist_copy(cur->item->data);
    1540             }
    1541           } else
    1542             cur->item = NULL;
    1543          
    1544         } else if (cur->action == AIM_CB_SSI_DEL) {
    1545           /* Remove the item from the official list */
    1546           owl_function_debugmsg("parseack: succesful delete");
    1547           if (aim_ssi_itemlist_valid(sess->ssi.official, cur->item))
    1548             aim_ssi_itemlist_del(&sess->ssi.official, cur->item);
    1549           cur->item = NULL;
    1550         }
    1551        
    1552       }
    1553     } /* End if (cur->item) */
    1554   } /* End for loop */
    1555  
    1556   if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1557     ret = userfunc(sess, rx, sess->ssi.pending);
    1558  
    1559   /* Free all aim_ssi_tmp's with an outcome */
    1560   cur = sess->ssi.pending;
    1561   while (cur && (cur->ack != 0xffff)) {
    1562     del = cur;
    1563     cur = cur->next;
    1564     free(del->name);
    1565     free(del);
    1566   }
    1567   sess->ssi.pending = cur;
    1568  
    1569   /* If we're not waiting for any more acks, then send more SNACs */
    1570 
    1571   if (!sess->ssi.pending) {
    1572     sess->ssi.pending = NULL;
    1573     sess->ssi.waiting_for_ack = 0;
    1574     owl_function_debugmsg("parseack: Clearing SSI waiting_for_ack");
    1575     aim_ssi_sync(sess);
    1576   }
    1577 
    1578   owl_function_debugmsg("parseack: returning with %i", ret);
    1579  
    1580   return ret;
     1488        int ret = 0;
     1489        aim_rxcallback_t userfunc;
     1490        struct aim_ssi_tmp *cur, *del;
     1491
     1492        /* Read in the success/failure flags from the ack SNAC */
     1493        cur = sess->ssi.pending;
     1494        while (cur && (aim_bstream_empty(bs)>0)) {
     1495                cur->ack = aimbs_get16(bs);
     1496                cur = cur->next;
     1497        }
     1498
     1499        /*
     1500         * If outcome is 0, then add the item to the item list, or replace the other item,
     1501         * or remove the old item.  If outcome is non-zero, then remove the item from the
     1502         * local list, or unmodify it, or add it.
     1503         */
     1504        for (cur=sess->ssi.pending; (cur && (cur->ack != 0xffff)); cur=cur->next) {
     1505        if (cur->item) {
     1506                if (cur->ack) {
     1507                        /* Our action was unsuccessful, so change the local list back to how it was */
     1508                        if (cur->action == AIM_CB_SSI_ADD) {
     1509                                /* Remove the item from the local list */
     1510                                /* Make sure cur->item is still valid memory */
     1511                                if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) {
     1512                                        if (cur->item->name) {
     1513                                                cur->name = (char *)malloc((strlen(cur->item->name)+1)*sizeof(char));
     1514                                                strcpy(cur->name, cur->item->name);
     1515                                        }
     1516                                        aim_ssi_itemlist_del(&sess->ssi.local, cur->item);
     1517                                }
     1518                                cur->item = NULL;
     1519
     1520                        } else if (cur->action == AIM_CB_SSI_MOD) {
     1521                                /* Replace the local item with the item from the official list */
     1522                                if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) {
     1523                                        struct aim_ssi_item *cur1;
     1524                                        if ((cur1 = aim_ssi_itemlist_find(sess->ssi.official, cur->item->gid, cur->item->bid))) {
     1525                                                free(cur->item->name);
     1526                                                if (cur1->name) {
     1527                                                        cur->item->name = (char *)malloc((strlen(cur1->name)+1)*sizeof(char));
     1528                                                        strcpy(cur->item->name, cur1->name);
     1529                                                } else
     1530                                                        cur->item->name = NULL;
     1531                                                aim_tlvlist_free(&cur->item->data);
     1532                                                cur->item->data = aim_tlvlist_copy(cur1->data);
     1533                                        }
     1534                                } else
     1535                                        cur->item = NULL;
     1536
     1537                        } else if (cur->action == AIM_CB_SSI_DEL) {
     1538                                /* Add the item back into the local list */
     1539                                if (aim_ssi_itemlist_valid(sess->ssi.official, cur->item)) {
     1540                                        aim_ssi_itemlist_add(&sess->ssi.local, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data);
     1541                                } else
     1542                                        cur->item = NULL;
     1543                        }
     1544
     1545                } else {
     1546                        /* Do the exact opposite */
     1547                        if (cur->action == AIM_CB_SSI_ADD) {
     1548                        /* Add the local item to the official list */
     1549                                if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) {
     1550                                        aim_ssi_itemlist_add(&sess->ssi.official, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data);
     1551                                } else
     1552                                        cur->item = NULL;
     1553
     1554                        } else if (cur->action == AIM_CB_SSI_MOD) {
     1555                                /* Replace the official item with the item from the local list */
     1556                                if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) {
     1557                                        struct aim_ssi_item *cur1;
     1558                                        if ((cur1 = aim_ssi_itemlist_find(sess->ssi.official, cur->item->gid, cur->item->bid))) {
     1559                                                free(cur1->name);
     1560                                                if (cur->item->name) {
     1561                                                        cur1->name = (char *)malloc((strlen(cur->item->name)+1)*sizeof(char));
     1562                                                        strcpy(cur1->name, cur->item->name);
     1563                                                } else
     1564                                                        cur1->name = NULL;
     1565                                                aim_tlvlist_free(&cur1->data);
     1566                                                cur1->data = aim_tlvlist_copy(cur->item->data);
     1567                                        }
     1568                                } else
     1569                                        cur->item = NULL;
     1570
     1571                        } else if (cur->action == AIM_CB_SSI_DEL) {
     1572                                /* Remove the item from the official list */
     1573                                if (aim_ssi_itemlist_valid(sess->ssi.official, cur->item))
     1574                                        aim_ssi_itemlist_del(&sess->ssi.official, cur->item);
     1575                                cur->item = NULL;
     1576                        }
     1577
     1578                }
     1579        } /* End if (cur->item) */
     1580        } /* End for loop */
     1581
     1582        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
     1583                ret = userfunc(sess, rx, sess->ssi.pending);
     1584
     1585        /* Free all aim_ssi_tmp's with an outcome */
     1586        cur = sess->ssi.pending;
     1587        while (cur && (cur->ack != 0xffff)) {
     1588                del = cur;
     1589                cur = cur->next;
     1590                free(del->name);
     1591                free(del);
     1592        }
     1593        sess->ssi.pending = cur;
     1594
     1595        /* If we're not waiting for any more acks, then send more SNACs */
     1596        if (!sess->ssi.pending) {
     1597                sess->ssi.pending = NULL;
     1598                sess->ssi.waiting_for_ack = 0;
     1599                aim_ssi_sync(sess);
     1600        }
     1601
     1602        return ret;
    15811603}
    15821604
     
    15901612static int parsedataunchanged(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    15911613{
    1592   int ret = 0;
    1593   aim_rxcallback_t userfunc;
    1594  
    1595   sess->ssi.received_data = 1;
    1596  
    1597   if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1598     ret = userfunc(sess, rx);
    1599  
    1600   return ret;
     1614        int ret = 0;
     1615        aim_rxcallback_t userfunc;
     1616
     1617        sess->ssi.received_data = 1;
     1618
     1619        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
     1620                ret = userfunc(sess, rx);
     1621
     1622        return ret;
    16011623}
    16021624
     
    16091631faim_export int aim_ssi_modbegin(aim_session_t *sess)
    16101632{
    1611   aim_conn_t *conn;
    1612  
    1613   if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
    1614     return -EINVAL;
    1615  
    1616   return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTART);
     1633        aim_conn_t *conn;
     1634
     1635        if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
     1636                return -EINVAL;
     1637
     1638        return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTART);
    16171639}
    16181640
     
    16251647faim_export int aim_ssi_modend(aim_session_t *sess)
    16261648{
    1627   aim_conn_t *conn;
    1628  
    1629   if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI))) return -EINVAL;
    1630  
    1631   return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTOP);
     1649        aim_conn_t *conn;
     1650
     1651        if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
     1652                return -EINVAL;
     1653
     1654        return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTOP);
    16321655}
    16331656
     
    16401663faim_export int aim_ssi_sendauth(aim_session_t *sess, char *sn, char *msg)
    16411664{
    1642   aim_conn_t *conn;
    1643   aim_frame_t *fr;
    1644   aim_snacid_t snacid;
    1645  
    1646   if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn)
    1647     return -EINVAL;
    1648  
    1649   if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2)))
    1650     return -ENOMEM;
    1651  
    1652   snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTH, 0x0000, NULL, 0);
    1653   aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTH, 0x0000, snacid);
    1654  
    1655   /* Screen name */
    1656   aimbs_put8(&fr->data, strlen(sn));
    1657   aimbs_putraw(&fr->data, sn, strlen(sn));
    1658  
    1659   /* Message (null terminated) */
    1660   aimbs_put16(&fr->data, msg ? strlen(msg) : 0);
    1661   if (msg) {
    1662     aimbs_putraw(&fr->data, msg, strlen(msg));
    1663     aimbs_put8(&fr->data, 0x00);
    1664   }
    1665  
    1666   /* Unknown */
    1667   aimbs_put16(&fr->data, 0x0000);
    1668  
    1669   aim_tx_enqueue(sess, fr);
    1670  
    1671   return 0;
     1665        aim_conn_t *conn;
     1666        aim_frame_t *fr;
     1667        aim_snacid_t snacid;
     1668
     1669        if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn)
     1670                return -EINVAL;
     1671
     1672        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2)))
     1673                return -ENOMEM;
     1674
     1675        snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTH, 0x0000, NULL, 0);
     1676        aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTH, 0x0000, snacid);
     1677
     1678        /* Screen name */
     1679        aimbs_put8(&fr->data, strlen(sn));
     1680        aimbs_putraw(&fr->data, sn, strlen(sn));
     1681
     1682        /* Message (null terminated) */
     1683        aimbs_put16(&fr->data, msg ? strlen(msg) : 0);
     1684        if (msg) {
     1685                aimbs_putraw(&fr->data, msg, strlen(msg));
     1686                aimbs_put8(&fr->data, 0x00);
     1687        }
     1688
     1689        /* Unknown */
     1690        aimbs_put16(&fr->data, 0x0000);
     1691
     1692        aim_tx_enqueue(sess, fr);
     1693
     1694        return 0;
    16721695}
    16731696
     
    16771700static int receiveauthgrant(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    16781701{
    1679   int ret = 0;
    1680   aim_rxcallback_t userfunc;
    1681   fu16_t tmp;
    1682   char *sn, *msg;
    1683  
    1684   /* Read screen name */
    1685   if ((tmp = aimbs_get8(bs)))
    1686     sn = aimbs_getstr(bs, tmp);
    1687   else
    1688     sn = NULL;
    1689  
    1690   /* Read message (null terminated) */
    1691   if ((tmp = aimbs_get16(bs)))
    1692     msg = aimbs_getstr(bs, tmp);
    1693   else
    1694     msg = NULL;
    1695  
    1696   /* Unknown */
    1697   tmp = aimbs_get16(bs);
    1698  
    1699   if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1700     ret = userfunc(sess, rx, sn, msg);
    1701  
    1702   free(sn);
    1703   free(msg);
    1704  
    1705   return ret;
     1702        int ret = 0;
     1703        aim_rxcallback_t userfunc;
     1704        fu16_t tmp;
     1705        char *sn, *msg;
     1706
     1707        /* Read screen name */
     1708        if ((tmp = aimbs_get8(bs)))
     1709                sn = aimbs_getstr(bs, tmp);
     1710        else
     1711                sn = NULL;
     1712
     1713        /* Read message (null terminated) */
     1714        if ((tmp = aimbs_get16(bs)))
     1715                msg = aimbs_getstr(bs, tmp);
     1716        else
     1717                msg = NULL;
     1718
     1719        /* Unknown */
     1720        tmp = aimbs_get16(bs);
     1721
     1722        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
     1723                ret = userfunc(sess, rx, sn, msg);
     1724
     1725        free(sn);
     1726        free(msg);
     1727
     1728        return ret;
    17061729}
    17071730
     
    17151738faim_export int aim_ssi_sendauthrequest(aim_session_t *sess, char *sn, char *msg)
    17161739{
    1717   aim_conn_t *conn;
    1718   aim_frame_t *fr;
    1719   aim_snacid_t snacid;
    1720  
    1721   if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn)
    1722     return -EINVAL;
    1723  
    1724   if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2)))
    1725     return -ENOMEM;
    1726  
    1727   snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, NULL, 0);
    1728   aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, snacid);
    1729  
    1730   /* Screen name */
    1731   aimbs_put8(&fr->data, strlen(sn));
    1732   aimbs_putraw(&fr->data, sn, strlen(sn));
    1733  
    1734   /* Message (null terminated) */
    1735   aimbs_put16(&fr->data, msg ? strlen(msg) : 0);
    1736   if (msg) {
    1737     aimbs_putraw(&fr->data, msg, strlen(msg));
    1738     aimbs_put8(&fr->data, 0x00);
    1739   }
    1740  
    1741   /* Unknown */
    1742   aimbs_put16(&fr->data, 0x0000);
    1743  
    1744   aim_tx_enqueue(sess, fr);
    1745  
    1746   return 0;
     1740        aim_conn_t *conn;
     1741        aim_frame_t *fr;
     1742        aim_snacid_t snacid;
     1743
     1744        if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn)
     1745                return -EINVAL;
     1746
     1747        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2)))
     1748                return -ENOMEM;
     1749
     1750        snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, NULL, 0);
     1751        aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, snacid);
     1752
     1753        /* Screen name */
     1754        aimbs_put8(&fr->data, strlen(sn));
     1755        aimbs_putraw(&fr->data, sn, strlen(sn));
     1756
     1757        /* Message (null terminated) */
     1758        aimbs_put16(&fr->data, msg ? strlen(msg) : 0);
     1759        if (msg) {
     1760                aimbs_putraw(&fr->data, msg, strlen(msg));
     1761                aimbs_put8(&fr->data, 0x00);
     1762        }
     1763
     1764        /* Unknown */
     1765        aimbs_put16(&fr->data, 0x0000);
     1766
     1767        aim_tx_enqueue(sess, fr);
     1768
     1769        return 0;
    17471770}
    17481771
     
    17521775static int receiveauthrequest(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    17531776{
    1754   int ret = 0;
    1755   aim_rxcallback_t userfunc;
    1756   fu16_t tmp;
    1757   char *sn, *msg;
    1758  
    1759   /* Read screen name */
    1760   if ((tmp = aimbs_get8(bs)))
    1761     sn = aimbs_getstr(bs, tmp);
    1762   else
    1763     sn = NULL;
    1764  
    1765   /* Read message (null terminated) */
    1766   if ((tmp = aimbs_get16(bs)))
    1767     msg = aimbs_getstr(bs, tmp);
    1768   else
    1769     msg = NULL;
    1770  
    1771   /* Unknown */
    1772   tmp = aimbs_get16(bs);
    1773  
    1774   if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1775     ret = userfunc(sess, rx, sn, msg);
    1776  
    1777   free(sn);
    1778   free(msg);
    1779  
    1780   return ret;
     1777        int ret = 0;
     1778        aim_rxcallback_t userfunc;
     1779        fu16_t tmp;
     1780        char *sn, *msg;
     1781
     1782        /* Read screen name */
     1783        if ((tmp = aimbs_get8(bs)))
     1784                sn = aimbs_getstr(bs, tmp);
     1785        else
     1786                sn = NULL;
     1787
     1788        /* Read message (null terminated) */
     1789        if ((tmp = aimbs_get16(bs)))
     1790                msg = aimbs_getstr(bs, tmp);
     1791        else
     1792                msg = NULL;
     1793
     1794        /* Unknown */
     1795        tmp = aimbs_get16(bs);
     1796
     1797        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
     1798                ret = userfunc(sess, rx, sn, msg);
     1799
     1800        free(sn);
     1801        free(msg);
     1802
     1803        return ret;
    17811804}
    17821805
     
    17931816faim_export int aim_ssi_sendauthreply(aim_session_t *sess, char *sn, fu8_t reply, char *msg)
    17941817{
    1795   aim_conn_t *conn;
    1796   aim_frame_t *fr;
    1797   aim_snacid_t snacid;
    1798  
    1799   if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn)
    1800     return -EINVAL;
    1801  
    1802   if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 1+strlen(sn) + 1 + 2+(msg ? strlen(msg)+1 : 0) + 2)))
    1803     return -ENOMEM;
    1804  
    1805   snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, NULL, 0);
    1806   aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, snacid);
    1807  
    1808   /* Screen name */
    1809   aimbs_put8(&fr->data, strlen(sn));
    1810   aimbs_putraw(&fr->data, sn, strlen(sn));
    1811  
    1812   /* Grant or deny */
    1813   aimbs_put8(&fr->data, reply);
    1814  
    1815   /* Message (null terminated) */
    1816   aimbs_put16(&fr->data, msg ? (strlen(msg)+1) : 0);
    1817   if (msg) {
    1818     aimbs_putraw(&fr->data, msg, strlen(msg));
    1819     aimbs_put8(&fr->data, 0x00);
    1820   }
    1821  
    1822   /* Unknown */
    1823   aimbs_put16(&fr->data, 0x0000);
    1824  
    1825   aim_tx_enqueue(sess, fr);
    1826  
    1827   return 0;
     1818        aim_conn_t *conn;
     1819        aim_frame_t *fr;
     1820        aim_snacid_t snacid;
     1821
     1822        if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn)
     1823                return -EINVAL;
     1824
     1825        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 1+strlen(sn) + 1 + 2+(msg ? strlen(msg)+1 : 0) + 2)))
     1826                return -ENOMEM;
     1827
     1828        snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, NULL, 0);
     1829        aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, snacid);
     1830
     1831        /* Screen name */
     1832        aimbs_put8(&fr->data, strlen(sn));
     1833        aimbs_putraw(&fr->data, sn, strlen(sn));
     1834
     1835        /* Grant or deny */
     1836        aimbs_put8(&fr->data, reply);
     1837
     1838        /* Message (null terminated) */
     1839        aimbs_put16(&fr->data, msg ? (strlen(msg)+1) : 0);
     1840        if (msg) {
     1841                aimbs_putraw(&fr->data, msg, strlen(msg));
     1842                aimbs_put8(&fr->data, 0x00);
     1843        }
     1844
     1845        /* Unknown */
     1846        aimbs_put16(&fr->data, 0x0000);
     1847
     1848        aim_tx_enqueue(sess, fr);
     1849
     1850        return 0;
    18281851}
    18291852
     
    18351858static int receiveauthreply(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    18361859{
    1837   int ret = 0;
    1838   aim_rxcallback_t userfunc;
    1839   fu16_t tmp;
    1840   fu8_t reply;
    1841   char *sn, *msg;
    1842  
    1843   /* Read screen name */
    1844   if ((tmp = aimbs_get8(bs)))
    1845     sn = aimbs_getstr(bs, tmp);
    1846   else
    1847     sn = NULL;
    1848  
    1849   /* Read reply */
    1850   reply = aimbs_get8(bs);
    1851  
    1852   /* Read message (null terminated) */
    1853   if ((tmp = aimbs_get16(bs)))
    1854     msg = aimbs_getstr(bs, tmp);
    1855   else
    1856     msg = NULL;
    1857  
    1858   /* Unknown */
    1859   tmp = aimbs_get16(bs);
    1860  
    1861   if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1862     ret = userfunc(sess, rx, sn, reply, msg);
    1863  
    1864   free(sn);
    1865   free(msg);
    1866  
    1867   return ret;
     1860        int ret = 0;
     1861        aim_rxcallback_t userfunc;
     1862        fu16_t tmp;
     1863        fu8_t reply;
     1864        char *sn, *msg;
     1865
     1866        /* Read screen name */
     1867        if ((tmp = aimbs_get8(bs)))
     1868                sn = aimbs_getstr(bs, tmp);
     1869        else
     1870                sn = NULL;
     1871
     1872        /* Read reply */
     1873        reply = aimbs_get8(bs);
     1874
     1875        /* Read message (null terminated) */
     1876        if ((tmp = aimbs_get16(bs)))
     1877                msg = aimbs_getstr(bs, tmp);
     1878        else
     1879                msg = NULL;
     1880
     1881        /* Unknown */
     1882        tmp = aimbs_get16(bs);
     1883
     1884        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
     1885                ret = userfunc(sess, rx, sn, reply, msg);
     1886
     1887        free(sn);
     1888        free(msg);
     1889
     1890        return ret;
    18681891}
    18691892
     
    18731896static int receiveadded(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    18741897{
    1875   int ret = 0;
    1876   aim_rxcallback_t userfunc;
    1877   fu16_t tmp;
    1878   char *sn;
    1879  
    1880   /* Read screen name */
    1881   if ((tmp = aimbs_get8(bs))) {
    1882     sn = aimbs_getstr(bs, tmp);
    1883   } else {
    1884     sn = NULL;
    1885   }
    1886  
    1887   if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
    1888     ret = userfunc(sess, rx, sn);
    1889   }
    1890  
    1891   free(sn);
    1892   return(ret);
     1898        int ret = 0;
     1899        aim_rxcallback_t userfunc;
     1900        fu16_t tmp;
     1901        char *sn;
     1902
     1903        /* Read screen name */
     1904        if ((tmp = aimbs_get8(bs)))
     1905                sn = aimbs_getstr(bs, tmp);
     1906        else
     1907                sn = NULL;
     1908
     1909        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
     1910                ret = userfunc(sess, rx, sn);
     1911
     1912        free(sn);
     1913
     1914        return ret;
    18931915}
    18941916
    18951917static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    18961918{
    1897   if (snac->subtype == AIM_CB_SSI_RIGHTSINFO) {
    1898     return parserights(sess, mod, rx, snac, bs);
    1899   } else if (snac->subtype == AIM_CB_SSI_LIST) {
    1900     return parsedata(sess, mod, rx, snac, bs);
    1901   } else if (snac->subtype == AIM_CB_SSI_ADD) {
    1902     return parseadd(sess, mod, rx, snac, bs);
    1903   } else if (snac->subtype == AIM_CB_SSI_MOD) {
    1904     return parsemod(sess, mod, rx, snac, bs);
    1905   } else if (snac->subtype == AIM_CB_SSI_DEL) {
    1906     return parsedel(sess, mod, rx, snac, bs);
    1907   } else if (snac->subtype == AIM_CB_SSI_SRVACK) {
    1908     return parseack(sess, mod, rx, snac, bs);
    1909   } else if (snac->subtype == AIM_CB_SSI_NOLIST) {
    1910     return parsedataunchanged(sess, mod, rx, snac, bs);
    1911   } else if (snac->subtype == AIM_CB_SSI_RECVAUTH) {
    1912     return receiveauthgrant(sess, mod, rx, snac, bs);
    1913   } else if (snac->subtype == AIM_CB_SSI_RECVAUTHREQ) {
    1914     return receiveauthrequest(sess, mod, rx, snac, bs);
    1915   } else if (snac->subtype == AIM_CB_SSI_RECVAUTHREP) {
    1916     return receiveauthreply(sess, mod, rx, snac, bs);
    1917   } else if (snac->subtype == AIM_CB_SSI_ADDED) {
    1918     return receiveadded(sess, mod, rx, snac, bs);
    1919   }
    1920   return(0);
     1919
     1920        if (snac->subtype == AIM_CB_SSI_RIGHTSINFO)
     1921                return parserights(sess, mod, rx, snac, bs);
     1922        else if (snac->subtype == AIM_CB_SSI_LIST)
     1923                return parsedata(sess, mod, rx, snac, bs);
     1924        else if (snac->subtype == AIM_CB_SSI_ADD)
     1925                return parseadd(sess, mod, rx, snac, bs);
     1926        else if (snac->subtype == AIM_CB_SSI_MOD)
     1927                return parsemod(sess, mod, rx, snac, bs);
     1928        else if (snac->subtype == AIM_CB_SSI_DEL)
     1929                return parsedel(sess, mod, rx, snac, bs);
     1930        else if (snac->subtype == AIM_CB_SSI_SRVACK)
     1931                return parseack(sess, mod, rx, snac, bs);
     1932        else if (snac->subtype == AIM_CB_SSI_NOLIST)
     1933                return parsedataunchanged(sess, mod, rx, snac, bs);
     1934        else if (snac->subtype == AIM_CB_SSI_RECVAUTH)
     1935                return receiveauthgrant(sess, mod, rx, snac, bs);
     1936        else if (snac->subtype == AIM_CB_SSI_RECVAUTHREQ)
     1937                return receiveauthrequest(sess, mod, rx, snac, bs);
     1938        else if (snac->subtype == AIM_CB_SSI_RECVAUTHREP)
     1939                return receiveauthreply(sess, mod, rx, snac, bs);
     1940        else if (snac->subtype == AIM_CB_SSI_ADDED)
     1941                return receiveadded(sess, mod, rx, snac, bs);
     1942
     1943        return 0;
    19211944}
    19221945
    19231946static void ssi_shutdown(aim_session_t *sess, aim_module_t *mod)
    19241947{
    1925   aim_ssi_freelist(sess);
    1926   return;
     1948        aim_ssi_freelist(sess);
    19271949}
    19281950
    19291951faim_internal int ssi_modfirst(aim_session_t *sess, aim_module_t *mod)
    19301952{
    1931  
    1932   mod->family = AIM_CB_FAM_SSI;
    1933   mod->version = 0x0004;
    1934   mod->toolid = 0x0110;
    1935   mod->toolversion = 0x0629;
    1936   mod->flags = 0;
    1937   strncpy(mod->name, "ssi", sizeof(mod->name));
    1938   mod->snachandler = snachandler;
    1939   mod->shutdown = ssi_shutdown;
    1940  
    1941   return 0;
    1942 }
     1953
     1954        mod->family = AIM_CB_FAM_SSI;
     1955        mod->version = 0x0004;
     1956        mod->toolid = 0x0110;
     1957        mod->toolversion = 0x0629;
     1958        mod->flags = 0;
     1959        strncpy(mod->name, "ssi", sizeof(mod->name));
     1960        mod->snachandler = snachandler;
     1961        mod->shutdown = ssi_shutdown;
     1962
     1963        return 0;
     1964}
  • libfaim/tlv.c

    re374dee rcf02dd6  
    33#include <aim.h>
    44
    5 static aim_tlv_t *createtlv(void)
    6 {
    7         aim_tlv_t *newtlv;
    8 
    9         if (!(newtlv = (aim_tlv_t *)malloc(sizeof(aim_tlv_t))))
     5static aim_tlv_t *createtlv(fu16_t type, fu16_t length, fu8_t *value)
     6{
     7        aim_tlv_t *ret;
     8
     9        if (!(ret = (aim_tlv_t *)malloc(sizeof(aim_tlv_t))))
    1010                return NULL;
    11         memset(newtlv, 0, sizeof(aim_tlv_t));
    12 
    13         return newtlv;
     11        ret->type = type;
     12        ret->length = length;
     13        ret->value = value;
     14
     15        return ret;
    1416}
    1517
     
    2830
    2931/**
    30  * aim_readtlvchain - Read a TLV chain from a buffer.
    31  * @param bs Input bstream
     32 * Read a TLV chain from a buffer.
    3233 *
    3334 * Reads and parses a series of TLV patterns from a data buffer; the
    3435 * returned structure is manipulatable with the rest of the TLV
    35  * routines.  When done with a TLV chain, aim_freetlvchain() should
     36 * routines.  When done with a TLV chain, aim_tlvlist_free() should
    3637 * be called to free the dynamic substructures.
    3738 *
     
    4243 * in libfaim.
    4344 *
    44  */
    45 faim_internal aim_tlvlist_t *aim_readtlvchain(aim_bstream_t *bs)
     45 * @param bs Input bstream
     46 */
     47faim_internal aim_tlvlist_t *aim_tlvlist_read(aim_bstream_t *bs)
    4648{
    4749        aim_tlvlist_t *list = NULL, *cur;
     
    7173
    7274                        if (length > aim_bstream_empty(bs)) {
    73                                 aim_freetlvchain(&list);
     75                                aim_tlvlist_free(&list);
    7476                                return NULL;
    7577                        }
     
    7779                        cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
    7880                        if (!cur) {
    79                                 aim_freetlvchain(&list);
     81                                aim_tlvlist_free(&list);
    8082                                return NULL;
    8183                        }
     
    8385                        memset(cur, 0, sizeof(aim_tlvlist_t));
    8486
    85                         cur->tlv = createtlv();
     87                        cur->tlv = createtlv(type, length, NULL);
    8688                        if (!cur->tlv) {
    8789                                free(cur);
    88                                 aim_freetlvchain(&list);
     90                                aim_tlvlist_free(&list);
    8991                                return NULL;
    9092                        }
    91                         cur->tlv->type = type;
    92                         if ((cur->tlv->length = length)) {
    93                                cur->tlv->value = aimbs_getraw(bs, length);     
    94                                if (!cur->tlv->value) {
    95                                        freetlv(&cur->tlv);
    96                                        free(cur);
    97                                        aim_freetlvchain(&list);
    98                                        return NULL;
    99                                }
     93                        if (cur->tlv->length > 0) {
     94                                cur->tlv->value = aimbs_getraw(bs, length);     
     95                                if (!cur->tlv->value) {
     96                                        freetlv(&cur->tlv);
     97                                        free(cur);
     98                                        aim_tlvlist_free(&list);
     99                                        return NULL;
     100                                }
    100101                        }
    101102
     
    109110
    110111/**
    111  * aim_readtlvchain_num - Read a TLV chain from a buffer.
     112 * Read a TLV chain from a buffer.
     113 *
     114 * Reads and parses a series of TLV patterns from a data buffer; the
     115 * returned structure is manipulatable with the rest of the TLV
     116 * routines.  When done with a TLV chain, aim_tlvlist_free() should
     117 * be called to free the dynamic substructures.
     118 *
     119 * XXX There should be a flag setable here to have the tlvlist contain
     120 * bstream references, so that at least the ->value portion of each
     121 * element doesn't need to be malloc/memcpy'd.  This could prove to be
     122 * just as effecient as the in-place TLV parsing used in a couple places
     123 * in libfaim.
     124 *
    112125 * @param bs Input bstream
    113126 * @param num The max number of TLVs that will be read, or -1 if unlimited. 
     
    115128 *        but the chain is not at the end of the SNAC, and the chain is
    116129 *        preceeded by the number of TLVs.  So you can limit that with this.
     130 */
     131faim_internal aim_tlvlist_t *aim_tlvlist_readnum(aim_bstream_t *bs, fu16_t num)
     132{
     133        aim_tlvlist_t *list = NULL, *cur;
     134
     135        while ((aim_bstream_empty(bs) > 0) && (num != 0)) {
     136                fu16_t type, length;
     137
     138                type = aimbs_get16(bs);
     139                length = aimbs_get16(bs);
     140
     141                if (length > aim_bstream_empty(bs)) {
     142                        aim_tlvlist_free(&list);
     143                        return NULL;
     144                }
     145
     146                cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
     147                if (!cur) {
     148                        aim_tlvlist_free(&list);
     149                        return NULL;
     150                }
     151
     152                memset(cur, 0, sizeof(aim_tlvlist_t));
     153
     154                cur->tlv = createtlv(type, length, NULL);
     155                if (!cur->tlv) {
     156                        free(cur);
     157                        aim_tlvlist_free(&list);
     158                        return NULL;
     159                }
     160                if (cur->tlv->length > 0) {
     161                        cur->tlv->value = aimbs_getraw(bs, length);
     162                        if (!cur->tlv->value) {
     163                                freetlv(&cur->tlv);
     164                                free(cur);
     165                                aim_tlvlist_free(&list);
     166                                return NULL;
     167                        }
     168                }
     169
     170                if (num > 0)
     171                        num--;
     172                cur->next = list;
     173                list = cur;
     174        }
     175
     176        return list;
     177}
     178
     179/**
     180 * Read a TLV chain from a buffer.
    117181 *
    118182 * Reads and parses a series of TLV patterns from a data buffer; the
    119183 * returned structure is manipulatable with the rest of the TLV
    120  * routines.  When done with a TLV chain, aim_freetlvchain() should
     184 * routines.  When done with a TLV chain, aim_tlvlist_free() should
    121185 * be called to free the dynamic substructures.
    122186 *
     
    127191 * in libfaim.
    128192 *
    129  */
    130 faim_internal aim_tlvlist_t *aim_readtlvchain_num(aim_bstream_t *bs, fu16_t num)
    131 {
    132         aim_tlvlist_t *list = NULL, *cur;
    133 
    134         while ((aim_bstream_empty(bs) > 0) && (num != 0)) {
    135                 fu16_t type, length;
    136 
    137                 type = aimbs_get16(bs);
    138                 length = aimbs_get16(bs);
    139 
    140                 if (length > aim_bstream_empty(bs)) {
    141                         aim_freetlvchain(&list);
    142                         return NULL;
    143                 }
    144 
    145                 cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
    146                 if (!cur) {
    147                         aim_freetlvchain(&list);
    148                         return NULL;
    149                 }
    150 
    151                 memset(cur, 0, sizeof(aim_tlvlist_t));
    152 
    153                 cur->tlv = createtlv();
    154                 if (!cur->tlv) {
    155                         free(cur);
    156                         aim_freetlvchain(&list);
    157                         return NULL;
    158                 }
    159                 cur->tlv->type = type;
    160                 if ((cur->tlv->length = length)) {
    161                        cur->tlv->value = aimbs_getraw(bs, length);
    162                        if (!cur->tlv->value) {
    163                                freetlv(&cur->tlv);
    164                                free(cur);
    165                                aim_freetlvchain(&list);
    166                                return NULL;
    167                        }
    168                 }
    169 
    170                 num--;
    171                 cur->next = list;
    172                 list = cur;
    173         }
    174 
    175         return list;
    176 }
    177 
    178 /**
    179  * aim_readtlvchain_len - Read a TLV chain from a buffer.
    180193 * @param bs Input bstream
    181194 * @param len The max length in bytes that will be read.
     
    183196 *        but the chain is not at the end of the SNAC, and the chain is
    184197 *        preceeded by the length of the TLVs.  So you can limit that with this.
    185  *
    186  * Reads and parses a series of TLV patterns from a data buffer; the
    187  * returned structure is manipulatable with the rest of the TLV
    188  * routines.  When done with a TLV chain, aim_freetlvchain() should
    189  * be called to free the dynamic substructures.
    190  *
    191  * XXX There should be a flag setable here to have the tlvlist contain
    192  * bstream references, so that at least the ->value portion of each
    193  * element doesn't need to be malloc/memcpy'd.  This could prove to be
    194  * just as effecient as the in-place TLV parsing used in a couple places
    195  * in libfaim.
    196  *
    197  */
    198 faim_internal aim_tlvlist_t *aim_readtlvchain_len(aim_bstream_t *bs, fu16_t len)
     198 */
     199faim_internal aim_tlvlist_t *aim_tlvlist_readlen(aim_bstream_t *bs, fu16_t len)
    199200{
    200201        aim_tlvlist_t *list = NULL, *cur;
     
    207208
    208209                if (length > aim_bstream_empty(bs)) {
    209                         aim_freetlvchain(&list);
     210                        aim_tlvlist_free(&list);
    210211                        return NULL;
    211212                }
     
    213214                cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
    214215                if (!cur) {
    215                         aim_freetlvchain(&list);
     216                        aim_tlvlist_free(&list);
    216217                        return NULL;
    217218                }
     
    219220                memset(cur, 0, sizeof(aim_tlvlist_t));
    220221
    221                 cur->tlv = createtlv();
     222                cur->tlv = createtlv(type, length, NULL);
    222223                if (!cur->tlv) {
    223224                        free(cur);
    224                         aim_freetlvchain(&list);
     225                        aim_tlvlist_free(&list);
    225226                        return NULL;
    226227                }
    227                 cur->tlv->type = type;
    228                 if ((cur->tlv->length = length)) {
    229                        cur->tlv->value = aimbs_getraw(bs, length);
    230                        if (!cur->tlv->value) {
    231                                freetlv(&cur->tlv);
    232                                free(cur);
    233                                aim_freetlvchain(&list);
    234                                return NULL;
    235                        }
    236                 }
    237 
    238                 len -= aim_sizetlvchain(&cur);
     228                if (cur->tlv->length > 0) {
     229                        cur->tlv->value = aimbs_getraw(bs, length);
     230                        if (!cur->tlv->value) {
     231                                freetlv(&cur->tlv);
     232                                free(cur);
     233                                aim_tlvlist_free(&list);
     234                                return NULL;
     235                        }
     236                }
     237
     238                len -= aim_tlvlist_size(&cur);
    239239                cur->next = list;
    240240                list = cur;
     
    245245
    246246/**
    247  * aim_tlvlist_copy - Duplicate a TLV chain.
    248  * @param orig
    249  *
     247 * Duplicate a TLV chain.
    250248 * This is pretty pelf exslanatory.
    251249 *
     250 * @param orig The TLV chain you want to make a copy of.
     251 * @return A newly allocated TLV chain.
    252252 */
    253253faim_internal aim_tlvlist_t *aim_tlvlist_copy(aim_tlvlist_t *orig)
     
    256256
    257257        while (orig) {
    258                 aim_addtlvtochain_raw(&new, orig->tlv->type, orig->tlv->length, orig->tlv->value);
     258                aim_tlvlist_add_raw(&new, orig->tlv->type, orig->tlv->length, orig->tlv->value);
    259259                orig = orig->next;
    260260        }
     
    275275        aim_bstream_t bs1, bs2;
    276276
    277         if (aim_sizetlvchain(&one) != aim_sizetlvchain(&two))
     277        if (aim_tlvlist_size(&one) != aim_tlvlist_size(&two))
    278278                return 1;
    279279
    280         aim_bstream_init(&bs1, ((fu8_t *)malloc(aim_sizetlvchain(&one)*sizeof(fu8_t))), aim_sizetlvchain(&one));
    281         aim_bstream_init(&bs2, ((fu8_t *)malloc(aim_sizetlvchain(&two)*sizeof(fu8_t))), aim_sizetlvchain(&two));
    282 
    283         aim_writetlvchain(&bs1, &one);
    284         aim_writetlvchain(&bs2, &two);
     280        aim_bstream_init(&bs1, ((fu8_t *)malloc(aim_tlvlist_size(&one)*sizeof(fu8_t))), aim_tlvlist_size(&one));
     281        aim_bstream_init(&bs2, ((fu8_t *)malloc(aim_tlvlist_size(&two)*sizeof(fu8_t))), aim_tlvlist_size(&two));
     282
     283        aim_tlvlist_write(&bs1, &one);
     284        aim_tlvlist_write(&bs2, &two);
    285285
    286286        if (memcmp(bs1.data, bs2.data, bs1.len)) {
     
    297297
    298298/**
    299  * aim_freetlvchain - Free a TLV chain structure
     299 * Free a TLV chain structure
    300300 * @list: Chain to be freed
    301301 *
     
    305305 *
    306306 */
    307 faim_internal void aim_freetlvchain(aim_tlvlist_t **list)
     307faim_internal void aim_tlvlist_free(aim_tlvlist_t **list)
    308308{
    309309        aim_tlvlist_t *cur;
     
    328328
    329329/**
    330  * aim_counttlvchain - Count the number of TLVs in a chain
    331  * @list: Chain to be counted
    332  *
    333  * Returns the number of TLVs stored in the passed chain.
    334  *
    335  */
    336 faim_internal int aim_counttlvchain(aim_tlvlist_t **list)
     330 * Count the number of TLVs in a chain.
     331 *
     332 * @param list Chain to be counted.
     333 * @return The number of TLVs stored in the passed chain.
     334 */
     335faim_internal int aim_tlvlist_count(aim_tlvlist_t **list)
    337336{
    338337        aim_tlvlist_t *cur;
     
    349348
    350349/**
    351  * aim_sizetlvchain - Count the number of bytes in a TLV chain
    352  * @list: Chain to be sized
    353  *
    354  * Returns the number of bytes that would be needed to
    355  * write the passed TLV chain to a data buffer.
    356  *
    357  */
    358 faim_internal int aim_sizetlvchain(aim_tlvlist_t **list)
     350 * Count the number of bytes in a TLV chain.
     351 *
     352 * @param list Chain to be sized
     353 * @return The number of bytes that would be needed to
     354 *         write the passed TLV chain to a data buffer.
     355 */
     356faim_internal int aim_tlvlist_size(aim_tlvlist_t **list)
    359357{
    360358        aim_tlvlist_t *cur;
     
    371369
    372370/**
    373  * aim_addtlvtochain_raw - Add a string to a TLV chain
    374  * @list: Desination chain (%NULL pointer if empty)
    375  * @t: TLV type
    376  * @l: Length of string to add (not including %NULL)
    377  * @v: String to add
    378  *
    379371 * Adds the passed string as a TLV element of the passed type
    380372 * to the TLV chain.
    381373 *
    382  */
    383 faim_internal int aim_addtlvtochain_raw(aim_tlvlist_t **list, const fu16_t t, const fu16_t l, const fu8_t *v)
     374 * @param list Desination chain (%NULL pointer if empty).
     375 * @param type TLV type.
     376 * @length Length of string to add (not including %NULL).
     377 * @value String to add.
     378 * @retun The size of the value added.
     379 */
     380faim_internal int aim_tlvlist_add_raw(aim_tlvlist_t **list, const fu16_t type, const fu16_t length, const fu8_t *value)
    384381{
    385382        aim_tlvlist_t *newtlv, *cur;
    386383
    387         if (!list)
     384        if (list == NULL)
    388385                return 0;
    389386
     
    392389        memset(newtlv, 0x00, sizeof(aim_tlvlist_t));
    393390
    394         if (!(newtlv->tlv = createtlv())) {
     391        if (!(newtlv->tlv = createtlv(type, length, NULL))) {
    395392                free(newtlv);
    396393                return 0;
    397394        }
    398         newtlv->tlv->type = t;
    399         if ((newtlv->tlv->length = l)) {
     395        if (newtlv->tlv->length > 0) {
    400396                newtlv->tlv->value = (fu8_t *)malloc(newtlv->tlv->length);
    401                 memcpy(newtlv->tlv->value, v, newtlv->tlv->length);
     397                memcpy(newtlv->tlv->value, value, newtlv->tlv->length);
    402398        }
    403399
     
    414410
    415411/**
    416  * aim_addtlvtochain8 - Add a 8bit integer to a TLV chain
    417  * @list: Destination chain
    418  * @type: TLV type to add
    419  * @val: Value to add
    420  *
    421  * Adds a one-byte unsigned integer to a TLV chain.
    422  *
    423  */
    424 faim_internal int aim_addtlvtochain8(aim_tlvlist_t **list, const fu16_t t, const fu8_t v)
     412 * Add a one byte integer to a TLV chain.
     413 *
     414 * @param list Destination chain.
     415 * @param type TLV type to add.
     416 * @param value Value to add.
     417 * @retun The size of the value added.
     418 */
     419faim_internal int aim_tlvlist_add_8(aim_tlvlist_t **list, const fu16_t type, const fu8_t value)
    425420{
    426421        fu8_t v8[1];
    427422
    428         aimutil_put8(v8, v);
    429 
    430         return aim_addtlvtochain_raw(list, t, 1, v8);
    431 }
    432 
    433 /**
    434  * aim_addtlvtochain16 - Add a 16bit integer to a TLV chain
    435  * @list: Destination chain
    436  * @t: TLV type to add
    437  * @v: Value to add
    438  *
    439  * Adds a two-byte unsigned integer to a TLV chain.
    440  *
    441  */
    442 faim_internal int aim_addtlvtochain16(aim_tlvlist_t **list, const fu16_t t, const fu16_t v)
     423        aimutil_put8(v8, value);
     424
     425        return aim_tlvlist_add_raw(list, type, 1, v8);
     426}
     427
     428/**
     429 * Add a two byte integer to a TLV chain.
     430 *
     431 * @param list Destination chain.
     432 * @param type TLV type to add.
     433 * @param value Value to add.
     434 * @retun The size of the value added.
     435 */
     436faim_internal int aim_tlvlist_add_16(aim_tlvlist_t **list, const fu16_t type, const fu16_t value)
    443437{
    444438        fu8_t v16[2];
    445439
    446         aimutil_put16(v16, v);
    447 
    448         return aim_addtlvtochain_raw(list, t, 2, v16);
    449 }
    450 
    451 /**
    452  * aim_addtlvtochain32 - Add a 32bit integer to a TLV chain
    453  * @list: Destination chain
    454  * @type: TLV type to add
    455  * @val: Value to add
    456  *
    457  * Adds a four-byte unsigned integer to a TLV chain.
    458  *
    459  */
    460 faim_internal int aim_addtlvtochain32(aim_tlvlist_t **list, const fu16_t t, const fu32_t v)
     440        aimutil_put16(v16, value);
     441
     442        return aim_tlvlist_add_raw(list, type, 2, v16);
     443}
     444
     445/**
     446 * Add a four byte integer to a TLV chain.
     447 *
     448 * @param list Destination chain.
     449 * @param type TLV type to add.
     450 * @param value Value to add.
     451 * @retun The size of the value added.
     452 */
     453faim_internal int aim_tlvlist_add_32(aim_tlvlist_t **list, const fu16_t type, const fu32_t value)
    461454{
    462455        fu8_t v32[4];
    463456
    464         aimutil_put32(v32, v);
    465 
    466         return aim_addtlvtochain_raw(list, t, 4, v32);
    467 }
    468 
    469 /**
    470  * aim_addtlvtochain_caps - Add a capability block to a TLV chain
    471  * @list: Destination chain
    472  * @type: TLV type to add
    473  * @caps: Bitfield of capability flags to send
    474  *
     457        aimutil_put32(v32, value);
     458
     459        return aim_tlvlist_add_raw(list, type, 4, v32);
     460}
     461
     462/**
    475463 * Adds a block of capability blocks to a TLV chain. The bitfield
    476464 * passed in should be a bitwise %OR of any of the %AIM_CAPS constants:
    477465 *
    478  *      %AIM_CAPS_BUDDYICON   Supports Buddy Icons
    479  *
    480  *      %AIM_CAPS_VOICE       Supports Voice Chat
    481  *
    482  *      %AIM_CAPS_IMIMAGE     Supports DirectIM/IMImage
    483  *
    484  *      %AIM_CAPS_CHAT        Supports Chat
    485  *
    486  *      %AIM_CAPS_GETFILE     Supports Get File functions
    487  *
    488  *      %AIM_CAPS_SENDFILE    Supports Send File functions
    489  *
    490  */
    491 faim_internal int aim_addtlvtochain_caps(aim_tlvlist_t **list, const fu16_t t, const fu32_t caps)
     466 *     %AIM_CAPS_BUDDYICON   Supports Buddy Icons
     467 *     %AIM_CAPS_VOICE       Supports Voice Chat
     468 *     %AIM_CAPS_IMIMAGE     Supports DirectIM/IMImage
     469 *     %AIM_CAPS_CHAT        Supports Chat
     470 *     %AIM_CAPS_GETFILE     Supports Get File functions
     471 *     %AIM_CAPS_SENDFILE    Supports Send File functions
     472 *
     473 * @param list Destination chain
     474 * @param type TLV type to add
     475 * @param caps Bitfield of capability flags to send
     476 * @retun The size of the value added.
     477 */
     478faim_internal int aim_tlvlist_add_caps(aim_tlvlist_t **list, const fu16_t type, const fu32_t caps)
    492479{
    493480        fu8_t buf[16*16]; /* XXX icky fixed length buffer */
     
    501488        aim_putcap(&bs, caps);
    502489
    503         return aim_addtlvtochain_raw(list, t, aim_bstream_curpos(&bs), buf);
    504 }
    505 
    506 faim_internal int aim_addtlvtochain_userinfo(aim_tlvlist_t **list, fu16_t type, aim_userinfo_t *ui)
     490        return aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf);
     491}
     492
     493/**
     494 * Adds the given userinfo struct to a TLV chain.
     495 *
     496 * @param list Destination chain.
     497 * @param type TLV type to add.
     498 * @retun The size of the value added.
     499 */
     500faim_internal int aim_tlvlist_add_userinfo(aim_tlvlist_t **list, fu16_t type, aim_userinfo_t *userinfo)
    507501{
    508502        fu8_t buf[1024]; /* bleh */
     
    511505        aim_bstream_init(&bs, buf, sizeof(buf));
    512506
    513         aim_putuserinfo(&bs, ui);
    514 
    515         return aim_addtlvtochain_raw(list, type, aim_bstream_curpos(&bs), buf);
    516 }
    517 
    518 /**
    519  * aim_addtlvtochain_noval - Add a blank TLV to a TLV chain
    520  * @list: Destination chain
    521  * @type: TLV type to add
    522  *
     507        aim_putuserinfo(&bs, userinfo);
     508
     509        return aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf);
     510}
     511
     512/**
    523513 * Adds a TLV with a zero length to a TLV chain.
    524514 *
    525  */
    526 faim_internal int aim_addtlvtochain_noval(aim_tlvlist_t **list, const fu16_t t)
    527 {
    528         return aim_addtlvtochain_raw(list, t, 0, NULL);
     515 * @param list Destination chain.
     516 * @param type TLV type to add.
     517 * @retun The size of the value added.
     518 */
     519faim_internal int aim_tlvlist_add_noval(aim_tlvlist_t **list, const fu16_t type)
     520{
     521        return aim_tlvlist_add_raw(list, type, 0, NULL);
    529522}
    530523
     
    539532 *
    540533 */
    541 faim_internal int aim_addtlvtochain_frozentlvlist(aim_tlvlist_t **list, fu16_t type, aim_tlvlist_t **tl)
     534faim_internal int aim_tlvlist_add_frozentlvlist(aim_tlvlist_t **list, fu16_t type, aim_tlvlist_t **tl)
    542535{
    543536        fu8_t *buf;
     
    545538        aim_bstream_t bs;
    546539
    547         buflen = aim_sizetlvchain(tl);
     540        buflen = aim_tlvlist_size(tl);
    548541
    549542        if (buflen <= 0)
     
    555548        aim_bstream_init(&bs, buf, buflen);
    556549
    557         aim_writetlvchain(&bs, tl);
    558 
    559         aim_addtlvtochain_raw(list, type, aim_bstream_curpos(&bs), buf);
     550        aim_tlvlist_write(&bs, tl);
     551
     552        aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf);
    560553
    561554        free(buf);
     
    565558
    566559/**
    567  * aim_writetlvchain - Write a TLV chain into a data buffer.
     560 * Substitute a TLV of a given type with a new TLV of the same type.  If
     561 * you attempt to replace a TLV that does not exist, this function will
     562 * just add a new TLV as if you called aim_tlvlist_add_raw().
     563 *
     564 * @param list Desination chain (%NULL pointer if empty).
     565 * @param type TLV type.
     566 * @param length Length of string to add (not including %NULL).
     567 * @param value String to add.
     568 * @return The length of the TLV.
     569 */
     570faim_internal int aim_tlvlist_replace_raw(aim_tlvlist_t **list, const fu16_t type, const fu16_t length, const fu8_t *value)
     571{
     572        aim_tlvlist_t *cur;
     573
     574        if (list == NULL)
     575                return 0;
     576
     577        for (cur = *list; ((cur != NULL) && (cur->tlv->type != type)); cur = cur->next);
     578        if (cur == NULL)
     579                return aim_tlvlist_add_raw(list, type, length, value);
     580
     581        free(cur->tlv->value);
     582        cur->tlv->length = length;
     583        if (cur->tlv->length > 0) {
     584                cur->tlv->value = (fu8_t *)malloc(cur->tlv->length);
     585                memcpy(cur->tlv->value, value, cur->tlv->length);
     586        } else
     587                cur->tlv->value = NULL;
     588
     589        return cur->tlv->length;
     590}
     591
     592/**
     593 * Substitute a TLV of a given type with a new TLV of the same type.  If
     594 * you attempt to replace a TLV that does not exist, this function will
     595 * just add a new TLV as if you called aim_tlvlist_add_raw().
     596 *
     597 * @param list Desination chain (%NULL pointer if empty).
     598 * @param type TLV type.
     599 * @return The length of the TLV.
     600 */
     601faim_internal int aim_tlvlist_replace_noval(aim_tlvlist_t **list, const fu16_t type)
     602{
     603        return aim_tlvlist_replace_raw(list, type, 0, NULL);
     604}
     605
     606/**
     607 * Substitute a TLV of a given type with a new TLV of the same type.  If
     608 * you attempt to replace a TLV that does not exist, this function will
     609 * just add a new TLV as if you called aim_tlvlist_add_raw().
     610 *
     611 * @param list Desination chain (%NULL pointer if empty).
     612 * @param type TLV type.
     613 * @param value 8 bit value to add.
     614 * @return The length of the TLV.
     615 */
     616faim_internal int aim_tlvlist_replace_8(aim_tlvlist_t **list, const fu16_t type, const fu8_t value)
     617{
     618        fu8_t v8[1];
     619
     620        aimutil_put8(v8, value);
     621
     622        return aim_tlvlist_replace_raw(list, type, 1, v8);
     623}
     624
     625/**
     626 * Substitute a TLV of a given type with a new TLV of the same type.  If
     627 * you attempt to replace a TLV that does not exist, this function will
     628 * just add a new TLV as if you called aim_tlvlist_add_raw().
     629 *
     630 * @param list Desination chain (%NULL pointer if empty).
     631 * @param type TLV type.
     632 * @param value 32 bit value to add.
     633 * @return The length of the TLV.
     634 */
     635faim_internal int aim_tlvlist_replace_32(aim_tlvlist_t **list, const fu16_t type, const fu32_t value)
     636{
     637        fu8_t v32[4];
     638
     639        aimutil_put32(v32, value);
     640
     641        return aim_tlvlist_replace_raw(list, type, 4, v32);
     642}
     643
     644/**
     645 * Remove a TLV of a given type.  If you attempt to remove a TLV that
     646 * does not exist, nothing happens.
     647 *
     648 * @param list Desination chain (%NULL pointer if empty).
     649 * @param type TLV type.
     650 */
     651faim_internal void aim_tlvlist_remove(aim_tlvlist_t **list, const fu16_t type)
     652{
     653        aim_tlvlist_t *del;
     654
     655        if (!list || !(*list))
     656                return;
     657
     658        /* Remove the item from the list */
     659        if ((*list)->tlv->type == type) {
     660                del = *list;
     661                *list = (*list)->next;
     662        } else {
     663                aim_tlvlist_t *cur;
     664                for (cur=*list; (cur->next && (cur->next->tlv->type!=type)); cur=cur->next);
     665                if (!cur->next)
     666                        return;
     667                del = cur->next;
     668                cur->next = del->next;
     669        }
     670
     671        /* Free the removed item */
     672        free(del->tlv->value);
     673        free(del->tlv);
     674        free(del);
     675}
     676
     677/**
     678 * aim_tlvlist_write - Write a TLV chain into a data buffer.
    568679 * @buf: Destination buffer
    569680 * @buflen: Maximum number of bytes that will be written to buffer
     
    572683 * Copies a TLV chain into a raw data buffer, writing only the number
    573684 * of bytes specified. This operation does not free the chain;
    574  * aim_freetlvchain() must still be called to free up the memory used
     685 * aim_tlvlist_free() must still be called to free up the memory used
    575686 * by the chain structures.
    576687 *
    577688 * XXX clean this up, make better use of bstreams
    578689 */
    579 faim_internal int aim_writetlvchain(aim_bstream_t *bs, aim_tlvlist_t **list)
     690faim_internal int aim_tlvlist_write(aim_bstream_t *bs, aim_tlvlist_t **list)
    580691{
    581692        int goodbuflen;
     
    583694
    584695        /* do an initial run to test total length */
    585         goodbuflen = aim_sizetlvchain(list);
     696        goodbuflen = aim_tlvlist_size(list);
    586697
    587698        if (goodbuflen > aim_bstream_empty(bs))
     
    601712
    602713/**
    603  * aim_gettlv - Grab the Nth TLV of type type in the TLV list list.
    604  * @list: Source chain
    605  * @type: Requested TLV type
    606  * @nth: Index of TLV of type to get
     714 * Grab the Nth TLV of type type in the TLV list list.
    607715 *
    608716 * Returns a pointer to an aim_tlv_t of the specified type;
     
    611719 * in a chain.
    612720 *
    613  */
    614 faim_internal aim_tlv_t *aim_gettlv(aim_tlvlist_t *list, const fu16_t t, const int n)
     721 * @param list Source chain.
     722 * @param type Requested TLV type.
     723 * @param nth Index of TLV of type to get.
     724 * @return The TLV you were looking for, or NULL if one could not be found.
     725 */
     726faim_internal aim_tlv_t *aim_tlv_gettlv(aim_tlvlist_t *list, const fu16_t type, const int nth)
    615727{
    616728        aim_tlvlist_t *cur;
     
    619731        for (cur = list, i = 0; cur; cur = cur->next) {
    620732                if (cur && cur->tlv) {
    621                         if (cur->tlv->type == t)
     733                        if (cur->tlv->type == type)
    622734                                i++;
    623                         if (i >= n)
     735                        if (i >= nth)
    624736                                return cur->tlv;
    625737                }
     
    630742
    631743/**
    632  * aim_gettlv_str - Retrieve the Nth TLV in chain as a string.
    633  * @list: Source TLV chain
    634  * @type: TLV type to search for
    635  * @nth: Index of TLV to return
    636  *
    637  * Same as aim_gettlv(), except that the return value is a %NULL-
    638  * terminated string instead of an aim_tlv_t.  This is a
    639  * dynamic buffer and must be freed by the caller.
    640  *
    641  */
    642 faim_internal char *aim_gettlv_str(aim_tlvlist_t *list, const fu16_t t, const int n)
     744 * Retrieve the data from the nth TLV in the given TLV chain as a string.
     745 *
     746 * @param list Source TLV chain.
     747 * @param type TLV type to search for.
     748 * @param nth Index of TLV to return.
     749 * @return The value of the TLV you were looking for, or NULL if one could
     750 *         not be found.  This is a dynamic buffer and must be freed by the
     751 *         caller.
     752 */
     753faim_internal char *aim_tlv_getstr(aim_tlvlist_t *list, const fu16_t type, const int nth)
    643754{
    644755        aim_tlv_t *tlv;
    645756        char *newstr;
    646757
    647         if (!(tlv = aim_gettlv(list, t, n)))
     758        if (!(tlv = aim_tlv_gettlv(list, type, nth)))
    648759                return NULL;
    649760
    650761        newstr = (char *) malloc(tlv->length + 1);
    651762        memcpy(newstr, tlv->value, tlv->length);
    652         *(newstr + tlv->length) = '\0';
     763        newstr[tlv->length] = '\0';
    653764
    654765        return newstr;
     
    656767
    657768/**
    658  * aim_gettlv8 - Retrieve the Nth TLV in chain as a 8bit integer.
    659  * @list: Source TLV chain
    660  * @type: TLV type to search for
    661  * @nth: Index of TLV to return
    662  *
    663  * Same as aim_gettlv(), except that the return value is a
    664  * 8bit integer instead of an aim_tlv_t.
    665  *
    666  */
    667 faim_internal fu8_t aim_gettlv8(aim_tlvlist_t *list, const fu16_t t, const int n)
     769 * Retrieve the data from the nth TLV in the given TLV chain as an 8bit
     770 * integer.
     771 *
     772 * @param list Source TLV chain.
     773 * @param type TLV type to search for.
     774 * @param nth Index of TLV to return.
     775 * @return The value the TLV you were looking for, or 0 if one could
     776 *         not be found.
     777 */
     778faim_internal fu8_t aim_tlv_get8(aim_tlvlist_t *list, const fu16_t type, const int nth)
    668779{
    669780        aim_tlv_t *tlv;
    670781
    671         if (!(tlv = aim_gettlv(list, t, n)))
     782        if (!(tlv = aim_tlv_gettlv(list, type, nth)))
    672783                return 0; /* erm */
    673784        return aimutil_get8(tlv->value);
     
    675786
    676787/**
    677  * aim_gettlv16 - Retrieve the Nth TLV in chain as a 16bit integer.
    678  * @list: Source TLV chain
    679  * @type: TLV type to search for
    680  * @nth: Index of TLV to return
    681  *
    682  * Same as aim_gettlv(), except that the return value is a
    683  * 16bit integer instead of an aim_tlv_t.
    684  *
    685  */
    686 faim_internal fu16_t aim_gettlv16(aim_tlvlist_t *list, const fu16_t t, const int n)
     788 * Retrieve the data from the nth TLV in the given TLV chain as a 16bit
     789 * integer.
     790 *
     791 * @param list Source TLV chain.
     792 * @param type TLV type to search for.
     793 * @param nth Index of TLV to return.
     794 * @return The value the TLV you were looking for, or 0 if one could
     795 *         not be found.
     796 */
     797faim_internal fu16_t aim_tlv_get16(aim_tlvlist_t *list, const fu16_t type, const int nth)
    687798{
    688799        aim_tlv_t *tlv;
    689800
    690         if (!(tlv = aim_gettlv(list, t, n)))
     801        if (!(tlv = aim_tlv_gettlv(list, type, nth)))
    691802                return 0; /* erm */
    692803        return aimutil_get16(tlv->value);
     
    694805
    695806/**
    696  * aim_gettlv32 - Retrieve the Nth TLV in chain as a 32bit integer.
    697  * @list: Source TLV chain
    698  * @type: TLV type to search for
    699  * @nth: Index of TLV to return
    700  *
    701  * Same as aim_gettlv(), except that the return value is a
    702  * 32bit integer instead of an aim_tlv_t.
    703  *
    704  */
    705 faim_internal fu32_t aim_gettlv32(aim_tlvlist_t *list, const fu16_t t, const int n)
     807 * Retrieve the data from the nth TLV in the given TLV chain as a 32bit
     808 * integer.
     809 *
     810 * @param list Source TLV chain.
     811 * @param type TLV type to search for.
     812 * @param nth Index of TLV to return.
     813 * @return The value the TLV you were looking for, or 0 if one could
     814 *         not be found.
     815 */
     816faim_internal fu32_t aim_tlv_get32(aim_tlvlist_t *list, const fu16_t type, const int nth)
    706817{
    707818        aim_tlv_t *tlv;
    708819
    709         if (!(tlv = aim_gettlv(list, t, n)))
     820        if (!(tlv = aim_tlv_gettlv(list, type, nth)))
    710821                return 0; /* erm */
    711822        return aimutil_get32(tlv->value);
    712823}
    713 
    714 #if 0
    715 /**
    716  * aim_puttlv_8 - Write a one-byte TLV.
    717  * @buf: Destination buffer
    718  * @t: TLV type
    719  * @v: Value
    720  *
    721  * Writes a TLV with a one-byte integer value portion.
    722  *
    723  */
    724 faim_export int aim_puttlv_8(fu8_t *buf, const fu16_t t, const fu8_t v)
    725 {
    726         fu8_t v8[1];
    727 
    728         aimutil_put8(v8, v);
    729 
    730         return aim_puttlv_raw(buf, t, 1, v8);
    731 }
    732 
    733 /**
    734  * aim_puttlv_16 - Write a two-byte TLV.
    735  * @buf: Destination buffer
    736  * @t: TLV type
    737  * @v: Value
    738  *
    739  * Writes a TLV with a two-byte integer value portion.
    740  *
    741  */
    742 faim_export int aim_puttlv_16(fu8_t *buf, const fu16_t t, const fu16_t v)
    743 {
    744         fu8_t v16[2];
    745 
    746         aimutil_put16(v16, v);
    747 
    748         return aim_puttlv_raw(buf, t, 2, v16);
    749 }
    750 
    751 
    752 /**
    753  * aim_puttlv_32 - Write a four-byte TLV.
    754  * @buf: Destination buffer
    755  * @t: TLV type
    756  * @v: Value
    757  *
    758  * Writes a TLV with a four-byte integer value portion.
    759  *
    760  */
    761 faim_export int aim_puttlv_32(fu8_t *buf, const fu16_t t, const fu32_t v)
    762 {
    763         fu8_t v32[4];
    764 
    765         aimutil_put32(v32, v);
    766 
    767         return aim_puttlv_raw(buf, t, 4, v32);
    768 }
    769 
    770 /**
    771  * aim_puttlv_raw - Write a raw TLV.
    772  * @buf: Destination buffer
    773  * @t: TLV type
    774  * @l: Length of string
    775  * @v: String to write
    776  *
    777  * Writes a TLV with a raw value portion.  (Only the first @l
    778  * bytes of the passed buffer will be written, which should not
    779  * include a terminating NULL.)
    780  *
    781  */
    782 faim_export int aim_puttlv_raw(fu8_t *buf, const fu16_t t, const fu16_t l, const fu8_t *v)
    783 {
    784         int i;
    785 
    786         i = aimutil_put16(buf, t);
    787         i += aimutil_put16(buf+i, l);
    788         if (l)
    789                 memcpy(buf+i, v, l);
    790         i += l;
    791 
    792         return i;
    793 }
    794 #endif
  • libfaim/txqueue.c

    r1e34e40 rcf02dd6  
    2929faim_internal aim_frame_t *aim_tx_new(aim_session_t *sess, aim_conn_t *conn, fu8_t framing, fu16_t chan, int datalen)
    3030{
    31   aim_frame_t *fr;
    32  
    33   if (!conn) {
    34     faimdprintf(sess, 0, "aim_tx_new: ERROR: no connection specified\n");
    35     return NULL;
    36   }
    37  
    38   /* For sanity... */
    39   if ((conn->type == AIM_CONN_TYPE_RENDEZVOUS) || (conn->type == AIM_CONN_TYPE_LISTENER)) {
    40     if (framing != AIM_FRAMETYPE_OFT) {
    41       faimdprintf(sess, 0, "aim_tx_new: attempted to allocate inappropriate frame type for rendezvous connection\n");
    42       return NULL;
    43     }
    44   } else {
    45     if (framing != AIM_FRAMETYPE_FLAP) {
    46       faimdprintf(sess, 0, "aim_tx_new: attempted to allocate inappropriate frame type for FLAP connection\n");
    47       return NULL;
    48     }
    49   }
    50  
    51   if (!(fr = (aim_frame_t *)malloc(sizeof(aim_frame_t)))) return NULL;
    52   memset(fr, 0, sizeof(aim_frame_t));
    53  
    54   fr->conn = conn;
    55   fr->hdrtype = framing;
    56   if (fr->hdrtype == AIM_FRAMETYPE_FLAP) {
    57     fr->hdr.flap.type = chan;
    58   } else if (fr->hdrtype == AIM_FRAMETYPE_OFT) {
    59     fr->hdr.rend.type = chan;
    60   } else {
    61     faimdprintf(sess, 0, "tx_new: unknown framing\n");
    62   }
    63  
    64   if (datalen > 0) {
    65     fu8_t *data;
    66     if (!(data = (unsigned char *)malloc(datalen))) {
    67       aim_frame_destroy(fr);
    68       return NULL;
    69     }
    70     aim_bstream_init(&fr->data, data, datalen);
    71   }
    72  
    73   return fr;
     31        aim_frame_t *fr;
     32
     33        if (!conn) {
     34                faimdprintf(sess, 0, "aim_tx_new: ERROR: no connection specified\n");
     35                return NULL;
     36        }
     37
     38        /* For sanity... */
     39        if ((conn->type == AIM_CONN_TYPE_RENDEZVOUS) || (conn->type == AIM_CONN_TYPE_LISTENER)) {
     40                if (framing != AIM_FRAMETYPE_OFT) {
     41                        faimdprintf(sess, 0, "aim_tx_new: attempted to allocate inappropriate frame type for rendezvous connection\n");
     42                        return NULL;
     43                }
     44        } else {
     45                if (framing != AIM_FRAMETYPE_FLAP) {
     46                        faimdprintf(sess, 0, "aim_tx_new: attempted to allocate inappropriate frame type for FLAP connection\n");
     47                        return NULL;
     48                }
     49        }
     50
     51        if (!(fr = (aim_frame_t *)malloc(sizeof(aim_frame_t))))
     52                return NULL;
     53        memset(fr, 0, sizeof(aim_frame_t));
     54
     55        fr->conn = conn;
     56
     57        fr->hdrtype = framing;
     58
     59        if (fr->hdrtype == AIM_FRAMETYPE_FLAP) {
     60
     61                fr->hdr.flap.type = chan;
     62
     63        } else if (fr->hdrtype == AIM_FRAMETYPE_OFT) {
     64
     65                fr->hdr.rend.type = chan;
     66
     67        } else
     68                faimdprintf(sess, 0, "tx_new: unknown framing\n");
     69
     70        if (datalen > 0) {
     71                fu8_t *data;
     72
     73                if (!(data = (unsigned char *)malloc(datalen))) {
     74                        aim_frame_destroy(fr);
     75                        return NULL;
     76                }
     77
     78                aim_bstream_init(&fr->data, data, datalen);
     79        }
     80
     81        return fr;
    7482}
    7583
     
    9098static int aim_tx_enqueue__queuebased(aim_session_t *sess, aim_frame_t *fr)
    9199{
    92  
    93   if (!fr->conn) {
    94     faimdprintf(sess, 1, "aim_tx_enqueue: WARNING: enqueueing packet with no connecetion\n");
    95     fr->conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
    96   }
    97  
    98   if (fr->hdrtype == AIM_FRAMETYPE_FLAP) {
    99     /* assign seqnum -- XXX should really not assign until hardxmit */
    100     fr->hdr.flap.seqnum = aim_get_next_txseqnum(fr->conn);
    101   }
    102  
    103   fr->handled = 0; /* not sent yet */
    104  
    105   /* see overhead note in aim_rxqueue counterpart */
    106   if (!sess->queue_outgoing)
    107     sess->queue_outgoing = fr;
    108   else {
    109     aim_frame_t *cur;
    110    
    111     for (cur = sess->queue_outgoing; cur->next; cur = cur->next)
    112       ;
    113     cur->next = fr;
    114   }
    115  
    116   return 0;
     100
     101        if (!fr->conn) {
     102                faimdprintf(sess, 1, "aim_tx_enqueue: WARNING: enqueueing packet with no connecetion\n");
     103                fr->conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
     104        }
     105
     106        if (fr->hdrtype == AIM_FRAMETYPE_FLAP) {
     107                /* assign seqnum -- XXX should really not assign until hardxmit */
     108                fr->hdr.flap.seqnum = aim_get_next_txseqnum(fr->conn);
     109        }
     110
     111        fr->handled = 0; /* not sent yet */
     112
     113        /* see overhead note in aim_rxqueue counterpart */
     114        if (!sess->queue_outgoing)
     115                sess->queue_outgoing = fr;
     116        else {
     117                aim_frame_t *cur;
     118
     119                for (cur = sess->queue_outgoing; cur->next; cur = cur->next)
     120                        ;
     121                cur->next = fr;
     122        }
     123
     124        return 0;
    117125}
    118126
     
    131139{
    132140
    133   if (!fr->conn) {
    134     faimdprintf(sess, 1, "aim_tx_enqueue: ERROR: packet has no connection\n");
    135     aim_frame_destroy(fr);
    136     return 0;
    137   }
    138  
    139   if (fr->hdrtype == AIM_FRAMETYPE_FLAP) fr->hdr.flap.seqnum = aim_get_next_txseqnum(fr->conn);
    140   fr->handled = 0; /* not sent yet */
    141   aim_tx_sendframe(sess, fr);
    142   aim_frame_destroy(fr);
    143  
    144   return 0;
     141        if (!fr->conn) {
     142                faimdprintf(sess, 1, "aim_tx_enqueue: ERROR: packet has no connection\n");
     143                aim_frame_destroy(fr);
     144                return 0;
     145        }
     146
     147        if (fr->hdrtype == AIM_FRAMETYPE_FLAP)
     148                fr->hdr.flap.seqnum = aim_get_next_txseqnum(fr->conn);
     149
     150        fr->handled = 0; /* not sent yet */
     151
     152        aim_tx_sendframe(sess, fr);
     153
     154        aim_frame_destroy(fr);
     155
     156        return 0;
    145157}
    146158
    147159faim_export int aim_tx_setenqueue(aim_session_t *sess, int what, int (*func)(aim_session_t *, aim_frame_t *))
    148160{
    149   if (what == AIM_TX_QUEUED) {
    150     sess->tx_enqueue = &aim_tx_enqueue__queuebased;
    151   } else if (what == AIM_TX_IMMEDIATE) {
    152     sess->tx_enqueue = &aim_tx_enqueue__immediate;
    153   } else if (what == AIM_TX_USER) {
    154     if (!func) return -EINVAL;
    155     sess->tx_enqueue = func;
    156   } else {
    157     return -EINVAL; /* unknown action */
    158   }
    159  
    160   return 0;
     161       
     162        if (what == AIM_TX_QUEUED)
     163                sess->tx_enqueue = &aim_tx_enqueue__queuebased;
     164        else if (what == AIM_TX_IMMEDIATE)
     165                sess->tx_enqueue = &aim_tx_enqueue__immediate;
     166        else if (what == AIM_TX_USER) {
     167                if (!func)
     168                        return -EINVAL;
     169                sess->tx_enqueue = func;
     170        } else
     171                return -EINVAL; /* unknown action */
     172
     173        return 0;
    161174}
    162175
    163176faim_internal int aim_tx_enqueue(aim_session_t *sess, aim_frame_t *fr)
    164177{
    165  
    166   /*
    167   * If we want to send a connection thats inprogress, we have to force
    168   * them to use the queue based version. Otherwise, use whatever they
    169   * want.
    170   */
    171   if (fr && fr->conn &&
    172       (fr->conn->status & AIM_CONN_STATUS_INPROGRESS)) {
    173     return aim_tx_enqueue__queuebased(sess, fr);
    174   }
    175  
    176   return (*sess->tx_enqueue)(sess, fr);
     178       
     179        /*
     180        * If we want to send a connection thats inprogress, we have to force
     181        * them to use the queue based version. Otherwise, use whatever they
     182        * want.
     183        */
     184        if (fr && fr->conn &&
     185                        (fr->conn->status & AIM_CONN_STATUS_INPROGRESS)) {
     186                return aim_tx_enqueue__queuebased(sess, fr);
     187        }
     188
     189        return (*sess->tx_enqueue)(sess, fr);
    177190}
    178191
     
    188201faim_internal flap_seqnum_t aim_get_next_txseqnum(aim_conn_t *conn)
    189202{
    190   flap_seqnum_t ret;
    191   ret = ++conn->seqnum;
    192   return ret;
     203        flap_seqnum_t ret;
     204       
     205        ret = ++conn->seqnum;
     206
     207        return ret;
    193208}
    194209
    195210static int aim_send(int fd, const void *buf, size_t count)
    196211{
    197   int left, cur;
    198  
    199   for (cur = 0, left = count; left; ) {
    200     int ret;
    201    
    202     ret = send(fd, ((unsigned char *)buf)+cur, left, 0);
    203     if (ret == -1) {
    204       return -1;
    205     } else if (ret == 0) {
    206       return cur;
    207     }
    208    
    209     cur += ret;
    210     left -= ret;
    211   }
    212  
    213   return cur;
     212        int left, cur;
     213
     214        for (cur = 0, left = count; left; ) {
     215                int ret;
     216
     217                ret = send(fd, ((unsigned char *)buf)+cur, left, 0);
     218                if (ret == -1)
     219                        return -1;
     220                else if (ret == 0)
     221                        return cur;
     222
     223                cur += ret;
     224                left -= ret;
     225        }
     226
     227        return cur;
    214228}
    215229
    216230static int aim_bstream_send(aim_bstream_t *bs, aim_conn_t *conn, size_t count)
    217231{
    218   int wrote = 0;
    219   int rv = 0;
    220   if (!bs || !conn || (count < 0))
    221     return -EINVAL;
    222  
    223   if (count > aim_bstream_empty(bs))
    224     count = aim_bstream_empty(bs); /* truncate to remaining space */
    225  
    226   if (count) {
    227     if ((conn->type == AIM_CONN_TYPE_RENDEZVOUS) &&
    228         (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)) {
    229       /* I strongly suspect that this is a horrible thing to do
    230        * and I feel really guilty doing it. */
    231       const char *sn = aim_odc_getsn(conn);
    232       aim_rxcallback_t userfunc;
    233       while (count - wrote > 1024) {
    234         rv = aim_send(conn->fd, bs->data + bs->offset + wrote, 1024);
    235         if (rv < 0) {
    236           fprintf(stderr, "aim_bstream_send: aim_send failed...\n");
    237           return -EINVAL;
    238         }
    239         wrote = wrote + rv;
    240          
    241         if ((userfunc=aim_callhandler(conn->sessv, conn,
    242                                       AIM_CB_FAM_SPECIAL,
    243                                       AIM_CB_SPECIAL_IMAGETRANSFER)))
    244           userfunc(conn->sessv, NULL, sn,
    245                    count-wrote>1024 ? ((double)wrote / count) : 1);
    246       }
    247     }
    248     if (count - wrote) {
    249       rv = aim_send(conn->fd, bs->data + bs->offset + wrote, count - wrote);
    250       if (rv < 0) {
    251         fprintf(stderr, "aim_bstream_send: aim_send failed...\n");
    252         return -EINVAL;
    253       }
    254       wrote = wrote + rv;
    255     }
    256    
    257   }
    258  
    259   if (((aim_session_t *)conn->sessv)->debug >= 2) {
    260     int i;
    261     aim_session_t *sess = (aim_session_t *)conn->sessv;
    262    
    263     faimdprintf(sess, 2, "\nOutgoing data: (%d bytes)", wrote);
    264     for (i = 0; i < wrote; i++) {
    265       if (!(i % 8))
    266         faimdprintf(sess, 2, "\n\t");
    267       faimdprintf(sess, 2, "0x%02x ", *(bs->data + bs->offset + i));
    268     }
    269     faimdprintf(sess, 2, "\n");
    270   }
    271  
    272   bs->offset += wrote;
    273  
    274   return wrote;
     232        int wrote = 0;
     233        if (!bs || !conn || (count < 0))
     234                return -EINVAL;
     235
     236        if (count > aim_bstream_empty(bs))
     237                count = aim_bstream_empty(bs); /* truncate to remaining space */
     238
     239        if (count) {
     240                if ((conn->type == AIM_CONN_TYPE_RENDEZVOUS) &&
     241                    (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)) {
     242                        /* I strongly suspect that this is a horrible thing to do
     243                         * and I feel really guilty doing it. */
     244                        const char *sn = aim_odc_getsn(conn);
     245                        aim_rxcallback_t userfunc;
     246                        while (count - wrote > 1024) {
     247                                wrote = wrote + aim_send(conn->fd, bs->data + bs->offset + wrote, 1024);
     248                                if ((userfunc=aim_callhandler(conn->sessv, conn,
     249                                                                AIM_CB_FAM_SPECIAL,
     250                                                                AIM_CB_SPECIAL_IMAGETRANSFER)))
     251                                  userfunc(conn->sessv, NULL, sn,
     252                                           count-wrote>1024 ? ((double)wrote / count) : 1);
     253                        }
     254                }
     255                if (count - wrote) {
     256                        wrote = wrote + aim_send(conn->fd, bs->data + bs->offset + wrote, count - wrote);
     257                }
     258
     259        }
     260
     261        if (((aim_session_t *)conn->sessv)->debug >= 2) {
     262                int i;
     263                aim_session_t *sess = (aim_session_t *)conn->sessv;
     264
     265                faimdprintf(sess, 2, "\nOutgoing data: (%d bytes)", wrote);
     266                for (i = 0; i < wrote; i++) {
     267                        if (!(i % 8))
     268                                faimdprintf(sess, 2, "\n\t");
     269                        faimdprintf(sess, 2, "0x%02x ", *(bs->data + bs->offset + i));
     270                }
     271                faimdprintf(sess, 2, "\n");
     272        }
     273
     274        bs->offset += wrote;
     275
     276        return wrote;
    275277}
    276278
    277279static int sendframe_flap(aim_session_t *sess, aim_frame_t *fr)
    278280{
    279   aim_bstream_t obs;
    280   fu8_t *obs_raw;
    281   int payloadlen, err = 0, obslen;
    282  
    283   payloadlen = aim_bstream_curpos(&fr->data);
    284  
    285   if (!(obs_raw = malloc(6 + payloadlen)))
    286     return -ENOMEM;
    287  
    288   aim_bstream_init(&obs, obs_raw, 6 + payloadlen);
    289  
    290   /* FLAP header */
    291   aimbs_put8(&obs, 0x2a);
    292   aimbs_put8(&obs, fr->hdr.flap.type);
    293   aimbs_put16(&obs, fr->hdr.flap.seqnum);
    294   aimbs_put16(&obs, payloadlen);
    295  
    296   /* payload */
    297   aim_bstream_rewind(&fr->data);
    298   aimbs_putbs(&obs, &fr->data, payloadlen);
    299  
    300   obslen = aim_bstream_curpos(&obs);
    301   aim_bstream_rewind(&obs);
    302   if (aim_bstream_send(&obs, fr->conn, obslen) != obslen)
    303     err = -errno;
    304  
    305   free(obs_raw); /* XXX aim_bstream_free */
    306  
    307   fr->handled = 1;
    308   fr->conn->lastactivity = time(NULL);
    309  
    310   return err;
     281        aim_bstream_t obs;
     282        fu8_t *obs_raw;
     283        int payloadlen, err = 0, obslen;
     284
     285        payloadlen = aim_bstream_curpos(&fr->data);
     286
     287        if (!(obs_raw = malloc(6 + payloadlen)))
     288                return -ENOMEM;
     289
     290        aim_bstream_init(&obs, obs_raw, 6 + payloadlen);
     291
     292        /* FLAP header */
     293        aimbs_put8(&obs, 0x2a);
     294        aimbs_put8(&obs, fr->hdr.flap.type);
     295        aimbs_put16(&obs, fr->hdr.flap.seqnum);
     296        aimbs_put16(&obs, payloadlen);
     297
     298        /* payload */
     299        aim_bstream_rewind(&fr->data);
     300        aimbs_putbs(&obs, &fr->data, payloadlen);
     301
     302        obslen = aim_bstream_curpos(&obs);
     303        aim_bstream_rewind(&obs);
     304        if (aim_bstream_send(&obs, fr->conn, obslen) != obslen)
     305                err = -errno;
     306       
     307        free(obs_raw); /* XXX aim_bstream_free */
     308
     309        fr->handled = 1;
     310        fr->conn->lastactivity = time(NULL);
     311
     312        return err;
    311313}
    312314
Note: See TracChangeset for help on using the changeset viewer.