bool CAutoAsciiFiles::TransferRemoteAsAscii(wxString const& remote_file, ServerType server_type)
{
	int mode = COptions::Get()->GetOptionVal(OPTION_ASCIIBINARY);
	if (mode == 1)
		return true;
	else if (mode == 2)
		return false;

	if (server_type == VMS) {
		return TransferRemoteAsAscii(StripVMSRevision(remote_file.ToStdWstring()), DEFAULT);
	}

	if (!remote_file.empty() && remote_file[0] == '.')
		return COptions::Get()->GetOptionVal(OPTION_ASCIIDOTFILE) != 0;

	int pos = remote_file.Find('.', true);
	if (pos < 0 || static_cast<unsigned int>(pos) + 1 == remote_file.size()) {
		return COptions::Get()->GetOptionVal(OPTION_ASCIINOEXT) != 0;
	}
	wxString ext = remote_file.Mid(pos + 1);

	for (auto const& ascii_ext : m_ascii_extensions) {
		if (!ext.CmpNoCase(ascii_ext)) {
			return true;
		}
	}

	return false;
}
Beispiel #2
0
wxString CSearchDialogFileList::GetItemText(int item, unsigned int column)
{
    if (item < 0 || item >= (int)m_indexMapping.size())
        return _T("");
    int index = m_indexMapping[item];

    const CDirentry& entry = m_fileData[index].entry;
    if (!column)
        return entry.name;
    else if (column == 1)
        return m_fileData[index].path.GetPath();
    else if (column == 2)
    {
        if (entry.is_dir() || entry.size < 0)
            return _T("");
        else
            return CSizeFormat::Format(entry.size);
    }
    else if (column == 3)
    {
        CSearchFileData& data = m_fileData[index];
        if (data.fileType.IsEmpty())
        {
            if (data.path.GetType() == VMS)
                data.fileType = GetType(StripVMSRevision(entry.name), entry.is_dir());
            else
                data.fileType = GetType(entry.name, entry.is_dir());
        }

        return data.fileType;
    }
    else if (column == 4)
    {
        if (!entry.has_date())
            return _T("");

        if (entry.has_time())
            return CTimeFormat::FormatDateTime(entry.time);
        else
            return CTimeFormat::FormatDate(entry.time);
    }
    else if (column == 5)
        return entry.permissions;
    else if (column == 6)
        return entry.ownerGroup;
    return _T("");
}
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 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();
}
Beispiel #5
0
void CSearchDialog::OnDownload(wxCommandEvent& event)
{
    if (!m_pState->IsRemoteIdle())
        return;

    // Find all selected files and directories
    std::list<CServerPath> selected_dirs;
    std::list<int> selected_files;
    ProcessSelection(selected_files, selected_dirs);

    if (selected_files.empty() && selected_dirs.empty())
        return;

    if (selected_dirs.size() > 1)
    {
        wxMessageBox(_("Downloading multiple unrelated directories is not yet supported"), _("Downloading search results"), wxICON_EXCLAMATION);
        return;
    }

    CSearchDownloadDialog dlg;
    if (!dlg.Run(this, m_local_target.GetPath(), selected_files.size(), selected_dirs.size()))
        return;

    wxTextCtrl *pText = XRCCTRL(dlg, "ID_LOCALPATH", wxTextCtrl);

    CLocalPath path(pText->GetValue());
    if (path.empty() || !path.IsWriteable())
    {
        wxBell();
        return;
    }
    m_local_target = path;

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

    bool start = XRCCTRL(dlg, "ID_QUEUE_START", wxRadioButton)->GetValue();
    bool flatten = XRCCTRL(dlg, "ID_PATHS_FLATTEN", wxRadioButton)->GetValue();

    for (std::list<int>::const_iterator iter = selected_files.begin(); iter != selected_files.end(); ++iter)
    {
        const CDirentry& entry = m_results->m_fileData[*iter].entry;

        CLocalPath target_path = path;
        if (!flatten)
        {
            // Append relative path to search root to local target path
            CServerPath remote_path = m_results->m_fileData[*iter].path;
            std::list<wxString> segments;
            while (m_search_root.IsParentOf(remote_path, false) && remote_path.HasParent())
            {
                segments.push_front(remote_path.GetLastSegment());
                remote_path = remote_path.GetParent();
            }
            for (std::list<wxString>::const_iterator segment_iter = segments.begin(); segment_iter != segments.end(); ++segment_iter)
                target_path.AddSegment(*segment_iter);
        }

        CServerPath remote_path = m_results->m_fileData[*iter].path;
        wxString localName = CQueueView::ReplaceInvalidCharacters(entry.name);
        if (!entry.is_dir() && remote_path.GetType() == VMS && COptions::Get()->GetOptionVal(OPTION_STRIP_VMS_REVISION))
            localName = StripVMSRevision(localName);

        m_pQueue->QueueFile(!start, true,
                            entry.name, (localName != entry.name) ? localName : wxString(),
                            target_path, remote_path, *pServer, entry.size);
    }
    m_pQueue->QueueFile_Finish(start);

    enum CRecursiveOperation::OperationMode mode;
    if (flatten)
        mode = start ? CRecursiveOperation::recursive_download_flatten : CRecursiveOperation::recursive_addtoqueue_flatten;
    else
        mode = start ? CRecursiveOperation::recursive_download : CRecursiveOperation::recursive_addtoqueue;

    for (std::list<CServerPath>::const_iterator iter = selected_dirs.begin(); iter != selected_dirs.end(); ++iter)
    {
        CLocalPath target_path = path;
        if (!flatten && iter->HasParent())
            target_path.AddSegment(iter->GetLastSegment());

        m_pState->GetRecursiveOperationHandler()->AddDirectoryToVisit(*iter, _T(""), target_path, false);
        std::list<CFilter> filters; // Empty, recurse into everything
        m_pState->GetRecursiveOperationHandler()->StartRecursiveOperation(mode, *iter, filters, true, m_original_dir);
    }
}