Changeset e374dee for libfaim/im.c
- 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
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libfaim/im.c
r862371b re374dee 1 1 /* 2 * Family 0x0004 - Routines for sending/receiving Instant Messages. 3 * 4 * Note the term ICBM (Inter-Client Basic Message) which blankets 5 * all types of genericly routed through-server messages. Within 6 * the ICBM types (family 4), a channel is defined. Each channel 7 * represents a different type of message. Channel 1 is used for 8 * what would commonly be called an "instant message". Channel 2 9 * is used for negotiating "rendezvous". These transactions end in 10 * something more complex happening, such as a chat invitation, or 11 * a file transfer. Channel 3 is used for chat messages (not in 12 * the same family as these channels). Channel 4 is used for 13 * various ICQ messages. Examples are normal messages, URLs, and 14 * old-style authorization. 15 * 16 * In addition to the channel, every ICBM contains a cookie. For 17 * standard IMs, these are only used for error messages. However, 18 * the more complex rendezvous messages make suitably more complex 19 * use of this field. 20 * 2 * Family 0x0004 - Routines for sending/receiving Instant Messages. 3 * 4 * Note the term ICBM (Inter-Client Basic Message) which blankets 5 * all types of genericly routed through-server messages. Within 6 * the ICBM types (family 4), a channel is defined. Each channel 7 * represents a different type of message. Channel 1 is used for 8 * what would commonly be called an "instant message". Channel 2 9 * is used for negotiating "rendezvous". These transactions end in 10 * something more complex happening, such as a chat invitation, or 11 * a file transfer. Channel 3 is used for chat messages (not in 12 * the same family as these channels). Channel 4 is used for 13 * various ICQ messages. Examples are normal messages, URLs, and 14 * old-style authorization. 15 * 16 * In addition to the channel, every ICBM contains a cookie. For 17 * standard IMs, these are only used for error messages. However, 18 * the more complex rendezvous messages make suitably more complex 19 * use of this field. 20 * 21 * TODO: Split this up into an im.c file an an icbm.c file. It 22 * will be beautiful, you'll see. 23 * 24 * Need to rename all the mpmsg messages to aim_im_bleh. 25 * 26 * Make sure aim_conn_findbygroup is used by all functions. 21 27 */ 22 28 … … 27 33 #include "win32dep.h" 28 34 #endif 35 36 /** 37 * Add a standard ICBM header to the given bstream with the given 38 * information. 39 * 40 * @param bs The bstream to write the ICBM header to. 41 * @param c c is for cookie, and cookie is for me. 42 * @param ch The ICBM channel (1 through 4). 43 * @param sn Null-terminated scrizeen nizame. 44 * @return The number of bytes written. It's really not useful. 45 */ 46 static int aim_im_puticbm(aim_bstream_t *bs, const fu8_t *c, fu16_t ch, const char *sn) 47 { 48 aimbs_putraw(bs, c, 8); 49 aimbs_put16(bs, ch); 50 aimbs_put8(bs, strlen(sn)); 51 aimbs_putraw(bs, sn, strlen(sn)); 52 return 8+2+1+strlen(sn); 53 } 29 54 30 55 /* … … 38 63 * 39 64 * Heres the current collection: 40 * 0501 0003 0101 0101 01 41 * 0501 0003 0101 0201 01 42 * 43 * 0501 0004 0101 0102 0101 44 * 0501 0003 0101 02 45 * 0501 0001 01 iChat x.x46 * 0501 0001 0101 01 AOL v6.0, CompuServe 2000 v6.0, any47 * TOC client65 * 0501 0003 0101 0101 01 AOL Mobile Communicator, WinAIM 1.0.414 66 * 0501 0003 0101 0201 01 WinAIM 2.0.847, 2.1.1187, 3.0.1464, 67 * 4.3.2229, 4.4.2286 68 * 0501 0004 0101 0102 0101 WinAIM 4.1.2010, libfaim (right here) 69 * 0501 0003 0101 02 WinAIM 5 70 * 0501 0001 01 iChat x.x, mobile buddies 71 * 0501 0001 0101 01 AOL v6.0, CompuServe 2000 v6.0, any TOC client 72 * 0501 0002 0106 WinICQ 5.45.1.3777.85 48 73 * 49 74 * Note that in this function, only the feature bytes are tested, since … … 51 76 * 52 77 */ 53 faim_export fu16_t aim_ fingerprintclient(fu8_t *msghdr, int len)78 faim_export fu16_t aim_im_fingerprint(const fu8_t *msghdr, int len) 54 79 { 55 80 static const struct { … … 91 116 } 92 117 93 /* 94 * Subtype 0x0002 118 /** 119 * Subtype 0x0002 - Set ICBM parameters. 95 120 * 96 121 * I definitly recommend sending this. If you don't, you'll be stuck 97 * with the rather unreasonable defaults. You don't want those. Send this.122 * with the rather unreasonable defaults. 98 123 * 99 124 */ 100 faim_export int aim_ seticbmparam(aim_session_t *sess, struct aim_icbmparameters *params)125 faim_export int aim_im_setparams(aim_session_t *sess, struct aim_icbmparameters *params) 101 126 { 102 127 aim_conn_t *conn; … … 131 156 } 132 157 133 /* Subtype 0x0004 - Request ICBM parameter information. */ 134 faim_export int aim_reqicbmparams(aim_session_t *sess) 158 /** 159 * Subtype 0x0004 - Request ICBM parameter information. 160 * 161 */ 162 faim_export int aim_im_reqparams(aim_session_t *sess) 135 163 { 136 164 aim_conn_t *conn; … … 142 170 } 143 171 144 /* Subtype 0x0005 */ 145 static int paraminfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 146 { 172 /** 173 * Subtype 0x0005 - Receive parameter information. 174 * 175 */ 176 static int aim_im_paraminfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 177 { 178 aim_rxcallback_t userfunc; 147 179 struct aim_icbmparameters params; 148 aim_rxcallback_t userfunc;149 180 150 181 params.maxchan = aimbs_get16(bs); … … 161 192 } 162 193 163 /* This should be endian-safe now... but who knows... */ 164 faim_export fu16_t aim_iconsum(const fu8_t *buf, int buflen) 165 { 166 fu32_t sum; 167 int i; 168 169 for (i = 0, sum = 0; i + 1 < buflen; i += 2) 170 sum += (buf[i+1] << 8) + buf[i]; 171 if (i < buflen) 172 sum += buf[i]; 173 174 sum = ((sum & 0xffff0000) >> 16) + (sum & 0x0000ffff); 175 176 return (fu16_t)sum; 177 } 178 179 /* 194 /** 180 195 * Subtype 0x0006 - Send an ICBM (instant message). 181 196 * … … 220 235 * instead of writing out the bytes manually. 221 236 * 222 * XXX more precise verification that we never send SNACs larger than 8192 223 * XXX check SNAC size for multipart 224 * 225 */ 226 faim_export int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args) 227 { 228 static const fu8_t deffeatures[] = { 229 0x01, 0x01, 0x01, 0x02 230 }; 237 * XXX - more precise verification that we never send SNACs larger than 8192 238 * XXX - check SNAC size for multipart 239 * 240 */ 241 faim_export int aim_im_sendch1_ext(aim_session_t *sess, struct aim_sendimext_args *args) 242 { 231 243 aim_conn_t *conn; 232 int i, msgtlvlen;233 244 aim_frame_t *fr; 234 245 aim_snacid_t snacid; 246 fu8_t ck[8]; 247 int i, msgtlvlen; 248 static const fu8_t deffeatures[] = { 0x01, 0x01, 0x01, 0x02 }; 235 249 236 250 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) … … 275 289 return -ENOMEM; 276 290 277 /* XXX should be optional */291 /* XXX - should be optional */ 278 292 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, args->destsn, strlen(args->destsn)+1); 279 293 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); 280 294 281 295 /* 282 * Generate a random message cookie 296 * Generate a random message cookie 283 297 * 284 298 * We could cache these like we do SNAC IDs. (In fact, it … … 289 303 */ 290 304 for (i = 0; i < 8; i++) 291 aimbs_put8(&fr->data, (fu8_t) rand()); 292 293 /* 294 * Channel ID 295 */ 296 aimbs_put16(&fr->data, 0x0001); 297 298 /* 299 * Destination SN (prepended with byte length) 300 */ 301 aimbs_put8(&fr->data, strlen(args->destsn)); 302 aimbs_putraw(&fr->data, args->destsn, strlen(args->destsn)); 303 304 /* 305 * Message TLV (type 2). 306 */ 305 ck[i] = (fu8_t)rand(); 306 307 /* ICBM header */ 308 aim_im_puticbm(&fr->data, ck, 0x0001, args->destsn); 309 310 /* Message TLV (type 0x0002) */ 307 311 aimbs_put16(&fr->data, 0x0002); 308 312 aimbs_put16(&fr->data, msgtlvlen); 309 313 310 /* 311 * Features 312 * 313 */ 314 aimbs_put8(&fr->data, 0x05); 315 aimbs_put8(&fr->data, 0x01); 316 314 /* Features TLV (type 0x0501) */ 315 aimbs_put16(&fr->data, 0x0501); 317 316 if (args->flags & AIM_IMFLAGS_CUSTOMFEATURES) { 318 317 aimbs_put16(&fr->data, args->featureslen); … … 326 325 aim_mpmsg_section_t *sec; 327 326 327 /* Insert each message part in a TLV (type 0x0101) */ 328 328 for (sec = args->mpmsg->parts; sec; sec = sec->next) { 329 329 aimbs_put16(&fr->data, 0x0101); … … 336 336 } else { 337 337 338 /* Insert message text in a TLV (type 0x0101) */ 338 339 aimbs_put16(&fr->data, 0x0101); 339 340 340 /* 341 * Message block length. 342 */ 341 /* Message block length */ 343 342 aimbs_put16(&fr->data, args->msglen + 0x04); 344 343 345 /* 346 * Character set. 347 */ 348 if (args->flags & AIM_IMFLAGS_CUSTOMCHARSET) { 349 350 aimbs_put16(&fr->data, args->charset); 351 aimbs_put16(&fr->data, args->charsubset); 352 353 } else { 354 if (args->flags & AIM_IMFLAGS_UNICODE) 355 aimbs_put16(&fr->data, 0x0002); 356 else if (args->flags & AIM_IMFLAGS_ISO_8859_1) 357 aimbs_put16(&fr->data, 0x0003); 358 else 359 aimbs_put16(&fr->data, 0x0000); 360 361 aimbs_put16(&fr->data, 0x0000); 362 } 363 364 /* 365 * Message. Not terminated. 366 */ 344 /* Character set */ 345 aimbs_put16(&fr->data, args->charset); 346 aimbs_put16(&fr->data, args->charsubset); 347 348 /* Message. Not terminated */ 367 349 aimbs_putraw(&fr->data, args->msg, args->msglen); 368 350 } 369 351 370 /* 371 * Set the Request Acknowledge flag. 372 */ 373 if (args->flags & AIM_IMFLAGS_ACK) { 374 aimbs_put16(&fr->data, 0x0003); 375 aimbs_put16(&fr->data, 0x0000); 376 } 377 378 /* 379 * Set the Autoresponse flag. 380 */ 352 /* Set the Autoresponse flag */ 381 353 if (args->flags & AIM_IMFLAGS_AWAY) { 382 354 aimbs_put16(&fr->data, 0x0004); 355 aimbs_put16(&fr->data, 0x0000); 356 } else if (args->flags & AIM_IMFLAGS_ACK) { 357 /* Set the Request Acknowledge flag */ 358 aimbs_put16(&fr->data, 0x0003); 383 359 aimbs_put16(&fr->data, 0x0000); 384 360 } … … 414 390 aim_tx_enqueue(sess, fr); 415 391 392 /* Move this to receive aim_flap_nop and send aim_flap_nop */ 416 393 if (!(sess->flags & AIM_SESS_FLAGS_DONTTIMEOUTONICBM)) 417 394 aim_cleansnacs(sess, 60); /* clean out SNACs over 60sec old */ … … 421 398 422 399 /* 423 * Simple wrapper for aim_ send_im_ext()400 * Simple wrapper for aim_im_sendch1_ext() 424 401 * 425 402 * You cannot use aim_send_im if you need the HASICON flag. You must 426 * use aim_ send_im_ext directly for that.403 * use aim_im_sendch1_ext directly for that. 427 404 * 428 405 * aim_send_im also cannot be used if you require UNICODE messages, because 429 * that requires an explicit message length. Use aim_ send_im_ext().430 * 431 */ 432 faim_export int aim_ send_im(aim_session_t *sess, const char *destsn, fu16_t flags, const char *msg)406 * that requires an explicit message length. Use aim_im_sendch1_ext(). 407 * 408 */ 409 faim_export int aim_im_sendch1(aim_session_t *sess, const char *sn, fu16_t flags, const char *msg) 433 410 { 434 411 struct aim_sendimext_args args; 435 412 436 args.destsn = destsn;413 args.destsn = sn; 437 414 args.flags = flags; 438 415 args.msg = msg; 439 416 args.msglen = strlen(msg); 440 441 /* Make these don't get set by accident -- they need aim_send_im_ext */ 417 args.charset = 0x0000; 418 args.charsubset = 0x0000; 419 420 /* Make these don't get set by accident -- they need aim_im_sendch1_ext */ 442 421 args.flags &= ~(AIM_IMFLAGS_CUSTOMFEATURES | AIM_IMFLAGS_HASICON | AIM_IMFLAGS_MULTIPART); 443 422 444 return aim_ send_im_ext(sess, &args);445 } 446 447 /* 448 * Subtype 0x0006 423 return aim_im_sendch1_ext(sess, &args); 424 } 425 426 /** 427 * Subtype 0x0006 - Send your icon to a given user. 449 428 * 450 429 * This is also performance sensitive. (If you can believe it...) 451 430 * 452 431 */ 453 faim_export int aim_ send_icon(aim_session_t *sess, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu16_t iconsum)432 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) 454 433 { 455 434 aim_conn_t *conn; 456 int i;457 fu8_t ck[8];458 435 aim_frame_t *fr; 459 436 aim_snacid_t snacid; 437 fu8_t ck[8]; 438 int i; 460 439 461 440 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) … … 466 445 467 446 for (i = 0; i < 8; i++) 468 aimutil_put8(ck+i, (fu8_t) rand());447 ck[i] = (fu8_t)rand(); 469 448 470 449 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn)+2+2+2+8+16+2+2+2+2+2+2+2+4+4+4+iconlen+strlen(AIM_ICONIDENT)+2+2))) … … 474 453 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); 475 454 476 /* 477 * Cookie 478 */ 479 aimbs_putraw(&fr->data, ck, 8); 480 481 /* 482 * Channel (2) 483 */ 484 aimbs_put16(&fr->data, 0x0002); 485 486 /* 487 * Dest sn 488 */ 489 aimbs_put8(&fr->data, strlen(sn)); 490 aimbs_putraw(&fr->data, sn, strlen(sn)); 455 /* ICBM header */ 456 aim_im_puticbm(&fr->data, ck, 0x0002, sn); 491 457 492 458 /* … … 531 497 532 498 /* 533 * Subtype 0x0006 499 * Subtype 0x0006 - Send a rich text message. 534 500 * 535 501 * This only works for ICQ 2001b (thats 2001 not 2000). Better, only … … 545 511 * 546 512 */ 547 faim_export int aim_send_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args) 548 { 549 const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* AIM_CAPS_ICQRTF capability in string form */ 513 faim_export int aim_im_sendch2_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args) 514 { 550 515 aim_conn_t *conn; 551 int i;552 fu8_t ck[8];553 516 aim_frame_t *fr; 554 517 aim_snacid_t snacid; 555 int servdatalen; 518 fu8_t ck[8]; 519 const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* AIM_CAPS_ICQRTF capability in string form */ 520 int i, servdatalen; 556 521 557 522 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) … … 564 529 565 530 for (i = 0; i < 8; i++) 566 aimutil_put8(ck+i, (fu8_t) rand());531 ck[i] = (fu8_t)rand(); 567 532 568 533 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+128+servdatalen))) … … 572 537 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); 573 538 574 /* 575 * Cookie 576 */ 577 aimbs_putraw(&fr->data, ck, 8); 578 579 /* 580 * Channel (2) 581 */ 582 aimbs_put16(&fr->data, 0x0002); 583 584 /* 585 * Dest sn 586 */ 587 aimbs_put8(&fr->data, strlen(args->destsn)); 588 aimbs_putraw(&fr->data, args->destsn, strlen(args->destsn)); 589 590 /* 591 * TLV t(0005) 592 * 593 * Encompasses everything below. 594 */ 539 /* ICBM header */ 540 aim_im_puticbm(&fr->data, ck, 0x0002, args->destsn); 541 542 /* TLV t(0005) - Encompasses everything below. */ 595 543 aimbs_put16(&fr->data, 0x0005); 596 544 aimbs_put16(&fr->data, 2+8+16 + 2+2+2 + 2+2 + 2+2+servdatalen); … … 600 548 aim_putcap(&fr->data, AIM_CAPS_ICQSERVERRELAY); 601 549 602 /* 603 * t(000a) l(0002) v(0001) 604 */ 550 /* t(000a) l(0002) v(0001) */ 605 551 aimbs_put16(&fr->data, 0x000a); 606 552 aimbs_put16(&fr->data, 0x0002); 607 553 aimbs_put16(&fr->data, 0x0001); 608 554 609 /* 610 * t(000f) l(0000) v() 611 */ 555 /* t(000f) l(0000) v() */ 612 556 aimbs_put16(&fr->data, 0x000f); 613 557 aimbs_put16(&fr->data, 0x0000); 614 558 615 /* 616 * Service Data TLV 617 */ 559 /* Service Data TLV */ 618 560 aimbs_put16(&fr->data, 0x2711); 619 561 aimbs_put16(&fr->data, servdatalen); … … 648 590 } 649 591 650 /* Subtype 0x0006 */ 651 faim_internal int aim_request_directim(aim_session_t *sess, const char *destsn, fu8_t *ip, fu16_t port, fu8_t *ckret) 592 /** 593 * Subtype 0x0006 - Send an "I want to directly connect to you" message 594 * 595 */ 596 faim_export int aim_im_sendch2_odcrequest(aim_session_t *sess, fu8_t *cookie, const char *sn, const fu8_t *ip, fu16_t port) 652 597 { 653 598 aim_conn_t *conn; 654 fu8_t ck[8];655 599 aim_frame_t *fr; 656 600 aim_snacid_t snacid; 601 fu8_t ck[8]; 657 602 aim_tlvlist_t *tl = NULL, *itl = NULL; 658 603 int hdrlen, i; … … 663 608 return -EINVAL; 664 609 665 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 256+strlen( destsn))))610 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 256+strlen(sn)))) 666 611 return -ENOMEM; 667 612 … … 675 620 * TOC-compatible. 676 621 * 677 * XXX have I mentioned these should be generated in msgcookie.c?622 * XXX - have I mentioned these should be generated in msgcookie.c? 678 623 * 679 624 */ … … 682 627 ck[7] = '\0'; 683 628 684 if (ckret) 685 memcpy(ckret, ck, 8); 686 687 /* Cookie */ 688 aimbs_putraw(&fr->data, ck, 8); 689 690 /* Channel */ 691 aimbs_put16(&fr->data, 0x0002); 692 693 /* Destination SN */ 694 aimbs_put8(&fr->data, strlen(destsn)); 695 aimbs_putraw(&fr->data, destsn, strlen(destsn)); 629 if (cookie) 630 memcpy(cookie, ck, 8); 631 632 /* ICBM header */ 633 aim_im_puticbm(&fr->data, ck, 0x0002, sn); 696 634 697 635 aim_addtlvtochain_noval(&tl, 0x0003); … … 703 641 aimbs_put16(&hdrbs, 0x0000); 704 642 aimbs_putraw(&hdrbs, ck, 8); 705 aim_putcap(&hdrbs, AIM_CAPS_ IMIMAGE);643 aim_putcap(&hdrbs, AIM_CAPS_DIRECTIM); 706 644 707 645 aim_addtlvtochain16(&itl, 0x000a, 0x0001); … … 725 663 } 726 664 727 /* Subtype 0x0006 */ 728 faim_internal int aim_request_sendfile(aim_session_t *sess, const char *sn, const char *filename, fu16_t numfiles, fu32_t totsize, fu8_t *ip, fu16_t port, fu8_t *ckret) 665 /** 666 * Subtype 0x0006 - Send an "I want to send you this file" message 667 * 668 */ 669 faim_export int aim_im_sendch2_sendfile_ask(aim_session_t *sess, struct aim_oft_info *oft_info) 729 670 { 730 671 aim_conn_t *conn; 731 int i;732 fu8_t ck[8];733 672 aim_frame_t *fr; 734 673 aim_snacid_t snacid; 735 struct aim_snac_destructor snacdest; 736 737 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) 674 aim_tlvlist_t *tl=NULL, *subtl=NULL; 675 int i; 676 677 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !oft_info) 738 678 return -EINVAL; 739 679 740 if (!sn || !filename) 680 /* XXX - Should be like "21CBF95" and null terminated */ 681 for (i = 0; i < 7; i++) 682 oft_info->cookie[i] = 0x30 + ((fu8_t)rand() % 10); 683 oft_info->cookie[7] = '\0'; 684 685 { /* Create the subTLV chain */ 686 fu8_t *buf; 687 int buflen; 688 aim_bstream_t bs; 689 690 aim_addtlvtochain16(&subtl, 0x000a, 0x0001); 691 aim_addtlvtochain_noval(&subtl, 0x000f); 692 /* aim_addtlvtochain_raw(&subtl, 0x000e, 2, "en"); 693 aim_addtlvtochain_raw(&subtl, 0x000d, 8, "us-ascii"); 694 aim_addtlvtochain_raw(&subtl, 0x000c, 24, "Please accept this file."); */ 695 if (oft_info->clientip) { 696 fu8_t ip[4]; 697 char *nexttoken; 698 int i = 0; 699 nexttoken = strtok(oft_info->clientip, "."); 700 while (nexttoken && i<4) { 701 ip[i] = atoi(nexttoken); 702 nexttoken = strtok(NULL, "."); 703 i++; 704 } 705 aim_addtlvtochain_raw(&subtl, 0x0003, 4, ip); 706 } 707 aim_addtlvtochain16(&subtl, 0x0005, oft_info->port); 708 709 /* TLV t(2711) */ 710 buflen = 2+2+4+strlen(oft_info->fh.name)+1; 711 buf = malloc(buflen); 712 aim_bstream_init(&bs, buf, buflen); 713 aimbs_put16(&bs, (oft_info->fh.totfiles > 1) ? 0x0002 : 0x0001); 714 aimbs_put16(&bs, oft_info->fh.totfiles); 715 aimbs_put32(&bs, oft_info->fh.totsize); 716 717 /* Filename - NULL terminated, for some odd reason */ 718 aimbs_putraw(&bs, oft_info->fh.name, strlen(oft_info->fh.name)); 719 aimbs_put8(&bs, 0x00); 720 721 aim_addtlvtochain_raw(&subtl, 0x2711, bs.len, bs.data); 722 free(buf); 723 } 724 725 { /* Create the main TLV chain */ 726 fu8_t *buf; 727 int buflen; 728 aim_bstream_t bs; 729 730 /* TLV t(0005) - Encompasses everything from above. Gee. */ 731 buflen = 2+8+16+aim_sizetlvchain(&subtl); 732 buf = malloc(buflen); 733 aim_bstream_init(&bs, buf, buflen); 734 aimbs_put16(&bs, AIM_RENDEZVOUS_PROPOSE); 735 aimbs_putraw(&bs, oft_info->cookie, 8); 736 aim_putcap(&bs, AIM_CAPS_SENDFILE); 737 aim_writetlvchain(&bs, &subtl); 738 aim_freetlvchain(&subtl); 739 aim_addtlvtochain_raw(&tl, 0x0005, bs.len, bs.data); 740 free(buf); 741 742 /* TLV t(0003) - Request an ack */ 743 aim_addtlvtochain_noval(&tl, 0x0003); 744 } 745 746 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + aim_sizetlvchain(&tl)))) 747 return -ENOMEM; 748 749 snacid = aim_cachesnac(sess, 0x0004, 0x0006, AIM_SNACFLAGS_DESTRUCTOR, oft_info->cookie, sizeof(oft_info->cookie)); 750 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); 751 752 /* ICBM header */ 753 aim_im_puticbm(&fr->data, oft_info->cookie, 0x0002, oft_info->sn); 754 755 /* All that crap from above (the 0x0005 TLV and the 0x0003 TLV) */ 756 aim_writetlvchain(&fr->data, &tl); 757 aim_freetlvchain(&tl); 758 759 aim_tx_enqueue(sess, fr); 760 761 return 0; 762 } 763 764 /** 765 * Subtype 0x0006 - Send an "I will accept this file" message? 766 * 767 * @param rendid Capability type (AIM_CAPS_GETFILE or AIM_CAPS_SENDFILE) 768 */ 769 faim_export int aim_im_sendch2_sendfile_accept(aim_session_t *sess, struct aim_oft_info *oft_info) 770 { 771 aim_conn_t *conn; 772 aim_frame_t *fr; 773 aim_snacid_t snacid; 774 775 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !oft_info) 741 776 return -EINVAL; 742 777 743 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 +8+2+1+strlen(sn)+2+2+2+8+16+6+8+6+4+2+2+2+2+4+strlen(filename)+4)))778 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + 4+2+8+16))) 744 779 return -ENOMEM; 745 780 746 for (i = 0; i < 7; i++) 747 aimutil_put8(ck+i, 0x30 + ((fu8_t) rand() % 10)); 748 ck[7] = '\0'; 749 750 if (ckret) 751 memcpy(ckret, ck, 8); 752 753 /* Fill in the snac destructor so we know if the request 754 * times out. Use the cookie in the data field, so we 755 * know what request to cancel if there is an error. 756 */ 757 snacdest.data = malloc(8); 758 memcpy(snacdest.data, ck, 8); 759 snacdest.conn = conn; 760 snacid = aim_cachesnac(sess, 0x0004, 0x0006, AIM_SNACFLAGS_DESTRUCTOR, &snacdest, sizeof(snacdest)); 781 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); 761 782 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); 762 783 763 /* 764 * Cookie 765 */ 766 aimbs_putraw(&fr->data, ck, 8); 767 768 /* 769 * Channel (2) 770 */ 771 aimbs_put16(&fr->data, 0x0002); 772 773 /* 774 * Dest sn 775 */ 776 aimbs_put8(&fr->data, strlen(sn)); 777 aimbs_putraw(&fr->data, sn, strlen(sn)); 778 779 /* 780 * TLV t(0005) 781 * 782 * Encompasses everything below. Gee. 783 */ 784 /* ICBM header */ 785 aim_im_puticbm(&fr->data, oft_info->cookie, 0x0002, oft_info->sn); 786 784 787 aimbs_put16(&fr->data, 0x0005); 785 aimbs_put16(&fr->data, 2+8+16+6+8+6+4+2+2+2+2+4+strlen(filename)+4); 786 787 aimbs_put16(&fr->data, 0x0000); 788 aimbs_putraw(&fr->data, ck, 8); 788 aimbs_put16(&fr->data, 0x001a); 789 aimbs_put16(&fr->data, AIM_RENDEZVOUS_ACCEPT); 790 aimbs_putraw(&fr->data, oft_info->cookie, 8); 789 791 aim_putcap(&fr->data, AIM_CAPS_SENDFILE); 790 792 791 /* TLV t(000a) */ 792 aimbs_put16(&fr->data, 0x000a); 793 aimbs_put16(&fr->data, 0x0002); 794 aimbs_put16(&fr->data, 0x0001); 795 796 /* TLV t(0003) (IP) */ 797 aimbs_put16(&fr->data, 0x0003); 798 aimbs_put16(&fr->data, 0x0004); 799 aimbs_putraw(&fr->data, ip, 4); 800 801 /* TLV t(0005) (port) */ 793 aim_tx_enqueue(sess, fr); 794 795 return 0; 796 } 797 798 /** 799 * Subtype 0x0006 - Send a "cancel this file transfer" message? 800 * 801 */ 802 faim_export int aim_im_sendch2_sendfile_cancel(aim_session_t *sess, struct aim_oft_info *oft_info) 803 { 804 aim_conn_t *conn; 805 aim_frame_t *fr; 806 aim_snacid_t snacid; 807 808 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !oft_info) 809 return -EINVAL; 810 811 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + 4+2+8+16))) 812 return -ENOMEM; 813 814 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); 815 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); 816 817 /* ICBM header */ 818 aim_im_puticbm(&fr->data, oft_info->cookie, 0x0002, oft_info->sn); 819 802 820 aimbs_put16(&fr->data, 0x0005); 803 aimbs_put16(&fr->data, 0x0002); 804 aimbs_put16(&fr->data, port); 805 806 /* TLV t(000f) */ 807 aimbs_put16(&fr->data, 0x000f); 808 aimbs_put16(&fr->data, 0x0000); 809 810 /* TLV t(2711) */ 811 aimbs_put16(&fr->data, 0x2711); 812 aimbs_put16(&fr->data, 2+2+4+strlen(filename)+4); 813 814 /* ? */ 815 aimbs_put16(&fr->data, (numfiles > 1) ? 0x0002 : 0x0001); 816 aimbs_put16(&fr->data, numfiles); 817 aimbs_put32(&fr->data, totsize); 818 aimbs_putraw(&fr->data, filename, strlen(filename)); 819 820 /* ? */ 821 aimbs_put32(&fr->data, 0x00000000); 822 823 #if 0 824 /* Newer clients seem to send this (?) -- wtm */ 825 aimbs_put32(&fr->data, 0x00030000); 826 #endif 821 aimbs_put16(&fr->data, 0x001a); 822 aimbs_put16(&fr->data, AIM_RENDEZVOUS_CANCEL); 823 aimbs_putraw(&fr->data, oft_info->cookie, 8); 824 aim_putcap(&fr->data, AIM_CAPS_SENDFILE); 827 825 828 826 aim_tx_enqueue(sess, fr); … … 840 838 * @return Return 0 if no errors, otherwise return the error number. 841 839 */ 842 faim_export int aim_ send_im_ch2_geticqmessage(aim_session_t *sess, const char *sn, int type)840 faim_export int aim_im_sendch2_geticqaway(aim_session_t *sess, const char *sn, int type) 843 841 { 844 842 aim_conn_t *conn; 843 aim_frame_t *fr; 844 aim_snacid_t snacid; 845 845 int i; 846 846 fu8_t ck[8]; 847 aim_frame_t *fr;848 aim_snacid_t snacid;849 847 850 848 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !sn) … … 852 850 853 851 for (i = 0; i < 8; i++) 854 aimutil_put8(ck+i, (fu8_t) rand());852 ck[i] = (fu8_t)rand(); 855 853 856 854 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn) + 4+0x5e + 4))) … … 860 858 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); 861 859 862 /* Cookie */ 863 aimbs_putraw(&fr->data, ck, 8); 864 865 /* Channel (2) */ 866 aimbs_put16(&fr->data, 0x0002); 867 868 /* Dest sn */ 869 aimbs_put8(&fr->data, strlen(sn)); 870 aimbs_putraw(&fr->data, sn, strlen(sn)); 860 /* ICBM header */ 861 aim_im_puticbm(&fr->data, ck, 0x0002, sn); 871 862 872 863 /* TLV t(0005) - Encompasses almost everything below. */ … … 897 888 aimbs_putle16(&fr->data, 0x001b); /* L */ 898 889 aimbs_putle16(&fr->data, 0x0008); /* XXX - Protocol version */ 899 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ 900 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ 901 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ 902 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ 890 aim_putcap(&fr->data, AIM_CAPS_EMPTY); 903 891 aimbs_putle16(&fr->data, 0x0000); /* Unknown */ 904 892 aimbs_putle16(&fr->data, 0x0003); /* Client features? */ … … 927 915 aimbs_putle16(&fr->data, 0x0000); /* Status? */ 928 916 aimbs_putle16(&fr->data, 0x0001); /* Priority of this message? */ 929 aimbs_putle16(&fr->data, 0x0001); /* L ?*/930 aimbs_putle8(&fr->data, 0x00); /* Null termination?*/917 aimbs_putle16(&fr->data, 0x0001); /* L */ 918 aimbs_putle8(&fr->data, 0x00); /* String of length L */ 931 919 } /* End TLV t(2711) */ 932 920 } /* End TLV t(0005) */ … … 942 930 943 931 /** 944 * Subtype 0x0006 932 * Subtype 0x0006 - Send an ICQ-esque ICBM. 945 933 * 946 934 * This can be used to send an ICQ authorization reply (deny or grant). It is the "old way." … … 955 943 * @return Return 0 if no errors, otherwise return the error number. 956 944 */ 957 faim_export int aim_ send_im_ch4(aim_session_t *sess, char *sn, fu16_t type, fu8_t *message)945 faim_export int aim_im_sendch4(aim_session_t *sess, char *sn, fu16_t type, fu8_t *message) 958 946 { 959 947 aim_conn_t *conn; … … 961 949 aim_snacid_t snacid; 962 950 int i; 951 char ck[8]; 963 952 964 953 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0002))) … … 974 963 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); 975 964 976 /* 977 * Cookie 978 */ 965 /* Cookie */ 979 966 for (i=0; i<8; i++) 980 aimbs_put8(&fr->data, (fu8_t)rand()); 981 982 /* 983 * Channel (4) 984 */ 985 aimbs_put16(&fr->data, 0x0004); 986 987 /* 988 * Dest sn 989 */ 990 aimbs_put8(&fr->data, strlen(sn)); 991 aimbs_putraw(&fr->data, sn, strlen(sn)); 967 ck[i] = (fu8_t)rand(); 968 969 /* ICBM header */ 970 aim_im_puticbm(&fr->data, ck, 0x0004, sn); 992 971 993 972 /* … … 1022 1001 } 1023 1002 1003 /* 1004 * XXX - I don't see when this would ever get called... 1005 */ 1024 1006 static int outgoingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1025 1007 { … … 1177 1159 } 1178 1160 1179 /* XXX should provide a way of saying ISO-8859-1 specifically */1161 /* XXX - should provide a way of saying ISO-8859-1 specifically */ 1180 1162 faim_export int aim_mpmsg_addascii(aim_session_t *sess, aim_mpmsg_t *mpm, const char *ascii) 1181 1163 { … … 1280 1262 * the specified data length, which will not include the pad. 1281 1263 * 1282 * XXX There's an API bug here. For sending, the UNICODE is1264 * XXX - There's an API bug here. For sending, the UNICODE is 1283 1265 * given in host byte order (aim_mpmsg_addunicode), but here 1284 1266 * the received messages are given in network byte order. … … 1313 1295 args->charset = sec->charset; 1314 1296 args->charsubset = sec->charsubset; 1315 args->icbmflags |= AIM_IMFLAGS_CUSTOMCHARSET;1316 1297 1317 1298 /* Set up the simple flags */ … … 1331 1312 else if (args->charsubset == 0xffff) 1332 1313 ; /* no subencoding */ 1333 #if 01334 /* XXX this isn't really necesary... */1335 if ( ((args.flag1 != 0x0000) &&1336 (args.flag1 != 0x0002) &&1337 (args.flag1 != 0x0003) &&1338 (args.flag1 != 0xffff)) ||1339 ((args.flag2 != 0x0000) &&1340 (args.flag2 != 0x000b) &&1341 (args.flag2 != 0xffff))) {1342 faimdprintf(sess, 0, "icbm: **warning: encoding flags are being used! {%04x, %04x}\n", args.flag1, args.flag2);1343 }1344 #endif1345 1314 1346 1315 args->msg = sec->data; … … 1419 1388 } else if (type == 0x0006) { /* Message was received offline. */ 1420 1389 1421 /* XXX not sure if this actually gets sent. */1390 /* XXX - not sure if this actually gets sent. */ 1422 1391 args.icbmflags |= AIM_IMFLAGS_OFFLINE; 1423 1392 … … 1555 1524 { 1556 1525 1557 /* XXX aim_chat_roominfo_free() */1526 /* XXX - aim_chat_roominfo_free() */ 1558 1527 free(args->info.chat.roominfo.name); 1559 1528 … … 1616 1585 aim_bstream_advance(servdata, hdrlen); 1617 1586 1618 /* XXX This is such a hack. */1587 /* XXX - This is such a hack. */ 1619 1588 args->reqclass = AIM_CAPS_ICQRTF; 1620 1589 … … 1634 1603 args->destructor = (void *)incomingim_ch2_sendfile_free; 1635 1604 1636 if (servdata) { 1605 /* Maybe there is a better way to tell what kind of sendfile 1606 * this is? Maybe TLV t(000a)? */ 1607 if (servdata) { /* Someone is sending us a file */ 1637 1608 int flen; 1638 1609 … … 1642 1613 args->info.sendfile.totsize = aimbs_get32(servdata); 1643 1614 1644 /* XXX - create an aimbs_getnullstr function */ 1615 /* 1616 * I hope to God I'm right when I guess that there is a 1617 * 32 char max filename length for single files. I think 1618 * OFT tends to do that. Gotta love inconsistency. I saw 1619 * a 26 byte filename? 1620 */ 1621 /* AAA - create an aimbs_getnullstr function (don't anymore)(maybe) */ 1645 1622 /* Use an inelegant way of getting the null-terminated filename, 1646 1623 * since there's no easy bstream routine. */ … … 1651 1628 /* There is sometimes more after the null-terminated filename, 1652 1629 * but I'm unsure of its format. */ 1630 /* I don't believe him. */ 1653 1631 } 1654 1632 … … 1668 1646 int ret = 0; 1669 1647 1670 char clientip1[30] = {""};1671 char clientip 2[30] = {""};1648 char proxyip[30] = {""}; 1649 char clientip[30] = {""}; 1672 1650 char verifiedip[30] = {""}; 1673 1651 … … 1711 1689 1712 1690 /* 1713 * IP address from the perspective of the client. 1691 * IP address to proxy the file transfer through. 1692 * 1693 * XXX - I don't like this. Maybe just read in an int? Or inet_ntoa... 1714 1694 */ 1715 1695 if (aim_gettlv(list2, 0x0002, 1)) { … … 1717 1697 1718 1698 iptlv = aim_gettlv(list2, 0x0002, 1); 1719 1720 snprintf(clientip1, sizeof(clientip1), "%d.%d.%d.%d", 1721 aimutil_get8(iptlv->value+0), 1722 aimutil_get8(iptlv->value+1), 1723 aimutil_get8(iptlv->value+2), 1724 aimutil_get8(iptlv->value+3)); 1725 } 1726 1727 /* 1728 * Secondary IP address from the perspective of the client. 1699 if (iptlv->length == 4) 1700 snprintf(proxyip, sizeof(proxyip), "%hhd.%hhd.%hhd.%hhd", 1701 iptlv->value[0], iptlv->value[1], 1702 iptlv->value[2], iptlv->value[3]); 1703 } 1704 1705 /* 1706 * IP address from the perspective of the client. 1729 1707 */ 1730 1708 if (aim_gettlv(list2, 0x0003, 1)) { … … 1732 1710 1733 1711 iptlv = aim_gettlv(list2, 0x0003, 1); 1734 1735 snprintf(clientip2, sizeof(clientip2), "%d.%d.%d.%d", 1736 aimutil_get8(iptlv->value+0), 1737 aimutil_get8(iptlv->value+1), 1738 aimutil_get8(iptlv->value+2), 1739 aimutil_get8(iptlv->value+3)); 1712 if (iptlv->length == 4) 1713 snprintf(clientip, sizeof(clientip), "%hhd.%hhd.%hhd.%hhd", 1714 iptlv->value[0], iptlv->value[1], 1715 iptlv->value[2], iptlv->value[3]); 1740 1716 } 1741 1717 … … 1749 1725 1750 1726 iptlv = aim_gettlv(list2, 0x0004, 1); 1751 1752 snprintf(verifiedip, sizeof(verifiedip), "%d.%d.%d.%d", 1753 aimutil_get8(iptlv->value+0), 1754 aimutil_get8(iptlv->value+1), 1755 aimutil_get8(iptlv->value+2), 1756 aimutil_get8(iptlv->value+3)); 1727 if (iptlv->length == 4) 1728 snprintf(verifiedip, sizeof(verifiedip), "%hhd.%hhd.%hhd.%hhd", 1729 iptlv->value[0], iptlv->value[1], 1730 iptlv->value[2], iptlv->value[3]); 1757 1731 } 1758 1732 … … 1762 1736 if (aim_gettlv(list2, 0x0005, 1)) 1763 1737 args.port = aim_gettlv16(list2, 0x0005, 1); 1738 1739 /* 1740 * Something to do with ft -- two bytes 1741 * 0x0001 - "I want to send you this file" 1742 * 0x0002 - "I will accept this file from you" 1743 */ 1744 if (aim_gettlv(list2, 0x000a, 1)) 1745 ; 1764 1746 1765 1747 /* … … 1787 1769 args.language = aim_gettlv_str(list2, 0x000e, 1); 1788 1770 1789 /* Unknown -- two bytes = 0x0001 */1790 if (aim_gettlv(list2, 0x000a, 1))1791 ;1792 1793 /* Unknown -- no value*/1771 /* 1772 * Unknown -- no value 1773 * 1774 * Maybe means we should connect directly to transfer the file? 1775 */ 1794 1776 if (aim_gettlv(list2, 0x000f, 1)) 1795 1777 ; 1796 1778 1797 if (strlen(clientip1)) 1798 args.clientip = (char *)clientip1; 1799 if (strlen(clientip2)) 1800 args.clientip2 = (char *)clientip2; 1779 /* 1780 * Unknown -- no value 1781 * 1782 * Maybe means we should proxy the file transfer through an AIM server? 1783 */ 1784 if (aim_gettlv(list2, 0x0010, 1)) 1785 ; 1786 1787 if (strlen(proxyip)) 1788 args.proxyip = (char *)proxyip; 1789 if (strlen(clientip)) 1790 args.clientip = (char *)clientip; 1801 1791 if (strlen(verifiedip)) 1802 1792 args.verifiedip = (char *)verifiedip; 1803 1793 1804 1794 /* 1805 * This ismust be present in PROPOSALs, but will probably not1795 * This must be present in PROPOSALs, but will probably not 1806 1796 * exist in CANCELs and ACCEPTs. 1807 1797 * … … 1863 1853 1864 1854 args.uin = aimbs_getle32(&meat); 1865 args.type = aimbs_getle16(&meat); 1866 args.msg = aimbs_getraw(&meat, aimbs_getle16(&meat)); 1855 args.type = aimbs_getle8(&meat); 1856 args.flags = aimbs_getle8(&meat); 1857 args.msglen = aimbs_getle16(&meat); 1858 args.msg = aimbs_getraw(&meat, args.msglen); 1867 1859 1868 1860 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) … … 1905 1897 * Channel ID. 1906 1898 * 1907 * Channel 0x0001 is the message channel. There are 1908 * other channels for things called "rendevous" 1909 * which represent chat and some of the other new 1910 * features of AIM2/3/3.5. 1899 * Channel 0x0001 is the message channel. It is 1900 * used to send basic ICBMs. 1911 1901 * 1912 1902 * Channel 0x0002 is the Rendevous channel, which 1913 1903 * is where Chat Invitiations and various client-client 1914 1904 * connection negotiations come from. 1905 * 1906 * Channel 0x0003 is used for chat messages. 1915 1907 * 1916 1908 * Channel 0x0004 is used for ICQ authorization, or … … 1927 1919 * userinfo block contains the number of TLVs that contain user 1928 1920 * information, the rest are not even though there is no seperation. 1929 * aim_extractuserinfo() returns the number of bytes used by the 1930 * userinfo tlvs, so you can start reading the rest of them right 1931 * afterward. 1921 * You can start reading the message TLVs after aim_info_extract() 1922 * parses out the standard userinfo block. 1932 1923 * 1933 1924 * That also means that TLV types can be duplicated between the … … 1936 1927 * 1937 1928 */ 1938 aim_ extractuserinfo(sess, bs, &userinfo);1929 aim_info_extract(sess, bs, &userinfo); 1939 1930 1940 1931 /* … … 1970 1961 1971 1962 } else { 1972 1973 faimdprintf(sess, 0, "icbm: ICBM received on an unsupported channel. Ignoring.\n (chan = %04x)", channel); 1974 1975 return 0; 1976 } 1963 faimdprintf(sess, 0, "icbm: ICBM received on an unsupported channel. Ignoring. (chan = %04x)\n", channel); 1964 } 1965 1966 aim_info_free(&userinfo); 1977 1967 1978 1968 return ret; … … 1980 1970 1981 1971 /* 1982 * Subtype 0x0008 - Send a warning to destsn.1972 * Subtype 0x0008 - Send a warning to sn. 1983 1973 * 1984 1974 * Flags: … … 1988 1978 * 1989 1979 */ 1990 faim_export int aim_ send_warning(aim_session_t *sess, aim_conn_t *conn, const char *destsn, fu32_t flags)1980 faim_export int aim_im_warn(aim_session_t *sess, aim_conn_t *conn, const char *sn, fu32_t flags) 1991 1981 { 1992 1982 aim_frame_t *fr; 1993 1983 aim_snacid_t snacid; 1994 fu16_t outflags = 0x0000; 1995 1996 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, strlen(destsn)+13))) 1984 1985 if (!sess || !conn || !sn) 1986 return -EINVAL; 1987 1988 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, strlen(sn)+13))) 1997 1989 return -ENOMEM; 1998 1990 1999 snacid = aim_cachesnac(sess, 0x0004, 0x0008, 0x0000, destsn, strlen(destsn)+1); 2000 1991 snacid = aim_cachesnac(sess, 0x0004, 0x0008, 0x0000, sn, strlen(sn)+1); 2001 1992 aim_putsnac(&fr->data, 0x0004, 0x0008, 0x0000, snacid); 2002 1993 2003 if (flags & AIM_WARN_ANON) 2004 outflags |= 0x0001; 2005 2006 aimbs_put16(&fr->data, outflags); 2007 aimbs_put8(&fr->data, strlen(destsn)); 2008 aimbs_putraw(&fr->data, destsn, strlen(destsn)); 1994 aimbs_put16(&fr->data, (flags & AIM_WARN_ANON) ? 0x0001 : 0x0000); 1995 aimbs_put8(&fr->data, strlen(sn)); 1996 aimbs_putraw(&fr->data, sn, strlen(sn)); 2009 1997 2010 1998 aim_tx_enqueue(sess, fr); … … 2024 2012 2025 2013 channel = aimbs_get16(bs); 2026 aim_ extractuserinfo(sess, bs, &userinfo);2014 aim_info_extract(sess, bs, &userinfo); 2027 2015 nummissed = aimbs_get16(bs); 2028 2016 reason = aimbs_get16(bs); … … 2030 2018 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 2031 2019 ret = userfunc(sess, rx, channel, &userinfo, nummissed, reason); 2020 2021 aim_info_free(&userinfo); 2032 2022 } 2033 2023 … … 2044 2034 * 2045 2035 */ 2046 faim_export int aim_ denytransfer(aim_session_t *sess, const char *sender, const char *cookie, fu16_t code)2036 faim_export int aim_im_denytransfer(aim_session_t *sess, const char *sender, const char *cookie, fu16_t code) 2047 2037 { 2048 2038 aim_conn_t *conn; … … 2096 2086 2097 2087 if (channel == 0x0002) { /* File transfer declined */ 2088 aimbs_get16(bs); /* Unknown */ 2089 aimbs_get16(bs); /* Unknown */ 2098 2090 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 2099 2091 ret = userfunc(sess, rx, channel, sn, reason, ck); … … 2159 2151 } 2160 2152 2161 /* Subtype 0x000c */ 2153 /* 2154 * Subtype 0x000c - Receive an ack after sending an ICBM. 2155 * 2156 * You have to have send the message with the AIM_IMFLAGS_ACK flag set 2157 * (TLV t(0003)). The ack contains the ICBM header of the message you 2158 * sent. 2159 * 2160 */ 2162 2161 static int msgack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 2163 2162 { 2164 2163 aim_rxcallback_t userfunc; 2165 fu16_t type;2166 fu8_t snlen,*ck;2164 fu16_t ch; 2165 fu8_t *ck; 2167 2166 char *sn; 2168 2167 int ret = 0; 2169 2168 2170 2169 ck = aimbs_getraw(bs, 8); 2171 type = aimbs_get16(bs); 2172 snlen = aimbs_get8(bs); 2173 sn = aimbs_getstr(bs, snlen); 2170 ch = aimbs_get16(bs); 2171 sn = aimbs_getstr(bs, aimbs_get8(bs)); 2174 2172 2175 2173 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 2176 ret = userfunc(sess, rx, type, sn);2174 ret = userfunc(sess, rx, ch, sn); 2177 2175 2178 2176 free(sn); … … 2189 2187 * 2190 2188 */ 2191 faim_export int aim_ mtn_send(aim_session_t *sess, fu16_t type1,char *sn, fu16_t type2)2189 faim_export int aim_im_sendmtn(aim_session_t *sess, fu16_t type1, const char *sn, fu16_t type2) 2192 2190 { 2193 2191 aim_conn_t *conn; … … 2270 2268 2271 2269 if (snac->subtype == 0x0005) 2272 return paraminfo(sess, mod, rx, snac, bs);2270 return aim_im_paraminfo(sess, mod, rx, snac, bs); 2273 2271 else if (snac->subtype == 0x0006) 2274 2272 return outgoingim(sess, mod, rx, snac, bs); … … 2287 2285 } 2288 2286 2289 static int snacdestructor(aim_session_t *sess, aim_conn_t *conn, aim_modsnac_t *snac, void *data)2290 {2291 aim_rxcallback_t userfunc;2292 int ret = 0;2293 2294 if (snac->subtype == 0x0006) {2295 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_MSGTIMEOUT)))2296 ret = userfunc(sess, NULL, conn, data);2297 }2298 /* Note that we return 1 for success, 0 for failure. */2299 return ret;2300 }2301 2302 2287 faim_internal int msg_modfirst(aim_session_t *sess, aim_module_t *mod) 2303 2288 { … … 2306 2291 mod->version = 0x0001; 2307 2292 mod->toolid = 0x0110; 2308 mod->toolversion = 0x0 47b;2293 mod->toolversion = 0x0629; 2309 2294 mod->flags = 0; 2310 2295 strncpy(mod->name, "messaging", sizeof(mod->name)); 2311 2296 mod->snachandler = snachandler; 2312 mod->snacdestructor = snacdestructor;2313 2297 2314 2298 return 0;
Note: See TracChangeset
for help on using the changeset viewer.