filezillaapi.cpp

来自「一个支持FTP,SFTP的客户端程序」· C++ 代码 · 共 831 行 · 第 1/2 页

CPP
831
字号
// FileZilla - a Windows ftp client

// Copyright (C) 2002-2004 - Tim Kosse <tim.kosse@gmx.de>

// 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.

// FileZillaApi.cpp: Implementierung der Klasse CFileZillaApi.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "FileZillaApi.h"
#include "mainthread.h"
#include "directorycache.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Konstruktion/Destruktion
//////////////////////////////////////////////////////////////////////

CFileZillaApi::CFileZillaApi()
{
	m_hOwnerWnd=0;
	//Create Message IDs
	m_nReplyMessageID=RegisterWindowMessage( _T("FileZillaApiReplyMessage{8EF2E328-685E-4815-A9B9-823512F8381D}") );
	m_nInternalMessageID=0;
	m_pMainThread=0;
	m_bInitialized=FALSE;
}

CFileZillaApi::~CFileZillaApi()
{
	Destroy();
}

int CFileZillaApi::Init(HWND hOwnerWnd, int nReplyMessageID /*=0*/)
{
	//Check parameters
	//-> No check needed, if hOwnerWnd is NULL, use blocking mode and don't send status messages

	//Check if call allowed
	if (m_bInitialized)
		return FZ_REPLY_ALREADYINIZIALIZED;

	//Initialize variables
	if (nReplyMessageID)
		m_nReplyMessageID=nReplyMessageID;
	m_hOwnerWnd=hOwnerWnd;
	m_nInternalMessageID=RegisterWindowMessage( _T("FileZillaInternalApiMessage{F958620E-040C-4b33-A091-7E04E10AA660}") );
	if (!m_nInternalMessageID)
		return FZ_REPLY_NOTINITIALIZED;
	
	//Create thread object
	m_pMainThread = CMainThread::Create(THREAD_PRIORITY_BELOW_NORMAL, CREATE_SUSPENDED);

	//Initialize Thread variables
	m_pMainThread->m_nInternalMessageID=m_nInternalMessageID;
	m_pMainThread->m_nReplyMessageID=m_nReplyMessageID;
	m_pMainThread->m_hOwnerWnd=m_hOwnerWnd;

	m_pMainThread->InitLog(m_hOwnerWnd, m_nReplyMessageID);
	
	//Resume Thread
	m_pMainThread->ResumeThread();

	//Initialization OK
	m_bInitialized=TRUE;
	return FZ_REPLY_OK;
}

unsigned int CFileZillaApi::GetMessageID()
{
	return m_nReplyMessageID;
}

int CFileZillaApi::IsConnected()
{
	if (!m_bInitialized)
		return FZ_REPLY_NOTINITIALIZED;
	return m_pMainThread->IsConnected()?FZ_REPLY_OK:FZ_REPLY_NOTCONNECTED;
}

int CFileZillaApi::IsBusy()
{
	if (!m_bInitialized)
		return FZ_REPLY_NOTINITIALIZED;
	return m_pMainThread->IsBusy()?FZ_REPLY_BUSY:FZ_REPLY_IDLE;
}

int CFileZillaApi::Connect(const t_server &server)
{
	//Check parameters
	if (server.host=="" || server.port<1 || server.port>65535)
		return FZ_REPLY_INVALIDPARAM;
	
	BOOL bUseGSS = FALSE;
	if (COptions::GetOptionVal(OPTION_USEGSS))
	{
		USES_CONVERSION;
		
		CString GssServers = COptions::GetOption(OPTION_GSSSERVERS);
		hostent *fullname = gethostbyname(T2CA(server.host));
		CString host;
		if (fullname)
			host = fullname->h_name;
		else
			host = server.host;
		host.MakeLower();
		int i;
		while ((i=GssServers.Find( _T(";") ))!=-1)
		{
			if (("."+GssServers.Left(i))==host.Right(GssServers.Left(i).GetLength()+1) || GssServers.Left(i)==host)
			{
				bUseGSS = TRUE;
				break;
			}
			GssServers = GssServers.Mid(i+1);
		}
	}
	if (!bUseGSS && server.user == "")
		return FZ_REPLY_INVALIDPARAM;
		
	if (!(server.nServerType&FZ_SERVERTYPE_HIGHMASK))
		return FZ_REPLY_INVALIDPARAM;

	//Check if call allowed
	if (!m_bInitialized)
		return FZ_REPLY_NOTINITIALIZED;
	if (m_pMainThread->IsBusy())
		return FZ_REPLY_BUSY;

	t_command command;
	command.id=FZ_COMMAND_CONNECT;
	command.server=server;
	m_pMainThread->Command(command);
	if (m_hOwnerWnd)
		return FZ_REPLY_WOULDBLOCK;
	else
		return m_pMainThread->LastOperationSuccessful()?FZ_REPLY_OK:FZ_REPLY_ERROR;
}

