void CRecursiveOperation::StartRecursiveOperation(enum OperationMode mode, const CServerPath& startDir, const std::list<CFilter>& filters, bool allowParent /*=false*/, const CServerPath& finalDir /*=CServerPath()*/)
{
	wxCHECK_RET(m_operationMode == recursive_none, _T("StartRecursiveOperation called with m_operationMode != recursive_none"));
	wxCHECK_RET(m_pState->IsRemoteConnected(), _T("StartRecursiveOperation while disconnected"));
	wxCHECK_RET(!startDir.empty(), _T("Empty startDir in StartRecursiveOperation"));

	if (mode == recursive_chmod && !m_pChmodDlg)
		return;

	if ((mode == recursive_download || mode == recursive_addtoqueue || mode == recursive_download_flatten || mode == recursive_addtoqueue_flatten) && !m_pQueue)
		return;

	if (m_dirsToVisit.empty())
	{
		// Nothing to do in this case
		return;
	}

	m_operationMode = mode;
	m_pState->NotifyHandlers(STATECHANGE_REMOTE_IDLE);

	m_startDir = startDir;

	if (finalDir.empty())
		m_finalDir = startDir;
	else
		m_finalDir = finalDir;

	m_allowParent = allowParent;

	m_filters = filters;

	NextOperation();
}
void CRemoteRecursiveOperation::StartRecursiveOperation(OperationMode mode, std::vector<CFilter> const& filters, CServerPath const& finalDir)
{
	wxCHECK_RET(m_operationMode == recursive_none, _T("StartRecursiveOperation called with m_operationMode != recursive_none"));
	wxCHECK_RET(m_state.IsRemoteConnected(), _T("StartRecursiveOperation while disconnected"));
	wxCHECK_RET(!finalDir.empty(), _T("Empty final dir in recursive operation"));

	if (mode == recursive_chmod && !m_pChmodDlg)
		return;

	if ((mode == recursive_transfer || mode == recursive_addtoqueue || mode == recursive_transfer_flatten || mode == recursive_addtoqueue_flatten) && !m_pQueue)
		return;

	if (recursion_roots_.empty()) {
		// Nothing to do in this case
		return;
	}

	m_processedFiles = 0;
	m_processedDirectories = 0;

	m_operationMode = mode;
	m_state.NotifyHandlers(STATECHANGE_REMOTE_IDLE);
	m_state.NotifyHandlers(STATECHANGE_REMOTE_RECURSION_STATUS);

	m_filters = filters;

	NextOperation();
}
void CRecursiveOperation::ListingFailed(int error)
{
	if (m_operationMode == recursive_none)
		return;

	if( (error & FZ_REPLY_CANCELED) == FZ_REPLY_CANCELED) {
		// User has cancelled operation
		StopRecursiveOperation();
		return;
	}

	wxASSERT(!m_dirsToVisit.empty());
	if (m_dirsToVisit.empty())
		return;

	CNewDir dir = m_dirsToVisit.front();
	m_dirsToVisit.pop_front();
	if ((error & FZ_REPLY_CRITICALERROR) != FZ_REPLY_CRITICALERROR && !dir.second_try)
	{
		// Retry, could have been a temporary socket creating failure
		// (e.g. hitting a blocked port) or a disconnect (e.g. no-filetransfer-timeout)
		dir.second_try = true;
		m_dirsToVisit.push_front(dir);
	}

	NextOperation();
}
void CRecursiveOperation::StartRecursiveOperation(enum OperationMode mode, const CServerPath& startDir, bool allowParent /*=false*/, const CServerPath& finalDir /*=CServerPath()*/)
{
	wxCHECK_RET(m_operationMode == recursive_none, _T("StartRecursiveOperation called with m_operationMode != recursive_none"));
	wxCHECK_RET(m_pState->IsRemoteConnected(), _T("StartRecursiveOperation while disconnected"));
	wxCHECK_RET(!startDir.IsEmpty(), _T("Empty startDir in StartRecursiveOperation"));

	if (mode == recursive_chmod && !m_pChmodDlg)
		return;

	if ((mode == recursive_download || mode == recursive_addtoqueue) && !m_pQueue)
		return;

	if (m_dirsToVisit.empty())
	{
		// Nothing to do in this case
		return;
	}

	m_operationMode = mode;

	m_startDir = startDir;

	if (finalDir.IsEmpty())
		m_finalDir = startDir;
	else
		m_finalDir = finalDir;

	m_allowParent = allowParent;

	NextOperation();
}
void CRemoteRecursiveOperation::ListingFailed(int error)
{
	if (m_operationMode == recursive_none || recursion_roots_.empty())
		return;

	if( (error & FZ_REPLY_CANCELED) == FZ_REPLY_CANCELED) {
		// User has cancelled operation
		StopRecursiveOperation();
		return;
	}

	auto & root = recursion_roots_.front();
	wxCHECK_RET(!root.m_dirsToVisit.empty(), _T("Empty dirs to visit"));

	recursion_root::new_dir dir = root.m_dirsToVisit.front();
	root.m_dirsToVisit.pop_front();
	if ((error & FZ_REPLY_CRITICALERROR) != FZ_REPLY_CRITICALERROR && !dir.second_try) {
		// Retry, could have been a temporary socket creating failure
		// (e.g. hitting a blocked port) or a disconnect (e.g. no-filetransfer-timeout)
		dir.second_try = true;
		root.m_dirsToVisit.push_front(dir);
	}

	NextOperation();
}
VError DB4DJournalParser::_CheckFile( VDB4DProgressIndicator *inProgressIndicator )
{
	VError error = VE_OK;
	if ( fFileStream )
	{
		sLONG8 streamPos = 0;
		if ( inProgressIndicator )
		{
			inProgressIndicator->BeginSession( fFileStream->GetSize(), GetString(1005, 24) );
		}

		while ( error == VE_OK )
		{
			CDB4DJournalData *jData = NULL;
			uLONG8 globalOperation;
			error = NextOperation( fTotalOperationCount, &globalOperation, fTotalOperationCount ? NULL : &jData );
			if ( jData )
			{
				jData->Release();
			}

			if (globalOperation != 0)
				fLastOperation = globalOperation;
			if (fFirstOperation == 0)
				fFirstOperation = globalOperation;
				
			if ( inProgressIndicator )
			{
				if ( !inProgressIndicator->Progress( streamPos ) )
					error = VE_STREAM_USER_ABORTED;
				else if ( fTotalOperationCount%128 == 0 )
					VTask::Yield();
			}

			if ( fTotalOperationCount%512 == 0 ) 
			{
				streamPos = fFileStream->GetPos();
				fModuloDataOffset.AppendLong8(streamPos);
			}
		}

		if ( error == VE_STREAM_EOF )
		{
			fFileStream->ResetLastError();
			error = VE_OK;
		}

		if ( inProgressIndicator )
		{
			inProgressIndicator->EndSession();
		}
	}
	else
	{
		error = VE_UNIMPLEMENTED; // not initialized
	}
	return error;
}
void CRecursiveOperation::LinkIsNotDir()
{
	if (m_operationMode == recursive_none)
		return;

	wxASSERT(!m_dirsToVisit.empty());
	if (m_dirsToVisit.empty())
		return;

	CNewDir dir = m_dirsToVisit.front();
	m_dirsToVisit.pop_front();

	const CServer* pServer = m_pState->GetServer();
	if (!pServer)
	{
		NextOperation();
		return;
	}

	if (m_operationMode == recursive_delete)
	{
		if (!dir.subdir.empty())
		{
			std::list<wxString> files;
			files.push_back(dir.subdir);
			m_pState->m_pCommandQueue->ProcessCommand(new CDeleteCommand(dir.parent, files));
		}
		NextOperation();
		return;
	}
	else if (m_operationMode != recursive_list )
	{
		CLocalPath localPath = dir.localDir;
		wxString localFile = dir.subdir;
		if (m_operationMode != recursive_addtoqueue_flatten && m_operationMode != recursive_download_flatten)
			localPath.MakeParent();
		m_pQueue->QueueFile(m_operationMode == recursive_addtoqueue || m_operationMode == recursive_addtoqueue_flatten, true, dir.subdir, (dir.subdir == localFile) ? wxString() : localFile, localPath, dir.parent, *pServer, -1);
		m_pQueue->QueueFile_Finish(m_operationMode != recursive_addtoqueue);
	}

	NextOperation();
}
void CRecursiveOperation::ListingFailed()
{
	if (m_operationMode == recursive_none)
		return;

	wxASSERT(!m_dirsToVisit.empty());
	if (m_dirsToVisit.empty())
		return;

	m_dirsToVisit.pop_front();

	NextOperation();
}
void CRemoteRecursiveOperation::LinkIsNotDir()
{
	if (m_operationMode == recursive_none || recursion_roots_.empty()) {
		return;
	}

	auto & root = recursion_roots_.front();
	wxCHECK_RET(!root.m_dirsToVisit.empty(), _T("Empty dirs to visit"));

	recursion_root::new_dir dir = root.m_dirsToVisit.front();
	root.m_dirsToVisit.pop_front();

	const CServer* pServer = m_state.GetServer();
	if (!pServer) {
		NextOperation();
		return;
	}

	if (m_operationMode == recursive_delete) {
		if (!dir.subdir.empty()) {
			std::deque<std::wstring> files;
			files.push_back(dir.subdir);
			m_state.m_pCommandQueue->ProcessCommand(new CDeleteCommand(dir.parent, std::move(files)), CCommandQueue::recursiveOperation);
		}
		NextOperation();
		return;
	}
	else if (m_operationMode != recursive_list) {
		CLocalPath localPath = dir.localDir;
		std::wstring localFile = dir.subdir;
		if (m_operationMode != recursive_transfer_flatten) {
			localPath.MakeParent();
		}
		m_pQueue->QueueFile(!m_immediate, true, dir.subdir, (dir.subdir == localFile) ? std::wstring() : localFile, localPath, dir.parent, *pServer, -1);
		m_pQueue->QueueFile_Finish(m_immediate);
	}

	NextOperation();
}
Exemple #10
0
void Mac::TransmitDoneTask(void)
{
    ThreadError error;
    bool rxPending;

    error = otPlatRadioHandleTransmitDone(&rxPending);

    mAckTimer.Stop();

    if (error == kThreadError_ChannelAccessFailure &&
        mCsmaAttempts < kMaxCSMABackoffs)
    {
        mCsmaAttempts++;
        StartCsmaBackoff();
        ExitNow();
    }

    mCsmaAttempts = 0;

    switch (mState)
    {
    case kStateActiveScan:
        mAckTimer.Start(mScanDuration);
        break;

    case kStateTransmitBeacon:
        SentFrame(true);
        break;

    case kStateTransmitData:
        if (rxPending)
        {
            mReceiveTimer.Start(kDataPollTimeout);
        }
        else
        {
            mReceiveTimer.Stop();
        }

        SentFrame(error == kThreadError_None);
        break;

    default:
        assert(false);
        break;
    }

exit:
    NextOperation();
}
VError DB4DJournalParser::SetCurrentOperation( uLONG8 inOperation, CDB4DJournalData **outJournalData )
{
	VError error = VE_OK;
	if ( fFileStream )
	{
		if ( inOperation == fCurrentOperation )
		{
			*outJournalData = fCurrentData;
			if (fCurrentData != nil)
				fCurrentData->Retain();
		}
		else
		{
			if ((inOperation < fCurrentOperation) || (inOperation > (fCurrentOperation+4096)))
			{
				if ( inOperation%512 )
				{
					fFileStream->SetPos(fModuloDataOffset.GetLong8((inOperation/512)+1));
					fCurrentOperation = ((inOperation/512)*512);
				}
				else
				{
					fFileStream->SetPos(fModuloDataOffset.GetLong8(inOperation/512));
					fCurrentOperation = (((inOperation-1)/512)*512);
				}
			}

			*outJournalData = NULL;
			while ( error == VE_OK && fCurrentOperation < inOperation )
			{
				if ( *outJournalData )
					(*outJournalData)->Release();
				error = NextOperation( fCurrentOperation, NULL, outJournalData );
			}
		}

		if ( *outJournalData && error != VE_OK )
		{
			(*outJournalData)->Release();
			*outJournalData = NULL;
		}
	}
	else
	{
		*outJournalData = NULL;
		error = VE_UNIMPLEMENTED; // not initialized
	}
	return error;
}
Exemple #12
0
void Mac::HandleAckTimer(void)
{
    otPlatRadioIdle();

    switch (mState)
    {
    case kStateActiveScan:
        do
        {
            mScanChannels >>= 1;
            mScanChannel++;

            if (mScanChannels == 0 || mScanChannel > kPhyMaxChannel)
            {
                mActiveScanHandler(mActiveScanContext, NULL);
                ScheduleNextTransmission();
                ExitNow();
            }
        }
        while ((mScanChannels & 1) == 0);

        StartCsmaBackoff();
        break;

    case kStateTransmitData:
        otLogDebgMac("ack timer fired\n");
        SentFrame(false);
        break;

    default:
        assert(false);
        break;
    }

exit:
    NextOperation();
}
void CRemoteRecursiveOperation::StartRecursiveOperation(OperationMode mode, ActiveFilters const& filters, CServerPath const& finalDir, bool immediate)
{
	wxCHECK_RET(m_operationMode == recursive_none, _T("StartRecursiveOperation called with m_operationMode != recursive_none"));
	wxCHECK_RET(m_state.IsRemoteConnected(), _T("StartRecursiveOperation while disconnected"));
	wxCHECK_RET(!finalDir.empty(), _T("Empty final dir in recursive operation"));

	if (mode == recursive_chmod && !m_pChmodDlg) {
		return;
	}

	if ((mode == recursive_transfer || mode == recursive_transfer_flatten) && !m_pQueue) {
		return;
	}

	if (recursion_roots_.empty()) {
		// Nothing to do in this case
		return;
	}

	m_processedFiles = 0;
	m_processedDirectories = 0;

	m_immediate = immediate;
	m_operationMode = mode;

	if ((mode == CRecursiveOperation::recursive_transfer || mode == CRecursiveOperation::recursive_transfer_flatten) && immediate) {
		m_actionAfterBlocker = m_pQueue->GetActionAfterBlocker();
	}

	m_state.NotifyHandlers(STATECHANGE_REMOTE_IDLE);
	m_state.NotifyHandlers(STATECHANGE_REMOTE_RECURSION_STATUS);

	m_filters = filters;

	NextOperation();
}
void CRemoteRecursiveOperation::ProcessDirectoryListing(const CDirectoryListing* pDirectoryListing)
{
	if (!pDirectoryListing) {
		StopRecursiveOperation();
		return;
	}

	if (m_operationMode == recursive_none || recursion_roots_.empty())
		return;

	if (pDirectoryListing->failed()) {
		// Ignore this.
		// It will get handled by the failed command in ListingFailed
		return;
	}

	auto & root = recursion_roots_.front();
	wxASSERT(!root.m_dirsToVisit.empty());

	if (!m_state.IsRemoteConnected() || root.m_dirsToVisit.empty()) {
		StopRecursiveOperation();
		return;
	}

	recursion_root::new_dir dir = root.m_dirsToVisit.front();
	root.m_dirsToVisit.pop_front();

	if (!BelowRecursionRoot(pDirectoryListing->path, dir)) {
		NextOperation();
		return;
	}

	if (m_operationMode == recursive_delete && dir.doVisit && !dir.subdir.empty()) {
		// After recursing into directory to delete its contents, delete directory itself
		// Gets handled in NextOperation
		recursion_root::new_dir dir2 = dir;
		dir2.doVisit = false;
		root.m_dirsToVisit.push_front(dir2);
	}

	if (dir.link && !dir.recurse) {
		NextOperation();
		return;
	}

	// Check if we have already visited the directory
	if (!root.m_visitedDirs.insert(pDirectoryListing->path).second) {
		NextOperation();
		return;
	}

	++m_processedDirectories;

	const CServer* pServer = m_state.GetServer();
	wxASSERT(pServer);

	if (!pDirectoryListing->GetCount() && m_operationMode == recursive_transfer) {
		if (m_immediate) {
			wxFileName::Mkdir(dir.localDir.GetPath(), 0777, wxPATH_MKDIR_FULL);
			m_state.RefreshLocalFile(dir.localDir.GetPath());
		}
		else {
			m_pQueue->QueueFile(true, true, _T(""), _T(""), dir.localDir, CServerPath(), *pServer, -1);
			m_pQueue->QueueFile_Finish(false);
		}
	}

	CFilterManager filter;

	// Is operation restricted to a single child?
	bool const restrict = static_cast<bool>(dir.restrict);

	std::deque<std::wstring> filesToDelete;

	std::wstring const remotePath = pDirectoryListing->path.GetPath();

	if (m_operationMode == recursive_synchronize_download && !dir.localDir.empty()) {
		// Step one in synchronization: Delete local files not on the server
		fz::local_filesys fs;
		if (fs.begin_find_files(fz::to_native(dir.localDir.GetPath()))) {
			std::list<fz::native_string> paths_to_delete;

			bool isLink{};
			fz::native_string name;
			bool isDir{};
			int64_t size{};
			fz::datetime time;
			int attributes{};
			while (fs.get_next_file(name, isLink, isDir, &size, &time, &attributes)) {
				if (isLink) {
					continue;
				}
				auto const wname = fz::to_wstring(name);
				if (filter.FilenameFiltered(m_filters.first, wname, dir.localDir.GetPath(), isDir, size, attributes, time)) {
					continue;
				}

				// Local item isn't filtered

				int remoteIndex = pDirectoryListing->FindFile_CmpCase(fz::to_wstring(name));
				if (remoteIndex != -1) {
					CDirentry const& entry = (*pDirectoryListing)[remoteIndex];
					if (!filter.FilenameFiltered(m_filters.second, entry.name, remotePath, entry.is_dir(), entry.size, 0, entry.time)) {
						// Both local and remote items exist

						if (isDir == entry.is_dir() || entry.is_link()) {
							// Normal item, nothing we should do
							continue;
						}
					}
				}

				// Local item should be deleted if reaching this point
				paths_to_delete.push_back(fz::to_native(dir.localDir.GetPath()) + name);
			}

			fz::recursive_remove r;
			r.remove(paths_to_delete);
		}
	}

	bool added = false;

	for (int i = pDirectoryListing->GetCount() - 1; i >= 0; --i) {
		const CDirentry& entry = (*pDirectoryListing)[i];

		if (restrict) {
			if (entry.name != *dir.restrict)
				continue;
		}
		else if (filter.FilenameFiltered(m_filters.second, entry.name, remotePath, entry.is_dir(), entry.size, 0, entry.time))
			continue;

		if (!entry.is_dir()) {
			++m_processedFiles;
		}

		if (entry.is_dir() && (!entry.is_link() || m_operationMode != recursive_delete)) {
			if (dir.recurse) {
				recursion_root::new_dir dirToVisit;
				dirToVisit.parent = pDirectoryListing->path;
				dirToVisit.subdir = entry.name;
				dirToVisit.localDir = dir.localDir;
				dirToVisit.start_dir = dir.start_dir;

				if (m_operationMode == recursive_transfer || m_operationMode == recursive_synchronize_download) {
					// Non-flatten case
					dirToVisit.localDir.AddSegment(CQueueView::ReplaceInvalidCharacters(entry.name));
				}
				if (entry.is_link()) {
					dirToVisit.link = 1;
					dirToVisit.recurse = false;
				}
				root.m_dirsToVisit.push_front(dirToVisit);
			}
		}
		else {
			switch (m_operationMode)
			{
			case recursive_transfer:
			case recursive_transfer_flatten:
			case recursive_synchronize_download:
				{
					std::wstring localFile = CQueueView::ReplaceInvalidCharacters(entry.name);
					if (pDirectoryListing->path.GetType() == VMS && COptions::Get()->GetOptionVal(OPTION_STRIP_VMS_REVISION)) {
						localFile = StripVMSRevision(localFile);
					}
					m_pQueue->QueueFile(!m_immediate, true,
						entry.name, (entry.name == localFile) ? std::wstring() : localFile,
						dir.localDir, pDirectoryListing->path, *pServer, entry.size);
					added = true;
				}
				break;
			case recursive_delete:
				filesToDelete.push_back(entry.name);
				break;
			default:
				break;
			}
		}

		if (m_operationMode == recursive_chmod && m_pChmodDlg) {
			const int applyType = m_pChmodDlg->GetApplyType();
			if (!applyType ||
				(!entry.is_dir() && applyType == 1) ||
				(entry.is_dir() && applyType == 2))
			{
				char permissions[9];
				bool res = m_pChmodDlg->ConvertPermissions(*entry.permissions, permissions);
				std::wstring newPerms = m_pChmodDlg->GetPermissions(res ? permissions : 0, entry.is_dir()).ToStdWstring();
				m_state.m_pCommandQueue->ProcessCommand(new CChmodCommand(pDirectoryListing->path, entry.name, newPerms), CCommandQueue::recursiveOperation);
			}
		}
	}
	if (added) {
		m_pQueue->QueueFile_Finish(m_immediate);
	}

	if (m_operationMode == recursive_delete && !filesToDelete.empty()) {
		m_state.m_pCommandQueue->ProcessCommand(new CDeleteCommand(pDirectoryListing->path, std::move(filesToDelete)), CCommandQueue::recursiveOperation);
	}

	m_state.NotifyHandlers(STATECHANGE_REMOTE_RECURSION_STATUS);

	NextOperation();
}
void CRemoteRecursiveOperation::ProcessDirectoryListing(const CDirectoryListing* pDirectoryListing)
{
	if (!pDirectoryListing) {
		StopRecursiveOperation();
		return;
	}

	if (m_operationMode == recursive_none || recursion_roots_.empty())
		return;

	if (pDirectoryListing->failed()) {
		// Ignore this.
		// It will get handled by the failed command in ListingFailed
		return;
	}

	auto & root = recursion_roots_.front();
	wxASSERT(!root.m_dirsToVisit.empty());

	if (!m_state.IsRemoteConnected() || root.m_dirsToVisit.empty()) {
		StopRecursiveOperation();
		return;
	}

	recursion_root::new_dir dir = root.m_dirsToVisit.front();
	root.m_dirsToVisit.pop_front();

	if (!BelowRecursionRoot(pDirectoryListing->path, dir)) {
		NextOperation();
		return;
	}

	if (m_operationMode == recursive_delete && dir.doVisit && !dir.subdir.empty()) {
		// After recursing into directory to delete its contents, delete directory itself
		// Gets handled in NextOperation
		recursion_root::new_dir dir2 = dir;
		dir2.doVisit = false;
		root.m_dirsToVisit.push_front(dir2);
	}

	if (dir.link && !dir.recurse) {
		NextOperation();
		return;
	}

	// Check if we have already visited the directory
	if (!root.m_visitedDirs.insert(pDirectoryListing->path).second) {
		NextOperation();
		return;
	}

	++m_processedDirectories;

	const CServer* pServer = m_state.GetServer();
	wxASSERT(pServer);

	if (!pDirectoryListing->GetCount()) {
		if (m_operationMode == recursive_transfer) {
			wxFileName::Mkdir(dir.localDir.GetPath(), 0777, wxPATH_MKDIR_FULL);
			m_state.RefreshLocalFile(dir.localDir.GetPath());
		}
		else if (m_operationMode == recursive_addtoqueue) {
			m_pQueue->QueueFile(true, true, _T(""), _T(""), dir.localDir, CServerPath(), *pServer, -1);
			m_pQueue->QueueFile_Finish(false);
		}
	}

	CFilterManager filter;

	// Is operation restricted to a single child?
	bool const restrict = static_cast<bool>(dir.restrict);

	std::deque<wxString> filesToDelete;

	const wxString path = pDirectoryListing->path.GetPath();

	bool added = false;

	for (int i = pDirectoryListing->GetCount() - 1; i >= 0; --i) {
		const CDirentry& entry = (*pDirectoryListing)[i];

		if (restrict) {
			if (entry.name != *dir.restrict)
				continue;
		}
		else if (filter.FilenameFiltered(m_filters, entry.name, path, entry.is_dir(), entry.size, 0, entry.time))
			continue;

		if (!entry.is_dir()) {
			++m_processedFiles;
		}

		if (entry.is_dir() && (!entry.is_link() || m_operationMode != recursive_delete)) {
			if (dir.recurse) {
				recursion_root::new_dir dirToVisit;
				dirToVisit.parent = pDirectoryListing->path;
				dirToVisit.subdir = entry.name;
				dirToVisit.localDir = dir.localDir;
				dirToVisit.start_dir = dir.start_dir;

				if (m_operationMode == recursive_transfer || m_operationMode == recursive_addtoqueue) {
					// Non-flatten case
					dirToVisit.localDir.AddSegment(CQueueView::ReplaceInvalidCharacters(entry.name));
				}
				if (entry.is_link()) {
					dirToVisit.link = 1;
					dirToVisit.recurse = false;
				}
				root.m_dirsToVisit.push_front(dirToVisit);
			}
		}
		else {
			switch (m_operationMode)
			{
			case recursive_transfer:
			case recursive_transfer_flatten:
				{
					wxString localFile = CQueueView::ReplaceInvalidCharacters(entry.name);
					if (pDirectoryListing->path.GetType() == VMS && COptions::Get()->GetOptionVal(OPTION_STRIP_VMS_REVISION))
						localFile = StripVMSRevision(localFile);
					m_pQueue->QueueFile(m_operationMode == recursive_addtoqueue, true,
						entry.name, (entry.name == localFile) ? wxString() : localFile,
						dir.localDir, pDirectoryListing->path, *pServer, entry.size);
					added = true;
				}
				break;
			case recursive_addtoqueue:
			case recursive_addtoqueue_flatten:
				{
					wxString localFile = CQueueView::ReplaceInvalidCharacters(entry.name);
					if (pDirectoryListing->path.GetType() == VMS && COptions::Get()->GetOptionVal(OPTION_STRIP_VMS_REVISION))
						localFile = StripVMSRevision(localFile);
					m_pQueue->QueueFile(true, true,
						entry.name, (entry.name == localFile) ? wxString() : localFile,
						dir.localDir, pDirectoryListing->path, *pServer, entry.size);
					added = true;
				}
				break;
			case recursive_delete:
				filesToDelete.push_back(entry.name);
				break;
			default:
				break;
			}
		}

		if (m_operationMode == recursive_chmod && m_pChmodDlg) {
			const int applyType = m_pChmodDlg->GetApplyType();
			if (!applyType ||
				(!entry.is_dir() && applyType == 1) ||
				(entry.is_dir() && applyType == 2))
			{
				char permissions[9];
				bool res = m_pChmodDlg->ConvertPermissions(*entry.permissions, permissions);
				wxString newPerms = m_pChmodDlg->GetPermissions(res ? permissions : 0, entry.is_dir());
				m_state.m_pCommandQueue->ProcessCommand(new CChmodCommand(pDirectoryListing->path, entry.name, newPerms), CCommandQueue::recursiveOperation);
			}
		}
	}
	if (added)
		m_pQueue->QueueFile_Finish(m_operationMode != recursive_addtoqueue && m_operationMode != recursive_addtoqueue_flatten);

	if (m_operationMode == recursive_delete && !filesToDelete.empty())
		m_state.m_pCommandQueue->ProcessCommand(new CDeleteCommand(pDirectoryListing->path, std::move(filesToDelete)), CCommandQueue::recursiveOperation);

	m_state.NotifyHandlers(STATECHANGE_REMOTE_RECURSION_STATUS);

	NextOperation();
}
void CRecursiveOperation::ProcessDirectoryListing(const CDirectoryListing* pDirectoryListing)
{
	if (!pDirectoryListing)
	{
		StopRecursiveOperation();
		return;
	}

	if (m_operationMode == recursive_none)
		return;

	wxASSERT(!m_dirsToVisit.empty());

	if (!m_pState->IsRemoteConnected() || m_dirsToVisit.empty())
	{
		StopRecursiveOperation();
		return;
	}

	CNewDir dir = m_dirsToVisit.front();
	m_dirsToVisit.pop_front();

	if (!pDirectoryListing->path.IsSubdirOf(m_startDir, false))
	{
		// In some cases (chmod from tree for example) it is neccessary to list the
		// parent first
		if (pDirectoryListing->path != m_startDir || !m_allowParent)
		{
			NextOperation();
			return;
		}
	}

	if (m_operationMode == recursive_delete && dir.doVisit && dir.subdir != _T(""))
	{
		// After recursing into directory to delete its contents, delete directory itself
		// Gets handled in NextOperation
		CNewDir dir2 = dir;
		dir2.doVisit = false;
		m_dirsToVisit.push_front(dir2);
	}

	// Check if we have already visited the directory
	for (std::list<CServerPath>::const_iterator iter = m_visitedDirs.begin(); iter != m_visitedDirs.end(); iter++)
	{
		if (*iter == pDirectoryListing->path)
		{
			NextOperation();
			return;
		}
	}
	m_visitedDirs.push_back(pDirectoryListing->path);

	const CServer* pServer = m_pState->GetServer();
	wxASSERT(pServer);

	if (!pDirectoryListing->GetCount())
	{
		wxFileName fn(dir.localDir, _T(""));
		if (m_operationMode == recursive_download)
		{
			wxFileName::Mkdir(fn.GetPath(), 0777, wxPATH_MKDIR_FULL);
			m_pState->RefreshLocalFile(fn.GetFullPath());
		}
		else if (m_operationMode == recursive_addtoqueue)
			m_pQueue->QueueFile(true, true, fn.GetFullPath(), _T(""), CServerPath(), *pServer, -1);
	}

	CFilterDialog filter;

	// Is operation restricted to a single child?
	bool restrict = !dir.restrict.IsEmpty();

	for (int i = pDirectoryListing->GetCount() - 1; i >= 0; i--)
	{
		const CDirentry& entry = (*pDirectoryListing)[i];

		if (restrict)
		{
			if (entry.name != dir.restrict)
				continue;
		}
		else if (filter.FilenameFiltered(entry.name, entry.dir, entry.size, false))
			continue;

		if (entry.dir && !entry.link)
		{
			if (dir.recurse)
			{
				CNewDir dirToVisit;
				wxFileName fn(dir.localDir, _T(""));
				fn.AppendDir(entry.name);
				dirToVisit.parent = pDirectoryListing->path;
				dirToVisit.subdir = entry.name;
				dirToVisit.localDir = fn.GetFullPath();
				dirToVisit.doVisit = true;
				m_dirsToVisit.push_front(dirToVisit);
			}
		}
		else
		{
			switch (m_operationMode)
			{
			case recursive_addtoqueue:
			case recursive_download:
				{
					wxFileName fn(dir.localDir, entry.name);
					m_pQueue->QueueFile(m_operationMode == recursive_addtoqueue, true, fn.GetFullPath(), entry.name, pDirectoryListing->path, *pServer, entry.size);
				}
				break;
			case recursive_delete:
				m_pState->m_pCommandQueue->ProcessCommand(new CDeleteCommand(pDirectoryListing->path, entry.name));
				break;
			default:
				break;
			}
		}

		if (m_operationMode == recursive_chmod && m_pChmodDlg)
		{
			const int applyType = m_pChmodDlg->GetApplyType();
			if (!applyType ||
				(!entry.dir && applyType == 1) ||
				(entry.dir && applyType == 2))
			{
				char permissions[9];
				bool res = m_pChmodDlg->ConvertPermissions(entry.permissions, permissions);
				wxString newPerms = m_pChmodDlg->GetPermissions(res ? permissions : 0);
				m_pState->m_pCommandQueue->ProcessCommand(new CChmodCommand(pDirectoryListing->path, entry.name, newPerms));
			}
		}
	}

	NextOperation();
}
Exemple #17
0
void Mac::HandleReceiveTimer(void)
{
    otLogInfoMac("data poll timeout!\n");
    NextOperation();
}