Changeset 6042a54 for protocols/oscar/im.c
- Timestamp:
- 2012-10-19T23:38:33Z (12 years ago)
- Branches:
- master
- Children:
- 509cf60
- Parents:
- 386042c
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/oscar/im.c
r386042c r6042a54 23 23 #include "im.h" 24 24 #include "info.h" 25 26 /* This should be endian-safe now... but who knows... */27 guint16 aim_iconsum(const guint8 *buf, int buflen)28 {29 guint32 sum;30 int i;31 32 for (i = 0, sum = 0; i + 1 < buflen; i += 2)33 sum += (buf[i+1] << 8) + buf[i];34 if (i < buflen)35 sum += buf[i];36 37 sum = ((sum & 0xffff0000) >> 16) + (sum & 0x0000ffff);38 39 return (guint16)sum;40 }41 25 42 26 /* … … 306 290 } 307 291 308 /*309 * This is also performance sensitive. (If you can believe it...)310 *311 */312 int aim_send_icon(aim_session_t *sess, const char *sn, const guint8 *icon, int iconlen, time_t stamp, guint16 iconsum)313 {314 aim_conn_t *conn;315 int i;316 guint8 ck[8];317 aim_frame_t *fr;318 aim_snacid_t snacid;319 320 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))321 return -EINVAL;322 323 if (!sn || !icon || (iconlen <= 0) || (iconlen >= MAXICONLEN))324 return -EINVAL;325 326 for (i = 0; i < 8; i++)327 aimutil_put8(ck+i, (guint8) rand());328 329 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)))330 return -ENOMEM;331 332 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);333 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);334 335 /*336 * Cookie337 */338 aimbs_putraw(&fr->data, ck, 8);339 340 /*341 * Channel (2)342 */343 aimbs_put16(&fr->data, 0x0002);344 345 /*346 * Dest sn347 */348 aimbs_put8(&fr->data, strlen(sn));349 aimbs_putraw(&fr->data, (guint8 *)sn, strlen(sn));350 351 /*352 * TLV t(0005)353 *354 * Encompasses everything below.355 */356 aimbs_put16(&fr->data, 0x0005);357 aimbs_put16(&fr->data, 2+8+16+6+4+4+iconlen+4+4+4+strlen(AIM_ICONIDENT));358 359 aimbs_put16(&fr->data, 0x0000);360 aimbs_putraw(&fr->data, ck, 8);361 aim_putcap(&fr->data, AIM_CAPS_BUDDYICON);362 363 /* TLV t(000a) */364 aimbs_put16(&fr->data, 0x000a);365 aimbs_put16(&fr->data, 0x0002);366 aimbs_put16(&fr->data, 0x0001);367 368 /* TLV t(000f) */369 aimbs_put16(&fr->data, 0x000f);370 aimbs_put16(&fr->data, 0x0000);371 372 /* TLV t(2711) */373 aimbs_put16(&fr->data, 0x2711);374 aimbs_put16(&fr->data, 4+4+4+iconlen+strlen(AIM_ICONIDENT));375 aimbs_put16(&fr->data, 0x0000);376 aimbs_put16(&fr->data, iconsum);377 aimbs_put32(&fr->data, iconlen);378 aimbs_put32(&fr->data, stamp);379 aimbs_putraw(&fr->data, icon, iconlen);380 aimbs_putraw(&fr->data, (guint8 *)AIM_ICONIDENT, strlen(AIM_ICONIDENT));381 382 /* TLV t(0003) */383 aimbs_put16(&fr->data, 0x0003);384 aimbs_put16(&fr->data, 0x0000);385 386 aim_tx_enqueue(sess, fr);387 388 return 0;389 }390 391 /*392 * This only works for ICQ 2001b (thats 2001 not 2000). Better, only393 * send it to clients advertising the RTF capability. In fact, if you send394 * it to a client that doesn't support that capability, the server will gladly395 * bounce it back to you.396 *397 * You'd think this would be in icq.c, but, well, I'm trying to stick with398 * the one-group-per-file scheme as much as possible. This could easily399 * be an exception, since Rendezvous IMs are external of the Oscar core,400 * and therefore are undefined. Really I just need to think of a good way to401 * make an interface similar to what AOL actually uses. But I'm not using COM.402 *403 */404 int aim_send_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args)405 {406 const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* AIM_CAPS_ICQRTF capability in string form */407 aim_conn_t *conn;408 int i;409 guint8 ck[8];410 aim_frame_t *fr;411 aim_snacid_t snacid;412 int servdatalen;413 414 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))415 return -EINVAL;416 417 if (!args || !args->destsn || !args->rtfmsg)418 return -EINVAL;419 420 servdatalen = 2+2+16+2+4+1+2 + 2+2+4+4+4 + 2+4+2+strlen(args->rtfmsg)+1 + 4+4+4+strlen(rtfcap)+1;421 422 for (i = 0; i < 8; i++)423 aimutil_put8(ck+i, (guint8) rand());424 425 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+128+servdatalen)))426 return -ENOMEM;427 428 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);429 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);430 431 /*432 * Cookie433 */434 aimbs_putraw(&fr->data, ck, 8);435 436 /*437 * Channel (2)438 */439 aimbs_put16(&fr->data, 0x0002);440 441 /*442 * Dest sn443 */444 aimbs_put8(&fr->data, strlen(args->destsn));445 aimbs_putraw(&fr->data, (guint8 *)args->destsn, strlen(args->destsn));446 447 /*448 * TLV t(0005)449 *450 * Encompasses everything below.451 */452 aimbs_put16(&fr->data, 0x0005);453 aimbs_put16(&fr->data, 2+8+16 + 2+2+2 + 2+2 + 2+2+servdatalen);454 455 aimbs_put16(&fr->data, 0x0000);456 aimbs_putraw(&fr->data, ck, 8);457 aim_putcap(&fr->data, AIM_CAPS_ICQSERVERRELAY);458 459 /*460 * t(000a) l(0002) v(0001)461 */462 aimbs_put16(&fr->data, 0x000a);463 aimbs_put16(&fr->data, 0x0002);464 aimbs_put16(&fr->data, 0x0001);465 466 /*467 * t(000f) l(0000) v()468 */469 aimbs_put16(&fr->data, 0x000f);470 aimbs_put16(&fr->data, 0x0000);471 472 /*473 * Service Data TLV474 */475 aimbs_put16(&fr->data, 0x2711);476 aimbs_put16(&fr->data, servdatalen);477 478 aimbs_putle16(&fr->data, 11 + 16 /* 11 + (sizeof CLSID) */);479 aimbs_putle16(&fr->data, 9);480 aim_putcap(&fr->data, AIM_CAPS_EMPTY);481 aimbs_putle16(&fr->data, 0);482 aimbs_putle32(&fr->data, 0);483 aimbs_putle8(&fr->data, 0);484 aimbs_putle16(&fr->data, 0x03ea); /* trid1 */485 486 aimbs_putle16(&fr->data, 14);487 aimbs_putle16(&fr->data, 0x03eb); /* trid2 */488 aimbs_putle32(&fr->data, 0);489 aimbs_putle32(&fr->data, 0);490 aimbs_putle32(&fr->data, 0);491 492 aimbs_putle16(&fr->data, 0x0001);493 aimbs_putle32(&fr->data, 0);494 aimbs_putle16(&fr->data, strlen(args->rtfmsg)+1);495 aimbs_putraw(&fr->data, (guint8 *)args->rtfmsg, strlen(args->rtfmsg)+1);496 497 aimbs_putle32(&fr->data, args->fgcolor);498 aimbs_putle32(&fr->data, args->bgcolor);499 aimbs_putle32(&fr->data, strlen(rtfcap)+1);500 aimbs_putraw(&fr->data, (guint8 *)rtfcap, strlen(rtfcap)+1);501 502 aim_tx_enqueue(sess, fr);503 504 return 0;505 }506 507 int aim_request_directim(aim_session_t *sess, const char *destsn, guint8 *ip, guint16 port, guint8 *ckret)508 {509 aim_conn_t *conn;510 guint8 ck[8];511 aim_frame_t *fr;512 aim_snacid_t snacid;513 aim_tlvlist_t *tl = NULL, *itl = NULL;514 int hdrlen, i;515 guint8 *hdr;516 aim_bstream_t hdrbs;517 518 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))519 return -EINVAL;520 521 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 256+strlen(destsn))))522 return -ENOMEM;523 524 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);525 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);526 527 /*528 * Generate a random message cookie529 *530 * This cookie needs to be alphanumeric and NULL-terminated to be531 * TOC-compatible.532 *533 * XXX have I mentioned these should be generated in msgcookie.c?534 *535 */536 for (i = 0; i < 7; i++)537 ck[i] = 0x30 + ((guint8) rand() % 10);538 ck[7] = '\0';539 540 if (ckret)541 memcpy(ckret, ck, 8);542 543 /* Cookie */544 aimbs_putraw(&fr->data, ck, 8);545 546 /* Channel */547 aimbs_put16(&fr->data, 0x0002);548 549 /* Destination SN */550 aimbs_put8(&fr->data, strlen(destsn));551 aimbs_putraw(&fr->data, (guint8 *)destsn, strlen(destsn));552 553 aim_addtlvtochain_noval(&tl, 0x0003);554 555 hdrlen = 2+8+16+6+8+6+4;556 hdr = g_malloc(hdrlen);557 aim_bstream_init(&hdrbs, hdr, hdrlen);558 559 aimbs_put16(&hdrbs, 0x0000);560 aimbs_putraw(&hdrbs, ck, 8);561 aim_putcap(&hdrbs, AIM_CAPS_IMIMAGE);562 563 aim_addtlvtochain16(&itl, 0x000a, 0x0001);564 aim_addtlvtochain_raw(&itl, 0x0003, 4, ip);565 aim_addtlvtochain16(&itl, 0x0005, port);566 aim_addtlvtochain_noval(&itl, 0x000f);567 568 aim_writetlvchain(&hdrbs, &itl);569 570 aim_addtlvtochain_raw(&tl, 0x0005, aim_bstream_curpos(&hdrbs), hdr);571 572 aim_writetlvchain(&fr->data, &tl);573 574 g_free(hdr);575 aim_freetlvchain(&itl);576 aim_freetlvchain(&tl);577 578 aim_tx_enqueue(sess, fr);579 580 return 0;581 }582 583 int aim_request_sendfile(aim_session_t *sess, const char *sn, const char *filename, guint16 numfiles, guint32 totsize, guint8 *ip, guint16 port, guint8 *ckret)584 {585 aim_conn_t *conn;586 int i;587 guint8 ck[8];588 aim_frame_t *fr;589 aim_snacid_t snacid;590 591 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))592 return -EINVAL;593 594 if (!sn || !filename)595 return -EINVAL;596 597 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)))598 return -ENOMEM;599 600 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);601 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);602 603 for (i = 0; i < 7; i++)604 aimutil_put8(ck+i, 0x30 + ((guint8) rand() % 10));605 ck[7] = '\0';606 607 if (ckret)608 memcpy(ckret, ck, 8);609 610 /*611 * Cookie612 */613 aimbs_putraw(&fr->data, ck, 8);614 615 /*616 * Channel (2)617 */618 aimbs_put16(&fr->data, 0x0002);619 620 /*621 * Dest sn622 */623 aimbs_put8(&fr->data, strlen(sn));624 aimbs_putraw(&fr->data, (guint8 *)sn, strlen(sn));625 626 /*627 * TLV t(0005)628 *629 * Encompasses everything below. Gee.630 */631 aimbs_put16(&fr->data, 0x0005);632 aimbs_put16(&fr->data, 2+8+16+6+8+6+4+2+2+2+2+4+strlen(filename)+4);633 634 aimbs_put16(&fr->data, 0x0000);635 aimbs_putraw(&fr->data, ck, 8);636 aim_putcap(&fr->data, AIM_CAPS_SENDFILE);637 638 /* TLV t(000a) */639 aimbs_put16(&fr->data, 0x000a);640 aimbs_put16(&fr->data, 0x0002);641 aimbs_put16(&fr->data, 0x0001);642 643 /* TLV t(0003) (IP) */644 aimbs_put16(&fr->data, 0x0003);645 aimbs_put16(&fr->data, 0x0004);646 aimbs_putraw(&fr->data, ip, 4);647 648 /* TLV t(0005) (port) */649 aimbs_put16(&fr->data, 0x0005);650 aimbs_put16(&fr->data, 0x0002);651 aimbs_put16(&fr->data, port);652 653 /* TLV t(000f) */654 aimbs_put16(&fr->data, 0x000f);655 aimbs_put16(&fr->data, 0x0000);656 657 /* TLV t(2711) */658 aimbs_put16(&fr->data, 0x2711);659 aimbs_put16(&fr->data, 2+2+4+strlen(filename)+4);660 661 /* ? */662 aimbs_put16(&fr->data, 0x0001);663 aimbs_put16(&fr->data, numfiles);664 aimbs_put32(&fr->data, totsize);665 aimbs_putraw(&fr->data, (guint8 *)filename, strlen(filename));666 667 /* ? */668 aimbs_put32(&fr->data, 0x00000000);669 670 aim_tx_enqueue(sess, fr);671 672 return 0;673 }674 675 /**676 * Request the status message of the given ICQ user.677 *678 * @param sess The oscar session.679 * @param sn The UIN of the user of whom you wish to request info.680 * @param type The type of info you wish to request. This should be the current681 * state of the user, as one of the AIM_ICQ_STATE_* defines.682 * @return Return 0 if no errors, otherwise return the error number.683 */684 int aim_send_im_ch2_geticqmessage(aim_session_t *sess, const char *sn, int type)685 {686 aim_conn_t *conn;687 int i;688 guint8 ck[8];689 aim_frame_t *fr;690 aim_snacid_t snacid;691 692 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !sn)693 return -EINVAL;694 695 for (i = 0; i < 8; i++)696 aimutil_put8(ck+i, (guint8) rand());697 698 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn) + 4+0x5e + 4)))699 return -ENOMEM;700 701 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);702 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);703 704 /* Cookie */705 aimbs_putraw(&fr->data, ck, 8);706 707 /* Channel (2) */708 aimbs_put16(&fr->data, 0x0002);709 710 /* Dest sn */711 aimbs_put8(&fr->data, strlen(sn));712 aimbs_putraw(&fr->data, (guint8 *)sn, strlen(sn));713 714 /* TLV t(0005) - Encompasses almost everything below. */715 aimbs_put16(&fr->data, 0x0005); /* T */716 aimbs_put16(&fr->data, 0x005e); /* L */717 { /* V */718 aimbs_put16(&fr->data, 0x0000);719 720 /* Cookie */721 aimbs_putraw(&fr->data, ck, 8);722 723 /* Put the 16 byte server relay capability */724 aim_putcap(&fr->data, AIM_CAPS_ICQSERVERRELAY);725 726 /* TLV t(000a) */727 aimbs_put16(&fr->data, 0x000a);728 aimbs_put16(&fr->data, 0x0002);729 aimbs_put16(&fr->data, 0x0001);730 731 /* TLV t(000f) */732 aimbs_put16(&fr->data, 0x000f);733 aimbs_put16(&fr->data, 0x0000);734 735 /* TLV t(2711) */736 aimbs_put16(&fr->data, 0x2711);737 aimbs_put16(&fr->data, 0x0036);738 { /* V */739 aimbs_putle16(&fr->data, 0x001b); /* L */740 aimbs_putle16(&fr->data, 0x0008); /* AAA - Protocol version */741 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */742 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */743 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */744 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */745 aimbs_putle16(&fr->data, 0x0000); /* Unknown */746 aimbs_putle16(&fr->data, 0x0003); /* Client features? */747 aimbs_putle16(&fr->data, 0x0000); /* Unknown */748 aimbs_putle8(&fr->data, 0x00); /* Unkizown */749 aimbs_putle16(&fr->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */750 751 aimbs_putle16(&fr->data, 0x000e); /* L */752 aimbs_putle16(&fr->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */753 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */754 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */755 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */756 757 /* The type of status message being requested */758 if (type & AIM_ICQ_STATE_CHAT)759 aimbs_putle16(&fr->data, 0x03ec);760 else if(type & AIM_ICQ_STATE_DND)761 aimbs_putle16(&fr->data, 0x03eb);762 else if(type & AIM_ICQ_STATE_OUT)763 aimbs_putle16(&fr->data, 0x03ea);764 else if(type & AIM_ICQ_STATE_BUSY)765 aimbs_putle16(&fr->data, 0x03e9);766 else if(type & AIM_ICQ_STATE_AWAY)767 aimbs_putle16(&fr->data, 0x03e8);768 769 aimbs_putle16(&fr->data, 0x0000); /* Status? */770 aimbs_putle16(&fr->data, 0x0001); /* Priority of this message? */771 aimbs_putle16(&fr->data, 0x0001); /* L? */772 aimbs_putle8(&fr->data, 0x00); /* Null termination? */773 } /* End TLV t(2711) */774 } /* End TLV t(0005) */775 776 /* TLV t(0003) */777 aimbs_put16(&fr->data, 0x0003);778 aimbs_put16(&fr->data, 0x0000);779 780 aim_tx_enqueue(sess, fr);781 782 return 0;783 }784 785 292 /** 786 293 * answers status message requests … … 989 496 mpm->numparts++; 990 497 991 return 0;992 }993 994 int aim_mpmsg_addraw(aim_session_t *sess, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, const guint8 *data, guint16 datalen)995 {996 guint8 *dup;997 998 if (!(dup = g_malloc(datalen)))999 return -1;1000 memcpy(dup, data, datalen);1001 1002 if (mpmsg_addsection(sess, mpm, charset, charsubset, dup, datalen) == -1) {1003 g_free(dup);1004 return -1;1005 }1006 1007 return 0;1008 }1009 1010 /* XXX should provide a way of saying ISO-8859-1 specifically */1011 int aim_mpmsg_addascii(aim_session_t *sess, aim_mpmsg_t *mpm, const char *ascii)1012 {1013 char *dup;1014 1015 if (!(dup = g_strdup(ascii)))1016 return -1;1017 1018 if (mpmsg_addsection(sess, mpm, 0x0000, 0x0000, (guint8 *)dup, (guint16) strlen(ascii)) == -1) {1019 g_free(dup);1020 return -1;1021 }1022 1023 return 0;1024 }1025 1026 int aim_mpmsg_addunicode(aim_session_t *sess, aim_mpmsg_t *mpm, const guint16 *unicode, guint16 unicodelen)1027 {1028 guint8 *buf;1029 aim_bstream_t bs;1030 int i;1031 1032 if (!(buf = g_malloc(unicodelen * 2)))1033 return -1;1034 1035 aim_bstream_init(&bs, buf, unicodelen * 2);1036 1037 /* We assume unicode is in /host/ byte order -- convert to network */1038 for (i = 0; i < unicodelen; i++)1039 aimbs_put16(&bs, unicode[i]);1040 1041 if (mpmsg_addsection(sess, mpm, 0x0002, 0x0000, buf, aim_bstream_curpos(&bs)) == -1) {1042 g_free(buf);1043 return -1;1044 }1045 1046 498 return 0; 1047 499 } … … 1727 1179 1728 1180 return ret; 1729 }1730 1731 /*1732 * Possible codes:1733 * AIM_TRANSFER_DENY_NOTSUPPORTED -- "client does not support"1734 * AIM_TRANSFER_DENY_DECLINE -- "client has declined transfer"1735 * AIM_TRANSFER_DENY_NOTACCEPTING -- "client is not accepting transfers"1736 *1737 */1738 int aim_denytransfer(aim_session_t *sess, const char *sender, const guint8 *cookie, guint16 code)1739 {1740 aim_conn_t *conn;1741 aim_frame_t *fr;1742 aim_snacid_t snacid;1743 aim_tlvlist_t *tl = NULL;1744 1745 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))1746 return -EINVAL;1747 1748 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sender)+6)))1749 return -ENOMEM;1750 1751 snacid = aim_cachesnac(sess, 0x0004, 0x000b, 0x0000, NULL, 0);1752 aim_putsnac(&fr->data, 0x0004, 0x000b, 0x0000, snacid);1753 1754 aimbs_putraw(&fr->data, cookie, 8);1755 1756 aimbs_put16(&fr->data, 0x0002); /* channel */1757 aimbs_put8(&fr->data, strlen(sender));1758 aimbs_putraw(&fr->data, (guint8 *)sender, strlen(sender));1759 1760 aim_addtlvtochain16(&tl, 0x0003, code);1761 aim_writetlvchain(&fr->data, &tl);1762 aim_freetlvchain(&tl);1763 1764 aim_tx_enqueue(sess, fr);1765 1766 return 0;1767 1181 } 1768 1182
Note: See TracChangeset
for help on using the changeset viewer.