Changeset 862371b
- Timestamp:
- Jun 29, 2003, 1:47:04 PM (21 years ago)
- 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:
- e016fc2
- Parents:
- 03ad7b2
- Location:
- libfaim
- Files:
-
- 3 added
- 32 edited
Legend:
- Unmodified
- Added
- Removed
-
libfaim/Makefile.in
r5e53c4a r862371b 3 3 LDFLAGS=@LDFLAGS@ 4 4 RANLIB=@RANLIB@ 5 OBJS=admin.o adverts.o auth.o bos.o buddylist.o \6 chat.o chatnav.o conn.o ft.o icq.o im.o \7 info.o invite.o md5.o meta.o misc.o msgcookie.o \5 OBJS=admin.o adverts.o auth.o bos.o buddylist.o bstream.o \ 6 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 \ 8 8 popups.o rxhandlers.o rxqueue.o search.o service.o \ 9 9 snac.o ssi.o stats.o tlv.o translate.o txqueue.o \ -
libfaim/admin.c
r5e53c4a r862371b 1 /* 2 * Family 0x0007 - Account Administration. 3 * 4 * Used for stuff like changing the formating of your screen name, changing your 5 * email address, requesting an account confirmation email, getting account info, 6 * 7 */ 1 8 2 9 #define FAIM_INTERNAL 3 10 #include <aim.h> 4 11 5 /* called for both reply and change-reply */ 12 /* 13 * Subtype 0x0002 - Request a bit of account info. 14 * 15 * Info should be one of the following: 16 * 0x0001 - Screen name formatting 17 * 0x0011 - Email address 18 * 0x0013 - Unknown 19 * 20 */ 21 faim_export int aim_admin_getinfo(aim_session_t *sess, aim_conn_t *conn, fu16_t info) 22 { 23 aim_frame_t *fr; 24 aim_snacid_t snacid; 25 26 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 14))) 27 return -ENOMEM; 28 29 snacid = aim_cachesnac(sess, 0x0007, 0x0002, 0x0000, NULL, 0); 30 aim_putsnac(&fr->data, 0x0007, 0x0002, 0x0000, snacid); 31 32 aimbs_put16(&fr->data, info); 33 aimbs_put16(&fr->data, 0x0000); 34 35 aim_tx_enqueue(sess, fr); 36 37 return 0; 38 } 39 40 /* 41 * Subtypes 0x0003 and 0x0005 - Parse account info. 42 * 43 * Called in reply to both an information request (subtype 0x0002) and 44 * an information change (subtype 0x0004). 45 * 46 */ 6 47 static int infochange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 7 48 { 8 9 /* 10 * struct { 11 * unsigned short perms; 12 * unsigned short tlvcount; 13 * aim_tlv_t tlvs[tlvcount]; 14 * } admin_info[n]; 15 */ 16 while (aim_bstream_empty(bs)) { 17 fu16_t perms, tlvcount; 18 19 perms = aimbs_get16(bs); 20 tlvcount = aimbs_get16(bs); 21 22 while (tlvcount && aim_bstream_empty(bs)) { 23 aim_rxcallback_t userfunc; 24 fu16_t type, len; 25 fu8_t *val; 26 int str = 0; 27 28 type = aimbs_get16(bs); 29 len = aimbs_get16(bs); 30 31 if ((type == 0x0011) || (type == 0x0004)) 32 str = 1; 33 34 if (str) 35 val = aimbs_getstr(bs, len); 36 else 37 val = aimbs_getraw(bs, len); 38 39 /* XXX fix so its only called once for the entire packet */ 40 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 41 userfunc(sess, rx, (snac->subtype == 0x0005) ? 1 : 0, perms, type, len, val, str); 42 43 free(val); 44 45 tlvcount--; 49 aim_rxcallback_t userfunc; 50 char *url=NULL, *sn=NULL, *email=NULL; 51 fu16_t perms, tlvcount, err=0; 52 53 perms = aimbs_get16(bs); 54 tlvcount = aimbs_get16(bs); 55 56 while (tlvcount && aim_bstream_empty(bs)) { 57 fu16_t type, length; 58 59 type = aimbs_get16(bs); 60 length = aimbs_get16(bs); 61 62 switch (type) { 63 case 0x0001: { 64 sn = aimbs_getstr(bs, length); 65 } break; 66 67 case 0x0004: { 68 url = aimbs_getstr(bs, length); 69 } break; 70 71 case 0x0008: { 72 err = aimbs_get16(bs); 73 } break; 74 75 case 0x0011: { 76 if (length == 0) { 77 email = (char*)malloc(13*sizeof(char)); 78 strcpy(email, "*suppressed*"); 79 } else 80 email = aimbs_getstr(bs, length); 81 } break; 46 82 } 83 84 tlvcount--; 47 85 } 48 86 87 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 88 userfunc(sess, rx, (snac->subtype == 0x0005) ? 1 : 0, perms, err, url, sn, email); 89 90 if (sn) free(sn); 91 if (url) free(url); 92 if (email) free(email); 93 49 94 return 1; 50 95 } 51 96 97 /* 98 * Subtype 0x0004 - Set screenname formatting. 99 * 100 */ 101 faim_export int aim_admin_setnick(aim_session_t *sess, aim_conn_t *conn, const char *newnick) 102 { 103 aim_frame_t *fr; 104 aim_snacid_t snacid; 105 aim_tlvlist_t *tl = NULL; 106 107 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(newnick)))) 108 return -ENOMEM; 109 110 snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0); 111 aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid); 112 113 aim_addtlvtochain_raw(&tl, 0x0001, strlen(newnick), newnick); 114 115 aim_writetlvchain(&fr->data, &tl); 116 aim_freetlvchain(&tl); 117 118 aim_tx_enqueue(sess, fr); 119 120 121 return 0; 122 } 123 124 /* 125 * Subtype 0x0004 - Change password. 126 * 127 */ 128 faim_export int aim_admin_changepasswd(aim_session_t *sess, aim_conn_t *conn, const char *newpw, const char *curpw) 129 { 130 aim_frame_t *fr; 131 aim_tlvlist_t *tl = NULL; 132 aim_snacid_t snacid; 133 134 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+strlen(curpw)+4+strlen(newpw)))) 135 return -ENOMEM; 136 137 snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0); 138 aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid); 139 140 /* new password TLV t(0002) */ 141 aim_addtlvtochain_raw(&tl, 0x0002, strlen(newpw), newpw); 142 143 /* 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); 148 149 aim_tx_enqueue(sess, fr); 150 151 return 0; 152 } 153 154 /* 155 * Subtype 0x0004 - Change email address. 156 * 157 */ 158 faim_export int aim_admin_setemail(aim_session_t *sess, aim_conn_t *conn, const char *newemail) 159 { 160 aim_frame_t *fr; 161 aim_snacid_t snacid; 162 aim_tlvlist_t *tl = NULL; 163 164 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(newemail)))) 165 return -ENOMEM; 166 167 snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0); 168 aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid); 169 170 aim_addtlvtochain_raw(&tl, 0x0011, strlen(newemail), newemail); 171 172 aim_writetlvchain(&fr->data, &tl); 173 aim_freetlvchain(&tl); 174 175 aim_tx_enqueue(sess, fr); 176 177 return 0; 178 } 179 180 /* 181 * Subtype 0x0006 - Request account confirmation. 182 * 183 * This will cause an email to be sent to the address associated with 184 * the account. By following the instructions in the mail, you can 185 * get the TRIAL flag removed from your account. 186 * 187 */ 188 faim_export int aim_admin_reqconfirm(aim_session_t *sess, aim_conn_t *conn) 189 { 190 return aim_genericreq_n(sess, conn, 0x0007, 0x0006); 191 } 192 193 /* 194 * Subtype 0x0007 - Account confirmation request acknowledgement. 195 * 196 */ 52 197 static int accountconfirm(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 53 198 { 54 199 aim_rxcallback_t userfunc; 55 200 fu16_t status; 201 aim_tlvlist_t *tl; 56 202 57 203 status = aimbs_get16(bs); 204 /* This is 0x0013 if unable to confirm at this time */ 205 206 tl = aim_readtlvchain(bs); 58 207 59 208 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) … … 87 236 return 0; 88 237 } 89 90 faim_export int aim_admin_changepasswd(aim_session_t *sess, aim_conn_t *conn, const char *newpw, const char *curpw)91 {92 aim_frame_t *tx;93 aim_tlvlist_t *tl = NULL;94 aim_snacid_t snacid;95 96 if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+strlen(curpw)+4+strlen(newpw))))97 return -ENOMEM;98 99 snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0);100 aim_putsnac(&tx->data, 0x0007, 0x0004, 0x0000, snacid);101 102 /* new password TLV t(0002) */103 aim_addtlvtochain_raw(&tl, 0x0002, strlen(newpw), newpw);104 105 /* current password TLV t(0012) */106 aim_addtlvtochain_raw(&tl, 0x0012, strlen(curpw), curpw);107 108 aim_writetlvchain(&tx->data, &tl);109 aim_freetlvchain(&tl);110 111 aim_tx_enqueue(sess, tx);112 113 return 0;114 }115 116 /*117 * Request account confirmation.118 *119 * This will cause an email to be sent to the address associated with120 * the account. By following the instructions in the mail, you can121 * get the TRIAL flag removed from your account.122 *123 */124 faim_export int aim_admin_reqconfirm(aim_session_t *sess, aim_conn_t *conn)125 {126 return aim_genericreq_n(sess, conn, 0x0007, 0x0006);127 }128 129 /*130 * Request a bit of account info.131 *132 * The only known valid tag is 0x0011 (email address).133 *134 */135 faim_export int aim_admin_getinfo(aim_session_t *sess, aim_conn_t *conn, fu16_t info)136 {137 aim_frame_t *tx;138 aim_snacid_t snacid;139 140 if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 14)))141 return -ENOMEM;142 143 snacid = aim_cachesnac(sess, 0x0002, 0x0002, 0x0000, NULL, 0);144 aim_putsnac(&tx->data, 0x0007, 0x0002, 0x0000, snacid);145 146 aimbs_put16(&tx->data, info);147 aimbs_put16(&tx->data, 0x0000);148 149 aim_tx_enqueue(sess, tx);150 151 return 0;152 }153 154 faim_export int aim_admin_setemail(aim_session_t *sess, aim_conn_t *conn, const char *newemail)155 {156 aim_frame_t *tx;157 aim_snacid_t snacid;158 aim_tlvlist_t *tl = NULL;159 160 if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(newemail))))161 return -ENOMEM;162 163 snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0);164 aim_putsnac(&tx->data, 0x0007, 0x0004, 0x0000, snacid);165 166 aim_addtlvtochain_raw(&tl, 0x0011, strlen(newemail), newemail);167 168 aim_writetlvchain(&tx->data, &tl);169 aim_freetlvchain(&tl);170 171 aim_tx_enqueue(sess, tx);172 173 return 0;174 }175 176 faim_export int aim_admin_setnick(aim_session_t *sess, aim_conn_t *conn, const char *newnick)177 {178 aim_frame_t *tx;179 aim_snacid_t snacid;180 aim_tlvlist_t *tl = NULL;181 182 if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(newnick))))183 return -ENOMEM;184 185 snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0);186 aim_putsnac(&tx->data, 0x0007, 0x0004, 0x0000, snacid);187 188 aim_addtlvtochain_raw(&tl, 0x0001, strlen(newnick), newnick);189 190 aim_writetlvchain(&tx->data, &tl);191 aim_freetlvchain(&tl);192 193 aim_tx_enqueue(sess, tx);194 195 return 0;196 }197 -
libfaim/adverts.c
r5e53c4a r862371b 1 1 /* 2 * 2 * Family 0x0005 - Advertisements. 3 3 * 4 4 */ … … 30 30 return 0; 31 31 } 32 33 -
libfaim/aim.h
r5e53c4a r862371b 12 12 #define FAIM_VERSION_MAJOR 0 13 13 #define FAIM_VERSION_MINOR 99 14 #define FAIM_VERSION_MINORMINOR 414 #define FAIM_VERSION_MINORMINOR 1 15 15 16 16 #include <faimconfig.h> … … 26 26 #include <time.h> 27 27 28 #ifdef _WIN32 29 #include <windows.h> 30 #include <io.h> 31 #else 28 #ifndef _WIN32 32 29 #include <sys/time.h> 33 30 #include <unistd.h> 34 31 #include <netinet/in.h> 35 32 #include <sys/socket.h> 33 #else 34 #include <winsock.h> 36 35 #endif 37 36 … … 42 41 typedef fu32_t aim_snacid_t; 43 42 typedef fu16_t flap_seqnum_t; 44 45 /* Portability stuff (DMP) */46 47 #ifdef _WIN3248 #define sleep(x) Sleep((x)*1000)49 #define snprintf _snprintf /* I'm not sure whats wrong with Microsoft here */50 #define close(x) closesocket(x) /* no comment */51 #endif52 43 53 44 #if defined(mach) && defined(__APPLE__) … … 147 138 }; 148 139 149 #define AIM_CLIENTINFO_KNOWNGOOD_3_5_1670 { \140 #define CLIENTINFO_AIM_3_5_1670 { \ 150 141 "AOL Instant Messenger (SM), version 3.5.1670/WIN32", \ 151 142 0x0004, \ … … 158 149 } 159 150 160 #define AIM_CLIENTINFO_KNOWNGOOD_4_1_2010 { \151 #define CLIENTINFO_AIM_4_1_2010 { \ 161 152 "AOL Instant Messenger (SM), version 4.1.2010/WIN32", \ 162 153 0x0004, \ … … 169 160 } 170 161 162 #define CLIENTINFO_AIM_5_0_2938 { \ 163 "AOL Instant Messenger, version 5.0.2938/WIN32", \ 164 0x0109, \ 165 0x0005, \ 166 0x0000, \ 167 0x0000, \ 168 0x0b7a, \ 169 "us", \ 170 "en", \ 171 } 172 173 #define CLIENTINFO_ICQ_4_65_3281 { \ 174 "ICQ Inc. - Product of ICQ (TM) 2000b.4.65.1.3281.85", \ 175 0x010a, \ 176 0x0004, \ 177 0x0041, \ 178 0x0001, \ 179 0x0cd1, \ 180 "us", \ 181 "en", \ 182 } 183 184 #define CLIENTINFO_ICQ_5_34_3728 { \ 185 "ICQ Inc. - Product of ICQ (TM).2002a.5.34.1.3728.85", \ 186 0x010a, \ 187 0x0005, \ 188 0x0022, \ 189 0x0001, \ 190 0x0e8f, \ 191 "us", \ 192 "en", \ 193 } 194 171 195 /* 172 196 * I would make 4.1.2010 the default, but they seem to have found … … 174 198 * 175 199 * 3.5.1670 should work fine, however, you will be subjected to the 176 * memory test, which may require you to have a WinAIM binary l aying200 * memory test, which may require you to have a WinAIM binary lying 177 201 * around. (see login.c::memrequest()) 178 202 */ 179 #define AIM_CLIENTINFO_KNOWNGOOD AIM_CLIENTINFO_KNOWNGOOD_3_5_1670 203 #define CLIENTINFO_AIM_KNOWNGOOD CLIENTINFO_AIM_3_5_1670 204 #define CLIENTINFO_ICQ_KNOWNGOOD CLIENTINFO_ICQ_4_65_3281 180 205 181 206 #ifndef TRUE … … 192 217 #define AIM_CONN_TYPE_CHAT 0x000e 193 218 #define AIM_CONN_TYPE_CHATNAV 0x000d 219 #define AIM_CONN_TYPE_SEARCH 0x000f 220 #define AIM_CONN_TYPE_EMAIL 0x0018 194 221 195 222 /* they start getting arbitrary in rendezvous stuff =) */ … … 250 277 typedef struct aim_bstream_s { 251 278 fu8_t *data; 252 fu 16_t len;253 fu 16_t offset;279 fu32_t len; 280 fu32_t offset; 254 281 } aim_bstream_t; 255 282 … … 262 289 } flap; 263 290 struct { 291 fu8_t magic[4]; /* ODC2 OFT2 */ 292 fu16_t hdrlen; 264 293 fu16_t type; 265 fu8_t magic[4]; /* ODC2 OFT2 */ 266 fu16_t hdr2len; 267 fu8_t *hdr2; /* rest of bloated header */ 268 } oft; 294 } rend; 269 295 } hdr; 270 296 aim_bstream_t data; /* payload stream */ … … 305 331 306 332 /* ---- Internal Use Only ------------------------ */ 333 334 /* Server-stored information (ssi) */ 335 struct { 336 int received_data; 337 fu16_t revision; 338 struct aim_ssi_item *items; 339 time_t timestamp; 340 int waiting_for_ack; 341 aim_frame_t *holding_queue; 342 } ssi; 343 344 struct aim_emailinfo *emailinfo; 307 345 308 346 /* Connection information */ … … 381 419 fu32_t membersince; /* time_t */ 382 420 fu32_t onlinesince; /* time_t */ 383 fu32_t sessionlen; /* in seconds */421 fu32_t sessionlen; /* in seconds */ 384 422 fu32_t capabilities; 385 423 struct { … … 459 497 /* TLV list handling. */ 460 498 faim_internal aim_tlvlist_t *aim_readtlvchain(aim_bstream_t *bs); 499 faim_internal aim_tlvlist_t *aim_readtlvchain_num(aim_bstream_t *bs, fu16_t num); 461 500 faim_internal void aim_freetlvchain(aim_tlvlist_t **list); 462 501 faim_internal aim_tlv_t *aim_gettlv(aim_tlvlist_t *, fu16_t t, const int n); … … 518 557 char *bosip; 519 558 fu8_t *cookie; 559 char *chpassurl; 520 560 struct aim_clientrelease latestrelease; 521 561 struct aim_clientrelease latestbeta; … … 574 614 faim_export aim_conn_t *aim_getconn_fd(aim_session_t *, int fd); 575 615 576 /* aim_misc.c */616 /* misc.c */ 577 617 578 618 #define AIM_VISIBILITYCHANGE_PERMITADD 0x05 … … 620 660 faim_export int aim_ads_requestads(aim_session_t *sess, aim_conn_t *conn); 621 661 622 /* aim_im.c */662 /* im.c */ 623 663 624 664 struct aim_fileheader_t { … … 657 697 }; 658 698 659 struct aim_filetransfer_priv { 660 char sn[MAXSNLEN]; 661 char cookie[8]; 662 char ip[30]; 663 int state; 664 struct aim_fileheader_t fh; 665 }; 699 #define AIM_OFT_SUBTYPE_SEND_FILE 0x0001 700 #define AIM_OFT_SUBTYPE_SEND_DIR 0x0002 701 #define AIM_OFT_SUBTYPE_GET_FILE 0x0011 702 #define AIM_OPT_SUBTYPE_GET_LIST 0x0012 666 703 667 704 struct aim_chat_roominfo { … … 683 720 #define AIM_IMFLAGS_MULTIPART 0x0400 /* ->mpmsg section valid */ 684 721 #define AIM_IMFLAGS_OFFLINE 0x0800 /* send to offline user */ 722 #define AIM_IMFLAGS_TYPINGNOT 0x1000 /* typing notification */ 685 723 686 724 /* … … 822 860 const char *rtfmsg; 823 861 } rtfmsg; 862 struct { 863 fu16_t subtype; 864 fu16_t totfiles; 865 fu32_t totsize; 866 char *filename; 867 } sendfile; 824 868 } info; 825 869 void *destructor; /* used internally only */ 870 }; 871 872 /* Valid values for channel 4 args->type */ 873 #define AIM_ICQMSG_AUTHREQUEST 0x0006 874 #define AIM_ICQMSG_AUTHDENIED 0x0007 875 #define AIM_ICQMSG_AUTHGRANTED 0x0008 876 877 struct aim_incomingim_ch4_args { 878 fu32_t uin; /* Of the sender of the ICBM */ 879 fu16_t type; 880 char *msg; /* Reason for auth request, deny, or accept */ 826 881 }; 827 882 … … 831 886 faim_export int aim_send_icon(aim_session_t *sess, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu16_t iconsum); 832 887 faim_export fu16_t aim_iconsum(const fu8_t *buf, int buflen); 833 faim_export int aim_send_im_direct(aim_session_t *, aim_conn_t *, const char *msg); 888 faim_export int aim_send_typing(aim_session_t *sess, aim_conn_t *conn, int typing); 889 faim_export int aim_send_im_direct(aim_session_t *, aim_conn_t *, const char *msg, int len, int encoding); 834 890 faim_export const char *aim_directim_getsn(aim_conn_t *conn); 835 891 faim_export aim_conn_t *aim_directim_initiate(aim_session_t *, const char *destsn); 836 892 faim_export aim_conn_t *aim_directim_connect(aim_session_t *, const char *sn, const char *addr, const fu8_t *cookie); 837 893 838 faim_export aim_conn_t *aim_sendfile_initiate(aim_session_t *, const char *destsn, const char *filename, fu16_t numfiles, fu32_t totsize); 894 faim_export int aim_send_im_ch2_geticqmessage(aim_session_t *sess, const char *sn, int type); 895 faim_export aim_conn_t *aim_sendfile_initiate(aim_session_t *, const char *destsn, const char *filename, fu16_t numfiles, fu32_t totsize, char *cookret); 896 faim_export int aim_send_im_ch4(aim_session_t *sess, char *sn, fu16_t type, fu8_t *message); 897 898 faim_export int aim_mtn_send(aim_session_t *sess, fu16_t type1, char *sn, fu16_t type2); 839 899 840 900 faim_export aim_conn_t *aim_getfile_initiate(aim_session_t *sess, aim_conn_t *conn, const char *destsn); 841 901 faim_export int aim_oft_getfile_request(aim_session_t *sess, aim_conn_t *conn, const char *name, int size); 902 faim_export int aim_oft_sendfile_request(aim_session_t *sess, aim_conn_t *conn, 903 const char *name, int filesdone, int numfiles, int size, 904 int totsize); 842 905 faim_export int aim_oft_getfile_ack(aim_session_t *sess, aim_conn_t *conn); 843 faim_export int aim_oft_ getfile_end(aim_session_t *sess, aim_conn_t *conn);844 845 /* aim_info.c */906 faim_export int aim_oft_end(aim_session_t *sess, aim_conn_t *conn); 907 908 /* info.c */ 846 909 #define AIM_CAPS_BUDDYICON 0x00000001 847 910 #define AIM_CAPS_VOICE 0x00000002 … … 904 967 #define AIM_TRANSFER_DENY_NOTACCEPTING 0x0002 905 968 faim_export int aim_denytransfer(aim_session_t *sess, const char *sender, const char *cookie, unsigned short code); 906 faim_export aim_conn_t *aim_accepttransfer(aim_session_t *sess, aim_conn_t *conn, const char *sn, const fu8_t *cookie, const fu8_t *ip, fu16_t listingfiles, fu16_t listingtotsize, fu16_t listingsize, fu32_t listingchecksum, fu16_t rendid); 969 faim_export aim_conn_t *aim_accepttransfer(aim_session_t *sess, aim_conn_t *conn, const char *sn, const fu8_t *cookie, const fu8_t *ip, fu16_t port, fu16_t rendid, ...); 970 faim_export int aim_canceltransfer(aim_session_t *sess, aim_conn_t *conn, 971 const char *cookie, const char *sn, int rendid); 972 faim_export fu32_t aim_update_checksum(aim_session_t *sess, aim_conn_t *conn, 973 const unsigned char *buffer, int bufferlen); 907 974 908 975 faim_export int aim_getinfo(aim_session_t *, aim_conn_t *, const char *, unsigned short); … … 933 1000 934 1001 struct aim_icbmparameters { 935 unsigned short maxchan;936 unsigned longflags; /* AIM_IMPARAM_FLAG_ */937 unsigned short maxmsglen; /* message size that you will accept */938 unsigned short maxsenderwarn; /* this and below are *10 (999=99.9%) */939 unsigned short maxrecverwarn;940 unsigned longminmsginterval; /* in milliseconds? */1002 fu16_t maxchan; 1003 fu32_t flags; /* AIM_IMPARAM_FLAG_ */ 1004 fu16_t maxmsglen; /* message size that you will accept */ 1005 fu16_t maxsenderwarn; /* this and below are *10 (999=99.9%) */ 1006 fu16_t maxrecverwarn; 1007 fu32_t minmsginterval; /* in milliseconds? */ 941 1008 }; 942 1009 … … 954 1021 faim_export int aim_admin_setnick(aim_session_t *sess, aim_conn_t *conn, const char *newnick); 955 1022 956 /* aim_buddylist.c */1023 /* buddylist.c */ 957 1024 faim_export int aim_add_buddy(aim_session_t *, aim_conn_t *, const char *); 958 1025 faim_export int aim_remove_buddy(aim_session_t *, aim_conn_t *, const char *); 959 1026 960 /* aim_search.c */1027 /* search.c */ 961 1028 faim_export int aim_usersearch_address(aim_session_t *, aim_conn_t *, const char *); 1029 1030 /* newsearch.c */ 1031 struct aim_usersearch { 1032 char *first; 1033 char *last; 1034 char *middle; 1035 char *maiden; 1036 char *email; 1037 char *country; 1038 char *state; 1039 char *city; 1040 char *sn; 1041 char *interest; 1042 char *nick; 1043 char *zip; 1044 char *region; 1045 char *address; 1046 struct aim_usersearch *next; 1047 }; 1048 1049 faim_export int aim_usersearch_email(aim_session_t *, const char *, const char *); 1050 faim_export int aim_usersearch_name(aim_session_t *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *); 1051 faim_export int aim_usersearch_interest(aim_session_t *, const char *, const char *); 1052 962 1053 963 1054 /* These apply to exchanges as well. */ … … 995 1086 #define AIM_SSI_TYPE_BUDDY 0x0000 996 1087 #define AIM_SSI_TYPE_GROUP 0x0001 997 #define AIM_SSI_TYPE_PERMIT LIST0x0002998 #define AIM_SSI_TYPE_DENY LIST0x00031088 #define AIM_SSI_TYPE_PERMIT 0x0002 1089 #define AIM_SSI_TYPE_DENY 0x0003 999 1090 #define AIM_SSI_TYPE_PDINFO 0x0004 1000 1091 #define AIM_SSI_TYPE_PRESENCEPREFS 0x0005 … … 1009 1100 }; 1010 1101 1102 /* These build the actual SNACs and queue them to be sent */ 1011 1103 faim_export int aim_ssi_reqrights(aim_session_t *sess, aim_conn_t *conn); 1012 1104 faim_export int aim_ssi_reqdata(aim_session_t *sess, aim_conn_t *conn, time_t localstamp, fu16_t localrev); 1013 1105 faim_export int aim_ssi_enable(aim_session_t *sess, aim_conn_t *conn); 1106 faim_export int aim_ssi_addmoddel(aim_session_t *sess, aim_conn_t *conn, struct aim_ssi_item **items, unsigned int num, fu16_t subtype); 1014 1107 faim_export int aim_ssi_modbegin(aim_session_t *sess, aim_conn_t *conn); 1015 1108 faim_export int aim_ssi_modend(aim_session_t *sess, aim_conn_t *conn); 1109 1110 /* These handle the local variables */ 1111 faim_export struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, fu16_t gid, fu16_t bid); 1112 faim_export struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *sn, fu16_t type); 1113 faim_export struct aim_ssi_item *aim_ssi_itemlist_findparent(struct aim_ssi_item *list, char *sn); 1114 faim_export int aim_ssi_getpermdeny(struct aim_ssi_item *list); 1115 faim_export fu32_t aim_ssi_getpresence(struct aim_ssi_item *list); 1116 faim_export int aim_ssi_cleanlist(aim_session_t *sess, aim_conn_t *conn); 1117 faim_export int aim_ssi_addbuddies(aim_session_t *sess, aim_conn_t *conn, const char *gn, const char **sn, unsigned int num); 1118 faim_export int aim_ssi_addmastergroup(aim_session_t *sess, aim_conn_t *conn); 1119 faim_export int aim_ssi_addgroups(aim_session_t *sess, aim_conn_t *conn, const char **gn, unsigned int num); 1120 faim_export int aim_ssi_addpord(aim_session_t *sess, aim_conn_t *conn, const char **sn, unsigned int num, fu16_t type); 1121 faim_export int aim_ssi_movebuddy(aim_session_t *sess, aim_conn_t *conn, const char *oldgn, const char *newgn, const char *sn); 1122 faim_export int aim_ssi_rename_group(aim_session_t *sess, aim_conn_t *conn, const char *oldgn, const char *newgn); 1123 faim_export int aim_ssi_delbuddies(aim_session_t *sess, aim_conn_t *conn, const char *gn, char **sn, unsigned int num); 1124 faim_export int aim_ssi_delmastergroup(aim_session_t *sess, aim_conn_t *conn); 1125 faim_export int aim_ssi_delgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned int num); 1126 faim_export int aim_ssi_deletelist(aim_session_t *sess, aim_conn_t *conn); 1127 faim_export int aim_ssi_delpord(aim_session_t *sess, aim_conn_t *conn, const char **sn, unsigned int num, fu16_t type); 1128 faim_export int aim_ssi_setpermdeny(aim_session_t *sess, aim_conn_t *conn, fu8_t permdeny, fu32_t vismask); 1129 faim_export int aim_ssi_setpresence(aim_session_t *sess, aim_conn_t *conn, fu32_t presence); 1016 1130 1017 1131 struct aim_icq_offlinemsg { … … 1035 1149 faim_export int aim_icq_getsimpleinfo(aim_session_t *sess, const char *uin); 1036 1150 1037 /* aim_util.c */ 1151 /* email.c */ 1152 struct aim_emailinfo { 1153 fu8_t *cookie16; 1154 fu8_t *cookie8; 1155 char *url; 1156 fu16_t nummsgs; 1157 fu8_t unread; 1158 char *domain; 1159 fu16_t flag; 1160 struct aim_emailinfo *next; 1161 }; 1162 1163 faim_export int aim_email_sendcookies(aim_session_t *sess, aim_conn_t *conn); 1164 faim_export int aim_email_activate(aim_session_t *sess, aim_conn_t *conn); 1165 1166 /* util.c */ 1038 1167 /* 1039 1168 * These are really ugly. You'd think this was LISP. I wish it was. … … 1100 1229 faim_export char *aim_strsep(char **pp, const char *delim); 1101 1230 1102 /* aim_meta.c */1231 /* meta.c */ 1103 1232 faim_export char *aim_getbuilddate(void); 1104 1233 faim_export char *aim_getbuildtime(void); -
libfaim/aim_cbtypes.h
r5e53c4a r862371b 24 24 #define AIM_CB_FAM_CTN 0x000d /* ChatNav */ 25 25 #define AIM_CB_FAM_CHT 0x000e /* Chat */ 26 #define AIM_CB_FAM_SCH 0x000f /* "New" search */ 27 #define AIM_CB_FAM_SSI 0x0013 /* Server stored information */ 26 28 #define AIM_CB_FAM_ICQ 0x0015 27 29 #define AIM_CB_FAM_ATH 0x0017 30 #define AIM_CB_FAM_EML 0x0018 28 31 #define AIM_CB_FAM_OFT 0xfffe /* OFT/Rvous */ 29 32 #define AIM_CB_FAM_SPECIAL 0xffff /* Internal libfaim use */ … … 97 100 #define AIM_CB_MSG_EVIL 0x0009 98 101 #define AIM_CB_MSG_MISSEDCALL 0x000a 99 #define AIM_CB_MSG_CLIENT ERROR0x000b102 #define AIM_CB_MSG_CLIENTAUTORESP 0x000b 100 103 #define AIM_CB_MSG_ACK 0x000c 104 #define AIM_CB_MSG_MTN 0x0014 101 105 #define AIM_CB_MSG_DEFAULT 0xffff 102 106 … … 174 178 175 179 /* 180 * SNAC Family: "New" Search 181 * 182 * Most of these are actually special. 183 */ 184 #define AIM_CB_SCH_ERROR 0x0001 185 #define AIM_CB_SCH_SEARCH 0x0002 186 #define AIM_CB_SCH_RESULTS 0x0003 187 188 /* 176 189 * SNAC Family: ICQ 177 190 * … … 185 198 186 199 /* 200 * SNAC Family: Server-Stored Buddy Lists 201 */ 202 #define AIM_CB_SSI_ERROR 0x0001 203 #define AIM_CB_SSI_REQRIGHTS 0x0002 204 #define AIM_CB_SSI_RIGHTSINFO 0x0003 205 #define AIM_CB_SSI_REQLIST 0x0005 206 #define AIM_CB_SSI_LIST 0x0006 207 #define AIM_CB_SSI_ACTIVATE 0x0007 208 #define AIM_CB_SSI_ADD 0x0008 209 #define AIM_CB_SSI_MOD 0x0009 210 #define AIM_CB_SSI_DEL 0x000A 211 #define AIM_CB_SSI_SRVACK 0x000E 212 #define AIM_CB_SSI_NOLIST 0x000F 213 #define AIM_CB_SSI_EDITSTART 0x0011 214 #define AIM_CB_SSI_EDITSTOP 0x0012 215 216 /* 187 217 * SNAC Family: Authorizer 188 218 * … … 197 227 198 228 /* 229 * SNAC Family: Email 230 * 231 * Used for getting information on the email address 232 * associated with your screen name. 233 * 234 */ 235 #define AIM_CB_EML_ERROR 0x0001 236 #define AIM_CB_EML_SENDCOOKIES 0x0006 237 #define AIM_CB_EML_MAILSTATUS 0x0007 238 #define AIM_CB_EML_INIT 0x0016 239 240 /* 199 241 * OFT Services 200 242 * … … 207 249 #define AIM_CB_OFT_DIRECTIMINITIATE 0x0005 208 250 251 /* had been removed, put back by kretch */ 209 252 #define AIM_CB_OFT_GETFILECONNECTREQ 0x0006 /* connect request -- actually an OSCAR CAP*/ 210 253 #define AIM_CB_OFT_GETFILELISTINGREQ 0x0007 /* OFT listing.txt request */ … … 219 262 #define AIM_CB_OFT_GETFILESTATE4 0x0010 220 263 221 #define AIM_CB_OFT_SENDFILEDISCONNECT 0x0020 /* OFT connection disconnected.*/ 222 264 #define AIM_CB_OFT_SENDFILEFILEREQ 0x0011 /* started receiving file */ 265 #define AIM_CB_OFT_SENDFILEFILESEND 0x0012 /* buddy ready to for us to send */ 266 #define AIM_CB_OFT_SENDFILECOMPLETE 0x0013 /* send to buddy complete */ 267 #define AIM_CB_OFT_SENDFILEINITIATE 0x0014 /* connection to buddy initiated */ 223 268 224 269 … … 237 282 #define AIM_CB_SPECIAL_FLAPVER 0x0005 238 283 #define AIM_CB_SPECIAL_CONNINITDONE 0x0006 284 #define AIM_CB_SPECIAL_IMAGETRANSFER 0x007 285 #define AIM_CB_SPECIAL_MSGTIMEOUT 0x008 239 286 #define AIM_CB_SPECIAL_UNKNOWN 0xffff 240 287 #define AIM_CB_SPECIAL_DEFAULT AIM_CB_SPECIAL_UNKNOWN 241 288 289 /* SNAC flags */ 290 #define AIM_SNACFLAGS_DESTRUCTOR 0x0001 242 291 243 292 #endif/*__AIM_CBTYPES_H__ */ -
libfaim/aim_internal.h
r5e53c4a r862371b 25 25 char name[AIM_MODULENAME_MAXLEN+1]; 26 26 int (*snachandler)(aim_session_t *sess, struct aim_module_s *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs); 27 int (*snacdestructor)(aim_session_t *sess, aim_conn_t *conn, aim_modsnac_t *snac, void *data); 28 27 29 void (*shutdown)(aim_session_t *sess, struct aim_module_s *mod); 28 30 void *priv; … … 53 55 faim_internal int adverts_modfirst(aim_session_t *sess, aim_module_t *mod); 54 56 faim_internal int icq_modfirst(aim_session_t *sess, aim_module_t *mod); 57 faim_internal int email_modfirst(aim_session_t *sess, aim_module_t *mod); 58 faim_internal int newsearch_modfirst(aim_session_t *sess, aim_module_t *mod); 55 59 56 60 faim_internal int aim_genericreq_n(aim_session_t *, aim_conn_t *conn, fu16_t family, fu16_t subtype); … … 61 65 #define AIMBS_CURPOSPAIR(x) ((x)->data + (x)->offset), ((x)->len - (x)->offset) 62 66 63 faim_internal void aim_rxqueue_cleanbyconn(aim_session_t *sess, aim_conn_t *conn); 64 faim_internal int aim_recv(int fd, void *buf, size_t count); 65 faim_internal int aim_bstream_recv(aim_bstream_t *bs, int fd, size_t count); 67 /* bstream.c */ 66 68 faim_internal int aim_bstream_init(aim_bstream_t *bs, fu8_t *data, int len); 67 69 faim_internal int aim_bstream_empty(aim_bstream_t *bs); … … 88 90 faim_internal int aimbs_putbs(aim_bstream_t *bs, aim_bstream_t *srcbs, int len); 89 91 90 faim_internal int aim_get_command_rendezvous(aim_session_t *sess, aim_conn_t *conn); 91 92 faim_internal int aim_tx_sendframe(aim_session_t *sess, aim_frame_t *cur); 93 faim_internal flap_seqnum_t aim_get_next_txseqnum(aim_conn_t *); 94 faim_internal aim_frame_t *aim_tx_new(aim_session_t *sess, aim_conn_t *conn, fu8_t framing, fu8_t chan, int datalen); 95 faim_internal void aim_frame_destroy(aim_frame_t *); 96 faim_internal int aim_tx_enqueue(aim_session_t *, aim_frame_t *); 97 faim_internal int aim_tx_printqueue(aim_session_t *); 98 faim_internal void aim_tx_cleanqueue(aim_session_t *, aim_conn_t *); 99 92 /* conn.c */ 93 faim_internal aim_conn_t *aim_cloneconn(aim_session_t *sess, aim_conn_t *src); 94 95 /* ft.c */ 96 faim_internal int aim_rxdispatch_rendezvous(aim_session_t *sess, aim_frame_t *fr); 97 98 /* rxhandlers.c */ 100 99 faim_internal aim_rxcallback_t aim_callhandler(aim_session_t *sess, aim_conn_t *conn, u_short family, u_short type); 101 100 faim_internal int aim_callhandler_noparam(aim_session_t *sess, aim_conn_t *conn, fu16_t family, fu16_t type, aim_frame_t *ptr); 101 faim_internal int aim_parse_unknown(aim_session_t *, aim_frame_t *, ...); 102 faim_internal void aim_clonehandlers(aim_session_t *sess, aim_conn_t *dest, aim_conn_t *src); 103 104 /* rxqueue.c */ 105 faim_internal int aim_recv(int fd, void *buf, size_t count); 106 faim_internal int aim_bstream_recv(aim_bstream_t *bs, int fd, size_t count); 107 faim_internal void aim_rxqueue_cleanbyconn(aim_session_t *sess, aim_conn_t *conn); 108 faim_internal void aim_frame_destroy(aim_frame_t *); 109 110 /* txqueue.c */ 111 faim_internal aim_frame_t *aim_tx_new(aim_session_t *sess, aim_conn_t *conn, fu8_t framing, fu16_t chan, int datalen); 112 faim_internal int aim_tx_enqueue(aim_session_t *, aim_frame_t *); 113 faim_internal flap_seqnum_t aim_get_next_txseqnum(aim_conn_t *); 114 faim_internal int aim_tx_sendframe(aim_session_t *sess, aim_frame_t *cur); 115 faim_internal void aim_tx_cleanqueue(aim_session_t *, aim_conn_t *); 116 117 /* XXX - What is this? faim_internal int aim_tx_printqueue(aim_session_t *); */ 102 118 103 119 /* … … 114 130 } aim_snac_t; 115 131 132 struct aim_snac_destructor { 133 aim_conn_t *conn; 134 void *data; 135 }; 136 137 /* snac.c */ 116 138 faim_internal void aim_initsnachash(aim_session_t *sess); 117 139 faim_internal aim_snacid_t aim_newsnac(aim_session_t *, aim_snac_t *newsnac); … … 120 142 faim_internal void aim_cleansnacs(aim_session_t *, int maxage); 121 143 faim_internal int aim_putsnac(aim_bstream_t *, fu16_t family, fu16_t type, fu16_t flags, aim_snacid_t id); 122 123 faim_internal aim_conn_t *aim_cloneconn(aim_session_t *sess, aim_conn_t *src);124 faim_internal void aim_clonehandlers(aim_session_t *sess, aim_conn_t *dest, aim_conn_t *src);125 126 faim_internal int aim_oft_buildheader(unsigned char *,struct aim_fileheader_t *);127 128 faim_internal int aim_parse_unknown(aim_session_t *, aim_frame_t *, ...);129 144 130 145 /* Stored in ->priv of the service request SNAC for chats. */ -
libfaim/auth.c
r5e53c4a r862371b 1 1 /* 2 * Deals with the authorizer (group 0x0017=23, and old-style non-SNAC login). 2 * Family 0x0017 - Authentication. 3 * 4 * Deals with the authorizer for SNAC-based login, and also old-style 5 * non-SNAC login. 3 6 * 4 7 */ … … 148 151 149 152 /* 150 * Part two of the ICQ hack. Note the ignoring of the key and clientinfo. 151 */ 152 static int goddamnicq2(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *password) 153 { 154 static const char clientstr[] = {"ICQ Inc. - Product of ICQ (TM) 2000b.4.65.1.3281.85"}; 155 static const char lang[] = {"en"}; 156 static const char country[] = {"us"}; 153 * Part two of the ICQ hack. Note the ignoring of the key. 154 */ 155 static int goddamnicq2(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *password, struct client_info_s *ci) 156 { 157 157 aim_frame_t *fr; 158 158 aim_tlvlist_t *tl = NULL; … … 169 169 aim_encode_password(password, password_encoded); 170 170 171 aimbs_put32(&fr->data, 0x00000001); 171 aimbs_put32(&fr->data, 0x00000001); /* FLAP Version */ 172 172 aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), sn); 173 173 aim_addtlvtochain_raw(&tl, 0x0002, strlen(password), password_encoded); 174 aim_addtlvtochain_raw(&tl, 0x0003, strlen(clientstr), clientstr); 175 aim_addtlvtochain16(&tl, 0x0016, 0x010a); /* cliend ID */ 176 aim_addtlvtochain16(&tl, 0x0017, 0x0004); /* major version */ 177 aim_addtlvtochain16(&tl, 0x0018, 0x0041); /* minor version */ 178 aim_addtlvtochain16(&tl, 0x0019, 0x0001); /* point version */ 179 aim_addtlvtochain16(&tl, 0x001a, 0x0cd1); /* build */ 174 175 if (ci->clientstring) 176 aim_addtlvtochain_raw(&tl, 0x0003, strlen(ci->clientstring), ci->clientstring); 177 aim_addtlvtochain16(&tl, 0x0016, (fu16_t)ci->clientid); 178 aim_addtlvtochain16(&tl, 0x0017, (fu16_t)ci->major); 179 aim_addtlvtochain16(&tl, 0x0018, (fu16_t)ci->minor); 180 aim_addtlvtochain16(&tl, 0x0019, (fu16_t)ci->point); 181 aim_addtlvtochain16(&tl, 0x001a, (fu16_t)ci->build); 180 182 aim_addtlvtochain32(&tl, 0x0014, 0x00000055); /* distribution chan */ 181 aim_addtlvtochain_raw(&tl, 0x000f, strlen( lang),lang);182 aim_addtlvtochain_raw(&tl, 0x000e, strlen(c ountry),country);183 aim_addtlvtochain_raw(&tl, 0x000f, strlen(ci->lang), ci->lang); 184 aim_addtlvtochain_raw(&tl, 0x000e, strlen(ci->country), ci->country); 183 185 184 186 aim_writetlvchain(&fr->data, &tl); … … 277 279 */ 278 280 if (sess->flags & AIM_SESS_FLAGS_XORLOGIN) 279 return goddamnicq2(sess, conn, sn, password );281 return goddamnicq2(sess, conn, sn, password, ci); 280 282 281 283 … … 290 292 aim_encode_password_md5(password, key, digest); 291 293 aim_addtlvtochain_raw(&tl, 0x0025, 16, digest); 294 295 /* 296 * Newer versions of winaim have an empty type x004c TLV here. 297 */ 292 298 293 299 if (ci->clientstring) … … 305 311 * to use SSI. 306 312 */ 307 if (0) 308 aim_addtlvtochain8(&tl, 0x004a, 0x01); 313 aim_addtlvtochain8(&tl, 0x004a, 0x01); 309 314 310 315 aim_writetlvchain(&fr->data, &tl); … … 473 478 ; /* no idea what this is */ 474 479 480 /* 481 * URL to change password. 482 */ 483 if (aim_gettlv(tlvlist, 0x0054, 1)) 484 info.chpassurl = aim_gettlv_str(tlvlist, 0x0054, 1); 475 485 476 486 if ((userfunc = aim_callhandler(sess, rx->conn, snac ? snac->family : 0x0017, snac ? snac->subtype : 0x0003))) … … 481 491 free(info.errorurl); 482 492 free(info.email); 493 free(info.chpassurl); 483 494 free(info.latestrelease.name); 484 495 free(info.latestrelease.url); … … 539 550 return 0; 540 551 } 541 -
libfaim/bos.c
r5e53c4a r862371b 1 /* 2 * Family 0x0009 - Basic Oscar Service. 3 * 4 */ 1 5 2 6 #define FAIM_INTERNAL 3 7 #include <aim.h> 4 8 5 /* Request BOS rights (group 9, type 2)*/9 /* Subtype 0x0002 - Request BOS rights. */ 6 10 faim_export int aim_bos_reqrights(aim_session_t *sess, aim_conn_t *conn) 7 11 { … … 9 13 } 10 14 11 /* BOS Rights (group 9, type 3)*/15 /* Subtype 0x0003 - BOS Rights. */ 12 16 static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 13 17 { … … 43 47 44 48 /* 45 * S et group permisson mask (group 9, type 4)49 * Subtype 0x0004 - Set group permisson mask. 46 50 * 47 51 * Normally 0x1f (all classes). … … 58 62 59 63 /* 60 * Modify permit/deny lists (group 9, types 5, 6, 7, and 8)64 * Stubtypes 0x0005, 0x0006, 0x0007, and 0x0008 - Modify permit/deny lists. 61 65 * 62 66 * Changes your visibility depending on changetype: … … 159 163 return 0; 160 164 } 161 162 -
libfaim/buddylist.c
r5e53c4a r862371b 1 /* 2 * Family 0x0003 - Old-style Buddylist Management (non-SSI). 3 * 4 */ 1 5 2 6 #define FAIM_INTERNAL … … 4 8 5 9 /* 6 * Oncoming Buddy notifications contain a subset of the 7 * user information structure. Its close enough to run 8 * through aim_extractuserinfo() however. 9 * 10 * Although the offgoing notification contains no information, 11 * it is still in a format parsable by extractuserinfo. 12 * 13 */ 14 static int buddychange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 15 { 16 aim_userinfo_t userinfo; 17 aim_rxcallback_t userfunc; 18 19 aim_extractuserinfo(sess, bs, &userinfo); 20 21 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 22 return userfunc(sess, rx, &userinfo); 23 24 return 0; 25 } 26 10 * Subtype 0x0002 - Request rights. 11 * 12 * Request Buddy List rights. 13 * 14 */ 15 faim_export int aim_bos_reqbuddyrights(aim_session_t *sess, aim_conn_t *conn) 16 { 17 return aim_genericreq_n(sess, conn, 0x0003, 0x0002); 18 } 19 20 /* 21 * Subtype 0x0003 - Rights. 22 * 23 */ 27 24 static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 28 25 { … … 54 51 maxwatchers = aim_gettlv16(tlvlist, 0x0002, 1); 55 52 53 /* 54 * TLV type 0x0003: Unknown. 55 * 56 * ICQ only? 57 */ 58 56 59 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 57 60 ret = userfunc(sess, rx, maxbuddies, maxwatchers); … … 60 63 61 64 return ret; 65 } 66 67 /* 68 * Subtype 0x0004 - Add buddy to list. 69 * 70 * Adds a single buddy to your buddy list after login. 71 * XXX This should just be an extension of setbuddylist() 72 * 73 */ 74 faim_export int aim_add_buddy(aim_session_t *sess, aim_conn_t *conn, const char *sn) 75 { 76 aim_frame_t *fr; 77 aim_snacid_t snacid; 78 79 if (!sn || !strlen(sn)) 80 return -EINVAL; 81 82 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)))) 83 return -ENOMEM; 84 85 snacid = aim_cachesnac(sess, 0x0003, 0x0004, 0x0000, sn, strlen(sn)+1); 86 aim_putsnac(&fr->data, 0x0003, 0x0004, 0x0000, snacid); 87 88 aimbs_put8(&fr->data, strlen(sn)); 89 aimbs_putraw(&fr->data, sn, strlen(sn)); 90 91 aim_tx_enqueue(sess, fr); 92 93 return 0; 94 } 95 96 /* 97 * Subtype 0x0004 - Add multiple buddies to your buddy list. 98 * 99 * This just builds the "set buddy list" command then queues it. 100 * 101 * buddy_list = "Screen Name One&ScreenNameTwo&"; 102 * 103 * XXX Clean this up. 104 * 105 */ 106 faim_export int aim_bos_setbuddylist(aim_session_t *sess, aim_conn_t *conn, const char *buddy_list) 107 { 108 aim_frame_t *fr; 109 aim_snacid_t snacid; 110 int len = 0; 111 char *localcpy = NULL; 112 char *tmpptr = NULL; 113 114 if (!buddy_list || !(localcpy = strdup(buddy_list))) 115 return -EINVAL; 116 117 for (tmpptr = strtok(localcpy, "&"); tmpptr; ) { 118 faimdprintf(sess, 2, "---adding: %s (%d)\n", tmpptr, strlen(tmpptr)); 119 len += 1 + strlen(tmpptr); 120 tmpptr = strtok(NULL, "&"); 121 } 122 123 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+len))) 124 return -ENOMEM; 125 126 snacid = aim_cachesnac(sess, 0x0003, 0x0004, 0x0000, NULL, 0); 127 aim_putsnac(&fr->data, 0x0003, 0x0004, 0x0000, snacid); 128 129 strncpy(localcpy, buddy_list, strlen(buddy_list) + 1); 130 131 for (tmpptr = strtok(localcpy, "&"); tmpptr; ) { 132 133 faimdprintf(sess, 2, "---adding: %s (%d)\n", tmpptr, strlen(tmpptr)); 134 135 aimbs_put8(&fr->data, strlen(tmpptr)); 136 aimbs_putraw(&fr->data, tmpptr, strlen(tmpptr)); 137 tmpptr = strtok(NULL, "&"); 138 } 139 140 aim_tx_enqueue(sess, fr); 141 142 free(localcpy); 143 144 return 0; 145 } 146 147 /* 148 * Subtype 0x0005 - Remove buddy from list. 149 * 150 * XXX generalise to support removing multiple buddies (basically, its 151 * the same as setbuddylist() but with a different snac subtype). 152 * 153 */ 154 faim_export int aim_remove_buddy(aim_session_t *sess, aim_conn_t *conn, const char *sn) 155 { 156 aim_frame_t *fr; 157 aim_snacid_t snacid; 158 159 if (!sn || !strlen(sn)) 160 return -EINVAL; 161 162 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)))) 163 return -ENOMEM; 164 165 snacid = aim_cachesnac(sess, 0x0003, 0x0005, 0x0000, sn, strlen(sn)+1); 166 aim_putsnac(&fr->data, 0x0003, 0x0005, 0x0000, snacid); 167 168 aimbs_put8(&fr->data, strlen(sn)); 169 aimbs_putraw(&fr->data, sn, strlen(sn)); 170 171 aim_tx_enqueue(sess, fr); 172 173 return 0; 174 } 175 176 /* 177 * Subtype 0x000b 178 * 179 * XXX Why would we send this? 180 * 181 */ 182 faim_export int aim_sendbuddyoncoming(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *info) 183 { 184 aim_frame_t *fr; 185 aim_snacid_t snacid; 186 187 if (!sess || !conn || !info) 188 return -EINVAL; 189 190 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) 191 return -ENOMEM; 192 193 snacid = aim_cachesnac(sess, 0x0003, 0x000b, 0x0000, NULL, 0); 194 195 aim_putsnac(&fr->data, 0x0003, 0x000b, 0x0000, snacid); 196 aim_putuserinfo(&fr->data, info); 197 198 aim_tx_enqueue(sess, fr); 199 200 return 0; 201 } 202 203 /* 204 * Subtype 0x000c 205 * 206 * XXX Why would we send this? 207 * 208 */ 209 faim_export int aim_sendbuddyoffgoing(aim_session_t *sess, aim_conn_t *conn, const char *sn) 210 { 211 aim_frame_t *fr; 212 aim_snacid_t snacid; 213 214 if (!sess || !conn || !sn) 215 return -EINVAL; 216 217 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)))) 218 return -ENOMEM; 219 220 snacid = aim_cachesnac(sess, 0x0003, 0x000c, 0x0000, NULL, 0); 221 222 aim_putsnac(&fr->data, 0x0003, 0x000c, 0x0000, snacid); 223 aimbs_put8(&fr->data, strlen(sn)); 224 aimbs_putraw(&fr->data, sn, strlen(sn)); 225 226 aim_tx_enqueue(sess, fr); 227 228 return 0; 229 } 230 231 /* 232 * Subtypes 0x000b and 0x000c - Change in buddy status 233 * 234 * Oncoming Buddy notifications contain a subset of the 235 * user information structure. Its close enough to run 236 * through aim_extractuserinfo() however. 237 * 238 * Although the offgoing notification contains no information, 239 * it is still in a format parsable by extractuserinfo. 240 * 241 */ 242 static int buddychange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 243 { 244 aim_userinfo_t userinfo; 245 aim_rxcallback_t userfunc; 246 247 aim_extractuserinfo(sess, bs, &userinfo); 248 249 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 250 return userfunc(sess, rx, &userinfo); 251 252 return 0; 62 253 } 63 254 … … 86 277 return 0; 87 278 } 88 89 /*90 * aim_add_buddy()91 *92 * Adds a single buddy to your buddy list after login.93 *94 * XXX this should just be an extension of setbuddylist()95 *96 */97 faim_export int aim_add_buddy(aim_session_t *sess, aim_conn_t *conn, const char *sn)98 {99 aim_frame_t *fr;100 aim_snacid_t snacid;101 102 if (!sn || !strlen(sn))103 return -EINVAL;104 105 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn))))106 return -ENOMEM;107 108 snacid = aim_cachesnac(sess, 0x0003, 0x0004, 0x0000, sn, strlen(sn)+1);109 aim_putsnac(&fr->data, 0x0003, 0x0004, 0x0000, snacid);110 111 aimbs_put8(&fr->data, strlen(sn));112 aimbs_putraw(&fr->data, sn, strlen(sn));113 114 aim_tx_enqueue(sess, fr);115 116 return 0;117 }118 119 /*120 * XXX generalise to support removing multiple buddies (basically, its121 * the same as setbuddylist() but with a different snac subtype).122 *123 */124 faim_export int aim_remove_buddy(aim_session_t *sess, aim_conn_t *conn, const char *sn)125 {126 aim_frame_t *fr;127 aim_snacid_t snacid;128 129 if (!sn || !strlen(sn))130 return -EINVAL;131 132 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn))))133 return -ENOMEM;134 135 snacid = aim_cachesnac(sess, 0x0003, 0x0005, 0x0000, sn, strlen(sn)+1);136 aim_putsnac(&fr->data, 0x0003, 0x0005, 0x0000, snacid);137 138 aimbs_put8(&fr->data, strlen(sn));139 aimbs_putraw(&fr->data, sn, strlen(sn));140 141 aim_tx_enqueue(sess, fr);142 143 return 0;144 }145 -
libfaim/chat.c
r5e53c4a r862371b 1 1 /* 2 * aim_chat.c 3 * 4 * Routines for the Chat service. 2 * Family 0x000e - Routines for the Chat service. 5 3 * 6 4 */ … … 16 14 }; 17 15 18 static void dumpbox(aim_session_t *sess, unsigned char *buf, int len)19 {20 int i;21 22 if (!sess || !buf || !len)23 return;24 25 faimdprintf(sess, 1, "\nDump of %d bytes at %p:", len, buf);26 27 for (i = 0; i < len; i++) {28 if ((i % 8) == 0)29 faimdprintf(sess, 1, "\n\t");30 31 faimdprintf(sess, 1, "0x%2x ", buf[i]);32 }33 34 faimdprintf(sess, 1, "\n\n");35 36 return;37 }38 39 16 faim_internal void aim_conn_kill_chat(aim_session_t *sess, aim_conn_t *conn) 40 17 { … … 107 84 } 108 85 86 static int aim_addtlvtochain_chatroom(aim_tlvlist_t **list, fu16_t type, fu16_t exchange, const char *roomname, fu16_t instance) 87 { 88 fu8_t *buf; 89 int buflen; 90 aim_bstream_t bs; 91 92 buflen = 2 + 1 + strlen(roomname) + 2; 93 94 if (!(buf = malloc(buflen))) 95 return 0; 96 97 aim_bstream_init(&bs, buf, buflen); 98 99 aimbs_put16(&bs, exchange); 100 aimbs_put8(&bs, strlen(roomname)); 101 aimbs_putraw(&bs, roomname, strlen(roomname)); 102 aimbs_put16(&bs, instance); 103 104 aim_addtlvtochain_raw(list, type, aim_bstream_curpos(&bs), buf); 105 106 free(buf); 107 108 return 0; 109 } 110 109 111 /* 110 * Send a Chat Message. 112 * Join a room of name roomname. This is the first step to joining an 113 * already created room. It's basically a Service Request for 114 * family 0x000e, with a little added on to specify the exchange and room 115 * name. 116 */ 117 faim_export int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, fu16_t exchange, const char *roomname, fu16_t instance) 118 { 119 aim_frame_t *fr; 120 aim_snacid_t snacid; 121 aim_tlvlist_t *tl = NULL; 122 struct chatsnacinfo csi; 123 124 if (!sess || !conn || !roomname || !strlen(roomname)) 125 return -EINVAL; 126 127 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512))) 128 return -ENOMEM; 129 130 memset(&csi, 0, sizeof(csi)); 131 csi.exchange = exchange; 132 strncpy(csi.name, roomname, sizeof(csi.name)); 133 csi.instance = instance; 134 135 snacid = aim_cachesnac(sess, 0x0001, 0x0004, 0x0000, &csi, sizeof(csi)); 136 aim_putsnac(&fr->data, 0x0001, 0x0004, 0x0000, snacid); 137 138 /* 139 * Requesting service chat (0x000e) 140 */ 141 aimbs_put16(&fr->data, 0x000e); 142 143 aim_addtlvtochain_chatroom(&tl, 0x0001, exchange, roomname, instance); 144 aim_writetlvchain(&fr->data, &tl); 145 aim_freetlvchain(&tl); 146 147 aim_tx_enqueue(sess, fr); 148 149 return 0; 150 } 151 152 faim_internal int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo) 153 { 154 int namelen; 155 156 if (!bs || !outinfo) 157 return 0; 158 159 outinfo->exchange = aimbs_get16(bs); 160 namelen = aimbs_get8(bs); 161 outinfo->name = aimbs_getstr(bs, namelen); 162 outinfo->instance = aimbs_get16(bs); 163 164 return 0; 165 } 166 167 faim_export int aim_chat_leaveroom(aim_session_t *sess, const char *name) 168 { 169 aim_conn_t *conn; 170 171 if (!(conn = aim_chat_getconn(sess, name))) 172 return -ENOENT; 173 174 aim_conn_close(conn); 175 176 return 0; 177 } 178 179 /* 180 * conn must be a BOS connection! 181 */ 182 faim_export int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *msg, fu16_t exchange, const char *roomname, fu16_t instance) 183 { 184 int i; 185 aim_frame_t *fr; 186 aim_msgcookie_t *cookie; 187 struct aim_invite_priv *priv; 188 fu8_t ckstr[8]; 189 aim_snacid_t snacid; 190 aim_tlvlist_t *otl = NULL, *itl = NULL; 191 fu8_t *hdr; 192 int hdrlen; 193 aim_bstream_t hdrbs; 194 195 if (!sess || !conn || !sn || !msg || !roomname) 196 return -EINVAL; 197 198 if (conn->type != AIM_CONN_TYPE_BOS) 199 return -EINVAL; 200 201 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152+strlen(sn)+strlen(roomname)+strlen(msg)))) 202 return -ENOMEM; 203 204 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, sn, strlen(sn)+1); 205 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); 206 207 208 /* 209 * Cookie 210 */ 211 for (i = 0; i < sizeof(ckstr); i++) 212 aimutil_put8(ckstr, (fu8_t) rand()); 213 214 /* XXX should be uncached by an unwritten 'invite accept' handler */ 215 if ((priv = malloc(sizeof(struct aim_invite_priv)))) { 216 priv->sn = strdup(sn); 217 priv->roomname = strdup(roomname); 218 priv->exchange = exchange; 219 priv->instance = instance; 220 } 221 222 if ((cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_INVITE, priv))) 223 aim_cachecookie(sess, cookie); 224 else 225 free(priv); 226 227 for (i = 0; i < sizeof(ckstr); i++) 228 aimbs_put8(&fr->data, ckstr[i]); 229 230 231 /* 232 * Channel (2) 233 */ 234 aimbs_put16(&fr->data, 0x0002); 235 236 /* 237 * Dest sn 238 */ 239 aimbs_put8(&fr->data, strlen(sn)); 240 aimbs_putraw(&fr->data, sn, strlen(sn)); 241 242 /* 243 * TLV t(0005) 244 * 245 * Everything else is inside this TLV. 246 * 247 * Sigh. AOL was rather inconsistent right here. So we have 248 * to play some minor tricks. Right inside the type 5 is some 249 * raw data, followed by a series of TLVs. 250 * 251 */ 252 hdrlen = 2+8+16+6+4+4+strlen(msg)+4+2+1+strlen(roomname)+2; 253 hdr = malloc(hdrlen); 254 aim_bstream_init(&hdrbs, hdr, hdrlen); 255 256 aimbs_put16(&hdrbs, 0x0000); /* Unknown! */ 257 aimbs_putraw(&hdrbs, ckstr, sizeof(ckstr)); /* I think... */ 258 aim_putcap(&hdrbs, AIM_CAPS_CHAT); 259 260 aim_addtlvtochain16(&itl, 0x000a, 0x0001); 261 aim_addtlvtochain_noval(&itl, 0x000f); 262 aim_addtlvtochain_raw(&itl, 0x000c, strlen(msg), msg); 263 aim_addtlvtochain_chatroom(&itl, 0x2711, exchange, roomname, instance); 264 aim_writetlvchain(&hdrbs, &itl); 265 266 aim_addtlvtochain_raw(&otl, 0x0005, aim_bstream_curpos(&hdrbs), hdr); 267 268 aim_writetlvchain(&fr->data, &otl); 269 270 free(hdr); 271 aim_freetlvchain(&itl); 272 aim_freetlvchain(&otl); 273 274 aim_tx_enqueue(sess, fr); 275 276 return 0; 277 } 278 279 /* 280 * Subtype 0x0002 - General room information. Lots of stuff. 281 * 282 * Values I know are in here but I havent attached 283 * them to any of the 'Unknown's: 284 * - Language (English) 285 * 286 */ 287 static int infoupdate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 288 { 289 aim_userinfo_t *userinfo = NULL; 290 aim_rxcallback_t userfunc; 291 int ret = 0; 292 int usercount = 0; 293 fu8_t detaillevel = 0; 294 char *roomname = NULL; 295 struct aim_chat_roominfo roominfo; 296 fu16_t tlvcount = 0; 297 aim_tlvlist_t *tlvlist; 298 char *roomdesc = NULL; 299 fu16_t flags = 0; 300 fu32_t creationtime = 0; 301 fu16_t maxmsglen = 0, maxvisiblemsglen = 0; 302 fu16_t unknown_d2 = 0, unknown_d5 = 0; 303 304 aim_chat_readroominfo(bs, &roominfo); 305 306 detaillevel = aimbs_get8(bs); 307 308 if (detaillevel != 0x02) { 309 faimdprintf(sess, 0, "faim: chat_roomupdateinfo: detail level %d not supported\n", detaillevel); 310 return 1; 311 } 312 313 tlvcount = aimbs_get16(bs); 314 315 /* 316 * Everything else are TLVs. 317 */ 318 tlvlist = aim_readtlvchain(bs); 319 320 /* 321 * TLV type 0x006a is the room name in Human Readable Form. 322 */ 323 if (aim_gettlv(tlvlist, 0x006a, 1)) 324 roomname = aim_gettlv_str(tlvlist, 0x006a, 1); 325 326 /* 327 * Type 0x006f: Number of occupants. 328 */ 329 if (aim_gettlv(tlvlist, 0x006f, 1)) 330 usercount = aim_gettlv16(tlvlist, 0x006f, 1); 331 332 /* 333 * Type 0x0073: Occupant list. 334 */ 335 if (aim_gettlv(tlvlist, 0x0073, 1)) { 336 int curoccupant = 0; 337 aim_tlv_t *tmptlv; 338 aim_bstream_t occbs; 339 340 tmptlv = aim_gettlv(tlvlist, 0x0073, 1); 341 342 /* Allocate enough userinfo structs for all occupants */ 343 userinfo = calloc(usercount, sizeof(aim_userinfo_t)); 344 345 aim_bstream_init(&occbs, tmptlv->value, tmptlv->length); 346 347 while (curoccupant < usercount) 348 aim_extractuserinfo(sess, &occbs, &userinfo[curoccupant++]); 349 } 350 351 /* 352 * Type 0x00c9: Flags. (AIM_CHATROOM_FLAG) 353 */ 354 if (aim_gettlv(tlvlist, 0x00c9, 1)) 355 flags = aim_gettlv16(tlvlist, 0x00c9, 1); 356 357 /* 358 * Type 0x00ca: Creation time (4 bytes) 359 */ 360 if (aim_gettlv(tlvlist, 0x00ca, 1)) 361 creationtime = aim_gettlv32(tlvlist, 0x00ca, 1); 362 363 /* 364 * Type 0x00d1: Maximum Message Length 365 */ 366 if (aim_gettlv(tlvlist, 0x00d1, 1)) 367 maxmsglen = aim_gettlv16(tlvlist, 0x00d1, 1); 368 369 /* 370 * Type 0x00d2: Unknown. (2 bytes) 371 */ 372 if (aim_gettlv(tlvlist, 0x00d2, 1)) 373 unknown_d2 = aim_gettlv16(tlvlist, 0x00d2, 1); 374 375 /* 376 * Type 0x00d3: Room Description 377 */ 378 if (aim_gettlv(tlvlist, 0x00d3, 1)) 379 roomdesc = aim_gettlv_str(tlvlist, 0x00d3, 1); 380 381 /* 382 * Type 0x000d4: Unknown (flag only) 383 */ 384 if (aim_gettlv(tlvlist, 0x000d4, 1)) 385 ; 386 387 /* 388 * Type 0x00d5: Unknown. (1 byte) 389 */ 390 if (aim_gettlv(tlvlist, 0x00d5, 1)) 391 unknown_d5 = aim_gettlv8(tlvlist, 0x00d5, 1); 392 393 394 /* 395 * Type 0x00d6: Encoding 1 ("us-ascii") 396 */ 397 if (aim_gettlv(tlvlist, 0x000d6, 1)) 398 ; 399 400 /* 401 * Type 0x00d7: Language 1 ("en") 402 */ 403 if (aim_gettlv(tlvlist, 0x000d7, 1)) 404 ; 405 406 /* 407 * Type 0x00d8: Encoding 2 ("us-ascii") 408 */ 409 if (aim_gettlv(tlvlist, 0x000d8, 1)) 410 ; 411 412 /* 413 * Type 0x00d9: Language 2 ("en") 414 */ 415 if (aim_gettlv(tlvlist, 0x000d9, 1)) 416 ; 417 418 /* 419 * Type 0x00da: Maximum visible message length 420 */ 421 if (aim_gettlv(tlvlist, 0x000da, 1)) 422 maxvisiblemsglen = aim_gettlv16(tlvlist, 0x00da, 1); 423 424 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { 425 ret = userfunc(sess, 426 rx, 427 &roominfo, 428 roomname, 429 usercount, 430 userinfo, 431 roomdesc, 432 flags, 433 creationtime, 434 maxmsglen, 435 unknown_d2, 436 unknown_d5, 437 maxvisiblemsglen); 438 } 439 440 free(roominfo.name); 441 free(userinfo); 442 free(roomname); 443 free(roomdesc); 444 aim_freetlvchain(&tlvlist); 445 446 return ret; 447 } 448 449 /* Subtypes 0x0003 and 0x0004 */ 450 static int userlistchange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 451 { 452 aim_userinfo_t *userinfo = NULL; 453 aim_rxcallback_t userfunc; 454 int curcount = 0, ret = 0; 455 456 while (aim_bstream_empty(bs)) { 457 curcount++; 458 userinfo = realloc(userinfo, curcount * sizeof(aim_userinfo_t)); 459 aim_extractuserinfo(sess, bs, &userinfo[curcount-1]); 460 } 461 462 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 463 ret = userfunc(sess, rx, curcount, userinfo); 464 465 free(userinfo); 466 467 return ret; 468 } 469 470 /* 471 * Subtype 0x0005 - Send a Chat Message. 111 472 * 112 473 * Possible flags: … … 204 565 } 205 566 206 static int aim_addtlvtochain_chatroom(aim_tlvlist_t **list, fu16_t type, fu16_t exchange, const char *roomname, fu16_t instance)207 {208 fu8_t *buf;209 int buflen;210 aim_bstream_t bs;211 212 buflen = 2 + 1 + strlen(roomname) + 2;213 214 if (!(buf = malloc(buflen)))215 return 0;216 217 aim_bstream_init(&bs, buf, buflen);218 219 aimbs_put16(&bs, exchange);220 aimbs_put8(&bs, strlen(roomname));221 aimbs_putraw(&bs, roomname, strlen(roomname));222 aimbs_put16(&bs, instance);223 224 aim_addtlvtochain_raw(list, type, aim_bstream_curpos(&bs), buf);225 226 free(buf);227 228 return 0;229 }230 231 567 /* 232 * Join a room of name roomname. This is the first step to joining an 233 * already created room. It's basically a Service Request for 234 * family 0x000e, with a little added on to specify the exchange and room 235 * name. 236 */ 237 faim_export int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, fu16_t exchange, const char *roomname, fu16_t instance) 238 { 239 aim_frame_t *fr; 240 aim_snacid_t snacid; 241 aim_tlvlist_t *tl = NULL; 242 struct chatsnacinfo csi; 243 244 if (!sess || !conn || !roomname || !strlen(roomname)) 245 return -EINVAL; 246 247 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512))) 248 return -ENOMEM; 249 250 memset(&csi, 0, sizeof(csi)); 251 csi.exchange = exchange; 252 strncpy(csi.name, roomname, sizeof(csi.name)); 253 csi.instance = instance; 254 255 snacid = aim_cachesnac(sess, 0x0001, 0x0004, 0x0000, &csi, sizeof(csi)); 256 aim_putsnac(&fr->data, 0x0001, 0x0004, 0x0000, snacid); 257 258 /* 259 * Requesting service chat (0x000e) 260 */ 261 aimbs_put16(&fr->data, 0x000e); 262 263 aim_addtlvtochain_chatroom(&tl, 0x0001, exchange, roomname, instance); 264 aim_writetlvchain(&fr->data, &tl); 265 aim_freetlvchain(&tl); 266 267 aim_tx_enqueue(sess, fr); 268 269 return 0; 270 } 271 272 faim_internal int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo) 273 { 274 int namelen; 275 276 if (!bs || !outinfo) 277 return 0; 278 279 outinfo->exchange = aimbs_get16(bs); 280 namelen = aimbs_get8(bs); 281 outinfo->name = aimbs_getstr(bs, namelen); 282 outinfo->instance = aimbs_get16(bs); 283 284 return 0; 285 } 286 287 faim_export int aim_chat_leaveroom(aim_session_t *sess, const char *name) 288 { 289 aim_conn_t *conn; 290 291 if (!(conn = aim_chat_getconn(sess, name))) 292 return -ENOENT; 293 294 aim_conn_close(conn); 295 296 return 0; 297 } 298 299 /* 300 * conn must be a BOS connection! 301 */ 302 faim_export int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *msg, fu16_t exchange, const char *roomname, fu16_t instance) 303 { 304 int i; 305 aim_frame_t *fr; 306 aim_msgcookie_t *cookie; 307 struct aim_invite_priv *priv; 308 fu8_t ckstr[8]; 309 aim_snacid_t snacid; 310 aim_tlvlist_t *otl = NULL, *itl = NULL; 311 fu8_t *hdr; 312 int hdrlen; 313 aim_bstream_t hdrbs; 314 315 if (!sess || !conn || !sn || !msg || !roomname) 316 return -EINVAL; 317 318 if (conn->type != AIM_CONN_TYPE_BOS) 319 return -EINVAL; 320 321 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152+strlen(sn)+strlen(roomname)+strlen(msg)))) 322 return -ENOMEM; 323 324 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, sn, strlen(sn)+1); 325 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); 326 327 328 /* 329 * Cookie 330 */ 331 for (i = 0; i < sizeof(ckstr); i++) 332 aimutil_put8(ckstr, (fu8_t) rand()); 333 334 /* XXX should be uncached by an unwritten 'invite accept' handler */ 335 if ((priv = malloc(sizeof(struct aim_invite_priv)))) { 336 priv->sn = strdup(sn); 337 priv->roomname = strdup(roomname); 338 priv->exchange = exchange; 339 priv->instance = instance; 340 } 341 342 if ((cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_INVITE, priv))) 343 aim_cachecookie(sess, cookie); 344 else 345 free(priv); 346 347 for (i = 0; i < sizeof(ckstr); i++) 348 aimbs_put8(&fr->data, ckstr[i]); 349 350 351 /* 352 * Channel (2) 353 */ 354 aimbs_put16(&fr->data, 0x0002); 355 356 /* 357 * Dest sn 358 */ 359 aimbs_put8(&fr->data, strlen(sn)); 360 aimbs_putraw(&fr->data, sn, strlen(sn)); 361 362 /* 363 * TLV t(0005) 364 * 365 * Everything else is inside this TLV. 366 * 367 * Sigh. AOL was rather inconsistent right here. So we have 368 * to play some minor tricks. Right inside the type 5 is some 369 * raw data, followed by a series of TLVs. 370 * 371 */ 372 hdrlen = 2+8+16+6+4+4+strlen(msg)+4+2+1+strlen(roomname)+2; 373 hdr = malloc(hdrlen); 374 aim_bstream_init(&hdrbs, hdr, hdrlen); 375 376 aimbs_put16(&hdrbs, 0x0000); /* Unknown! */ 377 aimbs_putraw(&hdrbs, ckstr, sizeof(ckstr)); /* I think... */ 378 aim_putcap(&hdrbs, AIM_CAPS_CHAT); 379 380 aim_addtlvtochain16(&itl, 0x000a, 0x0001); 381 aim_addtlvtochain_noval(&itl, 0x000f); 382 aim_addtlvtochain_raw(&itl, 0x000c, strlen(msg), msg); 383 aim_addtlvtochain_chatroom(&itl, 0x2711, exchange, roomname, instance); 384 aim_writetlvchain(&hdrbs, &itl); 385 386 aim_addtlvtochain_raw(&otl, 0x0005, aim_bstream_curpos(&hdrbs), hdr); 387 388 aim_writetlvchain(&fr->data, &otl); 389 390 free(hdr); 391 aim_freetlvchain(&itl); 392 aim_freetlvchain(&otl); 393 394 aim_tx_enqueue(sess, fr); 395 396 return 0; 397 } 398 399 /* 400 * General room information. Lots of stuff. 568 * Subtype 0x0006 401 569 * 402 * Values I know are in here but I havent attached403 * them to any of the 'Unknown's:404 * - Language (English)405 *406 * SNAC 000e/0002407 */408 static int infoupdate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)409 {410 aim_userinfo_t *userinfo = NULL;411 aim_rxcallback_t userfunc;412 int ret = 0;413 int usercount = 0;414 fu8_t detaillevel = 0;415 char *roomname = NULL;416 struct aim_chat_roominfo roominfo;417 fu16_t tlvcount = 0;418 aim_tlvlist_t *tlvlist;419 char *roomdesc = NULL;420 fu16_t flags = 0;421 fu32_t creationtime = 0;422 fu16_t maxmsglen = 0, maxvisiblemsglen = 0;423 fu16_t unknown_d2 = 0, unknown_d5 = 0;424 425 dumpbox(sess, bs->data + bs->offset, aim_bstream_empty(bs));426 427 aim_chat_readroominfo(bs, &roominfo);428 429 detaillevel = aimbs_get8(bs);430 431 if (detaillevel != 0x02) {432 faimdprintf(sess, 0, "faim: chat_roomupdateinfo: detail level %d not supported\n", detaillevel);433 return 1;434 }435 436 tlvcount = aimbs_get16(bs);437 438 /*439 * Everything else are TLVs.440 */441 tlvlist = aim_readtlvchain(bs);442 443 /*444 * TLV type 0x006a is the room name in Human Readable Form.445 */446 if (aim_gettlv(tlvlist, 0x006a, 1))447 roomname = aim_gettlv_str(tlvlist, 0x006a, 1);448 449 /*450 * Type 0x006f: Number of occupants.451 */452 if (aim_gettlv(tlvlist, 0x006f, 1))453 usercount = aim_gettlv16(tlvlist, 0x006f, 1);454 455 /*456 * Type 0x0073: Occupant list.457 */458 if (aim_gettlv(tlvlist, 0x0073, 1)) {459 int curoccupant = 0;460 aim_tlv_t *tmptlv;461 aim_bstream_t occbs;462 463 tmptlv = aim_gettlv(tlvlist, 0x0073, 1);464 465 /* Allocate enough userinfo structs for all occupants */466 userinfo = calloc(usercount, sizeof(aim_userinfo_t));467 468 aim_bstream_init(&occbs, tmptlv->value, tmptlv->length);469 470 while (curoccupant < usercount)471 aim_extractuserinfo(sess, &occbs, &userinfo[curoccupant++]);472 }473 474 /*475 * Type 0x00c9: Flags. (AIM_CHATROOM_FLAG)476 */477 if (aim_gettlv(tlvlist, 0x00c9, 1))478 flags = aim_gettlv16(tlvlist, 0x00c9, 1);479 480 /*481 * Type 0x00ca: Creation time (4 bytes)482 */483 if (aim_gettlv(tlvlist, 0x00ca, 1))484 creationtime = aim_gettlv32(tlvlist, 0x00ca, 1);485 486 /*487 * Type 0x00d1: Maximum Message Length488 */489 if (aim_gettlv(tlvlist, 0x00d1, 1))490 maxmsglen = aim_gettlv16(tlvlist, 0x00d1, 1);491 492 /*493 * Type 0x00d2: Unknown. (2 bytes)494 */495 if (aim_gettlv(tlvlist, 0x00d2, 1))496 unknown_d2 = aim_gettlv16(tlvlist, 0x00d2, 1);497 498 /*499 * Type 0x00d3: Room Description500 */501 if (aim_gettlv(tlvlist, 0x00d3, 1))502 roomdesc = aim_gettlv_str(tlvlist, 0x00d3, 1);503 504 /*505 * Type 0x000d4: Unknown (flag only)506 */507 if (aim_gettlv(tlvlist, 0x000d4, 1))508 ;509 510 /*511 * Type 0x00d5: Unknown. (1 byte)512 */513 if (aim_gettlv(tlvlist, 0x00d5, 1))514 unknown_d5 = aim_gettlv8(tlvlist, 0x00d5, 1);515 516 517 /*518 * Type 0x00d6: Encoding 1 ("us-ascii")519 */520 if (aim_gettlv(tlvlist, 0x000d6, 1))521 ;522 523 /*524 * Type 0x00d7: Language 1 ("en")525 */526 if (aim_gettlv(tlvlist, 0x000d7, 1))527 ;528 529 /*530 * Type 0x00d8: Encoding 2 ("us-ascii")531 */532 if (aim_gettlv(tlvlist, 0x000d8, 1))533 ;534 535 /*536 * Type 0x00d9: Language 2 ("en")537 */538 if (aim_gettlv(tlvlist, 0x000d9, 1))539 ;540 541 /*542 * Type 0x00da: Maximum visible message length543 */544 if (aim_gettlv(tlvlist, 0x000da, 1))545 maxvisiblemsglen = aim_gettlv16(tlvlist, 0x00da, 1);546 547 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {548 ret = userfunc(sess,549 rx,550 &roominfo,551 roomname,552 usercount,553 userinfo,554 roomdesc,555 flags,556 creationtime,557 maxmsglen,558 unknown_d2,559 unknown_d5,560 maxvisiblemsglen);561 }562 563 free(roominfo.name);564 free(userinfo);565 free(roomname);566 free(roomdesc);567 aim_freetlvchain(&tlvlist);568 569 return ret;570 }571 572 static int userlistchange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)573 {574 aim_userinfo_t *userinfo = NULL;575 aim_rxcallback_t userfunc;576 int curcount = 0, ret = 0;577 578 while (aim_bstream_empty(bs)) {579 curcount++;580 userinfo = realloc(userinfo, curcount * sizeof(aim_userinfo_t));581 aim_extractuserinfo(sess, bs, &userinfo[curcount-1]);582 }583 584 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))585 ret = userfunc(sess, rx, curcount, userinfo);586 587 free(userinfo);588 589 return ret;590 }591 592 /*593 570 * We could probably include this in the normal ICBM parsing 594 571 * code as channel 0x0003, however, since only the start … … 734 711 return 0; 735 712 } 736 737 -
libfaim/chatnav.c
r5e53c4a r862371b 1 1 /* 2 * Handle ChatNav.3 * 4 * [The ChatNav(igation) service does various things to keep chat5 * alive. It provides room information, room searching and creating,6 * as well as giving users the right ("permission") to use chat.]2 * Family 0x000d - Handle ChatNav. 3 * 4 * The ChatNav(igation) service does various things to keep chat 5 * alive. It provides room information, room searching and creating, 6 * as well as giving users the right ("permission") to use chat. 7 7 * 8 8 */ … … 12 12 13 13 /* 14 * Subtype 0x0002 15 * 14 16 * conn must be a chatnav connection! 17 * 15 18 */ 16 19 faim_export int aim_chatnav_reqrights(aim_session_t *sess, aim_conn_t *conn) … … 19 22 } 20 23 24 /* 25 * Subtype 0x0008 26 */ 21 27 faim_export int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *name, fu16_t exchange) 22 28 { … … 346 352 347 353 /* 354 * Subtype 0x0009 355 * 348 356 * Since multiple things can trigger this callback, we must lookup the 349 357 * snacid to determine the original snac subtype that was called. … … 416 424 417 425 mod->family = 0x000d; 418 mod->version = 0x000 1;426 mod->version = 0x0003; 419 427 mod->toolid = 0x0010; 420 428 mod->toolversion = 0x047c; -
libfaim/conn.c
r5e53c4a r862371b 1 2 1 /* 3 2 * conn.c … … 15 14 #include <sys/socket.h> 16 15 #include <netinet/in.h> 16 #endif 17 18 #ifdef _WIN32 19 #include "win32dep.h" 17 20 #endif 18 21 … … 446 449 i = 3; 447 450 } 448 449 451 if (write(fd, buf, i) < i) { 450 452 *statusret = errno; … … 452 454 return -1; 453 455 } 454 455 456 if (read(fd, buf, 2) < 2) { 456 457 *statusret = errno; … … 502 503 return -1; 503 504 } 505 504 506 if (read(fd, buf, 10) < 10) { 505 507 *statusret = errno; … … 877 879 sess->modlistv = NULL; 878 880 881 sess->ssi.received_data = 0; 882 sess->ssi.waiting_for_ack = 0; 883 sess->ssi.holding_queue = NULL; 884 sess->ssi.revision = 0; 885 sess->ssi.items = NULL; 886 sess->ssi.timestamp = (time_t)0; 887 888 sess->emailinfo = NULL; 889 879 890 /* 880 891 * Default to SNAC login unless XORLOGIN is explicitly set. … … 909 920 aim__registermodule(sess, chatnav_modfirst); 910 921 aim__registermodule(sess, chat_modfirst); 911 /* missing 0x0f - 0x12 */ 922 aim__registermodule(sess, newsearch_modfirst); 923 /* missing 0x10 - 0x12 */ 912 924 aim__registermodule(sess, ssi_modfirst); 913 925 /* missing 0x14 */ 914 aim__registermodule(sess, icq_modfirst); 926 aim__registermodule(sess, icq_modfirst); /* XXX - Make sure this isn't sent for AIM */ 915 927 /* missing 0x16 */ 916 928 aim__registermodule(sess, auth_modfirst); 929 aim__registermodule(sess, email_modfirst); 917 930 918 931 return; … … 981 994 fd_set fds, wfds; 982 995 struct timeval tv; 983 int res, error = ETIMEDOUT; 996 int res; 997 int error = ETIMEDOUT; 998 984 999 aim_rxcallback_t userfunc; 985 1000 … … 1009 1024 if (FD_ISSET(conn->fd, &fds) || FD_ISSET(conn->fd, &wfds)) { 1010 1025 int len = sizeof(error); 1011 1012 1026 if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) 1013 1027 error = errno; … … 1019 1033 return -1; 1020 1034 } 1021 1022 1035 fcntl(conn->fd, F_SETFL, 0); /* XXX should restore original flags */ 1023 1036 … … 1054 1067 1055 1068 return 0; 1056 1057 1069 } 1058 1070 … … 1061 1073 * 1062 1074 * No-op. WinAIM 4.x sends these _every minute_ to keep 1063 * the connection alive. 1075 * the connection alive. 1064 1076 */ 1065 1077 faim_export int aim_flap_nop(aim_session_t *sess, aim_conn_t *conn) … … 1074 1086 return 0; 1075 1087 } 1076 1077 -
libfaim/ft.c
r5e53c4a r862371b 10 10 #endif 11 11 #include <aim.h> 12 13 12 14 13 #ifndef _WIN32 … … 17 16 #include <netinet/in.h> 18 17 #include <sys/utsname.h> /* for aim_directim_initiate */ 19 20 18 #include <arpa/inet.h> /* for inet_ntoa */ 21 19 #define G_DIR_SEPARATOR '/' 22 20 #endif 23 21 24 /* TODO: 25 o look for memory leaks.. there's going to be shitloads, i'm sure. 26 */ 22 #ifdef _WIN32 23 #include "win32dep.h" 24 #endif 25 26 #define AIM_OFT_PROTO_OFFER 0x0101 27 #define AIM_OFT_PROTO_ACCEPT 0x0202 28 #define AIM_OFT_PROTO_RESUME 0x0205 29 #define AIM_OFT_PROTO_RESUMEACCEPT 0x0207 30 #define AIM_OFT_PROTO_ACK 0x0204 31 32 struct aim_filetransfer_priv { 33 char sn[MAXSNLEN+1]; 34 char cookie[8]; 35 char ip[30]; 36 int state; 37 struct aim_fileheader_t fh; 38 }; 27 39 28 40 struct aim_directim_intdata { … … 33 45 34 46 static int listenestablish(fu16_t portnum); 47 static struct aim_fileheader_t *aim_oft_getfh(aim_bstream_t *bs); 48 static void oft_dirconvert(char *name); 49 static int aim_oft_buildheader(aim_bstream_t *bs, struct aim_fileheader_t *fh); 35 50 36 51 /** … … 90 105 aim_rxcallback_t userfunc; 91 106 92 93 107 newconn->priv = cur->priv; 94 108 cur->priv = NULL; … … 100 114 ret = userfunc(sess, NULL, newconn, cur); 101 115 #endif 116 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) { 117 struct aim_filetransfer_priv *ft; 118 aim_rxcallback_t userfunc; 119 120 /* The new conn automatically inherits the internal value 121 * of cur. */ 122 cur->internal = NULL; 123 ft = (struct aim_filetransfer_priv *)newconn->internal; 124 125 snprintf(ft->ip, sizeof(ft->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port)); 126 127 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_SENDFILEINITIATE))) 128 ret = userfunc(sess, NULL, newconn, cur); 102 129 } else { 103 130 faimdprintf(sess, 1,"Got a Connection on a listener that's not Rendezvous Closing conn.\n"); … … 110 137 111 138 /** 139 * aim_send_typing - send client-to-client typing notification over established connection 140 * @sess: session to conn 141 * @conn: directim connection 142 * @typing: If true, notify user has started typing; if false, notify user has stopped. 143 * 144 * The connection must have been previously established. 145 */ 146 faim_export int aim_send_typing(aim_session_t *sess, aim_conn_t *conn, int typing) 147 { 148 struct aim_directim_intdata *intdata = (struct aim_directim_intdata *)conn->internal; 149 aim_frame_t *fr; 150 aim_bstream_t *hdrbs; 151 fu8_t *hdr; 152 int hdrlen = 0x44; 153 154 if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS)) 155 return -EINVAL; 156 157 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x01, 0))) 158 return -ENOMEM; 159 memcpy(fr->hdr.rend.magic, "ODC2", 4); 160 fr->hdr.rend.hdrlen = hdrlen; 161 162 if (!(hdr = calloc(1, hdrlen))) { 163 aim_frame_destroy(fr); 164 return -ENOMEM; 165 } 166 167 hdrbs = &(fr->data); 168 aim_bstream_init(hdrbs, hdr, hdrlen); 169 170 aimbs_put16(hdrbs, 0x0006); 171 aimbs_put16(hdrbs, 0x0000); 172 aimbs_putraw(hdrbs, intdata->cookie, 8); 173 aimbs_put16(hdrbs, 0x0000); 174 aimbs_put16(hdrbs, 0x0000); 175 aimbs_put16(hdrbs, 0x0000); 176 aimbs_put16(hdrbs, 0x0000); 177 aimbs_put32(hdrbs, 0x00000000); 178 aimbs_put16(hdrbs, 0x0000); 179 aimbs_put16(hdrbs, 0x0000); 180 aimbs_put16(hdrbs, 0x0000); 181 182 /* flags -- 0x000e for "started typing", 0x0002 for "stopped typing */ 183 aimbs_put16(hdrbs, ( typing ? 0x000e : 0x0002)); 184 185 aimbs_put16(hdrbs, 0x0000); 186 aimbs_put16(hdrbs, 0x0000); 187 aimbs_putraw(hdrbs, sess->sn, strlen(sess->sn)); 188 189 aim_bstream_setpos(hdrbs, 52); /* bleeehh */ 190 191 aimbs_put8(hdrbs, 0x00); 192 aimbs_put16(hdrbs, 0x0000); 193 aimbs_put16(hdrbs, 0x0000); 194 aimbs_put16(hdrbs, 0x0000); 195 aimbs_put16(hdrbs, 0x0000); 196 aimbs_put16(hdrbs, 0x0000); 197 aimbs_put16(hdrbs, 0x0000); 198 aimbs_put16(hdrbs, 0x0000); 199 aimbs_put8(hdrbs, 0x00); 200 201 /* end of hdr */ 202 203 aim_tx_enqueue(sess, fr); 204 205 return 0; 206 } 207 208 /** 112 209 * aim_send_im_direct - send IM client-to-client over established connection 113 210 * @sess: session to conn 114 211 * @conn: directim connection 115 * @msg: null-terminated string to send; if this is NULL, it will send a "typing" notice. 116 * 212 * @msg: null-terminated string to send. 213 * @len: The length of the message to send, including binary data. 214 * @encoding: 0 for ascii, 2 for Unicode, 3 for ISO 8859-1 215 * 117 216 * Call this just like you would aim_send_im, to send a directim. You 118 217 * _must_ have previously established the directim connection. 119 218 */ 120 faim_export int aim_send_im_direct(aim_session_t *sess, aim_conn_t *conn, const char *msg )219 faim_export int aim_send_im_direct(aim_session_t *sess, aim_conn_t *conn, const char *msg, int len, int encoding) 121 220 { 122 221 struct aim_directim_intdata *intdata = (struct aim_directim_intdata *)conn->internal; 123 222 aim_frame_t *fr; 124 aim_bstream_t hdrbs; /* XXX this should be within aim_frame_t */ 125 126 if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS)) 223 aim_bstream_t *hdrbs; 224 int hdrlen = 0x44; 225 fu8_t *hdr; 226 227 if (!sess || !conn || !msg || (conn->type != AIM_CONN_TYPE_RENDEZVOUS)) 127 228 return -EINVAL; 128 229 129 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x01, strlen(msg)))) 130 return -ENOMEM; 131 132 memcpy(fr->hdr.oft.magic, "ODC2", 4); 230 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x01, len))) 231 return -ENOMEM; 232 233 memcpy(fr->hdr.rend.magic, "ODC2", 4); 234 fr->hdr.rend.hdrlen = hdrlen; 133 235 134 fr->hdr.oft.hdr2len = 0x44; 135 136 if (!(fr->hdr.oft.hdr2 = calloc(1, fr->hdr.oft.hdr2len))) { 236 if (!(hdr = calloc(1, hdrlen + len))) { 137 237 aim_frame_destroy(fr); 138 238 return -ENOMEM; 139 239 } 240 241 hdrbs = &(fr->data); 242 aim_bstream_init(hdrbs, hdr, hdrlen + len); 243 244 aimbs_put16(hdrbs, 0x0006); 245 aimbs_put16(hdrbs, 0x0000); 246 aimbs_putraw(hdrbs, intdata->cookie, 8); 247 aimbs_put16(hdrbs, 0x0000); 248 aimbs_put16(hdrbs, 0x0000); 249 aimbs_put16(hdrbs, 0x0000); 250 aimbs_put16(hdrbs, 0x0000); 251 aimbs_put32(hdrbs, len); 252 aimbs_put16(hdrbs, encoding); 253 aimbs_put16(hdrbs, 0x0000); 254 aimbs_put16(hdrbs, 0x0000); 140 255 141 aim_bstream_init(&hdrbs, fr->hdr.oft.hdr2, fr->hdr.oft.hdr2len); 142 143 aimbs_put16(&hdrbs, 0x0006); 144 aimbs_put16(&hdrbs, 0x0000); 145 aimbs_putraw(&hdrbs, intdata->cookie, 8); 146 aimbs_put16(&hdrbs, 0x0000); 147 aimbs_put16(&hdrbs, 0x0000); 148 aimbs_put16(&hdrbs, 0x0000); 149 aimbs_put16(&hdrbs, 0x0000); 150 aimbs_put32(&hdrbs, strlen(msg)); 151 aimbs_put16(&hdrbs, 0x0000); 152 aimbs_put16(&hdrbs, 0x0000); 153 aimbs_put16(&hdrbs, 0x0000); 154 155 /* flags -- 0x000e for "typing", 0x0000 for message */ 156 aimbs_put16(&hdrbs, msg ? 0x0000 : 0x000e); 157 158 aimbs_put16(&hdrbs, 0x0000); 159 aimbs_put16(&hdrbs, 0x0000); 160 aimbs_putraw(&hdrbs, sess->sn, strlen(sess->sn)); 161 162 aim_bstream_setpos(&hdrbs, 52); /* bleeehh */ 163 164 aimbs_put8(&hdrbs, 0x00); 165 aimbs_put16(&hdrbs, 0x0000); 166 aimbs_put16(&hdrbs, 0x0000); 167 aimbs_put16(&hdrbs, 0x0000); 168 aimbs_put16(&hdrbs, 0x0000); 169 aimbs_put16(&hdrbs, 0x0000); 170 aimbs_put16(&hdrbs, 0x0000); 171 aimbs_put16(&hdrbs, 0x0000); 172 256 /* flags -- 0x000e for "started typing", 0x0002 for "stopped typing, 0x0000 for message */ 257 aimbs_put16(hdrbs, 0x0000); 258 259 aimbs_put16(hdrbs, 0x0000); 260 aimbs_put16(hdrbs, 0x0000); 261 aimbs_putraw(hdrbs, sess->sn, strlen(sess->sn)); 262 263 aim_bstream_setpos(hdrbs, 52); /* bleeehh */ 264 265 aimbs_put8(hdrbs, 0x00); 266 aimbs_put16(hdrbs, 0x0000); 267 aimbs_put16(hdrbs, 0x0000); 268 aimbs_put16(hdrbs, 0x0000); 269 aimbs_put16(hdrbs, 0x0000); 270 aimbs_put16(hdrbs, 0x0000); 271 aimbs_put16(hdrbs, 0x0000); 272 aimbs_put16(hdrbs, 0x0000); 273 aimbs_put8(hdrbs, 0x00); 274 173 275 /* end of hdr2 */ 174 175 if (msg) { 276 176 277 #if 0 /* XXX this is how you send buddy icon info... */ 177 178 179 180 181 182 183 184 278 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0008); 279 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x000c); 280 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); 281 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x1466); 282 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0001); 283 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x2e0f); 284 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x393e); 285 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0xcac8); 185 286 #endif 186 aimbs_putraw(&fr->data, msg, strlen(msg)); 187 } 188 287 aimbs_putraw(hdrbs, msg, len); 288 189 289 aim_tx_enqueue(sess, fr); 190 290 191 291 return 0; 192 292 } … … 279 379 * 280 380 */ 281 faim_export aim_conn_t *aim_sendfile_initiate(aim_session_t *sess, const char *destsn, const char *filename, fu16_t numfiles, fu32_t totsize )381 faim_export aim_conn_t *aim_sendfile_initiate(aim_session_t *sess, const char *destsn, const char *filename, fu16_t numfiles, fu32_t totsize, char *cookret) 282 382 { 283 383 aim_conn_t *newconn; 284 384 aim_msgcookie_t *cookie; 285 struct aim_ directim_intdata *priv;385 struct aim_filetransfer_priv *ft; 286 386 int listenfd; 387 388 /* XXX allow different ports */ 287 389 fu16_t port = 4443; 288 390 fu8_t localip[4]; … … 299 401 cookie = (aim_msgcookie_t *)calloc(1, sizeof(aim_msgcookie_t)); 300 402 memcpy(cookie->cookie, ck, 8); 301 cookie->type = AIM_COOKIETYPE_OFTIM; 403 cookie->type = AIM_COOKIETYPE_OFTSEND; 404 memcpy(cookret, ck, 8); 302 405 303 406 /* this one is for the cookie */ 304 priv = (struct aim_directim_intdata *)calloc(1, sizeof(struct aim_directim_intdata));305 306 memcpy( priv->cookie, ck, 8);307 strncpy( priv->sn, destsn, sizeof(priv->sn));308 cookie->data = priv;407 ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)); 408 409 memcpy(ft->cookie, ck, 8); 410 strncpy(ft->sn, destsn, sizeof(ft->sn)); 411 cookie->data = ft; 309 412 aim_cachecookie(sess, cookie); 310 413 311 /* XXX switch to aim_cloneconn()? */312 414 if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL))) { 313 415 close(listenfd); … … 316 418 317 419 /* this one is for the conn */ 318 priv = (struct aim_directim_intdata *)calloc(1, sizeof(struct aim_directim_intdata));319 320 memcpy( priv->cookie, ck, 8);321 strncpy( priv->sn, destsn, sizeof(priv->sn));420 ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)); 421 422 memcpy(ft->cookie, ck, 8); 423 strncpy(ft->sn, destsn, sizeof(ft->sn)); 322 424 323 425 newconn->fd = listenfd; 324 426 newconn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE; 325 newconn->internal = priv;427 newconn->internal = ft; 326 428 newconn->lastactivity = time(NULL); 327 429 … … 335 437 * unsigned int aim_oft_listener_clean - close up old listeners 336 438 * @sess: session to clean up in 337 * @age: maximum age in seconds 439 * @age: maximum age in seconds 338 440 * 339 441 * returns number closed, -1 on error. 340 442 */ 341 faim_export unsigned int aim_oft_listener_clean(struct aim_session_t *sess, time_t age) 342 { 343 struct aim_conn_t *cur; 344 time_t now; 345 unsigned int hit = 0; 346 347 if (!sess) 348 return -1; 349 now = time(NULL); 350 faim_mutex_lock(&sess->connlistlock); 351 for(cur = sess->connlist;cur; cur = cur->next) 352 if (cur->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) { 353 faim_mutex_lock(&cur->active); 354 if (cur->lastactivity < (now - age) ) { 355 faim_mutex_unlock(&cur->active); 356 aim_conn_close(cur); 357 hit++; 358 } else 359 faim_mutex_unlock(&cur->active); 360 } 361 faim_mutex_unlock(&sess->connlistlock); 362 return hit; 363 } 364 #endif 443 faim_export unsigned int aim_oft_listener_clean(aim_session_t *sess, time_t age) 444 { 445 aim_conn_t *cur; 446 time_t now; 447 unsigned int hit = 0; 448 449 if (!sess) 450 return -1; 451 now = time(NULL); 452 453 for(cur = sess->connlist;cur; cur = cur->next) 454 if (cur->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) { 455 if (cur->lastactivity < (now - age) ) { 456 aim_conn_close(cur); 457 hit++; 458 } 459 } 460 return hit; 461 } 462 #endif 365 463 366 464 faim_export const char *aim_directim_getsn(aim_conn_t *conn) … … 369 467 370 468 if (!conn) 371 469 return NULL; 372 470 373 471 if ((conn->type != AIM_CONN_TYPE_RENDEZVOUS) || 374 472 (conn->subtype != AIM_CONN_SUBTYPE_OFT_DIRECTIM)) 375 473 return NULL; 376 474 377 475 if (!conn->internal) … … 432 530 * aim_directim_getconn - find a directim conn for buddy name 433 531 * @sess: your session, 434 * @name: the name to get, 532 * @name: the name to get, 435 533 * 436 534 * returns conn for directim with name, %NULL if none found. … … 466 564 * @cookie: the cookie used 467 565 * @ip: the ip to connect to 566 * @port: the port to use 567 * @rendid: capability type (%AIM_CAPS_GETFILE or %AIM_CAPS_SENDFILE) 568 * 468 569 * @listingfiles: number of files to share 469 570 * @listingtotsize: total size of shared files 470 571 * @listingsize: length of the listing file(buffer) 471 572 * @listingchecksum: checksum of the listing 472 * @rendid: capability type (%AIM_CAPS_GETFILE or %AIM_CAPS_SENDFILE)473 573 * 474 574 * Returns new connection or %NULL on error. … … 476 576 * XXX this should take a struct. 477 577 */ 478 faim_export aim_conn_t *aim_accepttransfer(aim_session_t *sess, 479 aim_conn_t *conn, 480 const char *sn, const fu8_t *cookie, 481 const fu8_t *ip, 482 fu16_t listingfiles, 483 fu16_t listingtotsize, 484 fu16_t listingsize, 485 fu32_t listingchecksum, 486 fu16_t rendid) 487 { 488 return NULL; 578 faim_export aim_conn_t *aim_accepttransfer(aim_session_t *sess, aim_conn_t *conn, const char *sn, 579 const fu8_t *cookie, const fu8_t *ip, 580 fu16_t port, fu16_t rendid, ...) 581 { 582 aim_frame_t *newpacket; 583 aim_conn_t *newconn; 584 struct aim_filetransfer_priv *priv; 585 int i; 586 char addr[21]; 587 588 if (!sess || !conn || !sn || !cookie || !ip) { 589 return NULL; 590 } 591 592 /* OSCAR CAP accept packet */ 593 594 if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x0002, 10+8+2+1+strlen(sn)+4+2+8+16))) { 595 return NULL; 596 } 597 598 aim_putsnac(&newpacket->data, 0x0004, 0x0006, 0x0000, sess->snacid_next); 599 600 for (i = 0; i < 8; i++) 601 aimbs_put8(&newpacket->data, cookie[i]); 602 603 aimbs_put16(&newpacket->data, 0x0002); 604 aimbs_put8(&newpacket->data, strlen(sn)); 605 aimbs_putraw(&newpacket->data, sn, strlen(sn)); 606 aimbs_put16(&newpacket->data, 0x0005); 607 aimbs_put16(&newpacket->data, 0x001a); 608 aimbs_put16(&newpacket->data, AIM_RENDEZVOUS_ACCEPT); 609 610 for (i = 0; i < 8; i++) /* yes, again... */ 611 aimbs_put8(&newpacket->data, cookie[i]); 612 613 aim_putcap(&newpacket->data, rendid); 614 aim_tx_enqueue(sess, newpacket); 615 616 snprintf(addr, sizeof(addr), "%s:%d", ip, port); 617 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, addr); 618 619 if (newconn->status & AIM_CONN_STATUS_CONNERR) { 620 return NULL; 621 } 622 623 if (!newconn || (newconn->fd == -1)) { 624 perror("aim_newconn"); 625 faimdprintf(sess, 2, "could not connect to %s (fd: %i)\n", ip, newconn?newconn->fd:0); 626 return newconn; 627 } 628 629 priv = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)); 630 631 memcpy(priv->cookie, cookie, 8); 632 priv->state = 0; 633 strncpy(priv->sn, sn, MAXSNLEN); 634 strncpy(priv->ip, ip, sizeof(priv->ip)); 635 newconn->internal = (void *)priv; 636 637 faimdprintf(sess, 2, "faim: connected to peer (fd = %d)\n", newconn->fd); 638 639 if (rendid == AIM_CAPS_GETFILE) { 640 return NULL; /* This should never happen for now. -- wtm */ 641 489 642 #if 0 490 struct command_tx_struct *newpacket, *newoft; 491 struct aim_conn_t *newconn; 492 struct aim_fileheader_t *fh; 493 struct aim_filetransfer_priv *priv; 494 struct aim_msgcookie_t *cachedcook; 495 int curbyte, i; 496 497 if (!sess || !conn || !sn || !cookie || !ip) { 498 return NULL; 499 } 500 501 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, ip); 502 503 if (!newconn || (newconn->fd == -1)) { 504 perror("aim_newconn"); 505 faimdprintf(sess, 2, "could not connect to %s (fd: %i)\n", ip, newconn?newconn->fd:0); 506 return newconn; 507 } else { 508 priv = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)); 509 510 memcpy(priv->cookie, cookie, 8); 511 priv->state = 0; 512 strncpy(priv->sn, sn, MAXSNLEN); 513 strncpy(priv->ip, ip, sizeof(priv->ip)); 514 newconn->priv = (void *)priv; 515 516 faimdprintf(sess, 2, "faim: connected to peer (fd = %d)\n", newconn->fd); 517 } 518 519 if (rendid == AIM_CAPS_GETFILE) { 520 newconn->subtype = AIM_CONN_SUBTYPE_OFT_GETFILE; 521 522 faimdprintf(sess, 2, "faim: getfile request accept\n"); 523 524 if (!(newoft = aim_tx_new(sess, newconn, AIM_FRAMETYPE_OFT, 0x1108, 0))) { 525 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n"); 526 /* XXX: conn leak here */ 527 return NULL; 528 } 529 530 newoft->lock = 1; 531 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 532 newoft->hdr.oft.hdr2len = 0x100 - 8; 533 534 if (!(fh = (struct aim_fileheader_t*)calloc(1, sizeof(struct aim_fileheader_t)))) { 535 /* XXX: conn leak here */ 536 perror("calloc"); 537 return NULL; 538 } 539 540 fh->encrypt = 0x0000; 541 fh->compress = 0x0000; 542 fh->totfiles = listingfiles; 543 fh->filesleft = listingfiles; /* is this right -- total parts and parts left?*/ 544 fh->totparts = 0x0001; 545 fh->partsleft = 0x0001; 546 fh->totsize = listingtotsize; 547 fh->size = listingsize; /* ls -l listing.txt */ 548 fh->modtime = (int)time(NULL); /* we'll go with current time for now */ 549 fh->checksum = listingchecksum; 550 fh->rfcsum = 0x00000000; 551 fh->rfsize = 0x00000000; 552 fh->cretime = 0x00000000; 553 fh->rfcsum = 0x00000000; 554 fh->nrecvd = 0x00000000; 555 fh->recvcsum = 0x00000000; 556 memset(fh->idstring, 0, sizeof(fh->idstring)); 557 memcpy(fh->idstring, "OFT_Windows ICBMFT V1.1 32", sizeof(fh->idstring)); 558 fh->flags = 0x02; 559 fh->lnameoffset = 0x1a; 560 fh->lsizeoffset = 0x10; 561 memset(fh->dummy, 0, sizeof(fh->dummy)); 562 memset(fh->macfileinfo, 0, sizeof(fh->macfileinfo)); 563 564 /* we need to figure out these encodings for filenames */ 565 fh->nencode = 0x0000; 566 fh->nlanguage = 0x0000; 567 memset(fh->name, 0, sizeof(fh->name)); 568 memcpy(fh->name, "listing.txt", sizeof(fh->name)); 569 570 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { 571 newoft->lock = 0; 572 aim_frame_destroy(newoft); 573 /* XXX: conn leak */ 574 perror("calloc (1)"); 575 return NULL; 576 } 577 578 memcpy(fh->bcookie, cookie, 8); 579 580 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, fh))) 581 faimdprintf(sess, 1, "eek, bh fail!\n"); 582 583 newoft->lock = 0; 584 aim_tx_enqueue(sess, newoft); 585 586 if (!(cachedcook = (struct aim_msgcookie_t *)calloc(1, sizeof(struct aim_msgcookie_t)))) { 587 faimdprintf(sess, 1, "faim: accepttransfer: couldn't calloc cachedcook. yeep!\n"); 588 /* XXX: more cleanup, conn leak */ 589 perror("calloc (2)"); 590 return NULL; 591 } 592 593 memcpy(&(priv->fh), fh, sizeof(struct aim_fileheader_t)); 594 memcpy(cachedcook->cookie, cookie, 8); 595 596 cachedcook->type = AIM_COOKIETYPE_OFTGET; 597 cachedcook->data = (void *)priv; 598 599 if (aim_cachecookie(sess, cachedcook) == -1) 600 faimdprintf(sess, 1, "faim: ERROR caching message cookie\n"); 601 602 free(fh); 603 604 /* OSCAR CAP accept packet */ 605 606 if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+8+2+1+strlen(sn)+4+2+8+16))) { 607 return NULL; 608 } 609 } else { 610 return NULL; 611 } 612 613 newpacket->lock = 1; 614 curbyte = aim_putsnac(newpacket->data, 0x0004, 0x0006, 0x0000, sess->snac_nextid); 615 616 for (i = 0; i < 8; i++) 617 curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]); 618 619 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); 620 curbyte += aimutil_put8(newpacket->data+curbyte, strlen(sn)); 621 curbyte += aimutil_putstr(newpacket->data+curbyte, sn, strlen(sn)); 622 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005); 623 curbyte += aimutil_put16(newpacket->data+curbyte, 0x001a); 624 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002 /* accept*/); 625 626 for (i = 0;i < 8; i++) 627 curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]); 628 629 curbyte += aim_putcap(newpacket->data+curbyte, 0x10, rendid); 630 newpacket->lock = 0; 631 aim_tx_enqueue(sess, newpacket); 632 633 return newconn; 643 struct aim_fileheader_t *fh; 644 aim_frame_t *newoft; 645 aim_msgcookie_t *cachedcook; 646 /* XXX take the following parameters fu16_t listingfiles, 647 fu16_t listingtotsize, 648 fu16_t listingsize, 649 fu32_t listingchecksum, */ 650 651 newconn->subtype = AIM_CONN_SUBTYPE_OFT_GETFILE; 652 653 faimdprintf(sess, 2, "faim: getfile request accept\n"); 654 655 if (!(newoft = aim_tx_new(sess, newconn, AIM_FRAMETYPE_OFT, 0x1108, 0))) { 656 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n"); 657 /* XXX: conn leak here */ 658 return NULL; 659 } 660 661 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 662 newoft->hdr.oft.hdr2len = 0x100 - 8; 663 664 if (!(fh = (struct aim_fileheader_t*)calloc(1, sizeof(struct aim_fileheader_t)))) { 665 /* XXX: conn leak here */ 666 perror("calloc"); 667 return NULL; 668 } 669 670 fh->encrypt = 0x0000; 671 fh->compress = 0x0000; 672 fh->totfiles = listingfiles; 673 fh->filesleft = listingfiles; /* is this right -- total parts and parts left?*/ 674 fh->totparts = 0x0001; 675 fh->partsleft = 0x0001; 676 fh->totsize = listingtotsize; 677 fh->size = listingsize; /* ls -l listing.txt */ 678 fh->modtime = (int)time(NULL); /* we'll go with current time for now */ 679 fh->checksum = listingchecksum; 680 fh->rfcsum = 0x00000000; 681 fh->rfsize = 0x00000000; 682 fh->cretime = 0x00000000; 683 fh->rfcsum = 0x00000000; 684 fh->nrecvd = 0x00000000; 685 fh->recvcsum = 0x00000000; 686 memset(fh->idstring, 0, sizeof(fh->idstring)); 687 strncpy(fh->idstring, "OFT_Windows ICBMFT V1.1 32", sizeof(fh->idstring)); 688 fh->flags = 0x02; 689 fh->lnameoffset = 0x1a; 690 fh->lsizeoffset = 0x10; 691 memset(fh->dummy, 0, sizeof(fh->dummy)); 692 memset(fh->macfileinfo, 0, sizeof(fh->macfileinfo)); 693 694 /* we need to figure out these encodings for filenames */ 695 fh->nencode = 0x0000; 696 fh->nlanguage = 0x0000; 697 memset(fh->name, 0, sizeof(fh->name)); 698 strncpy(fh->name, "listing.txt", sizeof(fh->name)); 699 700 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { 701 aim_frame_destroy(newoft); 702 /* XXX: conn leak */ 703 perror("calloc (1)"); 704 return NULL; 705 } 706 707 memcpy(fh->bcookie, cookie, 8); 708 709 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, fh))) 710 faimdprintf(sess, 1, "eek, bh fail!\n"); 711 712 aim_tx_enqueue(sess, newoft); 713 714 if (!(cachedcook = (aim_msgcookie_t *)calloc(1, sizeof(aim_msgcookie_t)))) { 715 faimdprintf(sess, 1, "faim: accepttransfer: couldn't calloc cachedcook. yeep!\n"); 716 /* XXX: more cleanup, conn leak */ 717 perror("calloc (2)"); 718 return NULL; 719 } 720 721 memcpy(&(priv->fh), fh, sizeof(struct aim_fileheader_t)); 722 memcpy(cachedcook->cookie, cookie, 8); 723 724 cachedcook->type = AIM_COOKIETYPE_OFTGET; 725 /* XXX doesn't priv need to be copied so we don't 726 * double free? -- wtm 727 */ 728 cachedcook->data = (void *)priv; 729 730 if (aim_cachecookie(sess, cachedcook) == -1) 731 faimdprintf(sess, 1, "faim: ERROR caching message cookie\n"); 732 733 free(fh); 634 734 #endif 735 736 } else if (rendid == AIM_CAPS_SENDFILE) { 737 newconn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE; 738 priv->fh.recvcsum = 0xffff0000; 739 } else { 740 return NULL; 741 } 742 743 return newconn; 744 } 745 746 /* conn is a BOS connection over which to send the cancel msg */ 747 faim_export int aim_canceltransfer(aim_session_t *sess, aim_conn_t *conn, 748 const char *cookie, const char *sn, int rendid) 749 { 750 aim_frame_t *newpacket; 751 int i; 752 753 if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x0002, 10+8+2+1+strlen(sn)+4+2+8+16))) { 754 return 1; 755 } 756 757 aim_putsnac(&newpacket->data, 0x0004, 0x0006, 0x0000, sess->snacid_next); 758 759 for (i = 0; i < 8; i++) 760 aimbs_put8(&newpacket->data, cookie[i]); 761 762 aimbs_put16(&newpacket->data, 0x0002); 763 aimbs_put8(&newpacket->data, strlen(sn)); 764 aimbs_putraw(&newpacket->data, sn, strlen(sn)); 765 aimbs_put16(&newpacket->data, 0x0005); 766 aimbs_put16(&newpacket->data, 0x001a); 767 aimbs_put16(&newpacket->data, AIM_RENDEZVOUS_CANCEL); 768 769 for (i = 0; i < 8; i++) 770 aimbs_put8(&newpacket->data, cookie[i]); 771 772 aim_putcap(&newpacket->data, rendid); 773 aim_tx_enqueue(sess, newpacket); 774 775 return 0; 635 776 } 636 777 637 778 /** 638 779 * aim_getlisting(FILE *file) -- get an aim_fileheader_t for a given FILE* 639 * 780 * @file is an opened listing file 640 781 * 641 782 * returns a pointer to the filled-in fileheader_t … … 649 790 return NULL; 650 791 #if 0 651 652 653 654 655 656 int linelength = 1024; 657 658 /* XXX: if we have a line longer than 1024chars, God help us. */ 659 if ( (linebuf = (char *)calloc(1, linelength)) == NULL ) { 660 faimdprintf(sess, 2, "linebuf calloc failed\n");661 return NULL; 662 } 663 664 if (fseek(file, 0, SEEK_END) == -1) { /* use this for sanity check */ 665 perror("getlisting END1 fseek:");666 faimdprintf(sess, 2, "getlising fseek END1 error\n"); 667 } 668 669 if ((size = ftell(file)) == -1) { 670 perror("getlisting END1 getpos:");671 faimdprintf(sess, 2, "getlising getpos END1 error\n"); 672 } 673 674 if (fseek(file, 0, SEEK_SET) != 0) { 675 perror("getlesting fseek(SET):");676 faimdprintf(sess, 2, "faim: getlisting: couldn't seek to beginning of listing file\n"); 677 } 678 679 memset(linebuf, 0, linelength); 680 681 size = 0; 682 683 while(fgets(linebuf, linelength, file)) { 684 totfiles++;685 memset(sizebuf, 0, 9); 686 687 size += strlen(linebuf); 688 689 if (strlen(linebuf) < 23) { 690 faimdprintf(sess, 2, "line \"%s\" too short. skipping\n", linebuf);691 continue; 692 } 693 694 695 696 697 698 699 700 701 } 702 703 704 705 706 } 707 708 709 710 711 712 * done at register time and cached, but, eh. */ 713 714 715 716 717 fh->encrypt= 0x0000;718 fh->compress = 0x0000; 719 fh->totfiles= totfiles;720 fh->filesleft = totfiles; /* is this right ?*/721 fh->totparts= 0x0001;722 fh->partsleft= 0x0001;723 fh->totsize= totsize;724 fh->size= size; /* ls -l listing.txt */725 fh->modtime= (int)time(NULL); /* we'll go with current time for now */726 fh->checksum= checksum; /* XXX: checksum ! */727 fh->rfcsum= 0x00000000;728 fh->rfsize= 0x00000000;729 fh->cretime= 0x00000000;730 fh->rfcsum= 0x00000000;731 fh->nrecvd= 0x00000000;732 fh->recvcsum= 0x00000000;733 734 /*memset(fh->idstring, 0, sizeof(fh->idstring)); */735 736 737 738 fh->flags= 0x02;739 740 741 742 /*memset(fh->dummy, 0, sizeof(fh->dummy)); */743 744 745 fh->nencode= 0x0000; /* we need to figure out these encodings for filenames */746 fh->nlanguage= 0x0000;747 748 /*memset(fh->name, 0, sizeof(fh->name)); */749 memcpy(fh->name, "listing.txt", sizeof(fh->name));750 751 752 753 792 struct aim_fileheader_t *fh; 793 u_long totsize = 0, size = 0, checksum = 0xffff0000; 794 short totfiles = 0; 795 char *linebuf, sizebuf[9]; 796 int linelength = 1024; 797 798 /* XXX: if we have a line longer than 1024chars, God help us. */ 799 if ((linebuf = (char *)calloc(1, linelength)) == NULL ) { 800 faimdprintf(sess, 2, "linebuf calloc failed\n"); 801 return NULL; 802 } 803 804 if (fseek(file, 0, SEEK_END) == -1) { /* use this for sanity check */ 805 perror("getlisting END1 fseek:"); 806 faimdprintf(sess, 2, "getlising fseek END1 error\n"); 807 } 808 809 if ((size = ftell(file)) == -1) { 810 perror("getlisting END1 getpos:"); 811 faimdprintf(sess, 2, "getlising getpos END1 error\n"); 812 } 813 814 if (fseek(file, 0, SEEK_SET) != 0) { 815 perror("getlesting fseek(SET):"); 816 faimdprintf(sess, 2, "faim: getlisting: couldn't seek to beginning of listing file\n"); 817 } 818 819 memset(linebuf, 0, linelength); 820 821 size = 0; 822 823 while(fgets(linebuf, linelength, file)) { 824 totfiles++; 825 memset(sizebuf, 0, 9); 826 827 size += strlen(linebuf); 828 829 if (strlen(linebuf) < 23) { 830 faimdprintf(sess, 2, "line \"%s\" too short. skipping\n", linebuf); 831 continue; 832 } 833 834 if (linebuf[strlen(linebuf)-1] != '\n') { 835 faimdprintf(sess, 2, "faim: OFT: getlisting -- hit EOF or line too long!\n"); 836 } 837 838 memcpy(sizebuf, linebuf+17, 8); 839 840 totsize += strtol(sizebuf, NULL, 10); 841 memset(linebuf, 0, linelength); 842 } 843 844 if (fseek(file, 0, SEEK_SET) == -1) { 845 perror("getlisting END2 fseek:"); 846 faimdprintf(sess, 2, "getlising fseek END2 error\n"); 847 } 848 849 free(linebuf); 850 851 /* we're going to ignore checksumming the data for now -- that 852 * requires walking the whole listing.txt. it should probably be 853 * done at register time and cached, but, eh. */ 854 855 if (!(fh = (struct aim_fileheader_t*)calloc(1, sizeof(struct aim_fileheader_t)))) 856 return NULL; 857 858 fh->encrypt = 0x0000; 859 fh->compress = 0x0000; 860 fh->totfiles = totfiles; 861 fh->filesleft = totfiles; /* is this right? */ 862 fh->totparts = 0x0001; 863 fh->partsleft = 0x0001; 864 fh->totsize = totsize; 865 fh->size = size; /* ls -l listing.txt */ 866 fh->modtime = (int)time(NULL); /* we'll go with current time for now */ 867 fh->checksum = checksum; /* XXX: checksum ! */ 868 fh->rfcsum = 0x00000000; 869 fh->rfsize = 0x00000000; 870 fh->cretime = 0x00000000; 871 fh->rfcsum = 0x00000000; 872 fh->nrecvd = 0x00000000; 873 fh->recvcsum = 0x00000000; 874 875 /* memset(fh->idstring, 0, sizeof(fh->idstring)); */ 876 memcpy(fh->idstring, "OFT_Windows ICBMFT V1.1 32", sizeof(fh->idstring)); 877 memset(fh->idstring+strlen(fh->idstring), 0, sizeof(fh->idstring)-strlen(fh->idstring)); 878 879 fh->flags = 0x02; 880 fh->lnameoffset = 0x1a; 881 fh->lsizeoffset = 0x10; 882 883 /* memset(fh->dummy, 0, sizeof(fh->dummy)); */ 884 memset(fh->macfileinfo, 0, sizeof(fh->macfileinfo)); 885 886 fh->nencode = 0x0000; /* we need to figure out these encodings for filenames */ 887 fh->nlanguage = 0x0000; 888 889 /* memset(fh->name, 0, sizeof(fh->name)); */ 890 strncpy(fh->name, "listing.txt", sizeof(fh->name)); 891 memset(fh->name+strlen(fh->name), 0, 64-strlen(fh->name)); 892 893 faimdprintf(sess, 2, "faim: OFT: listing fh name %s / %s\n", fh->name, (fh->name+(strlen(fh->name)))); 894 return fh; 754 895 #endif 755 896 } … … 757 898 /** 758 899 * aim_listenestablish - create a listening socket on a port. 759 * @portnum: the port number to bind to. 900 * @portnum: the port number to bind to. 760 901 * 761 902 * you need to call accept() when it's connected. returns your fd … … 784 925 ressave = res; 785 926 do { 786 listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 927 listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 787 928 if (listenfd < 0) 788 929 continue; … … 802 943 } 803 944 945 fcntl(listenfd, F_SETFL, O_NONBLOCK); 946 804 947 freeaddrinfo(ressave); 805 948 return listenfd; … … 834 977 return -1; 835 978 } 979 fcntl(listenfd, F_SETFL, O_NONBLOCK); 836 980 return listenfd; 837 981 #endif … … 849 993 int ret = 0; 850 994 char *listing; 851 struct command_tx_struct *newoft;995 aim_frame_t *newoft; 852 996 853 997 if (!(listing = malloc(ft->fh.size))) … … 860 1004 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x120b, 0))) { 861 1005 faimdprintf(sess, 2, "faim: aim_get_command_rendezvous: getfile listing: tx_new OFT failed\n"); 862 faim_mutex_unlock(&conn->active);863 1006 free(listing); 864 1007 aim_conn_close(conn); … … 896 1039 /* waiting on file data */ 897 1040 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILERECEIVE)) ) 898 return userfunc(sess, NULL, conn, ft); 1041 return userfunc(sess, NULL, conn, ft->fh.name, 1042 ft->fh.size); 899 1043 return 0; 900 1044 } … … 916 1060 { 917 1061 aim_msgcookie_t *cook; 918 struct aim_filetransfer_priv *priv = (struct aim_filetransfer_priv *)conn-> priv;1062 struct aim_filetransfer_priv *priv = (struct aim_filetransfer_priv *)conn->internal; 919 1063 920 1064 cook = aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTSEND); … … 926 1070 static void connkill_sendfile(aim_session_t *sess, aim_conn_t *conn) 927 1071 { 928 929 1072 free(conn->internal); 930 1073 … … 934 1077 static void connclose_getfile(aim_session_t *sess, aim_conn_t *conn) 935 1078 { 1079 #if 0 936 1080 aim_msgcookie_t *cook; 937 1081 struct aim_filetransfer_priv *priv = (struct aim_filetransfer_priv *)conn->priv; … … 939 1083 cook = aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTGET); 940 1084 aim_cookie_free(sess, cook); 941 1085 #endif 942 1086 return; 943 1087 } … … 1002 1146 } 1003 1147 1004 static int handlehdr_directim(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr)1148 static int handlehdr_directim(aim_session_t *sess, aim_conn_t *conn, aim_bstream_t *bs) 1005 1149 { 1006 1150 aim_frame_t fr; 1007 1151 aim_rxcallback_t userfunc; 1008 1152 fu32_t payloadlength; 1009 fu16_t flags ;1153 fu16_t flags, encoding; 1010 1154 char *snptr = NULL; 1011 1155 1012 1156 fr.conn = conn; 1013 1157 1014 payloadlength = aimutil_get32(hdr+22); 1015 flags = aimutil_get16(hdr+32); 1016 snptr = (char *)hdr+38; 1158 /* XXX ugly */ 1159 aim_bstream_setpos(bs, 20); 1160 payloadlength = aimbs_get32(bs); 1161 1162 aim_bstream_setpos(bs, 24); 1163 encoding = aimbs_get16(bs); 1164 1165 aim_bstream_setpos(bs, 30); 1166 flags = aimbs_get16(bs); 1167 1168 aim_bstream_setpos(bs, 36); 1169 /* XXX -create an aimbs_getnullstr function? */ 1170 snptr = aimbs_getstr(bs, MAXSNLEN); 1017 1171 1018 1172 faimdprintf(sess, 2, "faim: OFT frame: handlehdr_directim: %04x / %04x / %s\n", payloadlength, flags, snptr); 1019 1173 1020 if (flags == 0x000e) {1174 if (flags & 0x0002) { 1021 1175 int ret = 0; 1022 1176 1177 if (flags == 0x000c) { 1178 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING))) 1179 ret = userfunc(sess, &fr, snptr, 1); 1180 return ret; 1181 } 1182 1023 1183 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING))) 1024 ret = userfunc(sess, &fr, snptr );1184 ret = userfunc(sess, &fr, snptr, 0); 1025 1185 1026 1186 return ret; 1027 1187 1028 } else if (( flags == 0x0000) && payloadlength) {1029 char *msg ;1188 } else if (((flags & 0x000f) == 0x0000) && payloadlength) { 1189 char *msg, *msg2; 1030 1190 int ret = 0; 1191 int recvd = 0; 1192 int i; 1031 1193 1032 1194 if (!(msg = calloc(1, payloadlength+1))) 1033 1195 return -1; 1034 1035 if (aim_recv(conn->fd, msg, payloadlength) < payloadlength) { 1036 free(msg); 1037 return -1; 1196 msg2 = msg; 1197 1198 while (payloadlength - recvd) { 1199 if (payloadlength - recvd >= 1024) 1200 i = aim_recv(conn->fd, msg2, 1024); 1201 else 1202 i = aim_recv(conn->fd, msg2, payloadlength - recvd); 1203 if (i <= 0) { 1204 free(msg); 1205 return -1; 1206 } 1207 recvd = recvd + i; 1208 msg2 = msg2 + i; 1209 if ((userfunc=aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER))) 1210 userfunc(sess, &fr, snptr, (double)recvd / payloadlength); 1038 1211 } 1039 1040 msg[payloadlength] = '\0'; 1041 1212 1042 1213 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING)) ) 1043 ret = userfunc(sess, &fr, snptr, msg );1214 ret = userfunc(sess, &fr, snptr, msg, payloadlength, encoding); 1044 1215 1045 1216 free(msg); … … 1057 1228 struct aim_fileheader_t *fh; 1058 1229 struct aim_msgcookie_t *cook; 1059 struct command_tx_struct *newoft;1230 aim_frame_t *newoft; 1060 1231 aim_rxcallback_t userfunc; 1061 1232 … … 1081 1252 faimdprintf(sess, 1, "error caching cookie\n"); 1082 1253 return -1; 1083 } 1254 } 1084 1255 1085 1256 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x1209, 0))) { … … 1121 1292 1122 1293 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) 1123 faimdprintf(sess, 2, "shit, no cookie in 0x1209. (%i/%s)going to crash..\n", 1294 faimdprintf(sess, 2, "shit, no cookie in 0x1209. (%i/%s)going to crash..\n", AIM_COOKIETYPE_OFTGET, fh->bcookie); 1124 1295 1125 1296 ft = cook->data; … … 1173 1344 #if 0 1174 1345 struct aim_filetransfer_priv *ft; 1175 structaim_msgcookie_t *cook;1346 aim_msgcookie_t *cook; 1176 1347 struct aim_fileheader_t *fh; 1177 struct command_tx_struct *newoft;1348 aim_frame_t *newoft; 1178 1349 int i = 0; 1179 1350 aim_rxcallback_t userfunc; … … 1205 1376 } 1206 1377 1207 newoft->lock = 1;1208 1378 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 1209 1379 newoft->hdr.oft.hdr2len = 0x100 - 8; … … 1221 1391 aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)); 1222 1392 1223 newoft->lock = 0;1224 1393 aim_tx_enqueue(sess, newoft); 1225 1394 … … 1288 1457 } 1289 1458 1459 /* We are receiving a file, and the buddy sent us this header describing 1460 * it. We send back a similar header to confirm, then we're ready to 1461 * start reading the raw data. 1462 */ 1463 static int handlehdr_sendfile_sending(aim_session_t *sess, aim_conn_t *conn, aim_bstream_t *bs) 1464 { 1465 struct aim_filetransfer_priv *ft; 1466 struct aim_fileheader_t *fh; 1467 aim_frame_t *newoft; 1468 aim_rxcallback_t userfunc; 1469 1470 fh = aim_oft_getfh(bs); 1471 1472 /* We receive a null cookie for the first file; we must fill 1473 * it in to authenticate ourselves. -- wtm 1474 */ 1475 ft = conn->internal; 1476 memcpy(&(fh->bcookie), ft->cookie, 8); 1477 1478 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t)); 1479 free(fh); 1480 1481 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, AIM_OFT_PROTO_ACCEPT, 0))) { 1482 faimdprintf(sess, 2, "faim: send_final_transfer: tx_new OFT failed\n"); 1483 return -1; 1484 } 1485 1486 if (aim_oft_buildheader(&(newoft->data), &(ft->fh)) == -1) { 1487 return -1; 1488 } 1489 memcpy(newoft->hdr.rend.magic, "OFT2", 4); 1490 newoft->hdr.rend.hdrlen = aim_bstream_curpos(&newoft->data); 1491 1492 aim_tx_enqueue(sess, newoft); 1493 1494 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_SENDFILEFILEREQ)) == NULL) 1495 return 1; 1496 1497 { 1498 char *cur; 1499 /* Convert the directory separator: it is sent 1500 * as ^A (0x01). 1501 */ 1502 while ((cur = strchr(ft->fh.name, 0x01))) { 1503 *cur = G_DIR_SEPARATOR; 1504 } 1505 } 1506 return userfunc(sess, NULL, conn, &(ft->fh)); 1507 } 1508 1509 1510 /* 1511 * These were originally described by Josh Myer: 1512 * http://www.geocrawler.com/archives/3/896/2000/9/0/4291064/ 1513 * XXX this doesn't actually work yet 1514 * -- wtm 1515 */ 1516 static int handlehdr_sendfile_resume(aim_session_t *sess, aim_conn_t *conn, aim_bstream_t *bs) { 1517 aim_frame_t *newoft; 1518 aim_msgcookie_t *cook; 1519 struct aim_fileheader_t *fh; 1520 struct aim_filetransfer_priv *ft; 1521 1522 fh = aim_oft_getfh(bs); 1523 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTSEND))) { 1524 free(fh); 1525 return -1; 1526 } 1527 ft = (struct aim_filetransfer_priv *)cook->data; 1528 1529 ft->fh.nrecvd = fh->nrecvd; 1530 ft->fh.recvcsum = fh->recvcsum; 1531 strncpy(ft->fh.name, fh->name, sizeof(ft->fh.name)); 1532 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0106, 0))) { 1533 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n"); 1534 free(fh); 1535 return -1; 1536 } 1537 1538 if (aim_oft_buildheader(&(newoft->data), &(ft->fh)) == -1) { 1539 aim_frame_destroy(newoft); 1540 free(fh); 1541 return -1; 1542 } 1543 memcpy(newoft->hdr.rend.magic, "OFT2", 4); 1544 newoft->hdr.rend.hdrlen = aim_bstream_curpos(&newoft->data); 1545 1546 aim_tx_enqueue(sess, newoft); 1547 free(fh); 1548 1549 return 0; 1550 } 1551 1552 /* We are sending a file, and the buddy sent us this header indicating 1553 * that he or she is ready for the raw data. 1554 */ 1555 static int handlehdr_sendfile_recv(aim_session_t *sess, aim_conn_t *conn, aim_bstream_t *bs) { 1556 struct aim_fileheader_t *fh; 1557 aim_msgcookie_t *cook; 1558 int ret = 1; 1559 struct aim_filetransfer_priv *ft; 1560 aim_rxcallback_t userfunc; 1561 1562 fh = aim_oft_getfh(bs); 1563 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTSEND))) { 1564 free(fh); 1565 return -1; 1566 } 1567 ft = (struct aim_filetransfer_priv *)cook->data; 1568 1569 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_SENDFILEFILESEND)) ) 1570 ret = userfunc(sess, NULL, conn, &(ft->fh)); 1571 1572 free(fh); 1573 1574 return ret; 1575 } 1576 1290 1577 static int handlehdr_getfile_recv(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) 1291 1578 { 1292 1579 #if 0 1293 1580 struct aim_fileheader_t *fh; 1294 struct aim_filetransfer_priv *ft;1295 1581 struct aim_msgcookie_t *cook; 1296 1582 int ret = 1; 1297 1583 aim_rxcallback_t userfunc; 1584 struct aim_filetransfer_priv *ft; 1298 1585 1299 1586 fh = aim_oft_getfh(hdr); … … 1319 1606 } 1320 1607 1608 /* We just sent the raw data of a file, and the buddy sent us back this 1609 * header indicating that the transfer is complete. 1610 */ 1611 static int handlehdr_sendfile_finish(aim_session_t *sess, aim_conn_t *conn, aim_bstream_t *bs) 1612 { 1613 struct aim_fileheader_t *fh; 1614 aim_msgcookie_t *cook; 1615 aim_rxcallback_t userfunc; 1616 1617 fh = aim_oft_getfh(bs); 1618 1619 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTSEND))) { 1620 free(fh); 1621 return -1; 1622 } 1623 1624 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_SENDFILECOMPLETE)) ) 1625 userfunc(sess, NULL, conn, fh->bcookie); 1626 1627 free(fh); 1628 return 0; 1629 } 1630 1321 1631 static int handlehdr_getfile_finish(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) 1322 1632 { … … 1338 1648 } 1339 1649 1340 /** 1341 * aim_get_command_rendezvous - OFT equivalent of aim_get_command 1342 * @sess: session to work on 1343 * @conn: conn to pull data from 1344 * 1345 * this reads and handles data from conn->fd. currently a little rough 1346 * around the edges 1347 */ 1348 faim_internal int aim_get_command_rendezvous(aim_session_t *sess, aim_conn_t *conn) 1349 { 1350 fu8_t hdrbuf1[6]; 1351 fu8_t *hdr = NULL; 1352 int hdrlen, hdrtype; 1650 faim_internal int aim_rxdispatch_rendezvous(aim_session_t *sess, aim_frame_t *fr) 1651 { 1652 aim_conn_t *conn = fr->conn; 1653 aim_bstream_t *bs = &fr->data; 1353 1654 int ret = -1; 1354 1655 1355 if (!sess || !conn) 1356 return -1; 1357 1358 memset(hdrbuf1, 0, sizeof(hdrbuf1)); 1359 1360 /* I guess? I didn't understand any of that mess... */ 1361 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) 1656 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) { 1657 /* This should never happen. -- wtm */ 1362 1658 return getcommand_getfile(sess, conn); 1363 1659 1364 /* XXX fix all the error cases here */ 1365 if (aim_recv(conn->fd, hdrbuf1, 6) < 6) { 1366 1367 faimdprintf(sess, 2, "faim: rend: read error (fd: %i)\n", conn->fd); 1368 1369 aim_conn_close(conn); 1370 1371 return -1; 1372 } 1373 1374 hdrlen = aimutil_get16(hdrbuf1+4); 1375 hdrlen -= 6; 1376 1377 hdr = malloc(hdrlen); 1378 1379 if (aim_recv(conn->fd, hdr, hdrlen) < hdrlen) { 1380 faimdprintf(sess, 2, "faim: rend: read2 error on %d (%d)\n", conn->fd, hdrlen); 1381 free(hdr); 1382 aim_conn_close(conn); 1383 return -1; 1384 } 1385 1386 hdrtype = aimutil_get16(hdr); 1387 1388 if (hdrtype == 0x0001) 1389 ret = handlehdr_directim(sess, conn, hdr); 1390 else if (hdrtype == 0x1108) /* getfile listing.txt incoming tx->rx */ 1391 ret = handlehdr_getfile_listing(sess, conn, hdr); 1392 else if (hdrtype == 0x1209) /* get file listing ack rx->tx */ 1393 ret = handlehdr_getfile_listing2(sess, conn, hdr); 1394 else if (hdrtype == 0x120b) /* get file listing rx confirm */ 1395 ret = handlehdr_getfile_listing3(sess, conn, hdr); 1396 else if (hdrtype == 0x120c) /* getfile request */ 1397 ret = handlehdr_getfile_request(sess, conn, hdr); 1398 else if (hdrtype == 0x0101) /* getfile sending data */ 1399 ret = handlehdr_getfile_sending(sess, conn, hdr); 1400 else if (hdrtype == 0x0202) /* getfile recv data */ 1401 ret = handlehdr_getfile_recv(sess, conn, hdr); 1402 else if (hdrtype == 0x0204) /* getfile finished */ 1403 ret = handlehdr_getfile_finish(sess, conn, hdr); 1404 else { 1405 faimdprintf(sess, 2,"faim: OFT frame: uknown type %04x\n", hdrtype); 1406 ret = -1; 1660 } else if (conn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) { 1661 switch(fr->hdr.rend.type) { 1662 case AIM_OFT_PROTO_OFFER: 1663 ret = handlehdr_sendfile_sending(sess, conn, bs); 1664 break; 1665 case AIM_OFT_PROTO_RESUME: 1666 ret = handlehdr_sendfile_resume(sess, conn, bs); 1667 break; 1668 case AIM_OFT_PROTO_RESUMEACCEPT: /* like _ACCEPT */; 1669 case AIM_OFT_PROTO_ACCEPT: 1670 ret = handlehdr_sendfile_recv(sess, conn, bs); 1671 break; 1672 case AIM_OFT_PROTO_ACK: 1673 ret = handlehdr_sendfile_finish(sess, conn, bs); 1674 break; 1675 default: 1676 faimdprintf(sess, 2, "faim: OFT frame: uknown type %04x\n", fr->hdr.rend.type); 1677 ret = -1; 1678 break; 1679 } 1680 1681 } else if (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) { 1682 if (fr->hdr.rend.type == 0x0001) 1683 ret = handlehdr_directim(sess, conn, bs); 1684 else 1685 faimdprintf(sess, 0, "faim: DIM frame: unknown type %04x\n", fr->hdr.rend.type); 1686 1687 } else if (conn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) { 1688 /* This _really_ shouldn't happen. :) -- wtm */ 1689 char *hdr = NULL; 1690 int hdrtype = fr->hdr.rend.type; 1691 if (hdrtype == 0x1108) /* getfile listing.txt incoming tx->rx */ 1692 ret = handlehdr_getfile_listing(sess, conn, hdr); 1693 else if (hdrtype == 0x1209) /* get file listing ack rx->tx */ 1694 ret = handlehdr_getfile_listing2(sess, conn, hdr); 1695 else if (hdrtype == 0x120b) /* get file listing rx confirm */ 1696 ret = handlehdr_getfile_listing3(sess, conn, hdr); 1697 else if (hdrtype == 0x120c) /* getfile request */ 1698 ret = handlehdr_getfile_request(sess, conn, hdr); 1699 else if (hdrtype == 0x0101) /* getfile sending data */ 1700 ret = handlehdr_getfile_sending(sess, conn, hdr); 1701 else if (hdrtype == 0x0202) /* getfile recv data */ 1702 ret = handlehdr_getfile_recv(sess, conn, hdr); 1703 else if (hdrtype == 0x0204) /* getfile finished */ 1704 ret = handlehdr_getfile_finish(sess, conn, hdr); 1705 else { 1706 faimdprintf(sess, 2,"faim: OFT frame: uknown type %04x\n", hdrtype); 1707 ret = -1; 1708 } 1407 1709 } 1408 1710 1409 free(hdr);1410 1411 1711 if (ret == -1) 1412 1712 aim_conn_close(conn); … … 1415 1715 } 1416 1716 1417 #if 01418 1717 /** 1419 1718 * aim_oft_getfh - extracts an &aim_fileheader_t from buffer hdr. 1420 * @hdr: buffer to extract header from 1421 * 1422 * returns pointer to new struct on success; %NULL on error. 1423 * 1424 */ 1425 static struct aim_fileheader_t *aim_oft_getfh(unsigned char *hdr) 1426 { 1427 struct aim_fileheader_t *fh; 1428 int i, j; 1429 if (!(fh = calloc(1, sizeof(struct aim_fileheader_t)))) 1430 return NULL; 1431 1432 /* [0] and [1] are the type. we can ignore those here. */ 1433 i = 2; 1434 for(j = 0; j < 8; j++, i++) 1435 fh->bcookie[j] = hdr[i]; 1436 fh->encrypt = aimutil_get16(hdr+i); 1437 i += 2; 1438 fh->compress = aimutil_get16(hdr+i); 1439 i += 2; 1440 fh->totfiles = aimutil_get16(hdr+i); 1441 i += 2; 1442 fh->filesleft = aimutil_get16(hdr+i); 1443 i += 2; 1444 fh->totparts = aimutil_get16(hdr+i); 1445 i += 2; 1446 fh->partsleft = aimutil_get16(hdr+i); 1447 i += 2; 1448 fh->totsize = aimutil_get32(hdr+i); 1449 i += 4; 1450 fh->size = aimutil_get32(hdr+i); 1451 i += 4; 1452 fh->modtime = aimutil_get32(hdr+i); 1453 i += 4; 1454 fh->checksum = aimutil_get32(hdr+i); 1455 i += 4; 1456 fh->rfrcsum = aimutil_get32(hdr+i); 1457 i += 4; 1458 fh->rfsize = aimutil_get32(hdr+i); 1459 i += 4; 1460 fh->cretime = aimutil_get32(hdr+i); 1461 i += 4; 1462 fh->rfcsum = aimutil_get32(hdr+i); 1463 i += 4; 1464 fh->nrecvd = aimutil_get32(hdr+i); 1465 i += 4; 1466 fh->recvcsum = aimutil_get32(hdr+i); 1467 i += 4; 1468 memcpy(fh->idstring, hdr+i, 32); 1469 i += 32; 1470 fh->flags = aimutil_get8(hdr+i); 1471 i += 1; 1472 fh->lnameoffset = aimutil_get8(hdr+i); 1473 i += 1; 1474 fh->lsizeoffset = aimutil_get8(hdr+i); 1475 i += 1; 1476 memcpy(fh->dummy, hdr+i, 69); 1477 i += 69; 1478 memcpy(fh->macfileinfo, hdr+i, 16); 1479 i += 16; 1480 fh->nencode = aimutil_get16(hdr+i); 1481 i += 2; 1482 fh->nlanguage = aimutil_get16(hdr+i); 1483 i += 2; 1484 memcpy(fh->name, hdr+i, 64); 1485 i += 64; 1486 return fh; 1719 * @bs: bstream to extract header from 1720 * 1721 * returns pointer to new struct on success; %NULL on error. 1722 * 1723 */ 1724 static struct aim_fileheader_t *aim_oft_getfh(aim_bstream_t *bs) 1725 { 1726 struct aim_fileheader_t *fh; 1727 1728 if (!(fh = calloc(1, sizeof(struct aim_fileheader_t)))) 1729 return NULL; 1730 1731 /* The bstream should be positioned after the hdrtype. */ 1732 aimbs_getrawbuf(bs, fh->bcookie, 8); 1733 fh->encrypt = aimbs_get16(bs); 1734 fh->compress = aimbs_get16(bs); 1735 fh->totfiles = aimbs_get16(bs); 1736 fh->filesleft = aimbs_get16(bs); 1737 fh->totparts = aimbs_get16(bs); 1738 fh->partsleft = aimbs_get16(bs); 1739 fh->totsize = aimbs_get32(bs); 1740 fh->size = aimbs_get32(bs); 1741 fh->modtime = aimbs_get32(bs); 1742 fh->checksum = aimbs_get32(bs); 1743 fh->rfrcsum = aimbs_get32(bs); 1744 fh->rfsize = aimbs_get32(bs); 1745 fh->cretime = aimbs_get32(bs); 1746 fh->rfcsum = aimbs_get32(bs); 1747 fh->nrecvd = aimbs_get32(bs); 1748 fh->recvcsum = aimbs_get32(bs); 1749 aimbs_getrawbuf(bs, fh->idstring, 32); 1750 fh->flags = aimbs_get8(bs); 1751 fh->lnameoffset = aimbs_get8(bs); 1752 fh->lsizeoffset = aimbs_get8(bs); 1753 aimbs_getrawbuf(bs, fh->dummy, 69); 1754 aimbs_getrawbuf(bs, fh->macfileinfo, 16); 1755 fh->nencode = aimbs_get16(bs); 1756 fh->nlanguage = aimbs_get16(bs); 1757 aimbs_getrawbuf(bs, fh->name, 64); /* XXX */ 1758 1759 return fh; 1487 1760 } 1488 #endif1489 1761 1490 1762 /** … … 1492 1764 * @buffer: buffer of data to checksum 1493 1765 * @bufsize: size of buffer 1494 * @checksum: pointer to integer to place result in (pointer!) 1495 * 1496 * 1497 * Note that checksum is a pointer. Checksum should be filled with 1498 * 0xFFFF0000 for each new file; you can have this checksum chunks of 1499 * files in series if you just call it repeatedly in a for(; ; ) loop 1500 * and don't reset the checksum between each call. And you thought we 1501 * didn't care about you and your pathetic client's meomry footprint 1502 * ;^) 1503 * 1504 * 1505 * Also, it's been said that this is incorrect as currently 1506 * written. You were warned. 1507 */ 1508 faim_export fu32_t aim_oft_checksum(aim_session_t *sess, const char *buffer, int bufsize, fu32_t *checksum) 1509 { 1510 return 0xdeadbeef; 1511 #if 0 1512 fu16_t check0, check1; 1513 int i; 1514 1515 check0 = ((*checksum & 0xFF000000) >> 16); 1516 check1 = ((*checksum & 0x00ff0000) >> 16); 1517 for(i = 0; i < bufsize; i++) { 1518 if (i % 2) { /* use check1 -- second byte */ 1519 if ( (short)buffer[i] > check1 ) { /* wrapping */ 1520 check1 += 0x100; /* this is a cheap way to wrap */ 1521 1522 /* if we're wrapping, decrement the other one */ 1523 /* XXX: check this corner case */ 1524 if (check0 == 0) 1525 check0 = 0x00ff; 1526 else 1527 check0--; 1528 } 1529 check1 -= buffer[i]; 1530 } else { /* use check0 -- first byte */ 1531 if ( (short)buffer[i] > check0 ) { /* wrapping */ 1532 check0 += 0x100; /* this is a cheap way to wrap */ 1533 1534 /* if we're wrapping, decrement the other one */ 1535 /* XXX: check this corner case */ 1536 if (check1 == 0) 1537 check1 = 0x00ff; 1538 else 1539 check1--; 1540 } 1541 check0 -= buffer[i]; 1542 } 1543 } 1544 1545 if (check0 > 0xff || check1 > 0xff) { 1546 /* they shouldn't be able to do this. error! */ 1547 faimdprintf(sess, 2, "check0 or check1 is too high: 0x%04x, 0x%04x\n", check0, check1); 1548 return -1; 1549 } 1550 1551 /* grab just the lowest byte; this should be clean, but just in 1552 case */ 1553 check0 &= 0xff; 1554 check1 &= 0xff; 1555 1556 *checksum = ((check0 * 0x1000000) + (check1 * 0x10000)); 1557 return *checksum; 1558 #endif 1559 } 1560 1561 #if 0 1766 * @prevcheck: previous checksum 1767 * 1768 * Prevcheck should be 0xFFFF0000 for each new file; you can have this 1769 * checksum chunks of files in series if you just call it repeatedly in a 1770 * for(; ; ) loop and don't reset the checksum between each call. And you 1771 * thought we didn't care about you and your pathetic client's meomry 1772 * footprint ;^) 1773 * 1774 * Thanks to Graham Booker for providing this improved checksum 1775 * routine, which is simpler and should be more accurate than Josh 1776 * Myer's original code. -- wtm 1777 * 1778 * This algorithim works every time I have tried it. The other fails 1779 * sometimes. So, AOL who thought this up? It has got to be the weirdest 1780 * checksum I have ever seen. 1781 */ 1782 faim_export fu32_t aim_oft_checksum(const unsigned char *buffer, int bufferlen, int prevcheck) { 1783 fu32_t check = (prevcheck >> 16) & 0xffff, oldcheck; 1784 int i; 1785 unsigned short val; 1786 1787 for (i=0; i<bufferlen; i++) { 1788 oldcheck = check; 1789 if (i&1) { 1790 val = buffer[i]; 1791 } else { 1792 val = buffer[i] << 8; 1793 } 1794 check -= val; 1795 /* The follownig appears to be necessary.... It happens every once in a while and the checksum doesn't fail. */ 1796 if (check > oldcheck) { 1797 check--; 1798 } 1799 } 1800 check = ((check & 0x0000ffff) + (check >> 16)); 1801 check = ((check & 0x0000ffff) + (check >> 16)); 1802 return check << 16; 1803 } 1804 1805 faim_export fu32_t aim_update_checksum(aim_session_t *sess, aim_conn_t *conn, 1806 const unsigned char *buffer, int len) { 1807 struct aim_filetransfer_priv *ft = conn->internal; 1808 1809 ft->fh.nrecvd += len; 1810 ft->fh.recvcsum = aim_oft_checksum(buffer, len, ft->fh.recvcsum); 1811 1812 return 0; 1813 } 1814 1562 1815 /** 1563 1816 * aim_oft_buildheader - fills a buffer with network-order fh data 1564 * @dest: buffer to fill -- pre-alloced 1565 * @fh: fh to get data from 1566 * 1567 * returns length written; -1 on error. 1568 * DOES NOT DO BOUNDS CHECKING! 1569 * 1570 */ 1571 static int oft_buildheader(unsigned char *dest, struct aim_fileheader_t *fh) 1817 * @bs: bstream to fill -- automatically initialized 1818 * @fh: fh to get data from 1819 * 1820 * returns -1 on error. 1821 * 1822 */ 1823 static int aim_oft_buildheader(aim_bstream_t *bs, struct aim_fileheader_t *fh) 1572 1824 { 1573 int i, curbyte; 1574 if (!dest || !fh) 1575 return -1; 1576 curbyte = 0; 1577 for(i = 0; i < 8; i++) 1578 curbyte += aimutil_put8(dest+curbyte, fh->bcookie[i]); 1579 curbyte += aimutil_put16(dest+curbyte, fh->encrypt); 1580 curbyte += aimutil_put16(dest+curbyte, fh->compress); 1581 curbyte += aimutil_put16(dest+curbyte, fh->totfiles); 1582 curbyte += aimutil_put16(dest+curbyte, fh->filesleft); 1583 curbyte += aimutil_put16(dest+curbyte, fh->totparts); 1584 curbyte += aimutil_put16(dest+curbyte, fh->partsleft); 1585 curbyte += aimutil_put32(dest+curbyte, fh->totsize); 1586 curbyte += aimutil_put32(dest+curbyte, fh->size); 1587 curbyte += aimutil_put32(dest+curbyte, fh->modtime); 1588 curbyte += aimutil_put32(dest+curbyte, fh->checksum); 1589 curbyte += aimutil_put32(dest+curbyte, fh->rfrcsum); 1590 curbyte += aimutil_put32(dest+curbyte, fh->rfsize); 1591 curbyte += aimutil_put32(dest+curbyte, fh->cretime); 1592 curbyte += aimutil_put32(dest+curbyte, fh->rfcsum); 1593 curbyte += aimutil_put32(dest+curbyte, fh->nrecvd); 1594 curbyte += aimutil_put32(dest+curbyte, fh->recvcsum); 1595 memcpy(dest+curbyte, fh->idstring, 32); 1596 curbyte += 32; 1597 curbyte += aimutil_put8(dest+curbyte, fh->flags); 1598 curbyte += aimutil_put8(dest+curbyte, fh->lnameoffset); 1599 curbyte += aimutil_put8(dest+curbyte, fh->lsizeoffset); 1600 memcpy(dest+curbyte, fh->dummy, 69); 1601 curbyte += 69; 1602 memcpy(dest+curbyte, fh->macfileinfo, 16); 1603 curbyte += 16; 1604 curbyte += aimutil_put16(dest+curbyte, fh->nencode); 1605 curbyte += aimutil_put16(dest+curbyte, fh->nlanguage); 1606 memset(dest+curbyte, 0x00, 64); 1607 memcpy(dest+curbyte, fh->name, 64); 1608 1609 /* XXX: Filenames longer than 64B */ 1610 curbyte += 64; 1611 return curbyte; 1612 } 1613 #endif 1825 fu8_t *hdr; 1826 1827 if (!bs || !fh) 1828 return -1; 1829 1830 1831 1832 1833 if (!(hdr = (unsigned char *)calloc(1, 0x100 - 8))) { 1834 return -1; 1835 } 1836 aim_bstream_init(bs, hdr, 0x100 - 8); 1837 1838 aimbs_putraw(bs, fh->bcookie, 8); 1839 aimbs_put16(bs, fh->encrypt); 1840 aimbs_put16(bs, fh->compress); 1841 aimbs_put16(bs, fh->totfiles); 1842 aimbs_put16(bs, fh->filesleft); 1843 aimbs_put16(bs, fh->totparts); 1844 aimbs_put16(bs, fh->partsleft); 1845 aimbs_put32(bs, fh->totsize); 1846 aimbs_put32(bs, fh->size); 1847 aimbs_put32(bs, fh->modtime); 1848 aimbs_put32(bs, fh->checksum); 1849 aimbs_put32(bs, fh->rfrcsum); 1850 aimbs_put32(bs, fh->rfsize); 1851 aimbs_put32(bs, fh->cretime); 1852 aimbs_put32(bs, fh->rfcsum); 1853 aimbs_put32(bs, fh->nrecvd); 1854 aimbs_put32(bs, fh->recvcsum); 1855 aimbs_putraw(bs, fh->idstring, 32); 1856 aimbs_put8(bs, fh->flags); 1857 aimbs_put8(bs, fh->lnameoffset); 1858 aimbs_put8(bs, fh->lsizeoffset); 1859 aimbs_putraw(bs, fh->dummy, 69); 1860 aimbs_putraw(bs, fh->macfileinfo, 16); 1861 aimbs_put16(bs, fh->nencode); 1862 aimbs_put16(bs, fh->nlanguage); 1863 aimbs_putraw(bs, fh->name, 64); 1864 1865 /* XXX: Filenames longer than 64B */ 1866 return 0; 1867 } 1614 1868 1615 1869 /** … … 1625 1879 return NULL; 1626 1880 #if 0 1627 struct command_tx_struct *newpacket; 1628 struct aim_conn_t *newconn; 1629 struct aim_filetransfer_priv *priv; 1630 struct aim_msgcookie_t *cookie; 1631 int curbyte, i, listenfd; 1632 short port = 4443; 1633 struct hostent *hptr; 1634 struct utsname myname; 1635 char cap[16]; 1636 char d[4]; 1881 struct command_tx_struct *newpacket; 1882 struct aim_conn_t *newconn; 1883 struct aim_filetransfer_priv *priv; 1884 struct aim_msgcookie_t *cookie; 1885 int curbyte, i, listenfd; 1886 short port = 4443; 1887 struct hostent *hptr; 1888 struct utsname myname; 1889 char cap[16]; 1890 char d[4]; 1891 1892 /* Open our socket */ 1893 1894 if ( (listenfd = aim_listenestablish(port)) == -1) 1895 return NULL; 1896 1897 /* get our local IP */ 1898 1899 if (uname(&myname) < 0) 1900 return NULL; 1901 if ( (hptr = gethostbyname(myname.nodename)) == NULL) 1902 return NULL; 1903 memcpy(&d, hptr->h_addr_list[0], 4); 1904 1905 aim_putcap(cap, 16, AIM_CAPS_GETFILE); 1906 1907 /* create the OSCAR packet */ 1908 1909 if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+8+2+1+strlen(destsn)+4+4+0x42))) 1910 return NULL; 1911 newpacket->lock = 1; 1912 1913 /* lock struct */ 1914 curbyte = 0; 1915 curbyte += aim_putsnac(newpacket->data+curbyte, 0x0004, 0x0006, 0x0000, sess->snac_nextid); 1916 1917 /* XXX: check the cookie before commiting to using it */ 1918 1919 /* Generate a random message cookie 1920 * This cookie needs to be alphanumeric and NULL-terminated to be TOC-compatible. */ 1921 for (i=0; i<7; i++) 1922 curbyte += aimutil_put8(newpacket->data+curbyte, 0x30 + ((u_char) random() % 10)); 1923 1924 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00); 1925 1926 /* grab all the data for cookie caching. */ 1637 1927 1638 /* Open our socket */ 1639 1640 if ( (listenfd = aim_listenestablish(port)) == -1) 1641 return NULL; 1642 1643 /* get our local IP */ 1644 1645 if (uname(&myname) < 0) 1646 return NULL; 1647 if ( (hptr = gethostbyname(myname.nodename)) == NULL) 1648 return NULL; 1649 memcpy(&d, hptr->h_addr_list[0], 4); 1650 1651 aim_putcap(cap, 16, AIM_CAPS_GETFILE); 1652 1653 /* create the OSCAR packet */ 1654 1655 if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+8+2+1+strlen(destsn)+4+4+0x42))) 1656 return NULL; 1657 newpacket->lock = 1; 1658 1659 /* lock struct */ 1660 curbyte = 0; 1661 curbyte += aim_putsnac(newpacket->data+curbyte, 0x0004, 0x0006, 0x0000, sess->snac_nextid); 1662 1663 /* XXX: check the cookie before commiting to using it */ 1664 1665 /* Generate a random message cookie 1666 * This cookie needs to be alphanumeric and NULL-terminated to be TOC-compatible. */ 1667 for (i=0; i<7; i++) 1668 curbyte += aimutil_put8(newpacket->data+curbyte, 0x30 + ((u_char) random() % 10)); 1669 1670 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00); 1671 1672 /* grab all the data for cookie caching. */ 1928 if (!(cookie = (struct aim_msgcookie_t *)calloc(1, sizeof(struct aim_msgcookie_t)))) 1929 return NULL; 1930 memcpy(cookie->cookie, newpacket->data+curbyte-8, 8); 1931 cookie->type = AIM_COOKIETYPE_OFTGET; 1932 1933 if (!(priv = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) 1934 return NULL; 1935 memcpy(priv->cookie, cookie, 8); 1936 memcpy(priv->sn, destsn, sizeof(priv->sn)); 1937 memcpy(priv->fh.name, "listing.txt", strlen("listing.txt")); 1938 priv->state = 1; 1939 1940 cookie->data = priv; 1941 1942 aim_cachecookie(sess, cookie); 1943 1944 /* Channel ID */ 1945 curbyte += aimutil_put16(newpacket->data+curbyte,0x0002); 1946 1947 /* Destination SN (prepended with byte length) */ 1948 curbyte += aimutil_put8(newpacket->data+curbyte,strlen(destsn)); 1949 curbyte += aimutil_putstr(newpacket->data+curbyte, destsn, strlen(destsn)); 1950 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003); 1951 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); 1952 1953 /* enTLV start */ 1954 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005); 1955 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0042); 1956 1957 /* Flag data / ICBM Parameters? */ 1958 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00); 1959 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00); 1960 1961 /* Cookie */ 1962 curbyte += aimutil_putstr(newpacket->data+curbyte, (char *)cookie, 8); 1963 1964 /* Capability String */ 1965 curbyte += aimutil_putstr(newpacket->data+curbyte, (char *)cap, 0x10); 1966 1967 /* 000a/0002 : 0001 */ 1968 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000a); 1969 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); 1970 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001); 1971 1972 /* 0003/0004: IP address */ 1973 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003); 1974 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0004); 1975 for (i = 0; i < 4; i++) 1976 curbyte += aimutil_put8(newpacket->data+curbyte, d[i]); 1977 1978 /* already in network byte order */ 1673 1979 1674 if (!(cookie = (struct aim_msgcookie_t *)calloc(1, sizeof(struct aim_msgcookie_t)))) 1675 return NULL; 1676 memcpy(cookie->cookie, newpacket->data+curbyte-8, 8); 1677 cookie->type = AIM_COOKIETYPE_OFTGET; 1678 1679 if (!(priv = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) 1680 return NULL; 1681 memcpy(priv->cookie, cookie, 8); 1682 memcpy(priv->sn, destsn, sizeof(priv->sn)); 1683 memcpy(priv->fh.name, "listing.txt", strlen("listing.txt")); 1684 priv->state = 1; 1685 1686 cookie->data = priv; 1687 1688 aim_cachecookie(sess, cookie); 1689 1690 /* Channel ID */ 1691 curbyte += aimutil_put16(newpacket->data+curbyte,0x0002); 1692 1693 /* Destination SN (prepended with byte length) */ 1694 curbyte += aimutil_put8(newpacket->data+curbyte,strlen(destsn)); 1695 curbyte += aimutil_putstr(newpacket->data+curbyte, destsn, strlen(destsn)); 1696 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003); 1697 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); 1698 1699 /* enTLV start */ 1700 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005); 1701 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0042); 1702 1703 /* Flag data / ICBM Parameters? */ 1704 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00); 1705 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00); 1706 1707 /* Cookie */ 1708 curbyte += aimutil_putstr(newpacket->data+curbyte, (char *)cookie, 8); 1709 1710 /* Capability String */ 1711 curbyte += aimutil_putstr(newpacket->data+curbyte, (char *)cap, 0x10); 1712 1713 /* 000a/0002 : 0001 */ 1714 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000a); 1715 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); 1716 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001); 1717 1718 /* 0003/0004: IP address */ 1719 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003); 1720 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0004); 1721 for(i = 0; i < 4; i++) 1722 curbyte += aimutil_put8(newpacket->data+curbyte, d[i]); 1723 1724 /* already in network byte order */ 1725 1726 /* 0005/0002: Port */ 1727 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005); 1728 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); 1729 curbyte += aimutil_put16(newpacket->data+curbyte, port); 1730 1731 /* 000f/0000: ?? */ 1732 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000f); 1733 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); 1734 1735 /* 2711/000c: ?? */ 1736 curbyte += aimutil_put16(newpacket->data+curbyte, 0x2711); 1737 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000c); 1738 curbyte += aimutil_put32(newpacket->data+curbyte, 0x00120001); 1739 1740 for(i = 0; i < 0x000c - 4; i++) 1741 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00); 1742 1743 newpacket->commandlen = curbyte; 1744 newpacket->lock = 0; 1745 aim_tx_enqueue(sess, newpacket); 1746 1747 /* allocate and set up our connection */ 1748 1749 i = fcntl(listenfd, F_GETFL, 0); 1750 fcntl(listenfd, F_SETFL, i | O_NONBLOCK); 1751 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL); 1752 1753 if (!newconn){ 1754 perror("aim_newconn"); 1755 return NULL; 1756 } 1757 1758 newconn->fd = listenfd; 1759 newconn->subtype = AIM_CONN_SUBTYPE_OFT_GETFILE; 1760 newconn->priv = priv; 1761 faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd); 1762 1763 return newconn; 1980 /* 0005/0002: Port */ 1981 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005); 1982 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); 1983 curbyte += aimutil_put16(newpacket->data+curbyte, port); 1984 1985 /* 000f/0000: ?? */ 1986 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000f); 1987 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); 1988 1989 /* 2711/000c: ?? */ 1990 curbyte += aimutil_put16(newpacket->data+curbyte, 0x2711); 1991 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000c); 1992 curbyte += aimutil_put32(newpacket->data+curbyte, 0x00120001); 1993 1994 for (i = 0; i < 0x000c - 4; i++) 1995 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00); 1996 1997 newpacket->commandlen = curbyte; 1998 newpacket->lock = 0; 1999 aim_tx_enqueue(sess, newpacket); 2000 2001 /* allocate and set up our connection */ 2002 2003 i = fcntl(listenfd, F_GETFL, 0); 2004 fcntl(listenfd, F_SETFL, i | O_NONBLOCK); 2005 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL); 2006 2007 if (!newconn){ 2008 perror("aim_newconn"); 2009 return NULL; 2010 } 2011 2012 newconn->fd = listenfd; 2013 newconn->subtype = AIM_CONN_SUBTYPE_OFT_GETFILE; 2014 newconn->internal = priv; 2015 faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd); 2016 2017 return newconn; 1764 2018 #endif 1765 2019 } … … 1775 2029 * returns -1 on error, 0 on successful enqueuing 1776 2030 */ 2031 #if 0 1777 2032 faim_export int aim_oft_getfile_request(aim_session_t *sess, aim_conn_t *conn, const char *name, int size) 1778 2033 { 1779 return -EINVAL; 1780 #if 0 1781 struct command_tx_struct *newoft; 1782 struct aim_filetransfer_priv *ft; 1783 if (!sess || !conn || !conn->priv || !name) 1784 return -1; 1785 1786 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x120c, 0))) { 1787 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n"); 1788 return -1; 1789 } 1790 1791 newoft->lock = 1; 1792 1793 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 1794 newoft->hdr.oft.hdr2len = 0x100 - 8; 1795 1796 ft = (struct aim_filetransfer_priv *)conn->priv; 1797 ft->fh.filesleft = 1; 1798 ft->fh.totfiles = 1; 1799 ft->fh.totparts = 1; 1800 ft->fh.partsleft = 1; 1801 ft->fh.totsize = size; 1802 ft->fh.size = size; 1803 ft->fh.checksum = 0; 1804 memcpy(ft->fh.name, name, strlen(name)); 1805 memset(ft->fh.name+strlen(name), 0, 1); 1806 1807 if (!(newoft->hdr.oft.hdr2 = (unsigned char *)calloc(1,newoft->hdr.oft.hdr2len))) { 1808 newoft->lock = 0; 1809 aim_frame_destroy(newoft); 1810 return -1; 1811 } 1812 1813 if (!(aim_oft_buildheader(newoft->hdr.oft.hdr2, &(ft->fh)))) { 1814 newoft->lock = 0; 1815 aim_frame_destroy(newoft); 1816 return -1; 1817 } 1818 1819 newoft->lock = 0; 1820 1821 aim_tx_enqueue(sess, newoft); 1822 return 0; 2034 aim_frame_t *newoft; 2035 struct aim_filetransfer_priv *ft; 2036 if (!sess || !conn || !conn->priv || !name) 2037 return -1; 2038 2039 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x120c, 0))) { 2040 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n"); 2041 return -1; 2042 } 2043 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 2044 newoft->hdr.oft.hdr2len = 0x100 - 8; 2045 2046 ft = (struct aim_filetransfer_priv *)conn->priv; 2047 ft->fh.filesleft = 1; 2048 ft->fh.totfiles = 1; 2049 ft->fh.totparts = 1; 2050 ft->fh.partsleft = 1; 2051 ft->fh.totsize = size; 2052 ft->fh.size = size; 2053 ft->fh.checksum = 0; 2054 memcpy(ft->fh.name, name, strlen(name)); 2055 memset(ft->fh.name+strlen(name), 0, 1); 2056 2057 if (!(newoft->hdr.oft.hdr2 = (unsigned char *)calloc(1,newoft->hdr.oft.hdr2len))) { 2058 aim_frame_destroy(newoft); 2059 return -1; 2060 } 2061 2062 if (!(aim_oft_buildheader(newoft->hdr.oft.hdr2, &(ft->fh)))) { 2063 aim_frame_destroy(newoft); 2064 return -1; 2065 } 2066 2067 aim_tx_enqueue(sess, newoft); 2068 return 0; 2069 } 1823 2070 #endif 2071 2072 /* Identify a file that we are about to send by transmitting the 2073 * appropriate header. 2074 */ 2075 faim_export int aim_oft_sendfile_request(aim_session_t *sess, aim_conn_t *conn, const char *filename, int filesdone, int numfiles, int size, int totsize) 2076 { 2077 aim_frame_t *newoft; 2078 aim_msgcookie_t *cook; 2079 struct aim_filetransfer_priv *ft = (struct aim_filetransfer_priv *)conn->internal; 2080 struct aim_fileheader_t *fh; 2081 2082 if (!sess || !conn || !filename) 2083 return -1; 2084 2085 if (!(fh = (struct aim_fileheader_t*)calloc(1, sizeof(struct aim_fileheader_t)))) 2086 return -1; 2087 2088 #ifdef DUMB_OFT_CHECKSUM 2089 /* Yes, we are supposed to checksum the whole file before sending, and 2090 * yes, it's dumb. This is the only way to get some clients (such as 2091 * Mac AIM v4.5.163) to successfully complete the transfer. With 2092 * the WinAIM clients, we seem to be able to get away with just 2093 * setting the checksum to zero. 2094 * -- wtm 2095 */ 2096 { 2097 int fd = open(filename, O_RDONLY); 2098 if (fd >= 0) { 2099 int bytes; 2100 char buf[1024]; 2101 fh->checksum = 0xffff0000; 2102 while ((bytes = aim_recv(fd, buf, 1024)) > 0) { 2103 fh->checksum = aim_oft_checksum(buf, bytes, fh->checksum); 2104 } 2105 } 2106 close(fd); 2107 } 2108 #else 2109 fh->checksum = 0x00000000; 2110 #endif 2111 fh->encrypt = 0x0000; 2112 fh->compress = 0x0000; 2113 fh->totfiles = numfiles; 2114 fh->filesleft = numfiles - filesdone; 2115 fh->totparts = 0x0001; /* set to 0x0002 sending Mac resource forks */ 2116 fh->partsleft = 0x0001; 2117 fh->totsize = totsize; 2118 fh->size = size; 2119 fh->modtime = (int)time(NULL); /* we'll go with current time for now */ 2120 /* fh->checksum set above */ 2121 fh->rfcsum = 0x00000000; 2122 fh->rfsize = 0x00000000; 2123 fh->cretime = 0x00000000; 2124 fh->rfcsum = 0x00000000; 2125 fh->nrecvd = 0x00000000; /* always zero initially */ 2126 fh->recvcsum= 0x00000000; /* ditto */ 2127 2128 strncpy(fh->idstring, "OFT_Windows ICBMFT V1.1 32", sizeof(fh->idstring)); 2129 fh->flags = 0x02; 2130 fh->lnameoffset = 0x1a; 2131 fh->lsizeoffset = 0x10; 2132 memset(fh->dummy, 0, sizeof(fh->dummy)); 2133 memset(fh->macfileinfo, 0, sizeof(fh->macfileinfo)); 2134 2135 /* apparently 0 is ASCII, 2 is UCS-2 */ 2136 /* it is likely that 3 is ISO 8859-1 */ 2137 fh->nencode = 0x0000; 2138 fh->nlanguage = 0x0000; 2139 2140 /* Convert the directory separator to ^A for portability. */ 2141 strncpy(fh->name, filename, sizeof(fh->name)); 2142 oft_dirconvert(fh->name); 2143 2144 /* XXX we should normally send a null cookie here, and make 2145 * the receiver fill it in for authentication -- wtm 2146 */ 2147 memcpy(fh->bcookie, ft->cookie, 8); 2148 2149 if (!(cook = aim_checkcookie(sess, ft->cookie, AIM_COOKIETYPE_OFTSEND))) { 2150 return -1; 2151 } 2152 2153 /* Update both headers to be safe. */ 2154 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t)); 2155 memcpy(&(((struct aim_filetransfer_priv *)cook->data)->fh), fh, sizeof(struct aim_fileheader_t)); 2156 2157 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, AIM_OFT_PROTO_OFFER, 0))) { 2158 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n"); 2159 free(fh); 2160 return -1; 2161 } 2162 2163 if (aim_oft_buildheader(&newoft->data, fh) == -1) { 2164 aim_frame_destroy(newoft); 2165 free(fh); 2166 return -1; 2167 } 2168 2169 memcpy(newoft->hdr.rend.magic, "OFT2", 4); 2170 newoft->hdr.rend.hdrlen = aim_bstream_curpos(&newoft->data); 2171 2172 aim_tx_enqueue(sess, newoft); 2173 free(fh); 2174 return 0; 1824 2175 } 1825 2176 … … 1837 2188 return -EINVAL; 1838 2189 #if 0 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 2190 struct command_tx_struct *newoft; 2191 struct aim_filetransfer_priv *ft; 2192 2193 if (!sess || !conn || !conn->priv) 2194 return -1; 2195 2196 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0202, 0))) { 2197 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n"); 2198 return -1; 2199 } 2200 2201 newoft->lock = 1; 2202 2203 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 2204 newoft->hdr.oft.hdr2len = 0x100-8; 2205 2206 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { 2207 newoft->lock = 0; 2208 aim_frame_destroy(newoft); 2209 return -1; 2210 } 2211 2212 ft = (struct aim_filetransfer_priv *)conn->priv; 2213 2214 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) { 2215 newoft->lock = 0; 2216 aim_frame_destroy(newoft); 2217 return -1; 2218 } 2219 2220 newoft->lock = 0; 2221 aim_tx_enqueue(sess, newoft); 2222 return 0; 1872 2223 #endif 1873 2224 } 1874 2225 1875 2226 /** 1876 * aim_oft_ getfile_end - end a getfile.2227 * aim_oft_end - end a getfile/sendfile. 1877 2228 * @sess: your session 1878 2229 * @conn: the getfile connection … … 1881 2232 * receiving/requesting end. 1882 2233 */ 1883 faim_export int aim_oft_getfile_end(aim_session_t *sess, aim_conn_t *conn) 1884 { 1885 return -EINVAL; 1886 #if 0 1887 struct command_tx_struct *newoft; 1888 struct aim_filetransfer_priv *ft; 1889 1890 if (!sess || !conn || !conn->priv) 1891 return -1; 1892 1893 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0204, 0))) { 1894 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n"); 1895 return -1; 1896 } 1897 1898 newoft->lock = 1; 1899 1900 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 1901 newoft->hdr.oft.hdr2len = 0x100 - 8; 1902 1903 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { 1904 newoft->lock = 0; 1905 aim_frame_destroy(newoft); 1906 return -1; 1907 } 1908 1909 ft = (struct aim_filetransfer_priv *)conn->priv; 1910 ft->state = 4; /* no longer wanting data */ 1911 ft->fh.nrecvd = ft->fh.size; 1912 ft->fh.recvcsum = ft->fh.checksum; 1913 ft->fh.flags = 0x21; 1914 1915 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) { 1916 newoft->lock = 0; 1917 aim_frame_destroy(newoft); 1918 return -1; 1919 } 1920 1921 newoft->lock = 0; 1922 aim_tx_enqueue(sess, newoft); 1923 1924 return 0; 1925 #endif /* 0 */ 1926 } 1927 2234 faim_export int aim_oft_end(aim_session_t *sess, aim_conn_t *conn) 2235 { 2236 aim_frame_t *newoft; 2237 struct aim_filetransfer_priv *ft; 2238 2239 if (!sess || !conn || !conn->internal) 2240 return -1; 2241 2242 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, AIM_OFT_PROTO_ACK, 0))) { 2243 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n"); 2244 return -1; 2245 } 2246 2247 ft = (struct aim_filetransfer_priv *)conn->internal; 2248 ft->state = 4; /* no longer wanting data */ 2249 ft->fh.flags = 0x21; 2250 2251 if (aim_oft_buildheader(&(newoft->data), &(ft->fh)) == -1) { 2252 aim_frame_destroy(newoft); 2253 return -1; 2254 } 2255 memcpy(newoft->hdr.rend.magic, "OFT2", 4); 2256 newoft->hdr.rend.hdrlen = aim_bstream_curpos(&newoft->data); 2257 2258 aim_tx_enqueue(sess, newoft); 2259 2260 return 0; 2261 } 2262 2263 /* 2264 * Convert the directory separator to ^A, which seems to be AOL's attempt at portability. 2265 */ 2266 static void oft_dirconvert(char *name) { 2267 char *c = name; 2268 while ((c = strchr(c, G_DIR_SEPARATOR))) 2269 *c = 0x01; 2270 } -
libfaim/icq.c
r5e53c4a r862371b 1 1 /* 2 * Encapsulated ICQ.2 * Family 0x0015 - Encapsulated ICQ. 3 3 * 4 4 */ … … 263 263 return 0; 264 264 } 265 266 -
libfaim/im.c
r5e53c4a r862371b 1 1 /* 2 * aim_im.c 3 * 4 * The routines for sending/receiving Instant Messages. 2 * Family 0x0004 - Routines for sending/receiving Instant Messages. 5 3 * 6 4 * Note the term ICBM (Inter-Client Basic Message) which blankets … … 11 9 * is used for negotiating "rendezvous". These transactions end in 12 10 * something more complex happening, such as a chat invitation, or 13 * a file transfer. 11 * a file transfer. Channel 3 is used for chat messages (not in 12 * the same family as these channels). Channel 4 is used for 13 * various ICQ messages. Examples are normal messages, URLs, and 14 * old-style authorization. 14 15 * 15 16 * In addition to the channel, every ICBM contains a cookie. For … … 22 23 #define FAIM_INTERNAL 23 24 #include <aim.h> 25 26 #ifdef _WIN32 27 #include "win32dep.h" 28 #endif 24 29 25 30 /* … … 37 42 * 4.3.2229, 4.4.2286 38 43 * 0501 0004 0101 0102 0101 WinAIM 4.1.2010, libfaim (right here) 44 * 0501 0003 0101 02 WinAIM 5 45 * 0501 0001 01 iChat x.x 39 46 * 0501 0001 0101 01 AOL v6.0, CompuServe 2000 v6.0, any 40 47 * TOC client … … 84 91 } 85 92 93 /* 94 * Subtype 0x0002 95 * 96 * I definitly recommend sending this. If you don't, you'll be stuck 97 * with the rather unreasonable defaults. You don't want those. Send this. 98 * 99 */ 100 faim_export int aim_seticbmparam(aim_session_t *sess, struct aim_icbmparameters *params) 101 { 102 aim_conn_t *conn; 103 aim_frame_t *fr; 104 aim_snacid_t snacid; 105 106 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) 107 return -EINVAL; 108 109 if (!params) 110 return -EINVAL; 111 112 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+16))) 113 return -ENOMEM; 114 115 snacid = aim_cachesnac(sess, 0x0004, 0x0002, 0x0000, NULL, 0); 116 aim_putsnac(&fr->data, 0x0004, 0x0002, 0x0000, snacid); 117 118 /* This is read-only (see Parameter Reply). Must be set to zero here. */ 119 aimbs_put16(&fr->data, 0x0000); 120 121 /* These are all read-write */ 122 aimbs_put32(&fr->data, params->flags); 123 aimbs_put16(&fr->data, params->maxmsglen); 124 aimbs_put16(&fr->data, params->maxsenderwarn); 125 aimbs_put16(&fr->data, params->maxrecverwarn); 126 aimbs_put32(&fr->data, params->minmsginterval); 127 128 aim_tx_enqueue(sess, fr); 129 130 return 0; 131 } 132 133 /* Subtype 0x0004 - Request ICBM parameter information. */ 134 faim_export int aim_reqicbmparams(aim_session_t *sess) 135 { 136 aim_conn_t *conn; 137 138 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) 139 return -EINVAL; 140 141 return aim_genericreq_n(sess, conn, 0x0004, 0x0004); 142 } 143 144 /* Subtype 0x0005 */ 145 static int paraminfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 146 { 147 struct aim_icbmparameters params; 148 aim_rxcallback_t userfunc; 149 150 params.maxchan = aimbs_get16(bs); 151 params.flags = aimbs_get32(bs); 152 params.maxmsglen = aimbs_get16(bs); 153 params.maxsenderwarn = aimbs_get16(bs); 154 params.maxrecverwarn = aimbs_get16(bs); 155 params.minmsginterval = aimbs_get32(bs); 156 157 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 158 return userfunc(sess, rx, ¶ms); 159 160 return 0; 161 } 162 86 163 /* This should be endian-safe now... but who knows... */ 87 164 faim_export fu16_t aim_iconsum(const fu8_t *buf, int buflen) … … 101 178 102 179 /* 103 * S end an ICBM (instant message).180 * Subtype 0x0006 - Send an ICBM (instant message). 104 181 * 105 182 * … … 195 272 } 196 273 197 198 274 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, msgtlvlen+128))) 199 275 return -ENOMEM; … … 315 391 /* 316 392 * Set the I HAVE A REALLY PURTY ICON flag. 393 * XXX - This should really only be sent on initial 394 * IMs and when you change your icon. 317 395 */ 318 396 if (args->flags & AIM_IMFLAGS_HASICON) { … … 327 405 /* 328 406 * Set the Buddy Icon Requested flag. 407 * XXX - Everytime? Surely not... 329 408 */ 330 409 if (args->flags & AIM_IMFLAGS_BUDDYREQ) { … … 367 446 368 447 /* 448 * Subtype 0x0006 449 * 369 450 * This is also performance sensitive. (If you can believe it...) 370 451 * … … 450 531 451 532 /* 533 * Subtype 0x0006 534 * 452 535 * This only works for ICQ 2001b (thats 2001 not 2000). Better, only 453 536 * send it to clients advertising the RTF capability. In fact, if you send … … 565 648 } 566 649 650 /* Subtype 0x0006 */ 567 651 faim_internal int aim_request_directim(aim_session_t *sess, const char *destsn, fu8_t *ip, fu16_t port, fu8_t *ckret) 568 652 { … … 641 725 } 642 726 727 /* Subtype 0x0006 */ 643 728 faim_internal int aim_request_sendfile(aim_session_t *sess, const char *sn, const char *filename, fu16_t numfiles, fu32_t totsize, fu8_t *ip, fu16_t port, fu8_t *ckret) 644 729 { … … 648 733 aim_frame_t *fr; 649 734 aim_snacid_t snacid; 735 struct aim_snac_destructor snacdest; 650 736 651 737 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) … … 657 743 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn)+2+2+2+8+16+6+8+6+4+2+2+2+2+4+strlen(filename)+4))) 658 744 return -ENOMEM; 659 660 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);661 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);662 745 663 746 for (i = 0; i < 7; i++) … … 667 750 if (ckret) 668 751 memcpy(ckret, ck, 8); 752 753 /* Fill in the snac destructor so we know if the request 754 * times out. Use the cookie in the data field, so we 755 * know what request to cancel if there is an error. 756 */ 757 snacdest.data = malloc(8); 758 memcpy(snacdest.data, ck, 8); 759 snacdest.conn = conn; 760 snacid = aim_cachesnac(sess, 0x0004, 0x0006, AIM_SNACFLAGS_DESTRUCTOR, &snacdest, sizeof(snacdest)); 761 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); 669 762 670 763 /* … … 720 813 721 814 /* ? */ 722 aimbs_put16(&fr->data, 0x0001);815 aimbs_put16(&fr->data, (numfiles > 1) ? 0x0002 : 0x0001); 723 816 aimbs_put16(&fr->data, numfiles); 724 817 aimbs_put32(&fr->data, totsize); … … 727 820 /* ? */ 728 821 aimbs_put32(&fr->data, 0x00000000); 822 823 #if 0 824 /* Newer clients seem to send this (?) -- wtm */ 825 aimbs_put32(&fr->data, 0x00030000); 826 #endif 827 828 aim_tx_enqueue(sess, fr); 829 830 return 0; 831 } 832 833 /** 834 * Subtype 0x0006 - Request the status message of the given ICQ user. 835 * 836 * @param sess The oscar session. 837 * @param sn The UIN of the user of whom you wish to request info. 838 * @param type The type of info you wish to request. This should be the current 839 * state of the user, as one of the AIM_ICQ_STATE_* defines. 840 * @return Return 0 if no errors, otherwise return the error number. 841 */ 842 faim_export int aim_send_im_ch2_geticqmessage(aim_session_t *sess, const char *sn, int type) 843 { 844 aim_conn_t *conn; 845 int i; 846 fu8_t ck[8]; 847 aim_frame_t *fr; 848 aim_snacid_t snacid; 849 850 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !sn) 851 return -EINVAL; 852 853 for (i = 0; i < 8; i++) 854 aimutil_put8(ck+i, (fu8_t) rand()); 855 856 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn) + 4+0x5e + 4))) 857 return -ENOMEM; 858 859 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); 860 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); 861 862 /* Cookie */ 863 aimbs_putraw(&fr->data, ck, 8); 864 865 /* Channel (2) */ 866 aimbs_put16(&fr->data, 0x0002); 867 868 /* Dest sn */ 869 aimbs_put8(&fr->data, strlen(sn)); 870 aimbs_putraw(&fr->data, sn, strlen(sn)); 871 872 /* TLV t(0005) - Encompasses almost everything below. */ 873 aimbs_put16(&fr->data, 0x0005); /* T */ 874 aimbs_put16(&fr->data, 0x005e); /* L */ 875 { /* V */ 876 aimbs_put16(&fr->data, 0x0000); 877 878 /* Cookie */ 879 aimbs_putraw(&fr->data, ck, 8); 880 881 /* Put the 16 byte server relay capability */ 882 aim_putcap(&fr->data, AIM_CAPS_ICQSERVERRELAY); 883 884 /* TLV t(000a) */ 885 aimbs_put16(&fr->data, 0x000a); 886 aimbs_put16(&fr->data, 0x0002); 887 aimbs_put16(&fr->data, 0x0001); 888 889 /* TLV t(000f) */ 890 aimbs_put16(&fr->data, 0x000f); 891 aimbs_put16(&fr->data, 0x0000); 892 893 /* TLV t(2711) */ 894 aimbs_put16(&fr->data, 0x2711); 895 aimbs_put16(&fr->data, 0x0036); 896 { /* V */ 897 aimbs_putle16(&fr->data, 0x001b); /* L */ 898 aimbs_putle16(&fr->data, 0x0008); /* XXX - Protocol version */ 899 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ 900 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ 901 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ 902 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ 903 aimbs_putle16(&fr->data, 0x0000); /* Unknown */ 904 aimbs_putle16(&fr->data, 0x0003); /* Client features? */ 905 aimbs_putle16(&fr->data, 0x0000); /* Unknown */ 906 aimbs_putle8(&fr->data, 0x00); /* Unkizown */ 907 aimbs_putle16(&fr->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */ 908 909 aimbs_putle16(&fr->data, 0x000e); /* L */ 910 aimbs_putle16(&fr->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */ 911 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ 912 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ 913 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ 914 915 /* The type of status message being requested */ 916 if (type & AIM_ICQ_STATE_CHAT) 917 aimbs_putle16(&fr->data, 0x03ec); 918 else if(type & AIM_ICQ_STATE_DND) 919 aimbs_putle16(&fr->data, 0x03eb); 920 else if(type & AIM_ICQ_STATE_OUT) 921 aimbs_putle16(&fr->data, 0x03ea); 922 else if(type & AIM_ICQ_STATE_BUSY) 923 aimbs_putle16(&fr->data, 0x03e9); 924 else if(type & AIM_ICQ_STATE_AWAY) 925 aimbs_putle16(&fr->data, 0x03e8); 926 927 aimbs_putle16(&fr->data, 0x0000); /* Status? */ 928 aimbs_putle16(&fr->data, 0x0001); /* Priority of this message? */ 929 aimbs_putle16(&fr->data, 0x0001); /* L? */ 930 aimbs_putle8(&fr->data, 0x00); /* Null termination? */ 931 } /* End TLV t(2711) */ 932 } /* End TLV t(0005) */ 933 934 /* TLV t(0003) */ 935 aimbs_put16(&fr->data, 0x0003); 936 aimbs_put16(&fr->data, 0x0000); 937 938 aim_tx_enqueue(sess, fr); 939 940 return 0; 941 } 942 943 /** 944 * Subtype 0x0006 945 * 946 * This can be used to send an ICQ authorization reply (deny or grant). It is the "old way." 947 * The new way is to use SSI. I like the new way a lot better. This seems like such a hack, 948 * mostly because it's in network byte order. Figuring this stuff out sometimes takes a while, 949 * but thats ok, because it gives me time to try to figure out what kind of drugs the AOL people 950 * were taking when they merged the two protocols. 951 * 952 * @param sn The destination screen name. 953 * @param type The type of message. 0x0007 for authorization denied. 0x0008 for authorization granted. 954 * @param message The message you want to send, it should be null terminated. 955 * @return Return 0 if no errors, otherwise return the error number. 956 */ 957 faim_export int aim_send_im_ch4(aim_session_t *sess, char *sn, fu16_t type, fu8_t *message) 958 { 959 aim_conn_t *conn; 960 aim_frame_t *fr; 961 aim_snacid_t snacid; 962 int i; 963 964 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0002))) 965 return -EINVAL; 966 967 if (!sn || !type || !message) 968 return -EINVAL; 969 970 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+3+strlen(sn)+12+strlen(message)+1+4))) 971 return -ENOMEM; 972 973 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); 974 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); 975 976 /* 977 * Cookie 978 */ 979 for (i=0; i<8; i++) 980 aimbs_put8(&fr->data, (fu8_t)rand()); 981 982 /* 983 * Channel (4) 984 */ 985 aimbs_put16(&fr->data, 0x0004); 986 987 /* 988 * Dest sn 989 */ 990 aimbs_put8(&fr->data, strlen(sn)); 991 aimbs_putraw(&fr->data, sn, strlen(sn)); 992 993 /* 994 * TLV t(0005) 995 * 996 * ICQ data (the UIN and the message). 997 */ 998 aimbs_put16(&fr->data, 0x0005); 999 aimbs_put16(&fr->data, 4 + 2+2+strlen(message)+1); 1000 1001 /* 1002 * Your UIN 1003 */ 1004 aimbs_putle32(&fr->data, atoi(sess->sn)); 1005 1006 /* 1007 * TLV t(type) l(strlen(message)+1) v(message+NULL) 1008 */ 1009 aimbs_putle16(&fr->data, type); 1010 aimbs_putle16(&fr->data, strlen(message)+1); 1011 aimbs_putraw(&fr->data, message, strlen(message)+1); 1012 1013 /* 1014 * TLV t(0006) l(0000) v() 1015 */ 1016 aimbs_put16(&fr->data, 0x0006); 1017 aimbs_put16(&fr->data, 0x0000); 729 1018 730 1019 aim_tx_enqueue(sess, fr); … … 1157 1446 args.icbmflags |= AIM_IMFLAGS_BUDDYREQ; 1158 1447 1448 } else if (type == 0x000b) { /* Non-direct connect typing notification */ 1449 1450 args.icbmflags |= AIM_IMFLAGS_TYPINGNOT; 1451 1159 1452 } else if (type == 0x0017) { 1160 1453 … … 1331 1624 } 1332 1625 1626 static void incomingim_ch2_sendfile_free(aim_session_t *sess, struct aim_incomingim_ch2_args *args) 1627 { 1628 free(args->info.sendfile.filename); 1629 } 1630 1631 static void incomingim_ch2_sendfile(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, aim_bstream_t *servdata) 1632 { 1633 1634 args->destructor = (void *)incomingim_ch2_sendfile_free; 1635 1636 if (servdata) { 1637 int flen; 1638 1639 /* subtype is one of AIM_OFT_SUBTYPE_* */ 1640 args->info.sendfile.subtype = aimbs_get16(servdata); 1641 args->info.sendfile.totfiles = aimbs_get16(servdata); 1642 args->info.sendfile.totsize = aimbs_get32(servdata); 1643 1644 /* XXX - create an aimbs_getnullstr function */ 1645 /* Use an inelegant way of getting the null-terminated filename, 1646 * since there's no easy bstream routine. */ 1647 for (flen = 0; aimbs_get8(servdata); flen++); 1648 aim_bstream_advance(servdata, -flen -1); 1649 args->info.sendfile.filename = aimbs_getstr(servdata, flen); 1650 1651 /* There is sometimes more after the null-terminated filename, 1652 * but I'm unsure of its format. */ 1653 } 1654 1655 return; 1656 } 1657 1333 1658 typedef void (*ch2_args_destructor_t)(aim_session_t *sess, struct aim_incomingim_ch2_args *args); 1334 1659 … … 1358 1683 * First two bytes represent the status of the connection. 1359 1684 * 1360 * 0 is a request, 1 is a deny (?), 2 is an accept1685 * 0 is a request, 1 is a cancel, 2 is an accept 1361 1686 */ 1362 1687 args.status = aimbs_get16(&bbs); … … 1502 1827 else if (args.reqclass & AIM_CAPS_ICQSERVERRELAY) 1503 1828 incomingim_ch2_icqserverrelay(sess, mod, rx, snac, userinfo, &args, sdbsptr); 1829 else if (args.reqclass & AIM_CAPS_SENDFILE) 1830 incomingim_ch2_sendfile(sess, mod, rx, snac, userinfo, &args, sdbsptr); 1504 1831 1505 1832 … … 1520 1847 } 1521 1848 1849 static int incomingim_ch4(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, fu16_t channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, fu8_t *cookie) 1850 { 1851 aim_bstream_t meat; 1852 aim_rxcallback_t userfunc; 1853 aim_tlv_t *block; 1854 struct aim_incomingim_ch4_args args; 1855 int ret = 0; 1856 1857 /* 1858 * Make a bstream for the meaty part. Yum. Meat. 1859 */ 1860 if (!(block = aim_gettlv(tlvlist, 0x0005, 1))) 1861 return -1; 1862 aim_bstream_init(&meat, block->value, block->length); 1863 1864 args.uin = aimbs_getle32(&meat); 1865 args.type = aimbs_getle16(&meat); 1866 args.msg = aimbs_getraw(&meat, aimbs_getle16(&meat)); 1867 1868 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1869 ret = userfunc(sess, rx, channel, userinfo, &args); 1870 1871 free(args.msg); 1872 1873 return ret; 1874 } 1875 1522 1876 /* 1877 * Subtype 0x0007 1878 * 1523 1879 * It can easily be said that parsing ICBMs is THE single 1524 1880 * most difficult thing to do in the in AIM protocol. In … … 1557 1913 * is where Chat Invitiations and various client-client 1558 1914 * connection negotiations come from. 1559 * 1915 * 1916 * Channel 0x0004 is used for ICQ authorization, or 1917 * possibly any system notice. 1918 * 1560 1919 */ 1561 1920 channel = aimbs_get16(bs); … … 1603 1962 aim_freetlvchain(&tlvlist); 1604 1963 1964 } else if (channel == 4) { 1965 aim_tlvlist_t *tlvlist; 1966 1967 tlvlist = aim_readtlvchain(bs); 1968 ret = incomingim_ch4(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie); 1969 aim_freetlvchain(&tlvlist); 1970 1605 1971 } else { 1606 1972 … … 1614 1980 1615 1981 /* 1982 * Subtype 0x0008 - Send a warning to destsn. 1983 * 1984 * Flags: 1985 * AIM_WARN_ANON Send as an anonymous (doesn't count as much) 1986 * 1987 * returns -1 on error (couldn't alloc packet), 0 on success. 1988 * 1989 */ 1990 faim_export int aim_send_warning(aim_session_t *sess, aim_conn_t *conn, const char *destsn, fu32_t flags) 1991 { 1992 aim_frame_t *fr; 1993 aim_snacid_t snacid; 1994 fu16_t outflags = 0x0000; 1995 1996 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, strlen(destsn)+13))) 1997 return -ENOMEM; 1998 1999 snacid = aim_cachesnac(sess, 0x0004, 0x0008, 0x0000, destsn, strlen(destsn)+1); 2000 2001 aim_putsnac(&fr->data, 0x0004, 0x0008, 0x0000, snacid); 2002 2003 if (flags & AIM_WARN_ANON) 2004 outflags |= 0x0001; 2005 2006 aimbs_put16(&fr->data, outflags); 2007 aimbs_put8(&fr->data, strlen(destsn)); 2008 aimbs_putraw(&fr->data, destsn, strlen(destsn)); 2009 2010 aim_tx_enqueue(sess, fr); 2011 2012 return 0; 2013 } 2014 2015 /* Subtype 0x000a */ 2016 static int missedcall(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 2017 { 2018 int ret = 0; 2019 aim_rxcallback_t userfunc; 2020 fu16_t channel, nummissed, reason; 2021 aim_userinfo_t userinfo; 2022 2023 while (aim_bstream_empty(bs)) { 2024 2025 channel = aimbs_get16(bs); 2026 aim_extractuserinfo(sess, bs, &userinfo); 2027 nummissed = aimbs_get16(bs); 2028 reason = aimbs_get16(bs); 2029 2030 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 2031 ret = userfunc(sess, rx, channel, &userinfo, nummissed, reason); 2032 } 2033 2034 return ret; 2035 } 2036 2037 /* 2038 * Subtype 0x000b 2039 * 1616 2040 * Possible codes: 1617 2041 * AIM_TRANSFER_DENY_NOTSUPPORTED -- "client does not support" … … 1652 2076 1653 2077 /* 1654 * aim_reqicbmparaminfo()1655 * 1656 * Request ICBM parameter information.2078 * Subtype 0x000b - Receive the response from an ICQ status message request. 2079 * 2080 * This contains the ICQ status message. Go figure. 1657 2081 * 1658 2082 */ 1659 faim_export int aim_reqicbmparams(aim_session_t *sess) 1660 { 1661 aim_conn_t *conn; 1662 1663 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) 1664 return -EINVAL; 1665 1666 return aim_genericreq_n(sess, conn, 0x0004, 0x0004); 1667 } 1668 1669 /* 1670 * 1671 * I definitly recommend sending this. If you don't, you'll be stuck 1672 * with the rather unreasonable defaults. You don't want those. Send this. 1673 * 1674 */ 1675 faim_export int aim_seticbmparam(aim_session_t *sess, struct aim_icbmparameters *params) 1676 { 1677 aim_conn_t *conn; 1678 aim_frame_t *fr; 1679 aim_snacid_t snacid; 1680 1681 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) 1682 return -EINVAL; 1683 1684 if (!params) 1685 return -EINVAL; 1686 1687 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+16))) 1688 return -ENOMEM; 1689 1690 snacid = aim_cachesnac(sess, 0x0004, 0x0002, 0x0000, NULL, 0); 1691 aim_putsnac(&fr->data, 0x0004, 0x0002, 0x0000, snacid); 1692 1693 /* This is read-only (see Parameter Reply). Must be set to zero here. */ 1694 aimbs_put16(&fr->data, 0x0000); 1695 1696 /* These are all read-write */ 1697 aimbs_put32(&fr->data, params->flags); 1698 aimbs_put16(&fr->data, params->maxmsglen); 1699 aimbs_put16(&fr->data, params->maxsenderwarn); 1700 aimbs_put16(&fr->data, params->maxrecverwarn); 1701 aimbs_put32(&fr->data, params->minmsginterval); 1702 1703 aim_tx_enqueue(sess, fr); 1704 1705 return 0; 1706 } 1707 1708 static int paraminfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1709 { 1710 struct aim_icbmparameters params; 1711 aim_rxcallback_t userfunc; 1712 1713 params.maxchan = aimbs_get16(bs); 1714 params.flags = aimbs_get32(bs); 1715 params.maxmsglen = aimbs_get16(bs); 1716 params.maxsenderwarn = aimbs_get16(bs); 1717 params.maxrecverwarn = aimbs_get16(bs); 1718 params.minmsginterval = aimbs_get32(bs); 1719 1720 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1721 return userfunc(sess, rx, ¶ms); 1722 1723 return 0; 1724 } 1725 1726 static int missedcall(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1727 { 1728 int ret = 0; 1729 aim_rxcallback_t userfunc; 1730 fu16_t channel, nummissed, reason; 1731 aim_userinfo_t userinfo; 1732 1733 while (aim_bstream_empty(bs)) { 1734 1735 channel = aimbs_get16(bs); 1736 aim_extractuserinfo(sess, bs, &userinfo); 1737 nummissed = aimbs_get16(bs); 1738 reason = aimbs_get16(bs); 1739 1740 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1741 ret = userfunc(sess, rx, channel, &userinfo, nummissed, reason); 1742 } 1743 1744 return ret; 1745 } 1746 1747 static int clienterr(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 2083 static int clientautoresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1748 2084 { 1749 2085 int ret = 0; … … 1759 2095 reason = aimbs_get16(bs); 1760 2096 1761 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1762 ret = userfunc(sess, rx, channel, sn, reason); 2097 if (channel == 0x0002) { /* File transfer declined */ 2098 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 2099 ret = userfunc(sess, rx, channel, sn, reason, ck); 2100 } else if (channel == 0x0004) { /* ICQ message */ 2101 switch (reason) { 2102 case 0x0003: { /* ICQ status message. Maybe other stuff too, you never know with these people. */ 2103 fu8_t statusmsgtype, *msg; 2104 fu16_t len; 2105 fu32_t state; 2106 2107 len = aimbs_getle16(bs); /* Should be 0x001b */ 2108 aim_bstream_advance(bs, len); /* Unknown */ 2109 2110 len = aimbs_getle16(bs); /* Should be 0x000e */ 2111 aim_bstream_advance(bs, len); /* Unknown */ 2112 2113 statusmsgtype = aimbs_getle8(bs); 2114 switch (statusmsgtype) { 2115 case 0xe8: 2116 state = AIM_ICQ_STATE_AWAY; 2117 break; 2118 case 0xe9: 2119 state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY; 2120 break; 2121 case 0xea: 2122 state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_OUT; 2123 break; 2124 case 0xeb: 2125 state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY; 2126 break; 2127 case 0xec: 2128 state = AIM_ICQ_STATE_CHAT; 2129 break; 2130 default: 2131 state = 0; 2132 break; 2133 } 2134 2135 aimbs_getle8(bs); /* Unknown - 0x03 Maybe this means this is an auto-reply */ 2136 aimbs_getle16(bs); /* Unknown - 0x0000 */ 2137 aimbs_getle16(bs); /* Unknown - 0x0000 */ 2138 2139 len = aimbs_getle16(bs); 2140 msg = aimbs_getraw(bs, len); 2141 2142 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 2143 ret = userfunc(sess, rx, channel, sn, reason, state, msg); 2144 2145 free(msg); 2146 } break; 2147 2148 default: { 2149 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 2150 ret = userfunc(sess, rx, channel, sn, reason); 2151 } break; 2152 } /* end switch */ 2153 } 1763 2154 1764 2155 free(ck); … … 1768 2159 } 1769 2160 2161 /* Subtype 0x000c */ 1770 2162 static int msgack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1771 2163 { … … 1786 2178 free(sn); 1787 2179 free(ck); 2180 2181 return ret; 2182 } 2183 2184 /* 2185 * Subtype 0x0014 - Send a mini typing notification (mtn) packet. 2186 * 2187 * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer, 2188 * and Gaim 0.60 and newer. 2189 * 2190 */ 2191 faim_export int aim_mtn_send(aim_session_t *sess, fu16_t type1, char *sn, fu16_t type2) 2192 { 2193 aim_conn_t *conn; 2194 aim_frame_t *fr; 2195 aim_snacid_t snacid; 2196 2197 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0002))) 2198 return -EINVAL; 2199 2200 if (!sn) 2201 return -EINVAL; 2202 2203 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+11+strlen(sn)+2))) 2204 return -ENOMEM; 2205 2206 snacid = aim_cachesnac(sess, 0x0004, 0x0014, 0x0000, NULL, 0); 2207 aim_putsnac(&fr->data, 0x0004, 0x0014, 0x0000, snacid); 2208 2209 /* 2210 * 8 days of light 2211 * Er, that is to say, 8 bytes of 0's 2212 */ 2213 aimbs_put16(&fr->data, 0x0000); 2214 aimbs_put16(&fr->data, 0x0000); 2215 aimbs_put16(&fr->data, 0x0000); 2216 aimbs_put16(&fr->data, 0x0000); 2217 2218 /* 2219 * Type 1 (should be 0x0001 for mtn) 2220 */ 2221 aimbs_put16(&fr->data, type1); 2222 2223 /* 2224 * Dest sn 2225 */ 2226 aimbs_put8(&fr->data, strlen(sn)); 2227 aimbs_putraw(&fr->data, sn, strlen(sn)); 2228 2229 /* 2230 * Type 2 (should be 0x0000, 0x0001, or 0x0002 for mtn) 2231 */ 2232 aimbs_put16(&fr->data, type2); 2233 2234 aim_tx_enqueue(sess, fr); 2235 2236 return 0; 2237 } 2238 2239 /* 2240 * Subtype 0x0014 - Receive a mini typing notification (mtn) packet. 2241 * 2242 * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer, 2243 * and Gaim 0.60 and newer. 2244 * 2245 */ 2246 static int mtn_receive(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 2247 { 2248 int ret = 0; 2249 aim_rxcallback_t userfunc; 2250 char *sn; 2251 fu8_t snlen; 2252 fu16_t type1, type2; 2253 2254 aim_bstream_advance(bs, 8); /* Unknown - All 0's */ 2255 type1 = aimbs_get16(bs); 2256 snlen = aimbs_get8(bs); 2257 sn = aimbs_getstr(bs, snlen); 2258 type2 = aimbs_get16(bs); 2259 2260 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 2261 ret = userfunc(sess, rx, type1, sn, type2); 2262 2263 free(sn); 1788 2264 1789 2265 return ret; … … 1802 2278 return missedcall(sess, mod, rx, snac, bs); 1803 2279 else if (snac->subtype == 0x000b) 1804 return client err(sess, mod, rx, snac, bs);2280 return clientautoresp(sess, mod, rx, snac, bs); 1805 2281 else if (snac->subtype == 0x000c) 1806 2282 return msgack(sess, mod, rx, snac, bs); 2283 else if (snac->subtype == 0x0014) 2284 return mtn_receive(sess, mod, rx, snac, bs); 1807 2285 1808 2286 return 0; 2287 } 2288 2289 static int snacdestructor(aim_session_t *sess, aim_conn_t *conn, aim_modsnac_t *snac, void *data) 2290 { 2291 aim_rxcallback_t userfunc; 2292 int ret = 0; 2293 2294 if (snac->subtype == 0x0006) { 2295 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_MSGTIMEOUT))) 2296 ret = userfunc(sess, NULL, conn, data); 2297 } 2298 /* Note that we return 1 for success, 0 for failure. */ 2299 return ret; 1809 2300 } 1810 2301 … … 1819 2310 strncpy(mod->name, "messaging", sizeof(mod->name)); 1820 2311 mod->snachandler = snachandler; 2312 mod->snacdestructor = snacdestructor; 1821 2313 1822 2314 return 0; -
libfaim/info.c
r5e53c4a r862371b 1 1 /* 2 * aim_info.c2 * Family 0x0002 - Information. 3 3 * 4 4 * The functions here are responsible for requesting and parsing information- … … 15 15 }; 16 16 17 /* 18 * Subtype 0x0002 19 * 20 * Request Location services rights. 21 * 22 */ 23 faim_export int aim_bos_reqlocaterights(aim_session_t *sess, aim_conn_t *conn) 24 { 25 return aim_genericreq_n(sess, conn, 0x0002, 0x0002); 26 } 27 28 /* 29 * Subtype 0x0004 30 * 31 * Gives BOS your profile. 32 * 33 */ 34 faim_export int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profile, const char *awaymsg, fu32_t caps) 35 { 36 static const char defencoding[] = {"text/aolrtf; charset=\"us-ascii\""}; 37 aim_frame_t *fr; 38 aim_tlvlist_t *tl = NULL; 39 aim_snacid_t snacid; 40 41 /* Build to packet first to get real length */ 42 if (profile) { 43 aim_addtlvtochain_raw(&tl, 0x0001, strlen(defencoding), defencoding); 44 aim_addtlvtochain_raw(&tl, 0x0002, strlen(profile), profile); 45 } 46 47 /* 48 * So here's how this works: 49 * - You are away when you have a non-zero-length type 4 TLV stored. 50 * - You become unaway when you clear the TLV with a zero-length 51 * type 4 TLV. 52 * - If you do not send the type 4 TLV, your status does not change 53 * (that is, if you were away, you'll remain away). 54 */ 55 if (awaymsg) { 56 if (strlen(awaymsg)) { 57 aim_addtlvtochain_raw(&tl, 0x0003, strlen(defencoding), defencoding); 58 aim_addtlvtochain_raw(&tl, 0x0004, strlen(awaymsg), awaymsg); 59 } else 60 aim_addtlvtochain_noval(&tl, 0x0004); 61 } 62 63 aim_addtlvtochain_caps(&tl, 0x0005, caps); 64 65 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + aim_sizetlvchain(&tl)))) 66 &