comparison src/protocols/oscar/oscar.c @ 4656:e557a10a9541

[gaim-migrate @ 4967] This works pretty reliably between gaim and Winaim. It seems to work ok between 2 gaim clients. Anyway, I figure this is better than nothing. Oh, by the way, this is "send file" support for AIM over oscar. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Fri, 07 Mar 2003 03:49:48 +0000
parents 0f8717733f33
children 745f583372cd
comparison
equal deleted inserted replaced
4655:fac4c73dd5ad 4656:e557a10a9541
178 }; 178 };
179 179
180 /* BBB */ 180 /* BBB */
181 struct oscar_xfer_data { 181 struct oscar_xfer_data {
182 fu8_t cookie[8]; 182 fu8_t cookie[8];
183 char *clientip; 183 gchar *clientip;
184 char *clientip2; 184 gchar *clientip2;
185 fu32_t modtime; 185 fu32_t modtime;
186 fu32_t checksum; 186 fu32_t checksum;
187 aim_conn_t *conn; 187 aim_conn_t *conn;
188 struct gaim_xfer *xfer; 188 struct gaim_xfer *xfer;
189 struct gaim_connection *gc; 189 struct gaim_connection *gc;
281 } 281 }
282 282
283 return c; 283 return c;
284 } 284 }
285 285
286 /* XXX - I really don't like forward declarations */ 286 /* All the libfaim->gaim callback functions */
287 static void oscar_callback(gpointer data, gint source, GaimInputCondition condition);
288
289 /* BBB */
290 /*
291 * This little area in oscar.c is the nexus of file transfer code,
292 * so I wrote a little explanation of what happens. I am such a
293 * ninja.
294 *
295 * The series of events for a file send is:
296 * -Create xfer and call gaim_xfer_request (this happens in oscar_ask_sendfile)
297 * -User chooses a file and oscar_xfer_init is called. It establishs a
298 * listening socket, then asks the remote user to connect to us (and
299 * gives them the file name, port, IP, etc.)
300 * -They connect to us and we send them an AIM_CB_OFT_PROMPT (this happens
301 * in oscar_sendfile_established)
302 * -They send us an AIM_CB_OFT_ACK and then we start sending data
303 * -When we finish, they send us an AIM_CB_OFT_DONE and they close the
304 * connection.
305 * -We get drunk because file transfer kicks ass.
306 *
307 * The series of events for a file receive is:
308 * -Create xfer and call gaim_xfer request (this happens in incomingim_chan2)
309 * -Gaim user selects file to name and location to save file to and
310 * oscar_xfer_init is called
311 * -It connects to the remote user using the IP they gave us earlier
312 * -After connecting, they send us an AIM_CB_OFT_PROMPT. In reply, we send
313 * them an AIM_CB_OFT_ACK.
314 * -They begin to send us lots of raw data.
315 * -When they finish sending data we send an AIM_CB_OFT_DONE and then close
316 * the connectionn.
317 */
318 static void oscar_sendfile_connected(gpointer data, gint source, GaimInputCondition condition);
319 static int oscar_sendfile_established(aim_session_t *, aim_frame_t *, ...);
320 static int oscar_sendfile_prompt(aim_session_t *, aim_frame_t *, ...);
321 static int oscar_sendfile_ack(aim_session_t *, aim_frame_t *, ...);
322 static int oscar_sendfile_done(aim_session_t *, aim_frame_t *, ...);
323
324 /* XXX - This function is pretty ugly */
325 static void
326 oscar_xfer_init(struct gaim_xfer *xfer)
327 {
328 struct gaim_connection *gc;
329 struct oscar_data *od;
330 struct oscar_xfer_data *xfer_data;
331 debug_printf("in oscar_xfer_init\n");
332
333 if (!(xfer_data = xfer->data))
334 return;
335 if (!(gc = xfer_data->gc))
336 return;
337 if (!(od = gc->proto_data))
338 return;
339
340 if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) {
341 int i;
342 char ip[4];
343 gchar **ipsplit;
344
345 if (xfer->local_ip) {
346 ipsplit = g_strsplit(xfer->local_ip, ".", 4);
347 for (i=0; ipsplit[i]; i++)
348 ip[i] = atoi(ipsplit[i]);
349 g_strfreev(ipsplit);
350 } else {
351 memset(ip, 0x00, 4);
352 }
353
354 xfer->filename = g_path_get_basename(xfer->local_filename);
355 xfer_data->checksum = aim_oft_checksum_file(xfer->local_filename);
356
357 /*
358 * Try a few random ports. Maybe we need a
359 * way to tell libfaim to listen for multiple
360 * connections on one listener socket.
361 */
362 xfer_data->conn = aim_sendfile_listen(od->sess, xfer_data->cookie, ip, xfer->local_port);
363 for (i=0; (i<5 && !xfer_data->conn); i++) {
364 xfer->local_port = (rand() % (65535-1024)) + 1024;
365 xfer_data->conn = aim_sendfile_listen(od->sess, xfer_data->cookie, ip, xfer->local_port);
366 }
367 if (xfer_data->conn) {
368 xfer->watcher = gaim_input_add(xfer_data->conn->fd, GAIM_INPUT_READ, oscar_callback, xfer_data->conn);
369 aim_im_sendch2_sendfile_ask(od->sess, xfer_data->cookie, xfer->who, ip, xfer->local_port, xfer->filename, 1, xfer->size);
370 aim_conn_addhandler(od->sess, xfer_data->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_ESTABLISHED, oscar_sendfile_established, 0);
371 } else {
372 do_error_dialog(_("File Transfer Aborted"), _("Unable to establish listener socket."), GAIM_ERROR);
373 /* XXX - The below line causes a crash because the transfer is canceled before the "Ok" callback on the file selection thing exists, I think */
374 /* gaim_xfer_cancel(xfer); */
375 }
376 } else if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) {
377 xfer_data->conn = aim_newconn(od->sess, AIM_CONN_TYPE_RENDEZVOUS, NULL);
378 if (xfer_data->conn) {
379 xfer_data->conn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE;
380 aim_conn_addhandler(od->sess, xfer_data->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_PROMPT, oscar_sendfile_prompt, 0);
381 xfer_data->conn->fd = xfer->fd = proxy_connect(gc->account, xfer->remote_ip, xfer->remote_port, oscar_sendfile_connected, xfer);
382 if (xfer->fd == -1) {
383 do_error_dialog(_("File Transfer Aborted"), _("Unable to establish file descriptor."), GAIM_ERROR);
384 /* gaim_xfer_cancel? */
385 }
386 } else {
387 do_error_dialog(_("File Transfer Aborted"), _("Unable to create new connection."), GAIM_ERROR);
388 /* gaim_xfer_cancel? */
389 /* Try a different port? Ask them to connect to us? */
390 }
391
392 }
393 }
394
395 static void
396 oscar_xfer_start(struct gaim_xfer *xfer)
397 {
398 /* struct gaim_connection *gc;
399 struct oscar_data *od;
400 struct oscar_xfer_data *xfer_data;
401
402 if (!(xfer_data = xfer->data))
403 return;
404 if (!(gc = xfer_data->gc))
405 return;
406 if (!(od = gc->proto_data))
407 return;
408
409 od = xfer_data->od;
410 */
411 debug_printf("AAA - in oscar_xfer_start\n");
412
413 /* I'm pretty sure we don't need to do jack here. Nor Jill. */
414 }
415
416 static void
417 oscar_xfer_end(struct gaim_xfer *xfer)
418 {
419 struct gaim_connection *gc;
420 struct oscar_data *od;
421 struct oscar_xfer_data *xfer_data;
422 debug_printf("AAA - in oscar_xfer_end\n");
423
424 if (!(xfer_data = xfer->data))
425 return;
426
427 if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE)
428 aim_oft_sendheader(xfer_data->conn->sessv, xfer_data->conn, AIM_CB_OFT_DONE, xfer_data->cookie, xfer->filename, 1, 1, xfer->size, xfer->size, xfer_data->modtime, xfer_data->checksum, 0x02, xfer->size, xfer_data->checksum);
429
430 if ((gc = xfer_data->gc)) {
431 if ((od = gc->proto_data))
432 od->file_transfers = g_slist_remove(od->file_transfers, xfer);
433 }
434
435 g_free(xfer_data);
436 xfer->data = NULL;
437 }
438
439 static void
440 oscar_xfer_cancel(struct gaim_xfer *xfer)
441 {
442 struct gaim_connection *gc;
443 struct oscar_data *od;
444 struct oscar_xfer_data *xfer_data;
445 aim_conn_t *conn;
446 debug_printf("AAA - in oscar_xfer_cancel\n");
447
448 if (!(xfer_data = xfer->data))
449 return;
450
451 if ((conn = xfer_data->conn)) {
452 aim_session_t *sess;
453 if ((sess = conn->sessv))
454 if (xfer_data->cookie && xfer->who)
455 aim_im_sendch2_sendfile_cancel(sess, xfer_data->cookie, xfer->who, AIM_CAPS_SENDFILE);
456 }
457
458 if ((gc = xfer_data->gc))
459 if ((od = gc->proto_data))
460 od->file_transfers = g_slist_remove(od->file_transfers, xfer);
461
462 g_free(xfer_data);
463 xfer->data = NULL;
464 }
465
466 static void
467 oscar_xfer_ack(struct gaim_xfer *xfer, const char *buffer, size_t size)
468 {
469 struct oscar_xfer_data *xfer_data;
470
471 if (!(xfer_data = xfer->data))
472 return;
473
474 /* xfer_data->checksum = aim_oft_checksum_chunk(buffer, size, xfer_data->checksum); */
475 }
476
477 static struct gaim_xfer *
478 oscar_find_xfer_by_cookie(GSList *fts, const char *ck)
479 {
480 struct gaim_xfer *xfer;
481 struct oscar_xfer_data *data;
482
483 while (fts) {
484 xfer = fts->data;
485 data = xfer->data;
486
487 if (data && !strcmp(data->cookie, ck))
488 return xfer;
489
490 fts = g_slist_next(fts);
491 }
492
493 return NULL;
494 }
495
496 static struct gaim_xfer *
497 oscar_find_xfer_by_conn(GSList *fts, aim_conn_t *conn)
498 {
499 struct gaim_xfer *xfer;
500 struct oscar_xfer_data *data;
501
502 while (fts) {
503 xfer = fts->data;
504 data = xfer->data;
505
506 if (data && (conn == data->conn))
507 return xfer;
508
509 fts = g_slist_next(fts);
510 }
511
512 return NULL;
513 }
514
515 static int gaim_parse_auth_resp (aim_session_t *, aim_frame_t *, ...); 287 static int gaim_parse_auth_resp (aim_session_t *, aim_frame_t *, ...);
516 static int gaim_parse_login (aim_session_t *, aim_frame_t *, ...); 288 static int gaim_parse_login (aim_session_t *, aim_frame_t *, ...);
517 static int gaim_handle_redirect (aim_session_t *, aim_frame_t *, ...); 289 static int gaim_handle_redirect (aim_session_t *, aim_frame_t *, ...);
518 static int gaim_info_change (aim_session_t *, aim_frame_t *, ...); 290 static int gaim_info_change (aim_session_t *, aim_frame_t *, ...);
519 static int gaim_account_confirm (aim_session_t *, aim_frame_t *, ...); 291 static int gaim_account_confirm (aim_session_t *, aim_frame_t *, ...);
564 static int gaim_ssi_authrequest (aim_session_t *, aim_frame_t *, ...); 336 static int gaim_ssi_authrequest (aim_session_t *, aim_frame_t *, ...);
565 static int gaim_ssi_authreply (aim_session_t *, aim_frame_t *, ...); 337 static int gaim_ssi_authreply (aim_session_t *, aim_frame_t *, ...);
566 static int gaim_ssi_gotadded (aim_session_t *, aim_frame_t *, ...); 338 static int gaim_ssi_gotadded (aim_session_t *, aim_frame_t *, ...);
567 #endif 339 #endif
568 340
341 /* for DirectIM/image transfer */
569 static int gaim_odc_initiate (aim_session_t *, aim_frame_t *, ...); 342 static int gaim_odc_initiate (aim_session_t *, aim_frame_t *, ...);
570 static int gaim_odc_incoming (aim_session_t *, aim_frame_t *, ...); 343 static int gaim_odc_incoming (aim_session_t *, aim_frame_t *, ...);
571 static int gaim_odc_typing (aim_session_t *, aim_frame_t *, ...); 344 static int gaim_odc_typing (aim_session_t *, aim_frame_t *, ...);
572 static int gaim_update_ui (aim_session_t *, aim_frame_t *, ...); 345 static int gaim_update_ui (aim_session_t *, aim_frame_t *, ...);
346
347 /* for file transfer */
348 static int oscar_sendfile_estblsh(aim_session_t *, aim_frame_t *, ...);
349 static int oscar_sendfile_prompt (aim_session_t *, aim_frame_t *, ...);
350 static int oscar_sendfile_ack (aim_session_t *, aim_frame_t *, ...);
351 static int oscar_sendfile_done (aim_session_t *, aim_frame_t *, ...);
573 352
574 static fu32_t check_encoding(const char *utf8); 353 static fu32_t check_encoding(const char *utf8);
575 static fu32_t parse_encoding(const char *enc); 354 static fu32_t parse_encoding(const char *enc);
576 355
577 static char *msgerrreason[] = { 356 static char *msgerrreason[] = {
917 gc->inpa = gaim_input_add(bosconn->fd, GAIM_INPUT_READ, oscar_callback, bosconn); 696 gc->inpa = gaim_input_add(bosconn->fd, GAIM_INPUT_READ, oscar_callback, bosconn);
918 set_login_progress(gc, 4, _("Connection established, cookie sent")); 697 set_login_progress(gc, 4, _("Connection established, cookie sent"));
919 } 698 }
920 699
921 /* BBB */ 700 /* BBB */
701 /*
702 * This little area in oscar.c is the nexus of file transfer code,
703 * so I wrote a little explanation of what happens. I am such a
704 * ninja.
705 *
706 * The series of events for a file send is:
707 * -Create xfer and call gaim_xfer_request (this happens in oscar_ask_sendfile)
708 * -User chooses a file and oscar_xfer_init is called. It establishs a
709 * listening socket, then asks the remote user to connect to us (and
710 * gives them the file name, port, IP, etc.)
711 * -They connect to us and we send them an AIM_CB_OFT_PROMPT (this happens
712 * in oscar_sendfile_estblsh)
713 * -They send us an AIM_CB_OFT_ACK and then we start sending data
714 * -When we finish, they send us an AIM_CB_OFT_DONE and they close the
715 * connection.
716 * -We get drunk because file transfer kicks ass.
717 *
718 * The series of events for a file receive is:
719 * -Create xfer and call gaim_xfer request (this happens in incomingim_chan2)
720 * -Gaim user selects file to name and location to save file to and
721 * oscar_xfer_init is called
722 * -It connects to the remote user using the IP they gave us earlier
723 * -After connecting, they send us an AIM_CB_OFT_PROMPT. In reply, we send
724 * them an AIM_CB_OFT_ACK.
725 * -They begin to send us lots of raw data.
726 * -When they finish sending data we send an AIM_CB_OFT_DONE and then close
727 * the connectionn.
728 */
729 static void oscar_sendfile_connected(gpointer data, gint source, GaimInputCondition condition);
730
731 /* XXX - This function is pretty ugly */
732 static void
733 oscar_xfer_init(struct gaim_xfer *xfer)
734 {
735 struct gaim_connection *gc;
736 struct oscar_data *od;
737 struct oscar_xfer_data *xfer_data;
738
739 debug_printf("in oscar_xfer_init\n");
740 if (!(xfer_data = xfer->data))
741 return;
742 if (!(gc = xfer_data->gc))
743 return;
744 if (!(od = gc->proto_data))
745 return;
746
747 if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) {
748 int i;
749 char ip[4];
750 gchar **ipsplit;
751
752 if (xfer->local_ip) {
753 ipsplit = g_strsplit(xfer->local_ip, ".", 4);
754 for (i=0; ipsplit[i]; i++)
755 ip[i] = atoi(ipsplit[i]);
756 g_strfreev(ipsplit);
757 } else {
758 memset(ip, 0x00, 4);
759 }
760
761 xfer->filename = g_path_get_basename(xfer->local_filename);
762 xfer_data->checksum = aim_oft_checksum_file(xfer->local_filename);
763
764 /*
765 * First try the port specified earlier (5190). If that fails, try a
766 * few random ports. Maybe we need a way to tell libfaim to listen
767 * for multiple connections on one listener socket.
768 */
769 xfer_data->conn = aim_sendfile_listen(od->sess, xfer_data->cookie, ip, xfer->local_port);
770 for (i=0; (i<5 && !xfer_data->conn); i++) {
771 xfer->local_port = (rand() % (65535-1024)) + 1024;
772 xfer_data->conn = aim_sendfile_listen(od->sess, xfer_data->cookie, ip, xfer->local_port);
773 }
774 debug_printf("port is %d, ip is %hhd.%hhd.%hhd.%hhd\n", xfer->local_port, ip[0], ip[1], ip[2], ip[3]);
775 if (xfer_data->conn) {
776 xfer->watcher = gaim_input_add(xfer_data->conn->fd, GAIM_INPUT_READ, oscar_callback, xfer_data->conn);
777 aim_im_sendch2_sendfile_ask(od->sess, xfer_data->cookie, xfer->who, ip, xfer->local_port, xfer->filename, 1, xfer->size);
778 aim_conn_addhandler(od->sess, xfer_data->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_ESTABLISHED, oscar_sendfile_estblsh, 0);
779 } else {
780 do_error_dialog(_("File Transfer Aborted"), _("Unable to establish listener socket."), GAIM_ERROR);
781 /* XXX - The below line causes a crash because the transfer is canceled before the "Ok" callback on the file selection thing exists, I think */
782 /* gaim_xfer_cancel(xfer); */
783 }
784 } else if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) {
785 xfer_data->conn = aim_newconn(od->sess, AIM_CONN_TYPE_RENDEZVOUS, NULL);
786 if (xfer_data->conn) {
787 xfer_data->conn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE;
788 aim_conn_addhandler(od->sess, xfer_data->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_PROMPT, oscar_sendfile_prompt, 0);
789 xfer_data->conn->fd = xfer->fd = proxy_connect(gc->account, xfer->remote_ip, xfer->remote_port, oscar_sendfile_connected, xfer);
790 if (xfer->fd == -1) {
791 do_error_dialog(_("File Transfer Aborted"), _("Unable to establish file descriptor."), GAIM_ERROR);
792 /* gaim_xfer_cancel(xfer); */
793 }
794 } else {
795 do_error_dialog(_("File Transfer Aborted"), _("Unable to create new connection."), GAIM_ERROR);
796 /* gaim_xfer_cancel(xfer); */
797 /* Try a different port? Ask them to connect to us? */
798 }
799
800 }
801 }
802
803 static void
804 oscar_xfer_start(struct gaim_xfer *xfer)
805 {
806 /* struct gaim_connection *gc;
807 struct oscar_data *od;
808 struct oscar_xfer_data *xfer_data;
809
810 if (!(xfer_data = xfer->data))
811 return;
812 if (!(gc = xfer_data->gc))
813 return;
814 if (!(od = gc->proto_data))
815 return;
816
817 od = xfer_data->od;
818 */
819 debug_printf("AAA - in oscar_xfer_start\n");
820
821 /* I'm pretty sure we don't need to do jack here. Nor Jill. */
822 }
823
824 static void
825 oscar_xfer_end(struct gaim_xfer *xfer)
826 {
827 struct gaim_connection *gc;
828 struct oscar_data *od;
829 struct oscar_xfer_data *xfer_data;
830
831 debug_printf("AAA - in oscar_xfer_end\n");
832 if (!(xfer_data = xfer->data))
833 return;
834
835 if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE)
836 aim_oft_sendheader(xfer_data->conn->sessv, xfer_data->conn, AIM_CB_OFT_DONE, xfer_data->cookie, xfer->filename, 1, 1, xfer->size, xfer->size, xfer_data->modtime, xfer_data->checksum, 0x02, xfer->size, xfer_data->checksum);
837
838 g_free(xfer_data->clientip);
839 g_free(xfer_data->clientip2);
840
841 if ((gc = xfer_data->gc)) {
842 if ((od = gc->proto_data))
843 od->file_transfers = g_slist_remove(od->file_transfers, xfer);
844 }
845
846 g_free(xfer_data);
847 xfer->data = NULL;
848 }
849
850 static void
851 oscar_xfer_cancel(struct gaim_xfer *xfer)
852 {
853 struct gaim_connection *gc;
854 struct oscar_data *od;
855 struct oscar_xfer_data *xfer_data;
856 aim_conn_t *conn;
857
858 debug_printf("AAA - in oscar_xfer_cancel\n");
859 if (!(xfer_data = xfer->data))
860 return;
861
862 if ((conn = xfer_data->conn)) {
863 aim_session_t *sess;
864 if ((sess = conn->sessv))
865 if (xfer_data->cookie && xfer->who)
866 aim_im_sendch2_sendfile_cancel(sess, xfer_data->cookie, xfer->who, AIM_CAPS_SENDFILE);
867 }
868
869 g_free(xfer_data->clientip);
870 g_free(xfer_data->clientip2);
871
872 if ((gc = xfer_data->gc))
873 if ((od = gc->proto_data))
874 od->file_transfers = g_slist_remove(od->file_transfers, xfer);
875
876 g_free(xfer_data);
877 xfer->data = NULL;
878 }
879
880 static void
881 oscar_xfer_ack(struct gaim_xfer *xfer, const char *buffer, size_t size)
882 {
883 struct oscar_xfer_data *xfer_data;
884
885 if (!(xfer_data = xfer->data))
886 return;
887
888 if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) {
889 /*
890 * If we're done sending, intercept the socket from the core ft code
891 * and wait for the other guy to send the "done" OFT packet.
892 */
893 if (gaim_xfer_get_bytes_remaining(xfer) <= 0) {
894 gaim_input_remove(xfer->watcher);
895 xfer->watcher = gaim_input_add(xfer->fd, GAIM_INPUT_READ, oscar_callback, xfer_data->conn);
896 xfer->fd = 0;
897 gaim_xfer_set_completed(xfer, TRUE);
898 }
899 } else if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) {
900 /* Update our rolling checksum */
901 /* xfer_data->checksum = aim_oft_checksum_chunk(buffer, size, xfer_data->checksum); */
902 }
903 }
904
905 static struct gaim_xfer *
906 oscar_find_xfer_by_cookie(GSList *fts, const char *ck)
907 {
908 struct gaim_xfer *xfer;
909 struct oscar_xfer_data *data;
910
911 while (fts) {
912 xfer = fts->data;
913 data = xfer->data;
914
915 if (data && !strcmp(data->cookie, ck))
916 return xfer;
917
918 fts = g_slist_next(fts);
919 }
920
921 return NULL;
922 }
923
924 static struct gaim_xfer *
925 oscar_find_xfer_by_conn(GSList *fts, aim_conn_t *conn)
926 {
927 struct gaim_xfer *xfer;
928 struct oscar_xfer_data *data;
929
930 while (fts) {
931 xfer = fts->data;
932 data = xfer->data;
933
934 if (data && (conn == data->conn))
935 return xfer;
936
937 fts = g_slist_next(fts);
938 }
939
940 return NULL;
941 }
942
922 static void oscar_ask_sendfile(struct gaim_connection *gc, char *destsn) { 943 static void oscar_ask_sendfile(struct gaim_connection *gc, char *destsn) {
923 struct oscar_data *od = (struct oscar_data *)gc->proto_data; 944 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
924 945
925 /* You want to send a file to someone else, you're so generous */ 946 /* You want to send a file to someone else, you're so generous */
926 struct gaim_xfer *xfer; 947 struct gaim_xfer *xfer;
946 /* Setup our I/O op functions */ 967 /* Setup our I/O op functions */
947 gaim_xfer_set_init_fnc(xfer, oscar_xfer_init); 968 gaim_xfer_set_init_fnc(xfer, oscar_xfer_init);
948 gaim_xfer_set_start_fnc(xfer, oscar_xfer_start); 969 gaim_xfer_set_start_fnc(xfer, oscar_xfer_start);
949 gaim_xfer_set_end_fnc(xfer, oscar_xfer_end); 970 gaim_xfer_set_end_fnc(xfer, oscar_xfer_end);
950 gaim_xfer_set_cancel_fnc(xfer, oscar_xfer_cancel); 971 gaim_xfer_set_cancel_fnc(xfer, oscar_xfer_cancel);
972 gaim_xfer_set_ack_fnc(xfer, oscar_xfer_ack);
951 973
952 /* Keep track of this transfer for later */ 974 /* Keep track of this transfer for later */
953 od->file_transfers = g_slist_append(od->file_transfers, xfer); 975 od->file_transfers = g_slist_append(od->file_transfers, xfer);
954 976
955 /* Now perform the request */ 977 /* Now perform the request */
1682 /* 1704 /*
1683 * This is called after a remote AIM user has connected to us. We 1705 * This is called after a remote AIM user has connected to us. We
1684 * want to do some voodoo with the socket file descriptors, add a 1706 * want to do some voodoo with the socket file descriptors, add a
1685 * callback or two, and then send the AIM_CB_OFT_PROMPT. 1707 * callback or two, and then send the AIM_CB_OFT_PROMPT.
1686 */ 1708 */
1687 static int oscar_sendfile_established(aim_session_t *sess, aim_frame_t *fr, ...) { 1709 static int oscar_sendfile_estblsh(aim_session_t *sess, aim_frame_t *fr, ...) {
1688 struct gaim_connection *gc = sess->aux_data; 1710 struct gaim_connection *gc = sess->aux_data;
1689 struct oscar_data *od = (struct oscar_data *)gc->proto_data; 1711 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
1690 struct gaim_xfer *xfer; 1712 struct gaim_xfer *xfer;
1691 struct oscar_xfer_data *xfer_data; 1713 struct oscar_xfer_data *xfer_data;
1692 va_list ap; 1714 va_list ap;
1693 aim_conn_t *conn, *listenerconn; 1715 aim_conn_t *conn, *listenerconn;
1694 debug_printf("AAA - in oscar_sendfile_established\n"); 1716
1695 1717 debug_printf("AAA - in oscar_sendfile_estblsh\n");
1696 va_start(ap, fr); 1718 va_start(ap, fr);
1697 conn = va_arg(ap, aim_conn_t *); 1719 conn = va_arg(ap, aim_conn_t *);
1698 listenerconn = va_arg(ap, aim_conn_t *); 1720 listenerconn = va_arg(ap, aim_conn_t *);
1699 va_end(ap); 1721 va_end(ap);
1700 1722
1727 */ 1749 */
1728 static void oscar_sendfile_connected(gpointer data, gint source, GaimInputCondition condition) { 1750 static void oscar_sendfile_connected(gpointer data, gint source, GaimInputCondition condition) {
1729 struct gaim_connection *gc; 1751 struct gaim_connection *gc;
1730 struct gaim_xfer *xfer; 1752 struct gaim_xfer *xfer;
1731 struct oscar_xfer_data *xfer_data; 1753 struct oscar_xfer_data *xfer_data;
1732 debug_printf("AAA - in oscar_sendfile_connected\n"); 1754
1733 1755 debug_printf("AAA - in oscar_sendfile_connected\n");
1734 if (!(xfer = data)) 1756 if (!(xfer = data))
1735 return; 1757 return;
1736 if (!(xfer_data = xfer->data)) 1758 if (!(xfer_data = xfer->data))
1737 return; 1759 return;
1738 if (!(gc = xfer_data->gc)) 1760 if (!(gc = xfer_data->gc))
1765 struct oscar_xfer_data *xfer_data; 1787 struct oscar_xfer_data *xfer_data;
1766 va_list ap; 1788 va_list ap;
1767 aim_conn_t *conn; 1789 aim_conn_t *conn;
1768 fu8_t *cookie; 1790 fu8_t *cookie;
1769 struct aim_fileheader_t *fh; 1791 struct aim_fileheader_t *fh;
1770 debug_printf("AAA - in oscar_sendfile_prompt\n"); 1792
1771 1793 debug_printf("AAA - in oscar_sendfile_prompt\n");
1772 va_start(ap, fr); 1794 va_start(ap, fr);
1773 conn = va_arg(ap, aim_conn_t *); 1795 conn = va_arg(ap, aim_conn_t *);
1774 cookie = va_arg(ap, fu8_t *); 1796 cookie = va_arg(ap, fu8_t *);
1775 fh = va_arg(ap, struct aim_fileheader_t *); 1797 fh = va_arg(ap, struct aim_fileheader_t *);
1776 va_end(ap); 1798 va_end(ap);
1795 1817
1796 return 0; 1818 return 0;
1797 } 1819 }
1798 1820
1799 /* 1821 /*
1800 * We are sending a file to someone else. They have just acknowledged are 1822 * We are sending a file to someone else. They have just acknowledged out
1801 * prompt, so we want to start sending data like there's no tomorrow. 1823 * prompt, so we want to start sending data like there's no tomorrow.
1802 */ 1824 */
1803 static int oscar_sendfile_ack(aim_session_t *sess, aim_frame_t *fr, ...) { 1825 static int oscar_sendfile_ack(aim_session_t *sess, aim_frame_t *fr, ...) {
1804 struct gaim_connection *gc = sess->aux_data; 1826 struct gaim_connection *gc = sess->aux_data;
1805 struct oscar_data *od = gc->proto_data; 1827 struct oscar_data *od = gc->proto_data;
1806 struct gaim_xfer *xfer; 1828 struct gaim_xfer *xfer;
1807 va_list ap; 1829 va_list ap;
1808 aim_conn_t *conn; 1830 aim_conn_t *conn;
1809 fu8_t *cookie; 1831 fu8_t *cookie;
1810 struct aim_fileheader_t *fh; 1832 struct aim_fileheader_t *fh;
1811 debug_printf("AAA - in oscar_sendfile_ack\n"); 1833
1812 1834 debug_printf("AAA - in oscar_sendfile_ack\n");
1813 va_start(ap, fr); 1835 va_start(ap, fr);
1814 conn = va_arg(ap, aim_conn_t *); 1836 conn = va_arg(ap, aim_conn_t *);
1815 cookie = va_arg(ap, fu8_t *); 1837 cookie = va_arg(ap, fu8_t *);
1816 fh = va_arg(ap, struct aim_fileheader_t *); 1838 fh = va_arg(ap, struct aim_fileheader_t *);
1817 va_end(ap); 1839 va_end(ap);
1818 1840
1819 if (!(xfer = oscar_find_xfer_by_cookie(od->file_transfers, cookie))) 1841 if (!(xfer = oscar_find_xfer_by_cookie(od->file_transfers, cookie)))
1820 return 1; 1842 return 1;
1843
1844 /* We want to stop listening with a normal thingy */
1845 gaim_input_remove(xfer->watcher);
1846 xfer->watcher = 0;
1821 1847
1822 gaim_xfer_start(xfer, xfer->fd, NULL, 0); 1848 gaim_xfer_start(xfer, xfer->fd, NULL, 0);
1823 1849
1824 return 0; 1850 return 0;
1825 } 1851 }
1834 struct gaim_xfer *xfer; 1860 struct gaim_xfer *xfer;
1835 va_list ap; 1861 va_list ap;
1836 aim_conn_t *conn; 1862 aim_conn_t *conn;
1837 fu8_t *cookie; 1863 fu8_t *cookie;
1838 struct aim_fileheader_t *fh; 1864 struct aim_fileheader_t *fh;
1839 debug_printf("AAA - in oscar_sendfile_done\n"); 1865
1840 1866 debug_printf("AAA - in oscar_sendfile_done\n");
1841 va_start(ap, fr); 1867 va_start(ap, fr);
1842 conn = va_arg(ap, aim_conn_t *); 1868 conn = va_arg(ap, aim_conn_t *);
1843 cookie = va_arg(ap, fu8_t *); 1869 cookie = va_arg(ap, fu8_t *);
1844 fh = va_arg(ap, struct aim_fileheader_t *); 1870 fh = va_arg(ap, struct aim_fileheader_t *);
1845 va_end(ap); 1871 va_end(ap);
1846 1872
1847 if (!(xfer = oscar_find_xfer_by_conn(od->file_transfers, conn))) 1873 if (!(xfer = oscar_find_xfer_by_conn(od->file_transfers, conn)))
1848 return 1; 1874 return 1;
1849 1875
1850 gaim_xfer_set_completed(xfer, TRUE); 1876 xfer->fd = conn->fd;
1851 gaim_xfer_end(xfer); 1877 gaim_xfer_end(xfer);
1852 1878
1853 return 0; 1879 return 0;
1854 } 1880 }
1855 1881
2059 struct gaim_xfer *xfer; 2085 struct gaim_xfer *xfer;
2060 struct oscar_xfer_data *xfer_data; 2086 struct oscar_xfer_data *xfer_data;
2061 2087
2062 if (!args->cookie || !args->verifiedip || !args->port || 2088 if (!args->cookie || !args->verifiedip || !args->port ||
2063 !args->info.sendfile.filename || !args->info.sendfile.totsize || 2089 !args->info.sendfile.filename || !args->info.sendfile.totsize ||
2064 !args->info.sendfile.totfiles || !args->reqclass) 2090 !args->info.sendfile.totfiles || !args->reqclass) {
2091 debug_printf("%s tried to send you a file with incomplete information.\n", userinfo->sn);
2065 return 1; 2092 return 1;
2093 }
2066 2094
2067 if (args->info.sendfile.subtype == AIM_OFT_SUBTYPE_SEND_DIR) { 2095 if (args->info.sendfile.subtype == AIM_OFT_SUBTYPE_SEND_DIR) {
2068 /* last char of the ft req is a star, they are sending us a 2096 /* last char of the ft req is a star, they are sending us a
2069 * directory -- remove the star and trailing slash so we dont save 2097 * directory -- remove the star and trailing slash so we dont save
2070 * directories that look like 'dirname\*' -- arl */ 2098 * directories that look like 'dirname\*' -- arl */
5150 pbm->label = _("Direct IM"); 5178 pbm->label = _("Direct IM");
5151 pbm->callback = oscar_ask_direct_im; 5179 pbm->callback = oscar_ask_direct_im;
5152 pbm->gc = gc; 5180 pbm->gc = gc;
5153 m = g_list_append(m, pbm); 5181 m = g_list_append(m, pbm);
5154 5182
5155 #if 0
5156 pbm = g_new0(struct proto_buddy_menu, 1); 5183 pbm = g_new0(struct proto_buddy_menu, 1);
5157 pbm->label = _("Send File"); 5184 pbm->label = _("Send File");
5158 pbm->callback = oscar_ask_sendfile; 5185 pbm->callback = oscar_ask_sendfile;
5159 pbm->gc = gc; 5186 pbm->gc = gc;
5160 m = g_list_append(m, pbm); 5187 m = g_list_append(m, pbm);
5161 #endif
5162 } 5188 }
5163 } 5189 }
5164 5190
5165 #if 0 5191 #if 0
5166 pbm = g_new0(struct proto_buddy_menu, 1); 5192 pbm = g_new0(struct proto_buddy_menu, 1);