cloudstack/thirdparty/vnc/viewer/AxVncViewer/FileTransfer.cpp

4071 lines
116 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2002 Ultr@VNC Team Members. All Rights Reserved.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
// If the source code for the program is not available from the place from
// which you received this file, check
// http://ultravnc.sourceforge.net/
//
////////////////////////////////////////////////////////////////////////////
// FileTransfer.cpp: implementation of the FileTransfer class.
// sf@2002 - sf@2003 - sf@2004 - FileTransfer
// This class handles all the FileTransfer messages, events and procs, as well as the
// DialogBox which allows the user to browse Client ans Server disks-directories,
// and select some files to transfer between Client and Server.
//
// The GUI is very basic because I don't want to include MFC Classes in VNC...
// I use only Windows SDK.
//
//
// The GUI is now quite bearable, but following modifs could be done one day or another
// - Add more columns to FileLists (File type, Attributes...)
// - Add the possibility to sort files by colomns (File Size Order, File Ext order...)
// - Total progress should be based on total files' size instead of total number of files
// - Make the History persistent (file) so it's not lost each time the FileTransfer Win is closed
// - Clean-up the code (duplicated parts, arrays and strings dimensions checks...)
// - Display the total files size in the currently displayed directory
// - Remember the current directories - Partially done: the FT window can be minimized...
#include "stdhdrs.h"
#include "vncviewer.h"
#include "FileTransfer.h"
#include "Exception.h"
#include "commctrl.h"
#include "shlobj.h"
#include "zlib/zlib.h"
// These strings contain all the translated FT messages
extern char sz_H1[64];
extern char sz_H2[64];
extern char sz_H3[128];
extern char sz_H4[64];
extern char sz_H5[64];
extern char sz_H6[64];
extern char sz_H7[64];
extern char sz_H8[64];
extern char sz_H9[64];
extern char sz_H10[64];
extern char sz_H11[64];
extern char sz_H12[64];
extern char sz_H13[64];
extern char sz_H14[64];
extern char sz_H15[64];
extern char sz_H16[64];
extern char sz_H17[64];
extern char sz_H18[64];
extern char sz_H19[64];
extern char sz_H20[64];
extern char sz_H21[64];
extern char sz_H22[64];
extern char sz_H23[64];
extern char sz_H24[64];
extern char sz_H25[64];
extern char sz_H26[64];
extern char sz_H27[64];
extern char sz_H28[64];
extern char sz_H29[64];
extern char sz_H30[64];
extern char sz_H31[64];
extern char sz_H32[64];
extern char sz_H33[64];
extern char sz_H34[64];
extern char sz_H35[64];
extern char sz_H36[64];
extern char sz_H37[64];
extern char sz_H38[128];
extern char sz_H39[64];
extern char sz_H40[64];
extern char sz_H41[64];
extern char sz_H42[64];
extern char sz_H43[128];
extern char sz_H44[64];
extern char sz_H45[64];
extern char sz_H46[128];
extern char sz_H47[64];
extern char sz_H48[64];
extern char sz_H49[64];
extern char sz_H50[64];
extern char sz_H51[64];
extern char sz_H52[64];
extern char sz_H53[64];
extern char sz_H54[64];
extern char sz_H55[64];
extern char sz_H56[64];
extern char sz_H57[64];
// Folder Transfer messages
extern char sz_H58[64];
extern char sz_H59[64];
extern char sz_H60[64];
extern char sz_H61[64];
extern char sz_H62[128];
extern char sz_H63[64];
extern char sz_H64[64];
extern char sz_H65[64];
extern char sz_H66[64];
extern char sz_H67[64];
extern char sz_H68[128];
extern char sz_H69[64];
extern char sz_H70[64];
extern char sz_H71[64];
extern char sz_H72[128];
extern char sz_H73[64];
// File/dir Rename messages
extern char sz_M1[64];
extern char sz_M2[64];
extern char sz_M3[64];
extern char sz_M4[64];
extern char sz_M5[64];
extern char sz_M6[64];
extern char sz_M7[64];
extern char sz_M8[64];
typedef BOOL (WINAPI *PGETDISKFREESPACEEX)(LPCSTR,PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
//
//
//
FileTransfer::FileTransfer(VNCviewerApp *pApp, ClientConnection *pCC)
{
// vnclog.Print(0, _T("FileTransfer\n"));
m_pApp = pApp;
m_pCC = pCC;
m_fAbort = false;
m_fAborted = false;
m_FilesList.clear();
m_nFilesToTransfer = 0;
m_nFilesTransfered = 0;
m_fFileCommandPending = false;
m_fFileTransferRunning = false;
m_fFileDownloadRunning = false;
m_fDirectoryReceptionRunning = false;
m_fVisible = true;
m_fFTAllowed = false;
m_timer = 0;
m_pZipUnZip = new CZipUnZip32();
m_lpCSBuffer = NULL;
m_nCSOffset = 0;
m_nCSBufferSize = 0;
m_nDeleteCount = 0;
memset(m_szDeleteButtonLabel, 0, sizeof(m_szDeleteButtonLabel));
memset(m_szNewFolderButtonLabel, 0, sizeof(m_szNewFolderButtonLabel));
memset(m_szRenameButtonLabel, 0, sizeof(m_szRenameButtonLabel));
m_fOldFTProtocole = false;
m_nBlockSize = sz_rfbBlockSize;
m_dwCurrentValue = 0;
m_dwCurrentPercent = 0;
m_fSendFileChunk = false;
m_mmRes = -1;
}
//
//
//
FileTransfer::~FileTransfer()
{
// vnclog.Print(0, _T("nFileTransfer\n"));
m_fFileCommandPending = false;
m_fFileTransferRunning = false;
m_FilesList.clear();
if (m_pZipUnZip) delete m_pZipUnZip;
}
void FileTransfer::InitFTTimer()
{
if (m_mmRes != -1) return;
m_fSendFileChunk = false;
m_mmRes = timeSetEvent( 1, 0, fpTimer, (DWORD)this, TIME_PERIODIC );
}
void FileTransfer::KillFTTimer()
{
timeKillEvent(m_mmRes);
m_mmRes = -1;
}
void CALLBACK FileTransfer::fpTimer(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
FileTransfer* ft = (FileTransfer *) dwUser;
if (!ft->m_fFileUploadRunning) return;
if (!ft->m_fSendFileChunk)
{
ft->m_fSendFileChunk = true;
ft->m_dwLastChunkTime = timeGetTime();
SendMessage(ft->m_pCC->m_hwndMain, FileTransferSendPacketMessage, (WPARAM) 0, (LPARAM) 0);
// sf@2005 - FileTransfer Temporization
// - Prevents the windows message stack to be blocked too much when transfering over slow conenction
// - Gives more priority to screen updates during asynchronous filetransfer
long lDelta = timeGetTime() - ft->m_dwLastChunkTime;
if (lDelta > 200)
{
//if (lDelta < 3000)
// Sleep(lDelta);
//else
Sleep(150);
}
else if (!ft->m_fVisible && !ft->m_fOldFTProtocole && !ft->m_pCC->IsDormant())
Sleep(50);
ft->m_fSendFileChunk = false;
}
}
//
//
//
void FileTransfer::ShowFileTransferWindow(bool fVisible)
{
// vnclog.Print(0, _T("ShowFileTransferWindow\n"));
ShowWindow(hWnd, fVisible ? SW_RESTORE : SW_MINIMIZE);
SetForegroundWindow(hWnd);
// Put the FT Windows always on Top if fullscreen
if (fVisible && m_pCC->InFullScreenMode())
{
RECT Rect;
GetWindowRect(hWnd, &Rect);
SetWindowPos(hWnd,
HWND_TOPMOST,
Rect.left,
Rect.top,
Rect.right - Rect.left,
Rect.bottom - Rect.top,
SWP_SHOWWINDOW);
}
m_fVisible = fVisible; // This enables screen updates to be processed in ClientConnection
// Refresh screen view if FileTransfer window has been hidden
if (!fVisible)
m_pCC->SendAppropriateFramebufferUpdateRequest();
}
//
// Simply the classic Windows message processing
//
bool PseudoYield(HWND hWnd)
{
// vnclog.Print(0, _T("PseudoYield\n"));
MSG msg;
while (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_CLOSE) return FALSE;
}
return TRUE;
}
//
// ProcessFileTransferMsg
//
// Here we process all incoming FileTransferMsg stuff
// coming from the server.
// The server only sends FileTransfer data when requested
// by the client. Possible request are:
//
// - Send the list of your drives
// - Send the content of a directory
// - Send a file
// - Accept a file
// - ...
//
// We use the main ClientConnection thread and its
// rfb message reception loop.
// This function is called by the rfb message processing thread.
// Thus it's safe to call the ReadExact and ReadString
// functions in the functions that are called from here:
// PopulateRemoteListBox, ReceiveFile
//
void FileTransfer::ProcessFileTransferMsg(void)
{
// vnclog.Print(0, _T("ProcessFileTransferMsg\n"));
rfbFileTransferMsg ft;
m_pCC->ReadExact(((char *) &ft) + m_pCC->m_nTO, sz_rfbFileTransferMsg - m_pCC->m_nTO);
switch (ft.contentType)
{
// Response to a rfbDirContentRequest request:
// some directory data is received from the server
case rfbDirPacket:
switch (ft.contentParam)
{
// Response to a rfbRDrivesList request
case rfbADrivesList:
ListRemoteDrives(hWnd, Swap32IfLE(ft.length));
m_fFileCommandPending = false;
break;
// Response to a rfbRDirContent request
case rfbADirectory:
case rfbAFile:
if (!m_fDirectoryReceptionRunning)
PopulateRemoteListBox(hWnd, Swap32IfLE(ft.length));
else
ReceiveDirectoryItem(hWnd, Swap32IfLE(ft.length));
break;
default: // This is bad. Add rfbADirectoryEnd instead...
if (m_fDirectoryReceptionRunning)
{
FinishDirectoryReception();
m_fFileCommandPending = false;
}
break;
}
break;
// In response to a rfbFileTransferRequest request
// A file is received from the server.
case rfbFileHeader:
ReceiveFiles(Swap32IfLE(ft.size), Swap32IfLE(ft.length));
break;
// In response to a rfbFileTransferOffer request
// The server can send the checksums of the destination file before sending a ack through
// rfbFileAcceptHeader (only if the destination file already exists and is accessible)
case rfbFileChecksums:
ReceiveDestinationFileChecksums(Swap32IfLE(ft.size), Swap32IfLE(ft.length));
break;
// In response to a rfbFileTransferOffer request
// A ack or nack is received from the server.
case rfbFileAcceptHeader:
SendFiles(Swap32IfLE(ft.size), Swap32IfLE(ft.length));
break;
// Response to a command
case rfbCommandReturn:
switch (ft.contentParam)
{
case rfbADirCreate:
CreateRemoteDirectoryFeedback(Swap32IfLE(ft.size), Swap32IfLE(ft.length));
m_fFileCommandPending = false;
break;
case rfbAFileDelete:
DeleteRemoteFileFeedback(Swap32IfLE(ft.size), Swap32IfLE(ft.length));
m_fFileCommandPending = false;
break;
case rfbAFileRename:
RenameRemoteFileOrDirectoryFeedback(Swap32IfLE(ft.size), Swap32IfLE(ft.length));
m_fFileCommandPending = false;
break;
}
break;
// Should never be handled here but in the File Transfer Loop
case rfbFilePacket:
ReceiveFileChunk(Swap32IfLE(ft.length), Swap32IfLE(ft.size));
break;
// Should never be handled here but in the File Transfer Loop
case rfbEndOfFile:
FinishFileReception();
break;
// Abort current file transfer
// For versions <=RC18 we also use it to test if we're allowed to use FileTransfer on the server
case rfbAbortFileTransfer:
// AbortFileDownload();
if (m_fFileDownloadRunning)
{
m_fFileDownloadError = true;
FinishFileReception();
}
else
{
// We want the viewer to be backward compatible with UltraWinVNC running the old FT protocole
m_fOldFTProtocole = true; // Old permission method -> it's a <=RC18 server
m_nBlockSize = 4096; // Old packet size value...
ShowWindow(GetDlgItem(hWnd, IDC_RENAME_B), SW_HIDE);
TestPermission(Swap32IfLE(ft.size), 0);
}
break;
// New FT handshaking/permission method (from RC19)
case rfbFileTransferAccess:
TestPermission(Swap32IfLE(ft.size), ft.contentParam);
break;
default:
return;
break;
}
}
//
// request file transfer permission
//
void FileTransfer::RequestPermission()
{
// vnclog.Print(0, _T("RequestPermission\n"));
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
// Versions <= RC18 method
ft.contentType = rfbAbortFileTransfer;
// ft.contentParam = 0;
ft.contentParam = rfbFileTransferVersion; // Old viewer will send 0
// New method can't be used yet as we want backward compatibility (new viewer FT must
// work with old UltraWinVNC FT
// ft.contentType = rfbFileTransferAccess;
// ft.contentParam = rfbFileTransferVersion;
ft.length = 0;
ft.size = 0;
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
return;
}
//
// Test if we are allowed to access filetransfer
//
bool FileTransfer::TestPermission(long lSize, int nVersion)
{
// vnclog.Print(0, _T("TestPermission\n"));
if (lSize == -1)
{
m_fFTAllowed = false;
HWND hWndRemoteList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
SendDlgItemMessage(hWnd, IDC_REMOTE_DRIVECB, LB_RESETCONTENT, 0, 0L);
ListView_DeleteAllItems(hWndRemoteList);
SetDlgItemText(hWnd, IDC_CURR_REMOTE, sz_H1);
SetDlgItemText(hWnd, IDC_REMOTE_STATUS, sz_H2);
SetStatus(sz_H3);
DisableButtons(hWnd);
ShowWindow(GetDlgItem(hWnd, IDCANCEL), SW_SHOW);
}
else
{
m_fFTAllowed = true;
RequestRemoteDrives();
SetStatus(sz_H4);
}
return true;
}
//
// Receive all the files that are referenced in m_FilesList
//
bool FileTransfer::ReceiveFiles(unsigned long lSize, int nLen)
{
// vnclog.Print(0, _T("ReceiveFiles\n"));
// Receive the incoming file
m_nFilesTransfered++;
SetGlobalCount();
if (!ReceiveFile(lSize, nLen))
RequestNextFile();
return true;
}
//
// A file has just been received
// Request the following one if any
//
bool FileTransfer::RequestNextFile()
{
// vnclog.Print(0, _T("RequestNextFile\n"));
SetGlobalCount();
m_iFile++; // go to next file in the list of files to receive
HWND hWndLocalList = GetDlgItem(hWnd, IDC_LOCAL_FILELIST);
HWND hWndRemoteList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
// If one more file has to be received, ask for it !
if (m_iFile != m_FilesList.end() && !m_fAbort)
{
TCHAR szSelectedFile[128];
TCHAR szDstFile[MAX_PATH];
memset(szSelectedFile, 0, 128);
memset(szDstFile, 0, MAX_PATH);
LVITEM Item;
Item.mask = LVIF_TEXT;
Item.iSubItem = 0;
Item.pszText = szSelectedFile;
Item.cchTextMax = 128;
// Get the name file to receive in the remote list
Item.iItem = *m_iFile;
ListView_GetItem(hWndRemoteList, &Item);
GetDlgItemText(hWnd, IDC_CURR_REMOTE, szDstFile, sizeof(szDstFile));
if (!strlen(szDstFile)) return false; // no destination dir selected - msgbox ?
strcat(szDstFile, szSelectedFile);
RequestRemoteFile(szDstFile);
}
else // All the files have been processed and hopefully received
{
// Refresh the local list so new files are displayed and highlighted
ListView_DeleteAllItems(hWndLocalList);
PopulateLocalListBox(hWnd, "");
if (m_fAbort)
SetStatus(sz_H5);
else
SetStatus(sz_H6);
EnableButtons(hWnd);
ShowFileTransferWindow(true);
Sleep(1000);
//MessageBeep(-1);
// Unlock
m_fFileCommandPending = false;
}
return true;
}
//
// Send all the files that are referenced in m_FilesList
//
bool FileTransfer::SendFiles(long lSize, int nLen)
{
InitFTTimer(); // sf@2005
// vnclog.Print(0, _T("SendFiles\n"));
// Receive the incoming file
m_nFilesTransfered++;
SetGlobalCount();
if (!SendFile(lSize, nLen))
OfferNextFile();
return true;
}
bool FileTransfer::OfferNextFile()
{
// vnclog.Print(0, _T("OfferNextFile\n"));
SetGlobalCount();
m_iFile++; // go to next file in the list of files to send
HWND hWndLocalList = GetDlgItem(hWnd, IDC_LOCAL_FILELIST);
HWND hWndRemoteList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
// If one more file has to be sent, offer it !
if (m_iFile != m_FilesList.end() && !m_fAbort)
{
TCHAR szSelectedFile[128];
TCHAR szSrcFile[MAX_PATH];
memset(szSelectedFile, 0, 128);
memset(szSrcFile, 0, MAX_PATH);
LVITEM Item;
Item.mask = LVIF_TEXT;
Item.iSubItem = 0;
Item.pszText = szSelectedFile;
Item.cchTextMax = 128;
// Get the name of file to send in the local list
Item.iItem = *m_iFile;
ListView_GetItem(hWndLocalList, &Item);
GetDlgItemText(hWnd, IDC_CURR_LOCAL, szSrcFile, sizeof(szSrcFile));
if (!strlen(szSrcFile)) return false; // no destination dir selected - msgbox ?
strcat(szSrcFile, szSelectedFile);
if (!OfferLocalFile(szSrcFile))
SendFiles(-1, 0);
}
else // All the files have been processed and hopefully received
{
// Refresh the remote list so new files are displayed and highlighted
ListView_DeleteAllItems(hWndRemoteList);
RequestRemoteDirectoryContent(hWnd, "");
if (m_fAbort)
SetStatus(sz_H7);
else
SetStatus(sz_H6);
EnableButtons(hWnd);
ShowFileTransferWindow(true);
Sleep(1000);
//MessageBeep(-1);
// Unlock
m_fFileCommandPending = false;
KillFTTimer(); // sf@2005
}
return true;
}
//
// Format file size so it is user friendly to read
//
void FileTransfer::GetFriendlyFileSizeString(__int64 Size, char* szText)
{
szText[0] = '\0';
if( Size > (1024*1024*1024) )
{
__int64 lRest = (Size % (1024*1024*1024));
Size /= (1024*1024*1024);
wsprintf(szText,"%u.%2.2lu Gb", (unsigned long)Size, (unsigned long)(lRest * 100 / 1024 / 1024 / 1024));
}
else if( Size > (1024*1024) )
{
unsigned long lRest = (Size % (1024*1024));
Size /= (1024*1024);
wsprintf(szText,"%u.%2.2lu Mb", (unsigned long)Size, lRest * 100 / 1024 / 1024);
}
else if ( Size > 1024 )
{
unsigned long lRest = Size % (1024);
Size /= 1024;
wsprintf(szText,"%u.%2.2lu Kb", (unsigned long)Size, lRest * 100 / 1024);
}
else
{
wsprintf(szText,"%u bytes", (unsigned long)Size);
}
}
//
// GetFileSize() doesn't handle files > 4GBytes...
// GetFileSizeEx() doesn't exist under Win9x...
// So let's write our own function.
//
bool FileTransfer::MyGetFileSize(char* szFilePath, ULARGE_INTEGER *n2FileSize)
{
WIN32_FIND_DATA fd;
HANDLE ff;
SetErrorMode(SEM_FAILCRITICALERRORS); // No popup please !
ff = FindFirstFile(szFilePath, &fd);
SetErrorMode( 0 );
if (ff == INVALID_HANDLE_VALUE)
{
return false;
}
FindClose(ff);
(*n2FileSize).LowPart = fd.nFileSizeLow;
(*n2FileSize).HighPart = fd.nFileSizeHigh;
(*n2FileSize).QuadPart = (((__int64)fd.nFileSizeHigh) << 32 ) + fd.nFileSizeLow;
return true;
}
//
// Add a file line to a ListView
//
void FileTransfer::AddFileToFileList(HWND hWnd, int nListId, WIN32_FIND_DATA& fd, bool fLocalSide)
{
// vnclog.Print(0, _T("AddFileToFileList\n"));
char szFileName[MAX_PATH + 2];
HWND hWndList = GetDlgItem(hWnd, nListId);
// If we need to keep more info on the file, we can use LVITEM lParam
// (it will be usefull if we want to make comparison between local and remote files
// for a resume function for instance, or for sorting purposes)
//
// We could also display Files attributes and other Files times...
if (((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY && strcmp(fd.cFileName, "."))
||
(!strcmp(fd.cFileName, ".."))
)
{
sprintf(szFileName, "%s%s%s", rfbDirPrefix, fd.cFileName, rfbDirSuffix);
char szUpDirMask[16];
sprintf(szUpDirMask, "%s..%s", rfbDirPrefix, rfbDirSuffix);
if (!strcmp(szFileName, szUpDirMask) && nListId == IDC_LOCAL_FILELIST)
{
nListId = nListId;
}
// Name
LVITEM Item;
Item.mask = LVIF_TEXT | LVIF_IMAGE;
Item.iItem = 0;
Item.iSubItem = 0;
Item.iImage = 0;
Item.pszText = szFileName;
int nItem = ListView_InsertItem(hWndList, &Item);
// Type
Item.mask = LVIF_TEXT;
Item.iItem = nItem;
Item.iSubItem = 1;
Item.pszText = "Folder";
ListView_SetItem(hWndList, &Item);
}
else if (strcmp(fd.cFileName, ".")) // Test actually Not necessary for remote list
{
// Name
LVITEM Item;
Item.mask = LVIF_TEXT | LVIF_IMAGE;
Item.iItem = 0;
Item.iSubItem = 0;
Item.iImage = 1;
Item.pszText = fd.cFileName;
int nItem = ListView_InsertItem(hWndList,&Item);
// Size
__int64 Size = ( ((__int64)fd.nFileSizeHigh) << 32 ) + fd.nFileSizeLow;
char szText[256];
GetFriendlyFileSizeString(Size, szText);
Item.mask = LVIF_TEXT;
Item.iItem = nItem;
Item.iSubItem = 1;
Item.pszText = szText;
ListView_SetItem(hWndList, &Item);
// Last Modif Time
// sf@2003
// For now, we've made the choice off displaying all the files
// off client AND server sides converted in clients local
// time only. So we ALSO convert server's files times in client local time
FILETIME LocalFileTime;
FileTimeToLocalFileTime(&fd.ftLastWriteTime, &LocalFileTime);
SYSTEMTIME FileTime;
FileTimeToSystemTime(fLocalSide ? &LocalFileTime : &LocalFileTime /*&fd.ftLastWriteTime*/, &FileTime);
wsprintf(szText,"%2.2d/%2.2d/%4.4d %2.2d:%2.2d",
FileTime.wMonth,
FileTime.wDay,
FileTime.wYear,
FileTime.wHour,
FileTime.wMinute
);
Item.mask = LVIF_TEXT;
Item.iItem = nItem;
Item.iSubItem = 2;
Item.pszText = szText;
ListView_SetItem(hWndList,&Item);
}
}
//
// Select the new transfered files in the dest FileList so the user find them easely
//
void FileTransfer::HighlightTransferedFiles(HWND hSrcList, HWND hDstList)
{
// vnclog.Print(0, _T("HighlightTransferedFiles\n"));
if (m_FilesList.size() > 0)
{
TCHAR szSelectedFile[128];
LVITEM Item;
Item.mask = LVIF_TEXT;
Item.iSubItem = 0;
Item.pszText = szSelectedFile;
Item.cchTextMax = 128;
LVFINDINFO Info;
Info.flags = LVFI_STRING;
Info.psz = (LPSTR)szSelectedFile;
for (m_iFile = m_FilesList.begin();
m_iFile != m_FilesList.end();
m_iFile++)
{
// Get the name of the file sent
Item.iItem = *m_iFile;
ListView_GetItem(hSrcList, &Item);
// Find this file in the list and highlight it
int nTheIndex = ListView_FindItem(hDstList, -1, &Info);
if (nTheIndex > -1)
{
ListView_SetItemState(hDstList, nTheIndex, LVIS_SELECTED, LVIS_SELECTED);
ListView_EnsureVisible(hDstList, nTheIndex, FALSE);
}
}
m_FilesList.clear();
}
}
//
//
//
bool FileTransfer::IsShortcutFolder(LPSTR szPath)
{
// vnclog.Print(0, _T("IsShortcutFolder\n"));
// Todo: Cultures Translation
char szGUIDir[64];
sprintf(szGUIDir, "%s%s%s", rfbDirPrefix, "My Documents", rfbDirSuffix);
if (!strnicmp(szPath, szGUIDir, strlen(szGUIDir)))
return true;
sprintf(szGUIDir, "%s%s%s", rfbDirPrefix, "Desktop", rfbDirSuffix);
if (!strnicmp(szPath, szGUIDir, strlen(szGUIDir)))
return true;
sprintf(szGUIDir, "%s%s%s", rfbDirPrefix, "Network Favorites", rfbDirSuffix);
if (!strnicmp(szPath, szGUIDir, strlen(szGUIDir)))
return true;
return false;
}
//
//
//
bool FileTransfer::ResolvePossibleShortcutFolder(HWND hWnd, LPSTR szFolder)
{
// vnclog.Print(0, _T("ResolvePossibleShortcutFolder\n"));
TCHAR szP[MAX_PATH];
int nFolder = -1;
char szGUIDir[64];
sprintf(szGUIDir, "%s%s%s", rfbDirPrefix, "My Documents", rfbDirSuffix);
if (!strnicmp(szFolder, szGUIDir, strlen(szGUIDir)))
nFolder = CSIDL_PERSONAL;
sprintf(szGUIDir, "%s%s%s", rfbDirPrefix, "Desktop", rfbDirSuffix);
if (!strnicmp(szFolder, szGUIDir, strlen(szGUIDir)))
nFolder = CSIDL_DESKTOP;
sprintf(szGUIDir, "%s%s%s", rfbDirPrefix, "Network Favorites", rfbDirSuffix);
if (!strnicmp(szFolder, szGUIDir, strlen(szGUIDir)))
nFolder = CSIDL_NETHOOD;
/*
if (!strnicmp(szFolder, "(Net. Shares)", 9))
nFolder = CSIDL_NETWORK;
*/
if (nFolder != -1)
{
// if (SHGetSpecialFolderPath(NULL, szP, nFolder, FALSE))
if (GetSpecialFolderPath(nFolder, szP))
{
strcat(szP,"\\");
SetDlgItemText(hWnd, IDC_CURR_LOCAL, szP);
}
return true;
}
return false;
}
bool FileTransfer::GetSpecialFolderPath(int nId, char* szPath)
{
LPITEMIDLIST pidl;
if (SHGetSpecialFolderLocation(0, nId, &pidl) != NOERROR)
return false;
if (!SHGetPathFromIDList(pidl, szPath) )
return false;
return true;
}
//
// Populate the local machine listbox with files located in szPath
//
void FileTransfer::PopulateLocalListBox(HWND hWnd, LPSTR szPath)
{
// vnclog.Print(0, _T("PopulateLocalListBox\n"));
char ofDir[MAX_PATH];
char ofDirT[MAX_PATH];
int nSelected = -1;
int nCount = 0;
int nFileCount = 0;
char szLocalStatus[128];
HWND hWndLocalList = GetDlgItem(hWnd, IDC_LOCAL_FILELIST);
HWND hWndRemoteList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
ofDir[0] = '\0';
ofDirT[0] = '\0';
if (lstrlen(szPath) == 0)
{
nCount = ListView_GetItemCount(hWndLocalList);
for (nSelected = 0; nSelected < nCount; nSelected++)
{
if(ListView_GetItemState(hWndLocalList, nSelected, LVIS_SELECTED) & LVIS_SELECTED)
{
LVITEM Item;
Item.mask = LVIF_TEXT;
Item.iItem = nSelected;
Item.iSubItem = 0;
Item.pszText = ofDirT;
Item.cchTextMax = MAX_PATH;
ListView_GetItem(hWndLocalList, &Item);
break;
}
}
if (ResolvePossibleShortcutFolder(hWnd, ofDirT))
ofDirT[0] = '\0';
}
else
{
// Usual shortcuts case
if (ResolvePossibleShortcutFolder(hWnd, szPath))
{
}
else
{
// General case
szPath[6] = '\0';
// szPath always contains a drive letter (X:) or (..)
strcpy(ofDirT, szPath);
// In the case of (..) we keep the current path intact
char szUpDirMask[16];
sprintf(szUpDirMask, "%s..%s", rfbDirPrefix, rfbDirSuffix);
if (strcmp(ofDirT, szUpDirMask))
SetDlgItemText(hWnd, IDC_CURR_LOCAL, "");
}
}
if (nSelected == nCount || lstrlen(ofDirT) == 0)
{
GetDlgItemText(hWnd, IDC_CURR_LOCAL, ofDirT, sizeof(ofDirT));
if (strlen(ofDirT) == 0) return;
}
else
{
if (ofDirT[0] == rfbDirPrefix[0] && ofDirT[1] == rfbDirPrefix[1])
{
strncpy(ofDir, ofDirT + 2, strlen(ofDirT) - 3);
ofDir[strlen(ofDirT) - 4] = '\0';
}
else
return;
GetDlgItemText(hWnd, IDC_CURR_LOCAL, ofDirT, sizeof(ofDirT));
if (!stricmp(ofDir, ".."))
{
char* p;
ofDirT[strlen(ofDirT) - 1] = '\0';
p = strrchr(ofDirT, '\\');
if (p == NULL) return;
*p = '\0';
}
else
strcat(ofDirT, ofDir);
strcat(ofDirT, "\\");
SetDlgItemText(hWnd, IDC_CURR_LOCAL, ofDirT);
}
strcpy(ofDir, ofDirT);
strcat(ofDir, "*");
// Select the good drive in the drives combo box (the first time only)
int nIndex = SendDlgItemMessage(hWnd, IDC_LOCAL_DRIVECB, CB_GETCURSEL, 0, 0L);
if (nIndex == LB_ERR)
{
char szDrive[5];
strcpy(szDrive, rfbDirPrefix);
strncat(szDrive, ofDir, 2);
nIndex = SendDlgItemMessage(hWnd, IDC_LOCAL_DRIVECB, CB_FINDSTRING, -1, (LPARAM)(LPSTR)szDrive);
SendDlgItemMessage(hWnd, IDC_LOCAL_DRIVECB, CB_SETCURSEL, nIndex, 0L);
}
sprintf(szLocalStatus, sz_H8);
SetDlgItemText(hWnd, IDC_LOCAL_STATUS, szLocalStatus);
ListView_DeleteAllItems(hWndLocalList);
WIN32_FIND_DATA fd;
HANDLE ff;
int bRet = 1;
SetErrorMode(SEM_FAILCRITICALERRORS); // No popup please !
ff = FindFirstFile(ofDir, &fd);
SetErrorMode( 0 );
if (ff == INVALID_HANDLE_VALUE)
{
sprintf(szLocalStatus, sz_H9);
SetDlgItemText(hWnd, IDC_LOCAL_STATUS, szLocalStatus);
return;
}
while (bRet != 0)
{
AddFileToFileList(hWnd, IDC_LOCAL_FILELIST, fd, true);
nFileCount++;
if (!PseudoYield(GetParent(hWnd))) return;
bRet = FindNextFile(ff, &fd);
}
FindClose(ff);
sprintf(szLocalStatus, " > %d %s", nFileCount, sz_H58);
SetDlgItemText(hWnd, IDC_LOCAL_STATUS, szLocalStatus);
// If some files have been received
HighlightTransferedFiles( hWndRemoteList, hWndLocalList);
}
//
// Request the contents of a remote directory
//
void FileTransfer::RequestRemoteDirectoryContent(HWND hWnd, LPSTR szPath)
{
// vnclog.Print(0, _T("RequestRemoteDirectoryContent\n"));
if (!m_fFTAllowed)
{
m_fFileCommandPending = false;
return;
}
char ofDir[MAX_PATH];
char ofDirT[MAX_PATH];
int nSelected = -1;
int nCount = 0;
HWND hWndRemoteList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
ofDir[0] = '\0';
ofDirT[0] = '\0';
if (lstrlen(szPath) == 0)
{
nCount = ListView_GetItemCount(hWndRemoteList);
for (nSelected = 0; nSelected < nCount; nSelected++)
{
if(ListView_GetItemState(hWndRemoteList, nSelected, LVIS_SELECTED) & LVIS_SELECTED)
{
LVITEM Item;
Item.mask = LVIF_TEXT;
Item.iItem = nSelected;
Item.iSubItem = 0;
Item.pszText = ofDirT;
Item.cchTextMax = MAX_PATH;
ListView_GetItem(hWndRemoteList, &Item);
break;
}
}
}
else
{
if (!IsShortcutFolder(szPath))
szPath[6] = '\0';
// szPath always contains a drive letter (X:) or (..)
strcpy(ofDirT, szPath);
// In the case of (..) we keep the current path intact
char szUpDirMask[16];
sprintf(szUpDirMask, "%s..%s", rfbDirPrefix, rfbDirSuffix);
if (strcmp(ofDirT, szUpDirMask))
SetDlgItemText(hWnd, IDC_CURR_REMOTE, "");
}
if (nSelected == nCount || lstrlen(ofDirT) == 0)
{
GetDlgItemText(hWnd, IDC_CURR_REMOTE, ofDirT, sizeof(ofDirT));
if (strlen(ofDirT) == 0)
{
m_fFileCommandPending = false;
return;
}
}
else
{
if (ofDirT[0] == rfbDirPrefix[0] && ofDirT[1] == rfbDirPrefix[1])
{
strncpy(ofDir, ofDirT + 2, strlen(ofDirT) - 3);
ofDir[strlen(ofDirT) - 4] = '\0';
}
else
{
m_fFileCommandPending = false;
return;
}
GetDlgItemText(hWnd, IDC_CURR_REMOTE, ofDirT, sizeof(ofDirT));
if (!stricmp(ofDir, ".."))
{
char* p;
ofDirT[strlen(ofDirT) - 1] = '\0';
p = strrchr(ofDirT, '\\');
if (p == NULL)
{
m_fFileCommandPending = false;
return;
}
*p = '\0';
}
else
strcat(ofDirT, ofDir);
strcat(ofDirT, "\\");
SetDlgItemText(hWnd, IDC_CURR_REMOTE, ofDirT);
}
strcpy(ofDir, ofDirT);
// Todo: In case of shortcuts dir, do a translation here !
// Select the good drive in the drives combo box (the first time only)
int nIndex = SendDlgItemMessage(hWnd, IDC_REMOTE_DRIVECB, CB_GETCURSEL, 0, 0L);
if (nIndex == LB_ERR)
{
char szDrive[5];
strcpy(szDrive, rfbDirPrefix);
strncat(szDrive, ofDir, 2);
nIndex = SendDlgItemMessage(hWnd, IDC_REMOTE_DRIVECB, CB_FINDSTRING, -1, (LPARAM)(LPSTR)szDrive);
SendDlgItemMessage(hWnd, IDC_REMOTE_DRIVECB, CB_SETCURSEL, nIndex, 0L);
}
ListView_DeleteAllItems(hWndRemoteList);
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
ft.contentType = rfbDirContentRequest;
ft.contentParam = rfbRDirContent; // Directory content please
ft.length = Swap32IfLE(strlen(ofDir));
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
m_pCC->WriteExact((char *)ofDir, strlen(ofDir));
return;
}
//
// Populate the remote machine listbox with files received from server
//
void FileTransfer::PopulateRemoteListBox(HWND hWnd, int nLen)
{
// vnclog.Print(0, _T("PopulateRemoteListBox\n"));
char szRemoteStatus[128];
// If the distant media is not browsable for some reason
if (nLen == 0)
{
sprintf(szRemoteStatus, sz_H10);
SetDlgItemText(hWnd, IDC_REMOTE_STATUS, szRemoteStatus);
return;
}
// sf@2004 - Read the returned Directory full path
if (nLen > 1 && !m_fOldFTProtocole)
{
TCHAR szPath[MAX_PATH];
if (nLen > sizeof(szPath)) return;
m_pCC->ReadString((char *)szPath, nLen);
SetDlgItemText(hWnd, IDC_CURR_REMOTE, szPath);
}
sprintf(szRemoteStatus, sz_H11);
SetDlgItemText(hWnd, IDC_REMOTE_STATUS, szRemoteStatus);
// The dir in the current packet
memset(&m_fd, '\0', sizeof(WIN32_FIND_DATA));
m_nFileCount = 0;
m_fDirectoryReceptionRunning = true;
// FT Backward compatibility DIRTY hack for DSMPlugin mode...
if (m_fOldFTProtocole && m_pCC->m_fUsePlugin)
{
m_pCC->m_nTO = 0;
ProcessFileTransferMsg();
}
//ListView_DeleteAllItems(GetDlgItem(hWnd, IDC_REMOTE_FILELIST));
}
//
//
//
void FileTransfer::ReceiveDirectoryItem(HWND hWnd, int nLen)
{
// vnclog.Print(0, _T("ReceiveDirectoryItem\n"));
if (!m_fDirectoryReceptionRunning) return;
if (nLen > sizeof(m_szFileSpec)) return;
// Read the File/Directory full info
m_pCC->ReadString((char *)m_szFileSpec, nLen);
memset(&m_fd, '\0', sizeof(WIN32_FIND_DATA));
memcpy(&m_fd, m_szFileSpec, nLen);
AddFileToFileList(hWnd, IDC_REMOTE_FILELIST, m_fd, false);
m_nFileCount++;
// PseudoYield(pFileTransfer->hWnd);
if (!PseudoYield(GetParent(hWnd))) return;
// FT Backward compatibility DIRTY hack for DSMPlugin mode...
if (m_fOldFTProtocole && m_pCC->m_fUsePlugin)
{
m_pCC->m_nTO = 0;
ProcessFileTransferMsg();
}
}
//
//
//
void FileTransfer::FinishDirectoryReception()
{
// vnclog.Print(0, _T("FinishDirectoryReception\n"));
if (!m_fDirectoryReceptionRunning) return;
HWND hWndLocalList = GetDlgItem(hWnd, IDC_LOCAL_FILELIST);
HWND hWndRemoteList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
char szRemoteStatus[128];
sprintf(szRemoteStatus, " > %d %s", m_nFileCount, sz_H58);
SetDlgItemText(hWnd, IDC_REMOTE_STATUS, szRemoteStatus);
// If some files have been sent to remote side highlight them
HighlightTransferedFiles(hWndLocalList, hWndRemoteList);
// UpdateWindow(hWnd);
m_fDirectoryReceptionRunning = false;
}
//
// request the list of remote drives
//
void FileTransfer::RequestRemoteDrives()
{
// vnclog.Print(0, _T("RequestRemoteDrives\n"));
if (!m_fFTAllowed) return;
// TODO : hook error !
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
ft.contentType = rfbDirContentRequest;
ft.contentParam = rfbRDrivesList; // List of Remote Drives please
ft.length = 0;
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
return;
}
//
// Fill the Remote FilesList and remote drives combo box
//
void FileTransfer::ListRemoteDrives(HWND hWnd, int nLen)
{
// vnclog.Print(0, _T("ListRemoteDrives\n"));
TCHAR szDrivesList[256]; // Format when filled : "C:t<NULL>D:t<NULL>....Z:t<NULL><NULL>"
TCHAR szDrive[4];
TCHAR szTheDrive[128];
TCHAR szType[32];
int nIndex = 0;
if (nLen > sizeof(szDrivesList)) return;
m_pCC->ReadString((char *)szDrivesList, nLen);
HWND hWndRemoteList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
SendDlgItemMessage(hWnd, IDC_REMOTE_DRIVECB, LB_RESETCONTENT, 0, 0L);
ListView_DeleteAllItems(hWndRemoteList);
SetDlgItemText(hWnd, IDC_CURR_REMOTE, "");
// Fill the tree with the remote drives
while (nIndex < nLen - 3)
{
strcpy(szDrive, szDrivesList + nIndex);
nIndex += 4;
// Get the type of drive
switch (szDrive[2])
{
case 'l':
sprintf(szType, "%s", "Local Disk");
break;
case 'f':
sprintf(szType, "%s", "Removable");
break;
case 'c':
sprintf(szType, "%s", "CD-ROM");
break;
case 'n':
sprintf(szType, "%s", "Network");
break;
default:
sprintf(szType, "%s", "Unknown");
break;
}
szDrive[2] = '\0'; // remove the type char
sprintf(szTheDrive, "%s%s%s", rfbDirPrefix, szDrive, rfbDirSuffix);
LVITEM Item;
Item.mask = LVIF_TEXT | LVIF_IMAGE;
Item.iItem = 0;
Item.iSubItem = 0;
Item.iImage = 2;
Item.pszText = szTheDrive;
int nItem = ListView_InsertItem(hWndRemoteList, &Item);
Item.mask = LVIF_TEXT;
Item.iItem = nItem;
Item.iSubItem = 1;
Item.pszText = szType;
ListView_SetItem(hWndRemoteList, &Item);
// Prepare it for Combo Box and add it
strcat(szTheDrive, " - ");
strcat(szTheDrive, szType);
SendMessage(GetDlgItem(hWnd, IDC_REMOTE_DRIVECB), CB_ADDSTRING, 0, (LPARAM)szTheDrive);
}
// List the usual shorcuts
if (!m_fOldFTProtocole)
{
char szGUIDir[64];
// MyDocuments
LVITEM Item;
Item.mask = LVIF_TEXT;
Item.iItem = 0;
Item.iSubItem = 0;
sprintf(szGUIDir, "%s%s%s", rfbDirPrefix, "My Documents", rfbDirSuffix);
Item.pszText = szGUIDir; // Todo: Fr/De
ListView_InsertItem(hWndRemoteList, &Item);
SendMessage(GetDlgItem(hWnd, IDC_REMOTE_DRIVECB), CB_ADDSTRING, 0, (LPARAM)szGUIDir);
// Desktop
Item.mask = LVIF_TEXT;
Item.iItem = 0;
Item.iSubItem = 0;
sprintf(szGUIDir, "%s%s%s", rfbDirPrefix, "Desktop", rfbDirSuffix);
Item.pszText = szGUIDir; // Todo: Fr/De
ListView_InsertItem(hWndRemoteList, &Item);
SendMessage(GetDlgItem(hWnd, IDC_REMOTE_DRIVECB), CB_ADDSTRING, 0, (LPARAM)szGUIDir);
Item.mask = LVIF_TEXT;
Item.iItem = 0;
Item.iSubItem = 0;
sprintf(szGUIDir, "%s%s%s", rfbDirPrefix, "Network Favorites", rfbDirSuffix);
Item.pszText = szGUIDir; // Todo: Fr/De
ListView_InsertItem(hWndRemoteList, &Item);
SendMessage(GetDlgItem(hWnd, IDC_REMOTE_DRIVECB), CB_ADDSTRING, 0, (LPARAM)szGUIDir);
}
SendMessage(GetDlgItem(hWnd, IDC_REMOTE_DRIVECB), CB_SETCURSEL, -1, 0);
}
//
// List local drives
//
void FileTransfer::ListDrives(HWND hWnd)
{
// vnclog.Print(0, _T("ListDrives\n"));
TCHAR szDrivesList[256]; // Format when filled : "C:\<NULL>D:\<NULL>....Z:\<NULL><NULL>"
TCHAR szDrive[4];
TCHAR szTheDrive[32];
TCHAR szType[32];
UINT nType = 0;
DWORD dwLen;
int nIndex = 0;
dwLen = GetLogicalDriveStrings(256, szDrivesList);
HWND hWndLocalList = GetDlgItem(hWnd, IDC_LOCAL_FILELIST);
SendDlgItemMessage(hWnd, IDC_LOCAL_DRIVECB, LB_RESETCONTENT, 0, 0L);
ListView_DeleteAllItems(hWndLocalList);
SetDlgItemText(hWnd, IDC_CURR_LOCAL, "");
// Parse the list of drives
while (nIndex < dwLen - 3)
{
strcpy(szDrive, szDrivesList + nIndex);
nIndex += 4;
szDrive[2] = '\0'; // remove the '\'
sprintf(szTheDrive, "%s%s%s", rfbDirPrefix, szDrive, rfbDirSuffix);
// szName[0] = '\0';
szType[0] = '\0';
strcat(szDrive, "\\");
// GetVolumeInformation(szDrive, szName, sizeof(szName), NULL, NULL, NULL, NULL, NULL);
// Get infos on the Drive (type and Name)
nType = GetDriveType(szDrive);
switch (nType)
{
case DRIVE_FIXED:
sprintf(szType, "%s", "Local Disk");
break;
case DRIVE_REMOVABLE:
sprintf(szType, "%s", "Removable");
break;
case DRIVE_CDROM:
sprintf(szType, "%s", "CD-ROM");
break;
case DRIVE_REMOTE:
sprintf(szType, "%s", "Network");
break;
default:
sprintf(szType, "%s", "Unknown");
break;
}
// Add it to the ListView
LVITEM Item;
Item.mask = LVIF_TEXT | LVIF_IMAGE;
Item.iItem = 0;
Item.iSubItem = 0;
Item.iImage = 2;
Item.pszText = szTheDrive;
int nItem = ListView_InsertItem(hWndLocalList, &Item);
Item.mask = LVIF_TEXT;
Item.iItem = nItem;
Item.iSubItem = 1;
Item.pszText = szType;
ListView_SetItem(hWndLocalList, &Item);
// Prepare it for Combo Box and add it
strcat(szTheDrive, " - ");
strcat(szTheDrive, szType);
SendMessage(GetDlgItem(hWnd, IDC_LOCAL_DRIVECB), CB_ADDSTRING, 0, (LPARAM)szTheDrive);
}
// List the usual shorcuts
char szGUIDir[64];
// MyDocuments
LVITEM Item;
Item.mask = LVIF_TEXT;
Item.iItem = 0;
Item.iSubItem = 0;
sprintf(szGUIDir, "%s%s%s", rfbDirPrefix, "My Documents", rfbDirSuffix);
Item.pszText = szGUIDir; // Todo: Fr/De
ListView_InsertItem(hWndLocalList, &Item);
SendMessage(GetDlgItem(hWnd, IDC_LOCAL_DRIVECB), CB_ADDSTRING, 0, (LPARAM)szGUIDir);
// Desktop
Item.mask = LVIF_TEXT;
Item.iItem = 0;
Item.iSubItem = 0;
sprintf(szGUIDir, "%s%s%s", rfbDirPrefix, "Desktop", rfbDirSuffix);
Item.pszText = szGUIDir; // Todo: Fr/De
ListView_InsertItem(hWndLocalList, &Item);
SendMessage(GetDlgItem(hWnd, IDC_LOCAL_DRIVECB), CB_ADDSTRING, 0, (LPARAM)szGUIDir);
// MyDocuments
Item.mask = LVIF_TEXT;
Item.iItem = 0;
Item.iSubItem = 0;
sprintf(szGUIDir, "%s%s%s", rfbDirPrefix, "Network Favorites", rfbDirSuffix);
Item.pszText = szGUIDir; // Todo: Fr/De
ListView_InsertItem(hWndLocalList, &Item);
SendMessage(GetDlgItem(hWnd, IDC_LOCAL_DRIVECB), CB_ADDSTRING, 0, (LPARAM)szGUIDir);
SendMessage(GetDlgItem(hWnd, IDC_LOCAL_DRIVECB), CB_SETCURSEL, -1, 0);
}
//
// Set gauge max value
//
void FileTransfer::SetTotalSize(HWND hWnd, DWORD dwTotalSize)
{
// vnclog.Print(0, _T("SetTotalSize\n"));
SendDlgItemMessage(hWnd, IDC_PROGRESS, PBM_SETPOS, (WPARAM)0, (LPARAM)0L);
SendDlgItemMessage(hWnd, IDC_PROGRESS, PBM_SETRANGE, (WPARAM)0, MAKELPARAM(0, m_nBlockSize));
}
//
// Set gauge value
//
void FileTransfer::SetGauge(HWND hWnd, __int64 dwCount)
{
// vnclog.Print(0, _T("SetGauge\n"));
DWORD dwSmallerCount = (DWORD)(dwCount / m_nBlockSize);
DWORD dwSmallerFileSize = (DWORD)(m_nnFileSize / m_nBlockSize);
if (dwSmallerFileSize == 0) dwSmallerFileSize = 1;
DWORD dwValue = (DWORD)( (((__int64)(dwSmallerCount) * m_nBlockSize / dwSmallerFileSize)));
if (dwValue != m_dwCurrentValue)
{
SendDlgItemMessage(hWnd, IDC_PROGRESS, PBM_SETPOS, dwValue, 0);
m_dwCurrentValue = dwValue;
}
DWORD dwPercent = (DWORD)(((__int64)(dwSmallerCount) * 100 / dwSmallerFileSize));
if (dwPercent != m_dwCurrentPercent)
{
char szPercent[5];
sprintf(szPercent, "%d%%", dwPercent);
SetDlgItemText(hWnd, IDC_PERCENT, szPercent);
m_dwCurrentPercent = dwPercent;
}
}
//
// Display global progress (ratio files transfered/Total Files To transfer)
//
void FileTransfer::SetGlobalCount()
{
// vnclog.Print(0, _T("SetGlobalCount\n"));
char szGlobal[64];
wsprintf(szGlobal,
"File %d/%d",
m_nFilesTransfered,
m_nFilesToTransfer
);
SetDlgItemText(hWnd, IDC_GLOBAL_STATUS, szGlobal);
}
//
// Display current status and add it to the history combo box
//
void FileTransfer::SetStatus(LPSTR szStatus)
{
// vnclog.Print(0, _T("SetStatus\n"));
// time_t lTime;
char dbuffer [9];
char tbuffer [9];
char szHist[255 + 64];
SetDlgItemText(hWnd, IDC_STATUS, szStatus);
_tzset();
// time(&lTime);
_strdate(dbuffer);
_strtime(tbuffer);
sprintf(szHist, " > %s %s - %s", dbuffer, tbuffer/*ctime(&lTime)*/, szStatus);
LRESULT Index = SendMessage(GetDlgItem(hWnd, IDC_HISTORY_CB), CB_ADDSTRING, 0, (LPARAM)szHist);
SendMessage(GetDlgItem(hWnd, IDC_HISTORY_CB), CB_SETCURSEL, (WPARAM)Index, (LPARAM)0);
}
//
// Request a file
//
void FileTransfer::RequestRemoteFile(LPSTR szRemoteFileName)
{
// vnclog.Print(0, _T("RequestRemoteFile\n"));
if (!m_fFTAllowed) return;
// Ensure Backward FT compatibility (Directory reception)....
if (m_fOldFTProtocole)
{
char* p1 = strrchr(szRemoteFileName, '\\') + 1;
char* p2 = strrchr(szRemoteFileName, rfbDirSuffix[0]);
if (
p1[0] == rfbDirPrefix[0] && p1[1] == rfbDirPrefix[1] // Check dir prefix
&& p2[0] == rfbDirSuffix[0] && p2[1] == rfbDirSuffix[1] && p2 != NULL && p1 < p2 // Check dir suffix
) //
{
// p1 = strrchr(szRemoteFileName, '\\') + 1;
char szDirectoryName[MAX_PATH];
strcpy(szDirectoryName, p1 + 2); // Skip dir prefix (2 chars)
szDirectoryName[strlen(szDirectoryName) - 2] = '\0'; // Remove dir suffix (2 chars)
*p1 = '\0';
strcat(szRemoteFileName, "("),
strcat(szRemoteFileName, szDirectoryName);
strcat(szRemoteFileName, ")");
}
}
// TODO : hook error !
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
ft.contentType = rfbFileTransferRequest;
ft.contentParam = 0;
ft.length = Swap32IfLE(strlen(szRemoteFileName));
ft.size = (m_pCC->kbitsPerSecond > 2048) ? Swap32IfLE(0) : Swap32IfLE(1); // 1 means "Enable compression"
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
m_pCC->WriteExact((char *)szRemoteFileName, strlen(szRemoteFileName));
return;
}
//
// Receive a file
//
bool FileTransfer::ReceiveFile(unsigned long lSize, int nLen)
{
// vnclog.Print(0, _T("ReceiveFile\n"));
if (!m_fFTAllowed) return false;
int fError = false;
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
ft.contentType = rfbFileHeader;
ft.size = Swap32IfLE(0);
ft.length = Swap32IfLE(0);
char *szRemoteFileName = new char [nLen+1];
if (szRemoteFileName == NULL) return false;
memset(szRemoteFileName, 0, nLen+1);
// Read in the Name of the file to copy (remote full name !)
m_pCC->ReadExact(szRemoteFileName, nLen);
char szStatus[512];
// If lSize = -1 (0xFFFFFFFF) that means that the Src file on the remote machine
// could not be opened for some reason (locked, doesn't exits any more...)
if (lSize == -1)
{
sprintf(szStatus, " %s < %s > %s", sz_H12, szRemoteFileName, sz_H13);
// SetDlgItemText(pFileTransfer->hWnd, IDC_STATUS, szStatus);
SetStatus(szStatus);
delete [] szRemoteFileName;
return false;
}
// sf@2004 - The file size can be wrong for huge files (>4Gb)
// idealy we should pass another param (sizeH) in the rfbFileTransfer msg (same thing
// for the Date/Time) but we want to maintain backward compatibility between all Ultra V1 RC version..
// So instead we pass the additionnal High size param after the received string...of the current msg
// Parse the FileTime and isolate filename
CARD32 sizeH = 0;
if (!m_fOldFTProtocole)
{
CARD32 sizeHtmp;
m_pCC->ReadExact((char*)&sizeHtmp, sizeof(CARD32));
sizeH = Swap32IfLE(sizeHtmp);
}
// Get the current path (destination path)
GetDlgItemText(hWnd, IDC_CURR_LOCAL, m_szDestFileName, sizeof(m_szDestFileName));
char *p = strrchr(szRemoteFileName, ',');
if (p == NULL)
m_szIncomingFileTime[0] = '\0';
else
{
strcpy(m_szIncomingFileTime, p+1);
*p = '\0';
}
// Check the free space on local destination drive
bool fErr = false;
ULARGE_INTEGER lpFreeBytesAvailable;
ULARGE_INTEGER lpTotalBytes;
ULARGE_INTEGER lpTotalFreeBytes;
unsigned long dwFreeKBytes;
char *szDestPath = new char [strlen(m_szDestFileName) + 1];
memset(szDestPath, 0, strlen(m_szDestFileName) + 1);
strcpy(szDestPath, m_szDestFileName);
*strrchr(szDestPath, '\\') = '\0'; // We don't handle UNCs for now
PGETDISKFREESPACEEX pGetDiskFreeSpaceEx;
pGetDiskFreeSpaceEx = (PGETDISKFREESPACEEX)GetProcAddress( GetModuleHandle("kernel32.dll"),"GetDiskFreeSpaceExA");
if (pGetDiskFreeSpaceEx)
{
if (!pGetDiskFreeSpaceEx((LPCTSTR)szDestPath,
&lpFreeBytesAvailable,
&lpTotalBytes,
&lpTotalFreeBytes)) fErr = true;
}
delete [] szDestPath;
dwFreeKBytes = (unsigned long) (Int64ShraMod32(lpFreeBytesAvailable.QuadPart, 10));
if (dwFreeKBytes < (unsigned long)(lSize / 1000)) fErr = true;
if (fErr)
{
sprintf(szStatus, " %s < %s >",sz_H14, strrchr(szRemoteFileName, '\\') + 1);
SetStatus(szStatus);
delete [] szRemoteFileName;
// Tell the server to cancel the transfer
ft.size = Swap32IfLE(-1);
if (m_fOldFTProtocole)
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg);
else
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
return false;
}
strcat(m_szDestFileName, strrchr(szRemoteFileName, '\\') + 1);
m_nnFileSize = (((__int64)(sizeH)) << 32) + lSize;
char szFFS[96];
GetFriendlyFileSizeString(m_nnFileSize, szFFS);
sprintf(szStatus, " %s < %s > (%s) <<<",
sz_H15, m_szDestFileName , szFFS/*, szRemoteFileName*/);
SetStatus(szStatus);
SetTotalSize(hWnd, lSize); // In bytes
SetGauge(hWnd, 0); // In bytes
UpdateWindow(hWnd);
// Create the local Destination file
m_hDestFile = CreateFile(m_szDestFileName,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
// sf@2004 - Delta Transfer
// DWORD dwErr = GetLastError();
bool fAlreadyExists = (GetLastError() == ERROR_ALREADY_EXISTS);
if (m_hDestFile == INVALID_HANDLE_VALUE)
{
sprintf(szStatus, " %s < %s > %s", sz_H12, m_szDestFileName, sz_H16);
SetStatus(szStatus);
CloseHandle(m_hDestFile);
delete [] szRemoteFileName;
// Tell the server to cancel the transfer
ft.size = Swap32IfLE(-1);
if (m_fOldFTProtocole)
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg);
else
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
return false;
}
delete [] szRemoteFileName;
m_pCC->CheckFileChunkBufferSize(m_nBlockSize + 1024);
// sf@2004 - Delta Transfer
if (fAlreadyExists && !m_fOldFTProtocole)
{
// DWORD dwFileSize = GetFileSize(m_hDestFile, NULL);
ULARGE_INTEGER n2FileSize;
bool bSizeOk = MyGetFileSize(m_szDestFileName, &n2FileSize);
// if (dwFileSize != 0xFFFFFFFF)
if (bSizeOk)
{
unsigned long nCSBufferSize = (4 * (unsigned long)(n2FileSize.QuadPart / m_nBlockSize)) + 1024;
char* lpCSBuff = new char [nCSBufferSize];
if (lpCSBuff != NULL)
{
int nCSBufferLen = GenerateFileChecksums( m_hDestFile,
lpCSBuff,
nCSBufferSize
);
if (nCSBufferLen != -1)
{
//sprintf(szStatus, " Sending %d bytes of file checksums to remote machine. Please Wait...", nCSBufferSize);
//SetStatus(szStatus);
rfbFileTransferMsg ftm;
ftm.type = rfbFileTransfer;
ftm.contentType = rfbFileChecksums;
ftm.size = Swap32IfLE(nCSBufferSize);
ftm.length = Swap32IfLE(nCSBufferLen);
m_pCC->WriteExact((char *)&ftm, sz_rfbFileTransferMsg, rfbFileTransfer);
m_pCC->WriteExact((char *)lpCSBuff, nCSBufferLen);
}
}
}
}
// Tell the server that the transfer can start
ft.size = Swap32IfLE(lSize);
if (m_fOldFTProtocole)
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg);
else
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
// DWORD dwNbPackets = (DWORD)(lSize / m_nBlockSize);
m_dwNbReceivedPackets = 0;
m_dwNbBytesWritten = 0;
m_dwTotalNbBytesWritten = 0;
m_dwTotalNbBytesNotReallyWritten = 0;
m_nPacketCount = 0;
m_fPacketCompressed = true;
m_fFileDownloadError = false;
m_fFileDownloadRunning = true;
// FT Backward compatibility DIRTY hack for DSMPlugin mode...
if (m_fOldFTProtocole && m_pCC->m_fUsePlugin)
{
m_pCC->m_nTO = 0;
ProcessFileTransferMsg();
}
return true;
}
//
// Receive incoming file chunk
//
bool FileTransfer::ReceiveFileChunk(int nLen, int nSize)
{
// vnclog.Print(0, _T("ReceiveFileChunk\n"));
if (!m_fFileDownloadRunning) return false;
if (m_fFileDownloadError)
FinishFileReception();
BOOL fRes = true;
bool fAlreadyHere = (nSize == 2);
m_fPacketCompressed = true; // sf@2005 - This missing line was causing RC19 file reception bug...
if (nLen > m_pCC->m_filechunkbufsize) return false;
// sf@2004 - Delta Transfer - Empty packet
if (fAlreadyHere)
{
DWORD dwPtr = SetFilePointer(m_hDestFile, nLen, NULL, FILE_CURRENT);
if (dwPtr == 0xFFFFFFFF)
fRes = false;
}
else
{
m_pCC->ReadExact((char *)m_pCC->m_filechunkbuf, nLen);
if (nSize == 0)
m_fPacketCompressed = false;
unsigned int nRawBytes = m_nBlockSize + 1024;
if (m_fPacketCompressed)
{
// Decompress incoming data
m_pCC->CheckFileZipBufferSize(nRawBytes);
int nRetU = uncompress( (unsigned char*)m_pCC->m_filezipbuf,// Dest
(unsigned long *)&nRawBytes,// Dest len
(unsigned char*)m_pCC->m_filechunkbuf, // Src
nLen // Src len
);
if (nRetU != 0)
{
// vnclog.Print(0, _T("uncompress error in ReceiveFile: %d\n"), nRet);
m_fFileDownloadError = true;
// break;
}
Sleep(5);
}
fRes = WriteFile(m_hDestFile,
m_fPacketCompressed ? m_pCC->m_filezipbuf : m_pCC->m_filechunkbuf,
m_fPacketCompressed ? nRawBytes : nLen,
&m_dwNbBytesWritten,
NULL);
}
if (!fRes)
{
// TODO: Ask the server to stop the transfer
m_fFileDownloadError = true;
}
m_dwTotalNbBytesWritten += (fAlreadyHere ? nLen : m_dwNbBytesWritten);
m_dwTotalNbBytesNotReallyWritten += (fAlreadyHere ? nLen : 0);
m_dwNbReceivedPackets++;
// Refresh of the progress bar
SetGauge(hWnd, m_dwTotalNbBytesWritten);
PseudoYield(GetParent(hWnd));
// We still support the *dirty* old "Abort" method (for backward compatibility wirh UltraVNC Servers <=RC18)
if (m_fOldFTProtocole)
{
// Every 10 packets, test if the transfer must be stopped
m_nPacketCount++;
if (m_nPacketCount > 10)
{
m_fAborted = true;
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
ft.contentType = rfbFilePacket;
ft.contentParam = 0;
ft.length = 0;
if (m_fAbort || m_fFileDownloadError)
{
// Ask the server to stop the transfer
ft.size = Swap32IfLE(-1);
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg/*, rfbFileTransfer*/);
}
else
{
// Tell the server to continue the transfer
ft.size = Swap32IfLE(0);
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg/*, rfbFileTransfer*/);
}
m_nPacketCount = 0;
}
}
else // New V2 FT Protocole
{
// Now abort the file transfer if required by the user
if (m_fAbort && !m_fAborted)
{
m_fAborted = true;
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
ft.contentType = rfbAbortFileTransfer;
ft.contentParam = 0;
ft.length = 0;
ft.size = 0;
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
}
}
// FT Backward compatibility DIRTY hack for DSMPlugin mode...
if (m_fOldFTProtocole && m_pCC->m_fUsePlugin)
{
m_pCC->m_nTO = 0;
ProcessFileTransferMsg();
}
return true;
}
//
// Finish File Download
//
bool FileTransfer::FinishFileReception()
{
// vnclog.Print(0, _T("FinishFileReception\n"));
if (!m_fFileDownloadRunning) return false;
m_fFileDownloadRunning = false;
// sf@2004 - Delta transfer
SetEndOfFile(m_hDestFile);
// TODO : check dwNbReceivedPackets and dwTotalNbBytesWritten or test a checksum
FlushFileBuffers(m_hDestFile);
char szStatus[512];
if (m_fFileDownloadError)
sprintf(szStatus, " %s < %s > %s", sz_H19,m_szDestFileName,sz_H20);
else
// sprintf(szStatus, " %s < %s > %s - %u bytes", sz_H17, m_szDestFileName,sz_H18, (m_dwTotalNbBytesWritten - m_dwTotalNbBytesNotReallyWritten)); // Testing
sprintf(szStatus, " %s < %s > %s", sz_H17, m_szDestFileName,sz_H18);
SetStatus(szStatus);
// Set the DestFile Time Stamp
if (strlen(m_szIncomingFileTime))
{
FILETIME DestFileTime;
SYSTEMTIME FileTime;
FileTime.wMonth = atoi(m_szIncomingFileTime);
FileTime.wDay = atoi(m_szIncomingFileTime + 3);
FileTime.wYear = atoi(m_szIncomingFileTime + 6);
FileTime.wHour = atoi(m_szIncomingFileTime + 11);
FileTime.wMinute = atoi(m_szIncomingFileTime + 14);
FileTime.wMilliseconds = 0;
FileTime.wSecond = 0;
SystemTimeToFileTime(&FileTime, &DestFileTime);
// ToDo: hook error
SetFileTime(m_hDestFile, &DestFileTime, &DestFileTime, &DestFileTime);
}
CloseHandle(m_hDestFile);
// sf@2004 - Delta Transfer - Now we can keep the existing file data :)
if (m_fFileDownloadError && m_fOldFTProtocole) DeleteFile(m_szDestFileName);
// sf@2003 - Directory Transfer trick
// If the file is an Ultra Directory Zip we unzip it here and we delete the
// received file
// Todo: make a better free space check (above) in this particular case. The free space must be at least
// 3 times the size of the directory zip file (this zip file is ~50% of the real directory size)
UnzipPossibleDirectory(m_szDestFileName);
// SetStatus(szStatus);
UpdateWindow(hWnd);
// Sound notif
// MessageBeep(-1);
// Request the next file in the list
RequestNextFile();
return true;
}
//
// Unzip possible directory
// Todo: handle unzip error correctly...
//
int FileTransfer::UnzipPossibleDirectory(LPSTR szFileName)
{
// vnclog.Print(0, _T("UnzipPossibleDirectory\n"));
if (!m_fFileDownloadError
&&
!strncmp(strrchr(szFileName, '\\') + 1, rfbZipDirectoryPrefix, strlen(rfbZipDirectoryPrefix))
)
{
char szStatus[512];
char szPath[MAX_PATH + MAX_PATH];
char szDirName[MAX_PATH]; // Todo: improve this (size)
strcpy(szPath, szFileName);
// Todo: improve all this (p, p2, p3 NULL test or use a standard substring extraction function)
char *p = strrchr(szPath, '\\') + 1;
char *p2 = strchr(p, '-') + 1; // rfbZipDirectoryPrefix MUST have a "-" at the end...
strcpy(szDirName, p2);
char *p3 = strrchr(szDirName, '.');
*p3 = '\0';
if (p != NULL) *p = '\0';
strcat(szPath, szDirName);
// Create the Directory
sprintf(szStatus, " %s < %s > %s", sz_H59 , szDirName, sz_H60);
SetStatus(szStatus);
bool fUnzip = m_pZipUnZip->UnZipDirectory(szPath, szFileName);
if (fUnzip)
sprintf(szStatus, " %s < %s > %s", sz_H61, szDirName, sz_H18);
else
sprintf(szStatus, " %s < %s >. %s", sz_H62, szDirName, sz_H63);
SetStatus(szStatus);
DeleteFile(szFileName);
}
return 0;
}
//
// Finish File Download
//
bool FileTransfer::AbortFileReception()
{
// vnclog.Print(0, _T("AbortFileReception\n"));
if (!m_fFileDownloadRunning) return false;
m_fFileDownloadError = true;
FlushFileBuffers(m_hDestFile);
char szStatus[512];
sprintf(szStatus, " %s < %s > %s", sz_H19, m_szDestFileName,sz_H20);
m_fFileDownloadRunning = false;
return true;
}
//
// Offer a file
//
bool FileTransfer::OfferLocalFile(LPSTR szSrcFileName)
{
// vnclog.Print(0, _T("OfferLocalFile\n"));
if (!m_fFTAllowed) return false;
char szStatus[512];
strcpy(m_szSrcFileName, szSrcFileName);
// sf@2003 - Directory Transfer trick
// The File to transfer is actually a directory, so we must Zip it recursively and send
// the resulting zip file (it will be recursively unzipped on server side once
// the transfer is done)
int nDirZipRet = ZipPossibleDirectory(m_szSrcFileName);
if (nDirZipRet == -1)
return false;
// Open local src file
m_hSrcFile = CreateFile(
m_szSrcFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
if (m_hSrcFile == INVALID_HANDLE_VALUE)
{
sprintf(szStatus, " %s < %s >", sz_H21, m_szSrcFileName);
SetStatus(szStatus);
DWORD TheError = GetLastError();
return false;
}
// Size of src file
ULARGE_INTEGER n2SrcSize;
bool bSize = MyGetFileSize(m_szSrcFileName, &n2SrcSize);
// if (dwSrcSize == -1)
if (!bSize)
{
sprintf(szStatus, " %s < %s >", sz_H21, m_szSrcFileName);
SetStatus(szStatus);
CloseHandle(m_hSrcFile);
return false;
}
char szFFS[96];
GetFriendlyFileSizeString(n2SrcSize.QuadPart, szFFS);
sprintf(szStatus, " %s < %s > (%s) >>>", sz_H22, m_szSrcFileName , szFFS);
SetStatus(szStatus);
m_nnFileSize = n2SrcSize.QuadPart;
SetTotalSize(hWnd, m_nnFileSize); // In bytes
SetGauge(hWnd, 0); // In bytes
UpdateWindow(hWnd);
// Add the File Time Stamp to the filename
FILETIME SrcFileModifTime;
BOOL fRes = GetFileTime(m_hSrcFile, NULL, NULL, &SrcFileModifTime);
if (!fRes)
{
sprintf(szStatus, " %s < %s >", sz_H23, m_szSrcFileName);
SetStatus(szStatus);
CloseHandle(m_hSrcFile);
return false;
}
CloseHandle(m_hSrcFile);
TCHAR szDstFileName[MAX_PATH + 32];
memset(szDstFileName, 0, MAX_PATH + 32);
GetDlgItemText(hWnd, IDC_CURR_REMOTE, szDstFileName, sizeof(szDstFileName));
if (!strlen(szDstFileName)) return false; // no destination dir selected - msgbox ?
strcat(szDstFileName, strrchr(m_szSrcFileName, '\\') + 1);
char szSrcFileTime[18];
// sf@2003
// For now, we've made the choice off displaying all the files
// off client AND server sides converted in clients local
// time only. We keep file time as it is before transfering the file (absolute time)
/*
FILETIME LocalFileTime;
FileTimeToLocalFileTime(&SrcFileModifTime, &LocalFileTime);
*/
SYSTEMTIME FileTime;
FileTimeToSystemTime(/*&LocalFileTime*/&SrcFileModifTime, &FileTime);
wsprintf(szSrcFileTime,"%2.2d/%2.2d/%4.4d %2.2d:%2.2d",
FileTime.wMonth,
FileTime.wDay,
FileTime.wYear,
FileTime.wHour,
FileTime.wMinute
);
strcat(szDstFileName, ",");
strcat(szDstFileName, szSrcFileTime);
// sf@2004 - Delta Transfer
if (m_lpCSBuffer != NULL)
{
delete [] m_lpCSBuffer;
m_lpCSBuffer = NULL;
}
m_nCSOffset = 0;
m_nCSBufferSize = 0;
// Send the FileTransferMsg with rfbFileTransferOffer
// So the server creates the appropriate new file on the other side
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
ft.contentType = rfbFileTransferOffer;
ft.contentParam = 0;
ft.size = Swap32IfLE(n2SrcSize.LowPart); // File Size in bytes
ft.length = Swap32IfLE(strlen(szDstFileName));
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
m_pCC->WriteExact((char *)szDstFileName, strlen(szDstFileName));
if (!m_fOldFTProtocole)
{
CARD32 sizeH = Swap32IfLE(n2SrcSize.HighPart);
m_pCC->WriteExact((char *)&sizeH, sizeof(CARD32));
}
return true;
}
//
// Zip a possible directory
//
int FileTransfer::ZipPossibleDirectory(LPSTR szSrcFileName)
{
// vnclog.Print(0, _T("ZipPossibleDirectory\n"));
char* p1 = strrchr(szSrcFileName, '\\') + 1;
char* p2 = strrchr(szSrcFileName, rfbDirSuffix[0]);
if (
p1[0] == rfbDirPrefix[0] && p1[1] == rfbDirPrefix[1] // Check dir prefix
&& p2[1] == rfbDirSuffix[1] && p2 != NULL && p1 < p2 // Check dir suffix
) //
{
// sf@2004 - Improving Directory Transfer: Avoids ReadOnly media problem
char szDirZipPath[MAX_PATH];
char szWorkingDir[MAX_PATH];
if (GetModuleFileName(NULL, szWorkingDir, MAX_PATH))
{
char* p = strrchr(szWorkingDir, '\\');
if (p == NULL)
return -1;
*(p+1) = '\0';
}
else
return -1;
char szStatus[512];
char szPath[MAX_PATH];
char szDirectoryName[MAX_PATH];
strcpy(szPath, szSrcFileName);
p1 = strrchr(szPath, '\\') + 1;
strcpy(szDirectoryName, p1 + 2); // Skip dir prefix (2 chars)
szDirectoryName[strlen(szDirectoryName) - 2] = '\0'; // Remove dir suffix (2 chars)
*p1 = '\0';
if ((strlen(szPath) + strlen(rfbZipDirectoryPrefix) + strlen(szDirectoryName) + 4) > (MAX_PATH - 1)) return false;
// sprintf(szSrcFileName, "%s%s%s%s", szPath, rfbZipDirectoryPrefix, szDirectoryName, ".zip");
sprintf(szDirZipPath, "%s%s%s%s", szWorkingDir, rfbZipDirectoryPrefix, szDirectoryName, ".zip");
strcat(szPath, szDirectoryName);
strcpy(szDirectoryName, szPath);
if (strlen(szDirectoryName) > (MAX_PATH - 4)) return -1;
strcat(szDirectoryName, "\\*.*");
sprintf(szStatus, " %s < %s > %s", sz_H64, szPath, sz_H65);
SetStatus(szStatus);
bool fZip = m_pZipUnZip->ZipDirectory(szPath, szDirectoryName, szDirZipPath/*szSrcFileName*/, true);
if (fZip)
sprintf(szStatus, " %s < %s > %s", sz_H66, szPath, sz_H67);
else
sprintf(szStatus, " %s < %s >. %s", sz_H68, szPath, sz_H69);
SetStatus(szStatus);
if (!fZip) return -1;
strcpy(szSrcFileName, szDirZipPath);
return 1;
}
else
return 0;
}
//
// sf@2004 - Delta Transfer
// Destination file already exists
// The server sends the checksums of this file in one shot.
//
bool FileTransfer::ReceiveDestinationFileChecksums(int nSize, int nLen)
{
// vnclog.Print(0, _T("ReceiveDestinationFileChecksums\n"));
m_lpCSBuffer = new char [nLen+1]; //nSize
if (m_lpCSBuffer == NULL)
{
return false;
}
// char szStatus[255];
// sprintf(szStatus, " Receiving %d bytes of file checksums from remote machine. Please wait...", nLen);
// SetStatus(szStatus);
memset(m_lpCSBuffer, '\0', nLen+1); // nSize
m_pCC->ReadExact((char *)m_lpCSBuffer, nLen);
m_nCSBufferSize = nLen;
return true;
}
//
// SendFile
//
bool FileTransfer::SendFile(long lSize, int nLen)
{
// vnclog.Print(0, _T("SendFile\n"));
if (!m_fFTAllowed) return false;
if (nLen == 0) return false; // Used when the local file could no be open in OfferLocalFile
char *szRemoteFileName = new char [nLen+1];
if (szRemoteFileName == NULL) return false;
memset(szRemoteFileName, 0, nLen+1);
// Read in the Name of the file to copy (remote full name !)
m_pCC->ReadExact(szRemoteFileName, nLen);
char szStatus[512];
// If lSize = -1 (0xFFFFFFFF) that means that the Dst file on the remote machine
// could not be created for some reason (locked..)
if (lSize == -1)
{
sprintf(szStatus, " %s < %s > %s",sz_H12, szRemoteFileName,sz_H24);
SetStatus(szStatus);
sprintf(szStatus, " %s < %s >%s", sz_H25,szRemoteFileName,sz_H26);
SetStatus(szStatus);
delete [] szRemoteFileName;
return false;
}
// Build the local file path
// sf@2004 - Directory Transfer improvement : filename already known
/*
if (m_fOldFTProtocole)
{
GetDlgItemText(hWnd, IDC_CURR_LOCAL, m_szSrcFileName, sizeof(m_szSrcFileName));
strcat(m_szSrcFileName, strrchr(szRemoteFileName, '\\') + 1);
}
*/
delete [] szRemoteFileName;
// Open src file
m_hSrcFile = CreateFile(
m_szSrcFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
if (m_hSrcFile == INVALID_HANDLE_VALUE)
{
sprintf(szStatus, " %s < %s >", sz_H21, m_szSrcFileName);
SetStatus(szStatus);
DWORD TheError = GetLastError();
return false;
}
m_fFileUploadError = false;
m_dwNbBytesRead = 0;
m_dwTotalNbBytesRead = 0;
m_fEof = false;
// If the connection speed is > 2048 Kbit/s, no need to compress.
m_fCompress = (m_pCC->kbitsPerSecond <= 2048);
m_fFileUploadRunning = true;
m_dwLastChunkTime = timeGetTime();
// m_nNotSent = 0;
// SendFileChunk();
return true;
}
//
// Send the next file packet (upload)
// This function is called asynchronously from the
// main ClientConnection message loop
//
bool FileTransfer::SendFileChunk()
{
// vnclog.Print(0, _T("SendFilechunk\n"));
if (! m_fFileUploadRunning) return false;
if ( m_fEof || m_fFileUploadError)
{
FinishFileSending();
return true;
}
m_pCC->CheckFileChunkBufferSize(m_nBlockSize + 1024);
int nRes = ReadFile(m_hSrcFile, m_pCC->m_filechunkbuf, m_nBlockSize, &m_dwNbBytesRead, NULL);
if (!nRes && m_dwNbBytesRead != 0)
{
m_fFileUploadError = true;
}
if (nRes && m_dwNbBytesRead == 0)
{
m_fEof = true;
}
else
{
// sf@2004 - Delta Transfer
bool fAlreadyThere = false;
unsigned long nCS = 0;
// if Checksums are available for this file
if (m_lpCSBuffer != NULL)
{
if (m_nCSOffset < m_nCSBufferSize)
{
memcpy(&nCS, &m_lpCSBuffer[m_nCSOffset], 4);
if (nCS != 0)
{
m_nCSOffset += 4;
unsigned long cs = adler32(0L, Z_NULL, 0);
cs = adler32(cs, m_pCC->m_filechunkbuf, (int)m_dwNbBytesRead);
if (cs == nCS)
fAlreadyThere = true;
}
}
}
if (fAlreadyThere)
{
// Send the FileTransferMsg with empty rfbFilePacket
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
ft.contentType = rfbFilePacket;
ft.size = Swap32IfLE(2); // Means "Empty packet"// Swap32IfLE(nCS);
ft.length = Swap32IfLE(m_dwNbBytesRead);
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
// m_nNotSent += m_dwNbBytesRead;
}
else
{
// Compress the data
// (Compressed data can be longer if it was already compressed)
unsigned int nMaxCompSize = m_nBlockSize + 1024; // TODO: Improve this...
bool fCompressed = false;
if (m_fCompress && !m_fOldFTProtocole)
{
m_pCC->CheckFileZipBufferSize(nMaxCompSize);
int nRetC = compress((unsigned char*)(m_pCC->m_filezipbuf),
(unsigned long*)&nMaxCompSize,
(unsigned char*)m_pCC->m_filechunkbuf,
m_dwNbBytesRead
);
if (nRetC != 0)
{
// Todo: send data uncompressed instead
m_fFileUploadError = true;
return false;
}
Sleep(5);
fCompressed = true;
}
// If data compressed is larger, we're presumably dealing with already compressed data.
if (nMaxCompSize > m_dwNbBytesRead)
fCompressed = false;
// m_fCompress = false;
// Send the FileTransferMsg with rfbFilePacket
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
ft.contentType = rfbFilePacket;
ft.size = fCompressed ? Swap32IfLE(1) : Swap32IfLE(0);
ft.length = fCompressed ? Swap32IfLE(nMaxCompSize) : Swap32IfLE(m_dwNbBytesRead);
if(m_fOldFTProtocole)
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg);
else
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
if (fCompressed)
m_pCC->WriteExact((char *)m_pCC->m_filezipbuf, nMaxCompSize);
else
m_pCC->WriteExact((char *)m_pCC->m_filechunkbuf, m_dwNbBytesRead);
}
m_dwTotalNbBytesRead += m_dwNbBytesRead;
// Refresh progress bar
SetGauge(hWnd, m_dwTotalNbBytesRead);
PseudoYield(GetParent(hWnd));
if (m_fAbort)
{
m_fFileUploadError = true;
FinishFileSending();
return false;
}
}
// Order next asynchronous packet sending
// If Gui is visible or old blocking FT protocole : no screen updates, more speed
/*
if (m_fVisible || m_fOldFTProtocole)
{
// SendFileChunk(); // Fixme: Beware call stack...
// if (m_pCC->kbitsPerSecond <= 2048)
PostMessage(m_pCC->m_hwndMain, FileTransferSendPacketMessage, (WPARAM) 0, (LPARAM) 0);
}
else
{
//if (m_pCC->kbitsPerSecond <= 2048)
//else
// Sleep(50);
PostMessage(m_pCC->m_hwndMain, FileTransferSendPacketMessage, (WPARAM) 0, (LPARAM) 0);
}
// PostMessage(hWnd, FileTransferSendPacketMessage, (WPARAM) 0, (LPARAM) 0);
*/
return true;
}
bool FileTransfer::FinishFileSending()
{
// vnclog.Print(0, _T("FinishSendFile\n"));
if (!m_fFileUploadRunning) return false;
m_fFileUploadRunning = false;
char szStatus[512];
CloseHandle(m_hSrcFile);
if ( !m_fFileUploadError || m_fEof)
{
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
ft.contentType = rfbEndOfFile;
if (m_fOldFTProtocole)
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg);
else
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
sprintf(szStatus, " %s < %s > %s", sz_H17, m_szSrcFileName, sz_H27/*, (int)((lTotalComp * 100) / dwTotalNbBytesWritten), fCompress ? "C" : "N"*//*, szDstFileName*/);
}
else // Error during file transfer loop
{
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
ft.contentType = rfbAbortFileTransfer;
if (m_fOldFTProtocole)
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg);
else
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
sprintf(szStatus, " %s < %s > %s", sz_H19, m_szSrcFileName, sz_H28);
}
// If the transfered file is a Directory zip, we delete it locally, whatever the result of the transfer
if (!strncmp(strrchr(m_szSrcFileName, '\\') + 1, rfbZipDirectoryPrefix, strlen(rfbZipDirectoryPrefix)))
{
DeleteFile(m_szSrcFileName);
if (!m_fFileUploadError)
{
char szDirectoryName[MAX_PATH];
char *p = strrchr(m_szSrcFileName, '\\');
char *p1 = strchr(p, '-');
strcpy(szDirectoryName, p1 + 1);
szDirectoryName[strlen(szDirectoryName) - 4] = '\0'; // Remove '.zip'
// sprintf(szStatus, " %s < %s > %s - Not really sent: %ld", sz_H66, szDirectoryName, sz_H70, m_nNotSent);
sprintf(szStatus, " %s < %s > %s", sz_H66, szDirectoryName, sz_H70);
}
}
SetStatus(szStatus);
UpdateWindow(hWnd);
// Sound notif
//MessageBeep(-1);
// Send next file in the list, if any
OfferNextFile();
// if (nRet) return true; else return false;
// return !m_fFileUploadError;
return true;
}
//
// Request the creation of a directory on the remote machine
//
void FileTransfer::CreateRemoteDirectory(LPSTR szDir)
{
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
ft.contentType = rfbCommand;
ft.contentParam = rfbCDirCreate;
ft.size = 0;
ft.length = Swap32IfLE(strlen(szDir));
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
m_pCC->WriteExact((char *)szDir, strlen(szDir));
return;
}
//
// Request the deletion of a file on the remote machine
//
void FileTransfer::DeleteRemoteFile(LPSTR szFile)
{
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
ft.contentType = rfbCommand;
ft.contentParam = rfbCFileDelete;
ft.size = 0;
ft.length = Swap32IfLE(strlen(szFile));
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
m_pCC->WriteExact((char *)szFile, strlen(szFile));
return;
}
//
// Request the renaming of a file or a directory
//
void FileTransfer::RenameRemoteFileOrDirectory(LPSTR szCurrentName, LPSTR szNewName)
{
char szMsgContent[(2 * MAX_PATH) + 1];
sprintf(szMsgContent, "%s*%s", szCurrentName, szNewName);
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
ft.contentType = rfbCommand;
ft.contentParam = rfbCFileRename; // or rfbCDirRename ...
ft.size = 0;
ft.length = Swap32IfLE(strlen(szMsgContent));
m_pCC->WriteExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
m_pCC->WriteExact((char *)szMsgContent, strlen(szMsgContent));
return;
}
//
// Server's response to a directory creation command
//
bool FileTransfer::CreateRemoteDirectoryFeedback(long lSize, int nLen)
{
char *szRemoteName = new char [nLen+1];
if (szRemoteName == NULL) return false;
memset(szRemoteName, 0, nLen+1);
m_pCC->ReadExact(szRemoteName, nLen);
char szStatus[512];
if (lSize == -1)
{
sprintf(szStatus, "%s < %s > %s", sz_H29,szRemoteName,sz_H30);
SetStatus(szStatus);
delete [] szRemoteName;
return false;
}
sprintf(szStatus, "%s < %s > %s",sz_H31, szRemoteName,sz_H32);
SetStatus(szStatus);
// Refresh the remote list
ListView_DeleteAllItems(GetDlgItem(hWnd, IDC_REMOTE_FILELIST));
RequestRemoteDirectoryContent(hWnd, "");
delete [] szRemoteName;
return true;
}
//
// Server's response to a File Deletion command
//
bool FileTransfer::DeleteRemoteFileFeedback(long lSize, int nLen)
{
char *szRemoteName = new char [nLen+1];
if (szRemoteName == NULL) return false;
memset(szRemoteName, 0, nLen+1);
m_pCC->ReadExact(szRemoteName, nLen);
char szStatus[512];
if (lSize == -1)
{
sprintf(szStatus, "%s < %s > %s", sz_H33,szRemoteName,sz_H30);
SetStatus(szStatus);
delete [] szRemoteName;
return false;
}
sprintf(szStatus, "%s < %s > %s", sz_H17,szRemoteName,sz_H34);
SetStatus(szStatus);
// Refresh the remote list
if (--m_nDeleteCount == 0)
ListView_DeleteAllItems(GetDlgItem(hWnd, IDC_REMOTE_FILELIST));
RequestRemoteDirectoryContent(hWnd, "");
delete [] szRemoteName;
return true;
}
//
// Server's response to a File Deletion command
//
bool FileTransfer::RenameRemoteFileOrDirectoryFeedback(long lSize, int nLen)
{
char *szContent = new char [nLen+1];
if (szContent == NULL) return false;
memset(szContent, 0, nLen+1);
m_pCC->ReadExact(szContent, nLen);
char szStatus[512];
char *p = strrchr(szContent, '*');
char szOldName[MAX_PATH];
char szCurrentName[MAX_PATH];
strcpy(szCurrentName, p + 1);
*p = '\0';
strcpy(szOldName, szContent);
if (lSize == -1 || p == NULL)
{
sprintf(szStatus, " %s < %s > %s", sz_M5, szOldName, sz_H30);
SetStatus(szStatus);
delete [] szContent;
return false;
}
sprintf(szStatus, " %s < %s > %s < %s >", sz_M8 , szOldName, sz_M7, szCurrentName);
SetStatus(szStatus);
// Refresh the remote list
ListView_DeleteAllItems(GetDlgItem(hWnd, IDC_REMOTE_FILELIST));
RequestRemoteDirectoryContent(hWnd, "");
delete [] szContent;
return true;
}
//
// sf@2004 - Delta Transfer
// Create the checksums buffer of an open file
//
int FileTransfer::GenerateFileChecksums(HANDLE hFile, char* lpCSBuffer, int nCSBufferSize)
{
bool fEof = false;
bool fError = false;
DWORD dwNbBytesRead = 0;
int nCSBufferOffset = 0;
char* lpBuffer = new char [m_nBlockSize];
if (lpBuffer == NULL)
return -1;
while ( !fEof )
{
int nRes = ReadFile(hFile, lpBuffer, m_nBlockSize, &dwNbBytesRead, NULL);
if (!nRes && dwNbBytesRead != 0)
fError = true;
if (nRes && dwNbBytesRead == 0)
fEof = true;
else
{
unsigned long cs = adler32(0L, Z_NULL, 0);
cs = adler32(cs, (unsigned char*)lpBuffer, (int)dwNbBytesRead);
memcpy(lpCSBuffer + nCSBufferOffset, &cs, 4);
nCSBufferOffset += 4;
}
}
SetFilePointer(hFile, 0L, NULL, FILE_BEGIN);
delete [] lpBuffer;
if (fError)
return -1;
return nCSBufferOffset;
}
bool FileTransfer::IsDirectoryGetIt(char* szName)
{
char szWork[MAX_PATH];
strcpy(szWork, szName);
if (szWork[0] == rfbDirPrefix[0] && szWork[1] == rfbDirPrefix[1])
{
strncpy(szName, szWork + 2, strlen(szWork) - 3);
szName[strlen(szWork) - 4] = '\0';
return true;
}
return false;
}
#ifndef _ULTRAVNCAX_
int FileTransfer::DoDialog()
#else
int FileTransfer::DoDialog ( HWND parent /*= NULL*/ )
#endif
{
#ifndef _ULTRAVNCAX_
return DialogBoxParam(pApp->m_instance, DIALOG_MAKEINTRESOURCE(IDD_FILETRANSFER_DLG),
NULL, (DLGPROC) FileTransferDlgProc, (LONG) this);
#else
return DialogBoxParam(pApp->m_instance, DIALOG_MAKEINTRESOURCE(IDD_FILETRANSFER_DLG),
parent, (DLGPROC) FileTransferDlgProc, (LONG) this);
#endif
}
//
// 2006 - Resizable FT Window mod - By Roytam1 & and KP774
//
void FTAdjustLeft(LPRECT lprc)
{
int cx = lprc->right - lprc->left - GetSystemMetrics(SM_CXSIZEFRAME) * 2;
if(cx < 611)
{
lprc->left = lprc->right - 611 - GetSystemMetrics(SM_CXSIZEFRAME) * 2;
}
}
void FTAdjustTop(LPRECT lprc)
{
int cy = lprc->bottom - lprc->top - GetSystemMetrics(SM_CYSIZEFRAME) * 2;
if(cy < 429)
{
lprc->top = lprc->bottom - 429 - GetSystemMetrics(SM_CYSIZEFRAME) * 2;
}
}
void FTAdjustRight(LPRECT lprc)
{
int cx = lprc->right - lprc->left - GetSystemMetrics(SM_CXSIZEFRAME) * 2;
if(cx < 611)
{
lprc->right = lprc->left + 611 + GetSystemMetrics(SM_CXSIZEFRAME) * 2;
}
}
void FTAdjustBottom(LPRECT lprc)
{
int cy = lprc->bottom - lprc->top - GetSystemMetrics(SM_CYSIZEFRAME) * 2;
if(cy < 429)
{
lprc->bottom = lprc->top + 429 + GetSystemMetrics(SM_CYSIZEFRAME) * 2;
}
}
// sf@2006
void FTAdjustFileNameColumns(HWND hWnd)
{
RECT rc;
GetWindowRect(GetDlgItem(hWnd, IDC_LOCAL_FILELIST), &rc);
int w = rc.right - rc.left;
int cw = w - (70 + 100 + 25);
if (cw < 120) cw = 120;
LVCOLUMN Column;
Column.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_ORDER|LVCF_SUBITEM;
Column.fmt = LVCFMT_LEFT;
Column.cx = cw;
Column.pszText = "Name";
Column.iSubItem = 0;
Column.iOrder = 0;
HWND hWndList = GetDlgItem(hWnd, IDC_LOCAL_FILELIST);
ListView_SetColumn(hWndList, 0, &Column);
hWndList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
ListView_SetColumn(hWndList, 0, &Column);
}
//
//
//
BOOL CALLBACK FileTransfer::FileTransferDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
// This is a static method, so we don't know which instantiation we're
// dealing with. But we can get a pseudo-this from the parameter to
// WM_INITDIALOG, which we therafter store with the window and retrieve
// as follows:
FileTransfer *_this = (FileTransfer *) GetWindowLong(hWnd, GWL_USERDATA);
switch (uMsg)
{
case WM_TIMER:
{
// We have to wait for NetBuf flush
// !!!: Not necessary anymore - Pb solved on server side.
DWORD lTime = timeGetTime();
// DWORD lLastTime = _this->m_pCC->m_lLastRfbRead;
// DWORD lDelta = abs(timeGetTime() - _this->m_pCC->m_lLastRfbRead);
if (true/*meGetTime() - _this->m_pCC->m_lLastRfbRead) > 1000 */)
{
_this->m_fFileCommandPending = true;
_this->RequestPermission();
if (KillTimer(hWnd, _this->m_timer))
_this->m_timer = 0;
}
break;
}
case WM_INITDIALOG:
{
SetWindowLong(hWnd, GWL_USERDATA, lParam);
FileTransfer *_this = (FileTransfer *) lParam;
// CentreWindow(hWnd);
_this->hWnd = hWnd;
// Window always on top if Fullscreen On
if (_this->m_pCC->InFullScreenMode())
{
RECT Rect;
GetWindowRect(hWnd, &Rect);
SetWindowPos(hWnd,
HWND_TOPMOST,
Rect.left,
Rect.top,
Rect.right - Rect.left,
Rect.bottom - Rect.top,
SWP_SHOWWINDOW);
}
SetForegroundWindow(hWnd);
// Set the title
const long lTitleBufSize=256;
char szRemoteName[lTitleBufSize];
char szTitle[lTitleBufSize];
if (_snprintf(szRemoteName, 127 ,"%s", _this->m_pCC->m_desktopName) < 0 )
{
szRemoteName[128-4]='.';
szRemoteName[128-3]='.';
szRemoteName[128-2]='.';
szRemoteName[128-1]=0x00;
}
_snprintf(szTitle, lTitleBufSize-1," %s < %s> - VMOpsVNC", sz_H35,szRemoteName);
SetWindowText(hWnd, szTitle);
// Create all the columns of the Files ListViews
LVCOLUMN Column;
Column.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_ORDER|LVCF_SUBITEM;
Column.fmt = LVCFMT_LEFT;
Column.cx = 166;
Column.pszText = "Name";
Column.iSubItem = 0;
Column.iOrder = 0;
HWND hWndList = GetDlgItem(hWnd, IDC_LOCAL_FILELIST);
ListView_InsertColumn(hWndList, 0, &Column);
hWndList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
ListView_InsertColumn(hWndList, 0, &Column);
Column.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_ORDER|LVCF_SUBITEM;
Column.fmt = LVCFMT_LEFT;
Column.cx = 70;
Column.pszText = "Size";
Column.iSubItem = 1;
Column.iOrder = 1;
hWndList = GetDlgItem(hWnd, IDC_LOCAL_FILELIST);
ListView_InsertColumn(hWndList, 1, &Column);
hWndList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
ListView_InsertColumn(hWndList, 1, &Column);
Column.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_ORDER|LVCF_SUBITEM;
Column.fmt = LVCFMT_LEFT;
Column.cx = 100;
Column.pszText = "Modified";
Column.iSubItem = 2;
Column.iOrder = 2;
hWndList = GetDlgItem(hWnd, IDC_LOCAL_FILELIST);
ListView_InsertColumn(hWndList, 2, &Column);
hWndList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
ListView_InsertColumn(hWndList, 2, &Column);
// Make the selection bar full width in the ListViews
hWndList = GetDlgItem(hWnd, IDC_LOCAL_FILELIST);
ListView_SetExtendedListViewStyleEx(hWndList, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
hWndList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
ListView_SetExtendedListViewStyleEx(hWndList, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
// Create Icons List of ListViews
_this->InitListViewImagesList(GetDlgItem(hWnd, IDC_LOCAL_FILELIST));
_this->InitListViewImagesList(GetDlgItem(hWnd, IDC_REMOTE_FILELIST));
// Create the status bar
HWND hStatusBar = CreateStatusWindow(WS_VISIBLE|WS_CHILD, sz_H36 , hWnd, IDC_STATUS);
// Populate the Local listboxes with local drives
_this->ListDrives(hWnd);
// Populate the remote listboxes with remote drives if allowed by the server
if (false/*!_this->m_pCC->m_pEncrypt->IsEncryptionEnabled()*/)
{
/*
if (!_this->m_fFileCommandPending)
{
_this->m_fFileCommandPending = true;
// RequestRemoteDrives(_this);
RequestPermission(_this);
SetStatus(_this, " Connecting. Please Wait...");
}
*/
}
else
{
_this->m_timer = SetTimer( hWnd, 3333, 1000, NULL);
_this->SetStatus(sz_H37);
}
// Save original (translated) buttons labels
if (strlen(_this->m_szDeleteButtonLabel) == 0)
{
// char szLbl[64];
HWND hB = GetDlgItem(hWnd, IDC_DELETE_B);
GetWindowText(hB, (LPSTR)_this->m_szDeleteButtonLabel, 64);
}
if (strlen(_this->m_szNewFolderButtonLabel) == 0)
{
// char szLbl[64];
HWND hB = GetDlgItem(hWnd, IDC_NEWFOLDER_B);
GetWindowText(hB, (LPSTR)_this->m_szNewFolderButtonLabel, 64);
}
if (strlen(_this->m_szRenameButtonLabel) == 0)
{
// char szLbl[64];
HWND hB = GetDlgItem(hWnd, IDC_RENAME_B);
GetWindowText(hB, (LPSTR)_this->m_szRenameButtonLabel, 64);
}
// Disable Close Window in in title bar
HMENU hMenu = GetSystemMenu(_this->hWnd, 0);
int nCount = GetMenuItemCount(hMenu);
RemoveMenu(hMenu, nCount-1, MF_DISABLED | MF_BYPOSITION);
RemoveMenu(hMenu, nCount-2, MF_DISABLED | MF_BYPOSITION);
DrawMenuBar(_this->hWnd);
return TRUE;
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
return TRUE;
case IDCANCEL:
EndDialog(hWnd, FALSE);
return TRUE;
// Send selected files
case IDC_UPLOAD_B:
{
if (_this->m_fFileCommandPending) break;
TCHAR szSelectedFile[128];
TCHAR szCurrLocal[MAX_PATH];
TCHAR szDstFile[MAX_PATH + 32];
memset(szSelectedFile, 0, 128);
memset(szCurrLocal, 0, MAX_PATH);
memset(szDstFile, 0, MAX_PATH + 32);
int nSelected = -1;
int nCount = 0;
HWND hWndLocalList = GetDlgItem(hWnd, IDC_LOCAL_FILELIST);
HWND hWndRemoteList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
LVITEM Item;
Item.mask = LVIF_TEXT;
Item.iSubItem = 0;
Item.pszText = szSelectedFile;
Item.cchTextMax = 128;
// If no destination is set,nothing to do.
GetDlgItemText(hWnd, IDC_CURR_REMOTE, szDstFile, sizeof(szDstFile));
if (!strlen(szDstFile)) break; // no dest dir selected
// Get all the selected files on check if they already exist on remote side
// If they already exist, the user is prompted for overwrite
// Store the indexes of selected files in a list
_this->m_FilesList.clear();
nCount = ListView_GetItemCount(hWndLocalList);
_this->m_nConfirmAnswer = CONFIRM_YES;
for (nSelected = 0; nSelected < nCount; nSelected++)
{
if(ListView_GetItemState(hWndLocalList, nSelected, LVIS_SELECTED) & LVIS_SELECTED)
{
Item.iItem = nSelected;
ListView_GetItem(hWndLocalList, &Item);
// if (szSelectedFile[0] != '(') // Only a file can be transfered
char szUpDirMask[16];
sprintf(szUpDirMask, "%s..%s", rfbDirPrefix, rfbDirSuffix);
if (stricmp(szSelectedFile, szUpDirMask))
{
LVFINDINFO Info;
Info.flags = LVFI_STRING;
Info.psz = (LPSTR)szSelectedFile;
int nTheIndex = ListView_FindItem(hWndRemoteList, -1, &Info);
bool fDirectory = (szSelectedFile[0] == rfbDirPrefix[0] && szSelectedFile[1] == rfbDirPrefix[1]);
if (nTheIndex > -1)
{
if (_this->m_nConfirmAnswer == CONFIRM_YES || _this->m_nConfirmAnswer == CONFIRM_NO)
{
char szMes[MAX_PATH + 96];
if (fDirectory)
wsprintf(szMes, "%s < %s >\n%s", sz_H71, szSelectedFile, sz_H72);
else
wsprintf(szMes, "%s < %s >\n%s", sz_H17, szSelectedFile, sz_H38);
_this->DoFTConfirmDialog(sz_H39, _T(szMes));
if (_this->m_nConfirmAnswer == CONFIRM_NO)
continue;
if (_this->m_nConfirmAnswer == CONFIRM_NOALL)
break;
}
}
// Add the file to the list
_this->m_FilesList.push_back(nSelected);
}
}
}
if (_this->m_FilesList.size() == 0) break;
// Display Status
char szLocalStatus[128];
sprintf(szLocalStatus, " > %d %s", _this->m_FilesList.size(),sz_H40);
SetDlgItemText(hWnd, IDC_LOCAL_STATUS, szLocalStatus);
sprintf(szLocalStatus, "%s %d %s", sz_H41,_this->m_FilesList.size(),sz_H42);
_this->SetStatus(szLocalStatus);
_this->m_nFilesTransfered = 0;
_this->m_nFilesToTransfer = _this->m_FilesList.size();
// Disable buttons
_this->DisableButtons(_this->hWnd);
ShowWindow(GetDlgItem(hWnd, IDC_ABORT_B), SW_SHOW);
// Get the fisrt selected file name
_this->m_iFile = _this->m_FilesList.begin();
Item.iItem = *_this->m_iFile;
ListView_GetItem(hWndLocalList, &Item);
GetDlgItemText(hWnd, IDC_CURR_LOCAL, szCurrLocal, sizeof(szCurrLocal));
if (!strlen(szCurrLocal)) break; // no src dir selected
strcat(szCurrLocal, szSelectedFile);
// Request the first file of the list (-> triggers the transfer of the whole list)
_this->m_fFileCommandPending = true;
_this->m_fAbort = false;
_this->m_fAborted = false;
if (!_this->OfferLocalFile(szCurrLocal))
_this->SendFiles(-1, 0); // If the first file could not be opened try next file
}
break;
// Receive selected files
case IDC_DOWNLOAD_B:
{
if (_this->m_fFileCommandPending) break;
TCHAR szSelectedFile[128];
TCHAR szCurrLocal[MAX_PATH];
TCHAR szDstFile[MAX_PATH + 32];
memset(szSelectedFile, 0, 128);
memset(szCurrLocal, 0, MAX_PATH);
memset(szDstFile, 0, MAX_PATH + 32);
int nSelected = -1;
int nCount = 0;
HWND hWndLocalList = GetDlgItem(hWnd, IDC_LOCAL_FILELIST);
HWND hWndRemoteList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
LVITEM Item;
Item.mask = LVIF_TEXT;
Item.iSubItem = 0;
Item.pszText = szSelectedFile;
Item.cchTextMax = 128;
// If no dst dir is selected, nothing to do
GetDlgItemText(hWnd, IDC_CURR_LOCAL, szCurrLocal, sizeof(szCurrLocal));
if (!strlen(szCurrLocal)) break; // no dst dir selected
// Get all the selected files on check if they already exist on local side
// If they already exist, the user is prompted for overwrite
// Store the indexes of selected files in a list
_this->m_FilesList.clear();
nCount = ListView_GetItemCount(hWndRemoteList);
_this->m_nConfirmAnswer = CONFIRM_YES;
for (nSelected = 0; nSelected < nCount; nSelected++)
{
if(ListView_GetItemState(hWndRemoteList, nSelected, LVIS_SELECTED) & LVIS_SELECTED)
{
Item.iItem = nSelected;
ListView_GetItem(hWndRemoteList, &Item);
// if (szSelectedFile[0] != '(') // Only a file can be transfered
char szUpDirMask[16];
sprintf(szUpDirMask, "%s..%s", rfbDirPrefix, rfbDirSuffix);
if (stricmp(szSelectedFile, szUpDirMask))
{
LVFINDINFO Info;
Info.flags = LVFI_STRING;
Info.psz = (LPSTR)szSelectedFile;
int nTheIndex = ListView_FindItem(hWndLocalList, -1, &Info);
bool fDirectory = (szSelectedFile[0] == rfbDirPrefix[0] && szSelectedFile[1] == rfbDirPrefix[1]);
if (nTheIndex > -1)
{
if (_this->m_nConfirmAnswer == CONFIRM_YES || _this->m_nConfirmAnswer == CONFIRM_NO)
{
char szMes[MAX_PATH + 96];
if (fDirectory)
wsprintf(szMes, "%s < %s >\n\n%s", sz_H73, szSelectedFile, sz_H72);
else
wsprintf(szMes, "%s < %s >\n\n%s", sz_H17,szSelectedFile,sz_H43);
_this->DoFTConfirmDialog(sz_H47, _T(szMes));
if (_this->m_nConfirmAnswer == CONFIRM_NO)
continue;
if (_this->m_nConfirmAnswer == CONFIRM_NOALL)
break;
}
}
// Add the file to the list
_this->m_FilesList.push_back(nSelected);
}
}
}
if (_this->m_FilesList.size() == 0) break;
// Display Status
char szRemoteStatus[128];
sprintf(szRemoteStatus, " > %d %s", _this->m_FilesList.size(),sz_H40);
SetDlgItemText(hWnd, IDC_REMOTE_STATUS, szRemoteStatus);
sprintf(szRemoteStatus, "%s %d %s ",sz_H44, _this->m_FilesList.size(),sz_H45);
_this->SetStatus(szRemoteStatus);
_this->m_nFilesTransfered = 0;
_this->m_nFilesToTransfer = _this->m_FilesList.size();
// Disable buttons
_this->DisableButtons(_this->hWnd);
ShowWindow(GetDlgItem(_this->hWnd, IDC_ABORT_B), SW_SHOW);
// Get the fisrt selected file name
_this->m_iFile = _this->m_FilesList.begin();
Item.iItem = *_this->m_iFile;
ListView_GetItem(hWndRemoteList, &Item);
GetDlgItemText(hWnd, IDC_CURR_REMOTE, szDstFile, sizeof(szDstFile));
if (!strlen(szDstFile)) break; // no src dir selected
strcat(szDstFile, szSelectedFile);
// Request the first file of the list (-> triggers the transfer of the whole list)
_this->m_fFileCommandPending = true;
_this->m_fAbort = false;
_this->m_fAborted = false;
_this->RequestRemoteFile(szDstFile);
}
break;
case IDC_LOCAL_ROOTB:
{
char ofDir[MAX_PATH];
int nSelected = SendMessage(GetDlgItem(hWnd, IDC_LOCAL_DRIVECB), CB_GETCURSEL, 0, 0);
if (nSelected == -1) break;
SendMessage(GetDlgItem(hWnd, IDC_LOCAL_DRIVECB), CB_GETLBTEXT, (WPARAM)nSelected, (LPARAM)ofDir);
//ofDir[4] = '\0'; // Hum...
_this->PopulateLocalListBox(hWnd, ofDir);
}
break;
case IDC_REMOTE_ROOTB:
if (!_this->m_fFileCommandPending)
{
_this->m_fFileCommandPending = true;
char ofDir[MAX_PATH];
int nSelected = SendMessage(GetDlgItem(hWnd, IDC_REMOTE_DRIVECB), CB_GETCURSEL, 0, 0);
if (nSelected == -1) break;
SendMessage(GetDlgItem(hWnd, IDC_REMOTE_DRIVECB), CB_GETLBTEXT, (WPARAM)nSelected, (LPARAM)ofDir);
//ofDir[4] = '\0'; // Hum...
_this->RequestRemoteDirectoryContent(hWnd, ofDir);
}
break;
case IDC_LOCAL_UPB:
{
char szUpDirMask[16];
sprintf(szUpDirMask, "%s..%s", rfbDirPrefix, rfbDirSuffix);
_this->PopulateLocalListBox(hWnd, szUpDirMask);
}
break;
case IDC_REMOTE_UPB:
if (!_this->m_fFileCommandPending)
{
_this->m_fFileCommandPending = true;
char szUpDirMask[16];
sprintf(szUpDirMask, "%s..%s", rfbDirPrefix, rfbDirSuffix);
_this->RequestRemoteDirectoryContent(hWnd, szUpDirMask);
}
break;
case IDC_ABORT_B:
_this->m_fAbort = true;
break;
case IDC_DELETE_B:
// Delete Local File
if (_this->m_fFocusLocal)
{
HWND hWndLocalList = GetDlgItem(hWnd, IDC_LOCAL_FILELIST);
int nCount = ListView_GetSelectedCount(hWndLocalList);
char szMes[MAX_PATH + 96];
TCHAR szSelectedFile[128];
memset(szSelectedFile, 0, 128);
int nSelected = -1;
TCHAR szCurrLocal[MAX_PATH];
memset(szCurrLocal, 0, MAX_PATH);
GetDlgItemText(hWnd, IDC_CURR_LOCAL, szCurrLocal, sizeof(szCurrLocal));
if (!strlen(szCurrLocal)) break; // no dst dir selected
LVITEM Item;
Item.mask = LVIF_TEXT;
Item.iSubItem = 0;
Item.pszText = szSelectedFile;
Item.cchTextMax = 128;
nCount = ListView_GetItemCount(hWndLocalList);
_this->m_nConfirmAnswer = CONFIRM_YES;
for (nSelected = 0; nSelected < nCount; nSelected++)
{
if(ListView_GetItemState(hWndLocalList, nSelected, LVIS_SELECTED) & LVIS_SELECTED)
{
Item.iItem = nSelected;
ListView_GetItem(hWndLocalList, &Item);
if (szSelectedFile[0] == rfbDirPrefix[0] && szSelectedFile[1] == rfbDirPrefix[1]) continue;// Only a file can be deleted
GetDlgItemText(hWnd, IDC_CURR_LOCAL, szCurrLocal, sizeof(szCurrLocal));
if (strlen(szCurrLocal) + strlen(szSelectedFile) > MAX_PATH)
{
// TODO: Display Error
continue;
}
if (_this->m_nConfirmAnswer == CONFIRM_YES || _this->m_nConfirmAnswer == CONFIRM_NO)
{
wsprintf(szMes, "%s\n\n< %s > ?\n", sz_H48,szSelectedFile);
_this->DoFTConfirmDialog(sz_H47, _T(szMes));
if (_this->m_nConfirmAnswer == CONFIRM_NO)
continue;
if (_this->m_nConfirmAnswer == CONFIRM_NOALL)
break;
}
strcat(szCurrLocal, szSelectedFile);
if (!DeleteFile(szCurrLocal))
{
wsprintf(szMes, "%s < %s >", sz_H49,szCurrLocal);
_this->SetStatus(szMes);
break;
}
wsprintf(szMes, "%s < %s > %s", sz_H17,szCurrLocal,sz_H50);
_this->SetStatus(szMes);
}
}
// Refresh the Local List view
ListView_DeleteAllItems(GetDlgItem(hWnd, IDC_LOCAL_FILELIST));
_this->PopulateLocalListBox(hWnd, "");
}
else // Delete remote file
{
if (_this->m_fFileCommandPending) break;
HWND hWndRemoteList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
int nCount = ListView_GetSelectedCount(hWndRemoteList);
char szMes[MAX_PATH + 96];
TCHAR szSelectedFile[128];
memset(szSelectedFile, 0, 128);
int nSelected = -1;
TCHAR szCurrRemote[MAX_PATH];
memset(szCurrRemote, 0, MAX_PATH);
GetDlgItemText(hWnd, IDC_CURR_REMOTE, szCurrRemote, sizeof(szCurrRemote));
if (!strlen(szCurrRemote)) break; // no dst dir selected
LVITEM Item;
Item.mask = LVIF_TEXT;
Item.iSubItem = 0;
Item.pszText = szSelectedFile;
Item.cchTextMax = 128;
nCount = ListView_GetItemCount(hWndRemoteList);
_this->m_nConfirmAnswer = CONFIRM_YES;
_this->m_nDeleteCount = 0;
for (nSelected = 0; nSelected < nCount; nSelected++)
{
if(ListView_GetItemState(hWndRemoteList, nSelected, LVIS_SELECTED) & LVIS_SELECTED)
{
Item.iItem = nSelected;
ListView_GetItem(hWndRemoteList, &Item);
if (szSelectedFile[0] == rfbDirPrefix[0] && szSelectedFile[1] == rfbDirPrefix[1]) continue;// Only a file can be deleted
GetDlgItemText(hWnd, IDC_CURR_REMOTE, szCurrRemote, sizeof(szCurrRemote));
if (strlen(szCurrRemote) + strlen(szSelectedFile) > MAX_PATH) continue;
if (_this->m_nConfirmAnswer == CONFIRM_YES || _this->m_nConfirmAnswer == CONFIRM_NO)
{
wsprintf(szMes, "%s\n\n< %s > ?\n", sz_H51, szSelectedFile);
_this->DoFTConfirmDialog(sz_H47, _T(szMes));
if (_this->m_nConfirmAnswer == CONFIRM_NO)
continue;
if (_this->m_nConfirmAnswer == CONFIRM_NOALL)
break;
}
_this->m_fFileCommandPending = true;
strcat(szCurrRemote, szSelectedFile);
_this->m_nDeleteCount++;
_this->DeleteRemoteFile(szCurrRemote);
}
}
}
break;
case IDC_NEWFOLDER_B:
// Create Local Folder
if (_this->m_fFocusLocal)
{
char szMes[MAX_PATH + 96];
TCHAR szCurrLocal[MAX_PATH];
GetDlgItemText(hWnd, IDC_CURR_LOCAL, szCurrLocal, sizeof(szCurrLocal));
if (!strlen(szCurrLocal)) break; // no dst dir selected
memset(_this->m_szFTParam, '\0', sizeof(_this->m_szFTParam));
_this->DoFTParamDialog(sz_H57,sz_H52);
if (strlen(_this->m_szFTParam) == 0 || (strlen(szCurrLocal) + strlen(_this->m_szFTParam)) > 248)
{
// TODO: Error Message
break;
}
strcat(szCurrLocal, _this->m_szFTParam);
if (!CreateDirectory(szCurrLocal, NULL))
{
// TODO: Error Message
wsprintf(szMes, "%s < %s >", sz_H53,szCurrLocal);
_this->SetStatus(szMes);
break;
}
wsprintf(szMes, "%s < %s > %s", sz_H54,szCurrLocal,sz_H55);
_this->SetStatus(szMes);
// Refresh the Local List view
ListView_DeleteAllItems(GetDlgItem(hWnd, IDC_LOCAL_FILELIST));
_this->PopulateLocalListBox(hWnd, "");
}
else // Create Remote Folder
{
if (_this->m_fFileCommandPending) break;
TCHAR szCurrRemote[MAX_PATH];
GetDlgItemText(hWnd, IDC_CURR_REMOTE, szCurrRemote, sizeof(szCurrRemote));
if (!strlen(szCurrRemote)) break; // no dst dir selected
memset(_this->m_szFTParam, '\0', sizeof(_this->m_szFTParam));
_this->DoFTParamDialog(sz_H57,sz_H56);
if (strlen(_this->m_szFTParam) == 0 || (strlen(szCurrRemote) + strlen(szCurrRemote)) > 248)
{
// TODO: Error Message
break;
}
_this->m_fFileCommandPending = true;
strcat(szCurrRemote, _this->m_szFTParam);
_this->CreateRemoteDirectory(szCurrRemote);
}
break;
case IDC_RENAME_B:
{
// Create Local Folder
if (_this->m_fFocusLocal)
{
HWND hWndLocalList = GetDlgItem(hWnd, IDC_LOCAL_FILELIST);
int nCount = ListView_GetSelectedCount(hWndLocalList);
if (nCount == 0 || nCount > 1)
{
MessageBox( NULL,
sz_M1,
sz_M2,
MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST);
break;
}
char szMes[MAX_PATH + 96];
TCHAR szSelectedFile[128];
memset(szSelectedFile, 0, 128);
int nSelected = -1;
TCHAR szCurrLocal[MAX_PATH];
memset(szCurrLocal, 0, MAX_PATH);
TCHAR szNewLocal[MAX_PATH];
memset(szNewLocal, 0, MAX_PATH);
GetDlgItemText(hWnd, IDC_CURR_LOCAL, szCurrLocal, sizeof(szCurrLocal));
if (!strlen(szCurrLocal)) break; // no dst dir selected
LVITEM Item;
Item.mask = LVIF_TEXT;
Item.iSubItem = 0;
Item.pszText = szSelectedFile;
Item.cchTextMax = 128;
nCount = ListView_GetItemCount(hWndLocalList);
for (nSelected = 0; nSelected < nCount; nSelected++)
{
if(ListView_GetItemState(hWndLocalList, nSelected, LVIS_SELECTED) & LVIS_SELECTED)
{
Item.iItem = nSelected;
ListView_GetItem(hWndLocalList, &Item);
_this->IsDirectoryGetIt(szSelectedFile);
strcpy(_this->m_szFTParam, szSelectedFile);
_this->DoFTParamDialog(sz_M3, sz_M4);
if (strlen(_this->m_szFTParam) == 0 || (strlen(szCurrLocal) + strlen(_this->m_szFTParam)) > 248)
{
// TODO: Error Message
break;
}
strcpy(szNewLocal, szCurrLocal);
strcat(szCurrLocal, szSelectedFile); // Old full name
strcat(szNewLocal, _this->m_szFTParam); // New full name
if (!MoveFile(szCurrLocal, szNewLocal))
{
wsprintf(szMes, "%s < %s >", sz_M5, szCurrLocal);
_this->SetStatus(szMes);
break;
}
wsprintf(szMes, "%s < %s > %s < %s >", sz_M6, szCurrLocal, sz_M7, szNewLocal);
_this->SetStatus(szMes);
}
}
// Refresh the Local List view
ListView_DeleteAllItems(GetDlgItem(hWnd, IDC_LOCAL_FILELIST));
_this->PopulateLocalListBox(hWnd, "");
}
else // Rename Remote
{
if (_this->m_fFileCommandPending) break;
HWND hWndRemoteList = GetDlgItem(hWnd, IDC_REMOTE_FILELIST);
int nCount = ListView_GetSelectedCount(hWndRemoteList);
if (nCount == 0 || nCount > 1)
{
MessageBox( NULL,
sz_M1,
sz_M2,
MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST);
break;
}
// char szMes[MAX_PATH + 96];
TCHAR szSelectedFile[128];
memset(szSelectedFile, 0, 128);
int nSelected = -1;
TCHAR szCurrRemote[MAX_PATH];
memset(szCurrRemote, 0, MAX_PATH);
TCHAR szNewRemote[MAX_PATH];
memset(szNewRemote, 0, MAX_PATH);
GetDlgItemText(hWnd, IDC_CURR_REMOTE, szCurrRemote, sizeof(szCurrRemote));
if (!strlen(szCurrRemote)) break; // no dst dir selected
LVITEM Item;
Item.mask = LVIF_TEXT;
Item.iSubItem = 0;
Item.pszText = szSelectedFile;
Item.cchTextMax = 128;
nCount = ListView_GetItemCount(hWndRemoteList);
for (nSelected = 0; nSelected < nCount; nSelected++)
{
if(ListView_GetItemState(hWndRemoteList, nSelected, LVIS_SELECTED) & LVIS_SELECTED)
{
Item.iItem = nSelected;
ListView_GetItem(hWndRemoteList, &Item);
_this->IsDirectoryGetIt(szSelectedFile);
strcpy(_this->m_szFTParam, szSelectedFile);
_this->DoFTParamDialog(sz_M3, sz_M4);
if (strrchr(_this->m_szFTParam, '*') != NULL
||
strlen(_this->m_szFTParam) == 0 ||
(strlen(szCurrRemote) + strlen(_this->m_szFTParam)) > 248)
{
// TODO: Error Message
break;
}
strcpy(szNewRemote, szCurrRemote);
strcat(szCurrRemote, szSelectedFile); // Old full name
strcat(szNewRemote, _this->m_szFTParam); // New full name
_this->m_fFileCommandPending = true;
_this->RenameRemoteFileOrDirectory(szCurrRemote, szNewRemote);
}
}
}
}
break;
case IDC_LOCAL_DRIVECB:
switch (HIWORD(wParam))
{
case CBN_SELCHANGE:
char ofDir[MAX_PATH];
int nSelected = SendMessage(GetDlgItem(hWnd, IDC_LOCAL_DRIVECB), CB_GETCURSEL, 0, 0);
if (nSelected == -1) break;
SendMessage(GetDlgItem(hWnd, IDC_LOCAL_DRIVECB), CB_GETLBTEXT, (WPARAM)nSelected, (LPARAM)ofDir);
// ofDir[4] = '\0'; // Hum...
_this->PopulateLocalListBox(hWnd, ofDir);
// UpdateWindow(hWnd);
break;
}
break;
case IDC_REMOTE_DRIVECB:
switch (HIWORD(wParam))
{
case CBN_SELCHANGE:
char ofDir[MAX_PATH];
int nSelected = SendMessage(GetDlgItem(hWnd, IDC_REMOTE_DRIVECB), CB_GETCURSEL, 0, 0);
if (nSelected == -1) break;
SendMessage(GetDlgItem(hWnd, IDC_REMOTE_DRIVECB), CB_GETLBTEXT, (WPARAM)nSelected, (LPARAM)ofDir);
//ofDir[4] = '\0'; // Hum...
_this->RequestRemoteDirectoryContent(hWnd, ofDir);
// UpdateWindow(hWnd);
break;
}
break;
case IDC_HIDE_B:
_this->ShowFileTransferWindow(false);
return TRUE;
}
break;
case WM_SYSCOMMAND:
switch (LOWORD(wParam))
{
case SC_RESTORE:
_this->ShowFileTransferWindow(true);
return TRUE;
case SC_MINIMIZE:
SendMessage(hWnd,WM_COMMAND,MAKEWPARAM(IDC_HIDE_B,0),0);
return FALSE;
}
break;
case WM_SIZING:
LPRECT lprc;
lprc = (LPRECT)lParam;
switch(wParam)
{
case WMSZ_TOPLEFT:
FTAdjustTop(lprc);
FTAdjustLeft(lprc);
case WMSZ_TOP:
FTAdjustTop(lprc);
case WMSZ_TOPRIGHT:
FTAdjustTop(lprc);
FTAdjustRight(lprc);
case WMSZ_LEFT:
FTAdjustLeft(lprc);
case WMSZ_RIGHT:
FTAdjustRight(lprc);
case WMSZ_BOTTOMLEFT:
FTAdjustBottom(lprc);
FTAdjustLeft(lprc);
case WMSZ_BOTTOM:
FTAdjustBottom(lprc);
case WMSZ_BOTTOMRIGHT:
FTAdjustBottom(lprc);
FTAdjustRight(lprc);
}
return TRUE;
case WM_SIZE:
int cx;
int cy;
int icx;
int icy;
int lf_an;
RECT rc;
if(wParam == SIZE_MINIMIZED)
{
break;
}
cx = LOWORD(lParam); //Client Width
cy = HIWORD(lParam); //Client Height
icy = cy-85-50;
icx = cx/2 - (21+4) * 2 - 94 - 95 - 7 * 4;
lf_an=(cx - 112)/2;
//Left
GetWindowRect(GetDlgItem(hWnd, IDC_LOCAL_DRIVECB), &rc);
MoveWindow(GetDlgItem(hWnd, IDC_LOCAL_DRIVECB), 4, 4, icx, rc.bottom - rc.top, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_LM_STATIC), 4+icx+7, 4, 141, 19, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_LOCAL_ROOTB), 4+icx+7+141+7, 4, 25, 18, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_LOCAL_UPB), 4+icx+7+141+7+25+4, 4, 25, 18, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_CURR_LOCAL), 4, 25, lf_an, 18, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_LOCAL_FILELIST), 4, 46, lf_an, icy, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_LOCAL_STATUS), 4, cy-85+4, lf_an, 15, TRUE);
//Right
GetWindowRect(GetDlgItem(hWnd, IDC_REMOTE_DRIVECB), &rc);
MoveWindow(GetDlgItem(hWnd, IDC_REMOTE_DRIVECB), lf_an+109, 4, icx, rc.bottom - rc.top, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_RM_STATIC), lf_an+109+icx+7, 4, 141, 19, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_REMOTE_ROOTB), lf_an+109+icx+7+141+7, 4, 25, 18, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_REMOTE_UPB), lf_an+109+icx+7+141+7+25+4, 4, 25, 18, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_CURR_REMOTE), lf_an+109, 25, lf_an, 18, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_REMOTE_FILELIST), lf_an+109, 46, lf_an, icy, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_REMOTE_STATUS), lf_an+109, cy-85+4, lf_an, 15, TRUE);
//Bottom
icx = cx-135-69;
MoveWindow(GetDlgItem(hWnd, IDC_HS_STATIC), 8, cy-85+4+18+4, 39, 15, TRUE);
GetWindowRect(GetDlgItem(hWnd, IDC_HISTORY_CB), &rc);
MoveWindow(GetDlgItem(hWnd, IDC_HISTORY_CB), 65, cy-85+4+18, cx-69, rc.bottom-rc.top, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_PR_STATIC), 8, cy-85+4+15+4+4+18+3, 56, 15, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_PROGRESS), 65, cy-85+4+15+4+4+18+2, icx, 15, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_PERCENT), 65+icx+6, cy-85+4+10+4+4+18+4+2, 25, 12, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_GLOBAL_STATUS), 65+icx+6+25+3, cy-85+4+10+4+4+18+4+2, 97, 12, TRUE);
GetWindowRect(GetDlgItem(hWnd, IDC_STATUS), &rc);
MoveWindow(GetDlgItem(hWnd, IDC_STATUS), 0, cy-(rc.bottom-rc.top), cx, rc.bottom-rc.top, TRUE);
//Center
icy = 46+icy/2;
MoveWindow(GetDlgItem(hWnd, IDC_UPLOAD_B), lf_an+10+2, icy-15-20-6-20-5-20, 90, 20, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_DOWNLOAD_B), lf_an+10+2, icy-15-20-6-20, 90, 20, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_ABORT_B), lf_an+10+2, icy-15-20, 90, 20, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_DELETE_B), lf_an+10+2, icy+15, 90, 20, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_NEWFOLDER_B), lf_an+10+2, icy+15+20+6, 90, 20, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_RENAME_B), lf_an+10+2, icy+15+20+6+20+6, 90, 20, TRUE);
MoveWindow(GetDlgItem(hWnd, IDC_HIDE_B), lf_an+10+2, cy-103-20-4-6, 90, 20, TRUE);
MoveWindow(GetDlgItem(hWnd, IDCANCEL), lf_an+10+2, cy-103-4, 90, 20, TRUE);
InvalidateRect(hWnd, NULL, FALSE);
FTAdjustFileNameColumns(hWnd); // sf@2006
return TRUE;
// Messages from ListViews
case WM_NOTIFY:
{
// int nId = (int) wParam;
LPNMHDR lpNmh = (LPNMHDR) lParam;
switch(lpNmh->code)
{
case HDN_ITEMCLICK:
return TRUE;
case NM_SETFOCUS:
if (lpNmh->hwndFrom == GetDlgItem(hWnd, IDC_LOCAL_FILELIST))
{
_this->m_fFocusLocal = true;
char szTxt[64];
HWND hB = GetDlgItem(hWnd, IDC_DELETE_B);
sprintf(szTxt, "<- %s", _this->m_szDeleteButtonLabel);
SetWindowText(hB, szTxt);
hB = GetDlgItem(hWnd, IDC_NEWFOLDER_B);
sprintf(szTxt, "<- %s", _this->m_szNewFolderButtonLabel);
SetWindowText(hB, szTxt);
hB = GetDlgItem(hWnd, IDC_RENAME_B);
sprintf(szTxt, "<- %s", _this->m_szRenameButtonLabel);
SetWindowText(hB, szTxt);
}
if (lpNmh->hwndFrom == GetDlgItem(hWnd, IDC_REMOTE_FILELIST))
{
_this->m_fFocusLocal = false;
char szTxt[64];
HWND hB = GetDlgItem(hWnd, IDC_DELETE_B);
sprintf(szTxt, "%s ->", _this->m_szDeleteButtonLabel);
SetWindowText(hB, szTxt);
hB = GetDlgItem(hWnd, IDC_NEWFOLDER_B);
sprintf(szTxt, "%s ->", _this->m_szNewFolderButtonLabel);
SetWindowText(hB, szTxt);
hB = GetDlgItem(hWnd, IDC_RENAME_B);
sprintf(szTxt, "%s ->", _this->m_szRenameButtonLabel);
SetWindowText(hB, szTxt);
}
return TRUE;
case NM_DBLCLK:
if (lpNmh->hwndFrom == GetDlgItem(hWnd, IDC_LOCAL_FILELIST))
{
_this->PopulateLocalListBox(hWnd, "");
}
if (lpNmh->hwndFrom == GetDlgItem(hWnd, IDC_REMOTE_FILELIST))
{
if (!_this->m_fFileCommandPending)
{
_this->m_fFileCommandPending = true;
_this->RequestRemoteDirectoryContent(hWnd, "");
}
}
return TRUE;
}
}
break;
case WM_DESTROY:
if (_this->m_timer != 0) KillTimer(hWnd, _this->m_timer);
EndDialog(hWnd, FALSE);
return TRUE;
}
/*
// Process FileTransfer asynchronous Send Packet Message
if (uMsg == FileTransferSendPacketMessage)
{
_this->SendFileChunk();
return 0;
}
*/
return 0;
}
//
// Params acquisition Dialog Box
//
int FileTransfer::DoFTParamDialog(LPSTR szTitle, LPSTR szComment)
{
strcpy(m_szFTParamTitle, szTitle);
strcpy(m_szFTParamComment, szComment);
#ifndef _ULTRAVNCAX_
return DialogBoxParam(pApp->m_instance, DIALOG_MAKEINTRESOURCE(IDD_FTPARAM_DLG), NULL, (DLGPROC) FTParamDlgProc, (LONG) this);
#else
return DialogBoxParam(pApp->m_instance, DIALOG_MAKEINTRESOURCE(IDD_FTPARAM_DLG), hWnd, (DLGPROC) FTParamDlgProc, (LONG) this);
#endif
}
BOOL CALLBACK FileTransfer::FTParamDlgProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
FileTransfer *_this = (FileTransfer *) GetWindowLong(hwnd, GWL_USERDATA);
switch (uMsg)
{
case WM_INITDIALOG:
{
SetWindowLong(hwnd, GWL_USERDATA, lParam);
_this = (FileTransfer *) lParam;
CentreWindow(hwnd);
// Set Title
SetWindowText(hwnd, _this->m_szFTParamTitle);
// Set Comment
SetDlgItemText(hwnd, IDC_FTPARAMCOMMENT, _this->m_szFTParamComment);
//S et param initial value
SetDlgItemText(hwnd, IDC_FTPARAM_EDIT, _this->m_szFTParam);
return TRUE;
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
{
UINT res = GetDlgItemText( hwnd, IDC_FTPARAM_EDIT, _this->m_szFTParam, 256);
EndDialog(hwnd, TRUE);
return TRUE;
}
case IDCANCEL:
strcpy(_this->m_szFTParam, "");
EndDialog(hwnd, FALSE);
return TRUE;
}
break;
case WM_DESTROY:
EndDialog(hwnd, FALSE);
return TRUE;
}
return 0;
}
//
// Params acquisition Dialog Box
//
int FileTransfer::DoFTConfirmDialog(LPSTR szTitle, LPSTR szComment)
{
strcpy(m_szFTConfirmTitle, szTitle);
strcpy(m_szFTConfirmComment, szComment);
#ifndef _ULTRAVNCAX_
return DialogBoxParam(pApp->m_instance, DIALOG_MAKEINTRESOURCE(IDD_FTCONFIRM_DLG), NULL, (DLGPROC) FTConfirmDlgProc, (LONG) this);
#else
return DialogBoxParam(pApp->m_instance, DIALOG_MAKEINTRESOURCE(IDD_FTCONFIRM_DLG), hWnd, (DLGPROC) FTConfirmDlgProc, (LONG) this);
#endif
}
BOOL CALLBACK FileTransfer::FTConfirmDlgProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
FileTransfer *_this = (FileTransfer *) GetWindowLong(hwnd, GWL_USERDATA);
switch (uMsg)
{
case WM_INITDIALOG:
{
SetWindowLong(hwnd, GWL_USERDATA, lParam);
_this = (FileTransfer *) lParam;
CentreWindow(hwnd);
// Set Title
SetWindowText(hwnd, _this->m_szFTConfirmTitle);
// Set Comment
SetDlgItemText(hwnd, IDC_FTPCONFIRMCOMMENT, _this->m_szFTConfirmComment);
// Todo: Init buttons labels with corrsponding culture (En, Fr, De...)
return TRUE;
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_YES_B:
_this->m_nConfirmAnswer = CONFIRM_YES;
EndDialog(hwnd, TRUE);
return TRUE;
case IDC_YESALL_B:
_this->m_nConfirmAnswer = CONFIRM_YESALL;
EndDialog(hwnd, TRUE);
return TRUE;
case IDC_NO_B:
_this->m_nConfirmAnswer = CONFIRM_NO;
EndDialog(hwnd, TRUE);
return TRUE;
case IDC_NOALL_B:
_this->m_nConfirmAnswer = CONFIRM_NOALL;
EndDialog(hwnd, TRUE);
return TRUE;
case IDOK:
EndDialog(hwnd, TRUE);
return TRUE;
case IDCANCEL:
EndDialog(hwnd, FALSE);
return TRUE;
}
break;
case WM_DESTROY:
EndDialog(hwnd, FALSE);
return TRUE;
}
return 0;
}
//
//
//
void FileTransfer::DisableButtons(HWND hWnd)
{
ShowWindow(GetDlgItem(hWnd, IDC_UPLOAD_B), SW_HIDE);
ShowWindow(GetDlgItem(hWnd, IDC_DOWNLOAD_B), SW_HIDE);
ShowWindow(GetDlgItem(hWnd, IDC_DELETE_B), SW_HIDE);
ShowWindow(GetDlgItem(hWnd, IDC_NEWFOLDER_B), SW_HIDE);
ShowWindow(GetDlgItem(hWnd, IDC_RENAME_B), SW_HIDE);
ShowWindow(GetDlgItem(hWnd, IDCANCEL), SW_HIDE);
ShowWindow(GetDlgItem(hWnd, IDC_HIDE_B), SW_SHOW);
EnableWindow(GetDlgItem(hWnd, IDC_LOCAL_FILELIST), FALSE);
EnableWindow(GetDlgItem(hWnd, IDC_LOCAL_DRIVECB), FALSE);
EnableWindow(GetDlgItem(hWnd, IDC_LOCAL_ROOTB), FALSE);
EnableWindow(GetDlgItem(hWnd, IDC_LOCAL_UPB), FALSE);
EnableWindow(GetDlgItem(hWnd, IDC_REMOTE_FILELIST), FALSE);
EnableWindow(GetDlgItem(hWnd, IDC_REMOTE_DRIVECB), FALSE);
EnableWindow(GetDlgItem(hWnd, IDC_REMOTE_ROOTB), FALSE);
EnableWindow(GetDlgItem(hWnd, IDC_REMOTE_UPB), FALSE);
}
//
//
//
void FileTransfer::EnableButtons(HWND hWnd)
{
ShowWindow(GetDlgItem(hWnd, IDC_ABORT_B), SW_HIDE);
ShowWindow(GetDlgItem(hWnd, IDC_UPLOAD_B), SW_SHOW);
ShowWindow(GetDlgItem(hWnd, IDC_DOWNLOAD_B), SW_SHOW);
ShowWindow(GetDlgItem(hWnd, IDCANCEL), SW_SHOW);
ShowWindow(GetDlgItem(hWnd, IDC_DELETE_B), SW_SHOW);
ShowWindow(GetDlgItem(hWnd, IDC_NEWFOLDER_B), SW_SHOW);
if (!m_fOldFTProtocole)
ShowWindow(GetDlgItem(hWnd, IDC_RENAME_B), SW_SHOW);
EnableWindow(GetDlgItem(hWnd, IDC_LOCAL_FILELIST), TRUE);
EnableWindow(GetDlgItem(hWnd, IDC_LOCAL_DRIVECB), TRUE);
EnableWindow(GetDlgItem(hWnd, IDC_LOCAL_ROOTB), TRUE);
EnableWindow(GetDlgItem(hWnd, IDC_LOCAL_UPB), TRUE);
EnableWindow(GetDlgItem(hWnd, IDC_REMOTE_FILELIST), TRUE);
EnableWindow(GetDlgItem(hWnd, IDC_REMOTE_DRIVECB), TRUE);
EnableWindow(GetDlgItem(hWnd, IDC_REMOTE_ROOTB), TRUE);
EnableWindow(GetDlgItem(hWnd, IDC_REMOTE_UPB), TRUE);
}
void FileTransfer::InitListViewImagesList(HWND hListView)
{
HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_MASK, 2, 2);
HICON hIcon = LoadIcon(pApp->m_instance, MAKEINTRESOURCE(IDI_DIR));
ImageList_AddIcon(hImageList, hIcon);
DestroyIcon(hIcon);
hIcon = LoadIcon(pApp->m_instance, MAKEINTRESOURCE(IDI_FILE));
ImageList_AddIcon(hImageList, hIcon);
DestroyIcon(hIcon);
hIcon = LoadIcon(pApp->m_instance, MAKEINTRESOURCE(IDI_DRIVE));
ImageList_AddIcon(hImageList, hIcon);
DestroyIcon(hIcon);
ListView_SetImageList(hListView, hImageList, LVSIL_SMALL);
}