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

📄 sftpcontrolsocket.cpp

📁 一个FTP下载的源代码。代码质量非常高
💻 CPP
📖 第 1 页 / 共 5 页
字号:
						found=TRUE;
						break;
					}
				}
				if (found)
				{
					t_directory::t_direntry *direntry=new t_directory::t_direntry[dir.num-1];
					int j=0;
					for (int i=0;i<dir.num;i++)
					{
						if (dir.direntry[i].name==pData->m_FileName)
							continue;
						direntry[j]=dir.direntry[i];
						j++;
					}
					delete [] dir.direntry;
					dir.direntry=direntry;
					dir.num--;
					cache.Store(dir, bCached);
					BOOL updated=FALSE;
					if (m_pDirectoryListing)
						if (m_pDirectoryListing->path==dir.path)
						{
							updated=TRUE;
							SetDirectoryListing(&dir);
						}
					if (!updated)
						if (WorkingDir.path==dir.path)
						{
							updated=TRUE;
							m_pOwner->SetWorkingDir(&dir);
						}
				}
			}
			cache.Unlock();
		}
		ResetOperation(FZ_REPLY_OK);
	}
}

void CSFtpControlSocket::Rename(CString oldName, CString newName, const CServerPath &path, const CServerPath &newPath)
{
	LogMessage(__FILE__, __LINE__, this, FZ_LOG_DEBUG, _T("Rename(\"%s\", \"%s\", \"%s\", \"%s\")  OpMode=%d OpState=%d"), oldName, newName, path.GetPath(),
			   newPath.GetPath(), m_Operation.nOpMode, m_Operation.nOpState);
	class CRenameData : public CFtpControlSocket::t_operation::COpData
	{
	public:
		CRenameData() {}
		virtual ~CRenameData() {}
		CString oldName, newName;
		CServerPath path;
		CServerPath newPath;
	};
	if (oldName != "")
	{
		ASSERT(newName != "");
		ASSERT(!path.IsEmpty());
		ASSERT(m_Operation.nOpMode == CSMODE_NONE);
		ASSERT(m_Operation.nOpState == -1);
		ASSERT(!m_Operation.pData);

		USES_CONVERSION;

		m_Operation.nOpMode = CSMODE_RENAME;
		int nLen;
		char *pData;
		if (newPath.IsEmpty())
		{
			nLen = _tcslen( path.GetPath() + oldName + path.GetPath() + newName) + 2;
			pData = new char[nLen];
			strcpy(pData, T2CA(path.GetPath() + oldName));
			strcpy(pData + _tcslen(path.GetPath() + oldName) + 1, T2CA(path.GetPath() + newName));
		}
		else
		{
			nLen = _tcslen( path.GetPath() + oldName + newPath.GetPath() + newName) + 2;
			pData = new char[nLen];
			strcpy(pData, T2CA(path.GetPath() + oldName));
			strcpy(pData + _tcslen(path.GetPath() + oldName) + 1, T2CA(newPath.GetPath() + newName));
		}
		if (!m_pDataChannel->Send(SFTP_DATAID_STC_RENAME, nLen, pData))
		{
			delete [] pData;
			DoClose();
			return;
		}
		delete [] pData;
		CRenameData *data = new CRenameData;
		data->oldName = oldName;
		data->newName = newName;
		data->path = path;
		data->newPath = newPath;
		m_Operation.pData = data;
	}
	else
	{
		ASSERT(oldName == "");
		ASSERT(path.IsEmpty());
		ASSERT(newPath.IsEmpty());
		ASSERT(m_Operation.nOpMode == CSMODE_RENAME);
		ASSERT(m_Operation.pData);
		if (m_bError)
		{
			ResetOperation(FZ_REPLY_ERROR);
			return;
		}

		//Rename entry in cached directory
		CRenameData *pData = reinterpret_cast<CRenameData *>(m_Operation.pData);
			
		CDirectoryCache cache;

		cache.Lock();
				
		//Rename all references to the directory in the cache
		if (pData->newPath.IsEmpty())
			cache.Rename(pData->path, pData->oldName, pData->newName, m_CurrentServer);
		
		BOOL bCached = TRUE;
		t_directory dir;
		BOOL res = cache.Lookup(pData->path, m_CurrentServer, dir);
		if (!res)
			bCached = FALSE;
		if (!res && m_pDirectoryListing)
		{
			if (m_pDirectoryListing->path == pData->path)
			{
				dir = *m_pDirectoryListing;
				res = TRUE;
			}
		}
		t_directory WorkingDir;
		BOOL bFound = m_pOwner->GetWorkingDir(&WorkingDir);
		if (!res && bFound)
			if (WorkingDir.path == pData->path)
			{
				dir = WorkingDir;
				res = TRUE;
			}
		if (res)
		{
			for (int i=0; i<dir.num; i++)
				if (dir.direntry[i].name == pData->oldName)
				{
					if (pData->newPath.IsEmpty())
					{
						dir.direntry[i].name = pData->newName;
						dir.direntry[i].lName = pData->newName;
						dir.direntry[i].lName.MakeLower();

						CDirectoryCache cache;
						cache.Store(dir, bCached);
						BOOL updated = FALSE;
						if (m_pDirectoryListing && m_pDirectoryListing->path == dir.path)
						{
							updated = TRUE;
							SetDirectoryListing(&dir, WorkingDir.path == dir.path);
						}
						if (!updated)
							if (WorkingDir.path == dir.path)
							{
								updated = TRUE;
								m_pOwner->SetWorkingDir(&dir);
							}
					}
					else
					{
						t_directory::t_direntry oldentry = dir.direntry[i];

						for (int j = i+1; j < dir.num; j++)
						{
							dir.direntry[j-1] = dir.direntry[j];
						}
						dir.num--;

						CDirectoryCache cache;
						cache.Store(dir, bCached);
							
						// If directory, delete old directory from cache
						t_directory olddir;
						res = cache.Lookup(pData->path, pData->oldName, m_CurrentServer, olddir);
						if (res)
						{
							cache.Purge(olddir.path, m_CurrentServer);
							t_directory newdir;
							if (cache.Lookup(dir.path, m_CurrentServer, newdir))
								dir = newdir;
						}

						BOOL updated = FALSE;
						if (m_pDirectoryListing && m_pDirectoryListing->path == dir.path)
						{
							updated = TRUE;
							SetDirectoryListing(&dir, WorkingDir.path == dir.path);
						}
						if (!updated)
							if (WorkingDir.path == dir.path)
							{
								updated = TRUE;
								m_pOwner->SetWorkingDir(&dir);
							}
																	
						BOOL bCached = TRUE;
						BOOL res = cache.Lookup(pData->newPath, m_CurrentServer, dir);
						if (!res)
							bCached = FALSE;
						if (!res && m_pDirectoryListing)
						{
							if (m_pDirectoryListing->path == pData->newPath)
							{
								dir = *m_pDirectoryListing;
								res = TRUE;
							}
						}
						t_directory WorkingDir;
						BOOL bFound = m_pOwner->GetWorkingDir(&WorkingDir);
						if (!res && bFound)
							if (WorkingDir.path == pData->newPath)
							{
								dir = WorkingDir;
								res = TRUE;
							}
						if (res)
						{
							t_directory::t_direntry *direntry = new t_directory::t_direntry[dir.num + 1];
							for (int i = 0; i < dir.num; i++)
								direntry[i] = dir.direntry[i];
							direntry[dir.num] = oldentry;
							direntry[dir.num].name = pData->newName;
							direntry[dir.num].lName = pData->newName;
							direntry[dir.num].lName.MakeLower();
							dir.num++;
							delete [] dir.direntry;
							dir.direntry = direntry;
									
							CDirectoryCache cache;
							cache.Store(dir, bCached);
							BOOL updated = FALSE;
							if (m_pDirectoryListing && m_pDirectoryListing->path == dir.path)
							{
								updated = TRUE;
								SetDirectoryListing(&dir, WorkingDir.path == dir.path);
							}
							if (!updated)
								if (WorkingDir.path == dir.path)
								{
									updated = TRUE;
									m_pOwner->SetWorkingDir(&dir);
								}
						}
					}
					break;
				}
		}
		cache.Unlock();
		ResetOperation(FZ_REPLY_OK);
	}
}

