예제 #1
0
int CFileZillaEnginePrivate::List(const CListCommand &command)
{
	if (!IsConnected())
		return FZ_REPLY_NOTCONNECTED;

	if (command.GetPath().IsEmpty() && command.GetSubDir() != _T(""))
		return FZ_REPLY_SYNTAXERROR;

	if (command.GetFlags() & LIST_FLAG_LINK && command.GetSubDir() == _T(""))
		return FZ_REPLY_SYNTAXERROR;

	bool refresh = (command.GetFlags() & LIST_FLAG_REFRESH) != 0;
	bool avoid = (command.GetFlags() & LIST_FLAG_AVOID) != 0;
	if (refresh && avoid)
		return FZ_REPLY_SYNTAXERROR;

	if (!refresh && !command.GetPath().IsEmpty())
	{
		const CServer* pServer = m_pControlSocket->GetCurrentServer();
		if (pServer)
		{
			CServerPath path(CPathCache::Lookup(*pServer, command.GetPath(), command.GetSubDir()));
			if (path.IsEmpty() && command.GetSubDir().IsEmpty())
				path = command.GetPath();
			if (!path.IsEmpty())
			{
				CDirectoryListing *pListing = new CDirectoryListing;
				CDirectoryCache cache;
				bool is_outdated = false;
				bool found = cache.Lookup(*pListing, *pServer, path, true, is_outdated);
				if (found && !is_outdated)
				{
					if (pListing->m_hasUnsureEntries)
						refresh = true;
					else
					{
						if (!avoid)
						{
							m_lastListDir = pListing->path;
							m_lastListTime = wxDateTime::Now();
							CDirectoryListingNotification *pNotification = new CDirectoryListingNotification(pListing->path);
							AddNotification(pNotification);
						}
						delete pListing;
						return FZ_REPLY_OK;
					}
				}
				if (is_outdated)
					refresh = true;
				delete pListing;
			}
		}
	}
	if (IsBusy())
		return FZ_REPLY_BUSY;

	m_pCurrentCommand = command.Clone();
	return m_pControlSocket->List(command.GetPath(), command.GetSubDir(), command.GetFlags());
}
예제 #2
0
void CFileZillaEnginePrivate::SendDirectoryListingNotification(const CServerPath& path, bool onList, bool modified, bool failed)
{
	wxASSERT(m_pControlSocket);
	
	const CServer* const pOwnServer = m_pControlSocket->GetCurrentServer();
	wxASSERT(pOwnServer);

	m_lastListDir = path;

	if (failed)
	{
		CDirectoryListingNotification *pNotification = new CDirectoryListingNotification(path, false, true);
		AddNotification(pNotification);
		m_lastListTime = CTimeEx::Now();

		// On failed messages, we don't notify other engines
		return;
	}

	const CDirectoryCache cache;
	
	CTimeEx changeTime;
	if (!cache.GetChangeTime(changeTime, *pOwnServer, path))
		return;
	
	CDirectoryListingNotification *pNotification = new CDirectoryListingNotification(path, !onList);
	AddNotification(pNotification);
	m_lastListTime = changeTime;

	if (!modified)
		return;

	// Iterate over the other engine, send notification if last listing
	// directory is the same
	for (std::list<CFileZillaEnginePrivate*>::iterator iter = m_engineList.begin(); iter != m_engineList.end(); iter++)
	{
		CFileZillaEnginePrivate* const pEngine = *iter;
		if (!pEngine->m_pControlSocket || pEngine->m_pControlSocket == m_pControlSocket)
			continue;

		const CServer* const pServer = pEngine->m_pControlSocket->GetCurrentServer();
		if (!pServer || *pServer != *pOwnServer)
			continue;

		if (pEngine->m_lastListDir != path)
			continue;

		if (pEngine->m_lastListTime.GetTime().IsValid() && changeTime <= pEngine->m_lastListTime)
			continue;
		
		pEngine->m_lastListTime = changeTime;
		CDirectoryListingNotification *pNotification = new CDirectoryListingNotification(path, true);
		pEngine->AddNotification(pNotification);
	}
}
예제 #3
0
int CFileZillaEngine::CacheLookup(const CServerPath& path, CDirectoryListing& listing)
{
	if (!IsConnected())
		return FZ_REPLY_ERROR;

	wxASSERT(m_pControlSocket->GetCurrentServer());

	CDirectoryCache cache;
	bool is_outdated = false;
	if (!cache.Lookup(listing, *m_pControlSocket->GetCurrentServer(), path, true, is_outdated))
		return FZ_REPLY_ERROR;

	return FZ_REPLY_OK;
}
예제 #4
0
void CDirectoryCache::SetDirectory(const CStdString& strPath1, const CFileItemList &items)
{
  CSingleLock lock (m_cs);

  CStdString strPath = _P(strPath1);
  if (CUtil::HasSlashAtEnd(strPath))
    strPath.Delete(strPath.size() - 1);

  g_directoryCache.ClearDirectory(strPath);
  CDir* dir = new CDir;
  dir->m_Items = new CFileItemList;
  dir->m_strPath = strPath;
  dir->m_Items->SetFastLookup(true);
  dir->m_Items->Append(items);
  g_directoryCache.m_vecCache.push_back(dir);
}
예제 #5
0
int CControlSocket::CheckOverwriteFile()
{
	if (!m_pCurOpData)
	{
		LogMessage(__TFILE__, __LINE__, this, MessageType::Debug_Info, _T("Empty m_pCurOpData"));
		ResetOperation(FZ_REPLY_INTERNALERROR);
		return FZ_REPLY_ERROR;
	}

	CFileTransferOpData *pData = static_cast<CFileTransferOpData *>(m_pCurOpData);

	if (pData->download)
	{
		if (!wxFile::Exists(pData->localFile))
			return FZ_REPLY_OK;
	}

	CDirentry entry;
	bool dirDidExist;
	bool matchedCase;
	CDirectoryCache cache;
	CServerPath remotePath;
	if (pData->tryAbsolutePath || m_CurrentPath.empty())
		remotePath = pData->remotePath;
	else
		remotePath = m_CurrentPath;
	bool found = cache.LookupFile(entry, *m_pCurrentServer, remotePath, pData->remoteFile, dirDidExist, matchedCase);

	// Ignore entries with wrong case
	if (found && !matchedCase)
		found = false;

	if (!pData->download)
	{
		if (!found && pData->remoteFileSize == -1 && !pData->fileTime.IsValid())
			return FZ_REPLY_OK;
	}

	CFileExistsNotification *pNotification = new CFileExistsNotification;

	pNotification->download = pData->download;
	pNotification->localFile = pData->localFile;
	pNotification->remoteFile = pData->remoteFile;
	pNotification->remotePath = pData->remotePath;
	pNotification->localSize = pData->localFileSize;
	pNotification->remoteSize = pData->remoteFileSize;
	pNotification->ascii = !pData->transferSettings.binary;

	if (pData->download && pNotification->localSize != -1)
		pNotification->canResume = true;
	else if (!pData->download && pNotification->remoteSize != -1)
		pNotification->canResume = true;
	else
		pNotification->canResume = false;

	pNotification->localTime = CLocalFileSystem::GetModificationTime(pData->localFile);

	if (pData->fileTime.IsValid())
		pNotification->remoteTime = pData->fileTime;

	if (found) {
		if (!pData->fileTime.IsValid()) {
			if (entry.has_date()) {
				pNotification->remoteTime = entry.time;
				pData->fileTime = entry.time;
			}
		}
	}

	SendAsyncRequest(pNotification);

	return FZ_REPLY_WOULDBLOCK;
}
예제 #6
0
int CControlSocket::ResetOperation(int nErrorCode)
{
	LogMessage(MessageType::Debug_Verbose, _T("CControlSocket::ResetOperation(%d)"), nErrorCode);

	if (nErrorCode & FZ_REPLY_WOULDBLOCK)
	{
		LogMessage(MessageType::Debug_Warning, _T("ResetOperation with FZ_REPLY_WOULDBLOCK in nErrorCode (%d)"), nErrorCode);
	}

	if (m_pCurOpData && m_pCurOpData->holdsLock)
		UnlockCache();

	if (m_pCurOpData && m_pCurOpData->pNextOpData)
	{
		COpData *pNext = m_pCurOpData->pNextOpData;
		m_pCurOpData->pNextOpData = 0;
		delete m_pCurOpData;
		m_pCurOpData = pNext;
		if (nErrorCode == FZ_REPLY_OK ||
			nErrorCode == FZ_REPLY_ERROR ||
			nErrorCode == FZ_REPLY_CRITICALERROR)
		{
			return ParseSubcommandResult(nErrorCode);
		}
		else
			return ResetOperation(nErrorCode);
	}

	wxString prefix;
	if ((nErrorCode & FZ_REPLY_CRITICALERROR) == FZ_REPLY_CRITICALERROR &&
		(!m_pCurOpData || m_pCurOpData->opId != Command::transfer))
	{
		prefix = _("Critical error:") + _T(" ");
	}

	if (m_pCurOpData)
	{
		const Command commandId = m_pCurOpData->opId;
		switch (commandId)
		{
		case Command::none:
			if( !prefix.empty() ) {
				LogMessage(MessageType::Error, _("Critical error"));
			}
			break;
		case Command::connect:
			if ((nErrorCode & FZ_REPLY_CANCELED) == FZ_REPLY_CANCELED)
				LogMessage(MessageType::Error, prefix + _("Connection attempt interrupted by user"));
			else if (nErrorCode != FZ_REPLY_OK)
				LogMessage(MessageType::Error, prefix + _("Could not connect to server"));
			break;
		case Command::list:
			if ((nErrorCode & FZ_REPLY_CANCELED) == FZ_REPLY_CANCELED)
				LogMessage(MessageType::Error, prefix + _("Directory listing aborted by user"));
			else if (nErrorCode != FZ_REPLY_OK)
				LogMessage(MessageType::Error, prefix + _("Failed to retrieve directory listing"));
			else
				LogMessage(MessageType::Status, _("Directory listing successful"));
			break;
		case Command::transfer:
			{
				CFileTransferOpData *pData = static_cast<CFileTransferOpData *>(m_pCurOpData);
				if (!pData->download && pData->transferInitiated)
				{
					if (!m_pCurrentServer)
						LogMessage(__TFILE__, __LINE__, this, MessageType::Debug_Warning, _T("m_pCurrentServer is 0"));
					else
					{
						CDirectoryCache cache;
						bool updated = cache.UpdateFile(*m_pCurrentServer, pData->remotePath, pData->remoteFile, true, CDirectoryCache::file, (nErrorCode == FZ_REPLY_OK) ? pData->localFileSize : -1);

						if (updated)
							m_pEngine->SendDirectoryListingNotification(pData->remotePath, false, true, false);
					}
				}
				LogTransferResultMessage(nErrorCode, pData);
			}
			break;
		default:
			if ((nErrorCode & FZ_REPLY_CANCELED) == FZ_REPLY_CANCELED)
				LogMessage(MessageType::Error, prefix + _("Interrupted by user"));
			break;
		}

		delete m_pCurOpData;
		m_pCurOpData = 0;
	}

	ResetTransferStatus();

	SetWait(false);

	if (m_invalidateCurrentPath) {
		m_CurrentPath.clear();
		m_invalidateCurrentPath = false;
	}

	return m_pEngine->ResetOperation(nErrorCode);
}
예제 #7
0
bool CControlSocket::SetFileExistsAction(CFileExistsNotification *pFileExistsNotification)
{
	wxASSERT(pFileExistsNotification);

	if (!m_pCurOpData || m_pCurOpData->opId != Command::transfer)
	{
		LogMessage(__TFILE__, __LINE__, this, MessageType::Debug_Info, _T("No or invalid operation in progress, ignoring request reply %f"), pFileExistsNotification->GetRequestID());
		return false;
	}

	CFileTransferOpData *pData = static_cast<CFileTransferOpData *>(m_pCurOpData);

	switch (pFileExistsNotification->overwriteAction)
	{
	case CFileExistsNotification::overwrite:
		SendNextCommand();
		break;
	case CFileExistsNotification::overwriteNewer:
		if (!pFileExistsNotification->localTime.IsValid() || !pFileExistsNotification->remoteTime.IsValid())
			SendNextCommand();
		else if (pFileExistsNotification->download && pFileExistsNotification->localTime.IsEarlierThan(pFileExistsNotification->remoteTime))
			SendNextCommand();
		else if (!pFileExistsNotification->download && pFileExistsNotification->localTime.IsLaterThan(pFileExistsNotification->remoteTime))
			SendNextCommand();
		else
		{
			if (pData->download)
			{
				wxString filename = pData->remotePath.FormatFilename(pData->remoteFile);
				LogMessage(MessageType::Status, _("Skipping download of %s"), filename);
			}
			else
			{
				LogMessage(MessageType::Status, _("Skipping upload of %s"), pData->localFile);
			}
			ResetOperation(FZ_REPLY_OK);
		}
		break;
	case CFileExistsNotification::overwriteSize:
		/* First compare flags both size known but different, one size known and the other not (obviously they are different).
		Second compare flags the remaining case in which we need to send command : both size unknown */
		if ((pFileExistsNotification->localSize != pFileExistsNotification->remoteSize) || (pFileExistsNotification->localSize == -1))
			SendNextCommand();
		else {
			if (pData->download) {
				wxString filename = pData->remotePath.FormatFilename(pData->remoteFile);
				LogMessage(MessageType::Status, _("Skipping download of %s"), filename);
			}
			else {
				LogMessage(MessageType::Status, _("Skipping upload of %s"), pData->localFile);
			}
			ResetOperation(FZ_REPLY_OK);
		}
		break;
	case CFileExistsNotification::overwriteSizeOrNewer:
		if (!pFileExistsNotification->localTime.IsValid() || !pFileExistsNotification->remoteTime.IsValid())
			SendNextCommand();
		/* First compare flags both size known but different, one size known and the other not (obviously they are different).
		Second compare flags the remaining case in which we need to send command : both size unknown */
		else if ((pFileExistsNotification->localSize != pFileExistsNotification->remoteSize) || (pFileExistsNotification->localSize == -1))
			SendNextCommand();
		else if (pFileExistsNotification->download && pFileExistsNotification->localTime.IsEarlierThan(pFileExistsNotification->remoteTime))
			SendNextCommand();
		else if (!pFileExistsNotification->download && pFileExistsNotification->localTime.IsLaterThan(pFileExistsNotification->remoteTime))
			SendNextCommand();
		else
		{
			if (pData->download)
			{
				wxString filename = pData->remotePath.FormatFilename(pData->remoteFile);
				LogMessage(MessageType::Status, _("Skipping download of %s"), filename);
			}
			else
			{
				LogMessage(MessageType::Status, _("Skipping upload of %s"), pData->localFile);
			}
			ResetOperation(FZ_REPLY_OK);
		}
		break;
	case CFileExistsNotification::resume:
		if (pData->download && pData->localFileSize != -1)
			pData->resume = true;
		else if (!pData->download && pData->remoteFileSize != -1)
			pData->resume = true;
		SendNextCommand();
		break;
	case CFileExistsNotification::rename:
		if (pData->download)
		{
			wxFileName fn = pData->localFile;
			fn.SetFullName(pFileExistsNotification->newName);
			pData->localFile = fn.GetFullPath();

			wxLongLong size;
			bool isLink;
			if (CLocalFileSystem::GetFileInfo(pData->localFile, isLink, &size, 0, 0) == CLocalFileSystem::file)
				pData->localFileSize = size.GetValue();
			else
				pData->localFileSize = -1;

			if (CheckOverwriteFile() == FZ_REPLY_OK)
				SendNextCommand();
		}
		else
		{
			pData->remoteFile = pFileExistsNotification->newName;

			CDirectoryCache cache;

			CDirentry entry;
			bool dir_did_exist;
			bool matched_case;
			if (cache.LookupFile(entry, *m_pCurrentServer, pData->tryAbsolutePath ? pData->remotePath : m_CurrentPath, pData->remoteFile, dir_did_exist, matched_case) &&
				matched_case)
			{
				wxLongLong size = entry.size;
				pData->remoteFileSize = size.GetValue();
				if (entry.has_date())
					pData->fileTime = entry.time;

				if (CheckOverwriteFile() != FZ_REPLY_OK)
					break;
			}
			else
			{
				pData->fileTime = CDateTime();
				pData->remoteFileSize = -1;
			}

			SendNextCommand();
		}
		break;
	case CFileExistsNotification::skip:
		if (pData->download)
		{
			wxString filename = pData->remotePath.FormatFilename(pData->remoteFile);
			LogMessage(MessageType::Status, _("Skipping download of %s"), filename);
		}
		else
		{
			LogMessage(MessageType::Status, _("Skipping upload of %s"), pData->localFile);
		}
		ResetOperation(FZ_REPLY_OK);
		break;
	default:
		LogMessage(__TFILE__, __LINE__, this, MessageType::Debug_Warning, _T("Unknown file exists action: %d"), pFileExistsNotification->overwriteAction);
		ResetOperation(FZ_REPLY_INTERNALERROR);
		return false;
	}

	return true;
}
예제 #8
0
BOOL CFileZillaApi::DumpDirectoryCache(LPCTSTR pFileName)
{
	CDirectoryCache cache;
	return cache.Dump(pFileName);
}
예제 #9
0
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;
#ifndef MPEXT_NO_CACHE
	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;
