Mercurial > pidgin
comparison src/protocols/oscar/im.c @ 2270:d82efea341ef
[gaim-migrate @ 2280]
new libfaim. stupid bugs.
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Wed, 12 Sep 2001 00:39:51 +0000 |
parents | 933346315b9b |
children | 7ec21662ffc2 |
comparison
equal
deleted
inserted
replaced
2269:7ff6170d84a0 | 2270:d82efea341ef |
---|---|
136 * in all of libfaim, it is written with performance in mind. As such, | 136 * in all of libfaim, it is written with performance in mind. As such, |
137 * it is not as clear as it could be in respect to how this message is | 137 * it is not as clear as it could be in respect to how this message is |
138 * supposed to be layed out. Most obviously, tlvlists should be used | 138 * supposed to be layed out. Most obviously, tlvlists should be used |
139 * instead of writing out the bytes manually. | 139 * instead of writing out the bytes manually. |
140 * | 140 * |
141 * XXX support multipart | 141 * XXX more precise verification that we never send SNACs larger than 8192 |
142 * XXX check SNAC size for multipart | |
142 * | 143 * |
143 */ | 144 */ |
144 faim_export int aim_send_im_ext(aim_session_t *sess, aim_conn_t *conn, struct aim_sendimext_args *args) | 145 faim_export int aim_send_im_ext(aim_session_t *sess, aim_conn_t *conn, struct aim_sendimext_args *args) |
145 { | 146 { |
146 static const fu8_t deffeatures[] = { | 147 static const fu8_t deffeatures[] = { |
151 aim_snacid_t snacid; | 152 aim_snacid_t snacid; |
152 | 153 |
153 if (!sess || !conn || !args) | 154 if (!sess || !conn || !args) |
154 return -EINVAL; | 155 return -EINVAL; |
155 | 156 |
156 if (!args->msg || (args->msglen <= 0)) | 157 if (args->flags & AIM_IMFLAGS_MULTIPART) { |
157 return -EINVAL; | 158 if (args->mpmsg->numparts <= 0) |
158 | 159 return -EINVAL; |
159 if (args->msglen >= MAXMSGLEN) | 160 } else { |
160 return -E2BIG; | 161 if (!args->msg || (args->msglen <= 0)) |
161 | 162 return -EINVAL; |
162 msgtlvlen = 12 + args->msglen; | 163 |
164 if (args->msglen >= MAXMSGLEN) | |
165 return -E2BIG; | |
166 } | |
167 | |
168 /* Painfully calculate the size of the message TLV */ | |
169 msgtlvlen = 1 + 1; /* 0501 */ | |
170 | |
163 if (args->flags & AIM_IMFLAGS_CUSTOMFEATURES) | 171 if (args->flags & AIM_IMFLAGS_CUSTOMFEATURES) |
164 msgtlvlen += args->featureslen; | 172 msgtlvlen += 2 + args->featureslen; |
165 else | 173 else |
166 msgtlvlen += sizeof(deffeatures); | 174 msgtlvlen += 2 + sizeof(deffeatures); |
167 | 175 |
168 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, args->msglen+512))) | 176 if (args->flags & AIM_IMFLAGS_MULTIPART) { |
177 aim_mpmsg_section_t *sec; | |
178 | |
179 for (sec = args->mpmsg->parts; sec; sec = sec->next) { | |
180 msgtlvlen += 2 /* 0101 */ + 2 /* block len */; | |
181 msgtlvlen += 4 /* charset */ + sec->datalen; | |
182 } | |
183 | |
184 } else { | |
185 msgtlvlen += 2 /* 0101 */ + 2 /* block len */; | |
186 msgtlvlen += 4 /* charset */ + args->msglen; | |
187 } | |
188 | |
189 | |
190 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, msgtlvlen+128))) | |
169 return -ENOMEM; | 191 return -ENOMEM; |
170 | 192 |
171 /* XXX should be optional */ | 193 /* XXX should be optional */ |
172 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, args->destsn, strlen(args->destsn)+1); | 194 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, args->destsn, strlen(args->destsn)+1); |
173 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); | 195 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); |
214 } else { | 236 } else { |
215 aimbs_put16(&fr->data, sizeof(deffeatures)); | 237 aimbs_put16(&fr->data, sizeof(deffeatures)); |
216 aimbs_putraw(&fr->data, deffeatures, sizeof(deffeatures)); | 238 aimbs_putraw(&fr->data, deffeatures, sizeof(deffeatures)); |
217 } | 239 } |
218 | 240 |
219 aimbs_put16(&fr->data, 0x0101); | 241 if (args->flags & AIM_IMFLAGS_MULTIPART) { |
220 | 242 aim_mpmsg_section_t *sec; |
221 /* | 243 |
222 * Message block length. | 244 for (sec = args->mpmsg->parts; sec; sec = sec->next) { |
223 */ | 245 aimbs_put16(&fr->data, 0x0101); |
224 aimbs_put16(&fr->data, args->msglen + 0x04); | 246 aimbs_put16(&fr->data, sec->datalen + 4); |
225 | 247 aimbs_put16(&fr->data, sec->charset); |
226 /* | 248 aimbs_put16(&fr->data, sec->charsubset); |
227 * Character set. | 249 aimbs_putraw(&fr->data, sec->data, sec->datalen); |
228 */ | 250 } |
229 if (args->flags & AIM_IMFLAGS_UNICODE) | 251 |
230 aimbs_put16(&fr->data, 0x0002); | 252 } else { |
231 else if (args->flags & AIM_IMFLAGS_ISO_8859_1) | 253 |
232 aimbs_put16(&fr->data, 0x0003); | 254 aimbs_put16(&fr->data, 0x0101); |
233 else | 255 |
234 aimbs_put16(&fr->data, 0x0000); | 256 /* |
235 | 257 * Message block length. |
236 aimbs_put16(&fr->data, 0x0000); | 258 */ |
237 | 259 aimbs_put16(&fr->data, args->msglen + 0x04); |
238 /* | 260 |
239 * Message. Not terminated. | 261 /* |
240 */ | 262 * Character set. |
241 aimbs_putraw(&fr->data, args->msg, args->msglen); | 263 */ |
264 if (args->flags & AIM_IMFLAGS_CUSTOMCHARSET) { | |
265 | |
266 aimbs_put16(&fr->data, args->charset); | |
267 aimbs_put16(&fr->data, args->charsubset); | |
268 | |
269 } else { | |
270 if (args->flags & AIM_IMFLAGS_UNICODE) | |
271 aimbs_put16(&fr->data, 0x0002); | |
272 else if (args->flags & AIM_IMFLAGS_ISO_8859_1) | |
273 aimbs_put16(&fr->data, 0x0003); | |
274 else | |
275 aimbs_put16(&fr->data, 0x0000); | |
276 | |
277 aimbs_put16(&fr->data, 0x0000); | |
278 } | |
279 | |
280 /* | |
281 * Message. Not terminated. | |
282 */ | |
283 aimbs_putraw(&fr->data, args->msg, args->msglen); | |
284 } | |
242 | 285 |
243 /* | 286 /* |
244 * Set the Request Acknowledge flag. | 287 * Set the Request Acknowledge flag. |
245 */ | 288 */ |
246 if (args->flags & AIM_IMFLAGS_ACK) { | 289 if (args->flags & AIM_IMFLAGS_ACK) { |
302 args.flags = flags; | 345 args.flags = flags; |
303 args.msg = msg; | 346 args.msg = msg; |
304 args.msglen = strlen(msg); | 347 args.msglen = strlen(msg); |
305 | 348 |
306 /* Make these don't get set by accident -- they need aim_send_im_ext */ | 349 /* Make these don't get set by accident -- they need aim_send_im_ext */ |
307 args.flags &= ~(AIM_IMFLAGS_CUSTOMFEATURES | AIM_IMFLAGS_HASICON); | 350 args.flags &= ~(AIM_IMFLAGS_CUSTOMFEATURES | AIM_IMFLAGS_HASICON | AIM_IMFLAGS_MULTIPART); |
308 | 351 |
309 return aim_send_im_ext(sess, conn, &args); | 352 return aim_send_im_ext(sess, conn, &args); |
310 } | 353 } |
311 | 354 |
312 /* | 355 /* |
313 * This is also performance sensative. (If you can believe it...) | 356 * This is also performance sensitive. (If you can believe it...) |
314 * | 357 * |
315 */ | 358 */ |
316 faim_export int aim_send_icon(aim_session_t *sess, aim_conn_t *conn, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu32_t iconsum) | 359 faim_export int aim_send_icon(aim_session_t *sess, aim_conn_t *conn, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu32_t iconsum) |
317 { | 360 { |
318 int i; | 361 int i; |
452 | 495 |
453 free(sn); | 496 free(sn); |
454 aim_freetlvchain(&tlvlist); | 497 aim_freetlvchain(&tlvlist); |
455 | 498 |
456 return ret; | 499 return ret; |
500 } | |
501 | |
502 /* | |
503 * Ahh, the joys of nearly ridiculous over-engineering. | |
504 * | |
505 * Not only do AIM ICBM's support multiple channels. Not only do they | |
506 * support multiple character sets. But they support multiple character | |
507 * sets / encodings within the same ICBM. | |
508 * | |
509 * These multipart messages allow for complex space savings techniques, which | |
510 * seem utterly unnecessary by today's standards. In fact, there is only | |
511 * one client still in popular use that still uses this method: AOL for the | |
512 * Macintosh, Version 5.0. Obscure, yes, I know. | |
513 * | |
514 * In modern (non-"legacy") clients, if the user tries to send a character | |
515 * that is not ISO-8859-1 or ASCII, the client will send the entire message | |
516 * as UNICODE, meaning that every character in the message will occupy the | |
517 * full 16 bit UNICODE field, even if the high order byte would be zero. | |
518 * Multipart messages prevent this wasted space by allowing the client to | |
519 * only send the characters in UNICODE that need to be sent that way, and | |
520 * the rest of the message can be sent in whatever the native character | |
521 * set is (probably ASCII). | |
522 * | |
523 * An important note is that sections will be displayed in the order that | |
524 * they appear in the ICBM. There is no facility for merging or rearranging | |
525 * sections at run time. So if you have, say, ASCII then UNICODE then ASCII, | |
526 * you must supply two ASCII sections with a UNICODE in the middle, and incur | |
527 * the associated overhead. | |
528 * | |
529 * Normally I would have laughed and given a firm 'no' to supporting this | |
530 * seldom-used feature, but something is attracting me to it. In the future, | |
531 * it may be possible to abuse this to send mixed-media messages to other | |
532 * open source clients (like encryption or something) -- see faimtest for | |
533 * examples of how to do this. | |
534 * | |
535 * I would definitly recommend avoiding this feature unless you really | |
536 * know what you are doing, and/or you have something neat to do with it. | |
537 * | |
538 */ | |
539 faim_export int aim_mpmsg_init(aim_session_t *sess, aim_mpmsg_t *mpm) | |
540 { | |
541 | |
542 memset(mpm, 0, sizeof(aim_mpmsg_t)); | |
543 | |
544 return 0; | |
545 } | |
546 | |
547 static int mpmsg_addsection(aim_session_t *sess, aim_mpmsg_t *mpm, fu16_t charset, fu16_t charsubset, fu8_t *data, fu16_t datalen) | |
548 { | |
549 aim_mpmsg_section_t *sec; | |
550 | |
551 if (!(sec = malloc(sizeof(aim_mpmsg_section_t)))) | |
552 return -1; | |
553 | |
554 sec->charset = charset; | |
555 sec->charsubset = charsubset; | |
556 sec->data = data; | |
557 sec->datalen = datalen; | |
558 sec->next = NULL; | |
559 | |
560 if (!mpm->parts) | |
561 mpm->parts = sec; | |
562 else { | |
563 aim_mpmsg_section_t *cur; | |
564 | |
565 for (cur = mpm->parts; cur->next; cur = cur->next) | |
566 ; | |
567 cur->next = sec; | |
568 } | |
569 | |
570 mpm->numparts++; | |
571 | |
572 return 0; | |
573 } | |
574 | |
575 faim_export int aim_mpmsg_addraw(aim_session_t *sess, aim_mpmsg_t *mpm, fu16_t charset, fu16_t charsubset, const fu8_t *data, fu16_t datalen) | |
576 { | |
577 fu8_t *dup; | |
578 | |
579 if (!(dup = malloc(datalen))) | |
580 return -1; | |
581 memcpy(dup, data, datalen); | |
582 | |
583 if (mpmsg_addsection(sess, mpm, charset, charsubset, dup, datalen) == -1) { | |
584 free(dup); | |
585 return -1; | |
586 } | |
587 | |
588 return 0; | |
589 } | |
590 | |
591 /* XXX should provide a way of saying ISO-8859-1 specifically */ | |
592 faim_export int aim_mpmsg_addascii(aim_session_t *sess, aim_mpmsg_t *mpm, const char *ascii) | |
593 { | |
594 fu8_t *dup; | |
595 | |
596 if (!(dup = strdup(ascii))) | |
597 return -1; | |
598 | |
599 if (mpmsg_addsection(sess, mpm, 0x0000, 0x0000, dup, strlen(ascii)) == -1) { | |
600 free(dup); | |
601 return -1; | |
602 } | |
603 | |
604 return 0; | |
605 } | |
606 | |
607 faim_export int aim_mpmsg_addunicode(aim_session_t *sess, aim_mpmsg_t *mpm, const fu16_t *unicode, fu16_t unicodelen) | |
608 { | |
609 fu8_t *buf; | |
610 aim_bstream_t bs; | |
611 int i; | |
612 | |
613 if (!(buf = malloc(unicodelen * 2))) | |
614 return -1; | |
615 | |
616 aim_bstream_init(&bs, buf, unicodelen * 2); | |
617 | |
618 /* We assume unicode is in /host/ byte order -- convert to network */ | |
619 for (i = 0; i < unicodelen; i++) | |
620 aimbs_put16(&bs, unicode[i]); | |
621 | |
622 if (mpmsg_addsection(sess, mpm, 0x0002, 0x0000, buf, aim_bstream_curpos(&bs)) == -1) { | |
623 free(buf); | |
624 return -1; | |
625 } | |
626 | |
627 return 0; | |
628 } | |
629 | |
630 faim_export void aim_mpmsg_free(aim_session_t *sess, aim_mpmsg_t *mpm) | |
631 { | |
632 aim_mpmsg_section_t *cur; | |
633 | |
634 for (cur = mpm->parts; cur; ) { | |
635 aim_mpmsg_section_t *tmp; | |
636 | |
637 tmp = cur->next; | |
638 free(cur->data); | |
639 free(cur); | |
640 cur = tmp; | |
641 } | |
642 | |
643 mpm->numparts = 0; | |
644 mpm->parts = NULL; | |
645 | |
646 return; | |
647 } | |
648 | |
649 /* | |
650 * Start by building the multipart structures, then pick the first | |
651 * human-readable section and stuff it into args->msg so no one gets | |
652 * suspicious. | |
653 * | |
654 */ | |
655 static int incomingim_ch1_parsemsgs(aim_session_t *sess, fu8_t *data, int len, struct aim_incomingim_ch1_args *args) | |
656 { | |
657 static const fu16_t charsetpri[] = { | |
658 0x0000, /* ASCII first */ | |
659 0x0003, /* then ISO-8859-1 */ | |
660 0x0002, /* UNICODE as last resort */ | |
661 }; | |
662 static const int charsetpricount = 3; | |
663 int i; | |
664 aim_bstream_t mbs; | |
665 aim_mpmsg_section_t *sec; | |
666 | |
667 aim_bstream_init(&mbs, data, len); | |
668 | |
669 while (aim_bstream_empty(&mbs)) { | |
670 fu16_t msglen, flag1, flag2; | |
671 fu8_t *msgbuf; | |
672 | |
673 aimbs_get8(&mbs); /* 01 */ | |
674 aimbs_get8(&mbs); /* 01 */ | |
675 | |
676 /* Message string length, including character set info. */ | |
677 msglen = aimbs_get16(&mbs); | |
678 | |
679 /* Character set info */ | |
680 flag1 = aimbs_get16(&mbs); | |
681 flag2 = aimbs_get16(&mbs); | |
682 | |
683 /* Message. */ | |
684 msglen -= 4; | |
685 | |
686 /* | |
687 * For now, we don't care what the encoding is. Just copy | |
688 * it into a multipart struct and deal with it later. However, | |
689 * always pad the ending with a NULL. This makes it easier | |
690 * to treat ASCII sections as strings. It won't matter for | |
691 * UNICODE or binary data, as you should never read past | |
692 * the specified data length, which will not include the pad. | |
693 * | |
694 * XXX There's an API bug here. For sending, the UNICODE is | |
695 * given in host byte order (aim_mpmsg_addunicode), but here | |
696 * the received messages are given in network byte order. | |
697 * | |
698 */ | |
699 msgbuf = aimbs_getstr(&mbs, msglen); | |
700 mpmsg_addsection(sess, &args->mpmsg, flag1, flag2, msgbuf, msglen); | |
701 | |
702 } /* while */ | |
703 | |
704 args->icbmflags |= AIM_IMFLAGS_MULTIPART; /* always set */ | |
705 | |
706 /* | |
707 * Clients that support multiparts should never use args->msg, as it | |
708 * will point to an arbitrary section. | |
709 * | |
710 * Here, we attempt to provide clients that do not support multipart | |
711 * messages with something to look at -- hopefully a human-readable | |
712 * string. But, failing that, a UNICODE message, or nothing at all. | |
713 * | |
714 * Which means that even if args->msg is NULL, it does not mean the | |
715 * message was blank. | |
716 * | |
717 */ | |
718 for (i = 0; i < charsetpricount; i++) { | |
719 for (sec = args->mpmsg.parts; sec; sec = sec->next) { | |
720 | |
721 if (sec->charset != charsetpri[i]) | |
722 continue; | |
723 | |
724 /* Great. We found one. Fill it in. */ | |
725 args->charset = sec->charset; | |
726 args->charsubset = sec->charsubset; | |
727 args->icbmflags |= AIM_IMFLAGS_CUSTOMCHARSET; | |
728 | |
729 /* Set up the simple flags */ | |
730 if (args->charset == 0x0000) | |
731 ; /* ASCII */ | |
732 else if (args->charset == 0x0002) | |
733 args->icbmflags |= AIM_IMFLAGS_UNICODE; | |
734 else if (args->charset == 0x0003) | |
735 args->icbmflags |= AIM_IMFLAGS_ISO_8859_1; | |
736 else if (args->charset == 0xffff) | |
737 ; /* no encoding (yeep!) */ | |
738 | |
739 if (args->charsubset == 0x0000) | |
740 ; /* standard subencoding? */ | |
741 else if (args->charsubset == 0x000b) | |
742 args->icbmflags |= AIM_IMFLAGS_SUBENC_MACINTOSH; | |
743 else if (args->charsubset == 0xffff) | |
744 ; /* no subencoding */ | |
745 #if 0 | |
746 /* XXX this isn't really necesary... */ | |
747 if ( ((args.flag1 != 0x0000) && | |
748 (args.flag1 != 0x0002) && | |
749 (args.flag1 != 0x0003) && | |
750 (args.flag1 != 0xffff)) || | |
751 ((args.flag2 != 0x0000) && | |
752 (args.flag2 != 0x000b) && | |
753 (args.flag2 != 0xffff))) { | |
754 faimdprintf(sess, 0, "icbm: **warning: encoding flags are being used! {%04x, %04x}\n", args.flag1, args.flag2); | |
755 } | |
756 #endif | |
757 | |
758 args->msg = sec->data; | |
759 args->msglen = sec->datalen; | |
760 | |
761 return 0; | |
762 } | |
763 } | |
764 | |
765 /* No human-readable sections found. Oh well. */ | |
766 args->charset = args->charsubset = 0xffff; | |
767 args->msg = NULL; | |
768 args->msglen = 0; | |
769 | |
770 return 0; | |
457 } | 771 } |
458 | 772 |
459 /* | 773 /* |
460 * | 774 * |
461 * This should use tlvlists, but doesn't for performance reasons. | 775 * This should use tlvlists, but doesn't for performance reasons. |
488 struct aim_incomingim_ch1_args args; | 802 struct aim_incomingim_ch1_args args; |
489 int endpos; | 803 int endpos; |
490 | 804 |
491 memset(&args, 0, sizeof(args)); | 805 memset(&args, 0, sizeof(args)); |
492 | 806 |
807 aim_mpmsg_init(sess, &args.mpmsg); | |
808 | |
493 /* | 809 /* |
494 * This used to be done using tlvchains. For performance reasons, | 810 * This used to be done using tlvchains. For performance reasons, |
495 * I've changed it to process the TLVs in-place. This avoids lots | 811 * I've changed it to process the TLVs in-place. This avoids lots |
496 * of per-IM memory allocations. | 812 * of per-IM memory allocations. |
497 */ | 813 */ |
520 /* XXX XXX this is all evil! */ | 836 /* XXX XXX this is all evil! */ |
521 args.features = bs->data + bs->offset; | 837 args.features = bs->data + bs->offset; |
522 aim_bstream_advance(bs, args.featureslen); | 838 aim_bstream_advance(bs, args.featureslen); |
523 args.icbmflags |= AIM_IMFLAGS_CUSTOMFEATURES; | 839 args.icbmflags |= AIM_IMFLAGS_CUSTOMFEATURES; |
524 | 840 |
525 aimbs_get8(bs); /* 01 */ | 841 /* |
526 aimbs_get8(bs); /* 01 */ | 842 * The rest of the TLV contains one or more message |
527 | 843 * blocks... |
528 /* Message string length, including flag words. */ | 844 */ |
529 args.msglen = aimbs_get16(bs); | 845 incomingim_ch1_parsemsgs(sess, bs->data + bs->offset /* XXX evil!!! */, length - 2 - 2 - args.featureslen, &args); |
530 | |
531 /* Flag words. */ | |
532 args.flag1 = aimbs_get16(bs); | |
533 if (args.flag1 == 0x0000) | |
534 ; /* ASCII */ | |
535 else if (args.flag1 == 0x0002) | |
536 args.icbmflags |= AIM_IMFLAGS_UNICODE; | |
537 else if (args.flag1 == 0x0003) | |
538 args.icbmflags |= AIM_IMFLAGS_ISO_8859_1; | |
539 else if (args.flag1 == 0xffff) | |
540 ; /* no encoding (yeep!) */ | |
541 | |
542 args.flag2 = aimbs_get16(bs); | |
543 if (args.flag2 == 0x0000) | |
544 ; /* standard subencoding? */ | |
545 else if (args.flag2 == 0x000b) | |
546 args.icbmflags |= AIM_IMFLAGS_SUBENC_MACINTOSH; | |
547 else if (args.flag2 == 0xffff) | |
548 ; /* no subencoding */ | |
549 | |
550 /* XXX this isn't really necesary... */ | |
551 if ( ((args.flag1 != 0x0000) && | |
552 (args.flag1 != 0x0002) && | |
553 (args.flag1 != 0x0003) && | |
554 (args.flag1 != 0xffff)) || | |
555 ((args.flag2 != 0x0000) && | |
556 (args.flag2 != 0x000b) && | |
557 (args.flag2 != 0xffff))) { | |
558 faimdprintf(sess, 0, "icbm: **warning: encoding flags are being used! {%04x, %04x}\n", args.flag1, args.flag2); | |
559 } | |
560 | |
561 /* Message. */ | |
562 args.msglen -= 4; | |
563 if (args.icbmflags & AIM_IMFLAGS_UNICODE) { | |
564 fu8_t *umsg; | |
565 | |
566 /* Can't use getstr because of wide null */ | |
567 umsg = aimbs_getraw(bs, args.msglen); | |
568 args.msg = malloc(args.msglen+2); | |
569 memcpy(args.msg, umsg, args.msglen); | |
570 args.msg[args.msglen] = '\0'; /* wide NULL */ | |
571 args.msg[args.msglen+1] = '\0'; | |
572 | |
573 free(umsg); | |
574 | |
575 } else | |
576 args.msg = aimbs_getstr(bs, args.msglen); | |
577 | 846 |
578 } else if (type == 0x0003) { /* Server Ack Requested */ | 847 } else if (type == 0x0003) { /* Server Ack Requested */ |
579 | 848 |
580 args.icbmflags |= AIM_IMFLAGS_ACK; | 849 args.icbmflags |= AIM_IMFLAGS_ACK; |
581 | 850 |
616 | 885 |
617 | 886 |
618 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | 887 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) |
619 ret = userfunc(sess, rx, channel, userinfo, &args); | 888 ret = userfunc(sess, rx, channel, userinfo, &args); |
620 | 889 |
890 aim_mpmsg_free(sess, &args.mpmsg); | |
621 free(args.extdata); | 891 free(args.extdata); |
622 free(args.msg); | |
623 | 892 |
624 return ret; | 893 return ret; |
625 } | 894 } |
626 | 895 |
627 static int incomingim_ch2_buddylist(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, struct aim_userinfo_s *userinfo, struct aim_incomingim_ch2_args *args, aim_tlvlist_t *list2) | 896 static int incomingim_ch2_buddylist(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, struct aim_userinfo_s *userinfo, struct aim_incomingim_ch2_args *args, aim_tlvlist_t *list2) |
728 faimdprintf(sess, 0, "ERROR caching message cookie\n"); | 997 faimdprintf(sess, 0, "ERROR caching message cookie\n"); |
729 | 998 |
730 /* XXX: implement all this */ | 999 /* XXX: implement all this */ |
731 | 1000 |
732 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | 1001 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) |
733 ret = userfunc(sess, rx, 0x0002, userinfo, &args); | 1002 ret = userfunc(sess, rx, 0x0002, userinfo, args); |
734 | 1003 |
735 return ret; | 1004 return ret; |
736 } | 1005 } |
737 | 1006 |
738 static int incomingim_ch2_chat(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, struct aim_userinfo_s *userinfo, struct aim_incomingim_ch2_args *args, aim_tlvlist_t *list2) | 1007 static int incomingim_ch2_chat(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, struct aim_userinfo_s *userinfo, struct aim_incomingim_ch2_args *args, aim_tlvlist_t *list2) |
755 | 1024 |
756 if (aim_gettlv(list2, 0x000e, 1)) | 1025 if (aim_gettlv(list2, 0x000e, 1)) |
757 args->info.chat.lang = aim_gettlv_str(list2, 0x000e, 1); | 1026 args->info.chat.lang = aim_gettlv_str(list2, 0x000e, 1); |
758 | 1027 |
759 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | 1028 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) |
760 ret = userfunc(sess, rx, 0x0002, userinfo, &args); | 1029 ret = userfunc(sess, rx, 0x0002, userinfo, args); |
761 | 1030 |
762 /* XXX free_roominfo */ | 1031 /* XXX free_roominfo */ |
763 free(args->info.chat.roominfo.name); | 1032 free(args->info.chat.roominfo.name); |
764 free(args->info.chat.msg); | 1033 free(args->info.chat.msg); |
765 free(args->info.chat.encoding); | 1034 free(args->info.chat.encoding); |
806 | 1075 |
807 args->info.getfile.ip = ip; | 1076 args->info.getfile.ip = ip; |
808 memcpy(args->info.getfile.cookie, args->cookie, 8); | 1077 memcpy(args->info.getfile.cookie, args->cookie, 8); |
809 | 1078 |
810 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | 1079 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) |
811 ret = userfunc(sess, rx, 0x0002, userinfo, &args); | 1080 ret = userfunc(sess, rx, 0x0002, userinfo, args); |
812 | 1081 |
813 return ret; | 1082 return ret; |
814 } | 1083 } |
815 | 1084 |
816 static int incomingim_ch2_sendfile(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, struct aim_userinfo_s *userinfo, struct aim_incomingim_ch2_args *args, aim_tlvlist_t *list2) | 1085 static int incomingim_ch2_sendfile(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, struct aim_userinfo_s *userinfo, struct aim_incomingim_ch2_args *args, aim_tlvlist_t *list2) |