6 * Copyright (C) 2010-2018 SIPE Project <http://sipe.sourceforge.net/>
7 * Copyright (C) 2010 Jakub Adam <jakub.adam@ktknet.cz>
8 * Copyright (C) 2010 Tomáš Hrabčík <tomas.hrabcik@tieto.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <sys/types.h>
32 #include <glib/gstdio.h>
34 #include "miranda-version.h"
35 #include "newpluginapi.h"
36 #include "m_protosvc.h"
37 #include "m_protoint.h"
38 #include "m_database.h"
39 #include "m_protomod.h"
42 #include "sipe-common.h"
43 #include "sipe-backend.h"
44 #include "sipe-core.h"
45 #include "miranda-private.h"
47 #define FT_SIPE_DEBUG_INFO(fmt, ...) sipe_backend_debug(SIPE_DEBUG_LEVEL_INFO, "[FT:%08x] %s: " fmt, ft, __func__, __VA_ARGS__)
48 #define FT_SIPE_DEBUG_INFO_NOFORMAT(msg) sipe_backend_debug(SIPE_DEBUG_LEVEL_INFO, "[FT:%08x] %s: %s", ft, __func__, msg)
50 #define FT_INITIAL_BUFFER_SIZE 4096
51 #define FT_MAX_BUFFER_SIZE 65535
55 SIPE_MIRANDA_XFER_STATUS_UNKNOWN
= 0, /**< Unknown, the xfer may be null. */
56 // SIPE_MIRANDA_XFER_STATUS_NOT_STARTED, /**< It hasn't started yet. */
57 // SIPE_MIRANDA_XFER_STATUS_ACCEPTED, /**< Receive accepted, but destination file not selected yet */
58 SIPE_MIRANDA_XFER_STATUS_STARTED
, /**< purple_xfer_start has been called. */
59 SIPE_MIRANDA_XFER_STATUS_DONE
, /**< The xfer completed successfully. */
60 SIPE_MIRANDA_XFER_STATUS_CANCEL_LOCAL
, /**< The xfer was cancelled by us. */
61 SIPE_MIRANDA_XFER_STATUS_CANCEL_REMOTE
/**< The xfer was cancelled by the other end, or we couldn't connect. */
62 } sipe_miranda_xfer_status
;
64 struct sipe_backend_file_transfer
{
68 struct sipe_file_transfer
*ft
;
71 size_t bytes_remaining
;
72 size_t current_buffer_size
;
73 struct sipe_miranda_sel_entry
*watcher
;
75 gchar
*local_filename
;
81 PROTOFILETRANSFERSTATUS st
;
82 sipe_miranda_xfer_status status
;
86 update_progress(struct sipe_backend_file_transfer
*xfer
)
89 ZeroMemory(pfts
, sizeof(PROTOFILETRANSFERSTATUS
));
90 pfts
->flags
= PFTS_UTF
| (ft
->sending
? PFTS_SENDING
: PFTS_RECEIVING
); /* Standard FT is Ansi only */
92 pfts
->pszFiles
= ft
->pszFiles
;
94 pfts
->pszFiles
= NULL
; /* FIXME */
95 pfts
->currentFileTime
= ft
->dwThisFileDate
;
98 xfer
->st
.flags
= (xfer
->incoming
? PFTS_RECEIVING
: PFTS_SENDING
);
99 xfer
->st
.szWorkingDir
= "none";
100 xfer
->st
.szCurrentFile
= xfer
->filename
;
101 xfer
->st
.totalFiles
= 1;
102 xfer
->st
.totalBytes
= xfer
->file_size
;
103 xfer
->st
.totalProgress
= xfer
->bytes_sent
;
104 xfer
->st
.currentFileNumber
= 1;
105 xfer
->st
.currentFileSize
= xfer
->file_size
;
106 xfer
->st
.currentFileProgress
= xfer
->bytes_sent
;
108 ProtoBroadcastAck(xfer
->pr
->proto
.m_szModuleName
,
117 increase_buffer_size(struct sipe_backend_file_transfer
*xfer
)
119 xfer
->current_buffer_size
= MIN(xfer
->current_buffer_size
* 1.5,
123 void sipe_backend_ft_error(struct sipe_file_transfer
*ft
,
128 FT_SIPE_DEBUG_INFO("file transfer error: <%s>", errmsg
);
130 if (ft
->backend_private
->incoming
)
132 msg
= g_strdup_printf("Incoming file transfer failed");
134 msg
= g_strdup_printf("Outgoing file transfer failed");
137 sipe_miranda_AddEvent(ft
->backend_private
->pr
, ft
->backend_private
->hContact
, SIPE_EVENTTYPE_ERROR_NOTIFY
, time(NULL
), DBEF_UTF
, strlen(msg
), (PBYTE
)msg
);
142 const gchar
*sipe_backend_ft_get_error(SIPE_UNUSED_PARAMETER
struct sipe_file_transfer
*ft
)
145 return strerror(errno
); /* FIXME: Only valid for the file side i think */
149 free_xfer_struct(struct sipe_backend_file_transfer
*xfer
)
151 struct sipe_file_transfer
*ft
= xfer
->ft
;
155 sipe_miranda_input_remove(xfer
->watcher
);
158 if (ft
->deallocate
) {
166 cancel_remote(struct sipe_backend_file_transfer
*xfer
)
168 struct sipe_file_transfer
*ft
= xfer
->ft
;
170 FT_SIPE_DEBUG_INFO_NOFORMAT("");
174 xfer
->status
= SIPE_MIRANDA_XFER_STATUS_CANCEL_REMOTE
;
175 xfer
->end_time
= time(NULL
);
177 msg
= g_strdup_printf("File transfer cancelled by peer");
178 sipe_miranda_AddEvent(ft
->backend_private
->pr
, ft
->backend_private
->hContact
, SIPE_EVENTTYPE_ERROR_NOTIFY
, time(NULL
), DBEF_UTF
, strlen(msg
), (PBYTE
)msg
);
181 free_xfer_struct(xfer
);
183 if (xfer
->watcher
!= 0) {
184 sipe_miranda_input_remove(xfer
->watcher
);
189 Netlib_CloseHandle(xfer
->fd
);
191 if (xfer
->dest_fp
!= NULL
) {
192 fclose(xfer
->dest_fp
);
193 xfer
->dest_fp
= NULL
;
196 xfer
->bytes_remaining
= 0;
197 g_free(xfer
->filename
);
198 /* g_free(xfer); FIXME: needs refcounting like purple i guess */
201 void sipe_backend_ft_deallocate(struct sipe_file_transfer
*ft
)
203 struct sipe_backend_file_transfer
*xfer
= ft
->backend_private
;
205 /* If file transfer is not finished, cancel it */
206 if (xfer
->status
!= SIPE_MIRANDA_XFER_STATUS_DONE
207 && xfer
->status
!= SIPE_MIRANDA_XFER_STATUS_CANCEL_LOCAL
208 && xfer
->status
!= SIPE_MIRANDA_XFER_STATUS_CANCEL_REMOTE
)
215 gssize
sipe_backend_ft_read(struct sipe_file_transfer
*ft
,
221 FT_SIPE_DEBUG_INFO("reading up to <%d> bytes", size
);
222 bytes_read
= Netlib_Recv(ft
->backend_private
->fd
, data
, size
, MSG_NODUMP
);
223 FT_SIPE_DEBUG_INFO("came back from read <%d>", bytes_read
);
224 if (bytes_read
== 0) {
225 /* Sender canceled transfer before it was finished */
226 FT_SIPE_DEBUG_INFO_NOFORMAT("no read cause sender cancelled");
228 } else if (bytes_read
== SOCKET_ERROR
) {
229 int err
= WSAGetLastError();
230 if (err
== WSAEWOULDBLOCK
) {
233 FT_SIPE_DEBUG_INFO("Error reading <%d>", err
);
237 FT_SIPE_DEBUG_INFO("read <%d> bytes [%02x:%c]", bytes_read
, *data
, *data
);
241 gssize
sipe_backend_ft_write(struct sipe_file_transfer
*ft
,
246 FT_SIPE_DEBUG_INFO("writing <%d> bytes", size
);
247 bytes_written
= Netlib_Send(ft
->backend_private
->fd
, data
, size
, MSG_NODUMP
);
248 if (bytes_written
== SOCKET_ERROR
) {
249 int err
= WSAGetLastError();
250 if (err
== WSAEWOULDBLOCK
) {
253 FT_SIPE_DEBUG_INFO("Error writing <%u>", err
);
257 FT_SIPE_DEBUG_INFO("wrote <%d> bytes", bytes_written
);
258 return bytes_written
;
262 cancel_local(struct sipe_backend_file_transfer
*xfer
)
264 struct sipe_file_transfer
*ft
= xfer
->ft
;
266 FT_SIPE_DEBUG_INFO_NOFORMAT("");
268 xfer
->status
= SIPE_MIRANDA_XFER_STATUS_CANCEL_LOCAL
;
269 xfer
->end_time
= time(NULL
);
271 msg
= g_strdup_printf("File transfer cancelled");
272 sipe_miranda_AddEvent(ft
->backend_private
->pr
, ft
->backend_private
->hContact
, SIPE_EVENTTYPE_ERROR_NOTIFY
, time(NULL
), DBEF_UTF
, strlen(msg
), (PBYTE
)msg
);
275 free_xfer_struct(xfer
);
277 if (xfer
->watcher
!= 0) {
278 sipe_miranda_input_remove(xfer
->watcher
);
283 Netlib_CloseHandle(xfer
->fd
);
285 if (xfer
->dest_fp
!= NULL
) {
286 fclose(xfer
->dest_fp
);
287 xfer
->dest_fp
= NULL
;
290 xfer
->bytes_remaining
= 0;
292 g_free(xfer
->filename
);
296 void sipe_backend_ft_set_completed(struct sipe_file_transfer
*ft
)
301 void sipe_backend_ft_cancel_local(struct sipe_file_transfer
*ft
)
303 cancel_local(ft
->backend_private
);
306 void sipe_backend_ft_cancel_remote(struct sipe_file_transfer
*ft
)
308 cancel_remote(ft
->backend_private
);
311 static struct sipe_backend_file_transfer
*
312 new_xfer(SIPPROTO
*pr
,
313 struct sipe_file_transfer
*ft
,
316 struct sipe_backend_file_transfer
*xfer
= g_new0(struct sipe_backend_file_transfer
, 1);
318 xfer
->current_buffer_size
= FT_INITIAL_BUFFER_SIZE
;
319 xfer
->buffer
= g_byte_array_sized_new(FT_INITIAL_BUFFER_SIZE
);
321 xfer
->hContact
= hContact
;
324 xfer
->st
.cbSize
= sizeof(PROTOFILETRANSFERSTATUS
);
325 xfer
->st
.hContact
= hContact
;
330 void sipe_backend_ft_incoming(struct sipe_core_public
*sipe_public
,
331 struct sipe_file_transfer
*ft
,
333 const gchar
*file_name
,
336 SIPPROTO
*pr
= sipe_public
->backend_private
;
337 PROTORECVFILET pre
= {0};
341 FT_SIPE_DEBUG_INFO("Incoming ft <%08x> from <%s> file <%s> size <%d>", ft
, who
, file_name
, file_size
);
342 hContact
= sipe_backend_buddy_find( sipe_public
, who
, NULL
);
345 FT_SIPE_DEBUG_INFO("Adding miranda contact for incoming transfer from <%s>", who
);
346 hContact
= ( HANDLE
)CallService( MS_DB_CONTACT_ADD
, 0, 0 );
347 CallService( MS_PROTO_ADDTOCONTACT
, ( WPARAM
)hContact
,( LPARAM
)pr
->proto
.m_szModuleName
);
348 DBWriteContactSettingByte( hContact
, "CList", "NotOnList", 1 );
349 sipe_miranda_setContactString( pr
, hContact
, SIP_UNIQUEID
, who
); // name
352 ft
->backend_private
= new_xfer(pr
, ft
, hContact
);
353 ft
->backend_private
->incoming
= TRUE
;
354 ft
->backend_private
->file_size
= file_size
;
355 ft
->backend_private
->bytes_remaining
= file_size
;
356 ft
->backend_private
->bytes_sent
= 0;
357 ft
->backend_private
->filename
= g_strdup(file_name
);
359 pre
.flags
= PREF_TCHAR
;
360 pre
.timestamp
= time(NULL
);
361 pre
.tszDescription
= mir_a2t(file_name
);
363 pre
.ptszFiles
= &pre
.tszDescription
;
364 pre
.lParam
= (LPARAM
)ft
;
366 ccs
.szProtoService
= PSR_FILE
;
367 ccs
.hContact
= hContact
;
369 ccs
.lParam
= (LPARAM
)&pre
;
370 CallService(MS_PROTO_CHAINRECV
, 0, (LPARAM
)&ccs
);
375 sipe_backend_ft_outgoing(struct sipe_core_public
*sipe_public
,
376 struct sipe_file_transfer
*ft
,
378 const gchar
*file_name
)
380 SIPPROTO
*pr
= sipe_public
->backend_private
;
386 hContact
= sipe_backend_buddy_find( sipe_public
, who
, NULL
);
387 ft
->backend_private
= new_xfer(pr
, ft
, hContact
);
388 ft
->backend_private
->incoming
= FALSE
;
389 result
= _tstat64( file_name
, &buf
);
392 FT_SIPE_DEBUG_INFO("Could not stat file, error<%d>", result
);
393 ft
->backend_private
->file_size
= 0;
397 ft
->backend_private
->file_size
= buf
.st_size
;
398 ft
->backend_private
->bytes_remaining
= ft
->backend_private
->file_size
;
399 ft
->backend_private
->bytes_sent
= 0;
401 ft
->backend_private
->local_filename
= g_strdup(file_name
);
402 ft
->backend_private
->filename
= g_path_get_basename(ft
->backend_private
->local_filename
);
403 FT_SIPE_DEBUG_INFO("set filename to <%s>", ft
->backend_private
->filename
);
404 ft
->init(ft
, ft
->backend_private
->filename
, ft
->backend_private
->file_size
, who
);
405 sipe_miranda_SendBroadcast(pr
, hContact
, ACKTYPE_FILE
, ACKRESULT_CONNECTING
, (HANDLE
)ft
->backend_private
, 0);
410 sipe_backend_ft_incoming_accept(struct sipe_file_transfer
*ft
,
412 unsigned short port_min
,
413 unsigned short port_max
)
420 set_completed(struct sipe_backend_file_transfer
*xfer
, gboolean completed
)
422 if (completed
== TRUE
) {
425 xfer
->status
= SIPE_MIRANDA_XFER_STATUS_DONE
;
427 if (xfer
->filename
!= NULL
)
429 char *filename
= g_markup_escape_text(xfer
->filename
, -1);
430 if (xfer
->local_filename
&& xfer
->incoming
)
432 char *local
= g_markup_escape_text(xfer
->local_filename
, -1);
433 msg
= g_strdup_printf("Transfer of file <A HREF=\"file://%s\">%s</A> complete",
438 msg
= g_strdup_printf("Transfer of file %s complete",
443 msg
= g_strdup("File transfer complete");
445 sipe_miranda_AddEvent(xfer
->pr
, xfer
->hContact
, SIPE_EVENTTYPE_ERROR_NOTIFY
, time(NULL
), DBEF_UTF
, strlen(msg
), (PBYTE
)msg
);
446 sipe_miranda_SendBroadcast(xfer
->pr
, xfer
->hContact
, ACKTYPE_FILE
, ACKRESULT_SUCCESS
, (HANDLE
)xfer
, 0);
451 update_progress(xfer
);
455 do_transfer(struct sipe_backend_file_transfer
*xfer
)
458 guchar
*buffer
= NULL
;
460 struct sipe_file_transfer
*ft
= xfer
->ft
;
462 FT_SIPE_DEBUG_INFO("incoming <%d>", xfer
->incoming
);
463 if (xfer
->incoming
) {
464 FT_SIPE_DEBUG_INFO_NOFORMAT("incoming branch");
465 r
= ft
->read(xfer
->ft
, &buffer
, xfer
->bytes_remaining
,
466 xfer
->current_buffer_size
);
469 wc
= fwrite(buffer
, 1, r
, xfer
->dest_fp
);
472 SIPE_DEBUG_ERROR("Unable to write whole buffer.");
478 if ((xfer
->file_size
> 0) && ((xfer
->bytes_sent
+r
) >= xfer
->file_size
))
479 set_completed(xfer
, TRUE
);
488 size_t s
= MIN(xfer
->bytes_remaining
, xfer
->current_buffer_size
);
489 gboolean read
= TRUE
;
490 FT_SIPE_DEBUG_INFO("outgoing branch, size <%u>", s
);
492 /* this is so the prpl can keep the connection open
493 if it needs to for some odd reason. */
496 sipe_miranda_input_remove(xfer
->watcher
);
503 if (xfer
->buffer
->len
< s
) {
504 s
-= xfer
->buffer
->len
;
512 buffer
= g_malloc(s
);
513 result
= fread(buffer
, 1, s
, xfer
->dest_fp
);
515 FT_SIPE_DEBUG_INFO_NOFORMAT("Unable to read whole buffer.");
523 g_byte_array_append(xfer
->buffer
, buffer
, result
);
525 buffer
= xfer
->buffer
->data
;
526 result
= xfer
->buffer
->len
;
529 s
= MIN(xfer
->bytes_remaining
, result
);
530 r
= ft
->write(ft
, buffer
, s
);
532 if ((xfer
->bytes_remaining
- r
) == 0)
533 set_completed(xfer
, TRUE
);
535 if (r
>= 0 && (xfer
->bytes_sent
+r
) >= xfer
->file_size
&& xfer
->status
!= SIPE_MIRANDA_XFER_STATUS_DONE
)
536 set_completed(xfer
, TRUE
);
542 /* We don't free buffer if priv->buffer is set, because in
543 that case buffer doesn't belong to us. */
546 } else if (r
== result
) {
548 * We managed to write the entire buffer. This means our
549 * network is fast and our buffer is too small, so make it
552 increase_buffer_size(xfer
);
557 * Remove what we wrote
558 * If we wrote the whole buffer the byte array will be empty
559 * Otherwise we'll keep what wasn't sent for next time.
562 g_byte_array_remove_range(xfer
->buffer
, 0, r
);
566 FT_SIPE_DEBUG_INFO_NOFORMAT("back to common code");
568 if (xfer
->file_size
> 0)
569 xfer
->bytes_remaining
-= r
;
571 xfer
->bytes_sent
+= r
;
574 update_progress(xfer
);
577 if (xfer
->status
== SIPE_MIRANDA_XFER_STATUS_DONE
)
579 xfer
->end_time
= time(NULL
);
580 if (xfer
->ft
->end
&& xfer
->ft
->end(xfer
->ft
)) {
581 /* We're done with this transfer */
582 free_xfer_struct(xfer
);
583 } else if (xfer
->incoming
) {
584 _unlink(xfer
->local_filename
);
587 if (xfer
->watcher
!= 0) {
588 sipe_miranda_input_remove(xfer
->watcher
);
593 Netlib_CloseHandle(xfer
->fd
);
595 if (xfer
->dest_fp
!= NULL
) {
596 fclose(xfer
->dest_fp
);
597 xfer
->dest_fp
= NULL
;
600 g_free(xfer
->filename
);
606 transfer_cb(gpointer data
, gint source
, sipe_miranda_input_condition condition
)
608 struct sipe_backend_file_transfer
*xfer
= data
;
609 SIPE_DEBUG_INFO_NOFORMAT("");
614 begin_transfer(struct sipe_file_transfer
*ft
)
616 struct sipe_backend_file_transfer
*xfer
= ft
->backend_private
;
617 SIPPROTO
*pr
= xfer
->pr
;
619 xfer
->dest_fp
= fopen(xfer
->local_filename
, xfer
->incoming
? "wb" : "rb");
620 if (xfer
->dest_fp
== NULL
) {
625 msg
= g_strdup_printf("Error reading %s: \n%s.\n", xfer
->local_filename
, g_strerror(err
));
627 msg
= g_strdup_printf("Error writing %s: \n%s.\n", xfer
->local_filename
, g_strerror(err
));
629 sipe_miranda_AddEvent(ft
->backend_private
->pr
, ft
->backend_private
->hContact
, SIPE_EVENTTYPE_ERROR_NOTIFY
, time(NULL
), DBEF_UTF
, strlen(msg
), (PBYTE
)msg
);
631 FT_SIPE_DEBUG_INFO("error opening local file: %s", g_strerror(errno
));
636 fseek(xfer
->dest_fp
, xfer
->bytes_sent
, SEEK_SET
);
638 xfer
->start_time
= time(NULL
);
641 FT_SIPE_DEBUG_INFO("incoming <%d> size <%d>", ft
->backend_private
->incoming
, ft
->backend_private
->file_size
);
642 if (!ft
->backend_private
->incoming
) {
643 /* Set socket to nonblocking */
644 SOCKET sock
= CallService(MS_NETLIB_GETSOCKET
, (WPARAM
)xfer
->fd
, (LPARAM
)0);
645 unsigned long parm
= 1;
647 if (ioctlsocket(sock
, FIONBIO
, &parm
) == SOCKET_ERROR
)
649 FT_SIPE_DEBUG_INFO("Error ioctlsocket <%d>", WSAGetLastError());
652 FT_SIPE_DEBUG_INFO("outgoing ft <%08x> size <%d>", ft
, ft
->backend_private
->file_size
);
655 ft
->start(ft
, ft
->backend_private
->file_size
);
660 xfer
->watcher
= sipe_miranda_input_add(xfer
->fd
, xfer
->incoming
?SIPE_MIRANDA_INPUT_READ
:SIPE_MIRANDA_INPUT_WRITE
, transfer_cb
, xfer
);
662 FT_SIPE_DEBUG_INFO("watcher [%08x]", xfer
->watcher
);
666 ft_connected_callback(HANDLE fd
, void* data
, const gchar
*reason
)
668 struct sipe_file_transfer
*ft
= (struct sipe_file_transfer
*)data
;
669 struct sipe_backend_file_transfer
*xfer
= ft
->backend_private
;
670 SIPPROTO
*pr
= ft
->backend_private
->pr
;
676 ft
->backend_private
->fd
= fd
;
683 sipe_backend_ft_start(struct sipe_file_transfer
*ft
, struct sipe_backend_fd
*fd
,
684 const char* ip
, unsigned port
)
686 ft
->backend_private
->status
= SIPE_MIRANDA_XFER_STATUS_STARTED
;
690 FT_SIPE_DEBUG_INFO("Should connect to <%s:%d>", ip
, port
);
691 sipe_miranda_connect(ft
->backend_private
->pr
, ip
, port
, FALSE
, 5, ft_connected_callback
, ft
);
695 FT_SIPE_DEBUG_INFO("Should use incoming fd <%08x>", fd
);
696 ft
->backend_private
->fd
= fd
;
701 sipe_backend_ft_is_incoming(struct sipe_file_transfer
*ft
)
703 FT_SIPE_DEBUG_INFO("ft <%08x> incoming <%d>", ft
, ft
->backend_private
->incoming
);
704 return ft
->backend_private
->incoming
;
708 sipe_miranda_SendFile( SIPPROTO
*pr
, HANDLE hContact
, const PROTOCHAR
* szDescription
, PROTOCHAR
** ppszFiles
)
712 if ( !DBGetContactSettingString( hContact
, pr
->proto
.m_szModuleName
, SIP_UNIQUEID
, &dbv
)) {
713 struct sipe_file_transfer
*ft
;
715 ft
= sipe_core_ft_create_outgoing(pr
->sip
, dbv
.pszVal
, TCHAR2CHAR(ppszFiles
[0]));
717 FT_SIPE_DEBUG_INFO("SendFile: desc <%ls> name <%s> size <%d> to <%s>", szDescription
, TCHAR2CHAR(ppszFiles
[0]), ft
->backend_private
->file_size
, dbv
.pszVal
);
719 DBFreeVariant( &dbv
);
721 return ft
->backend_private
;
728 sipe_miranda_RecvFile( SIPPROTO
*pr
, HANDLE hContact
, PROTOFILEEVENT
* evt
)
730 CCSDATA ccs
= { hContact
, PSR_FILE
, 0, (LPARAM
)evt
};
731 return CallService(MS_PROTO_RECVFILET
, 0, (LPARAM
)&ccs
);
735 sipe_miranda_FileAllow( SIPPROTO
*pr
, HANDLE hContact
, HANDLE hTransfer
, const PROTOCHAR
* szPath
)
737 struct sipe_file_transfer
*ft
= (struct sipe_file_transfer
*)hTransfer
;
738 FT_SIPE_DEBUG_INFO("Incoming ft <%08x> allowed", ft
);
739 ft
->backend_private
->local_filename
= g_strdup_printf("%s%s", TCHAR2CHAR(szPath
), ft
->backend_private
->filename
);
740 sipe_miranda_SendBroadcast(pr
, hContact
, ACKTYPE_FILE
, ACKRESULT_CONNECTING
, (HANDLE
)ft
->backend_private
, 0);
741 ft
->init(ft
, ft
->backend_private
->filename
, ft
->backend_private
->file_size
, NULL
);
742 return ft
->backend_private
;
746 sipe_miranda_FileDeny( SIPPROTO
*pr
, HANDLE hContact
, HANDLE hTransfer
, const PROTOCHAR
* szReason
)
748 struct sipe_file_transfer
*ft
= (struct sipe_file_transfer
*)hTransfer
;
749 FT_SIPE_DEBUG_INFO("FileDeny: reason <%s>", szReason
);
750 if (ft
->backend_private
->incoming
&& ft
->request_denied
)
751 ft
->request_denied(ft
);
752 free_xfer_struct(ft
->backend_private
);