6 * Copyright (C) 2010-2016 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"
46 #include "miranda-private.h"
48 #define FT_SIPE_DEBUG_INFO(fmt, ...) sipe_backend_debug(SIPE_DEBUG_LEVEL_INFO, "[FT:%08x] %s: " fmt, ft, __func__, __VA_ARGS__)
49 #define FT_SIPE_DEBUG_INFO_NOFORMAT(msg) sipe_backend_debug(SIPE_DEBUG_LEVEL_INFO, "[FT:%08x] %s: %s", ft, __func__, msg)
51 #define FT_INITIAL_BUFFER_SIZE 4096
52 #define FT_MAX_BUFFER_SIZE 65535
56 SIPE_MIRANDA_XFER_STATUS_UNKNOWN
= 0, /**< Unknown, the xfer may be null. */
57 // SIPE_MIRANDA_XFER_STATUS_NOT_STARTED, /**< It hasn't started yet. */
58 // SIPE_MIRANDA_XFER_STATUS_ACCEPTED, /**< Receive accepted, but destination file not selected yet */
59 SIPE_MIRANDA_XFER_STATUS_STARTED
, /**< purple_xfer_start has been called. */
60 SIPE_MIRANDA_XFER_STATUS_DONE
, /**< The xfer completed successfully. */
61 SIPE_MIRANDA_XFER_STATUS_CANCEL_LOCAL
, /**< The xfer was cancelled by us. */
62 SIPE_MIRANDA_XFER_STATUS_CANCEL_REMOTE
/**< The xfer was cancelled by the other end, or we couldn't connect. */
63 } sipe_miranda_xfer_status
;
65 struct sipe_backend_file_transfer
{
69 struct sipe_file_transfer
*ft
;
72 size_t bytes_remaining
;
73 size_t current_buffer_size
;
74 struct sipe_miranda_sel_entry
*watcher
;
76 gchar
*local_filename
;
82 PROTOFILETRANSFERSTATUS st
;
83 sipe_miranda_xfer_status status
;
87 update_progress(struct sipe_backend_file_transfer
*xfer
)
90 ZeroMemory(pfts
, sizeof(PROTOFILETRANSFERSTATUS
));
91 pfts
->flags
= PFTS_UTF
| (ft
->sending
? PFTS_SENDING
: PFTS_RECEIVING
); /* Standard FT is Ansi only */
93 pfts
->pszFiles
= ft
->pszFiles
;
95 pfts
->pszFiles
= NULL
; /* FIXME */
96 pfts
->currentFileTime
= ft
->dwThisFileDate
;
99 xfer
->st
.flags
= (xfer
->incoming
? PFTS_RECEIVING
: PFTS_SENDING
);
100 xfer
->st
.szWorkingDir
= "none";
101 xfer
->st
.szCurrentFile
= xfer
->filename
;
102 xfer
->st
.totalFiles
= 1;
103 xfer
->st
.totalBytes
= xfer
->file_size
;
104 xfer
->st
.totalProgress
= xfer
->bytes_sent
;
105 xfer
->st
.currentFileNumber
= 1;
106 xfer
->st
.currentFileSize
= xfer
->file_size
;
107 xfer
->st
.currentFileProgress
= xfer
->bytes_sent
;
109 ProtoBroadcastAck(xfer
->pr
->proto
.m_szModuleName
,
118 increase_buffer_size(struct sipe_backend_file_transfer
*xfer
)
120 xfer
->current_buffer_size
= MIN(xfer
->current_buffer_size
* 1.5,
124 void sipe_backend_ft_error(struct sipe_file_transfer
*ft
,
129 FT_SIPE_DEBUG_INFO("file transfer error: <%s>", errmsg
);
131 if (ft
->backend_private
->incoming
)
133 msg
= g_strdup_printf("Incoming file transfer failed");
135 msg
= g_strdup_printf("Outgoing file transfer failed");
138 sipe_miranda_AddEvent(ft
->backend_private
->pr
, ft
->backend_private
->hContact
, SIPE_EVENTTYPE_ERROR_NOTIFY
, time(NULL
), DBEF_UTF
, strlen(msg
), (PBYTE
)msg
);
143 const gchar
*sipe_backend_ft_get_error(SIPE_UNUSED_PARAMETER
struct sipe_file_transfer
*ft
)
146 return strerror(errno
); /* FIXME: Only valid for the file side i think */
150 free_xfer_struct(struct sipe_backend_file_transfer
*xfer
)
152 struct sipe_file_transfer
*ft
= xfer
->ft
;
156 sipe_miranda_input_remove(xfer
->watcher
);
159 if (ft
->deallocate
) {
167 cancel_remote(struct sipe_backend_file_transfer
*xfer
)
169 struct sipe_file_transfer
*ft
= xfer
->ft
;
171 FT_SIPE_DEBUG_INFO_NOFORMAT("");
175 xfer
->status
= SIPE_MIRANDA_XFER_STATUS_CANCEL_REMOTE
;
176 xfer
->end_time
= time(NULL
);
178 msg
= g_strdup_printf("File transfer cancelled by peer");
179 sipe_miranda_AddEvent(ft
->backend_private
->pr
, ft
->backend_private
->hContact
, SIPE_EVENTTYPE_ERROR_NOTIFY
, time(NULL
), DBEF_UTF
, strlen(msg
), (PBYTE
)msg
);
182 free_xfer_struct(xfer
);
184 if (xfer
->watcher
!= 0) {
185 sipe_miranda_input_remove(xfer
->watcher
);
190 Netlib_CloseHandle(xfer
->fd
);
192 if (xfer
->dest_fp
!= NULL
) {
193 fclose(xfer
->dest_fp
);
194 xfer
->dest_fp
= NULL
;
197 xfer
->bytes_remaining
= 0;
198 g_free(xfer
->filename
);
199 /* g_free(xfer); FIXME: needs refcounting like purple i guess */
202 void sipe_backend_ft_deallocate(struct sipe_file_transfer
*ft
)
204 struct sipe_backend_file_transfer
*xfer
= ft
->backend_private
;
206 /* If file transfer is not finished, cancel it */
207 if (xfer
->status
!= SIPE_MIRANDA_XFER_STATUS_DONE
208 && xfer
->status
!= SIPE_MIRANDA_XFER_STATUS_CANCEL_LOCAL
209 && xfer
->status
!= SIPE_MIRANDA_XFER_STATUS_CANCEL_REMOTE
)
216 gssize
sipe_backend_ft_read(struct sipe_file_transfer
*ft
,
222 FT_SIPE_DEBUG_INFO("reading up to <%d> bytes", size
);
223 bytes_read
= Netlib_Recv(ft
->backend_private
->fd
, data
, size
, MSG_NODUMP
);
224 FT_SIPE_DEBUG_INFO("came back from read <%d>", bytes_read
);
225 if (bytes_read
== 0) {
226 /* Sender canceled transfer before it was finished */
227 FT_SIPE_DEBUG_INFO_NOFORMAT("no read cause sender cancelled");
229 } else if (bytes_read
== SOCKET_ERROR
) {
230 int err
= WSAGetLastError();
231 if (err
== WSAEWOULDBLOCK
) {
234 FT_SIPE_DEBUG_INFO("Error reading <%d>", err
);
238 FT_SIPE_DEBUG_INFO("read <%d> bytes [%02x:%c]", bytes_read
, *data
, *data
);
242 gssize
sipe_backend_ft_write(struct sipe_file_transfer
*ft
,
247 FT_SIPE_DEBUG_INFO("writing <%d> bytes", size
);
248 bytes_written
= Netlib_Send(ft
->backend_private
->fd
, data
, size
, MSG_NODUMP
);
249 if (bytes_written
== SOCKET_ERROR
) {
250 int err
= WSAGetLastError();
251 if (err
== WSAEWOULDBLOCK
) {
254 FT_SIPE_DEBUG_INFO("Error writing <%u>", err
);
258 FT_SIPE_DEBUG_INFO("wrote <%d> bytes", bytes_written
);
259 return bytes_written
;
263 cancel_local(struct sipe_backend_file_transfer
*xfer
)
265 struct sipe_file_transfer
*ft
= xfer
->ft
;
267 FT_SIPE_DEBUG_INFO_NOFORMAT("");
269 xfer
->status
= SIPE_MIRANDA_XFER_STATUS_CANCEL_LOCAL
;
270 xfer
->end_time
= time(NULL
);
272 msg
= g_strdup_printf("File transfer cancelled");
273 sipe_miranda_AddEvent(ft
->backend_private
->pr
, ft
->backend_private
->hContact
, SIPE_EVENTTYPE_ERROR_NOTIFY
, time(NULL
), DBEF_UTF
, strlen(msg
), (PBYTE
)msg
);
276 free_xfer_struct(xfer
);
278 if (xfer
->watcher
!= 0) {
279 sipe_miranda_input_remove(xfer
->watcher
);
284 Netlib_CloseHandle(xfer
->fd
);
286 if (xfer
->dest_fp
!= NULL
) {
287 fclose(xfer
->dest_fp
);
288 xfer
->dest_fp
= NULL
;
291 xfer
->bytes_remaining
= 0;
293 g_free(xfer
->filename
);
297 void sipe_backend_ft_set_completed(struct sipe_file_transfer
*ft
)
302 void sipe_backend_ft_cancel_local(struct sipe_file_transfer
*ft
)
304 cancel_local(ft
->backend_private
);
307 void sipe_backend_ft_cancel_remote(struct sipe_file_transfer
*ft
)
309 cancel_remote(ft
->backend_private
);
312 static struct sipe_backend_file_transfer
*
313 new_xfer(SIPPROTO
*pr
,
314 struct sipe_file_transfer
*ft
,
317 struct sipe_backend_file_transfer
*xfer
= g_new0(struct sipe_backend_file_transfer
, 1);
319 xfer
->current_buffer_size
= FT_INITIAL_BUFFER_SIZE
;
320 xfer
->buffer
= g_byte_array_sized_new(FT_INITIAL_BUFFER_SIZE
);
322 xfer
->hContact
= hContact
;
325 xfer
->st
.cbSize
= sizeof(PROTOFILETRANSFERSTATUS
);
326 xfer
->st
.hContact
= hContact
;
331 void sipe_backend_ft_incoming(struct sipe_core_public
*sipe_public
,
332 struct sipe_file_transfer
*ft
,
334 const gchar
*file_name
,
337 SIPPROTO
*pr
= sipe_public
->backend_private
;
338 PROTORECVFILET pre
= {0};
342 FT_SIPE_DEBUG_INFO("Incoming ft <%08x> from <%s> file <%s> size <%d>", ft
, who
, file_name
, file_size
);
343 hContact
= sipe_backend_buddy_find( sipe_public
, who
, NULL
);
346 FT_SIPE_DEBUG_INFO("Adding miranda contact for incoming transfer from <%s>", who
);
347 hContact
= ( HANDLE
)CallService( MS_DB_CONTACT_ADD
, 0, 0 );
348 CallService( MS_PROTO_ADDTOCONTACT
, ( WPARAM
)hContact
,( LPARAM
)pr
->proto
.m_szModuleName
);
349 DBWriteContactSettingByte( hContact
, "CList", "NotOnList", 1 );
350 sipe_miranda_setContactString( pr
, hContact
, SIP_UNIQUEID
, who
); // name
353 ft
->backend_private
= new_xfer(pr
, ft
, hContact
);
354 ft
->backend_private
->incoming
= TRUE
;
355 ft
->backend_private
->file_size
= file_size
;
356 ft
->backend_private
->bytes_remaining
= file_size
;
357 ft
->backend_private
->bytes_sent
= 0;
358 ft
->backend_private
->filename
= g_strdup(file_name
);
360 pre
.flags
= PREF_TCHAR
;
361 pre
.timestamp
= time(NULL
);
362 pre
.tszDescription
= mir_a2t(file_name
);
364 pre
.ptszFiles
= &pre
.tszDescription
;
365 pre
.lParam
= (LPARAM
)ft
;
367 ccs
.szProtoService
= PSR_FILE
;
368 ccs
.hContact
= hContact
;
370 ccs
.lParam
= (LPARAM
)&pre
;
371 CallService(MS_PROTO_CHAINRECV
, 0, (LPARAM
)&ccs
);
376 sipe_backend_ft_outgoing(struct sipe_core_public
*sipe_public
,
377 struct sipe_file_transfer
*ft
,
379 const gchar
*file_name
)
381 SIPPROTO
*pr
= sipe_public
->backend_private
;
387 hContact
= sipe_backend_buddy_find( sipe_public
, who
, NULL
);
388 ft
->backend_private
= new_xfer(pr
, ft
, hContact
);
389 ft
->backend_private
->incoming
= FALSE
;
390 result
= _tstat64( file_name
, &buf
);
393 FT_SIPE_DEBUG_INFO("Could not stat file, error<%d>", result
);
394 ft
->backend_private
->file_size
= 0;
398 ft
->backend_private
->file_size
= buf
.st_size
;
399 ft
->backend_private
->bytes_remaining
= ft
->backend_private
->file_size
;
400 ft
->backend_private
->bytes_sent
= 0;
402 ft
->backend_private
->local_filename
= g_strdup(file_name
);
403 ft
->backend_private
->filename
= g_path_get_basename(ft
->backend_private
->local_filename
);
404 FT_SIPE_DEBUG_INFO("set filename to <%s>", ft
->backend_private
->filename
);
405 ft
->init(ft
, ft
->backend_private
->filename
, ft
->backend_private
->file_size
, who
);
406 sipe_miranda_SendBroadcast(pr
, hContact
, ACKTYPE_FILE
, ACKRESULT_CONNECTING
, (HANDLE
)ft
->backend_private
, 0);
411 sipe_backend_ft_incoming_accept(struct sipe_file_transfer
*ft
,
413 unsigned short port_min
,
414 unsigned short port_max
)
421 set_completed(struct sipe_backend_file_transfer
*xfer
, gboolean completed
)
423 if (completed
== TRUE
) {
426 xfer
->status
= SIPE_MIRANDA_XFER_STATUS_DONE
;
428 if (xfer
->filename
!= NULL
)
430 char *filename
= g_markup_escape_text(xfer
->filename
, -1);
431 if (xfer
->local_filename
&& xfer
->incoming
)
433 char *local
= g_markup_escape_text(xfer
->local_filename
, -1);
434 msg
= g_strdup_printf("Transfer of file <A HREF=\"file://%s\">%s</A> complete",
439 msg
= g_strdup_printf("Transfer of file %s complete",
444 msg
= g_strdup("File transfer complete");
446 sipe_miranda_AddEvent(xfer
->pr
, xfer
->hContact
, SIPE_EVENTTYPE_ERROR_NOTIFY
, time(NULL
), DBEF_UTF
, strlen(msg
), (PBYTE
)msg
);
447 sipe_miranda_SendBroadcast(xfer
->pr
, xfer
->hContact
, ACKTYPE_FILE
, ACKRESULT_SUCCESS
, (HANDLE
)xfer
, 0);
452 update_progress(xfer
);
456 do_transfer(struct sipe_backend_file_transfer
*xfer
)
459 guchar
*buffer
= NULL
;
461 struct sipe_file_transfer
*ft
= xfer
->ft
;
463 FT_SIPE_DEBUG_INFO("incoming <%d>", xfer
->incoming
);
464 if (xfer
->incoming
) {
465 FT_SIPE_DEBUG_INFO_NOFORMAT("incoming branch");
466 r
= ft
->read(xfer
->ft
, &buffer
, xfer
->bytes_remaining
,
467 xfer
->current_buffer_size
);
470 wc
= fwrite(buffer
, 1, r
, xfer
->dest_fp
);
473 SIPE_DEBUG_ERROR("Unable to write whole buffer.");
479 if ((xfer
->file_size
> 0) && ((xfer
->bytes_sent
+r
) >= xfer
->file_size
))
480 set_completed(xfer
, TRUE
);
489 size_t s
= MIN(xfer
->bytes_remaining
, xfer
->current_buffer_size
);
490 gboolean read
= TRUE
;
491 FT_SIPE_DEBUG_INFO("outgoing branch, size <%u>", s
);
493 /* this is so the prpl can keep the connection open
494 if it needs to for some odd reason. */
497 sipe_miranda_input_remove(xfer
->watcher
);
504 if (xfer
->buffer
->len
< s
) {
505 s
-= xfer
->buffer
->len
;
513 buffer
= g_malloc(s
);
514 result
= fread(buffer
, 1, s
, xfer
->dest_fp
);
516 FT_SIPE_DEBUG_INFO_NOFORMAT("Unable to read whole buffer.");
524 g_byte_array_append(xfer
->buffer
, buffer
, result
);
526 buffer
= xfer
->buffer
->data
;
527 result
= xfer
->buffer
->len
;
530 s
= MIN(xfer
->bytes_remaining
, result
);
531 r
= ft
->write(ft
, buffer
, s
);
533 if ((xfer
->bytes_remaining
- r
) == 0)
534 set_completed(xfer
, TRUE
);
536 if (r
>= 0 && (xfer
->bytes_sent
+r
) >= xfer
->file_size
&& xfer
->status
!= SIPE_MIRANDA_XFER_STATUS_DONE
)
537 set_completed(xfer
, TRUE
);
543 /* We don't free buffer if priv->buffer is set, because in
544 that case buffer doesn't belong to us. */
547 } else if (r
== result
) {
549 * We managed to write the entire buffer. This means our
550 * network is fast and our buffer is too small, so make it
553 increase_buffer_size(xfer
);
558 * Remove what we wrote
559 * If we wrote the whole buffer the byte array will be empty
560 * Otherwise we'll keep what wasn't sent for next time.
563 g_byte_array_remove_range(xfer
->buffer
, 0, r
);
567 FT_SIPE_DEBUG_INFO_NOFORMAT("back to common code");
569 if (xfer
->file_size
> 0)
570 xfer
->bytes_remaining
-= r
;
572 xfer
->bytes_sent
+= r
;
575 update_progress(xfer
);
578 if (xfer
->status
== SIPE_MIRANDA_XFER_STATUS_DONE
)
580 xfer
->end_time
= time(NULL
);
581 if (xfer
->ft
->end
&& xfer
->ft
->end(xfer
->ft
)) {
582 /* We're done with this transfer */
583 free_xfer_struct(xfer
);
584 } else if (xfer
->incoming
) {
585 _unlink(xfer
->local_filename
);
588 if (xfer
->watcher
!= 0) {
589 sipe_miranda_input_remove(xfer
->watcher
);
594 Netlib_CloseHandle(xfer
->fd
);
596 if (xfer
->dest_fp
!= NULL
) {
597 fclose(xfer
->dest_fp
);
598 xfer
->dest_fp
= NULL
;
601 g_free(xfer
->filename
);
607 transfer_cb(gpointer data
, gint source
, sipe_miranda_input_condition condition
)
609 struct sipe_backend_file_transfer
*xfer
= data
;
610 SIPE_DEBUG_INFO_NOFORMAT("");
615 begin_transfer(struct sipe_file_transfer
*ft
)
617 struct sipe_backend_file_transfer
*xfer
= ft
->backend_private
;
618 SIPPROTO
*pr
= xfer
->pr
;
620 xfer
->dest_fp
= fopen(xfer
->local_filename
, xfer
->incoming
? "wb" : "rb");
621 if (xfer
->dest_fp
== NULL
) {
626 msg
= g_strdup_printf("Error reading %s: \n%s.\n", xfer
->local_filename
, g_strerror(err
));
628 msg
= g_strdup_printf("Error writing %s: \n%s.\n", xfer
->local_filename
, g_strerror(err
));
630 sipe_miranda_AddEvent(ft
->backend_private
->pr
, ft
->backend_private
->hContact
, SIPE_EVENTTYPE_ERROR_NOTIFY
, time(NULL
), DBEF_UTF
, strlen(msg
), (PBYTE
)msg
);
632 FT_SIPE_DEBUG_INFO("error opening local file: %s", g_strerror(errno
));
637 fseek(xfer
->dest_fp
, xfer
->bytes_sent
, SEEK_SET
);
639 xfer
->start_time
= time(NULL
);
642 FT_SIPE_DEBUG_INFO("incoming <%d> size <%d>", ft
->backend_private
->incoming
, ft
->backend_private
->file_size
);
643 if (!ft
->backend_private
->incoming
) {
644 /* Set socket to nonblocking */
645 SOCKET sock
= CallService(MS_NETLIB_GETSOCKET
, (WPARAM
)xfer
->fd
, (LPARAM
)0);
646 unsigned long parm
= 1;
648 if (ioctlsocket(sock
, FIONBIO
, &parm
) == SOCKET_ERROR
)
650 FT_SIPE_DEBUG_INFO("Error ioctlsocket <%d>", WSAGetLastError());
653 FT_SIPE_DEBUG_INFO("outgoing ft <%08x> size <%d>", ft
, ft
->backend_private
->file_size
);
656 ft
->start(ft
, ft
->backend_private
->file_size
);
661 xfer
->watcher
= sipe_miranda_input_add(xfer
->fd
, xfer
->incoming
?SIPE_MIRANDA_INPUT_READ
:SIPE_MIRANDA_INPUT_WRITE
, transfer_cb
, xfer
);
663 FT_SIPE_DEBUG_INFO("watcher [%08x]", xfer
->watcher
);
667 ft_connected_callback(HANDLE fd
, void* data
, const gchar
*reason
)
669 struct sipe_file_transfer
*ft
= (struct sipe_file_transfer
*)data
;
670 struct sipe_backend_file_transfer
*xfer
= ft
->backend_private
;
671 SIPPROTO
*pr
= ft
->backend_private
->pr
;
677 ft
->backend_private
->fd
= fd
;
684 sipe_backend_ft_start(struct sipe_file_transfer
*ft
, struct sipe_backend_fd
*fd
,
685 const char* ip
, unsigned port
)
687 ft
->backend_private
->status
= SIPE_MIRANDA_XFER_STATUS_STARTED
;
691 FT_SIPE_DEBUG_INFO("Should connect to <%s:%d>", ip
, port
);
692 sipe_miranda_connect(ft
->backend_private
->pr
, ip
, port
, FALSE
, 5, ft_connected_callback
, ft
);
696 FT_SIPE_DEBUG_INFO("Should use incoming fd <%08x>", fd
);
697 ft
->backend_private
->fd
= fd
;
702 sipe_backend_ft_is_incoming(struct sipe_file_transfer
*ft
)
704 FT_SIPE_DEBUG_INFO("ft <%08x> incoming <%d>", ft
, ft
->backend_private
->incoming
);
705 return ft
->backend_private
->incoming
;
709 sipe_miranda_SendFile( SIPPROTO
*pr
, HANDLE hContact
, const PROTOCHAR
* szDescription
, PROTOCHAR
** ppszFiles
)
713 if ( !DBGetContactSettingString( hContact
, pr
->proto
.m_szModuleName
, SIP_UNIQUEID
, &dbv
)) {
714 struct sipe_file_transfer
*ft
;
716 ft
= sipe_core_ft_create_outgoing(pr
->sip
, dbv
.pszVal
, TCHAR2CHAR(ppszFiles
[0]));
718 FT_SIPE_DEBUG_INFO("SendFile: desc <%ls> name <%s> size <%d> to <%s>", szDescription
, TCHAR2CHAR(ppszFiles
[0]), ft
->backend_private
->file_size
, dbv
.pszVal
);
720 DBFreeVariant( &dbv
);
722 return ft
->backend_private
;
729 sipe_miranda_RecvFile( SIPPROTO
*pr
, HANDLE hContact
, PROTOFILEEVENT
* evt
)
731 CCSDATA ccs
= { hContact
, PSR_FILE
, 0, (LPARAM
)evt
};
732 return CallService(MS_PROTO_RECVFILET
, 0, (LPARAM
)&ccs
);
736 sipe_miranda_FileAllow( SIPPROTO
*pr
, HANDLE hContact
, HANDLE hTransfer
, const PROTOCHAR
* szPath
)
738 struct sipe_file_transfer
*ft
= (struct sipe_file_transfer
*)hTransfer
;
739 FT_SIPE_DEBUG_INFO("Incoming ft <%08x> allowed", ft
);
740 ft
->backend_private
->local_filename
= g_strdup_printf("%s%s", TCHAR2CHAR(szPath
), ft
->backend_private
->filename
);
741 sipe_miranda_SendBroadcast(pr
, hContact
, ACKTYPE_FILE
, ACKRESULT_CONNECTING
, (HANDLE
)ft
->backend_private
, 0);
742 ft
->init(ft
, ft
->backend_private
->filename
, ft
->backend_private
->file_size
, NULL
);
743 return ft
->backend_private
;
747 sipe_miranda_FileDeny( SIPPROTO
*pr
, HANDLE hContact
, HANDLE hTransfer
, const PROTOCHAR
* szReason
)
749 struct sipe_file_transfer
*ft
= (struct sipe_file_transfer
*)hTransfer
;
750 FT_SIPE_DEBUG_INFO("FileDeny: reason <%s>", szReason
);
751 if (ft
->backend_private
->incoming
&& ft
->request_denied
)
752 ft
->request_denied(ft
);
753 free_xfer_struct(ft
->backend_private
);