void CSFtpControlSocket::MakeDir(const CServerPath &path)
{
	//Directory creation works like this:
	//Find existing parent and create subdirs one by one
	LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("MakeDir(\"%s\")"), path.GetPath());
	
	class CMakeDirData : public CSFtpControlSocket::t_operation::COpData
	{
	public:
		CMakeDirData() {}
		virtual ~CMakeDirData() {}
		CServerPath path;
		CServerPath Current;
		std::list<CString> Segments;
	};

	if (m_Operation.nOpState==MKD_INIT)
	{
		ASSERT(!path.IsEmpty());
		ASSERT(m_Operation.nOpMode==CSMODE_NONE);
		ASSERT(!m_Operation.pData);
		m_Operation.nOpMode=CSMODE_MKDIR;
		if (!m_pDataChannel->Send(SFTP_DATAID_STC_CD, path.GetParent().GetPath()))
		{
			DoClose();
			return;
		}
		CMakeDirData *data=new CMakeDirData;
		data->path=path;
		data->Current=path.GetParent();
		data->Segments.push_front(path.GetLastSegment());
		m_Operation.pData=data;
		m_Operation.nOpState=MKD_FINDPARENT;
	}
	else if (m_Operation.nOpState==MKD_FINDPARENT)
	{
		ASSERT(m_Operation.nOpMode==CSMODE_MKDIR);
		ASSERT(path.IsEmpty());
		ASSERT(m_Operation.pData);
		CMakeDirData *pData=(CMakeDirData *)m_Operation.pData;
		if (!m_bError)
		{
			m_pOwner->SetCurrentPath(pData->Current);

			if (!m_pDirectoryListing)
			{
				CDirectoryCache cache;
				t_directory dir;
				BOOL res=cache.Lookup(pData->Current, m_CurrentServer, dir, TRUE);
				if (res)
					SetDirectoryListing(&dir);
			}
			
			m_Operation.nOpState=MKD_MAKESUBDIRS;
			pData->Current.AddSubdir(pData->Segments.front());
			CString Segment=pData->Segments.front();
			pData->Segments.pop_front();
			if (!m_pDataChannel->Send(SFTP_DATAID_STC_MKD, Segment))
			{
				DoClose();
				return;
			}
			m_Operation.nOpState=MKD_CHANGETOSUBDIR;
		}
		else
		{
			if (!pData->Current.HasParent())
				ResetOperation(FZ_REPLY_ERROR);
			else
			{
				pData->Segments.push_front(pData->Current.GetLastSegment());
				pData->Current=pData->Current.GetParent();
				if (!m_pDataChannel->Send(SFTP_DATAID_STC_CD, pData->Current.GetPath()))
				{
					DoClose();
					return;	
				}
			}
		}
	}
	else if (m_Operation.nOpState==MKD_MAKESUBDIRS)
	{
		if (!m_bError)
		{ //Create dir entry in parent dir
			CMakeDirData *pData=(CMakeDirData *)m_Operation.pData;

			ASSERT(!pData->Segments.empty());

			m_pOwner->SetCurrentPath(pData->Current);
			
			pData->Current.AddSubdir(pData->Segments.front());
			CString Segment=pData->Segments.front();
			pData->Segments.pop_front();
			if (!m_pDataChannel->Send(SFTP_DATAID_STC_MKD,Segment))
			{
				DoClose();
				return;
			}
			m_Operation.nOpState=MKD_CHANGETOSUBDIR;
		}
		else
			ResetOperation(FZ_REPLY_ERROR);
	}
	else if (m_Operation.nOpState==MKD_CHANGETOSUBDIR)
	{
		CMakeDirData *pData=(CMakeDirData *)m_Operation.pData;
		if (!m_bError)
		{ //Create dir entry in parent dir
			CServerPath path2=pData->Current;
			if (path2.HasParent())
			{
				CString name=path2.GetLastSegment();
				path2=path2.GetParent();
				CDirectoryCache cache;
				cache.Lock();
				BOOL bCached=TRUE;
				t_directory dir;
				BOOL res=cache.Lookup(path2,m_CurrentServer,dir);
				if (!res)
					bCached=FALSE;
				if (!res && m_pDirectoryListing)
				{
					if (m_pDirectoryListing->path==path2)
					{
						dir=*m_pDirectoryListing;
						res=TRUE;
					}
				}
				t_directory WorkingDir;
				BOOL bFound=m_pOwner->GetWorkingDir(&WorkingDir);
				if (!res && bFound)
					if (WorkingDir.path==path2)
					{
						dir=WorkingDir;
						res=TRUE;
					}
				if (!res)
				{
					dir.path==path2;
					dir.server=m_CurrentServer;
				}

				int i;
				for (i=0; i<dir.num;i++)
					if (dir.direntry[i].name==name)
					{
						LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("Warning: Dir already exists in cache!"));
						break;
					}
				if (i==dir.num)
				{
					t_directory::t_direntry *entries = new t_directory::t_direntry[dir.num+1];
					for (i=0;i<dir.num;i++)
						entries[i]=dir.direntry[i];
					entries[i].name=name;
					entries[i].lName=name;
					entries[i].lName.MakeLower();
					entries[i].dir=TRUE;
					entries[i].date.hasdate=FALSE;
					entries[i].size=-1;
					delete [] dir.direntry;
					dir.direntry=entries;
					dir.num++;
					cache.Store(dir, bCached);
					BOOL updated=FALSE;
					if (m_pDirectoryListing && m_pDirectoryListing->path==dir.path)
					{
						updated=TRUE;
						SetDirectoryListing(&dir);
					}
					if (!updated)
						if (WorkingDir.path==dir.path)
						{
							updated=TRUE;
							m_pOwner->SetWorkingDir(&dir);
						}
				}
				cache.Unlock();
			}
		}
		
		//Continue operation even if MKD failed, maybe another thread did create this directory for us
		if (pData->Segments.empty())
			ResetOperation(FZ_REPLY_OK);
		else
		{
			if (!m_pDataChannel->Send(SFTP_DATAID_STC_CD, pData->Current.GetPath()))
			{
				DoClose();
				return;
			}
			m_Operation.nOpState=MKD_MAKESUBDIRS;
		}				
	}
	else 
		ASSERT(FALSE);
}

void CSFtpControlSocket::RemoveDir(CString dirname, const CServerPath &path)
{
	LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("RemoveDir(\"%s\", \"%s\")"),dirname, path.GetPath());
	
	class CRemoveDirData : public CSFtpControlSocket::t_operation::COpData
	{
public:
		CRemoveDirData() {}
		virtual ~CRemoveDirData() {}
		CString m_DirName;
		CServerPath path;
	};
	if (dirname!="")
	{
		ASSERT(!path.IsEmpty());
		ASSERT(m_Operation.nOpMode==CSMODE_NONE);
		ASSERT(m_Operation.nOpState==-1);
		ASSERT(!m_Operation.pData);

⌨️ 快捷键说明

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