2 * @file yahoo_filexfer.c Yahoo Filetransfer
4 * Purple is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 /* TODO: it needs further refactoring */
36 #include "yahoo_packet.h"
37 #include "yahoo_filexfer.h"
38 #include "yahoo_doodle.h"
39 #include "yahoo_friend.h"
43 struct yahoo_xfer_data
{
46 PurpleHttpConnection
*hc
;
51 gchar
*xfer_peer_idstring
;
52 gchar
*xfer_idstring_for_relay
;
55 /* contains all filenames, in case of multiple transfers, with the first
56 * one in the list being the current file's name (ymsg15) */
57 GSList
*filename_list
;
58 GSList
*size_list
; /* corresponds to filename_list, with size as **STRING** */
63 yahoo_xfer_data_free(struct yahoo_xfer_data
*xd
)
70 yd
= purple_connection_get_protocol_data(gc
);
72 /* remove entry from map */
73 if(xd
->xfer_peer_idstring
) {
74 xfer
= g_hash_table_lookup(yd
->xfer_peer_idstring_map
, xd
->xfer_peer_idstring
);
76 g_hash_table_remove(yd
->xfer_peer_idstring_map
, xd
->xfer_peer_idstring
);
79 g_slist_free_full(xd
->filename_list
, g_free
);
80 g_slist_free_full(xd
->size_list
, g_free
);
84 g_free(xd
->xfer_peer_idstring
);
85 g_free(xd
->xfer_idstring_for_relay
);
90 yahoo_xfer_start(PurpleXfer
*xfer
);
93 yahoo_ft_new_xfer_struct(PurpleConnection
*gc
, PurpleXferType type
,
96 static PurpleHttpRequest
*
97 yahoo_ft_new_req(struct yahoo_xfer_data
*xd
)
99 PurpleHttpRequest
*req
;
102 g_return_val_if_fail(xd
!= NULL
, NULL
);
104 yd
= purple_connection_get_protocol_data(xd
->gc
);
106 req
= purple_http_request_new(xd
->url
);
107 purple_http_request_header_set(req
, "User-Agent",
108 YAHOO_CLIENT_USERAGENT
);
109 purple_http_request_header_set(req
, "Cache-Control", "no-cache");
111 PurpleHttpCookieJar
*cjar
;
113 cjar
= purple_http_request_get_cookie_jar(req
);
114 purple_http_cookie_jar_set(cjar
, "Y", yd
->cookie_y
);
115 purple_http_cookie_jar_set(cjar
, "T", yd
->cookie_t
);
122 yahoo_ft_url_gen(PurpleXfer
*xfer
, const gchar
*host
)
124 struct yahoo_xfer_data
*xfer_data
;
125 PurpleAccount
*account
;
127 g_return_val_if_fail(host
!= NULL
, NULL
);
129 xfer_data
= purple_xfer_get_protocol_data(xfer
);
130 account
= purple_connection_get_account(xfer_data
->gc
);
132 if (!xfer_data
->is_relay
) {
133 purple_debug_fatal("yahoo", "Non-relay FT aren't tested yet\n");
137 return g_strdup_printf("http://%s/relay?token=%s&sender=%s&recver=%s",
138 host
, purple_url_encode(xfer_data
->xfer_idstring_for_relay
),
139 purple_normalize(account
, purple_account_get_username(account
)),
140 purple_xfer_get_remote_user(xfer
));
144 yahoo_xfer_init_15(PurpleXfer
*xfer
)
146 struct yahoo_xfer_data
*xfer_data
;
147 PurpleConnection
*gc
;
148 PurpleAccount
*account
;
150 struct yahoo_packet
*pkt
;
152 xfer_data
= purple_xfer_get_protocol_data(xfer
);
154 yd
= purple_connection_get_protocol_data(gc
);
155 account
= purple_connection_get_account(gc
);
157 if (purple_xfer_get_xfer_type(xfer
) == PURPLE_XFER_TYPE_SEND
) {
159 filename
= g_path_get_basename(purple_xfer_get_local_filename(xfer
));
160 pkt
= yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15
,
161 YAHOO_STATUS_AVAILABLE
,
163 yahoo_packet_hash(pkt
, "sssiiiisiii",
164 1, purple_normalize(account
, purple_account_get_username(account
)),
165 5, purple_xfer_get_remote_user(xfer
),
166 265, xfer_data
->xfer_peer_idstring
,
172 28, (int)purple_xfer_get_size(xfer
),
177 if(xfer_data
->firstoflist
== TRUE
) {
178 pkt
= yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15
,
179 YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
181 yahoo_packet_hash(pkt
, "sssi",
182 1, purple_normalize(account
, purple_account_get_username(account
)),
183 5, purple_xfer_get_remote_user(xfer
),
184 265, xfer_data
->xfer_peer_idstring
,
187 pkt
= yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15
,
188 YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
190 yahoo_packet_hash(pkt
, "sssi",
191 1, purple_normalize(account
, purple_account_get_username(account
)),
192 5, purple_xfer_get_remote_user(xfer
),
193 265, xfer_data
->xfer_peer_idstring
,
197 yahoo_packet_send_and_free(pkt
, yd
);
201 yahoo_xfer_cancel_send(PurpleXfer
*xfer
)
203 struct yahoo_xfer_data
*xfer_data
;
205 xfer_data
= purple_xfer_get_protocol_data(xfer
);
207 if(purple_xfer_get_status(xfer
) == PURPLE_XFER_STATUS_CANCEL_LOCAL
)
209 PurpleConnection
*gc
;
210 PurpleAccount
*account
;
212 struct yahoo_packet
*pkt
;
215 yd
= purple_connection_get_protocol_data(gc
);
216 account
= purple_connection_get_account(gc
);
217 if(xfer_data
->xfer_idstring_for_relay
) /* hack to see if file trans acc/info packet has been received */
219 pkt
= yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15
,
220 YAHOO_STATUS_DISCONNECTED
,
222 yahoo_packet_hash(pkt
, "sssi",
223 1, purple_normalize(account
, purple_account_get_username(account
)),
224 5, purple_xfer_get_remote_user(xfer
),
225 265, xfer_data
->xfer_peer_idstring
,
230 pkt
= yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15
,
231 YAHOO_STATUS_AVAILABLE
,
233 yahoo_packet_hash(pkt
, "sssi",
234 1, purple_normalize(account
, purple_account_get_username(account
)),
235 5, purple_xfer_get_remote_user(xfer
),
236 265, xfer_data
->xfer_peer_idstring
,
239 yahoo_packet_send_and_free(pkt
, yd
);
243 purple_http_conn_cancel(xfer_data
->hc
);
244 yahoo_xfer_data_free(xfer_data
);
246 purple_xfer_set_protocol_data(xfer
, NULL
);
250 yahoo_xfer_cancel_recv(PurpleXfer
*xfer
)
252 struct yahoo_xfer_data
*xfer_data
;
254 xfer_data
= purple_xfer_get_protocol_data(xfer
);
256 if(purple_xfer_get_status(xfer
) == PURPLE_XFER_STATUS_CANCEL_LOCAL
)
259 PurpleConnection
*gc
;
260 PurpleAccount
*account
;
262 struct yahoo_packet
*pkt
;
265 yd
= purple_connection_get_protocol_data(gc
);
266 account
= purple_connection_get_account(gc
);
267 if(!xfer_data
->xfer_idstring_for_relay
) /* hack to see if file trans acc/info packet has been received */
269 pkt
= yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15
,
270 YAHOO_STATUS_AVAILABLE
,
272 yahoo_packet_hash(pkt
, "sssi",
273 1, purple_normalize(account
, purple_account_get_username(account
)),
274 5, purple_xfer_get_remote_user(xfer
),
275 265, xfer_data
->xfer_peer_idstring
,
280 pkt
= yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15
,
281 YAHOO_STATUS_DISCONNECTED
,
283 yahoo_packet_hash(pkt
, "sssi",
284 1, purple_normalize(account
, purple_account_get_username(account
)),
285 5, purple_xfer_get_remote_user(xfer
),
286 265, xfer_data
->xfer_peer_idstring
,
289 yahoo_packet_send_and_free(pkt
, yd
);
293 purple_http_conn_cancel(xfer_data
->hc
);
294 yahoo_xfer_data_free(xfer_data
);
296 purple_xfer_set_protocol_data(xfer
, NULL
);
299 static void yahoo_xfer_end(PurpleXfer
*xfer_old
)
301 struct yahoo_xfer_data
*xfer_data
;
302 PurpleXfer
*xfer
= NULL
;
303 PurpleConnection
*gc
;
306 xfer_data
= purple_xfer_get_protocol_data(xfer_old
);
308 && purple_xfer_get_xfer_type(xfer_old
) == PURPLE_XFER_TYPE_RECEIVE
309 && xfer_data
->filename_list
) {
310 /* removing top of filename & size list completely */
311 g_free( xfer_data
->filename_list
->data
);
312 g_free( xfer_data
->size_list
->data
);
314 xfer_data
->filename_list
->data
= NULL
;
315 xfer_data
->size_list
->data
= NULL
;
317 xfer_data
->filename_list
= g_slist_delete_link(xfer_data
->filename_list
, xfer_data
->filename_list
);
318 xfer_data
->size_list
= g_slist_delete_link(xfer_data
->size_list
, xfer_data
->size_list
);
320 /* if there are still more files */
321 if(xfer_data
->filename_list
)
326 filename
= xfer_data
->filename_list
->data
;
329 yd
= purple_connection_get_protocol_data(gc
);
331 /* setting up xfer_data for next file's tranfer */
332 g_free(xfer_data
->host
);
333 g_free(xfer_data
->path
);
334 g_free(xfer_data
->xfer_idstring_for_relay
);
335 xfer_data
->host
= NULL
;
336 xfer_data
->host
= NULL
;
337 xfer_data
->xfer_idstring_for_relay
= NULL
;
338 xfer_data
->info_val_249
= 0;
339 xfer_data
->firstoflist
= FALSE
;
341 /* Dereference xfer_data from old xfer */
342 purple_xfer_set_protocol_data(xfer_old
, NULL
);
344 /* Build the file transfer handle. */
345 xfer
= yahoo_ft_new_xfer_struct(gc
, PURPLE_XFER_TYPE_RECEIVE
, purple_xfer_get_remote_user(xfer_old
));
347 g_return_if_fail(xfer
!= NULL
);
349 /* Set the info about the incoming file. */
350 utf8_filename
= yahoo_string_decode(gc
, filename
, TRUE
);
351 purple_xfer_set_filename(xfer
, utf8_filename
);
352 g_free(utf8_filename
);
354 purple_xfer_set_protocol_data(xfer
, xfer_data
);
356 /* update map to current xfer */
357 g_hash_table_remove(yd
->xfer_peer_idstring_map
, xfer_data
->xfer_peer_idstring
);
358 g_hash_table_insert(yd
->xfer_peer_idstring_map
, xfer_data
->xfer_peer_idstring
, xfer
);
360 /* Now perform the request */
361 purple_xfer_request(xfer
);
367 yahoo_xfer_data_free(xfer_data
);
368 purple_xfer_set_protocol_data(xfer_old
, NULL
);
371 void yahoo_process_p2pfilexfer(PurpleConnection
*gc
, struct yahoo_packet
*pkt
)
373 GSList
*l
= pkt
->hash
;
377 char *service
= NULL
;
378 char *message
= NULL
;
379 char *command
= NULL
;
382 /* Get all the necessary values from this new packet */
385 struct yahoo_pair
*pair
= l
->data
;
388 case 5: /* Get who the packet is for */
389 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
392 purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
393 "got non-UTF-8 string for key %d\n", pair
->key
);
396 case 4: /* Get who the packet is from */
397 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
400 purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
401 "got non-UTF-8 string for key %d\n", pair
->key
);
404 case 49: /* Get the type of service */
405 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
406 service
= pair
->value
;
408 purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
409 "got non-UTF-8 string for key %d\n", pair
->key
);
412 case 14: /* Get the 'message' of the packet */
413 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
414 message
= pair
->value
;
416 purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
417 "got non-UTF-8 string for key %d\n", pair
->key
);
420 case 13: /* Get the command associated with this packet */
421 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
422 command
= pair
->value
;
424 purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
425 "got non-UTF-8 string for key %d\n", pair
->key
);
428 case 63: /* IMVironment name and version */
429 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
432 purple_debug_warning("yahoo", "yahoo_process_p2pfilexfer "
433 "got non-UTF-8 string for key %d\n", pair
->key
);
436 case 64: /* Not sure, but it does vary with initialization of Doodle */
443 /* If this packet is an IMVIRONMENT, handle it accordingly */
444 if(service
!= NULL
&& imv
!= NULL
&& !strcmp(service
, "IMVIRONMENT"))
446 /* Check for a Doodle packet and handle it accordingly */
447 if(strstr(imv
, "doodle;") != NULL
)
448 yahoo_doodle_process(gc
, me
, from
, command
, message
, imv
);
450 /* If an IMVIRONMENT packet comes without a specific imviroment name */
451 if(!strcmp(imv
, ";0"))
453 /* It is unfortunately time to close all IMVironments with the remote client */
454 yahoo_doodle_command_got_shutdown(gc
, from
);
459 PurpleXfer
*yahoo_new_xfer(PurpleConnection
*gc
, const char *who
)
462 struct yahoo_xfer_data
*xfer_data
;
464 g_return_val_if_fail(who
!= NULL
, NULL
);
466 xfer_data
= g_new0(struct yahoo_xfer_data
, 1);
469 /* Build the file transfer handle. */
470 xfer
= yahoo_ft_new_xfer_struct(gc
, PURPLE_XFER_TYPE_SEND
, who
);
474 g_return_val_if_reached(NULL
);
477 purple_xfer_set_protocol_data(xfer
, xfer_data
);
482 static gchar
* yahoo_xfer_new_xfer_id(void)
486 ans
= g_strnfill(24, ' ');
489 for(i
= 0; i
< 22; i
++)
491 j
= g_random_int_range (0,61);
495 ans
[i
] = j
- 26 + 'A';
497 ans
[i
] = j
- 52 + '0';
503 yahoo_xfer_dns_connected_15(GObject
*sender
, GAsyncResult
*result
, gpointer data
)
505 GError
*error
= NULL
;
506 GList
*addresses
= NULL
;
507 GInetAddress
*inet_address
= NULL
;
509 struct yahoo_xfer_data
*xd
;
510 struct yahoo_packet
*pkt
;
511 PurpleConnection
*gc
;
512 PurpleAccount
*account
;
518 if (!(xd
= purple_xfer_get_protocol_data(xfer
)))
521 account
= purple_connection_get_account(gc
);
522 yd
= purple_connection_get_protocol_data(gc
);
524 addresses
= g_resolver_lookup_by_name_finish(G_RESOLVER(sender
),
527 purple_debug_error("yahoo",
528 "Unable to find an IP address for relay.msg.yahoo.com : %s\n",
531 purple_xfer_cancel_remote(xfer
);
537 inet_address
= G_INET_ADDRESS(addresses
->data
);
538 xd
->host
= g_inet_address_to_string(inet_address
);
540 g_resolver_free_addresses(addresses
);
542 pkt
= yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
543 filename
= g_path_get_basename(purple_xfer_get_local_filename(xfer
));
545 yahoo_packet_hash(pkt
, "ssssis",
546 1, purple_normalize(account
, purple_account_get_username(account
)),
547 5, purple_xfer_get_remote_user(xfer
),
548 265, xd
->xfer_peer_idstring
,
554 yahoo_packet_send_and_free(pkt
, yd
);
557 gboolean
yahoo_can_receive_file(PurpleConnection
*gc
, const char *who
)
564 void yahoo_send_file(PurpleConnection
*gc
, const char *who
, const char *file
)
566 struct yahoo_xfer_data
*xfer_data
;
567 YahooData
*yd
= purple_connection_get_protocol_data(gc
);
568 PurpleXfer
*xfer
= yahoo_new_xfer(gc
, who
);
570 g_return_if_fail(xfer
!= NULL
);
573 /* if we don't have a p2p connection, try establishing it now */
574 if( !g_hash_table_lookup(yd
->peers
, who
) )
575 yahoo_send_p2p_pkt(gc
, who
, 0);
578 xfer_data
= purple_xfer_get_protocol_data(xfer
);
579 xfer_data
->xfer_peer_idstring
= yahoo_xfer_new_xfer_id();
580 g_hash_table_insert(yd
->xfer_peer_idstring_map
, xfer_data
->xfer_peer_idstring
, xfer
);
582 /* Now perform the request */
584 purple_xfer_request_accepted(xfer
, file
);
586 purple_xfer_request(xfer
);
589 void yahoo_process_filetrans_15(PurpleConnection
*gc
, struct yahoo_packet
*pkt
)
596 struct yahoo_xfer_data
*xfer_data
;
597 char *service
= NULL
;
598 char *filename
= NULL
;
599 char *xfer_peer_idstring
= NULL
;
602 GSList
*filename_list
= NULL
;
603 GSList
*size_list
= NULL
;
606 yd
= purple_connection_get_protocol_data(gc
);
608 for (l
= pkt
->hash
; l
; l
= l
->next
) {
609 struct yahoo_pair
*pair
= l
->data
;
613 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
616 purple_debug_warning("yahoo", "yahoo_process_filetrans_15 "
617 "got non-UTF-8 string for key %d\n", pair
->key
);
623 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
624 xfer_peer_idstring
= pair
->value
;
626 purple_debug_warning("yahoo", "yahoo_process_filetrans_15 "
627 "got non-UTF-8 string for key %d\n", pair
->key
);
631 filename_list
= g_slist_prepend(filename_list
, g_strdup(pair
->value
));
635 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
636 size_list
= g_slist_prepend(size_list
, g_strdup(pair
->value
));
638 purple_debug_warning("yahoo", "yahoo_process_filetrans_15 "
639 "got non-UTF-8 string for key %d\n", pair
->key
);
643 val_222
= atol(pair
->value
);
644 /* 1=send, 2=cancel, 3=accept, 4=reject */
647 /* check for p2p and imviron .... not sure it comes by this service packet. Since it was bundled with filexfer in old ymsg version, still keeping it. */
649 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
650 service
= pair
->value
;
652 purple_debug_warning("yahoo", "yahoo_process_filetrans_15 "
653 "got non-UTF-8 string for key %d\n", pair
->key
);
657 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
660 purple_debug_warning("yahoo", "yahoo_process_filetrans_15 "
661 "got non-UTF-8 string for key %d\n", pair
->key
);
668 if(!xfer_peer_idstring
)
671 if(val_222
== 2 || val_222
== 4)
673 xfer
= g_hash_table_lookup(yd
->xfer_peer_idstring_map
,
676 purple_xfer_cancel_remote(xfer
);
681 struct yahoo_xfer_data
*xd
;
684 xfer
= g_hash_table_lookup(yd
->xfer_peer_idstring_map
,
689 xd
= purple_xfer_get_protocol_data(xfer
);
692 * In the file trans info packet that we must reply with, we are
693 * supposed to mention the ip address...
694 * purple connect does not give me a way of finding the ip address...
695 * so, purple dnsquery is used... but retries, trying with next ip
696 * address etc. is not implemented..TODO
699 /* To send through p2p */
700 if( g_hash_table_lookup(yd
->peers
, from
) ) {
701 /* send p2p file transfer information */
702 purple_debug_error("yahoo", "p2p file transfers are not supported yet\n");
703 /*xd->is_relay = FALSE;*/
707 resolver
= g_resolver_get_default();
708 g_resolver_lookup_by_name_async(resolver
,
709 YAHOO_XFER_RELAY_HOST
,
711 yahoo_xfer_dns_connected_15
,
713 g_object_unref(resolver
);
718 /* processing for p2p and imviron .... not sure it comes by this service packet. Since it was bundled with filexfer in old ymsg version, still keeping it. */
720 * The remote user has changed their IMVironment. We
721 * record it for later use.
723 if (from
&& imv
&& service
&& (strcmp("IMVIRONMENT", service
) == 0)) {
724 g_hash_table_replace(yd
->imvironments
, g_strdup(from
), g_strdup(imv
));
728 if (pkt
->service
== YAHOO_SERVICE_P2PFILEXFER
) {
729 if (service
&& (strcmp("FILEXFER", service
) != 0)) {
730 purple_debug_misc("yahoo", "unhandled service 0x%02x\n", pkt
->service
);
738 /* have to change list into order in which client at other end sends */
739 filename_list
= g_slist_reverse(filename_list
);
740 size_list
= g_slist_reverse(size_list
);
741 filename
= filename_list
->data
;
744 xfer_data
= g_new0(struct yahoo_xfer_data
, 1);
745 xfer_data
->firstoflist
= TRUE
;
747 xfer_data
->xfer_peer_idstring
= g_strdup(xfer_peer_idstring
);
748 xfer_data
->filename_list
= filename_list
;
749 xfer_data
->size_list
= size_list
;
751 /* Build the file transfer handle. */
752 xfer
= yahoo_ft_new_xfer_struct(gc
, PURPLE_XFER_TYPE_RECEIVE
, from
);
754 /* Set the info about the incoming file. */
755 utf8_filename
= yahoo_string_decode(gc
, filename
, TRUE
);
756 purple_xfer_set_filename(xfer
, utf8_filename
);
757 g_free(utf8_filename
);
759 purple_xfer_set_protocol_data(xfer
, xfer_data
);
761 g_hash_table_insert(yd
->xfer_peer_idstring_map
,
762 xfer_data
->xfer_peer_idstring
,
767 message
= g_strdup_printf(_("%s is trying to send you a group of %d files.\n"), purple_xfer_get_remote_user(xfer
), nooffiles
);
768 purple_xfer_conversation_write(xfer
, message
, FALSE
);
771 /* Now perform the request */
772 purple_xfer_request(xfer
);
776 yahoo_process_filetrans_15_sent(PurpleHttpConnection
*hc
,
777 PurpleHttpResponse
*response
, gpointer _xfer
)
779 PurpleXfer
*xfer
= _xfer
;
780 struct yahoo_xfer_data
*xd
;
782 xd
= purple_xfer_get_protocol_data(xfer
);
786 if (purple_xfer_is_cancelled(xfer
))
789 if (!purple_http_response_is_successful(response
) ||
790 purple_xfer_get_bytes_remaining(xfer
) > 0)
792 purple_xfer_set_status(xfer
, PURPLE_XFER_STATUS_CANCEL_REMOTE
);
793 purple_xfer_end(xfer
);
795 purple_xfer_set_completed(xfer
, TRUE
);
796 purple_xfer_end(xfer
);
801 yahoo_process_filetrans_15_downloaded(PurpleHttpConnection
*hc
,
802 PurpleHttpResponse
*response
, gpointer _xfer
)
804 PurpleXfer
*xfer
= _xfer
;
805 struct yahoo_xfer_data
*xd
;
807 xd
= purple_xfer_get_protocol_data(xfer
);
811 if (purple_xfer_is_cancelled(xfer
))
814 if (!purple_http_response_is_successful(response
) ||
815 purple_xfer_get_bytes_remaining(xfer
) > 0)
817 purple_xfer_set_status(xfer
, PURPLE_XFER_STATUS_CANCEL_REMOTE
);
818 purple_xfer_end(xfer
);
820 purple_xfer_set_completed(xfer
, TRUE
);
821 purple_xfer_end(xfer
);
826 yahoo_process_filetrans_15_reader(PurpleHttpConnection
*hc
,
827 gchar
*buffer
, size_t offset
, size_t length
, gpointer _xfer
,
828 PurpleHttpContentReaderCb cb
)
830 PurpleXfer
*xfer
= _xfer
;
833 if ((goffset
)offset
!= purple_xfer_get_bytes_sent(xfer
)) {
834 purple_debug_warning("yahoo",
835 "offset != purple_xfer_get_bytes_sent(xfer)\n");
838 stored
= purple_xfer_read_file(xfer
, (guchar
*)buffer
, length
);
840 cb(hc
, (stored
>= 0), (purple_xfer_get_bytes_remaining(xfer
) == 0),
845 yahoo_process_filetrans_15_writer(PurpleHttpConnection
*http_conn
,
846 PurpleHttpResponse
*response
, const gchar
*buffer
, size_t offset
,
847 size_t length
, gpointer _xfer
)
849 PurpleXfer
*xfer
= _xfer
;
851 return purple_xfer_write_file(xfer
, (const guchar
*)buffer
, length
);
855 yahoo_process_filetrans_15_watcher(PurpleHttpConnection
*hc
,
856 gboolean reading_state
, int processed
, int total
, gpointer _xfer
)
858 PurpleXfer
*xfer
= _xfer
;
861 (purple_xfer_get_xfer_type(xfer
) == PURPLE_XFER_TYPE_RECEIVE
))
866 purple_xfer_set_size(xfer
, total
);
867 purple_xfer_update_progress(xfer
);
870 static void yahoo_xfer_start(PurpleXfer
*xfer
)
872 PurpleHttpRequest
*req
;
873 struct yahoo_xfer_data
*xd
;
875 xd
= purple_xfer_get_protocol_data(xfer
);
877 req
= yahoo_ft_new_req(xd
);
878 purple_http_request_set_timeout(req
, -1);
879 if (purple_xfer_get_xfer_type(xfer
) == PURPLE_XFER_TYPE_RECEIVE
) {
880 purple_http_request_set_max_len(req
, -1);
881 purple_http_request_set_response_writer(req
,
882 yahoo_process_filetrans_15_writer
, xfer
);
883 xd
->hc
= purple_http_request(xd
->gc
, req
,
884 yahoo_process_filetrans_15_downloaded
, xfer
);
886 purple_http_request_set_method(req
, "POST");
887 /* YHttpServer quirk: it sets content-length, but doesn't sends
889 purple_http_request_set_max_len(req
, 0);
890 purple_http_request_set_contents_reader(req
,
891 yahoo_process_filetrans_15_reader
,
892 purple_xfer_get_size(xfer
), xfer
);
893 xd
->hc
= purple_http_request(xd
->gc
, req
,
894 yahoo_process_filetrans_15_sent
, xfer
);
897 purple_http_conn_set_progress_watcher(xd
->hc
,
898 yahoo_process_filetrans_15_watcher
, xfer
, -1);
899 purple_http_request_unref(req
);
903 yahoo_process_filetrans_info_15_got(PurpleHttpConnection
*hc
,
904 PurpleHttpResponse
*response
, gpointer _xfer
)
906 PurpleXfer
*xfer
= _xfer
;
907 struct yahoo_xfer_data
*xd
;
910 xd
= purple_xfer_get_protocol_data(xfer
);
911 yd
= purple_connection_get_protocol_data(xd
->gc
);
915 if (!purple_http_response_is_successful(response
)) {
916 purple_notify_error(yd
->gc
, NULL
, _("File Transfer Failed"),
917 _("Unable to get file header."),
918 purple_request_cpar_from_connection(yd
->gc
));
919 purple_xfer_cancel_remote(xfer
);
923 purple_xfer_start(xfer
, -1, NULL
, 0);
926 void yahoo_process_filetrans_info_15(PurpleConnection
*gc
, struct yahoo_packet
*pkt
)
933 struct yahoo_xfer_data
*xfer_data
;
934 char *xfer_peer_idstring
= NULL
;
935 char *xfer_idstring_for_relay
= NULL
;
937 struct yahoo_packet
*pkt_to_send
;
939 yd
= purple_connection_get_protocol_data(gc
);
941 for (l
= pkt
->hash
; l
; l
= l
->next
) {
942 struct yahoo_pair
*pair
= l
->data
;
950 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
951 xfer_peer_idstring
= pair
->value
;
953 purple_debug_warning("yahoo", "yahoo_process_filetrans_info_15 "
954 "got non-UTF-8 string for key %d\n", pair
->key
);
957 case 27: /* filename */
960 val_66
= strtol(pair
->value
, NULL
, 10);
963 val_249
= strtol(pair
->value
, NULL
, 10);
964 /* 249 has value 1 or 2 when doing p2p transfer and value 3 when relaying through yahoo server */
967 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
968 url
= pair
->value
; /* TODO: rename to host? what about non-relay? */
970 purple_debug_warning("yahoo", "yahoo_process_filetrans_info_15 "
971 "got non-UTF-8 string for key %d\n", pair
->key
);
975 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
976 xfer_idstring_for_relay
= pair
->value
;
978 purple_debug_warning("yahoo", "yahoo_process_filetrans_info_15 "
979 "got non-UTF-8 string for key %d\n", pair
->key
);
985 if(!xfer_peer_idstring
)
988 xfer
= g_hash_table_lookup(yd
->xfer_peer_idstring_map
, xfer_peer_idstring
);
994 purple_xfer_cancel_remote(xfer
);
998 xfer_data
= purple_xfer_get_protocol_data(xfer
);
1000 xfer_data
->info_val_249
= val_249
;
1001 xfer_data
->xfer_idstring_for_relay
= g_strdup(xfer_idstring_for_relay
);
1002 if(val_249
== 1 || val_249
== 3) {
1003 PurpleHttpRequest
*req
;
1004 PurpleAccount
*account
;
1006 xfer_data
->is_relay
= (val_249
== 3);
1008 if (!xfer_data
->is_relay
) {
1009 purple_debug_error("yahoo", "Non-relay FT aren't tested yet.\n");
1010 purple_notify_error(gc
, NULL
, _("File Transfer Failed"),
1011 _("Unsupported method"),
1012 purple_request_cpar_from_connection(gc
));
1013 purple_xfer_cancel_remote(xfer
);
1016 account
= purple_connection_get_account(xfer_data
->gc
);
1018 xfer_data
->url
= yahoo_ft_url_gen(xfer
, url
);
1020 pkt_to_send
= yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15
,
1021 YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
1022 yahoo_packet_hash(pkt_to_send
, "ssssis",
1023 1, purple_normalize(account
, purple_account_get_username(account
)),
1024 5, purple_xfer_get_remote_user(xfer
),
1025 265, xfer_data
->xfer_peer_idstring
,
1026 27, purple_xfer_get_filename(xfer
),
1027 249, xfer_data
->info_val_249
,
1028 251, xfer_data
->xfer_idstring_for_relay
);
1030 yahoo_packet_send_and_free(pkt_to_send
, yd
);
1032 req
= yahoo_ft_new_req(xfer_data
);
1033 purple_http_request_set_method(req
, "HEAD");
1034 xfer_data
->hc
= purple_http_request(gc
, req
, yahoo_process_filetrans_info_15_got
, xfer
);
1035 purple_http_request_unref(req
);
1037 else if (val_249
== 2)
1038 purple_debug_error("yahoo", "p2p file transfers are not supported yet\n");
1041 /* TODO: Check filename etc. No probs till some hacker comes in the way */
1042 void yahoo_process_filetrans_acc_15(PurpleConnection
*gc
, struct yahoo_packet
*pkt
)
1044 gchar
*xfer_peer_idstring
= NULL
;
1045 gchar
*xfer_idstring_for_relay
= NULL
;
1048 struct yahoo_xfer_data
*xfer_data
;
1054 yd
= purple_connection_get_protocol_data(gc
);
1055 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1056 struct yahoo_pair
*pair
= l
->data
;
1058 switch (pair
->key
) {
1060 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
1061 xfer_idstring_for_relay
= pair
->value
;
1063 purple_debug_warning("yahoo", "yahoo_process_filetrans_acc_15 "
1064 "got non-UTF-8 string for key %d\n", pair
->key
);
1068 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
1069 xfer_peer_idstring
= pair
->value
;
1071 purple_debug_warning("yahoo", "yahoo_process_filetrans_acc_15 "
1072 "got non-UTF-8 string for key %d\n", pair
->key
);
1076 val_66
= atol(pair
->value
);
1079 val_249
= atol(pair
->value
);
1082 if (g_utf8_validate(pair
->value
, -1, NULL
)) {
1083 /* we get a p2p url here when sending file, connected as client */
1086 purple_debug_warning("yahoo", "yahoo_process_filetrans_acc_15 "
1087 "got non-UTF-8 string for key %d\n", pair
->key
);
1093 xfer
= g_hash_table_lookup(yd
->xfer_peer_idstring_map
, xfer_peer_idstring
);
1096 if(val_66
== -1 || ( (!(xfer_idstring_for_relay
)) && (val_249
!= 2) ))
1098 purple_xfer_cancel_remote(xfer
);
1102 if( (val_249
== 2) && (!(url
)) )
1104 purple_xfer_cancel_remote(xfer
);
1108 xfer_data
= purple_xfer_get_protocol_data(xfer
);
1110 xfer_data
->host
= g_strdup(url
);
1112 xfer_data
->xfer_idstring_for_relay
= g_strdup(xfer_idstring_for_relay
);
1114 xfer_data
->url
= yahoo_ft_url_gen(xfer
, xfer_data
->host
);
1115 purple_xfer_start(xfer
, -1, NULL
, 0);
1119 yahoo_ft_new_xfer_struct(PurpleConnection
*gc
, PurpleXferType type
, const char *who
)
1123 g_return_val_if_fail(gc
!= NULL
, NULL
);
1124 g_return_val_if_fail(who
!= NULL
, NULL
);
1126 xfer
= purple_xfer_new(purple_connection_get_account(gc
), type
, who
);
1128 g_return_val_if_fail(xfer
!= NULL
, NULL
);
1130 purple_xfer_set_init_fnc(xfer
, yahoo_xfer_init_15
);
1131 purple_xfer_set_start_fnc(xfer
, yahoo_xfer_start
);
1132 purple_xfer_set_end_fnc(xfer
, yahoo_xfer_end
);
1133 purple_xfer_set_cancel_send_fnc(xfer
, yahoo_xfer_cancel_send
);
1134 purple_xfer_set_cancel_recv_fnc(xfer
, yahoo_xfer_cancel_recv
);
1135 purple_xfer_set_request_denied_fnc(xfer
, yahoo_xfer_cancel_recv
);