#endif
	if (dirname==_MPT("") || parent.IsEmpty())
		return FZ_REPLY_INVALIDPARAM;

#ifndef MPEXT_NO_CACHE
	//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;
		}
	}
#endif

	if (m_pMainThread->IsBusy())
		return FZ_REPLY_BUSY;
#ifndef MPEXT_NO_CACHE
	if (nListMode&FZ_LIST_FORCECACHE)
		return FZ_REPLY_ERROR;
#endif

	t_command command;
	command.id=FZ_COMMAND_LIST;
	command.path=parent;
	command.param1=dirname;
	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;
}
예제 #10
0
int CControlSocket::CheckOverwriteFile()
{
	if (!m_pCurOpData)
	{
		LogMessage(__TFILE__, __LINE__, this, Debug_Info, _T("Empty m_pCurOpData"));
		ResetOperation(FZ_REPLY_INTERNALERROR);
		return FZ_REPLY_ERROR;
	}

	CFileTransferOpData *pData = static_cast<CFileTransferOpData *>(m_pCurOpData);

	if (pData->download)
	{
		if (!wxFile::Exists(pData->localFile))
			return FZ_REPLY_OK;
	}

	CDirentry entry;
	bool dirDidExist;
	bool matchedCase;
	CDirectoryCache cache;
	CServerPath remotePath;
	if (pData->tryAbsolutePath || m_CurrentPath.IsEmpty())
		remotePath = pData->remotePath;
	else
		remotePath = m_CurrentPath;
	bool found = cache.LookupFile(entry, *m_pCurrentServer, remotePath, pData->remoteFile, dirDidExist, matchedCase);

	// Ignore entries with wrong case
	if (found && !matchedCase)
		found = false;

	if (!pData->download)
	{
		if (!found && pData->remoteFileSize == -1 && !pData->fileTime.IsValid())
			return FZ_REPLY_OK;
	}

	CFileExistsNotification *pNotification = new CFileExistsNotification;

	pNotification->download = pData->download;
	pNotification->localFile = pData->localFile;
	pNotification->remoteFile = pData->remoteFile;
	pNotification->remotePath = pData->remotePath;
	pNotification->localSize = pData->localFileSize;
	pNotification->remoteSize = pData->remoteFileSize;
	pNotification->ascii = !pData->transferSettings.binary;

	wxStructStat buf;
	int result;
	result = wxStat(pData->localFile, &buf);
	if (!result)
	{
		pNotification->localTime = wxDateTime(buf.st_mtime);
		if (!pNotification->localTime.IsValid())
			pNotification->localTime = wxDateTime(buf.st_ctime);
	}

	if (pData->fileTime.IsValid())
		pNotification->remoteTime = pData->fileTime;

	if (found)
	{
		if (!pData->fileTime.IsValid())
		{
			if (entry.hasDate)
			{
				pNotification->remoteTime = entry.time;
				pData->fileTime = entry.time;
			}
		}
	}

	pNotification->requestNumber = m_pEngine->GetNextAsyncRequestNumber();
	pData->waitForAsyncRequest = true;

	m_pEngine->AddNotification(pNotification);

	return FZ_REPLY_WOULDBLOCK;
}