⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filetransfer.cpp

📁 teamviewer source code vc++
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/////////////////////////////////////////////////////////////////////////////
//  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://www.teamviewer.com/
//
////////////////////////////////////////////////////////////////////////////


// 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 "..\winvnc\winvnc\vncservice.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, VNCLOG(_T("FileTransfer")));
	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_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; 
	m_fCreateDirPending = false;
	m_fInGetFilesRecursive = false;
	m_fGetFilesFirstResponse = false;
	hWnd = NULL;

	ZeroMemory(&m_szLastRemoteDirVisit,sizeof(m_szLastRemoteDirVisit));
}


//
//
//
FileTransfer::~FileTransfer()
{
//	vnclog.Print(0, VNCLOG(_T("nFileTransfer")));
	KillDialog();
	m_fFileCommandPending = false;
	m_FilesList.clear();
}

void FileTransfer::KillDialog()
{
	if(!hWnd) 
		return;
	if (m_timer != 0) 
		KillTimer(hWnd, m_timer);
	KillFTTimer();	
	EndDialog(hWnd, FALSE);				// return value==2: ClientConnection terminated
	hWnd = NULL;
}

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
		if (timeGetTime() - ft->m_dwLastChunkTime > 200)
			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)
{
	if(hParent)
		ShowWindow(hParent, fVisible ? SW_RESTORE : SW_MINIMIZE);
	ShowWindow(hWnd, fVisible ? SW_RESTORE : SW_MINIMIZE);
	SetForegroundWindow(hWnd);
}


//
// Simply the classic Windows message processing
//
bool PseudoYield(HWND hWnd)
{
//	vnclog.Print(0, VNCLOG(_T("PseudoYield")));
	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, VNCLOG(_T("ProcessFileTransferMsg")));
	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_fInGetFilesRecursive)
				GetFilesRecursiveResponse(Swap32IfLE(ft.length));
			else if (!m_fDirectoryReceptionRunning)
				PopulateRemoteListBox(hWnd, Swap32IfLE(ft.length));
			else
				ReceiveDirectoryItem(hWnd, Swap32IfLE(ft.length));
			break;
		default: // This is bad. Add rfbADirectoryEnd instead...
			if (m_fInGetFilesRecursive)
			{
				m_fInGetFilesRecursive = false;
				m_GetFiles.pop_front();
				GetFilesRecursive();
			}
			else
			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 rfbADirDelete:
		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, VNCLOG(_T("RequestPermission")));

    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, VNCLOG(_T("TestPermission")));
	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);
		
		//saves the last directory the user was browsing
		//its used later for redisplaying the remote directory content
		//search for IDC_ABORT_B:
		GetDlgItemText(hWnd, IDC_CURR_REMOTE, m_szLastRemoteDirVisit, sizeof(m_szLastRemoteDirVisit));
		ShowWindow(GetDlgItem(hWnd, IDC_ABORT_B), SW_SHOW);

		SetDlgItemText(hWnd, IDC_CURR_REMOTE, sz_H1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -