Mercurial > pidgin.yaz
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); |