Changeset e374dee
- Timestamp:
- Oct 10, 2003, 5:12:30 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:
- fe6f1d3
- Parents:
- f4d0975
- Location:
- libfaim
- Files:
-
- 32 edited
Legend:
- Unmodified
- Added
- Removed
-
libfaim/admin.c
r862371b re374dee 4 4 * Used for stuff like changing the formating of your screen name, changing your 5 5 * email address, requesting an account confirmation email, getting account info, 6 * 6 * 7 7 */ 8 8 … … 197 197 static int accountconfirm(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 198 198 { 199 int ret = 0; 199 200 aim_rxcallback_t userfunc; 200 201 fu16_t status; … … 207 208 208 209 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 209 ret urnuserfunc(sess, rx, status);210 211 return 0;210 ret = userfunc(sess, rx, status); 211 212 return ret; 212 213 } 213 214 … … 228 229 mod->family = 0x0007; 229 230 mod->version = 0x0001; 230 mod->toolid = AIM_TOOL_NEWWIN;231 mod->toolversion = 0x0 361; /* XXX this and above aren't right */231 mod->toolid = 0x0010; 232 mod->toolversion = 0x0629; 232 233 mod->flags = 0; 233 234 strncpy(mod->name, "admin", sizeof(mod->name)); -
libfaim/aim.h
r862371b re374dee 3 3 * 4 4 * "come on, i turned a chick lesbian; i think this is the hackish equivalent" 5 * -- Josh M eyer5 * -- Josh Myer 6 6 * 7 7 */ … … 29 29 #include <sys/time.h> 30 30 #include <unistd.h> 31 #include <netdb.h> 31 32 #include <netinet/in.h> 32 33 #include <sys/socket.h> … … 35 36 #endif 36 37 38 #ifdef __cplusplus 39 extern "C" { 40 #endif 41 37 42 /* XXX adjust these based on autoconf-detected platform */ 38 43 typedef unsigned char fu8_t; 39 44 typedef unsigned short fu16_t; 40 typedef unsigned longfu32_t;45 typedef unsigned int fu32_t; 41 46 typedef fu32_t aim_snacid_t; 42 47 typedef fu16_t flap_seqnum_t; … … 44 49 #if defined(mach) && defined(__APPLE__) 45 50 #define gethostbyname(x) gethostbyname2(x, AF_INET) 46 #endif47 48 #if defined(_WIN32) || defined(STRICT_ANSI)49 #define faim_shortfunc50 #else51 #define faim_shortfunc inline52 51 #endif 53 52 … … 73 72 #endif 74 73 74 #ifndef FALSE 75 #define FALSE (0) 76 #endif 77 78 #ifndef TRUE 79 #define TRUE (!FALSE) 80 #endif 81 75 82 /* 76 83 * Current Maximum Length for Screen Names (not including NULL) … … 79 86 * however it is aparently legal for them to be larger. 80 87 */ 81 #define MAXSNLEN 3288 #define MAXSNLEN 97 82 89 83 90 /* … … 114 121 #define MAXCHATMSGLEN 512 115 122 116 /* 117 * Standard size of an AIM authorization cookie118 */ 119 #define AIM_COOKIELEN 0x100123 /** 124 * Maximum length for the password of an ICQ account 125 */ 126 #define MAXICQPASSLEN 8 120 127 121 128 #define AIM_MD5_STRING "AOL Instant Messenger (SM)" … … 130 137 const char *clientstring; 131 138 fu16_t clientid; 132 int major; 133 int minor; 134 int point; 135 int build; 139 fu16_t major; 140 fu16_t minor; 141 fu16_t point; 142 fu16_t build; 143 fu32_t distrib; 136 144 const char *country; /* two-letter abbrev */ 137 145 const char *lang; /* two-letter abbrev */ 138 146 }; 139 147 148 /* Needs to be checked */ 140 149 #define CLIENTINFO_AIM_3_5_1670 { \ 141 150 "AOL Instant Messenger (SM), version 3.5.1670/WIN32", \ 142 151 0x0004, \ 143 0x0003, \ 144 0x0005, \ 145 0x0000, \ 146 0x0686, \ 147 "us", \ 148 "en", \ 152 0x0003, 0x0005, \ 153 0x0000, 0x0686, \ 154 0x0000002a, \ 155 "us", "en", \ 149 156 } 150 157 158 /* Needs to be checked */ 159 /* Latest winaim without ssi */ 151 160 #define CLIENTINFO_AIM_4_1_2010 { \ 152 "AOL Instant Messenger (SM), version 4.1.2010/WIN32", \ 153 0x0004, \ 154 0x0004, \ 155 0x0001, \ 156 0x0000, \ 157 0x07da, \ 158 "us", \ 159 "en", \ 161 "AOL Instant Messenger (SM), version 4.1.2010/WIN32", \ 162 0x0004, \ 163 0x0004, 0x0001, \ 164 0x0000, 0x07da, \ 165 0x0000004b, \ 166 "us", "en", \ 160 167 } 161 168 169 /* Needs to be checked */ 170 #define CLIENTINFO_AIM_4_3_2188 { \ 171 "AOL Instant Messenger (SM), version 4.3.2188/WIN32", \ 172 0x0109, \ 173 0x0400, 0x0003, \ 174 0x0000, 0x088c, \ 175 0x00000086, \ 176 "us", "en", \ 177 } 178 179 /* Needs to be checked */ 180 #define CLIENTINFO_AIM_4_8_2540 { \ 181 "AOL Instant Messenger (SM), version 4.8.2540/WIN32", \ 182 0x0109, \ 183 0x0004, 0x0008, \ 184 0x0000, 0x09ec, \ 185 0x000000af, \ 186 "us", "en", \ 187 } 188 189 /* Needs to be checked */ 162 190 #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", \ 191 "AOL Instant Messenger, version 5.0.2938/WIN32", \ 192 0x0109, \ 193 0x0005, 0x0000, \ 194 0x0000, 0x0b7a, \ 195 0x00000000, \ 196 "us", "en", \ 171 197 } 172 198 199 #define CLIENTINFO_AIM_5_1_3036 { \ 200 "AOL Instant Messenger, version 5.1.3036/WIN32", \ 201 0x0109, \ 202 0x0005, 0x0001, \ 203 0x0000, 0x0bdc, \ 204 0x000000d2, \ 205 "us", "en", \ 206 } 207 208 #define CLIENTINFO_ICHAT_1_0 { \ 209 "Apple iChat", \ 210 0x311a, \ 211 0x0001, 0x0000, \ 212 0x0000, 0x003c, \ 213 0x000000c6, \ 214 "us", "en", \ 215 } 216 217 /* Needs to be checked */ 173 218 #define CLIENTINFO_ICQ_4_65_3281 { \ 174 219 "ICQ Inc. - Product of ICQ (TM) 2000b.4.65.1.3281.85", \ 175 220 0x010a, \ 176 0x0004, \ 177 0x0041, \ 178 0x0001, \ 179 0x0cd1, \ 180 "us", \ 181 "en", \ 221 0x0004, 0x0041, \ 222 0x0001, 0x0cd1, \ 223 0x00000055, \ 224 "us", "en", \ 182 225 } 183 226 227 /* Needs to be checked */ 184 228 #define CLIENTINFO_ICQ_5_34_3728 { \ 185 229 "ICQ Inc. - Product of ICQ (TM).2002a.5.34.1.3728.85", \ 186 230 0x010a, \ 187 0x0005, \ 188 0x0022, \ 189 0x0001, \ 190 0x0e8f, \ 191 "us", \ 192 "en", \ 231 0x0005, 0x0022, \ 232 0x0001, 0x0e8f, \ 233 0x00000055, \ 234 "us", "en", \ 193 235 } 194 236 195 /* 196 * I would make 4.1.2010 the default, but they seem to have found 197 * an alternate way of breaking that one. 198 * 199 * 3.5.1670 should work fine, however, you will be subjected to the 200 * memory test, which may require you to have a WinAIM binary lying 201 * around. (see login.c::memrequest()) 202 */ 203 #define CLIENTINFO_AIM_KNOWNGOOD CLIENTINFO_AIM_3_5_1670 204 #define CLIENTINFO_ICQ_KNOWNGOOD CLIENTINFO_ICQ_4_65_3281 205 206 #ifndef TRUE 207 #define TRUE 1 208 #define FALSE 0 209 #endif 237 #define CLIENTINFO_ICQ_5_45_3777 { \ 238 "ICQ Inc. - Product of ICQ (TM).2003a.5.45.1.3777.85", \ 239 0x010a, \ 240 0x0005, 0x002d, \ 241 0x0001, 0x0ec1, \ 242 0x00000055, \ 243 "us", "en", \ 244 } 245 246 #define CLIENTINFO_ICQBasic_14_3_1068 { \ 247 "ICQBasic", \ 248 0x010a, \ 249 0x0014, 0x0003, \ 250 0x0000, 0x042c, \ 251 0x0000043d, \ 252 "us", "en", \ 253 } 254 255 #define CLIENTINFO_Netscape_7_0_1 { \ 256 "Netscape 2000 an approved user of AOL Instant Messenger (SM)", \ 257 0x1d0d, \ 258 0x0007, 0x0000, \ 259 0x0001, 0x0000, \ 260 0x00000058, \ 261 "us", "en", \ 262 } 263 264 #define CLIENTINFO_AIM_KNOWNGOOD CLIENTINFO_AIM_5_1_3036 265 #define CLIENTINFO_ICQ_KNOWNGOOD CLIENTINFO_ICQ_5_45_3777 210 266 211 267 /* 212 268 * These could be arbitrary, but its easier to use the actual AIM values 213 269 */ 214 #define AIM_CONN_TYPE_AUTH 0x0007 215 #define AIM_CONN_TYPE_ADS 0x0005 216 #define AIM_CONN_TYPE_BOS 0x0002 217 #define AIM_CONN_TYPE_CHAT 0x000e 218 #define AIM_CONN_TYPE_CHATNAV 0x000d 219 #define AIM_CONN_TYPE_SEARCH 0x000f 220 #define AIM_CONN_TYPE_EMAIL 0x0018 221 222 /* they start getting arbitrary in rendezvous stuff =) */ 223 #define AIM_CONN_TYPE_RENDEZVOUS 0x0101 /* these do not speak FLAP! */ 224 #define AIM_CONN_TYPE_RENDEZVOUS_OUT 0x0102 /* socket waiting for accept() */ 270 #define AIM_CONN_TYPE_BOS 0x0002 271 #define AIM_CONN_TYPE_ADS 0x0005 272 #define AIM_CONN_TYPE_AUTH 0x0007 273 #define AIM_CONN_TYPE_CHATNAV 0x000d 274 #define AIM_CONN_TYPE_CHAT 0x000e 275 #define AIM_CONN_TYPE_SEARCH 0x000f 276 #define AIM_CONN_TYPE_ICON 0x0010 277 #define AIM_CONN_TYPE_EMAIL 0x0018 278 279 /* they start getting arbitrary for rendezvous stuff =) */ 280 #define AIM_CONN_TYPE_RENDEZVOUS 0xfffe /* these do not speak FLAP! */ 281 #define AIM_CONN_TYPE_LISTENER 0xffff /* socket waiting for accept() */ 225 282 226 283 /* 227 284 * Subtypes, we need these for OFT stuff. 228 285 */ 229 #define AIM_CONN_SUBTYPE_OFT_DIRECTIM 230 #define AIM_CONN_SUBTYPE_OFT_GETFILE 231 #define AIM_CONN_SUBTYPE_OFT_SENDFILE 232 #define AIM_CONN_SUBTYPE_OFT_BUDDYICON 233 #define AIM_CONN_SUBTYPE_OFT_VOICE 286 #define AIM_CONN_SUBTYPE_OFT_DIRECTIM 0x0001 287 #define AIM_CONN_SUBTYPE_OFT_GETFILE 0x0002 288 #define AIM_CONN_SUBTYPE_OFT_SENDFILE 0x0003 289 #define AIM_CONN_SUBTYPE_OFT_BUDDYICON 0x0004 290 #define AIM_CONN_SUBTYPE_OFT_VOICE 0x0005 234 291 235 292 /* 236 293 * Status values returned from aim_conn_new(). ORed together. 237 294 */ 238 #define AIM_CONN_STATUS_READY 239 #define AIM_CONN_STATUS_INTERNALERR 240 #define AIM_CONN_STATUS_RESOLVERR 241 #define AIM_CONN_STATUS_CONNERR 242 #define AIM_CONN_STATUS_INPROGRESS 243 244 #define AIM_FRAMETYPE_FLAP 245 #define AIM_FRAMETYPE_OFT 295 #define AIM_CONN_STATUS_READY 0x0001 296 #define AIM_CONN_STATUS_INTERNALERR 0x0002 297 #define AIM_CONN_STATUS_RESOLVERR 0x0040 298 #define AIM_CONN_STATUS_CONNERR 0x0080 299 #define AIM_CONN_STATUS_INPROGRESS 0x0100 300 301 #define AIM_FRAMETYPE_FLAP 0x0000 302 #define AIM_FRAMETYPE_OFT 0x0001 246 303 247 304 typedef struct aim_conn_s { … … 289 346 } flap; 290 347 struct { 291 fu8_t magic[4]; /* ODC2 OFT2 */348 fu8_t magic[4]; /* ODC2 or OFT2 */ 292 349 fu16_t hdrlen; 293 350 fu16_t type; … … 297 354 fu8_t handled; /* 0 = new, !0 = been handled */ 298 355 fu8_t nofree; /* 0 = free data on purge, 1 = only unlink */ 299 aim_conn_t *conn; 356 aim_conn_t *conn; /* the connection it came in on... */ 300 357 struct aim_frame_s *next; 301 358 } aim_frame_t; 302 359 303 360 typedef struct aim_msgcookie_s { 304 unsigned charcookie[8];361 fu8_t cookie[8]; 305 362 int type; 306 363 void *data; … … 308 365 struct aim_msgcookie_s *next; 309 366 } aim_msgcookie_t; 367 368 /* Values for sess->flags */ 369 #define AIM_SESS_FLAGS_SNACLOGIN 0x00000001 370 #define AIM_SESS_FLAGS_XORLOGIN 0x00000002 371 #define AIM_SESS_FLAGS_NONBLOCKCONNECT 0x00000004 372 #define AIM_SESS_FLAGS_DONTTIMEOUTONICBM 0x00000008 310 373 311 374 /* … … 331 394 332 395 /* ---- 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;345 396 346 397 /* Connection information */ … … 368 419 int (*tx_enqueue)(struct aim_session_s *, aim_frame_t *); 369 420 421 void *modlistv; 422 423 struct { 424 char server[128]; 425 char username[128]; 426 char password[128]; 427 } socksproxy; 428 429 fu32_t flags; /* AIM_SESS_FLAGS_ */ 430 431 int debug; 432 void (*debugcb)(struct aim_session_s *sess, int level, const char *format, va_list va); /* same as faim_debugging_callback_t */ 433 370 434 /* 371 435 * Outstanding snac handling … … 376 440 aim_snacid_t snacid_next; 377 441 442 aim_msgcookie_t *msgcookies; 443 struct aim_icq_info *icq_info; 444 struct aim_oft_info *oft_info; 445 struct aim_authresp_info *authinfo; 446 struct aim_emailinfo *emailinfo; 447 448 /* Server-stored information (ssi) */ 378 449 struct { 379 char server[128]; 380 char username[128]; 381 char password[128]; 382 } socksproxy; 383 384 fu32_t flags; /* AIM_SESS_FLAGS_ */ 385 386 int debug; 387 void (*debugcb)(struct aim_session_s *sess, int level, const char *format, va_list va); /* same as faim_debugging_callback_t */ 388 389 aim_msgcookie_t *msgcookies; 390 391 void *modlistv; 450 int received_data; 451 fu16_t numitems; 452 struct aim_ssi_item *official; 453 struct aim_ssi_item *local; 454 struct aim_ssi_tmp *pending; 455 time_t timestamp; 456 int waiting_for_ack; 457 } ssi; 392 458 } aim_session_t; 393 459 394 /* Values for sess->flags */395 #define AIM_SESS_FLAGS_SNACLOGIN 0x00000001396 #define AIM_SESS_FLAGS_XORLOGIN 0x00000002397 #define AIM_SESS_FLAGS_NONBLOCKCONNECT 0x00000004398 #define AIM_SESS_FLAGS_DONTTIMEOUTONICBM 0x00000008399 400 460 /* Valid for calling aim_icq_setstatus() and for aim_userinfo_t->icqinfo.status */ 401 #define AIM_ICQ_STATE_NORMAL 0x00000000 402 #define AIM_ICQ_STATE_AWAY 0x00000001 403 #define AIM_ICQ_STATE_DND 0x00000002 404 #define AIM_ICQ_STATE_OUT 0x00000004 405 #define AIM_ICQ_STATE_BUSY 0x00000010 406 #define AIM_ICQ_STATE_CHAT 0x00000020 407 #define AIM_ICQ_STATE_INVISIBLE 0x00000100 408 #define AIM_ICQ_STATE_WEBAWARE 0x00010000 409 410 /* 411 * AIM User Info, Standard Form. 412 */ 413 typedef struct { 414 char sn[MAXSNLEN+1]; 415 fu16_t warnlevel; /* evil percent * 10 (999 = 99.9%) */ 416 fu16_t idletime; /* in seconds */ 417 fu16_t flags; 418 fu32_t createtime; /* time_t */ 419 fu32_t membersince; /* time_t */ 420 fu32_t onlinesince; /* time_t */ 421 fu32_t sessionlen; /* in seconds */ 422 fu32_t capabilities; 423 struct { 424 fu32_t status; 425 fu32_t ipaddr; 426 fu8_t crap[0x25]; /* until we figure it out... */ 427 } icqinfo; 428 fu32_t present; 429 } aim_userinfo_t; 430 431 #define AIM_USERINFO_PRESENT_FLAGS 0x00000001 432 #define AIM_USERINFO_PRESENT_MEMBERSINCE 0x00000002 433 #define AIM_USERINFO_PRESENT_ONLINESINCE 0x00000004 434 #define AIM_USERINFO_PRESENT_IDLE 0x00000008 435 #define AIM_USERINFO_PRESENT_ICQEXTSTATUS 0x00000010 436 #define AIM_USERINFO_PRESENT_ICQIPADDR 0x00000020 437 #define AIM_USERINFO_PRESENT_ICQDATA 0x00000040 438 #define AIM_USERINFO_PRESENT_CAPABILITIES 0x00000080 439 #define AIM_USERINFO_PRESENT_SESSIONLEN 0x00000100 440 #define AIM_USERINFO_PRESENT_CREATETIME 0x00000200 441 442 faim_export const char *aim_userinfo_sn(aim_userinfo_t *ui); 443 faim_export fu16_t aim_userinfo_flags(aim_userinfo_t *ui); 444 faim_export fu16_t aim_userinfo_idle(aim_userinfo_t *ui); 445 faim_export float aim_userinfo_warnlevel(aim_userinfo_t *ui); 446 faim_export time_t aim_userinfo_createtime(aim_userinfo_t *ui); 447 faim_export time_t aim_userinfo_membersince(aim_userinfo_t *ui); 448 faim_export time_t aim_userinfo_onlinesince(aim_userinfo_t *ui); 449 faim_export fu32_t aim_userinfo_sessionlen(aim_userinfo_t *ui); 450 faim_export int aim_userinfo_hascap(aim_userinfo_t *ui, fu32_t cap); 451 452 #define AIM_FLAG_UNCONFIRMED 0x0001 /* "damned transients" */ 453 #define AIM_FLAG_ADMINISTRATOR 0x0002 454 #define AIM_FLAG_AOL 0x0004 455 #define AIM_FLAG_OSCAR_PAY 0x0008 456 #define AIM_FLAG_FREE 0x0010 457 #define AIM_FLAG_AWAY 0x0020 458 #define AIM_FLAG_ICQ 0x0040 459 #define AIM_FLAG_WIRELESS 0x0080 460 #define AIM_FLAG_UNKNOWN100 0x0100 461 #define AIM_FLAG_UNKNOWN200 0x0200 462 #define AIM_FLAG_ACTIVEBUDDY 0x0400 463 #define AIM_FLAG_UNKNOWN800 0x0800 464 #define AIM_FLAG_ABINTERNAL 0x1000 465 466 #define AIM_FLAG_ALLUSERS 0x001f 467 468 469 #if defined(FAIM_INTERNAL) || defined(FAIM_NEED_TLV) 470 /* 471 * TLV handling 472 */ 473 474 /* Generic TLV structure. */ 475 typedef struct aim_tlv_s { 476 fu16_t type; 477 fu16_t length; 478 fu8_t *value; 479 } aim_tlv_t; 480 481 /* List of above. */ 482 typedef struct aim_tlvlist_s { 483 aim_tlv_t *tlv; 484 struct aim_tlvlist_s *next; 485 } aim_tlvlist_t; 486 487 /* TLV-handling functions */ 488 489 #if 0 490 /* Very, very raw TLV handling. */ 491 faim_internal int aim_puttlv_8(fu8_t *buf, const fu16_t t, const fu8_t v); 492 faim_internal int aim_puttlv_16(fu8_t *buf, const fu16_t t, const fu16_t v); 493 faim_internal int aim_puttlv_32(fu8_t *buf, const fu16_t t, const fu32_t v); 494 faim_internal int aim_puttlv_raw(fu8_t *buf, const fu16_t t, const fu16_t l, const fu8_t *v); 495 #endif 496 497 /* TLV list handling. */ 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); 500 faim_internal void aim_freetlvchain(aim_tlvlist_t **list); 501 faim_internal aim_tlv_t *aim_gettlv(aim_tlvlist_t *, fu16_t t, const int n); 502 faim_internal char *aim_gettlv_str(aim_tlvlist_t *, const fu16_t t, const int n); 503 faim_internal fu8_t aim_gettlv8(aim_tlvlist_t *list, const fu16_t type, const int num); 504 faim_internal fu16_t aim_gettlv16(aim_tlvlist_t *list, const fu16_t t, const int n); 505 faim_internal fu32_t aim_gettlv32(aim_tlvlist_t *list, const fu16_t t, const int n); 506 faim_internal int aim_writetlvchain(aim_bstream_t *bs, aim_tlvlist_t **list); 507 faim_internal int aim_addtlvtochain8(aim_tlvlist_t **list, const fu16_t t, const fu8_t v); 508 faim_internal int aim_addtlvtochain16(aim_tlvlist_t **list, const fu16_t t, const fu16_t v); 509 faim_internal int aim_addtlvtochain32(aim_tlvlist_t **list, const fu16_t type, const fu32_t v); 510 faim_internal int aim_addtlvtochain_raw(aim_tlvlist_t **list, const fu16_t t, const fu16_t l, const fu8_t *v); 511 faim_internal int aim_addtlvtochain_caps(aim_tlvlist_t **list, const fu16_t t, const fu32_t caps); 512 faim_internal int aim_addtlvtochain_noval(aim_tlvlist_t **list, const fu16_t type); 513 faim_internal int aim_addtlvtochain_userinfo(aim_tlvlist_t **list, fu16_t type, aim_userinfo_t *ui); 514 faim_internal int aim_addtlvtochain_frozentlvlist(aim_tlvlist_t **list, fu16_t type, aim_tlvlist_t **tl); 515 faim_internal int aim_counttlvchain(aim_tlvlist_t **list); 516 faim_internal int aim_sizetlvchain(aim_tlvlist_t **list); 517 #endif /* FAIM_INTERNAL */ 461 #define AIM_ICQ_STATE_NORMAL 0x00000000 462 #define AIM_ICQ_STATE_AWAY 0x00000001 463 #define AIM_ICQ_STATE_DND 0x00000002 464 #define AIM_ICQ_STATE_OUT 0x00000004 465 #define AIM_ICQ_STATE_BUSY 0x00000010 466 #define AIM_ICQ_STATE_CHAT 0x00000020 467 #define AIM_ICQ_STATE_INVISIBLE 0x00000100 468 #define AIM_ICQ_STATE_WEBAWARE 0x00010000 469 #define AIM_ICQ_STATE_HIDEIP 0x00020000 470 #define AIM_ICQ_STATE_BIRTHDAY 0x00080000 471 #define AIM_ICQ_STATE_DIRECTDISABLED 0x00100000 472 #define AIM_ICQ_STATE_ICQHOMEPAGE 0x00200000 473 #define AIM_ICQ_STATE_DIRECTREQUIREAUTH 0x10000000 474 #define AIM_ICQ_STATE_DIRECTCONTACTLIST 0x20000000 475 518 476 519 477 /* … … 542 500 typedef int (*aim_rxcallback_t)(aim_session_t *, aim_frame_t *, ...); 543 501 502 503 /* auth.c */ 544 504 struct aim_clientrelease { 545 505 char *name; … … 556 516 char *email; 557 517 char *bosip; 518 fu16_t cookielen; 558 519 fu8_t *cookie; 559 520 char *chpassurl; … … 566 527 fu16_t group; 567 528 const char *ip; 529 fu16_t cookielen; 568 530 const fu8_t *cookie; 569 531 struct { /* group == AIM_CONN_TYPE_CHAT */ … … 578 540 faim_export int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn); 579 541 faim_export int aim_send_login(aim_session_t *, aim_conn_t *, const char *, const char *, struct client_info_s *, const char *key); 580 faim_export int aim_encode_password_md5(const char *password, const char *key, unsigned char*digest);542 faim_export int aim_encode_password_md5(const char *password, const char *key, fu8_t *digest); 581 543 faim_export void aim_purge_rxqueue(aim_session_t *); 544 faim_export void aim_cleansnacs(aim_session_t *, int maxage); 582 545 583 546 #define AIM_TX_QUEUED 0 /* default */ … … 591 554 faim_export int aim_conn_setlatency(aim_conn_t *conn, int newval); 592 555 593 faim_export int aim_conn_addhandler(aim_session_t *, aim_conn_t *conn, u_short family, u_short type, aim_rxcallback_t newhandler, u_short flags);556 faim_export int aim_conn_addhandler(aim_session_t *, aim_conn_t *conn, fu16_t family, fu16_t type, aim_rxcallback_t newhandler, fu16_t flags); 594 557 faim_export int aim_clearhandlers(aim_conn_t *conn); 595 558 … … 600 563 faim_export int aim_conngetmaxfd(aim_session_t *); 601 564 faim_export aim_conn_t *aim_select(aim_session_t *, struct timeval *, int *); 565 faim_export int aim_conn_in_sess(aim_session_t *sess, aim_conn_t *conn); 602 566 faim_export int aim_conn_isready(aim_conn_t *); 603 567 faim_export int aim_conn_setstatus(aim_conn_t *, int); … … 607 571 typedef void (*faim_debugging_callback_t)(aim_session_t *sess, int level, const char *format, va_list va); 608 572 faim_export int aim_setdebuggingcb(aim_session_t *sess, faim_debugging_callback_t); 609 faim_export void aim_session_init(aim_session_t *, unsigned longflags, int debuglevel);573 faim_export void aim_session_init(aim_session_t *, fu32_t flags, int debuglevel); 610 574 faim_export void aim_session_kill(aim_session_t *); 611 575 faim_export void aim_setupproxy(aim_session_t *sess, const char *server, const char *username, const char *password); … … 614 578 faim_export aim_conn_t *aim_getconn_fd(aim_session_t *, int fd); 615 579 580 581 582 /* service.c */ 583 faim_export int aim_srv_setavailmsg(aim_session_t *sess, char *msg); 584 585 586 616 587 /* misc.c */ 617 588 … … 627 598 628 599 faim_export int aim_sendpauseack(aim_session_t *sess, aim_conn_t *conn); 629 faim_export int aim_send_warning(aim_session_t *sess, aim_conn_t *conn, const char *destsn, fu32_t flags);630 600 faim_export int aim_nop(aim_session_t *, aim_conn_t *); 631 601 faim_export int aim_flap_nop(aim_session_t *sess, aim_conn_t *conn); … … 633 603 faim_export int aim_bos_changevisibility(aim_session_t *, aim_conn_t *, int, const char *); 634 604 faim_export int aim_bos_setbuddylist(aim_session_t *, aim_conn_t *, const char *); 635 faim_export int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profile , const char *awaymsg, fu32_t caps);605 faim_export int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profile_encoding, const char *profile, const int profile_len, const char *awaymsg_encoding, const char *awaymsg, const int awaymsg_len, fu32_t caps); 636 606 faim_export int aim_bos_setgroupperm(aim_session_t *, aim_conn_t *, fu32_t mask); 637 607 faim_export int aim_bos_setprivacyflags(aim_session_t *, aim_conn_t *, fu32_t); … … 643 613 faim_export int aim_setdirectoryinfo(aim_session_t *sess, aim_conn_t *conn, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, fu16_t privacy); 644 614 faim_export int aim_setuserinterests(aim_session_t *sess, aim_conn_t *conn, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, fu16_t privacy); 645 faim_export int aim_setextstatus(aim_session_t *sess, aim_conn_t *conn, fu32_t status); 646 647 faim_export struct aim_fileheader_t *aim_getlisting(aim_session_t *sess, FILE *); 615 faim_export int aim_setextstatus(aim_session_t *sess, fu32_t status); 648 616 649 617 #define AIM_CLIENTTYPE_UNKNOWN 0x0000 … … 652 620 #define AIM_CLIENTTYPE_WINAIM41 0x0003 653 621 #define AIM_CLIENTTYPE_AOL_TOC 0x0004 654 faim_export unsigned short aim_fingerprintclient(unsigned char*msghdr, int len);622 faim_export fu16_t aim_im_fingerprint(const fu8_t *msghdr, int len); 655 623 656 624 #define AIM_RATE_CODE_CHANGE 0x0001 … … 660 628 faim_export int aim_ads_requestads(aim_session_t *sess, aim_conn_t *conn); 661 629 630 631 662 632 /* im.c */ 663 664 struct aim_fileheader_t { 665 #if 0 666 char magic[4]; /* 0 */ 667 short hdrlen; /* 4 */ 668 short hdrtype; /* 6 */ 669 #endif 670 char bcookie[8]; /* 8 */ 671 short encrypt; /* 16 */ 672 short compress; /* 18 */ 673 short totfiles; /* 20 */ 674 short filesleft; /* 22 */ 675 short totparts; /* 24 */ 676 short partsleft; /* 26 */ 677 long totsize; /* 28 */ 678 long size; /* 32 */ 679 long modtime; /* 36 */ 680 long checksum; /* 40 */ 681 long rfrcsum; /* 44 */ 682 long rfsize; /* 48 */ 683 long cretime; /* 52 */ 684 long rfcsum; /* 56 */ 685 long nrecvd; /* 60 */ 686 long recvcsum; /* 64 */ 687 char idstring[32]; /* 68 */ 688 char flags; /* 100 */ 689 char lnameoffset; /* 101 */ 690 char lsizeoffset; /* 102 */ 691 char dummy[69]; /* 103 */ 692 char macfileinfo[16]; /* 172 */ 693 short nencode; /* 188 */ 694 short nlanguage; /* 190 */ 695 char name[64]; /* 192 */ 696 /* 256 */ 697 }; 698 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 633 #define AIM_OFT_SUBTYPE_SEND_FILE 0x0001 634 #define AIM_OFT_SUBTYPE_SEND_DIR 0x0002 635 #define AIM_OFT_SUBTYPE_GET_FILE 0x0011 636 #define AIM_OPT_SUBTYPE_GET_LIST 0x0012 637 638 #define AIM_TRANSFER_DENY_NOTSUPPORTED 0x0000 639 #define AIM_TRANSFER_DENY_DECLINE 0x0001 640 #define AIM_TRANSFER_DENY_NOTACCEPTING 0x0002 641 642 #define AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED 0x00000001 643 #define AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED 0x00000002 644 645 /* This is what the server will give you if you don't set them yourself. */ 646 #define AIM_IMPARAM_DEFAULTS { \ 647 0, \ 648 AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED, \ 649 512, /* !! Note how small this is. */ \ 650 (99.9)*10, (99.9)*10, \ 651 1000 /* !! And how large this is. */ \ 652 } 653 654 /* This is what most AIM versions use. */ 655 #define AIM_IMPARAM_REASONABLE { \ 656 0, \ 657 AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED, \ 658 8000, \ 659 (99.9)*10, (99.9)*10, \ 660 0 \ 661 } 662 663 struct aim_icbmparameters { 664 fu16_t maxchan; 665 fu32_t flags; /* AIM_IMPARAM_FLAG_ */ 666 fu16_t maxmsglen; /* message size that you will accept */ 667 fu16_t maxsenderwarn; /* this and below are *10 (999=99.9%) */ 668 fu16_t maxrecverwarn; 669 fu32_t minmsginterval; /* in milliseconds? */ 670 }; 703 671 704 672 struct aim_chat_roominfo { 705 unsigned short exchange;673 fu16_t exchange; 706 674 char *name; 707 unsigned short instance;675 fu16_t instance; 708 676 }; 709 677 … … 717 685 #define AIM_IMFLAGS_CUSTOMFEATURES 0x0080 /* features field present */ 718 686 #define AIM_IMFLAGS_EXTDATA 0x0100 719 #define AIM_IMFLAGS_ CUSTOMCHARSET 0x0200 /* charset fields set */687 #define AIM_IMFLAGS_X 0x0200 720 688 #define AIM_IMFLAGS_MULTIPART 0x0400 /* ->mpmsg section valid */ 721 689 #define AIM_IMFLAGS_OFFLINE 0x0800 /* send to offline user */ … … 829 797 830 798 /* Valid values for channel 2 args->status */ 831 #define AIM_RENDEZVOUS_PROPOSE 832 #define AIM_RENDEZVOUS_CANCEL 833 #define AIM_RENDEZVOUS_ACCEPT 799 #define AIM_RENDEZVOUS_PROPOSE 0x0000 800 #define AIM_RENDEZVOUS_CANCEL 0x0001 801 #define AIM_RENDEZVOUS_ACCEPT 0x0002 834 802 835 803 struct aim_incomingim_ch2_args { 804 fu16_t status; 836 805 fu8_t cookie[8]; 837 fu16_t reqclass; 838 fu16_t status; 839 fu16_t errorcode; 806 int reqclass; 807 const char *proxyip; 840 808 const char *clientip; 841 const char *clientip2;842 809 const char *verifiedip; 843 810 fu16_t port; 811 fu16_t errorcode; 844 812 const char *msg; /* invite message or file description */ 845 813 const char *encoding; … … 871 839 872 840 /* Valid values for channel 4 args->type */ 873 #define AIM_ICQMSG_AUTHREQUEST 874 #define AIM_ICQMSG_AUTHDENIED 875 #define AIM_ICQMSG_AUTHGRANTED 841 #define AIM_ICQMSG_AUTHREQUEST 0x0006 842 #define AIM_ICQMSG_AUTHDENIED 0x0007 843 #define AIM_ICQMSG_AUTHGRANTED 0x0008 876 844 877 845 struct aim_incomingim_ch4_args { 878 846 fu32_t uin; /* Of the sender of the ICBM */ 879 fu16_t type; 847 fu8_t type; 848 fu8_t flags; 880 849 char *msg; /* Reason for auth request, deny, or accept */ 881 }; 882 883 faim_export int aim_send_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args); 884 faim_export int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args); 885 faim_export int aim_send_im(aim_session_t *, const char *destsn, unsigned short flags, const char *msg); 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); 887 faim_export fu16_t aim_iconsum(const fu8_t *buf, int buflen); 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); 890 faim_export const char *aim_directim_getsn(aim_conn_t *conn); 891 faim_export aim_conn_t *aim_directim_initiate(aim_session_t *, const char *destsn); 892 faim_export aim_conn_t *aim_directim_connect(aim_session_t *, const char *sn, const char *addr, const fu8_t *cookie); 893 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); 899 900 faim_export aim_conn_t *aim_getfile_initiate(aim_session_t *sess, aim_conn_t *conn, const char *destsn); 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); 905 faim_export int aim_oft_getfile_ack(aim_session_t *sess, aim_conn_t *conn); 906 faim_export int aim_oft_end(aim_session_t *sess, aim_conn_t *conn); 850 int msglen; 851 }; 852 853 /* SNAC sending functions */ 854 /* 0x0002 */ faim_export int aim_im_setparams(aim_session_t *sess, struct aim_icbmparameters *params); 855 /* 0x0004 */ faim_export int aim_im_reqparams(aim_session_t *sess); 856 /* 0x0006 */ faim_export int aim_im_sendch1_ext(aim_session_t *sess, struct aim_sendimext_args *args); 857 /* 0x0006 */ faim_export int aim_im_sendch1(aim_session_t *, const char *destsn, fu16_t flags, const char *msg); 858 /* 0x0006 */ faim_export int aim_im_sendch2_icon(aim_session_t *sess, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu16_t iconsum); 859 /* 0x0006 */ faim_export int aim_im_sendch2_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args); 860 /* 0x0006 */ faim_export int aim_im_sendch2_odcrequest(aim_session_t *sess, fu8_t *cookie, const char *sn, const fu8_t *ip, fu16_t port); 861 /* 0x0006 */ faim_export int aim_im_sendch2_sendfile_ask(aim_session_t *sess, struct aim_oft_info *oft_info); 862 /* 0x0006 */ faim_export int aim_im_sendch2_sendfile_accept(aim_session_t *sess, struct aim_oft_info *info); 863 /* 0x0006 */ faim_export int aim_im_sendch2_sendfile_cancel(aim_session_t *sess, struct aim_oft_info *oft_info); 864 /* 0x0006 */ faim_export int aim_im_sendch2_geticqaway(aim_session_t *sess, const char *sn, int type); 865 /* 0x0006 */ faim_export int aim_im_sendch4(aim_session_t *sess, char *sn, fu16_t type, fu8_t *message); 866 /* 0x0008 */ faim_export int aim_im_warn(aim_session_t *sess, aim_conn_t *conn, const char *destsn, fu32_t flags); 867 /* 0x000b */ faim_export int aim_im_denytransfer(aim_session_t *sess, const char *sender, const char *cookie, fu16_t code); 868 /* 0x0014 */ faim_export int aim_im_sendmtn(aim_session_t *sess, fu16_t type1, const char *sn, fu16_t type2); 869 870 871 872 /* ft.c */ 873 struct aim_fileheader_t { 874 #if 0 875 char magic[4]; /* 0 */ 876 fu16_t hdrlen; /* 4 */ 877 fu16_t hdrtype; /* 6 */ 878 #endif 879 char bcookie[8]; /* 8 */ 880 fu16_t encrypt; /* 16 */ 881 fu16_t compress; /* 18 */ 882 fu16_t totfiles; /* 20 */ 883 fu16_t filesleft; /* 22 */ 884 fu16_t totparts; /* 24 */ 885 fu16_t partsleft; /* 26 */ 886 fu32_t totsize; /* 28 */ 887 fu32_t size; /* 32 */ 888 fu32_t modtime; /* 36 */ 889 fu32_t checksum; /* 40 */ 890 fu32_t rfrcsum; /* 44 */ 891 fu32_t rfsize; /* 48 */ 892 fu32_t cretime; /* 52 */ 893 fu32_t rfcsum; /* 56 */ 894 fu32_t nrecvd; /* 60 */ 895 fu32_t recvcsum; /* 64 */ 896 fu8_t idstring[32]; /* 68 */ 897 fu8_t flags; /* 100 */ 898 fu8_t lnameoffset; /* 101 */ 899 fu8_t lsizeoffset; /* 102 */ 900 char dummy[69]; /* 103 */ 901 char macfileinfo[16]; /* 172 */ 902 fu16_t nencode; /* 188 */ 903 fu16_t nlanguage; /* 190 */ 904 char name[64]; /* 192 */ 905 /* 256 */ 906 }; 907 908 struct aim_oft_info { 909 char cookie[8]; 910 char *sn; 911 char *proxyip; 912 char *clientip; 913 char *verifiedip; 914 fu16_t port; 915 aim_conn_t *conn; 916 aim_session_t *sess; 917 struct aim_fileheader_t fh; 918 struct aim_oft_info *next; 919 }; 920 921 faim_export fu32_t aim_oft_checksum_chunk(const fu8_t *buffer, int bufferlen, fu32_t prevcheck); 922 faim_export fu32_t aim_oft_checksum_file(char *filename); 923 faim_export int aim_handlerendconnect(aim_session_t *sess, aim_conn_t *cur); 924 faim_export int aim_odc_send_typing(aim_session_t *sess, aim_conn_t *conn, int typing); 925 faim_export int aim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *msg, int len, int encoding, int isawaymsg); 926 faim_export const char *aim_odc_getsn(aim_conn_t *conn); 927 faim_export aim_conn_t *aim_odc_getconn(aim_session_t *sess, const char *sn); 928 faim_export aim_conn_t *aim_odc_initiate(aim_session_t *sess, const char *sn); 929 faim_export aim_conn_t *aim_odc_connect(aim_session_t *sess, const char *sn, const char *addr, const fu8_t *cookie); 930 931 faim_export struct aim_oft_info *aim_oft_createinfo(aim_session_t *sess, const fu8_t *cookie, const char *sn, const char *ip, fu16_t port, fu32_t size, fu32_t modtime, char *filename); 932 faim_export int aim_oft_destroyinfo(struct aim_oft_info *oft_info); 933 faim_export int aim_sendfile_listen(aim_session_t *sess, struct aim_oft_info *oft_info); 934 faim_export int aim_oft_sendheader(aim_session_t *sess, fu16_t type, struct aim_oft_info *oft_info); 935 936 907 937 908 938 /* info.c */ 909 #define AIM_CAPS_BUDDYICON 0x00000001 910 #define AIM_CAPS_VOICE 0x00000002 911 #define AIM_CAPS_IMIMAGE 0x00000004 912 #define AIM_CAPS_CHAT 0x00000008 913 #define AIM_CAPS_GETFILE 0x00000010 914 #define AIM_CAPS_SENDFILE 0x00000020 915 #define AIM_CAPS_GAMES 0x00000040 916 #define AIM_CAPS_SAVESTOCKS 0x00000080 917 #define AIM_CAPS_SENDBUDDYLIST 0x00000100 918 #define AIM_CAPS_GAMES2 0x00000200 919 #define AIM_CAPS_ICQ 0x00000400 920 #define AIM_CAPS_APINFO 0x00000800 939 /* 940 * AIM User Info, Standard Form. 941 */ 942 #define AIM_FLAG_UNCONFIRMED 0x0001 /* "damned transients" */ 943 #define AIM_FLAG_ADMINISTRATOR 0x0002 944 #define AIM_FLAG_AOL 0x0004 945 #define AIM_FLAG_OSCAR_PAY 0x0008 946 #define AIM_FLAG_FREE 0x0010 947 #define AIM_FLAG_AWAY 0x0020 948 #define AIM_FLAG_ICQ 0x0040 949 #define AIM_FLAG_WIRELESS 0x0080 950 #define AIM_FLAG_UNKNOWN100 0x0100 951 #define AIM_FLAG_UNKNOWN200 0x0200 952 #define AIM_FLAG_ACTIVEBUDDY 0x0400 953 #define AIM_FLAG_UNKNOWN800 0x0800 954 #define AIM_FLAG_ABINTERNAL 0x1000 955 #define AIM_FLAG_ALLUSERS 0x001f 956 957 #define AIM_USERINFO_PRESENT_FLAGS 0x00000001 958 #define AIM_USERINFO_PRESENT_MEMBERSINCE 0x00000002 959 #define AIM_USERINFO_PRESENT_ONLINESINCE 0x00000004 960 #define AIM_USERINFO_PRESENT_IDLE 0x00000008 961 #define AIM_USERINFO_PRESENT_ICQEXTSTATUS 0x00000010 962 #define AIM_USERINFO_PRESENT_ICQIPADDR 0x00000020 963 #define AIM_USERINFO_PRESENT_ICQDATA 0x00000040 964 #define AIM_USERINFO_PRESENT_CAPABILITIES 0x00000080 965 #define AIM_USERINFO_PRESENT_SESSIONLEN 0x00000100 966 #define AIM_USERINFO_PRESENT_CREATETIME 0x00000200 967 968 typedef struct { 969 char sn[MAXSNLEN+1]; 970 fu16_t warnlevel; /* evil percent * 10 (999 = 99.9%) */ 971 fu16_t idletime; /* in seconds */ 972 fu16_t flags; 973 fu32_t createtime; /* time_t */ 974 fu32_t membersince; /* time_t */ 975 fu32_t onlinesince; /* time_t */ 976 fu32_t sessionlen; /* in seconds */ 977 fu32_t capabilities; 978 struct { 979 fu32_t status; 980 fu32_t ipaddr; 981 fu8_t crap[0x25]; /* until we figure it out... */ 982 } icqinfo; 983 fu32_t present; 984 fu16_t iconcsumlen; 985 fu8_t *iconcsum; 986 char *availmsg_encoding; 987 char *availmsg; 988 int availmsg_len; 989 } aim_userinfo_t; 990 991 faim_export const char *aim_userinfo_sn(aim_userinfo_t *ui); 992 faim_export fu16_t aim_userinfo_flags(aim_userinfo_t *ui); 993 faim_export fu16_t aim_userinfo_idle(aim_userinfo_t *ui); 994 faim_export float aim_userinfo_warnlevel(aim_userinfo_t *ui); 995 faim_export time_t aim_userinfo_createtime(aim_userinfo_t *ui); 996 faim_export time_t aim_userinfo_membersince(aim_userinfo_t *ui); 997 faim_export time_t aim_userinfo_onlinesince(aim_userinfo_t *ui); 998 faim_export fu32_t aim_userinfo_sessionlen(aim_userinfo_t *ui); 999 faim_export int aim_userinfo_hascap(aim_userinfo_t *ui, fu32_t cap); 1000 1001 #define AIM_CAPS_BUDDYICON 0x00000001 1002 #define AIM_CAPS_VOICE 0x00000002 1003 #define AIM_CAPS_DIRECTIM 0x00000004 1004 #define AIM_CAPS_CHAT 0x00000008 1005 #define AIM_CAPS_GETFILE 0x00000010 1006 #define AIM_CAPS_SENDFILE 0x00000020 1007 #define AIM_CAPS_GAMES 0x00000040 1008 #define AIM_CAPS_SAVESTOCKS 0x00000080 1009 #define AIM_CAPS_SENDBUDDYLIST 0x00000100 1010 #define AIM_CAPS_GAMES2 0x00000200 1011 #define AIM_CAPS_ICQ 0x00000400 1012 #define AIM_CAPS_APINFO 0x00000800 921 1013 #define AIM_CAPS_ICQRTF 0x00001000 922 1014 #define AIM_CAPS_EMPTY 0x00002000 923 #define AIM_CAPS_ICQSERVERRELAY 0x00004000 924 #define AIM_CAPS_ICQUNKNOWN 0x00008000 925 #define AIM_CAPS_TRILLIANCRYPT 0x00010000 926 #define AIM_CAPS_LAST 0x00020000 1015 #define AIM_CAPS_ICQSERVERRELAY 0x00004000 1016 #define AIM_CAPS_ICQUTF8OLD 0x00008000 1017 #define AIM_CAPS_TRILLIANCRYPT 0x00010000 1018 #define AIM_CAPS_ICQUTF8 0x00020000 1019 #define AIM_CAPS_INTEROPERATE 0x00040000 1020 #define AIM_CAPS_ICHAT 0x00080000 1021 #define AIM_CAPS_HIPTOP 0x00100000 1022 #define AIM_CAPS_SECUREIM 0x00200000 1023 #define AIM_CAPS_LAST 0x00400000 927 1024 928 1025 faim_export int aim_0002_000b(aim_session_t *sess, aim_conn_t *conn, const char *sn); … … 931 1028 #define AIM_SENDMEMBLOCK_FLAG_ISHASH 1 932 1029 933 faim_export int aim_sendmemblock(aim_session_t *sess, aim_conn_t *conn, unsigned long offset, unsigned long len, const unsigned char *buf, unsigned charflag);1030 faim_export int aim_sendmemblock(aim_session_t *sess, aim_conn_t *conn, fu32_t offset, fu32_t len, const fu8_t *buf, fu8_t flag); 934 1031 935 1032 #define AIM_GETINFO_GENERALINFO 0x00001 … … 961 1058 #define AIM_COOKIETYPE_OFTICON 0x15 962 1059 963 faim_export int aim_handlerendconnect(aim_session_t *sess, aim_conn_t *cur); 964 965 #define AIM_TRANSFER_DENY_NOTSUPPORTED 0x0000 966 #define AIM_TRANSFER_DENY_DECLINE 0x0001 967 #define AIM_TRANSFER_DENY_NOTACCEPTING 0x0002 968 faim_export int aim_denytransfer(aim_session_t *sess, const char *sender, const char *cookie, unsigned short code); 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); 974 975 faim_export int aim_getinfo(aim_session_t *, aim_conn_t *, const char *, unsigned short); 976 faim_export int aim_sendbuddyoncoming(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *info); 977 faim_export int aim_sendbuddyoffgoing(aim_session_t *sess, aim_conn_t *conn, const char *sn); 978 979 #define AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED 0x00000001 980 #define AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED 0x00000002 981 982 /* This is what the server will give you if you don't set them yourself. */ 983 #define AIM_IMPARAM_DEFAULTS { \ 984 0, \ 985 AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED, \ 986 512, /* !! Note how small this is. */ \ 987 (99.9)*10, (99.9)*10, \ 988 1000 /* !! And how large this is. */ \ 989 } 990 991 /* This is what most AIM versions use. */ 992 #define AIM_IMPARAM_REASONABLE { \ 993 0, \ 994 AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED, \ 995 8000, \ 996 (99.9)*10, (99.9)*10, \ 997 0 \ 998 } 999 1000 1001 struct aim_icbmparameters { 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? */ 1008 }; 1009 1010 faim_export int aim_reqicbmparams(aim_session_t *sess); 1011 faim_export int aim_seticbmparam(aim_session_t *sess, struct aim_icbmparameters *params); 1012 1013 1014 /* auth.c */ 1015 faim_export int aim_sendcookie(aim_session_t *, aim_conn_t *, const fu8_t *); 1016 1017 faim_export int aim_admin_changepasswd(aim_session_t *, aim_conn_t *, const char *newpw, const char *curpw); 1018 faim_export int aim_admin_reqconfirm(aim_session_t *sess, aim_conn_t *conn); 1019 faim_export int aim_admin_getinfo(aim_session_t *sess, aim_conn_t *conn, fu16_t info); 1020 faim_export int aim_admin_setemail(aim_session_t *sess, aim_conn_t *conn, const char *newemail); 1021 faim_export int aim_admin_setnick(aim_session_t *sess, aim_conn_t *conn, const char *newnick); 1022 1023 /* buddylist.c */ 1024 faim_export int aim_add_buddy(aim_session_t *, aim_conn_t *, const char *); 1025 faim_export int aim_remove_buddy(aim_session_t *, aim_conn_t *, const char *); 1026 1027 /* search.c */ 1028 faim_export int aim_usersearch_address(aim_session_t *, aim_conn_t *, const char *); 1029 1030 /* newsearch.c */ 1031 struct aim_usersearch { 1060 /* 0x0005 */ faim_export int aim_getinfo(aim_session_t *, aim_conn_t *, const char *, fu16_t); 1061 1062 1063 1064 /* 0x0003 - buddylist.c */ 1065 /* 0x0004 */ faim_export int aim_add_buddy(aim_session_t *, aim_conn_t *, const char *); 1066 /* 0x0005 */ faim_export int aim_remove_buddy(aim_session_t *, aim_conn_t *, const char *); 1067 /* 0x000b */ faim_export int aim_sendbuddyoncoming(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *info); 1068 /* 0x000c */ faim_export int aim_sendbuddyoffgoing(aim_session_t *sess, aim_conn_t *conn, const char *sn); 1069 1070 1071 1072 /* 0x000a - search.c */ 1073 faim_export int aim_search_address(aim_session_t *, aim_conn_t *, const char *); 1074 1075 1076 1077 /* 0x000d - chatnav.c */ 1078 /* 0x000e - chat.c */ 1079 /* These apply to exchanges as well. */ 1080 #define AIM_CHATROOM_FLAG_EVILABLE 0x0001 1081 #define AIM_CHATROOM_FLAG_NAV_ONLY 0x0002 1082 #define AIM_CHATROOM_FLAG_INSTANCING_ALLOWED 0x0004 1083 #define AIM_CHATROOM_FLAG_OCCUPANT_PEEK_ALLOWED 0x0008 1084 1085 struct aim_chat_exchangeinfo { 1086 fu16_t number; 1087 fu16_t flags; 1088 char *name; 1089 char *charset1; 1090 char *lang1; 1091 char *charset2; 1092 char *lang2; 1093 }; 1094 1095 #define AIM_CHATFLAGS_NOREFLECT 0x0001 1096 #define AIM_CHATFLAGS_AWAY 0x0002 1097 faim_export int aim_chat_send_im(aim_session_t *sess, aim_conn_t *conn, fu16_t flags, const char *msg, int msglen); 1098 faim_export int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, fu16_t exchange, const char *roomname, fu16_t instance); 1099 faim_export int aim_chat_attachname(aim_conn_t *conn, fu16_t exchange, const char *roomname, fu16_t instance); 1100 faim_export char *aim_chat_getname(aim_conn_t *conn); 1101 faim_export aim_conn_t *aim_chat_getconn(aim_session_t *, const char *name); 1102 1103 faim_export int aim_chatnav_reqrights(aim_session_t *sess, aim_conn_t *conn); 1104 1105 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); 1106 1107 faim_export int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *name, fu16_t exchange); 1108 faim_export int aim_chat_leaveroom(aim_session_t *sess, const char *name); 1109 1110 1111 1112 /* 0x000f - odir.c */ 1113 struct aim_odir { 1032 1114 char *first; 1033 1115 char *last; … … 1044 1126 char *region; 1045 1127 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 1053 1054 /* These apply to exchanges as well. */ 1055 #define AIM_CHATROOM_FLAG_EVILABLE 0x0001 1056 #define AIM_CHATROOM_FLAG_NAV_ONLY 0x0002 1057 #define AIM_CHATROOM_FLAG_INSTANCING_ALLOWED 0x0004 1058 #define AIM_CHATROOM_FLAG_OCCUPANT_PEEK_ALLOWED 0x0008 1059 1060 struct aim_chat_exchangeinfo { 1061 fu16_t number; 1062 fu16_t flags; 1063 char *name; 1064 char *charset1; 1065 char *lang1; 1066 char *charset2; 1067 char *lang2; 1068 }; 1069 1070 #define AIM_CHATFLAGS_NOREFLECT 0x0001 1071 #define AIM_CHATFLAGS_AWAY 0x0002 1072 faim_export int aim_chat_send_im(aim_session_t *sess, aim_conn_t *conn, fu16_t flags, const char *msg, int msglen); 1073 faim_export int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, fu16_t exchange, const char *roomname, fu16_t instance); 1074 faim_export int aim_chat_attachname(aim_conn_t *conn, fu16_t exchange, const char *roomname, fu16_t instance); 1075 faim_export char *aim_chat_getname(aim_conn_t *conn); 1076 faim_export aim_conn_t *aim_chat_getconn(aim_session_t *, const char *name); 1077 1078 faim_export int aim_chatnav_reqrights(aim_session_t *sess, aim_conn_t *conn); 1079 1080 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); 1081 1082 faim_export int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *name, fu16_t exchange); 1083 faim_export int aim_chat_leaveroom(aim_session_t *sess, const char *name); 1084 1085 1086 #define AIM_SSI_TYPE_BUDDY 0x0000 1087 #define AIM_SSI_TYPE_GROUP 0x0001 1088 #define AIM_SSI_TYPE_PERMIT 0x0002 1089 #define AIM_SSI_TYPE_DENY 0x0003 1090 #define AIM_SSI_TYPE_PDINFO 0x0004 1091 #define AIM_SSI_TYPE_PRESENCEPREFS 0x0005 1128 struct aim_odir *next; 1129 }; 1130 1131 faim_export int aim_odir_email(aim_session_t *, const char *, const char *); 1132 faim_export int aim_odir_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 *); 1133 faim_export int aim_odir_interest(aim_session_t *, const char *, const char *); 1134 1135 1136 1137 /* 0x0010 - icon.c */ 1138 faim_export int aim_bart_upload(aim_session_t *sess, const fu8_t *icon, fu16_t iconlen); 1139 faim_export int aim_bart_request(aim_session_t *sess, const char *sn, const fu8_t *iconstr, fu16_t iconstrlen); 1140 1141 1142 1143 /* 0x0013 - ssi.c */ 1144 #define AIM_SSI_TYPE_BUDDY 0x0000 1145 #define AIM_SSI_TYPE_GROUP 0x0001 1146 #define AIM_SSI_TYPE_PERMIT 0x0002 1147 #define AIM_SSI_TYPE_DENY 0x0003 1148 #define AIM_SSI_TYPE_PDINFO 0x0004 1149 #define AIM_SSI_TYPE_PRESENCEPREFS 0x0005 1150 #define AIM_SSI_TYPE_ICONINFO 0x0014 1151 1152 #define AIM_SSI_ACK_SUCCESS 0x0000 1153 #define AIM_SSI_ACK_ITEMNOTFOUND 0x0002 1154 #define AIM_SSI_ACK_IDNUMINUSE 0x000a 1155 #define AIM_SSI_ACK_ATMAX 0x000c 1156 #define AIM_SSI_ACK_INVALIDNAME 0x000d 1157 #define AIM_SSI_ACK_AUTHREQUIRED 0x000e 1092 1158 1093 1159 struct aim_ssi_item { … … 1096 1162 fu16_t bid; 1097 1163 fu16_t type; 1098 void*data;1164 struct aim_tlvlist_s *data; 1099 1165 struct aim_ssi_item *next; 1100 1166 }; 1101 1167 1168 struct aim_ssi_tmp { 1169 fu16_t action; 1170 fu16_t ack; 1171 char *name; 1172 struct aim_ssi_item *item; 1173 struct aim_ssi_tmp *next; 1174 }; 1175 1102 1176 /* These build the actual SNACs and queue them to be sent */ 1103 faim_export int aim_ssi_reqrights(aim_session_t *sess, aim_conn_t *conn); 1104 faim_export int aim_ssi_reqdata(aim_session_t *sess, aim_conn_t *conn, time_t localstamp, fu16_t localrev); 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); 1107 faim_export int aim_ssi_modbegin(aim_session_t *sess, aim_conn_t *conn); 1108 faim_export int aim_ssi_modend(aim_session_t *sess, aim_conn_t *conn); 1109 1110 /* These handle the local variables */ 1177 /* 0x0002 */ faim_export int aim_ssi_reqrights(aim_session_t *sess); 1178 /* 0x0004 */ faim_export int aim_ssi_reqdata(aim_session_t *sess); 1179 /* 0x0005 */ faim_export int aim_ssi_reqifchanged(aim_session_t *sess, time_t localstamp, fu16_t localrev); 1180 /* 0x0007 */ faim_export int aim_ssi_enable(aim_session_t *sess); 1181 /* 0x0008 */ faim_export int aim_ssi_addmoddel(aim_session_t *sess); 1182 /* 0x0011 */ faim_export int aim_ssi_modbegin(aim_session_t *sess); 1183 /* 0x0012 */ faim_export int aim_ssi_modend(aim_session_t *sess); 1184 /* 0x0014 */ faim_export int aim_ssi_sendauth(aim_session_t *sess, char *sn, char *msg); 1185 /* 0x0018 */ faim_export int aim_ssi_sendauthrequest(aim_session_t *sess, char *sn, char *msg); 1186 /* 0x001a */ faim_export int aim_ssi_sendauthreply(aim_session_t *sess, char *sn, fu8_t reply, char *msg); 1187 1188 /* Client functions for retrieving SSI data */ 1111 1189 faim_export struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, fu16_t gid, fu16_t bid); 1112 1190 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); 1191 faim_export struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *sn); 1192 faim_export char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *sn); 1114 1193 faim_export int aim_ssi_getpermdeny(struct aim_ssi_item *list); 1115 1194 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); 1195 faim_export char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *sn); 1196 faim_export int aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *sn); 1197 1198 /* Client functions for changing SSI data */ 1199 faim_export int aim_ssi_addbuddy(aim_session_t *sess, const char *name, const char *group, const char *alias, const char *comment, const char *smsnum, int needauth); 1200 faim_export int aim_ssi_addpermit(aim_session_t *sess, const char *name); 1201 faim_export int aim_ssi_adddeny(aim_session_t *sess, const char *name); 1202 faim_export int aim_ssi_delbuddy(aim_session_t *sess, const char *name, const char *group); 1203 faim_export int aim_ssi_delpermit(aim_session_t *sess, const char *name); 1204 faim_export int aim_ssi_deldeny(aim_session_t *sess, const char *name); 1205 faim_export int aim_ssi_movebuddy(aim_session_t *sess, const char *oldgn, const char *newgn, const char *sn); 1206 faim_export int aim_ssi_aliasbuddy(aim_session_t *sess, const char *gn, const char *sn, const char *alias); 1207 faim_export int aim_ssi_rename_group(aim_session_t *sess, const char *oldgn, const char *newgn); 1208 faim_export int aim_ssi_cleanlist(aim_session_t *sess); 1209 faim_export int aim_ssi_deletelist(aim_session_t *sess); 1210 faim_export int aim_ssi_setpermdeny(aim_session_t *sess, fu8_t permdeny, fu32_t vismask); 1211 faim_export int aim_ssi_setpresence(aim_session_t *sess, fu32_t presence); 1212 faim_export int aim_ssi_seticon(aim_session_t *sess, fu8_t *iconsum, fu16_t iconsumlen); 1213 1214 1215 1216 /* 0x0015 - icq.c */ 1217 #define AIM_ICQ_INFO_SIMPLE 0x001 1218 #define AIM_ICQ_INFO_SUMMARY 0x002 1219 #define AIM_ICQ_INFO_EMAIL 0x004 1220 #define AIM_ICQ_INFO_PERSONAL 0x008 1221 #define AIM_ICQ_INFO_ADDITIONAL 0x010 1222 #define AIM_ICQ_INFO_WORK 0x020 1223 #define AIM_ICQ_INFO_INTERESTS 0x040 1224 #define AIM_ICQ_INFO_ORGS 0x080 1225 #define AIM_ICQ_INFO_UNKNOWN 0x100 1226 #define AIM_ICQ_INFO_HAVEALL 0x1ff 1130 1227 1131 1228 struct aim_icq_offlinemsg { … … 1133 1230 fu16_t year; 1134 1231 fu8_t month, day, hour, minute; 1135 fu16_t type; 1232 fu8_t type; 1233 fu8_t flags; 1136 1234 char *msg; 1137 }; 1138 1139 struct aim_icq_simpleinfo { 1235 int msglen; 1236 }; 1237 1238 struct aim_icq_info { 1239 fu16_t reqid; 1240 1241 /* simple */ 1140 1242 fu32_t uin; 1243 1244 /* general and "home" information (0x00c8) */ 1141 1245 char *nick; 1142 1246 char *first; 1143 1247 char *last; 1144 1248 char *email; 1249 char *homecity; 1250 char *homestate; 1251 char *homephone; 1252 char *homefax; 1253 char *homeaddr; 1254 char *mobile; 1255 char *homezip; 1256 fu16_t homecountry; 1257 /* fu8_t timezone; 1258 fu8_t hideemail; */ 1259 1260 /* personal (0x00dc) */ 1261 fu8_t age; 1262 fu8_t unknown; 1263 fu8_t gender; 1264 char *personalwebpage; 1265 fu16_t birthyear; 1266 fu8_t birthmonth; 1267 fu8_t birthday; 1268 fu8_t language1; 1269 fu8_t language2; 1270 fu8_t language3; 1271 1272 /* work (0x00d2) */ 1273 char *workcity; 1274 char *workstate; 1275 char *workphone; 1276 char *workfax; 1277 char *workaddr; 1278 char *workzip; 1279 fu16_t workcountry; 1280 char *workcompany; 1281 char *workdivision; 1282 char *workposition; 1283 char *workwebpage; 1284 1285 /* additional personal information (0x00e6) */ 1286 char *info; 1287 1288 /* email (0x00eb) */ 1289 fu16_t numaddresses; 1290 char **email2; 1291 1292 /* we keep track of these in a linked list because we're 1337 */ 1293 struct aim_icq_info *next; 1145 1294 }; 1146 1295 1147 1296 faim_export int aim_icq_reqofflinemsgs(aim_session_t *sess); 1148 1297 faim_export int aim_icq_ackofflinemsgs(aim_session_t *sess); 1298 faim_export int aim_icq_hideip(aim_session_t *sess); 1299 faim_export int aim_icq_changepasswd(aim_session_t *sess, const char *passwd); 1149 1300 faim_export int aim_icq_getsimpleinfo(aim_session_t *sess, const char *uin); 1150 1151 /* email.c */ 1301 faim_export int aim_icq_getalias(aim_session_t *sess, const char *uin); 1302 faim_export int aim_icq_getallinfo(aim_session_t *sess, const char *uin); 1303 1304 1305 1306 /* 0x0017 - auth.c */ 1307 faim_export int aim_sendcookie(aim_session_t *, aim_conn_t *, const fu16_t length, const fu8_t *); 1308 faim_export int aim_admin_changepasswd(aim_session_t *, aim_conn_t *, const char *newpw, const char *curpw); 1309 faim_export int aim_admin_reqconfirm(aim_session_t *sess, aim_conn_t *conn); 1310 faim_export int aim_admin_getinfo(aim_session_t *sess, aim_conn_t *conn, fu16_t info); 1311 faim_export int aim_admin_setemail(aim_session_t *sess, aim_conn_t *conn, const char *newemail); 1312 faim_export int aim_admin_setnick(aim_session_t *sess, aim_conn_t *conn, const char *newnick); 1313 1314 1315 1316 /* 0x0018 - email.c */ 1152 1317 struct aim_emailinfo { 1153 1318 fu8_t *cookie16; … … 1164 1329 faim_export int aim_email_activate(aim_session_t *sess, aim_conn_t *conn); 1165 1330 1331 1332 1333 /* tlv.c - TLV handling */ 1334 #if defined(FAIM_INTERNAL) || defined(FAIM_NEED_TLV) 1335 /* Generic TLV structure. */ 1336 typedef struct aim_tlv_s { 1337 fu16_t type; 1338 fu16_t length; 1339 fu8_t *value; 1340 } aim_tlv_t; 1341 1342 /* List of above. */ 1343 typedef struct aim_tlvlist_s { 1344 aim_tlv_t *tlv; 1345 struct aim_tlvlist_s *next; 1346 } aim_tlvlist_t; 1347 1348 /* TLV-handling functions */ 1349 1350 #if 0 1351 /* Very, very raw TLV handling. */ 1352 faim_internal int aim_puttlv_8(fu8_t *buf, const fu16_t t, const fu8_t v); 1353 faim_internal int aim_puttlv_16(fu8_t *buf, const fu16_t t, const fu16_t v); 1354 faim_internal int aim_puttlv_32(fu8_t *buf, const fu16_t t, const fu32_t v); 1355 faim_internal int aim_puttlv_raw(fu8_t *buf, const fu16_t t, const fu16_t l, const fu8_t *v); 1356 #endif 1357 1358 /* TLV list handling. */ 1359 faim_internal aim_tlvlist_t *aim_readtlvchain(aim_bstream_t *bs); 1360 faim_internal aim_tlvlist_t *aim_readtlvchain_num(aim_bstream_t *bs, fu16_t num); 1361 faim_internal aim_tlvlist_t *aim_readtlvchain_len(aim_bstream_t *bs, fu16_t len); 1362 faim_internal aim_tlvlist_t *aim_tlvlist_copy(aim_tlvlist_t *orig); 1363 faim_internal int aim_tlvlist_cmp(aim_tlvlist_t *one, aim_tlvlist_t *two); 1364 faim_internal void aim_freetlvchain(aim_tlvlist_t **list); 1365 faim_internal aim_tlv_t *aim_gettlv(aim_tlvlist_t *, fu16_t t, const int n); 1366 faim_internal char *aim_gettlv_str(aim_tlvlist_t *, const fu16_t t, const int n); 1367 faim_internal fu8_t aim_gettlv8(aim_tlvlist_t *list, const fu16_t type, const int num); 1368 faim_internal fu16_t aim_gettlv16(aim_tlvlist_t *list, const fu16_t t, const int n); 1369 faim_internal fu32_t aim_gettlv32(aim_tlvlist_t *list, const fu16_t t, const int n); 1370 faim_internal int aim_writetlvchain(aim_bstream_t *bs, aim_tlvlist_t **list); 1371 faim_internal int aim_addtlvtochain8(aim_tlvlist_t **list, const fu16_t t, const fu8_t v); 1372 faim_internal int aim_addtlvtochain16(aim_tlvlist_t **list, const fu16_t t, const fu16_t v); 1373 faim_internal int aim_addtlvtochain32(aim_tlvlist_t **list, const fu16_t type, const fu32_t v); 1374 faim_internal int aim_addtlvtochain_raw(aim_tlvlist_t **list, const fu16_t t, const fu16_t l, const fu8_t *v); 1375 faim_internal int aim_addtlvtochain_caps(aim_tlvlist_t **list, const fu16_t t, const fu32_t caps); 1376 faim_internal int aim_addtlvtochain_noval(aim_tlvlist_t **list, const fu16_t type); 1377 faim_internal int aim_addtlvtochain_userinfo(aim_tlvlist_t **list, fu16_t type, aim_userinfo_t *ui); 1378 faim_internal int aim_addtlvtochain_frozentlvlist(aim_tlvlist_t **list, fu16_t type, aim_tlvlist_t **tl); 1379 faim_internal int aim_counttlvchain(aim_tlvlist_t **list); 1380 faim_internal int aim_sizetlvchain(aim_tlvlist_t **list); 1381 #endif /* FAIM_INTERNAL */ 1382 1383 1384 1166 1385 /* util.c */ 1167 1386 /* … … 1172 1391 * 1173 1392 */ 1174 #define aimutil_put8(buf, data) ((*(buf) = ( u_char)(data)&0xff),1)1393 #define aimutil_put8(buf, data) ((*(buf) = (fu8_t)(data)&0xff),1) 1175 1394 #define aimutil_get8(buf) ((*(buf))&0xff) 1176 1395 #define aimutil_put16(buf, data) ( \ 1177 (*(buf) = ( u_char)((data)>>8)&0xff), \1178 (*((buf)+1) = ( u_char)(data)&0xff), \1396 (*(buf) = (fu8_t)((data)>>8)&0xff), \ 1397 (*((buf)+1) = (fu8_t)(data)&0xff), \ 1179 1398 2) 1180 1399 #define aimutil_get16(buf) ((((*(buf))<<8)&0xff00) + ((*((buf)+1)) & 0xff)) 1181 1400 #define aimutil_put32(buf, data) ( \ 1182 (*((buf)) = ( u_char)((data)>>24)&0xff), \1183 (*((buf)+1) = ( u_char)((data)>>16)&0xff), \1184 (*((buf)+2) = ( u_char)((data)>>8)&0xff), \1185 (*((buf)+3) = ( u_char)(data)&0xff), \1401 (*((buf)) = (fu8_t)((data)>>24)&0xff), \ 1402 (*((buf)+1) = (fu8_t)((data)>>16)&0xff), \ 1403 (*((buf)+2) = (fu8_t)((data)>>8)&0xff), \ 1404 (*((buf)+3) = (fu8_t)(data)&0xff), \ 1186 1405 4) 1187 1406 #define aimutil_get32(buf) ((((*(buf))<<24)&0xff000000) + \ … … 1192 1411 /* Little-endian versions (damn ICQ) */ 1193 1412 #define aimutil_putle8(buf, data) ( \ 1194 (*(buf) = ( unsigned char)(data) & 0xff), \1413 (*(buf) = (fu8_t)(data) & 0xff), \ 1195 1414 1) 1196 1415 #define aimutil_getle8(buf) ( \ … … 1198 1417 ) 1199 1418 #define aimutil_putle16(buf, data) ( \ 1200 (*((buf)+0) = ( unsigned char)((data) >> 0) & 0xff), \1201 (*((buf)+1) = ( unsigned char)((data) >> 8) & 0xff), \1419 (*((buf)+0) = (fu8_t)((data) >> 0) & 0xff), \ 1420 (*((buf)+1) = (fu8_t)((data) >> 8) & 0xff), \ 1202 1421 2) 1203 1422 #define aimutil_getle16(buf) ( \ … … 1206 1425 ) 1207 1426 #define aimutil_putle32(buf, data) ( \ 1208 (*((buf)+0) = ( unsigned char)((data) >> 0) & 0xff), \1209 (*((buf)+1) = ( unsigned char)((data) >> 8) & 0xff), \1210 (*((buf)+2) = ( unsigned char)((data) >> 16) & 0xff), \1211 (*((buf)+3) = ( unsigned char)((data) >> 24) & 0xff), \1427 (*((buf)+0) = (fu8_t)((data) >> 0) & 0xff), \ 1428 (*((buf)+1) = (fu8_t)((data) >> 8) & 0xff), \ 1429 (*((buf)+2) = (fu8_t)((data) >> 16) & 0xff), \ 1430 (*((buf)+3) = (fu8_t)((data) >> 24) & 0xff), \ 1212 1431 4) 1213 1432 #define aimutil_getle32(buf) ( \ … … 1218 1437 1219 1438 1220 faim_export int aimutil_putstr(u_char *, const char *, int); 1221 faim_export int aimutil_tokslen(char *toSearch, int index, char dl); 1439 faim_export int aimutil_putstr(char *, const char *, int); 1440 faim_export fu16_t aimutil_iconsum(const fu8_t *buf, int buflen); 1441 faim_export int aim_util_getlocalip(fu8_t *ip); 1442 faim_export int aimutil_tokslen(char *toSearch, int theindex, char dl); 1222 1443 faim_export int aimutil_itemcnt(char *toSearch, char dl); 1223 faim_export char *aimutil_itemi dx(char *toSearch, intindex, char dl);1444 faim_export char *aimutil_itemindex(char *toSearch, int theindex, char dl); 1224 1445 1225 1446 faim_export int aim_snlen(const char *sn); 1226 1447 faim_export int aim_sncmp(const char *sn1, const char *sn2); 1227 1448 1228 /* for libc's that dont have it */1229 faim_export char *aim_strsep(char **pp, const char *delim);1230 1231 /* meta.c */1232 faim_export char *aim_getbuilddate(void);1233 faim_export char *aim_getbuildtime(void);1234 faim_export int aim_getbuildstring(char *buf, int buflen);1235 1236 1449 #include <aim_internal.h> 1237 1450 1451 #ifdef __cplusplus 1452 } 1453 #endif 1454 1238 1455 #endif /* __AIM_H__ */ 1239 -
libfaim/aim_cbtypes.h
r862371b re374dee 25 25 #define AIM_CB_FAM_CHT 0x000e /* Chat */ 26 26 #define AIM_CB_FAM_SCH 0x000f /* "New" search */ 27 #define AIM_CB_FAM_ICO 0x0010 /* Used for uploading buddy icons */ 27 28 #define AIM_CB_FAM_SSI 0x0013 /* Server stored information */ 28 29 #define AIM_CB_FAM_ICQ 0x0015 … … 179 180 /* 180 181 * SNAC Family: "New" Search 181 *182 * Most of these are actually special.183 182 */ 184 183 #define AIM_CB_SCH_ERROR 0x0001 … … 187 186 188 187 /* 188 * SNAC Family: Buddy icons 189 */ 190 #define AIM_CB_ICO_ERROR 0x0001 191 #define AIM_CB_ICO_REQUEST 0x0004 192 #define AIM_CB_ICO_RESPONSE 0x0005 193 194 /* 189 195 * SNAC Family: ICQ 190 196 * … … 194 200 #define AIM_CB_ICQ_OFFLINEMSG 0x00f0 195 201 #define AIM_CB_ICQ_OFFLINEMSGCOMPLETE 0x00f1 196 #define AIM_CB_ICQ_SIMPLEINFO 0x00f2 202 #define AIM_CB_ICQ_INFO 0x00f2 203 #define AIM_CB_ICQ_ALIAS 0x00f3 197 204 #define AIM_CB_ICQ_DEFAULT 0xffff 198 205 … … 203 210 #define AIM_CB_SSI_REQRIGHTS 0x0002 204 211 #define AIM_CB_SSI_RIGHTSINFO 0x0003 205 #define AIM_CB_SSI_REQLIST 0x0005 212 #define AIM_CB_SSI_REQDATA 0x0004 213 #define AIM_CB_SSI_REQIFCHANGED 0x0005 206 214 #define AIM_CB_SSI_LIST 0x0006 207 215 #define AIM_CB_SSI_ACTIVATE 0x0007 … … 213 221 #define AIM_CB_SSI_EDITSTART 0x0011 214 222 #define AIM_CB_SSI_EDITSTOP 0x0012 223 #define AIM_CB_SSI_SENDAUTH 0x0014 224 #define AIM_CB_SSI_RECVAUTH 0x0015 225 #define AIM_CB_SSI_SENDAUTHREQ 0x0018 226 #define AIM_CB_SSI_RECVAUTHREQ 0x0019 227 #define AIM_CB_SSI_SENDAUTHREP 0x001a 228 #define AIM_CB_SSI_RECVAUTHREP 0x001b 229 #define AIM_CB_SSI_ADDED 0x001c 215 230 216 231 /* … … 241 256 * OFT Services 242 257 * 243 * See non-SNAC note below. 244 */ 245 #define AIM_CB_OFT_DIRECTIMCONNECTREQ 0x0001/* connect request -- actually an OSCAR CAP*/ 258 * For all of the above #defines, the number is the subtype 259 * of the SNAC. For OFT #defines, the number is the 260 * "hdrtype" which comes after the magic string and OFT 261 * packet length. 262 * 263 * I'm pretty sure the ODC ones are arbitrary right now, 264 * that should be changed. 265 */ 266 #define AIM_CB_OFT_DIRECTIMCONNECTREQ 0x0001 /* connect request -- actually an OSCAR CAP */ 246 267 #define AIM_CB_OFT_DIRECTIMINCOMING 0x0002 247 268 #define AIM_CB_OFT_DIRECTIMDISCONNECT 0x0003 248 269 #define AIM_CB_OFT_DIRECTIMTYPING 0x0004 249 #define AIM_CB_OFT_DIRECTIMINITIATE 0x0005 250 251 /* had been removed, put back by kretch */ 252 #define AIM_CB_OFT_GETFILECONNECTREQ 0x0006 /* connect request -- actually an OSCAR CAP*/ 253 #define AIM_CB_OFT_GETFILELISTINGREQ 0x0007 /* OFT listing.txt request */ 254 #define AIM_CB_OFT_GETFILEFILEREQ 0x0008 /* received file request */ 255 #define AIM_CB_OFT_GETFILEFILESEND 0x0009 /* received file request confirm -- send data */ 256 #define AIM_CB_OFT_GETFILECOMPLETE 0x000a /* received file send complete*/ 257 #define AIM_CB_OFT_GETFILEINITIATE 0x000b /* request for file get acknowledge */ 258 #define AIM_CB_OFT_GETFILEDISCONNECT 0x000c /* OFT connection disconnected.*/ 259 #define AIM_CB_OFT_GETFILELISTING 0x000d /* OFT listing.txt received.*/ 260 #define AIM_CB_OFT_GETFILERECEIVE 0x000e /* OFT file incoming.*/ 261 #define AIM_CB_OFT_GETFILELISTINGRXCONFIRM 0x000f 262 #define AIM_CB_OFT_GETFILESTATE4 0x0010 263 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 */ 268 270 #define AIM_CB_OFT_DIRECTIM_ESTABLISHED 0x0005 271 272 #define AIM_CB_OFT_PROMPT 0x0101 /* "I am going to send you this file, is that ok?" */ 273 #define AIM_CB_OFT_RESUMESOMETHING 0x0106 /* I really don't know */ 274 #define AIM_CB_OFT_ACK 0x0202 /* "Yes, it is ok for you to send me that file" */ 275 #define AIM_CB_OFT_DONE 0x0204 /* "I received that file with no problems, thanks a bunch" */ 276 #define AIM_CB_OFT_RESUME 0x0205 /* Resume transferring, sent by whoever paused? */ 277 #define AIM_CB_OFT_RESUMEACK 0x0207 /* Not really sure */ 278 279 #define AIM_CB_OFT_GETFILE_REQUESTLISTING 0x1108 /* "I have a listing.txt file, do you want it?" */ 280 #define AIM_CB_OFT_GETFILE_RECEIVELISTING 0x1209 /* "Yes, please send me your listing.txt file" */ 281 #define AIM_CB_OFT_GETFILE_RECEIVEDLISTING 0x120a /* received corrupt listing.txt file? */ /* I'm just guessing about this one... */ 282 #define AIM_CB_OFT_GETFILE_ACKLISTING 0x120b /* "I received the listing.txt file successfully" */ 283 #define AIM_CB_OFT_GETFILE_REQUESTFILE 0x120c /* "Please send me this file" */ 284 285 #define AIM_CB_OFT_ESTABLISHED 0xFFFF /* connection to buddy initiated */ 269 286 270 287 /* … … 282 299 #define AIM_CB_SPECIAL_FLAPVER 0x0005 283 300 #define AIM_CB_SPECIAL_CONNINITDONE 0x0006 284 #define AIM_CB_SPECIAL_IMAGETRANSFER 0x007 285 #define AIM_CB_SPECIAL_MSGTIMEOUT 0x008 301 #define AIM_CB_SPECIAL_IMAGETRANSFER 0x0007 302 #define AIM_CB_SPECIAL_MSGTIMEOUT 0x0008 303 #define AIM_CB_SPECIAL_CONNDEAD 0x0009 286 304 #define AIM_CB_SPECIAL_UNKNOWN 0xffff 287 305 #define AIM_CB_SPECIAL_DEFAULT AIM_CB_SPECIAL_UNKNOWN -
libfaim/aim_internal.h
r862371b re374dee 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 28 void (*shutdown)(aim_session_t *sess, struct aim_module_s *mod); … … 37 36 faim_internal aim_module_t *aim__findmodule(aim_session_t *sess, const char *name); 38 37 38 faim_internal int admin_modfirst(aim_session_t *sess, aim_module_t *mod); 39 39 faim_internal int buddylist_modfirst(aim_session_t *sess, aim_module_t *mod); 40 faim_internal int admin_modfirst(aim_session_t *sess, aim_module_t *mod);41 40 faim_internal int bos_modfirst(aim_session_t *sess, aim_module_t *mod); 42 41 faim_internal int search_modfirst(aim_session_t *sess, aim_module_t *mod); … … 49 48 faim_internal int locate_modfirst(aim_session_t *sess, aim_module_t *mod); 50 49 faim_internal int general_modfirst(aim_session_t *sess, aim_module_t *mod); 51 faim_internal int ssi_modfirst(aim_session_t *sess, aim_module_t *mod);52 50 faim_internal int invite_modfirst(aim_session_t *sess, aim_module_t *mod); 53 51 faim_internal int translate_modfirst(aim_session_t *sess, aim_module_t *mod); 54 52 faim_internal int popups_modfirst(aim_session_t *sess, aim_module_t *mod); 55 53 faim_internal int adverts_modfirst(aim_session_t *sess, aim_module_t *mod); 54 faim_internal int odir_modfirst(aim_session_t *sess, aim_module_t *mod); 55 faim_internal int bart_modfirst(aim_session_t *sess, aim_module_t *mod); 56 faim_internal int ssi_modfirst(aim_session_t *sess, aim_module_t *mod); 56 57 faim_internal int icq_modfirst(aim_session_t *sess, aim_module_t *mod); 57 58 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);59 59 60 60 faim_internal int aim_genericreq_n(aim_session_t *, aim_conn_t *conn, fu16_t family, fu16_t subtype); … … 97 97 98 98 /* rxhandlers.c */ 99 faim_internal aim_rxcallback_t aim_callhandler(aim_session_t *sess, aim_conn_t *conn, u_short family, u_short type);99 faim_internal aim_rxcallback_t aim_callhandler(aim_session_t *sess, aim_conn_t *conn, fu16_t family, fu16_t type); 100 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 101 faim_internal int aim_parse_unknown(aim_session_t *, aim_frame_t *, ...); … … 130 130 } aim_snac_t; 131 131 132 struct aim_snac_destructor {133 aim_conn_t *conn;134 void *data;135 };136 137 132 /* snac.c */ 138 133 faim_internal void aim_initsnachash(aim_session_t *sess); … … 140 135 faim_internal aim_snacid_t aim_cachesnac(aim_session_t *sess, const fu16_t family, const fu16_t type, const fu16_t flags, const void *data, const int datalen); 141 136 faim_internal aim_snac_t *aim_remsnac(aim_session_t *, aim_snacid_t id); 142 faim_internal void aim_cleansnacs(aim_session_t *, int maxage);143 137 faim_internal int aim_putsnac(aim_bstream_t *, fu16_t family, fu16_t type, fu16_t flags, aim_snacid_t id); 144 138 … … 148 142 char name[128]; 149 143 fu16_t instance; 150 };151 152 /* these are used by aim_*_clientready */153 #define AIM_TOOL_JAVA 0x0001154 #define AIM_TOOL_MAC 0x0002155 #define AIM_TOOL_WIN16 0x0003156 #define AIM_TOOL_WIN32 0x0004157 #define AIM_TOOL_MAC68K 0x0005158 #define AIM_TOOL_MACPPC 0x0006159 #define AIM_TOOL_NEWWIN 0x0010160 struct aim_tool_version {161 fu16_t group;162 fu16_t version;163 fu16_t tool;164 fu16_t toolversion;165 144 }; 166 145 … … 221 200 faim_internal int aim_cookie_free(aim_session_t *sess, aim_msgcookie_t *cookie); 222 201 223 faim_internal int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *); 202 faim_internal void aim_info_free(aim_userinfo_t *); 203 faim_internal int aim_info_extract(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *); 224 204 faim_internal int aim_putuserinfo(aim_bstream_t *bs, aim_userinfo_t *info); 225 205 … … 227 207 228 208 faim_internal void faimdprintf(aim_session_t *sess, int dlevel, const char *format, ...); 229 230 faim_internal int aim_request_directim(aim_session_t *sess, const char *destsn, fu8_t *ip, fu16_t port, fu8_t *ckret);231 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);232 faim_internal void aim_conn_close_rend(aim_session_t *sess, aim_conn_t *conn);233 faim_internal void aim_conn_kill_rend(aim_session_t *sess, aim_conn_t *conn);234 209 235 210 faim_internal void aim_conn_kill_chat(aim_session_t *sess, aim_conn_t *conn); -
libfaim/auth.c
r862371b re374dee 8 8 9 9 #define FAIM_INTERNAL 10 #include <aim.h> 10 #include <aim.h> 11 11 12 12 #include "md5.h" 13 13 14 static int aim_encode_password(const char *password, unsigned char*encoded);14 static int aim_encode_password(const char *password, fu8_t *encoded); 15 15 16 16 /* … … 22 22 * 23 23 */ 24 faim_export int aim_sendcookie(aim_session_t *sess, aim_conn_t *conn, const fu 8_t *chipsahoy)24 faim_export int aim_sendcookie(aim_session_t *sess, aim_conn_t *conn, const fu16_t length, const fu8_t *chipsahoy) 25 25 { 26 26 aim_frame_t *fr; 27 27 aim_tlvlist_t *tl = NULL; 28 28 29 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x0001, 4+2+2+ AIM_COOKIELEN)))29 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x0001, 4+2+2+length))) 30 30 return -ENOMEM; 31 31 32 32 aimbs_put32(&fr->data, 0x00000001); 33 aim_addtlvtochain_raw(&tl, 0x0006, AIM_COOKIELEN, chipsahoy);33 aim_addtlvtochain_raw(&tl, 0x0006, length, chipsahoy); 34 34 aim_writetlvchain(&fr->data, &tl); 35 35 aim_freetlvchain(&tl); … … 157 157 aim_frame_t *fr; 158 158 aim_tlvlist_t *tl = NULL; 159 char *password_encoded; 160 161 if (!(password_encoded = (char *) malloc(strlen(password)))) 159 int passwdlen; 160 fu8_t *password_encoded; 161 162 passwdlen = strlen(password); 163 if (!(password_encoded = (char *)malloc(passwdlen+1))) 162 164 return -ENOMEM; 165 if (passwdlen > MAXICQPASSLEN) 166 passwdlen = MAXICQPASSLEN; 163 167 164 168 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 1152))) { … … 171 175 aimbs_put32(&fr->data, 0x00000001); /* FLAP Version */ 172 176 aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), sn); 173 aim_addtlvtochain_raw(&tl, 0x0002, strlen(password), password_encoded);177 aim_addtlvtochain_raw(&tl, 0x0002, passwdlen, password_encoded); 174 178 175 179 if (ci->clientstring) … … 180 184 aim_addtlvtochain16(&tl, 0x0019, (fu16_t)ci->point); 181 185 aim_addtlvtochain16(&tl, 0x001a, (fu16_t)ci->build); 182 aim_addtlvtochain32(&tl, 0x0014, 0x00000055); /* distribution chan */186 aim_addtlvtochain32(&tl, 0x0014, (fu32_t)ci->distrib); /* distribution chan */ 183 187 aim_addtlvtochain_raw(&tl, 0x000f, strlen(ci->lang), ci->lang); 184 188 aim_addtlvtochain_raw(&tl, 0x000e, strlen(ci->country), ci->country); … … 202 206 * then the client information you send here must exactly match the 203 207 * executable that you're pulling the data from. 204 *205 * WinAIM 4.8.2540206 * clientstring = "AOL Instant Messenger (SM), version 4.8.2540/WIN32"207 * clientid = 0x0109208 * major = 0x0004209 * minor = 0x0008210 * point = 0x0000211 * build = 0x09ec212 * t(0x0014) = 0x000000af213 * t(0x004a) = 0x01214 *215 * WinAIM 4.3.2188:216 * clientstring = "AOL Instant Messenger (SM), version 4.3.2188/WIN32"217 * clientid = 0x0109218 * major = 0x0400219 * minor = 0x0003220 * point = 0x0000221 * build = 0x088c222 * unknown = 0x00000086223 * lang = "en"224 * country = "us"225 * unknown4a = 0x01226 *227 * Latest WinAIM that libfaim can emulate without server-side buddylists:228 * clientstring = "AOL Instant Messenger (SM), version 4.1.2010/WIN32"229 * clientid = 0x0004230 * major = 0x0004231 * minor = 0x0001232 * point = 0x0000233 * build = 0x07da234 * unknown= 0x0000004b235 *236 * WinAIM 3.5.1670:237 * clientstring = "AOL Instant Messenger (SM), version 3.5.1670/WIN32"238 * clientid = 0x0004239 * major = 0x0003240 * minor = 0x0005241 * point = 0x0000242 * build = 0x0686243 * unknown =0x0000002a244 208 * 245 209 * Java AIM 1.1.19: … … 304 268 aim_addtlvtochain16(&tl, 0x0019, (fu16_t)ci->point); 305 269 aim_addtlvtochain16(&tl, 0x001a, (fu16_t)ci->build); 270 aim_addtlvtochain32(&tl, 0x0014, (fu32_t)ci->distrib); 306 271 aim_addtlvtochain_raw(&tl, 0x000e, strlen(ci->country), ci->country); 307 272 aim_addtlvtochain_raw(&tl, 0x000f, strlen(ci->lang), ci->lang); 308 273 274 #ifndef NOSSI 309 275 /* 310 276 * If set, old-fashioned buddy lists will not work. You will need … … 312 278 */ 313 279 aim_addtlvtochain8(&tl, 0x004a, 0x01); 280 #endif 314 281 315 282 aim_writetlvchain(&fr->data, &tl); … … 388 355 aim_tlvlist_t *tlvlist; 389 356 aim_rxcallback_t userfunc; 390 struct aim_authresp_info info;357 struct aim_authresp_info *info; 391 358 int ret = 0; 392 359 393 memset(&info, 0, sizeof(info)); 360 info = (struct aim_authresp_info *)malloc(sizeof(struct aim_authresp_info)); 361 memset(info, 0, sizeof(struct aim_authresp_info)); 394 362 395 363 /* … … 404 372 memset(sess->sn, 0, sizeof(sess->sn)); 405 373 if (aim_gettlv(tlvlist, 0x0001, 1)) { 406 info .sn = aim_gettlv_str(tlvlist, 0x0001, 1);407 strncpy(sess->sn, info .sn, sizeof(sess->sn));374 info->sn = aim_gettlv_str(tlvlist, 0x0001, 1); 375 strncpy(sess->sn, info->sn, sizeof(sess->sn)); 408 376 } 409 377 … … 413 381 */ 414 382 if (aim_gettlv(tlvlist, 0x0008, 1)) 415 info .errorcode = aim_gettlv16(tlvlist, 0x0008, 1);383 info->errorcode = aim_gettlv16(tlvlist, 0x0008, 1); 416 384 if (aim_gettlv(tlvlist, 0x0004, 1)) 417 info .errorurl = aim_gettlv_str(tlvlist, 0x0004, 1);385 info->errorurl = aim_gettlv_str(tlvlist, 0x0004, 1); 418 386 419 387 /* … … 421 389 */ 422 390 if (aim_gettlv(tlvlist, 0x0005, 1)) 423 info .bosip = aim_gettlv_str(tlvlist, 0x0005, 1);391 info->bosip = aim_gettlv_str(tlvlist, 0x0005, 1); 424 392 425 393 /* … … 431 399 tmptlv = aim_gettlv(tlvlist, 0x0006, 1); 432 400 433 info.cookie = tmptlv->value; 401 info->cookielen = tmptlv->length; 402 info->cookie = tmptlv->value; 434 403 } 435 404 436 405 /* 437 406 * The email address attached to this account 438 * Not available for ICQ logins. 407 * Not available for ICQ or @mac.com logins. 408 * If you receive this TLV, then you are allowed to use 409 * family 0x0018 to check the status of your email. 410 * XXX - Not really true! 439 411 */ 440 412 if (aim_gettlv(tlvlist, 0x0011, 1)) 441 info .email = aim_gettlv_str(tlvlist, 0x0011, 1);413 info->email = aim_gettlv_str(tlvlist, 0x0011, 1); 442 414 443 415 /* 444 416 * The registration status. (Not real sure what it means.) 445 * Not available for ICQ logins.417 * Not available for ICQ or @mac.com logins. 446 418 * 447 419 * 1 = No disclosure … … 452 424 * to other users or not. AFAIK, this feature is no longer used. 453 425 * 426 * Means you can use the admin family? (0x0007) 427 * 454 428 */ 455 429 if (aim_gettlv(tlvlist, 0x0013, 1)) 456 info .regstatus = aim_gettlv16(tlvlist, 0x0013, 1);430 info->regstatus = aim_gettlv16(tlvlist, 0x0013, 1); 457 431 458 432 if (aim_gettlv(tlvlist, 0x0040, 1)) 459 info .latestbeta.build = aim_gettlv32(tlvlist, 0x0040, 1);433 info->latestbeta.build = aim_gettlv32(tlvlist, 0x0040, 1); 460 434 if (aim_gettlv(tlvlist, 0x0041, 1)) 461 info .latestbeta.url = aim_gettlv_str(tlvlist, 0x0041, 1);435 info->latestbeta.url = aim_gettlv_str(tlvlist, 0x0041, 1); 462 436 if (aim_gettlv(tlvlist, 0x0042, 1)) 463 info .latestbeta.info = aim_gettlv_str(tlvlist, 0x0042, 1);437 info->latestbeta.info = aim_gettlv_str(tlvlist, 0x0042, 1); 464 438 if (aim_gettlv(tlvlist, 0x0043, 1)) 465 info .latestbeta.name = aim_gettlv_str(tlvlist, 0x0043, 1);439 info->latestbeta.name = aim_gettlv_str(tlvlist, 0x0043, 1); 466 440 if (aim_gettlv(tlvlist, 0x0048, 1)) 467 441 ; /* no idea what this is */ 468 442 469 443 if (aim_gettlv(tlvlist, 0x0044, 1)) 470 info .latestrelease.build = aim_gettlv32(tlvlist, 0x0044, 1);444 info->latestrelease.build = aim_gettlv32(tlvlist, 0x0044, 1); 471 445 if (aim_gettlv(tlvlist, 0x0045, 1)) 472 info .latestrelease.url = aim_gettlv_str(tlvlist, 0x0045, 1);446 info->latestrelease.url = aim_gettlv_str(tlvlist, 0x0045, 1); 473 447 if (aim_gettlv(tlvlist, 0x0046, 1)) 474 info .latestrelease.info = aim_gettlv_str(tlvlist, 0x0046, 1);448 info->latestrelease.info = aim_gettlv_str(tlvlist, 0x0046, 1); 475 449 if (aim_gettlv(tlvlist, 0x0047, 1)) 476 info .latestrelease.name = aim_gettlv_str(tlvlist, 0x0047, 1);450 info->latestrelease.name = aim_gettlv_str(tlvlist, 0x0047, 1); 477 451 if (aim_gettlv(tlvlist, 0x0049, 1)) 478 452 ; /* no idea what this is */ … … 482 456 */ 483 457 if (aim_gettlv(tlvlist, 0x0054, 1)) 484 info.chpassurl = aim_gettlv_str(tlvlist, 0x0054, 1); 458 info->chpassurl = aim_gettlv_str(tlvlist, 0x0054, 1); 459 460 /* 461 * Unknown. Seen on an @mac.com screen name with value of 0x003f 462 */ 463 if (aim_gettlv(tlvlist, 0x0055, 1)) 464 ; 465 466 sess->authinfo = info; 485 467 486 468 if ((userfunc = aim_callhandler(sess, rx->conn, snac ? snac->family : 0x0017, snac ? snac->subtype : 0x0003))) 487 ret = userfunc(sess, rx, &info); 488 489 free(info.sn); 490 free(info.bosip); 491 free(info.errorurl); 492 free(info.email); 493 free(info.chpassurl); 494 free(info.latestrelease.name); 495 free(info.latestrelease.url); 496 free(info.latestrelease.info); 497 free(info.latestbeta.name); 498 free(info.latestbeta.url); 499 free(info.latestbeta.info); 469 ret = userfunc(sess, rx, info); 500 470 501 471 aim_freetlvchain(&tlvlist); … … 520 490 keystr = aimbs_getstr(bs, keylen); 521 491 492 /* XXX - When GiantGrayPanda signed on AIM I got a thing asking me to register 493 * for the netscape network. This SNAC had a type 0x0058 TLV with length 10. 494 * Data is 0x0007 0004 3e19 ae1e 0006 0004 0000 0005 */ 495 522 496 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 523 497 ret = userfunc(sess, rx, keystr); … … 526 500 527 501 return ret; 502 } 503 504 static void auth_shutdown(aim_session_t *sess, aim_module_t *mod) 505 { 506 if (sess->authinfo) { 507 free(sess->authinfo->sn); 508 free(sess->authinfo->bosip); 509 free(sess->authinfo->errorurl); 510 free(sess->authinfo->email); 511 free(sess->authinfo->chpassurl); 512 free(sess->authinfo->latestrelease.name); 513 free(sess->authinfo->latestrelease.url); 514 free(sess->authinfo->latestrelease.info); 515 free(sess->authinfo->latestbeta.name); 516 free(sess->authinfo->latestbeta.url); 517 free(sess->authinfo->latestbeta.info); 518 free(sess->authinfo); 519 } 528 520 } 529 521 … … 547 539 strncpy(mod->name, "auth", sizeof(mod->name)); 548 540 mod->snachandler = snachandler; 549 550 return 0; 551 } 541 mod->shutdown = auth_shutdown; 542 543 return 0; 544 } -
libfaim/bos.c
r862371b re374dee 2 2 * Family 0x0009 - Basic Oscar Service. 3 3 * 4 * The functionality of this family has been replaced by SSI. 4 5 */ 5 6 6 7 #define FAIM_INTERNAL 7 8 #include <aim.h> 9 10 #include <string.h> 8 11 9 12 /* Subtype 0x0002 - Request BOS rights. */ … … 127 130 128 131 for (i = 0; (i < (listcount - 1)) && (i < 99); i++) { 129 tmpptr = aimutil_itemi dx(localcpy, i, '&');132 tmpptr = aimutil_itemindex(localcpy, i, '&'); 130 133 131 134 aimbs_put8(&fr->data, strlen(tmpptr)); … … 156 159 mod->version = 0x0001; 157 160 mod->toolid = 0x0110; 158 mod->toolversion = 0x0 47b;161 mod->toolversion = 0x0629; 159 162 mod->flags = 0; 160 163 strncpy(mod->name, "bos", sizeof(mod->name)); -
libfaim/bstream.c
r862371b re374dee 231 231 return NULL; 232 232 } 233 233 234 234 ob[len] = '\0'; 235 235 -
libfaim/buddylist.c
r862371b re374dee 6 6 #define FAIM_INTERNAL 7 7 #include <aim.h> 8 9 #include <string.h> 8 10 9 11 /* … … 233 235 * 234 236 * Oncoming Buddy notifications contain a subset of the 235 * user information structure. It s close enough to run236 * through aim_ extractuserinfo() however.237 * user information structure. It's close enough to run 238 * through aim_info_extract() however. 237 239 * 238 240 * Although the offgoing notification contains no information, 239 * it is still in a format parsable by extractuserinfo.241 * it is still in a format parsable by aim_info_extract(). 240 242 * 241 243 */ 242 244 static int buddychange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 243 245 { 246 int ret = 0; 244 247 aim_userinfo_t userinfo; 245 248 aim_rxcallback_t userfunc; 246 249 247 aim_ extractuserinfo(sess, bs, &userinfo);250 aim_info_extract(sess, bs, &userinfo); 248 251 249 252 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 250 return userfunc(sess, rx, &userinfo); 251 252 return 0; 253 ret = userfunc(sess, rx, &userinfo); 254 255 aim_info_free(&userinfo); 256 257 return ret; 253 258 } 254 259 … … 270 275 mod->version = 0x0001; 271 276 mod->toolid = 0x0110; 272 mod->toolversion = 0x0 47b;277 mod->toolversion = 0x0629; 273 278 mod->flags = 0; 274 279 strncpy(mod->name, "buddylist", sizeof(mod->name)); -
libfaim/chat.c
r862371b re374dee 6 6 #define FAIM_INTERNAL 7 7 #include <aim.h> 8 9 #include <string.h> 8 10 9 11 /* Stored in the ->priv of chat connections */ … … 205 207 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); 206 208 207 208 209 /* 209 210 * Cookie 210 211 */ 211 for (i = 0; i < sizeof(ckstr); i++)212 aimutil_put8(ckstr, (fu8_t) rand());212 for (i = 0; i < 8; i++) 213 ckstr[i] = (fu8_t)rand(); 213 214 214 215 /* XXX should be uncached by an unwritten 'invite accept' handler */ … … 225 226 free(priv); 226 227 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)); 228 /* ICBM Header */ 229 aimbs_putraw(&fr->data, ckstr, 8); /* Cookie */ 230 aimbs_put16(&fr->data, 0x0002); /* Channel */ 231 aimbs_put8(&fr->data, strlen(sn)); /* Screename length */ 232 aimbs_putraw(&fr->data, sn, strlen(sn)); /* Screenname */ 241 233 242 234 /* … … 346 338 347 339 while (curoccupant < usercount) 348 aim_ extractuserinfo(sess, &occbs, &userinfo[curoccupant++]);340 aim_info_extract(sess, &occbs, &userinfo[curoccupant++]); 349 341 } 350 342 … … 424 416 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { 425 417 ret = userfunc(sess, 426 rx, 418 rx, 427 419 &roominfo, 428 420 roomname, 429 421 usercount, 430 userinfo, 422 userinfo, 431 423 roomdesc, 432 424 flags, … … 439 431 440 432 free(roominfo.name); 433 434 while (usercount > 0) 435 aim_info_free(&userinfo[--usercount]); 436 441 437 free(userinfo); 442 438 free(roomname); … … 457 453 curcount++; 458 454 userinfo = realloc(userinfo, curcount * sizeof(aim_userinfo_t)); 459 aim_ extractuserinfo(sess, bs, &userinfo[curcount-1]);455 aim_info_extract(sess, bs, &userinfo[curcount-1]); 460 456 } 461 457 … … 463 459 ret = userfunc(sess, rx, curcount, userinfo); 464 460 461 aim_info_free(userinfo); 465 462 free(userinfo); 466 463 … … 498 495 aim_putsnac(&fr->data, 0x000e, 0x0005, 0x0000, snacid); 499 496 500 501 /* 502 * Generate a random message cookie. 497 /* 498 * Cookie 503 499 * 504 500 * XXX mkcookie should generate the cookie and cache it in one 505 501 * operation to preserve uniqueness. 506 * 507 */ 508 for (i = 0; i < sizeof(ckstr); i++) 509 aimutil_put8(ckstr+i, (fu8_t) rand()); 502 */ 503 for (i = 0; i < 8; i++) 504 ckstr[i] = (fu8_t)rand(); 510 505 511 506 cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_CHAT, NULL); … … 514 509 aim_cachecookie(sess, cookie); 515 510 516 for (i = 0; i < sizeof(ckstr); i++) 517 aimbs_put8(&fr->data, ckstr[i]); 518 519 520 /* 521 * Channel ID. 522 */ 523 aimbs_put16(&fr->data, 0x0003); 524 511 /* ICBM Header */ 512 aimbs_putraw(&fr->data, ckstr, 8); /* Cookie */ 513 aimbs_put16(&fr->data, 0x0003); /* Channel */ 525 514 526 515 /* … … 544 533 * SubTLV: Type 1: Message 545 534 */ 546 aim_addtlvtochain_raw(&itl, 0x0001, strlen(msg), msg);535 aim_addtlvtochain_raw(&itl, 0x0001, msglen, msg); 547 536 548 537 /* … … 644 633 645 634 aim_bstream_init(&tbs, userinfotlv->value, userinfotlv->length); 646 aim_ extractuserinfo(sess, &tbs, &userinfo);635 aim_info_extract(sess, &tbs, &userinfo); 647 636 } 648 637 … … 678 667 ret = userfunc(sess, rx, &userinfo, msg); 679 668 669 aim_info_free(&userinfo); 680 670 free(cookie); 681 671 free(msg); … … 703 693 mod->family = 0x000e; 704 694 mod->version = 0x0001; 705 mod->toolid = 0x00 04; /* XXX this doesn't look right */706 mod->toolversion = 0x0 001; /* nor does this */695 mod->toolid = 0x0010; 696 mod->toolversion = 0x0629; 707 697 mod->flags = 0; 708 698 strncpy(mod->name, "chat", sizeof(mod->name)); -
libfaim/chatnav.c
r862371b re374dee 424 424 425 425 mod->family = 0x000d; 426 mod->version = 0x000 3;426 mod->version = 0x0001; 427 427 mod->toolid = 0x0010; 428 mod->toolversion = 0x0 47c;428 mod->toolversion = 0x0629; 429 429 mod->flags = 0; 430 430 strncpy(mod->name, "chatnav", sizeof(mod->name)); -
libfaim/configure
r5e53c4a re374dee 747 747 748 748 if test "$GCC" = yes; then 749 CFLAGS="$CFLAGS -Wall ";749 CFLAGS="$CFLAGS -Wall -g"; 750 750 fi 751 751 # Extract the first word of "ranlib", so it can be a program name with args. -
libfaim/configure.in
r5e53c4a re374dee 6 6 dnl we're using GCC, enable all warnings 7 7 if test "$GCC" = yes; then 8 CFLAGS="$CFLAGS -Wall ";8 CFLAGS="$CFLAGS -Wall -g"; 9 9 fi 10 10 AC_PROG_RANLIB -
libfaim/conn.c
r862371b re374dee 173 173 * This will free ->internal if it necessary... 174 174 */ 175 if ((*deadconn)->type == AIM_CONN_TYPE_RENDEZVOUS) 176 aim_conn_kill_rend(sess, *deadconn); 177 else if ((*deadconn)->type == AIM_CONN_TYPE_CHAT) 175 if ((*deadconn)->type == AIM_CONN_TYPE_CHAT) 178 176 aim_conn_kill_chat(sess, *deadconn); 179 177 … … 319 317 faim_export void aim_conn_close(aim_conn_t *deadconn) 320 318 { 319 aim_rxcallback_t userfunc; 321 320 322 321 if (deadconn->fd >= 3) 323 322 close(deadconn->fd); 323 324 324 deadconn->fd = -1; 325 326 if ((userfunc = aim_callhandler(deadconn->sessv, deadconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNDEAD))) 327 userfunc(deadconn->sessv, NULL, deadconn); 328 325 329 if (deadconn->handlerlist) 326 330 aim_clearhandlers(deadconn); 327 if (deadconn->type == AIM_CONN_TYPE_RENDEZVOUS)328 aim_conn_close_rend((aim_session_t *)deadconn->sessv, deadconn);329 331 330 332 return; … … 871 873 aim_initsnachash(sess); 872 874 sess->msgcookies = NULL; 875 sess->icq_info = NULL; 876 sess->oft_info = NULL; 873 877 sess->snacid_next = 0x00000001; 874 878 … … 880 884 881 885 sess->ssi.received_data = 0; 886 sess->ssi.numitems = 0; 887 sess->ssi.official = NULL; 888 sess->ssi.local = NULL; 889 sess->ssi.pending = NULL; 890 sess->ssi.timestamp = (time_t)0; 882 891 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 892 893 sess->authinfo = NULL; 888 894 sess->emailinfo = NULL; 889 895 … … 920 926 aim__registermodule(sess, chatnav_modfirst); 921 927 aim__registermodule(sess, chat_modfirst); 922 aim__registermodule(sess, newsearch_modfirst); 923 /* missing 0x10 - 0x12 */ 928 /* aim__registermodule(sess, odir_modfirst); */ /* kretch */ 929 /* aim__registermodule(sess, bart_modfirst); */ /* kretch */ 930 /* missing 0x11 - 0x12 */ 924 931 aim__registermodule(sess, ssi_modfirst); 925 932 /* missing 0x14 */ … … 992 999 faim_export int aim_conn_completeconnect(aim_session_t *sess, aim_conn_t *conn) 993 1000 { 994 fd_set fds, wfds;995 struct timeval tv;996 int res;997 int error = ETIMEDOUT;998 999 1001 aim_rxcallback_t userfunc; 1000 1002 … … 1005 1007 return -1; 1006 1008 1007 FD_ZERO(&fds); 1008 FD_SET(conn->fd, &fds); 1009 FD_ZERO(&wfds); 1010 FD_SET(conn->fd, &wfds); 1011 tv.tv_sec = 0; 1012 tv.tv_usec = 0; 1013 1014 if ((res = select(conn->fd+1, &fds, &wfds, NULL, &tv)) == -1) { 1015 error = errno; 1016 aim_conn_close(conn); 1017 errno = error; 1018 return -1; 1019 } else if (res == 0) { 1020 faimdprintf(sess, 0, "aim_conn_completeconnect: false alarm on %d\n", conn->fd); 1021 return 0; /* hasn't really completed yet... */ 1022 } 1023 1024 if (FD_ISSET(conn->fd, &fds) || FD_ISSET(conn->fd, &wfds)) { 1025 int len = sizeof(error); 1026 if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) 1027 error = errno; 1028 } 1029 1030 if (error) { 1031 aim_conn_close(conn); 1032 errno = error; 1033 return -1; 1034 } 1035 fcntl(conn->fd, F_SETFL, 0); /* XXX should restore original flags */ 1009 fcntl(conn->fd, F_SETFL, 0); 1036 1010 1037 1011 conn->status &= ~AIM_CONN_STATUS_INPROGRESS; -
libfaim/email.c
r862371b re374dee 63 63 /** 64 64 * Subtype 0x0007 - Receive information about your email account 65 * 65 66 * So I don't even know if you can have multiple 16 byte keys, 66 67 * but this is coded so it will handle that, and handle it well. … … 74 75 static int parseinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 75 76 { 77 int ret = 0; 76 78 aim_rxcallback_t userfunc; 77 79 struct aim_emailinfo *new; … … 125 127 126 128 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 127 return userfunc(sess, rx, new, havenewmail); 128 129 return 0; 129 ret = userfunc(sess, rx, new, havenewmail); 130 131 aim_freetlvchain(&tlvlist); 132 133 return ret; 130 134 } 131 135 -
libfaim/ft.c
r862371b re374dee 1 1 /* 2 * File transfer (OFT) and DirectIM (ODC). 3 * (OSCAR File Transfer, Oscar Direct Connect(ion?) 2 * Oscar File transfer (OFT) and Oscar Direct Connect (ODC). 3 * (ODC is also referred to as DirectIM and IM Image.) 4 * 5 * There are a few static helper functions at the top, then 6 * ODC stuff, then ft stuff. 7 * 8 * I feel like this is a good place to explain OFT, so I'm going to 9 * do just that. Each OFT packet has a header type. I guess this 10 * is pretty similar to the subtype of a SNAC packet. The type 11 * basically tells the other client the meaning of the OFT packet. 12 * There are two distinct types of file transfer, which I usually 13 * call "sendfile" and "getfile." Sendfile is when you send a file 14 * to another AIM user. Getfile is when you share a group of files, 15 * and other users request that you send them the files. 16 * 17 * A typical sendfile file transfer goes like this: 18 * 1) Sender sends a channel 2 ICBM telling the other user that 19 * we want to send them a file. At the same time, we open a 20 * listener socket (this should be done before sending the 21 * ICBM) on some port, and wait for them to connect to us. 22 * The ICBM we sent should contain our IP address and the port 23 * number that we're listening on. 24 * 2) The receiver connects to the sender on the given IP address 25 * and port. After the connection is established, the receiver 26 * sends an ICBM signifying that we are ready and waiting. 27 * 3) The sender sends an OFT PROMPT message over the OFT 28 * connection. 29 * 4) The receiver of the file sends back an exact copy of this 30 * OFT packet, except the cookie is filled in with the cookie 31 * from the ICBM. I think this might be an attempt to verify 32 * that the user that is connected is actually the guy that 33 * we sent the ICBM to. Oh, I've been calling this the ACK. 34 * 5) The sender starts sending raw data across the connection 35 * until the entire file has been sent. 36 * 6) The receiver knows the file is finished because the sender 37 * sent the file size in an earlier OFT packet. So then the 38 * receiver sends the DONE thingy (after filling in the 39 * "received" checksum and size) and closes the connection. 4 40 */ 5 41 6 42 #define FAIM_INTERNAL 7 8 43 #ifdef HAVE_CONFIG_H 9 #include <config.h>44 #include <config.h> 10 45 #endif 46 11 47 #include <aim.h> 12 48 13 49 #ifndef _WIN32 50 #include <stdio.h> 14 51 #include <netdb.h> 15 52 #include <sys/socket.h> 16 53 #include <netinet/in.h> 17 #include <sys/utsname.h> /* for aim_ directim_initiate */54 #include <sys/utsname.h> /* for aim_odc_initiate */ 18 55 #include <arpa/inet.h> /* for inet_ntoa */ 19 56 #define G_DIR_SEPARATOR '/' … … 24 61 #endif 25 62 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 }; 39 40 struct aim_directim_intdata { 63 struct aim_odc_intdata { 41 64 fu8_t cookie[8]; 42 65 char sn[MAXSNLEN+1]; … … 44 67 }; 45 68 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); 50 51 /** 52 * aim_handlerendconnect - call this to accept OFT connections and set up the required structures 53 * @sess: the session 54 * @cur: the conn the incoming connection is on 55 * 56 * call this when you get an outstanding read on a conn with subtype 57 * AIM_CONN_SUBTYPE_RENDEZVOUS_OUT, it will clone the current 58 * &aim_conn_t and tweak things as appropriate. the new conn and the 59 * listener conn are both returned to the client in the 60 * %AIM_CB_FAM_OFT, %AIM_CB_OFT_<CLASS>INITIATE callback. 61 */ 62 faim_export int aim_handlerendconnect(aim_session_t *sess, aim_conn_t *cur) 63 { 64 int acceptfd = 0; 65 struct sockaddr cliaddr; 66 int clilen = sizeof(cliaddr); 67 int ret = 0; 68 aim_conn_t *newconn; 69 70 if ((acceptfd = accept(cur->fd, &cliaddr, &clilen)) == -1) 71 return 0; /* not an error */ 72 73 if (cliaddr.sa_family != AF_INET) { /* just in case IPv6 really is happening */ 74 close(acceptfd); 75 aim_conn_close(cur); 76 return -1; 77 } 78 79 if (!(newconn = aim_cloneconn(sess, cur))) { 80 close(acceptfd); 81 aim_conn_close(cur); 82 return -1; 83 } 84 85 newconn->type = AIM_CONN_TYPE_RENDEZVOUS; 86 newconn->fd = acceptfd; 87 88 if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) { 89 struct aim_directim_intdata *priv; 90 aim_rxcallback_t userfunc; 91 92 priv = (struct aim_directim_intdata *)(newconn->internal = cur->internal); 93 cur->internal = NULL; 94 95 snprintf(priv->ip, sizeof(priv->ip), "%s:%u", 96 inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), 97 ntohs(((struct sockaddr_in *)&cliaddr)->sin_port)); 98 99 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE))) 100 ret = userfunc(sess, NULL, newconn, cur); 101 102 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) { 103 #if 0 104 struct aim_filetransfer_priv *priv; 105 aim_rxcallback_t userfunc; 106 107 newconn->priv = cur->priv; 108 cur->priv = NULL; 109 priv = (struct aim_filetransfer_priv *)newconn->priv; 110 111 snprintf(priv->ip, sizeof(priv->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port)); 112 113 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE))) 114 ret = userfunc(sess, NULL, newconn, cur); 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); 129 } else { 130 faimdprintf(sess, 1,"Got a Connection on a listener that's not Rendezvous Closing conn.\n"); 131 aim_conn_close(newconn); 132 ret = -1; 133 } 134 135 return ret; 136 } 137 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 /** 209 * aim_send_im_direct - send IM client-to-client over established connection 210 * @sess: session to conn 211 * @conn: directim connection 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 * 216 * Call this just like you would aim_send_im, to send a directim. You 217 * _must_ have previously established the directim connection. 218 */ 219 faim_export int aim_send_im_direct(aim_session_t *sess, aim_conn_t *conn, const char *msg, int len, int encoding) 220 { 221 struct aim_directim_intdata *intdata = (struct aim_directim_intdata *)conn->internal; 222 aim_frame_t *fr; 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)) 228 return -EINVAL; 229 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; 235 236 if (!(hdr = calloc(1, hdrlen + len))) { 237 aim_frame_destroy(fr); 238 return -ENOMEM; 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); 255 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 275 /* end of hdr2 */ 276 277 #if 0 /* XXX this is how you send buddy icon info... */ 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); 286 #endif 287 aimbs_putraw(hdrbs, msg, len); 288 289 aim_tx_enqueue(sess, fr); 290 291 return 0; 292 } 293 294 static int getlocalip(fu8_t *ip) 295 { 296 struct hostent *hptr; 297 char localhost[129]; 298 299 /* XXX if available, use getaddrinfo() */ 300 /* XXX allow client to specify which IP to use for multihomed boxes */ 301 302 if (gethostname(localhost, 128) < 0) 303 return -1; 304 305 if (!(hptr = gethostbyname(localhost))) 306 return -1; 307 308 memcpy(ip, hptr->h_addr_list[0], 4); 309 310 return 0; 311 } 312 313 /** 314 * aim_directim_intitiate - For those times when we want to open up the directim channel ourselves. 315 * @sess: your session, 316 * @conn: the BOS conn, 317 * @priv: a dummy priv value (we'll let it get filled in later) (if you pass a %NULL, we alloc one) 318 * @destsn: the SN to connect to. 319 * 320 */ 321 faim_export aim_conn_t *aim_directim_initiate(aim_session_t *sess, const char *destsn) 322 { 323 aim_conn_t *newconn; 324 aim_msgcookie_t *cookie; 325 struct aim_directim_intdata *priv; 326 int listenfd; 327 fu16_t port = 4443; 328 fu8_t localip[4]; 329 fu8_t ck[8]; 330 331 if (getlocalip(localip) == -1) 332 return NULL; 333 334 if ((listenfd = listenestablish(port)) == -1) 335 return NULL; 336 337 aim_request_directim(sess, destsn, localip, port, ck); 338 339 cookie = (aim_msgcookie_t *)calloc(1, sizeof(aim_msgcookie_t)); 340 memcpy(cookie->cookie, ck, 8); 341 cookie->type = AIM_COOKIETYPE_OFTIM; 342 343 /* this one is for the cookie */ 344 priv = (struct aim_directim_intdata *)calloc(1, sizeof(struct aim_directim_intdata)); 345 346 memcpy(priv->cookie, ck, 8); 347 strncpy(priv->sn, destsn, sizeof(priv->sn)); 348 cookie->data = priv; 349 aim_cachecookie(sess, cookie); 350 351 /* XXX switch to aim_cloneconn()? */ 352 if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL))) { 353 close(listenfd); 354 return NULL; 355 } 356 357 /* this one is for the conn */ 358 priv = (struct aim_directim_intdata *)calloc(1, sizeof(struct aim_directim_intdata)); 359 360 memcpy(priv->cookie, ck, 8); 361 strncpy(priv->sn, destsn, sizeof(priv->sn)); 362 363 newconn->fd = listenfd; 364 newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM; 365 newconn->internal = priv; 366 newconn->lastactivity = time(NULL); 367 368 faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd); 369 370 return newconn; 371 } 372 373 /** 374 * aim_sendfile_intitiate - For those times when we want to send the file ourselves. 375 * @sess: your session, 376 * @conn: the BOS conn, 377 * @destsn: the SN to connect to. 378 * @filename: the name of the files you want to send 379 * 380 */ 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) 382 { 383 aim_conn_t *newconn; 384 aim_msgcookie_t *cookie; 385 struct aim_filetransfer_priv *ft; 386 int listenfd; 387 388 /* XXX allow different ports */ 389 fu16_t port = 4443; 390 fu8_t localip[4]; 391 fu8_t ck[8]; 392 393 if (getlocalip(localip) == -1) 394 return NULL; 395 396 if ((listenfd = listenestablish(port)) == -1) 397 return NULL; 398 399 aim_request_sendfile(sess, destsn, filename, numfiles, totsize, localip, port, ck); 400 401 cookie = (aim_msgcookie_t *)calloc(1, sizeof(aim_msgcookie_t)); 402 memcpy(cookie->cookie, ck, 8); 403 cookie->type = AIM_COOKIETYPE_OFTSEND; 404 memcpy(cookret, ck, 8); 405 406 /* this one is for the cookie */ 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; 412 aim_cachecookie(sess, cookie); 413 414 if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL))) { 415 close(listenfd); 416 return NULL; 417 } 418 419 /* this one is for the conn */ 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)); 424 425 newconn->fd = listenfd; 426 newconn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE; 427 newconn->internal = ft; 428 newconn->lastactivity = time(NULL); 429 430 faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd); 431 432 return newconn; 433 } 434 435 #if 0 436 /** 437 * unsigned int aim_oft_listener_clean - close up old listeners 438 * @sess: session to clean up in 439 * @age: maximum age in seconds 440 * 441 * returns number closed, -1 on error. 442 */ 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 463 464 faim_export const char *aim_directim_getsn(aim_conn_t *conn) 465 { 466 struct aim_directim_intdata *intdata; 467 468 if (!conn) 469 return NULL; 470 471 if ((conn->type != AIM_CONN_TYPE_RENDEZVOUS) || 472 (conn->subtype != AIM_CONN_SUBTYPE_OFT_DIRECTIM)) 473 return NULL; 474 475 if (!conn->internal) 476 return NULL; 477 478 intdata = (struct aim_directim_intdata *)conn->internal; 479 480 return intdata->sn; 481 } 482 483 /** 484 * aim_directim_connect - connect to buddy for directim 485 * @sess: the session to append the conn to, 486 * @sn: the SN we're connecting to 487 * @addr: address to connect to 488 * 489 * This is a wrapper for aim_newconn. 490 * 491 * If addr is NULL, the socket is not created, but the connection is 492 * allocated and setup to connect. 493 * 494 */ 495 faim_export aim_conn_t *aim_directim_connect(aim_session_t *sess, const char *sn, const char *addr, const fu8_t *cookie) 496 { 497 aim_conn_t *newconn; 498 struct aim_directim_intdata *intdata; 499 500 if (!sess || !sn) 501 return NULL; 502 503 if (!(intdata = malloc(sizeof(struct aim_directim_intdata)))) 504 return NULL; 505 memset(intdata, 0, sizeof(struct aim_directim_intdata)); 506 507 memcpy(intdata->cookie, cookie, 8); 508 strncpy(intdata->sn, sn, sizeof(intdata->sn)); 509 if (addr) 510 strncpy(intdata->ip, addr, sizeof(intdata->ip)); 511 512 /* XXX verify that non-blocking connects actually work */ 513 if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, addr))) { 514 free(intdata); 515 return NULL; 516 } 517 518 if (!newconn) { 519 free(intdata); 520 return newconn; 521 } 522 523 newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM; 524 newconn->internal = intdata; 525 526 return newconn; 527 } 528 529 /** 530 * aim_directim_getconn - find a directim conn for buddy name 531 * @sess: your session, 532 * @name: the name to get, 533 * 534 * returns conn for directim with name, %NULL if none found. 535 * 536 */ 537 faim_export aim_conn_t *aim_directim_getconn(aim_session_t *sess, const char *name) 538 { 539 aim_conn_t *cur; 540 541 if (!sess || !name || !strlen(name)) 542 return NULL; 543 544 for (cur = sess->connlist; cur; cur = cur->next) { 545 struct aim_directim_intdata *intdata; 546 547 if ((cur->type != AIM_CONN_TYPE_RENDEZVOUS) || (cur->subtype != AIM_CONN_SUBTYPE_OFT_DIRECTIM)) 548 continue; 549 550 intdata = cur->internal; 551 552 if (aim_sncmp(intdata->sn, name) == 0) 553 break; 554 } 555 556 return cur; 557 } 558 559 /** 560 * aim_accepttransfer - accept a file transfer request 561 * @sess: the session, 562 * @conn: the BOS conn for the CAP reply 563 * @sn: the screenname to send it to, 564 * @cookie: the cookie used 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 * 569 * @listingfiles: number of files to share 570 * @listingtotsize: total size of shared files 571 * @listingsize: length of the listing file(buffer) 572 * @listingchecksum: checksum of the listing 573 * 574 * Returns new connection or %NULL on error. 575 * 576 * XXX this should take a struct. 577 */ 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; 69 /** 70 * Convert the directory separator from / (0x2f) to ^A (0x01) 71 * 72 * @param name The filename to convert. 73 */ 74 static void aim_oft_dirconvert_tostupid(char *name) 75 { 76 while (name[0]) { 77 if (name[0] == 0x01) 78 name[0] = G_DIR_SEPARATOR; 79 name++; 80 } 81 } 82 83 /** 84 * Convert the directory separator from ^A (0x01) to / (0x2f) 85 * 86 * @param name The filename to convert. 87 */ 88 static void aim_oft_dirconvert_fromstupid(char *name) 89 { 90 while (name[0]) { 91 if (name[0] == G_DIR_SEPARATOR) 92 name[0] = 0x01; 93 name++; 94 } 95 } 96 97 /** 98 * Calculate oft checksum of buffer 99 * 100 * Prevcheck should be 0xFFFF0000 when starting a checksum of a file. The 101 * checksum is kind of a rolling checksum thing, so each time you get bytes 102 * of a file you just call this puppy and it updates the checksum. You can 103 * calculate the checksum of an entire file by calling this in a while or a 104 * for loop, or something. 105 * 106 * Thanks to Graham Booker for providing this improved checksum routine, 107 * which is simpler and should be more accurate than Josh Myer's original 108 * code. -- wtm 109 * 110 * This algorithim works every time I have tried it. The other fails 111 * sometimes. So, AOL who thought this up? It has got to be the weirdest 112 * checksum I have ever seen. 113 * 114 * @param buffer Buffer of data to checksum. Man I'd like to buff her... 115 * @param bufsize Size of buffer. 116 * @param prevcheck Previous checksum. 117 */ 118 faim_export fu32_t aim_oft_checksum_chunk(const fu8_t *buffer, int bufferlen, fu32_t prevcheck) 119 { 120 fu32_t check = (prevcheck >> 16) & 0xffff, oldcheck; 585 121 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 642 #if 0 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); 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; 776 } 777 778 /** 779 * aim_getlisting(FILE *file) -- get an aim_fileheader_t for a given FILE* 780 * @file is an opened listing file 781 * 782 * returns a pointer to the filled-in fileheader_t 783 * 784 * Currently omits checksum. we'll fix this when AOL breaks us, i 785 * guess. 786 * 787 */ 788 faim_export struct aim_fileheader_t *aim_getlisting(aim_session_t *sess, FILE *file) 789 { 790 return NULL; 791 #if 0 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; 895 #endif 896 } 897 898 /** 899 * aim_listenestablish - create a listening socket on a port. 900 * @portnum: the port number to bind to. 901 * 902 * you need to call accept() when it's connected. returns your fd 903 * 904 * XXX: give the client author the responsibility of setting up a 905 * listener, then we no longer have a libfaim problem with broken 906 * solaris *innocent smile* -jbm 122 unsigned short val; 123 124 for (i=0; i<bufferlen; i++) { 125 oldcheck = check; 126 if (i&1) 127 val = buffer[i]; 128 else 129 val = buffer[i] << 8; 130 check -= val; 131 /* 132 * The following appears to be necessary.... It happens 133 * every once in a while and the checksum doesn't fail. 134 */ 135 if (check > oldcheck) 136 check--; 137 } 138 check = ((check & 0x0000ffff) + (check >> 16)); 139 check = ((check & 0x0000ffff) + (check >> 16)); 140 return check << 16; 141 } 142 143 faim_export fu32_t aim_oft_checksum_file(char *filename) { 144 FILE *fd; 145 fu32_t checksum = 0xffff0000; 146 147 if ((fd = fopen(filename, "rb"))) { 148 int bytes; 149 fu8_t buffer[1024]; 150 151 while ((bytes = fread(buffer, 1, 1024, fd))) 152 checksum = aim_oft_checksum_chunk(buffer, bytes, checksum); 153 fclose(fd); 154 } 155 156 return checksum; 157 } 158 159 /** 160 * Create a listening socket on a given port. 161 * 162 * XXX - Give the client author the responsibility of setting up a 163 * listener, then we no longer have a libfaim problem with broken 164 * solaris *innocent smile* -- jbm 165 * 166 * @param portnum The port number to bind to. 167 * @return The file descriptor of the listening socket. 907 168 */ 908 169 static int listenestablish(fu16_t portnum) … … 919 180 hints.ai_family = AF_UNSPEC; 920 181 hints.ai_socktype = SOCK_STREAM; 921 if (getaddrinfo(NULL /* any IP*/, serv, &hints, &res) != 0) {182 if (getaddrinfo(NULL /* any IP */, serv, &hints, &res) != 0) { 922 183 perror("getaddrinfo"); 923 184 return -1; … … 930 191 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 931 192 if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0) 932 break; 933 /* success */ 193 break; /* success */ 934 194 close(listenfd); 935 195 } while ( (res = res->ai_next) ); … … 938 198 return -1; 939 199 940 if (listen(listenfd, 1024)!=0) {941 perror("listen");942 return -1;943 }944 945 fcntl(listenfd, F_SETFL, O_NONBLOCK);946 947 200 freeaddrinfo(ressave); 948 return listenfd;949 201 #else 950 202 int listenfd; … … 953 205 954 206 if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 955 perror("socket (listenfd)");207 perror("socket"); 956 208 return -1; 957 209 } 958 210 959 211 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) != 0) { 960 perror("setsockopt (listenfd)");212 perror("setsockopt"); 961 213 close(listenfd); 962 214 return -1; 963 } 215 } 964 216 965 217 memset(&sockin, 0, sizeof(struct sockaddr_in)); … … 968 220 969 221 if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) { 970 perror("bind (listenfd)");222 perror("bind"); 971 223 close(listenfd); 972 224 return -1; 973 225 } 226 #endif 227 974 228 if (listen(listenfd, 4) != 0) { 975 perror("listen (listenfd)");229 perror("listen"); 976 230 close(listenfd); 977 231 return -1; 978 232 } 979 233 fcntl(listenfd, F_SETFL, O_NONBLOCK); 234 980 235 return listenfd; 236 } 237 238 /** 239 * After establishing a listening socket, this is called to accept a connection. It 240 * clones the conn used by the listener, and passes both of these to a signal handler. 241 * The signal handler should close the listener conn and keep track of the new conn, 242 * since this is what is used for file transfers and what not. 243 * 244 * @param sess The session. 245 * @param cur The conn the incoming connection is on. 246 * @return Return 0 if no errors, otherwise return the error number. 247 */ 248 faim_export int aim_handlerendconnect(aim_session_t *sess, aim_conn_t *cur) 249 { 250 int acceptfd = 0; 251 struct sockaddr addr; 252 socklen_t addrlen = sizeof(addr); 253 int ret = 0; 254 aim_conn_t *newconn; 255 char ip[20]; 256 int port; 257 258 if ((acceptfd = accept(cur->fd, &addr, &addrlen)) == -1) 259 return 0; /* not an error */ 260 261 if (addr.sa_family != AF_INET) { /* just in case IPv6 really is happening */ 262 close(acceptfd); 263 aim_conn_close(cur); 264 return -1; 265 } 266 267 strncpy(ip, inet_ntoa(((struct sockaddr_in *)&addr)->sin_addr), sizeof(ip)); 268 port = ntohs(((struct sockaddr_in *)&addr)->sin_port); 269 270 if (!(newconn = aim_cloneconn(sess, cur))) { 271 close(acceptfd); 272 aim_conn_close(cur); 273 return -ENOMEM; 274 } 275 276 newconn->type = AIM_CONN_TYPE_RENDEZVOUS; 277 newconn->fd = acceptfd; 278 279 if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) { 280 aim_rxcallback_t userfunc; 281 struct aim_odc_intdata *priv; 282 283 priv = (struct aim_odc_intdata *)(newconn->internal = cur->internal); 284 cur->internal = NULL; 285 snprintf(priv->ip, sizeof(priv->ip), "%s:%u", ip, port); 286 287 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIM_ESTABLISHED))) 288 ret = userfunc(sess, NULL, newconn, cur); 289 290 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) { 291 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) { 292 aim_rxcallback_t userfunc; 293 294 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_ESTABLISHED))) 295 ret = userfunc(sess, NULL, newconn, cur); 296 297 } else { 298 faimdprintf(sess, 1,"Got a connection on a listener that's not rendezvous. Closing connection.\n"); 299 aim_conn_close(newconn); 300 ret = -1; 301 } 302 303 return ret; 304 } 305 306 /** 307 * Send client-to-client typing notification over an established direct connection. 308 * 309 * @param sess The session. 310 * @param conn The already-connected ODC connection. 311 * @param typing If 0x0002, sends a "typing" message, 0x0001 sends "typed," and 312 * 0x0000 sends "stopped." 313 * @return Return 0 if no errors, otherwise return the error number. 314 */ 315 faim_export int aim_odc_send_typing(aim_session_t *sess, aim_conn_t *conn, int typing) 316 { 317 struct aim_odc_intdata *intdata = (struct aim_odc_intdata *)conn->internal; 318 aim_frame_t *fr; 319 aim_bstream_t *hdrbs; 320 fu8_t *hdr; 321 int hdrlen = 0x44; 322 323 if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS)) 324 return -EINVAL; 325 326 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0001, 0))) 327 return -ENOMEM; 328 memcpy(fr->hdr.rend.magic, "ODC2", 4); 329 fr->hdr.rend.hdrlen = hdrlen; 330 331 if (!(hdr = calloc(1, hdrlen))) { 332 aim_frame_destroy(fr); 333 return -ENOMEM; 334 } 335 336 hdrbs = &(fr->data); 337 aim_bstream_init(hdrbs, hdr, hdrlen); 338 339 aimbs_put16(hdrbs, 0x0006); 340 aimbs_put16(hdrbs, 0x0000); 341 aimbs_putraw(hdrbs, intdata->cookie, 8); 342 aimbs_put16(hdrbs, 0x0000); 343 aimbs_put16(hdrbs, 0x0000); 344 aimbs_put16(hdrbs, 0x0000); 345 aimbs_put16(hdrbs, 0x0000); 346 aimbs_put32(hdrbs, 0x00000000); 347 aimbs_put16(hdrbs, 0x0000); 348 aimbs_put16(hdrbs, 0x0000); 349 aimbs_put16(hdrbs, 0x0000); 350 351 if (typing == 0x0002) 352 aimbs_put16(hdrbs, 0x0002 | 0x0008); 353 else if (typing == 0x0001) 354 aimbs_put16(hdrbs, 0x0002 | 0x0004); 355 else 356 aimbs_put16(hdrbs, 0x0002); 357 358 aimbs_put16(hdrbs, 0x0000); 359 aimbs_put16(hdrbs, 0x0000); 360 aimbs_putraw(hdrbs, sess->sn, strlen(sess->sn)); 361 362 aim_bstream_setpos(hdrbs, 52); /* bleeehh */ 363 364 aimbs_put8(hdrbs, 0x00); 365 aimbs_put16(hdrbs, 0x0000); 366 aimbs_put16(hdrbs, 0x0000); 367 aimbs_put16(hdrbs, 0x0000); 368 aimbs_put16(hdrbs, 0x0000); 369 aimbs_put16(hdrbs, 0x0000); 370 aimbs_put16(hdrbs, 0x0000); 371 aimbs_put16(hdrbs, 0x0000); 372 aimbs_put8(hdrbs, 0x00); 373 374 /* end of hdr */ 375 376 aim_tx_enqueue(sess, fr); 377 378 return 0; 379 } 380 381 /** 382 * Send client-to-client IM over an established direct connection. 383 * Call this just like you would aim_send_im, to send a directim. 384 * 385 * @param sess The session. 386 * @param conn The already-connected ODC connection. 387 * @param msg Null-terminated string to send. 388 * @param len The length of the message to send, including binary data. 389 * @param encoding 0 for ascii, 2 for Unicode, 3 for ISO 8859-1. 390 * @param isawaymsg 0 if this is not an auto-response, 1 if it is. 391 * @return Return 0 if no errors, otherwise return the error number. 392 */ 393 faim_export int aim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *msg, int len, int encoding, int isawaymsg) 394 { 395 aim_frame_t *fr; 396 aim_bstream_t *hdrbs; 397 struct aim_odc_intdata *intdata = (struct aim_odc_intdata *)conn->internal; 398 int hdrlen = 0x44; 399 fu8_t *hdr; 400 401 if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS) || !msg) 402 return -EINVAL; 403 404 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x01, 0))) 405 return -ENOMEM; 406 407 memcpy(fr->hdr.rend.magic, "ODC2", 4); 408 fr->hdr.rend.hdrlen = hdrlen; 409 410 if (!(hdr = calloc(1, hdrlen + len))) { 411 aim_frame_destroy(fr); 412 return -ENOMEM; 413 } 414 415 hdrbs = &(fr->data); 416 aim_bstream_init(hdrbs, hdr, hdrlen + len); 417 418 aimbs_put16(hdrbs, 0x0006); 419 aimbs_put16(hdrbs, 0x0000); 420 aimbs_putraw(hdrbs, intdata->cookie, 8); 421 aimbs_put16(hdrbs, 0x0000); 422 aimbs_put16(hdrbs, 0x0000); 423 aimbs_put16(hdrbs, 0x0000); 424 aimbs_put16(hdrbs, 0x0000); 425 aimbs_put32(hdrbs, len); 426 aimbs_put16(hdrbs, encoding); 427 aimbs_put16(hdrbs, 0x0000); 428 aimbs_put16(hdrbs, 0x0000); 429 430 /* flags - used for typing notification and to mark if this is an away message */ 431 aimbs_put16(hdrbs, 0x0000 | isawaymsg); 432 433 aimbs_put16(hdrbs, 0x0000); 434 aimbs_put16(hdrbs, 0x0000); 435 aimbs_putraw(hdrbs, sess->sn, strlen(sess->sn)); 436 437 aim_bstream_setpos(hdrbs, 52); /* bleeehh */ 438 439 aimbs_put8(hdrbs, 0x00); 440 aimbs_put16(hdrbs, 0x0000); 441 aimbs_put16(hdrbs, 0x0000); 442 aimbs_put16(hdrbs, 0x0000); 443 aimbs_put16(hdrbs, 0x0000); 444 aimbs_put16(hdrbs, 0x0000); 445 aimbs_put16(hdrbs, 0x0000); 446 aimbs_put16(hdrbs, 0x0000); 447 aimbs_put8(hdrbs, 0x00); 448 449 /* end of hdr2 */ 450 451 #if 0 /* XXX - this is how you send buddy icon info... */ 452 aimbs_put16(hdrbs, 0x0008); 453 aimbs_put16(hdrbs, 0x000c); 454 aimbs_put16(hdrbs, 0x0000); 455 aimbs_put16(hdrbs, 0x1466); 456 aimbs_put16(hdrbs, 0x0001); 457 aimbs_put16(hdrbs, 0x2e0f); 458 aimbs_put16(hdrbs, 0x393e); 459 aimbs_put16(hdrbs, 0xcac8); 981 460 #endif 982 } 983 984 static int getcommand_getfile(aim_session_t *sess, aim_conn_t *conn) 985 { 986 #if 0 987 struct aim_filetransfer_priv *ft; 988 aim_rxcallback_t userfunc; 989 990 ft = conn->priv; 991 if (ft->state == 2) { 992 /* waiting on listing data */ 993 int ret = 0; 994 char *listing; 995 aim_frame_t *newoft; 996 997 if (!(listing = malloc(ft->fh.size))) 998 return -1; 999 1000 ft->state = 0; 1001 if (aim_recv(conn->fd, listing, ft->fh.size) != ft->fh.size) 1002 faimdprintf(sess, 2, "OFT get: file %s was short. (0x%lx)\n", ft->fh.name, ft->fh.size); 1003 1004 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x120b, 0))) { 1005 faimdprintf(sess, 2, "faim: aim_get_command_rendezvous: getfile listing: tx_new OFT failed\n"); 1006 free(listing); 1007 aim_conn_close(conn); 1008 return -1; 461 aimbs_putraw(hdrbs, msg, len); 462 463 aim_tx_enqueue(sess, fr); 464 465 return 0; 466 } 467 468 /** 469 * Get the screen name of the peer of a direct connection. 470 * 471 * @param conn The ODC connection. 472 * @return The screen name of the dude, or NULL if there was an anomaly. 473 */ 474 faim_export const char *aim_odc_getsn(aim_conn_t *conn) 475 { 476 struct aim_odc_intdata *intdata; 477 478 if (!conn || !conn->internal) 479 return NULL; 480 481 if ((conn->type != AIM_CONN_TYPE_RENDEZVOUS) || 482 (conn->subtype != AIM_CONN_SUBTYPE_OFT_DIRECTIM)) 483 return NULL; 484 485 intdata = (struct aim_odc_intdata *)conn->internal; 486 487 return intdata->sn; 488 } 489 490 /** 491 * Find the conn of a direct connection with the given buddy. 492 * 493 * @param sess The session. 494 * @param sn The screen name of the buddy whose direct connection you want to find. 495 * @return The conn for the direct connection with the given buddy, or NULL if no 496 * connection was found. 497 */ 498 faim_export aim_conn_t *aim_odc_getconn(aim_session_t *sess, const char *sn) 499 { 500 aim_conn_t *cur; 501 struct aim_odc_intdata *intdata; 502 503 if (!sess || !sn || !strlen(sn)) 504 return NULL; 505 506 for (cur = sess->connlist; cur; cur = cur->next) { 507 if ((cur->type == AIM_CONN_TYPE_RENDEZVOUS) && (cur->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)) { 508 intdata = cur->internal; 509 if (!aim_sncmp(intdata->sn, sn)) 510 return cur; 1009 511 } 1010 1011 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 1012 newoft->hdr.oft.hdr2len = 0x100 - 8; 1013 1014 /* Protocol BS - set nrecvd to size of listing, recvcsum to listing checksum, flags to 0 */ 1015 1016 ft->fh.nrecvd = ft->fh.size; 1017 ft->fh.recvcsum = ft->fh.checksum; 1018 ft->fh.flags = 0; 1019 1020 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { 1021 aim_frame_destroy(newoft); 1022 free(listing); 1023 return -1; 1024 } 1025 1026 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) 1027 faimdprintf(sess, 2, "eek! bh fail listing\n"); 1028 1029 /* send the 120b */ 1030 aim_tx_enqueue(sess, newoft); 1031 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTING)) ) 1032 ret = userfunc(sess, NULL, conn, ft, listing); 1033 1034 free(listing); 1035 return ret; 1036 } 1037 1038 if (ft->state == 3) { 1039 /* waiting on file data */ 1040 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILERECEIVE)) ) 1041 return userfunc(sess, NULL, conn, ft->fh.name, 1042 ft->fh.size); 1043 return 0; 1044 } 1045 1046 if (ft->state == 4) { 1047 if( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILESTATE4)) ) 1048 return userfunc(sess, NULL, conn); 1049 aim_conn_close(conn); 1050 return 0; 1051 } 1052 1053 return 0; 1054 #else 1055 return -1; 1056 #endif 1057 } 1058 1059 static void connclose_sendfile(aim_session_t *sess, aim_conn_t *conn) 1060 { 1061 aim_msgcookie_t *cook; 1062 struct aim_filetransfer_priv *priv = (struct aim_filetransfer_priv *)conn->internal; 1063 1064 cook = aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTSEND); 1065 aim_cookie_free(sess, cook); 1066 1067 return; 1068 } 1069 1070 static void connkill_sendfile(aim_session_t *sess, aim_conn_t *conn) 1071 { 1072 free(conn->internal); 1073 1074 return; 1075 } 1076 1077 static void connclose_getfile(aim_session_t *sess, aim_conn_t *conn) 1078 { 1079 #if 0 1080 aim_msgcookie_t *cook; 1081 struct aim_filetransfer_priv *priv = (struct aim_filetransfer_priv *)conn->priv; 1082 1083 cook = aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTGET); 1084 aim_cookie_free(sess, cook); 1085 #endif 1086 return; 1087 } 1088 1089 static void connkill_getfile(aim_session_t *sess, aim_conn_t *conn) 1090 { 1091 1092 free(conn->internal); 1093 1094 return; 1095 } 1096 1097 static void connclose_directim(aim_session_t *sess, aim_conn_t *conn) 1098 { 1099 struct aim_directim_intdata *intdata = (struct aim_directim_intdata *)conn->internal; 1100 aim_msgcookie_t *cook; 1101 1102 cook = aim_uncachecookie(sess, intdata->cookie, AIM_COOKIETYPE_OFTIM); 1103 aim_cookie_free(sess, cook); 1104 1105 return; 1106 } 1107 1108 static void connkill_directim(aim_session_t *sess, aim_conn_t *conn) 1109 { 1110 1111 free(conn->internal); 1112 1113 return; 1114 } 1115 1116 faim_internal void aim_conn_close_rend(aim_session_t *sess, aim_conn_t *conn) 1117 { 1118 1119 if (conn->type != AIM_CONN_TYPE_RENDEZVOUS) 1120 return; 1121 1122 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) 1123 connclose_sendfile(sess, conn); 1124 else if (conn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) 1125 connclose_getfile(sess, conn); 1126 else if (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) 1127 connclose_directim(sess, conn); 1128 1129 return; 1130 } 1131 1132 faim_internal void aim_conn_kill_rend(aim_session_t *sess, aim_conn_t *conn) 1133 { 1134 1135 if (conn->type != AIM_CONN_TYPE_RENDEZVOUS) 1136 return; 1137 1138 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) 1139 connkill_sendfile(sess, conn); 1140 else if (conn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) 1141 connkill_getfile(sess, conn); 1142 else if (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) 1143 connkill_directim(sess, conn); 1144 1145 return; 1146 } 1147 1148 static int handlehdr_directim(aim_session_t *sess, aim_conn_t *conn, aim_bstream_t *bs) 512 } 513 514 return NULL; 515 } 516 517 /** 518 * For those times when we want to open up the direct connection channel ourselves. 519 * 520 * You'll want to set up some kind of watcher on this socket. 521 * When the state changes, call aim_handlerendconnection with 522 * the connection returned by this. aim_handlerendconnection 523 * will accept the pending connection and stop listening. 524 * 525 * @param sess The session 526 * @param sn The screen name to connect to. 527 * @return The new connection. 528 */ 529 faim_export aim_conn_t *aim_odc_initiate(aim_session_t *sess, const char *sn) 530 { 531 aim_conn_t *newconn; 532 aim_msgcookie_t *cookie; 533 struct aim_odc_intdata *priv; 534 int listenfd; 535 fu16_t port = 4443; 536 fu8_t localip[4]; 537 fu8_t ck[8]; 538 539 if (aim_util_getlocalip(localip) == -1) 540 return NULL; 541 542 if ((listenfd = listenestablish(port)) == -1) 543 return NULL; 544 545 aim_im_sendch2_odcrequest(sess, ck, sn, localip, port); 546 547 cookie = (aim_msgcookie_t *)calloc(1, sizeof(aim_msgcookie_t)); 548 memcpy(cookie->cookie, ck, 8); 549 cookie->type = AIM_COOKIETYPE_OFTIM; 550 551 /* this one is for the cookie */ 552 priv = (struct aim_odc_intdata *)calloc(1, sizeof(struct aim_odc_intdata)); 553 554 memcpy(priv->cookie, ck, 8); 555 strncpy(priv->sn, sn, sizeof(priv->sn)); 556 cookie->data = priv; 557 aim_cachecookie(sess, cookie); 558 559 /* XXX - switch to aim_cloneconn()? */ 560 if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_LISTENER, NULL))) { 561 close(listenfd); 562 return NULL; 563 } 564 565 /* this one is for the conn */ 566 priv = (struct aim_odc_intdata *)calloc(1, sizeof(struct aim_odc_intdata)); 567 568 memcpy(priv->cookie, ck, 8); 569 strncpy(priv->sn, sn, sizeof(priv->sn)); 570 571 newconn->fd = listenfd; 572 newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM; 573 newconn->internal = priv; 574 newconn->lastactivity = time(NULL); 575 576 return newconn; 577 } 578 579 /** 580 * Connect directly to the given buddy for directim. 581 * 582 * This is a wrapper for aim_newconn. 583 * 584 * If addr is NULL, the socket is not created, but the connection is 585 * allocated and setup to connect. 586 * 587 * @param sess The Godly session. 588 * @param sn The screen name we're connecting to. I hope it's a girl... 589 * @param addr Address to connect to. 590 * @return The new connection. 591 */ 592 faim_export aim_conn_t *aim_odc_connect(aim_session_t *sess, const char *sn, const char *addr, const fu8_t *cookie) 593 { 594 aim_conn_t *newconn; 595 struct aim_odc_intdata *intdata; 596 597 if (!sess || !sn) 598 return NULL; 599 600 if (!(intdata = calloc(1, sizeof(struct aim_odc_intdata)))) 601 return NULL; 602 memcpy(intdata->cookie, cookie, 8); 603 strncpy(intdata->sn, sn, sizeof(intdata->sn)); 604 if (addr) 605 strncpy(intdata->ip, addr, sizeof(intdata->ip)); 606 607 /* XXX - verify that non-blocking connects actually work */ 608 if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, addr))) { 609 free(intdata); 610 return NULL; 611 } 612 613 newconn->internal = intdata; 614 newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM; 615 616 return newconn; 617 } 618 619 /** 620 * Sometimes you just don't know with these kinds of people. 621 * 622 * @param sess The session. 623 * @param conn The ODC connection of the incoming data. 624 * @param frr The frame allocated for the incoming data. 625 * @param bs It stands for "bologna sandwich." 626 * @return Return 0 if no errors, otherwise return the error number. 627 */ 628 static int handlehdr_odc(aim_session_t *sess, aim_conn_t *conn, aim_frame_t *frr, aim_bstream_t *bs) 1149 629 { 1150 630 aim_frame_t fr; 631 int ret = 0; 1151 632 aim_rxcallback_t userfunc; 1152 633 fu32_t payloadlength; … … 1156 637 fr.conn = conn; 1157 638 1158 /* XXXugly */639 /* AAA - ugly */ 1159 640 aim_bstream_setpos(bs, 20); 1160 641 payloadlength = aimbs_get32(bs); … … 1167 648 1168 649 aim_bstream_setpos(bs, 36); 1169 /* XXX -create an aimbs_getnullstr function? */ 1170 snptr = aimbs_getstr(bs, MAXSNLEN); 1171 1172 faimdprintf(sess, 2, "faim: OFT frame: handlehdr_directim: %04x / %04x / %s\n", payloadlength, flags, snptr); 1173 1174 if (flags & 0x0002) { 1175 int ret = 0; 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 650 /* XXX - create an aimbs_getnullstr function? */ 651 snptr = aimbs_getstr(bs, 32); /* Next 32 bytes contain the sn, padded with null chars */ 652 653 faimdprintf(sess, 2, "faim: OFT frame: handlehdr_odc: %04x / %04x / %s\n", payloadlength, flags, snptr); 654 655 if (flags & 0x0008) { 656 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING))) 657 ret = userfunc(sess, &fr, snptr, 2); 658 } else if (flags & 0x0004) { 659 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING))) 660 ret = userfunc(sess, &fr, snptr, 1); 661 } else { 1183 662 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING))) 1184 663 ret = userfunc(sess, &fr, snptr, 0); 1185 1186 return ret; 1187 1188 } else if (((flags & 0x000f) == 0x0000) && payloadlength) { 1189 char *msg, *msg2; 1190 int ret = 0; 664 } 665 666 if (payloadlength) { 667 char *msg; 1191 668 int recvd = 0; 1192 int i; 1193 1194 if (!(msg = calloc(1, payloadlength+1))) 1195 return -1; 1196 msg2 = msg; 1197 669 int i, isawaymsg; 670 671 isawaymsg = flags & 0x0001; 672 673 if (!(msg = calloc(1, payloadlength+1))) { 674 free(snptr); 675 return -ENOMEM; 676 } 677 1198 678 while (payloadlength - recvd) { 1199 679 if (payloadlength - recvd >= 1024) 1200 i = aim_recv(conn->fd, msg2, 1024);680 i = aim_recv(conn->fd, &msg[recvd], 1024); 1201 681 else 1202 i = aim_recv(conn->fd, msg2, payloadlength - recvd);682 i = aim_recv(conn->fd, &msg[recvd], payloadlength - recvd); 1203 683 if (i <= 0) { 1204 684 free(msg); 685 free(snptr); 1205 686 return -1; 1206 687 } 1207 688 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); 689 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER))) 690 ret = userfunc(sess, &fr, snptr, (double)recvd / payloadlength); 1211 691 } 1212 692 1213 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING)))1214 ret = userfunc(sess, &fr, snptr, msg, payloadlength, encoding );693 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING))) 694 ret = userfunc(sess, &fr, snptr, msg, payloadlength, encoding, isawaymsg); 1215 695 1216 696 free(msg); 1217 1218 return ret; 1219 } 697 } 698 699 free(snptr); 700 701 return ret; 702 } 703 704 faim_export struct aim_oft_info *aim_oft_createinfo(aim_session_t *sess, const fu8_t *cookie, const char *sn, const char *ip, fu16_t port, fu32_t size, fu32_t modtime, char *filename) 705 { 706 struct aim_oft_info *new; 707 708 if (!sess) 709 return NULL; 710 711 if (!(new = (struct aim_oft_info *)calloc(1, sizeof(struct aim_oft_info)))) 712 return NULL; 713 714 new->sess = sess; 715 if (cookie) 716 memcpy(new->cookie, cookie, 8); 717 if (ip) 718 new->clientip = strdup(ip); 719 if (sn) 720 new->sn = strdup(sn); 721 new->port = port; 722 new->fh.totfiles = 1; 723 new->fh.filesleft = 1; 724 new->fh.totparts = 1; 725 new->fh.partsleft = 1; 726 new->fh.totsize = size; 727 new->fh.size = size; 728 new->fh.modtime = modtime; 729 new->fh.checksum = 0xffff0000; 730 new->fh.rfrcsum = 0xffff0000; 731 new->fh.rfcsum = 0xffff0000; 732 new->fh.recvcsum = 0xffff0000; 733 strncpy(new->fh.idstring, "OFT_Windows ICBMFT V1.1 32", 31); 734 if (filename) 735 strncpy(new->fh.name, filename, 63); 736 737 new->next = sess->oft_info; 738 sess->oft_info = new; 739 740 return new; 741 } 742 743 /** 744 * Remove the given oft_info struct from the oft_info linked list, and 745 * then free its memory. 746 * 747 * @param sess The session. 748 * @param oft_info The aim_oft_info struct that we're destroying. 749 * @return Return 0 if no errors, otherwise return the error number. 750 */ 751 faim_export int aim_oft_destroyinfo(struct aim_oft_info *oft_info) 752 { 753 aim_session_t *sess; 754 755 if (!oft_info || !(sess = oft_info->sess)) 756 return -EINVAL; 757 758 if (sess->oft_info && (sess->oft_info == oft_info)) { 759 sess->oft_info = sess->oft_info->next; 760 } else { 761 struct aim_oft_info *cur; 762 for (cur=sess->oft_info; (cur->next && (cur->next!=oft_info)); cur=cur->next); 763 if (cur->next) 764 cur->next = cur->next->next; 765 } 766 767 free(oft_info->sn); 768 free(oft_info->proxyip); 769 free(oft_info->clientip); 770 free(oft_info->verifiedip); 771 free(oft_info); 1220 772 1221 773 return 0; 1222 774 } 1223 775 1224 static int handlehdr_getfile_listing(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) 1225 { 1226 #if 0 1227 struct aim_filetransfer_priv *ft; 1228 struct aim_fileheader_t *fh; 1229 struct aim_msgcookie_t *cook; 1230 aim_frame_t *newoft; 1231 aim_rxcallback_t userfunc; 1232 1233 faimdprintf(sess, 2,"faim: rend: fileget 0x1108\n"); 1234 fh = aim_oft_getfh(hdr); 1235 1236 faim_mutex_unlock(&conn->active); 1237 1238 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { 1239 free(fh); 1240 return -1; 1241 } 1242 1243 ft = cook->data; 1244 1245 /* we're waaaaiiiting.. for listing.txt */ 1246 ft->state = 2; 1247 1248 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t)); 1249 free(fh); 1250 1251 if(aim_cachecookie(sess, cook) == -1) { 1252 faimdprintf(sess, 1, "error caching cookie\n"); 1253 return -1; 1254 } 1255 1256 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x1209, 0))) { 1257 aim_conn_close(conn); 1258 return -1; 1259 } 1260 1261 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 1262 newoft->hdr.oft.hdr2len = 0x100 - 8; 1263 1264 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { 1265 newoft->lock = 0; 1266 aim_frame_destroy(newoft); 1267 return -1; 1268 } 1269 1270 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) { 1271 newoft->lock = 0; 1272 aim_frame_destroy(newoft); 1273 return -1; 1274 } 1275 1276 newoft->lock = 0; 1277 aim_tx_enqueue(sess, newoft); 1278 #endif 1279 return -1; 1280 } 1281 1282 static int handlehdr_getfile_listing2(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) 1283 { 1284 #if 0 1285 struct aim_filetransfer_priv *ft; 1286 struct aim_fileheader_t *fh; 1287 struct aim_msgcookie_t *cook; 1288 int ret = 0; 1289 aim_rxcallback_t userfunc; 1290 1291 fh = aim_oft_getfh(hdr); 1292 1293 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) 1294 faimdprintf(sess, 2, "shit, no cookie in 0x1209. (%i/%s)going to crash..\n", AIM_COOKIETYPE_OFTGET, fh->bcookie); 1295 1296 ft = cook->data; 1297 1298 if (ft->fh.size != fh->size) 1299 faimdprintf(sess, 2, "hrm. ft->fh.size (%ld) != fh->size (%ld). um. using ft->fh.size\n", ft->fh.size, fh->size); 1300 1301 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGREQ))) 1302 ret = userfunc(sess, NULL, conn, fh); 1303 1304 faimdprintf(sess, 2, "faim: get_command_rendezvous: hit end of 1209\n"); 1305 1306 free(fh); 1307 1308 return ret; 1309 #else 1310 return -1; 1311 #endif 1312 } 1313 1314 static int handlehdr_getfile_listing3(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) 1315 { 1316 #if 0 1317 struct aim_filetransfer_priv *ft; 1318 struct aim_msgcookie_t *cook; 1319 struct aim_fileheader_t *fh; 1320 aim_rxcallback_t userfunc; 1321 1322 fh = aim_oft_getfh(hdr); 1323 1324 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { 1325 free(fh); 1326 return -1; 1327 } 1328 1329 free(fh); 1330 1331 ft = cook->data; 1332 1333 if (aim_cachecookie(sess, cook) == -1) 1334 return -1; 1335 1336 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGRXCONFIRM))) 1337 return userfunc(sess, NULL, conn); 1338 #endif 1339 return -1; 1340 } 1341 1342 static int handlehdr_getfile_request(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) 1343 { 1344 #if 0 1345 struct aim_filetransfer_priv *ft; 1346 aim_msgcookie_t *cook; 1347 struct aim_fileheader_t *fh; 1348 aim_frame_t *newoft; 1349 int i = 0; 1350 aim_rxcallback_t userfunc; 1351 1352 fh = aim_oft_getfh(hdr); 1353 1354 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { 1355 free(fh); 1356 return -1; 1357 } 1358 1359 ft = cook->data; 1360 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t)); 1361 free(fh); 1362 1363 aim_cachecookie(sess, cook); 1364 1365 faimdprintf(sess, 2, "faim: fileget: %s seems to want %s\n", ft->sn, ft->fh.name); 1366 1367 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ)) ) 1368 i = userfunc(sess, NULL, conn, &(ft->fh), cook->cookie); 1369 1370 if (i < 0) 1371 return i; 1372 1373 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0101, 0))) { 1374 faimdprintf(sess, 2, "faim: send_final_transfer: tx_new OFT failed\n"); 1375 return -1; 1376 } 1377 1378 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 1379 newoft->hdr.oft.hdr2len = 0x100 - 8; 1380 1381 if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) { 1382 aim_frame_destroy(newoft); 1383 return -1; 1384 } 1385 1386 /* protocol BS: nrecvd, recvcsum to 0, flags to 0x20. */ 1387 ft->fh.nrecvd = 0; 1388 ft->fh.recvcsum = 0; 1389 ft->fh.flags = 0x20; 1390 1391 aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)); 1392 1393 aim_tx_enqueue(sess, newoft); 1394 1395 faimdprintf(sess, 2, "faim: OFT: OFT file header enqueued.\n"); 1396 1397 return i; 1398 #else 1399 return -1; 1400 #endif 1401 } 1402 1403 static int handlehdr_getfile_sending(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) 1404 { 1405 #if 0 1406 struct aim_fileheader_t *fh; 1407 struct aim_filetransfer_priv *ft; 1408 struct aim_msgcookie_t *cook; 1409 struct command_tx_struct *newoft; 1410 aim_rxcallback_t userfunc; 1411 1412 fh = aim_oft_getfh(hdr); 1413 1414 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { 1415 free(fh); 1416 return -1; 1417 } 1418 1419 free(fh); 1420 1421 ft = cook->data; 1422 1423 ft->state = 3; 1424 1425 if (aim_cachecookie(sess, cook) == -1) 1426 return -1; 1427 1428 faimdprintf(sess, 2, "faim: fileget: %s seems to want to send %s\n", ft->sn, ft->fh.name); 1429 1430 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0202, 0))) { 1431 faimdprintf(sess, 2, "faim: send_final_transfer: tx_new OFT failed\n"); 1432 return -1; 1433 } 1434 1435 newoft->lock = 1; 1436 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 1437 1438 newoft->hdr.oft.hdr2len = 0x100 - 8; 1439 1440 if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) { 1441 aim_frame_destroy(newoft); 1442 return -1; 1443 } 1444 1445 aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)); 1446 1447 newoft->lock = 0; 1448 aim_tx_enqueue(sess, newoft); 1449 1450 faimdprintf(sess, 2, "faim: OFT: OFT 0x0202 enqueued.\n"); 1451 1452 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ)) == NULL) 776 /** 777 * Creates a listener socket so the other dude can connect to us. 778 * 779 * You'll want to set up some kind of watcher on this socket. 780 * When the state changes, call aim_handlerendconnection with 781 * the connection returned by this. aim_handlerendconnection 782 * will accept the pending connection and stop listening. 783 * 784 * @param sess The session. 785 * @param oft_info File transfer information associated with this 786 * connection. 787 * @return Return 0 if no errors, otherwise return the error number. 788 */ 789 faim_export int aim_sendfile_listen(aim_session_t *sess, struct aim_oft_info *oft_info) 790 { 791 int listenfd; 792 793 if (!oft_info) 794 return -EINVAL; 795 796 if ((listenfd = listenestablish(oft_info->port)) == -1) 1453 797 return 1; 1454 #else 1455 return -1; 1456 #endif 1457 } 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); 798 799 if (!(oft_info->conn = aim_newconn(sess, AIM_CONN_TYPE_LISTENER, NULL))) { 800 close(listenfd); 801 return -ENOMEM; 802 } 803 804 oft_info->conn->fd = listenfd; 805 oft_info->conn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE; 806 oft_info->conn->lastactivity = time(NULL); 1548 807 1549 808 return 0; 1550 809 } 1551 810 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 1577 static int handlehdr_getfile_recv(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) 1578 { 1579 #if 0 1580 struct aim_fileheader_t *fh; 1581 struct aim_msgcookie_t *cook; 1582 int ret = 1; 1583 aim_rxcallback_t userfunc; 1584 struct aim_filetransfer_priv *ft; 1585 1586 fh = aim_oft_getfh(hdr); 1587 1588 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { 1589 free(fh); 1590 return -1; 1591 } 1592 1593 ft = cook->data; 1594 1595 faimdprintf(sess, 2, "faim: get_rend: looks like we're ready to send data.(oft 0x0202)\n"); 1596 1597 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND)) ) 1598 ret = userfunc(sess, NULL, conn, fh); 1599 1600 free(fh); 1601 1602 return ret; 1603 #else 1604 return -1; 1605 #endif 1606 } 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 1631 static int handlehdr_getfile_finish(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) 1632 { 1633 #if 0 1634 struct aim_fileheader_t *fh; 1635 aim_rxcallback_t userfunc; 1636 1637 fh = aim_oft_getfh(hdr); 1638 1639 faimdprintf(sess, 2, "faim: get_rend: looks like we're done with a transfer (oft 0x0204)\n"); 1640 1641 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE)) ) 1642 userfunc(sess, NULL, conn, fh); 1643 1644 free(fh); 1645 #endif 1646 1647 return -1; 1648 } 1649 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; 1654 int ret = -1; 1655 1656 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) { 1657 /* This should never happen. -- wtm */ 1658 return getcommand_getfile(sess, conn); 1659 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 } 1709 } 1710 1711 if (ret == -1) 1712 aim_conn_close(conn); 1713 1714 return ret; 1715 } 1716 1717 /** 1718 * aim_oft_getfh - extracts an &aim_fileheader_t from buffer hdr. 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) 811 /** 812 * Extract an &aim_fileheader_t from the given buffer. 813 * 814 * @param bs The should be from an incoming rendezvous packet. 815 * @return A pointer to new struct on success, or NULL on error. 816 */ 817 static struct aim_fileheader_t *aim_oft_getheader(aim_bstream_t *bs) 1725 818 { 1726 819 struct aim_fileheader_t *fh; … … 1755 848 fh->nencode = aimbs_get16(bs); 1756 849 fh->nlanguage = aimbs_get16(bs); 1757 aimbs_getrawbuf(bs, fh->name, 64); /* XXX */850 aimbs_getrawbuf(bs, fh->name, 64); /* XXX - filenames longer than 64B */ 1758 851 1759 852 return fh; … … 1761 854 1762 855 /** 1763 * aim_oft_checksum - calculate oft checksum of buffer 1764 * @buffer: buffer of data to checksum 1765 * @bufsize: size of buffer 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 1815 /** 1816 * aim_oft_buildheader - fills a buffer with network-order fh data 1817 * @bs: bstream to fill -- automatically initialized 1818 * @fh: fh to get data from 1819 * 1820 * returns -1 on error. 1821 * 856 * Fills a buffer with network-order fh data 857 * 858 * @param bs A bstream to fill -- automatically initialized 859 * @param fh A struct aim_fileheader_t to get data from. 860 * @return Return non-zero on error. 1822 861 */ 1823 862 static int aim_oft_buildheader(aim_bstream_t *bs, struct aim_fileheader_t *fh) … … 1826 865 1827 866 if (!bs || !fh) 1828 return -1; 1829 1830 1831 1832 1833 if (!(hdr = (unsigned char *)calloc(1, 0x100 - 8))) { 1834 return -1; 1835 } 867 return -EINVAL; 868 869 if (!(hdr = (unsigned char *)calloc(1, 0x100 - 8))) 870 return -ENOMEM; 871 1836 872 aim_bstream_init(bs, hdr, 0x100 - 8); 1837 1838 873 aimbs_putraw(bs, fh->bcookie, 8); 1839 874 aimbs_put16(bs, fh->encrypt); … … 1861 896 aimbs_put16(bs, fh->nencode); 1862 897 aimbs_put16(bs, fh->nlanguage); 1863 aimbs_putraw(bs, fh->name, 64); 1864 1865 /* XXX: Filenames longer than 64B */ 898 aimbs_putraw(bs, fh->name, 64); /* XXX - filenames longer than 64B */ 899 1866 900 return 0; 1867 901 } 1868 902 1869 903 /** 1870 * aim_getfile_intitiate - Request an OFT getfile session 1871 * @sess: your session, 1872 * @conn: the BOS conn, 1873 * @destsn is the SN to connect to. 1874 * 1875 * returns a new &aim_conn_t on success, %NULL on error 1876 */ 1877 faim_export aim_conn_t *aim_getfile_initiate(aim_session_t *sess, aim_conn_t *conn, const char *destsn) 1878 { 1879 return NULL; 904 * Create an OFT packet based on the given information, and send it on its merry way. 905 * 906 * @param sess The session. 907 * @param type The subtype of the OFT packet we're sending. 908 * @param oft_info The aim_oft_info struct with the connection and OFT 909 * info we're sending. 910 * @return Return 0 if no errors, otherwise return the error number. 911 */ 912 faim_export int aim_oft_sendheader(aim_session_t *sess, fu16_t type, struct aim_oft_info *oft_info) 913 { 914 aim_frame_t *fr; 915 916 if (!sess || !oft_info || !oft_info->conn || (oft_info->conn->type != AIM_CONN_TYPE_RENDEZVOUS)) 917 return -EINVAL; 918 1880 919 #if 0 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. */ 1927 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 */ 1979 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; 2018 #endif 2019 } 2020 2021 /** 2022 * aim_oft_getfile_request - request a particular file over an established getfile connection 2023 * @sess: your session 2024 * @conn: the established OFT getfile connection 2025 * @name: filename to request 2026 * @size: size of the file 2027 * 2028 * 2029 * returns -1 on error, 0 on successful enqueuing 2030 */ 2031 #if 0 2032 faim_export int aim_oft_getfile_request(aim_session_t *sess, aim_conn_t *conn, const char *name, int size) 2033 { 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 } 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 920 /* 921 * If you are receiving a file, the cookie should be null, if you are sending a 922 * file, the cookie should be the same as the one used in the ICBM negotiation 923 * SNACs. 2095 924 */ 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 #else2109 fh->checksum = 0x00000000;2110 #endif2111 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 925 fh->lnameoffset = 0x1a; 2131 926 fh->lsizeoffset = 0x10; 2132 memset(fh->dummy, 0, sizeof(fh->dummy));2133 memset(fh->macfileinfo, 0, sizeof(fh->macfileinfo));2134 927 2135 928 /* apparently 0 is ASCII, 2 is UCS-2 */ 2136 929 /* it is likely that 3 is ISO 8859-1 */ 930 /* I think "nlanguage" might be the same thing as "subenc" in im.c */ 2137 931 fh->nencode = 0x0000; 2138 932 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); 933 #endif 934 935 aim_oft_dirconvert_tostupid(oft_info->fh.name); 936 937 if (!(fr = aim_tx_new(sess, oft_info->conn, AIM_FRAMETYPE_OFT, type, 0))) 938 return -ENOMEM; 939 940 if (aim_oft_buildheader(&fr->data, &oft_info->fh) == -1) { 941 aim_frame_destroy(fr); 942 return -ENOMEM; 943 } 944 945 memcpy(fr->hdr.rend.magic, "OFT2", 4); 946 fr->hdr.rend.hdrlen = aim_bstream_curpos(&fr->data); 947 948 aim_tx_enqueue(sess, fr); 949 2174 950 return 0; 2175 951 } 2176 2177 /** 2178 * aim_oft_getfile_ack - acknowledge a getfile download as complete 2179 * @sess: your session 2180 * @conn: the getfile conn to send the ack over 2181 * 2182 * Call this function after you have read all the data in a particular 2183 * filetransfer. Returns -1 on error, 0 on apparent success 2184 * 2185 */ 2186 faim_export int aim_oft_getfile_ack(aim_session_t *sess, aim_conn_t *conn) 2187 { 2188 return -EINVAL; 2189 #if 0 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; 2223 #endif 2224 } 2225 2226 /** 2227 * aim_oft_end - end a getfile/sendfile. 2228 * @sess: your session 2229 * @conn: the getfile connection 2230 * 2231 * call this before you close the getfile connection if you're on the 2232 * receiving/requesting end. 2233 */ 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 } 952 953 /** 954 * Handle incoming data on a rendezvous connection. This is analogous to the 955 * consumesnac function in rxhandlers.c, and I really think this should probably 956 * be in rxhandlers.c as well, but I haven't finished cleaning everything up yet. 957 * 958 * @param sess The session. 959 * @param fr The frame allocated for the incoming data. 960 * @return Return 0 if the packet was handled correctly, otherwise return the 961 * error number. 962 */ 963 faim_internal int aim_rxdispatch_rendezvous(aim_session_t *sess, aim_frame_t *fr) 964 { 965 aim_conn_t *conn = fr->conn; 966 int ret = 1; 967 968 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) { 969 if (fr->hdr.rend.type == 0x0001) 970 ret = handlehdr_odc(sess, conn, fr, &fr->data); 971 else 972 faimdprintf(sess, 0, "faim: ODC directim frame unknown, type is %04x\n", fr->hdr.rend.type); 973 974 } else { 975 aim_rxcallback_t userfunc; 976 struct aim_fileheader_t *header = aim_oft_getheader(&fr->data); 977 aim_oft_dirconvert_fromstupid(header->name); /* XXX - This should be client-side */ 978 979 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, fr->hdr.rend.type))) 980 ret = userfunc(sess, fr, conn, header->bcookie, header); 981 982 free(header); 983 } 984 985 if (ret == -1) 986 aim_conn_close(conn); 987 988 return ret; 989 } -
libfaim/icq.c
r862371b re374dee 71 71 } 72 72 73 faim_export int aim_icq_hideip(aim_session_t *sess) 74 { 75 aim_conn_t *conn; 76 aim_frame_t *fr; 77 aim_snacid_t snacid; 78 int bslen; 79 80 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) 81 return -EINVAL; 82 83 bslen = 2+4+2+2+2+4; 84 85 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) 86 return -ENOMEM; 87 88 snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); 89 aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); 90 91 /* For simplicity, don't bother using a tlvlist */ 92 aimbs_put16(&fr->data, 0x0001); 93 aimbs_put16(&fr->data, bslen); 94 95 aimbs_putle16(&fr->data, bslen - 2); 96 aimbs_putle32(&fr->data, atoi(sess->sn)); 97 aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ 98 aimbs_putle16(&fr->data, snacid); /* eh. */ 99 aimbs_putle16(&fr->data, 0x0424); /* shrug. */ 100 aimbs_putle16(&fr->data, 0x0001); 101 aimbs_putle16(&fr->data, 0x0001); 102 103 aim_tx_enqueue(sess, fr); 104 105 return 0; 106 } 107 108 /** 109 * Change your ICQ password. 110 * 111 * @param sess The oscar session 112 * @param passwd The new password. If this is longer than 8 characters it 113 * will be truncated. 114 * @return Return 0 if no errors, otherwise return the error number. 115 */ 116 faim_export int aim_icq_changepasswd(aim_session_t *sess, const char *passwd) 117 { 118 aim_conn_t *conn; 119 aim_frame_t *fr; 120 aim_snacid_t snacid; 121 int bslen, passwdlen; 122 123 if (!passwd) 124 return -EINVAL; 125 126 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) 127 return -EINVAL; 128 129 passwdlen = strlen(passwd); 130 if (passwdlen > MAXICQPASSLEN) 131 passwdlen = MAXICQPASSLEN; 132 bslen = 2+4+2+2+2+2+passwdlen+1; 133 134 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) 135 return -ENOMEM; 136 137 snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); 138 aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); 139 140 /* For simplicity, don't bother using a tlvlist */ 141 aimbs_put16(&fr->data, 0x0001); 142 aimbs_put16(&fr->data, bslen); 143 144 aimbs_putle16(&fr->data, bslen - 2); 145 aimbs_putle32(&fr->data, atoi(sess->sn)); 146 aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ 147 aimbs_putle16(&fr->data, snacid); /* eh. */ 148 aimbs_putle16(&fr->data, 0x042e); /* shrug. */ 149 aimbs_putle16(&fr->data, passwdlen+1); 150 aimbs_putraw(&fr->data, passwd, passwdlen); 151 aimbs_putle8(&fr->data, '\0'); 152 153 aim_tx_enqueue(sess, fr); 154 155 return 0; 156 } 157 158 faim_export int aim_icq_getallinfo(aim_session_t *sess, const char *uin) 159 { 160 aim_conn_t *conn; 161 aim_frame_t *fr; 162 aim_snacid_t snacid; 163 int bslen; 164 struct aim_icq_info *info; 165 166 if (!uin || uin[0] < '0' || uin[0] > '9') 167 return -EINVAL; 168 169 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) 170 return -EINVAL; 171 172 bslen = 2 + 4 + 2 + 2 + 2 + 4; 173 174 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) 175 return -ENOMEM; 176 177 snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); 178 aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); 179 180 /* For simplicity, don't bother using a tlvlist */ 181 aimbs_put16(&fr->data, 0x0001); 182 aimbs_put16(&fr->data, bslen); 183 184 aimbs_putle16(&fr->data, bslen - 2); 185 aimbs_putle32(&fr->data, atoi(sess->sn)); 186 aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ 187 aimbs_putle16(&fr->data, snacid); /* eh. */ 188 aimbs_putle16(&fr->data, 0x04b2); /* shrug. */ 189 aimbs_putle32(&fr->data, atoi(uin)); 190 191 aim_tx_enqueue(sess, fr); 192 193 /* Keep track of this request and the ICQ number and request ID */ 194 info = (struct aim_icq_info *)calloc(1, sizeof(struct aim_icq_info)); 195 info->reqid = snacid; 196 info->uin = atoi(uin); 197 info->next = sess->icq_info; 198 sess->icq_info = info; 199 200 return 0; 201 } 202 203 faim_export int aim_icq_getalias(aim_session_t *sess, const char *uin) 204 { 205 aim_conn_t *conn; 206 aim_frame_t *fr; 207 aim_snacid_t snacid; 208 int bslen; 209 struct aim_icq_info *info; 210 211 if (!uin || uin[0] < '0' || uin[0] > '9') 212 return -EINVAL; 213 214 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) 215 return -EINVAL; 216 217 bslen = 2 + 4 + 2 + 2 + 2 + 4; 218 219 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) 220 return -ENOMEM; 221 222 snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); 223 aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); 224 225 /* For simplicity, don't bother using a tlvlist */ 226 aimbs_put16(&fr->data, 0x0001); 227 aimbs_put16(&fr->data, bslen); 228 229 aimbs_putle16(&fr->data, bslen - 2); 230 aimbs_putle32(&fr->data, atoi(sess->sn)); 231 aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ 232 aimbs_putle16(&fr->data, snacid); /* eh. */ 233 aimbs_putle16(&fr->data, 0x04ba); /* shrug. */ 234 aimbs_putle32(&fr->data, atoi(uin)); 235 236 aim_tx_enqueue(sess, fr); 237 238 /* Keep track of this request and the ICQ number and request ID */ 239 info = (struct aim_icq_info *)calloc(1, sizeof(struct aim_icq_info)); 240 info->reqid = snacid; 241 info->uin = atoi(uin); 242 info->next = sess->icq_info; 243 sess->icq_info = info; 244 245 return 0; 246 } 247 248 faim_export int aim_icq_getsimpleinfo(aim_session_t *sess, const char *uin) 249 { 250 aim_conn_t *conn; 251 aim_frame_t *fr; 252 aim_snacid_t snacid; 253 int bslen; 254 255 if (!uin || uin[0] < '0' || uin[0] > '9') 256 return -EINVAL; 257 258 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) 259 return -EINVAL; 260 261 bslen = 2 + 4 + 2 + 2 + 2 + 4; 262 263 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) 264 return -ENOMEM; 265 266 snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); 267 aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); 268 269 /* For simplicity, don't bother using a tlvlist */ 270 aimbs_put16(&fr->data, 0x0001); 271 aimbs_put16(&fr->data, bslen); 272 273 aimbs_putle16(&fr->data, bslen - 2); 274 aimbs_putle32(&fr->data, atoi(sess->sn)); 275 aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ 276 aimbs_putle16(&fr->data, snacid); /* eh. */ 277 aimbs_putle16(&fr->data, 0x051f); /* shrug. */ 278 aimbs_putle32(&fr->data, atoi(uin)); 279 280 aim_tx_enqueue(sess, fr); 281 282 return 0; 283 } 284 73 285 faim_export int aim_icq_sendxmlreq(aim_session_t *sess, const char *xml) 74 286 { … … 109 321 } 110 322 111 faim_export int aim_icq_getsimpleinfo(aim_session_t *sess, const char *uin) 112 { 113 aim_conn_t *conn; 114 aim_frame_t *fr; 115 aim_snacid_t snacid; 116 int bslen; 117 118 if (!uin || uin[0] < '0' || uin[0] > '9') 119 return -EINVAL; 120 121 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) 122 return -EINVAL; 123 124 bslen = 2 + 4 + 2 + 2 + 2 + 4; 125 126 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) 127 return -ENOMEM; 128 129 snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); 130 aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); 131 132 /* For simplicity, don't bother using a tlvlist */ 133 aimbs_put16(&fr->data, 0x0001); 134 aimbs_put16(&fr->data, bslen); 135 136 aimbs_putle16(&fr->data, bslen - 2); 137 aimbs_putle32(&fr->data, atoi(sess->sn)); 138 aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ 139 aimbs_putle16(&fr->data, snacid); /* eh. */ 140 aimbs_putle16(&fr->data, 0x051f); /* shrug. */ 141 aimbs_putle32(&fr->data, atoi(uin)); 142 143 aim_tx_enqueue(sess, fr); 144 145 return 0; 146 } 147 148 /* 149 * Response to 15/2, contains an ICQ packet. 323 static void aim_icq_freeinfo(struct aim_icq_info *info) { 324 int i; 325 326 if (!info) 327 return; 328 free(info->nick); 329 free(info->first); 330 free(info->last); 331 free(info->email); 332 free(info->homecity); 333 free(info->homestate); 334 free(info->homephone); 335 free(info->homefax); 336 free(info->homeaddr); 337 free(info->mobile); 338 free(info->homezip); 339 free(info->personalwebpage); 340 if (info->email2) 341 for (i = 0; i < info->numaddresses; i++) 342 free(info->email2[i]); 343 free(info->email2); 344 free(info->workcity); 345 free(info->workstate); 346 free(info->workphone); 347 free(info->workfax); 348 free(info->workaddr); 349 free(info->workzip); 350 free(info->workcompany); 351 free(info->workdivision); 352 free(info->workposition); 353 free(info->workwebpage); 354 free(info->info); 355 free(info); 356 } 357 358 /** 359 * Subtype 0x0003 - Response to 0x0015/0x002, contains an ICQesque packet. 150 360 */ 151 361 static int icqresponse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) … … 173 383