6 * Copyright (C) 2010-2015 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_cancel_local(struct sipe_file_transfer
*ft
)
299 cancel_local(ft
->backend_private
);
302 void sipe_backend_ft_cancel_remote(struct sipe_file_transfer
*ft
)
304 cancel_remote(ft
->backend_private
);
307 static struct sipe_backend_file_transfer
*
308 new_xfer(SIPPROTO
*pr
,
309 struct sipe_file_transfer
*ft
,
312 struct sipe_backend_file_transfer
*xfer
= g_new0(struct sipe_backend_file_transfer
, 1);
314 xfer
->current_buffer_size
= FT_INITIAL_BUFFER_SIZE
;
315 xfer
->buffer
= g_byte_array_sized_new(FT_INITIAL_BUFFER_SIZE
);
317 xfer
->hContact
= hContact
;
320 xfer
->st
.cbSize
= sizeof(PROTOFILETRANSFERSTATUS
);
321 xfer
->st
.hContact
= hContact
;
326 void sipe_backend_ft_incoming(struct sipe_core_public
*sipe_public
,
327 struct sipe_file_transfer
*ft
,
329 const gchar
*file_name
,
332 SIPPROTO
*pr
= sipe_public
->backend_private
;
333 PROTORECVFILET pre
= {0};
337 FT_SIPE_DEBUG_INFO("Incoming ft <%08x> from <%s> file <%s> size <%d>", ft
, who
, file_name
, file_size
);
338 hContact
= sipe_backend_buddy_find( sipe_public
, who
, NULL
);
341 FT_SIPE_DEBUG_INFO("Adding miranda contact for incoming transfer from <%s>", who
);
342 hContact
= ( HANDLE
)CallService( MS_DB_CONTACT_ADD
, 0, 0 );
343 CallService( MS_PROTO_ADDTOCONTACT
, ( WPARAM
)hContact
,( LPARAM
)pr
->proto
.m_szModuleName
);
344 DBWriteContactSettingByte( hContact
, "CList", "NotOnList", 1 );
345 sipe_miranda_setContactString( pr
, hContact
, SIP_UNIQUEID
, who
); // name
348 ft
->backend_private
= new_xfer(pr
, ft
, hContact
);
349 ft
->backend_private
->incoming
= TRUE
;
350 ft
->backend_private
->file_size
= file_size
;
351 ft
->backend_private
->bytes_remaining
= file_size
;
352 ft
->backend_private
->bytes_sent
= 0;
353 ft
->backend_private
->filename
= g_strdup(file_name
);
355 pre
.flags
= PREF_TCHAR
;
356 pre
.timestamp
= time(NULL
);
357 pre
.tszDescription
= mir_a2t(file_name
);
359 pre
.ptszFiles
= &pre
.tszDescription
;
360 pre
.lParam
= (LPARAM
)ft
;
362 ccs
.szProtoService
= PSR_FILE
;
363 ccs
.hContact
= hContact
;
365 ccs
.lParam
= (LPARAM
)&pre
;
366 CallService(MS_PROTO_CHAINRECV
, 0, (LPARAM
)&ccs
);
371 sipe_backend_ft_incoming_accept(struct sipe_file_transfer
*ft
,
373 unsigned short port_min
,
374 unsigned short port_max
)
381 set_completed(struct sipe_backend_file_transfer
*xfer
, gboolean completed
)
383 if (completed
== TRUE
) {
386 xfer
->status
= SIPE_MIRANDA_XFER_STATUS_DONE
;
388 if (xfer
->filename
!= NULL
)
390 char *filename
= g_markup_escape_text(xfer
->filename
, -1);
391 if (xfer
->local_filename
&& xfer
->incoming
)
393 char *local
= g_markup_escape_text(xfer
->local_filename
, -1);
394 msg
= g_strdup_printf("Transfer of file <A HREF=\"file://%s\">%s</A> complete",
399 msg
= g_strdup_printf("Transfer of file %s complete",
404 msg
= g_strdup("File transfer complete");
406 sipe_miranda_AddEvent(xfer
->pr
, xfer
->hContact
, SIPE_EVENTTYPE_ERROR_NOTIFY
, time(NULL
), DBEF_UTF
, strlen(msg
), (PBYTE
)msg
);
407 sipe_miranda_SendBroadcast(xfer
->pr
, xfer
->hContact
, ACKTYPE_FILE
, ACKRESULT_SUCCESS
, (HANDLE
)xfer
, 0);
412 update_progress(xfer
);
416 do_transfer(struct sipe_backend_file_transfer
*xfer
)
419 guchar
*buffer
= NULL
;
421 struct sipe_file_transfer
*ft
= xfer
->ft
;
423 FT_SIPE_DEBUG_INFO("incoming <%d>", xfer
->incoming
);
424 if (xfer
->incoming
) {
425 FT_SIPE_DEBUG_INFO_NOFORMAT("incoming branch");
426 r
= ft
->read(xfer
->ft
, &buffer
, xfer
->bytes_remaining
,
427 xfer
->current_buffer_size
);
430 wc
= fwrite(buffer
, 1, r
, xfer
->dest_fp
);
433 SIPE_DEBUG_ERROR("Unable to write whole buffer.");
439 if ((xfer
->file_size
> 0) && ((xfer
->bytes_sent
+r
) >= xfer
->file_size
))
440 set_completed(xfer
, TRUE
);
449 size_t s
= MIN(xfer
->bytes_remaining
, xfer
->current_buffer_size
);
450 gboolean read
= TRUE
;
451 FT_SIPE_DEBUG_INFO("outgoing branch, size <%u>", s
);
453 /* this is so the prpl can keep the connection open
454 if it needs to for some odd reason. */
457 sipe_miranda_input_remove(xfer
->watcher
);
464 if (xfer
->buffer
->len
< s
) {
465 s
-= xfer
->buffer
->len
;
473 buffer
= g_malloc(s
);
474 result
= fread(buffer
, 1, s
, xfer
->dest_fp
);
476 FT_SIPE_DEBUG_INFO_NOFORMAT("Unable to read whole buffer.");
484 g_byte_array_append(xfer
->buffer
, buffer
, result
);
486 buffer
= xfer
->buffer
->data
;
487 result
= xfer
->buffer
->len
;
490 s
= MIN(xfer
->bytes_remaining
, result
);
491 r
= ft
->write(ft
, buffer
, s
);
493 if ((xfer
->bytes_remaining
- r
) == 0)
494 set_completed(xfer
, TRUE
);
496 if (r
>= 0 && (xfer
->bytes_sent
+r
) >= xfer
->file_size
&& xfer
->status
!= SIPE_MIRANDA_XFER_STATUS_DONE
)
497 set_completed(xfer
, TRUE
);
503 /* We don't free buffer if priv->buffer is set, because in
504 that case buffer doesn't belong to us. */
507 } else if (r
== result
) {
509 * We managed to write the entire buffer. This means our
510 * network is fast and our buffer is too small, so make it
513 increase_buffer_size(xfer
);
518 * Remove what we wrote
519 * If we wrote the whole buffer the byte array will be empty
520 * Otherwise we'll keep what wasn't sent for next time.
523 g_byte_array_remove_range(xfer
->buffer
, 0, r
);
527 FT_SIPE_DEBUG_INFO_NOFORMAT("back to common code");
529 if (xfer
->file_size
> 0)
530 xfer
->bytes_remaining
-= r
;
532 xfer
->bytes_sent
+= r
;
535 update_progress(xfer
);
538 if (xfer
->status
== SIPE_MIRANDA_XFER_STATUS_DONE
)
540 xfer
->end_time
= time(NULL
);
541 if (xfer
->ft
->end
&& xfer
->ft
->end(xfer
->ft
)) {
542 /* We're done with this transfer */
543 free_xfer_struct(xfer
);
544 } else if (xfer
->incoming
) {
545 _unlink(xfer
->local_filename
);
548 if (xfer
->watcher
!= 0) {
549 sipe_miranda_input_remove(xfer
->watcher
);
554 Netlib_CloseHandle(xfer
->fd
);
556 if (xfer
->dest_fp
!= NULL
) {
557 fclose(xfer
->dest_fp
);
558 xfer
->dest_fp
= NULL
;
561 g_free(xfer
->filename
);
567 transfer_cb(gpointer data
, gint source
, sipe_miranda_input_condition condition
)
569 struct sipe_backend_file_transfer
*xfer
= data
;
570 SIPE_DEBUG_INFO_NOFORMAT("");
575 begin_transfer(struct sipe_file_transfer
*ft
)
577 struct sipe_backend_file_transfer
*xfer
= ft
->backend_private
;
578 SIPPROTO
*pr
= xfer
->pr
;
580 xfer
->dest_fp
= fopen(xfer
->local_filename
, xfer
->incoming
? "wb" : "rb");
581 if (xfer
->dest_fp
== NULL
) {
586 msg
= g_strdup_printf("Error reading %s: \n%s.\n", xfer
->local_filename
, g_strerror(err
));
588 msg
= g_strdup_printf("Error writing %s: \n%s.\n", xfer
->local_filename
, g_strerror(err
));
590 sipe_miranda_AddEvent(ft
->backend_private
->pr
, ft
->backend_private
->hContact
, SIPE_EVENTTYPE_ERROR_NOTIFY
, time(NULL
), DBEF_UTF
, strlen(msg
), (PBYTE
)msg
);
592 FT_SIPE_DEBUG_INFO("error opening local file: %s", g_strerror(errno
));
597 fseek(xfer
->dest_fp
, xfer
->bytes_sent
, SEEK_SET
);
599 xfer
->start_time
= time(NULL
);
602 FT_SIPE_DEBUG_INFO("incoming <%d> size <%d>", ft
->backend_private
->incoming
, ft
->backend_private
->file_size
);
603 if (!ft
->backend_private
->incoming
) {
604 /* Set socket to nonblocking */
605 SOCKET sock
= CallService(MS_NETLIB_GETSOCKET
, (WPARAM
)xfer
->fd
, (LPARAM
)0);
606 unsigned long parm
= 1;
608 if (ioctlsocket(sock
, FIONBIO
, &parm
) == SOCKET_ERROR
)
610 FT_SIPE_DEBUG_INFO("Error ioctlsocket <%d>", WSAGetLastError());
613 FT_SIPE_DEBUG_INFO("outgoing ft <%08x> size <%d>", ft
, ft
->backend_private
->file_size
);
616 ft
->start(ft
, ft
->backend_private
->file_size
);
621 xfer
->watcher
= sipe_miranda_input_add(xfer
->fd
, xfer
->incoming
?SIPE_MIRANDA_INPUT_READ
:SIPE_MIRANDA_INPUT_WRITE
, transfer_cb
, xfer
);
623 FT_SIPE_DEBUG_INFO("watcher [%08x]", xfer
->watcher
);
627 ft_connected_callback(HANDLE fd
, void* data
, const gchar
*reason
)
629 struct sipe_file_transfer
*ft
= (struct sipe_file_transfer
*)data
;
630 struct sipe_backend_file_transfer
*xfer
= ft
->backend_private
;
631 SIPPROTO
*pr
= ft
->backend_private
->pr
;
637 ft
->backend_private
->fd
= fd
;
644 sipe_backend_ft_start(struct sipe_file_transfer
*ft
, struct sipe_backend_fd
*fd
,
645 const char* ip
, unsigned port
)
647 ft
->backend_private
->status
= SIPE_MIRANDA_XFER_STATUS_STARTED
;
651 FT_SIPE_DEBUG_INFO("Should connect to <%s:%d>", ip
, port
);
652 sipe_miranda_connect(ft
->backend_private
->pr
, ip
, port
, FALSE
, 5, ft_connected_callback
, ft
);
656 FT_SIPE_DEBUG_INFO("Should use incoming fd <%08x>", fd
);
657 ft
->backend_private
->fd
= fd
;
662 sipe_backend_ft_is_incoming(struct sipe_file_transfer
*ft
)
664 FT_SIPE_DEBUG_INFO("ft <%08x> incoming <%d>", ft
, ft
->backend_private
->incoming
);
665 return ft
->backend_private
->incoming
;
669 sipe_miranda_SendFile( SIPPROTO
*pr
, HANDLE hContact
, const PROTOCHAR
* szDescription
, PROTOCHAR
** ppszFiles
)
671 struct sipe_file_transfer
*ft
= sipe_core_ft_allocate(pr
->sip
);
674 if ( !DBGetContactSettingString( hContact
, pr
->proto
.m_szModuleName
, SIP_UNIQUEID
, &dbv
)) {
679 ft
->backend_private
= new_xfer(pr
, ft
, hContact
);
680 ft
->backend_private
->incoming
= FALSE
;
681 result
= _tstat64( ppszFiles
[0], &buf
);
684 FT_SIPE_DEBUG_INFO("Could not stat file, error<%d>", result
);
685 ft
->backend_private
->file_size
= 0;
689 ft
->backend_private
->file_size
= buf
.st_size
;
690 ft
->backend_private
->bytes_remaining
= ft
->backend_private
->file_size
;
691 ft
->backend_private
->bytes_sent
= 0;
693 FT_SIPE_DEBUG_INFO("SendFile: desc <%ls> name <%s> size <%d> to <%s>", szDescription
, TCHAR2CHAR(ppszFiles
[0]), ft
->backend_private
->file_size
, dbv
.pszVal
);
694 ft
->backend_private
->local_filename
= g_strdup(TCHAR2CHAR(ppszFiles
[0]));
695 ft
->backend_private
->filename
= g_path_get_basename(ft
->backend_private
->local_filename
);
696 FT_SIPE_DEBUG_INFO("set filename to <%s>", ft
->backend_private
->filename
);
697 ft
->init(ft
, ft
->backend_private
->filename
, ft
->backend_private
->file_size
, dbv
.pszVal
);
698 sipe_miranda_SendBroadcast(pr
, hContact
, ACKTYPE_FILE
, ACKRESULT_CONNECTING
, (HANDLE
)ft
->backend_private
, 0);
701 DBFreeVariant( &dbv
);
704 return ft
->backend_private
;
708 sipe_miranda_RecvFile( SIPPROTO
*pr
, HANDLE hContact
, PROTOFILEEVENT
* evt
)
710 CCSDATA ccs
= { hContact
, PSR_FILE
, 0, (LPARAM
)evt
};
711 return CallService(MS_PROTO_RECVFILET
, 0, (LPARAM
)&ccs
);
715 sipe_miranda_FileAllow( SIPPROTO
*pr
, HANDLE hContact
, HANDLE hTransfer
, const PROTOCHAR
* szPath
)
717 struct sipe_file_transfer
*ft
= (struct sipe_file_transfer
*)hTransfer
;
718 FT_SIPE_DEBUG_INFO("Incoming ft <%08x> allowed", ft
);
719 ft
->backend_private
->local_filename
= g_strdup_printf("%s%s", TCHAR2CHAR(szPath
), ft
->backend_private
->filename
);
720 sipe_miranda_SendBroadcast(pr
, hContact
, ACKTYPE_FILE
, ACKRESULT_CONNECTING
, (HANDLE
)ft
->backend_private
, 0);
721 ft
->init(ft
, ft
->backend_private
->filename
, ft
->backend_private
->file_size
, NULL
);
722 return ft
->backend_private
;
726 sipe_miranda_FileDeny( SIPPROTO
*pr
, HANDLE hContact
, HANDLE hTransfer
, const PROTOCHAR
* szReason
)
728 struct sipe_file_transfer
*ft
= (struct sipe_file_transfer
*)hTransfer
;
729 FT_SIPE_DEBUG_INFO("FileDeny: reason <%s>", szReason
);
730 if (ft
->backend_private
->incoming
&& ft
->request_denied
)
731 ft
->request_denied(ft
);
732 free_xfer_struct(ft
->backend_private
);