int CFileZillaApi::List(int nListMode /*=FZ_LIST_USECACHE*/)
{
	//Check if call allowed
	if (!m_bInitialized)
		return FZ_REPLY_NOTINITIALIZED;
	if (IsConnected()==FZ_REPLY_NOTCONNECTED)
		return FZ_REPLY_NOTCONNECTED;
	if (nListMode&FZ_LIST_REALCHANGE)
		return FZ_REPLY_INVALIDPARAM;
	if (nListMode&FZ_LIST_FORCECACHE)
		nListMode|=FZ_LIST_USECACHE;
	//Check if current dir is cached
	CServerPath path;
	if (nListMode&FZ_LIST_USECACHE)
	{
		if (!m_pMainThread->GetWorkingDirPath(path) || path.IsEmpty())
			m_pMainThread->GetCurrentPath(path);
		if (!path.IsEmpty())
		{
			t_server server;
			BOOL res=m_pMainThread->GetCurrentServer(server);
			if (res)
			{
				t_directory *directory=new t_directory;
				CDirectoryCache cache;
				res=cache.Lookup(path,server,*directory);
				if (res)
				{
					BOOL bExact=TRUE;
					if (nListMode & FZ_LIST_EXACT)
						for (int i=0;i<directory->num;i++)
							if (directory->direntry[i].bUnsure || (directory->direntry[i].size==-1 && !directory->direntry[i].dir))
							{
								bExact=FALSE;
								break;
							}
					if (bExact)
					{
						m_pMainThread->SetWorkingDir(directory);
						delete directory;
						return FZ_REPLY_OK;
					}
				}
				delete directory;
			}
		}
	}

	if (m_pMainThread->IsBusy())
		return FZ_REPLY_BUSY;
	if (nListMode&FZ_LIST_FORCECACHE)
		return FZ_REPLY_ERROR;

	t_command command;
	command.id=FZ_COMMAND_LIST;
	command.path = path;
	command.param4=nListMode;
	m_pMainThread->Command(command);
	if (m_hOwnerWnd)
		return FZ_REPLY_WOULDBLOCK;
	else
		return m_pMainThread->LastOperationSuccessful()?FZ_REPLY_OK:FZ_REPLY_ERROR;
}

int CFileZillaApi::Cancel()
{
	//Check if call allowed
	if (!m_bInitialized)
		return FZ_REPLY_NOTINITIALIZED;
	if (IsBusy()!=FZ_REPLY_BUSY)
		return FZ_REPLY_NOTBUSY;
	m_pMainThread->PostThreadMessage(m_nInternalMessageID, FZAPI_THREADMSG_CANCEL, 0);
	return FZ_REPLY_WOULDBLOCK;
}

void CFileZillaApi::Destroy()
{
	if (!m_bInitialized)
		return;
	ASSERT(m_pMainThread);
	HANDLE tmp=m_pMainThread->m_hThread;
	m_pMainThread->Quit();
	//Wait for the main thread to quit
	WaitForSingleObject(tmp, 10000);
	PostMessage(m_hOwnerWnd, m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_QUITCOMPLETE, 0), 0);
		
	m_pMainThread=0;
	m_bInitialized=FALSE;
}

int CFileZillaApi::Disconnect()
{
	//Check if call allowed
	if (!m_bInitialized)
		return FZ_REPLY_NOTINITIALIZED;
	if (IsConnected()==FZ_REPLY_NOTCONNECTED)
		return FZ_REPLY_NOTCONNECTED;
	if (IsBusy()==FZ_REPLY_BUSY)
		return FZ_REPLY_BUSY;
	
	m_pMainThread->PostThreadMessage(m_nInternalMessageID,FZAPI_THREADMSG_DISCONNECT,0);
	return FZ_REPLY_WOULDBLOCK;
}

int CFileZillaApi::Command(t_command *pCommand)
{
	//Check if call allowed
	if (!m_bInitialized)
		return FZ_REPLY_NOTINITIALIZED;

	//Dispatch command to command specific functions
	switch(pCommand->id)
	{
	case FZ_COMMAND_LIST:
		if (pCommand->param1!="")
			return List(pCommand->path,pCommand->param1,pCommand->param4);
		else if (!pCommand->path.IsEmpty())
			return List(pCommand->path,pCommand->param4);
		else
			return List(pCommand->param4);
		break;
	case FZ_COMMAND_CONNECT:
		return Connect(pCommand->server);
		break;
	case FZ_COMMAND_DISCONNECT:
		return Disconnect();
		break;
	case FZ_COMMAND_FILETRANSFER:
		return FileTransfer(pCommand->transferfile);
		break;
	case FZ_COMMAND_DELETE:
		return Delete(pCommand->param1, pCommand->path);
		break;
	case FZ_COMMAND_REMOVEDIR:
		return RemoveDir(pCommand->param1, pCommand->path);
		break;
	case FZ_COMMAND_MAKEDIR:
		return MakeDir(pCommand->path);
		break;
	case FZ_COMMAND_RENAME:
		return Rename(pCommand->param1, pCommand->param2, pCommand->path, pCommand->newPath);
		break;
	case FZ_COMMAND_CUSTOMCOMMAND:
		return CustomCommand(pCommand->param1);
		break;
	case FZ_COMMAND_CHMOD:
		return Chmod(pCommand->param4, pCommand->param1, pCommand->path);
		break;
	}
	return FZ_REPLY_INVALIDPARAM;
}

int CFileZillaApi::List(const CServerPath& path, int nListMode /*=FZ_LIST_USECACHE*/)
{
	//Check if call allowed
	if (!m_bInitialized)
		return FZ_REPLY_NOTINITIALIZED;
	if (IsConnected()==FZ_REPLY_NOTCONNECTED)
		return FZ_REPLY_NOTCONNECTED;
	if ( (nListMode&(FZ_LIST_FORCECACHE|FZ_LIST_REALCHANGE))==(FZ_LIST_FORCECACHE|FZ_LIST_REALCHANGE) )
		return FZ_REPLY_INVALIDPARAM;
	if (nListMode&FZ_LIST_FORCECACHE)
		nListMode|=FZ_LIST_USECACHE;
	if (path.IsEmpty())
		return FZ_REPLY_INVALIDPARAM;
	
	//Check if current dir is cached
	if (nListMode&FZ_LIST_USECACHE && !(nListMode&FZ_LIST_REALCHANGE))
	{
		t_server server;
		BOOL res=m_pMainThread->GetCurrentServer(server);
		if (res)
		{
			t_directory *directory=new t_directory;
			CDirectoryCache cache;
			res=cache.Lookup(path,server,*directory);
			if (res)
			{
				BOOL bExact=TRUE;
				if (nListMode & FZ_LIST_EXACT)
					for (int i=0;i<directory->num;i++)
						if (directory->direntry[i].bUnsure || (directory->direntry[i].size==-1 && !directory->direntry[i].dir))
						{
							bExact=FALSE;
							break;
						}
				if (bExact)
				{
					m_pMainThread->SetWorkingDir(directory);
					delete directory;
					return FZ_REPLY_OK;
				}
			}
			delete directory;
		}
	}

	if (m_pMainThread->IsBusy())
		return FZ_REPLY_BUSY;
	if (nListMode&FZ_LIST_FORCECACHE)
		return FZ_REPLY_ERROR;

	t_command command;
	command.id=FZ_COMMAND_LIST;
	command.path=path;
	command.param4=nListMode;
	m_pMainThread->Command(command);
	if (m_hOwnerWnd)
		return FZ_REPLY_WOULDBLOCK;
	else
		return m_pMainThread->LastOperationSuccessful()?FZ_REPLY_OK:FZ_REPLY_ERROR;
}

int CFileZillaApi::List(const CServerPath& parent, CString dirname, int nListMode /*=FZ_LIST_USECACHE*/)
{
	//Check if call allowed
	if (!m_bInitialized)
		return FZ_REPLY_NOTINITIALIZED;
	if (IsConnected()==FZ_REPLY_NOTCONNECTED)
		return FZ_REPLY_NOTCONNECTED;
	if ( (nListMode&(FZ_LIST_FORCECACHE|FZ_LIST_REALCHANGE))==(FZ_LIST_FORCECACHE|FZ_LIST_REALCHANGE) )
		return FZ_REPLY_INVALIDPARAM;
	if (nListMode&FZ_LIST_FORCECACHE)
		nListMode|=FZ_LIST_USECACHE;
	if (dirname=="" || parent.IsEmpty())
		return FZ_REPLY_INVALIDPARAM;

	//Check if current dir is cached
	if (nListMode&FZ_LIST_USECACHE && !(nListMode&FZ_LIST_REALCHANGE))
	{
		t_server server;
		BOOL res=m_pMainThread->GetCurrentServer(server);
		if (res)
		{
			t_directory *directory=new t_directory;
			CDirectoryCache cache;
			res=cache.Lookup(parent,dirname,server,*directory);
			if (res)
			{
				BOOL bExact=TRUE;
				if (nListMode & FZ_LIST_EXACT)
					for (int i=0;i<directory->num;i++)
						if (directory->direntry[i].bUnsure || (directory->direntry[i].size==-1 && !directory->direntry[i].dir))
						{
							bExact=FALSE;
							break;
						}
				if (bExact)
				{
					m_pMainThread->SetWorkingDir(directory);
					delete directory;
					return FZ_REPLY_OK;
				}
			}
			delete directory;
		}
	}

⌨️ 快捷键说明

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