Пример #1
0
CLocalPath CLocalPath::GetParent(wxString* last_segment /*=0*/) const
{
	CLocalPath parent;

#ifdef __WXMSW__
	if (m_path.Len() == 3 && m_path[0] != '\\') // Drive root
	{
		if (last_segment)
			last_segment->clear();
		return CLocalPath(_T("\\"));
	}

	// C:\f\ has parent
	// C:\ does not
	// \\x\y\ shortest UNC
	//   ^ min
	const int min = 2;
#else
	const int min = 0;
#endif
	for (int i = (int)m_path.Len() - 2; i >= min; i--)
	{
		if (m_path[i] == path_separator)
		{
			if (last_segment)
			{
				*last_segment = m_path.Mid(i + 1);
				last_segment->RemoveLast();
			}
			return CLocalPath(m_path.Left(i + 1));
		}
	}

	return CLocalPath();
}
Пример #2
0
CLocalPath CLocalPath::GetParent(std::wstring* last_segment) const
{
	CLocalPath parent;

#ifdef FZ_WINDOWS
	if (m_path->size() == 3 && (*m_path)[0] != '\\') {
		// Drive root
		if (last_segment) {
			last_segment->clear();
		}
		return CLocalPath(L"\\");
	}

	// C:\f\ has parent
	// C:\ does not
	// \\x\y\ shortest UNC
	//   ^ min
	const int min = 2;
#else
	const int min = 0;
#endif
	for (int i = (int)m_path->size() - 2; i >= min; --i) {
		if ((*m_path)[i] == path_separator) {
			if (last_segment) {
				*last_segment = m_path->substr(i + 1, m_path->size() - i - 2);
			}
			return CLocalPath(m_path->substr(0, i + 1));
		}
	}

	return CLocalPath();
}
Пример #3
0
CLocalPath GetDownloadDir()
{
#ifdef __WXMSW__
	// Old Vista has a profile directory for downloaded files,
	// need to get it using SHGetKnownFolderPath which we need to
	// load dynamically to preserve forward compatibility with the
	// upgrade to Windows XP.
	wxDynamicLibrary lib(_T("shell32.dll"));
	if (lib.IsLoaded() && lib.HasSymbol(_T("SHGetKnownFolderPath"))) {
		tSHGetKnownFolderPath pSHGetKnownFolderPath = (tSHGetKnownFolderPath)lib.GetSymbol(_T("SHGetKnownFolderPath"));

		PWSTR path;
		HRESULT result = pSHGetKnownFolderPath(VISTASHIT_FOLDERID_Downloads, 0, 0, &path);
		if(result == S_OK) {
			wxString dir = path;
			CoTaskMemFree(path);
			return CLocalPath(dir);
		}
	}
#elif !defined(__WXMAC__)
	// Code copied from wx, but for downloads directory.
	// Also, directory is now unescaped.
	{
		wxLogNull logNull;
		wxString homeDir = wxFileName::GetHomeDir();
		wxString configPath;
		if (wxGetenv(wxT("XDG_CONFIG_HOME")))
			configPath = wxGetenv(wxT("XDG_CONFIG_HOME"));
		else
			configPath = homeDir + wxT("/.config");
		wxString dirsFile = configPath + wxT("/user-dirs.dirs");
		if (wxFileExists(dirsFile)) {
			wxTextFile textFile;
			if (textFile.Open(dirsFile)) {
				size_t i;
				for (i = 0; i < textFile.GetLineCount(); i++) {
					wxString line(textFile[i]);
					int pos = line.Find(wxT("XDG_DOWNLOAD_DIR"));
					if (pos != wxNOT_FOUND) {
						wxString value = line.AfterFirst(wxT('='));
						value = ShellUnescape(value);
						if (!value.IsEmpty() && wxDirExists(value))
							return CLocalPath(value);
						else
							break;
					}
				}
			}
		}
	}
#endif
	return CLocalPath(wxStandardPaths::Get().GetDocumentsDir());
}
Пример #4
0
CLocalPath GetDownloadDir()
{
#ifdef __WXMSW__
	// Unfortunately MinGW's import library lacks SHGetKnownFolderPath, even though it has it in its headers.
	wxDynamicLibrary lib(_T("shell32.dll"));
	if (lib.IsLoaded() && lib.HasSymbol(_T("SHGetKnownFolderPath"))) {
		tSHGetKnownFolderPath pSHGetKnownFolderPath = (tSHGetKnownFolderPath)lib.GetSymbol(_T("SHGetKnownFolderPath"));

		PWSTR path;
		HRESULT result = pSHGetKnownFolderPath(FOLDERID_Downloads, 0, 0, &path);
		if(result == S_OK) {
			std::wstring dir = path;
			CoTaskMemFree(path);
			return CLocalPath(dir);
		}
	}
#elif !defined(__WXMAC__)
	// Code copied from wx, but for downloads directory.
	// Also, directory is now unescaped.
	{
		wxLogNull logNull;
		wxString homeDir = wxFileName::GetHomeDir();
		wxString configPath;
		if (wxGetenv(wxT("XDG_CONFIG_HOME"))) {
			configPath = wxGetenv(wxT("XDG_CONFIG_HOME"));
		}
		else {
			configPath = homeDir + wxT("/.config");
		}
		wxString dirsFile = configPath + wxT("/user-dirs.dirs");
		if (wxFileExists(dirsFile)) {
			wxTextFile textFile;
			if (textFile.Open(dirsFile)) {
				size_t i;
				for (i = 0; i < textFile.GetLineCount(); i++) {
					wxString line(textFile[i]);
					int pos = line.Find(wxT("XDG_DOWNLOAD_DIR"));
					if (pos != wxNOT_FOUND) {
						wxString value = line.AfterFirst(wxT('='));
						value = ShellUnescape(value);
						if (!value.empty() && wxDirExists(value))
							return CLocalPath(value.ToStdWstring());
						else
							break;
					}
				}
			}
		}
	}
#endif
	return CLocalPath(wxStandardPaths::Get().GetDocumentsDir().ToStdWstring());
}
Пример #5
0
void CLocalTreeView::OnMenuUpload(wxCommandEvent& event)
{
	if (!m_contextMenuItem.IsOk())
		return;

	wxString path = GetDirFromItem(m_contextMenuItem);

	if (!CLocalPath(path).HasParent())
		return;

	if (!m_pState->IsRemoteConnected())
		return;

	const CServer server = *m_pState->GetServer();
	CServerPath remotePath = m_pState->GetRemotePath();
	if (remotePath.IsEmpty())
		return;

	if (!remotePath.ChangePath(GetItemText(m_contextMenuItem)))
		return;

	if (path.Last() == wxFileName::GetPathSeparator())
		path.RemoveLast();
	m_pQueueView->QueueFolder(event.GetId() == XRCID("ID_ADDTOQUEUE"), false, path, remotePath, server);
}
Пример #6
0
void CLocalListView::OnMenuUpload(wxCommandEvent& event)
{
	const CServer* pServer = m_pState->GetServer();
	if (!pServer)
	{
		wxBell();
		return;
	}

	bool added = false;

	bool queue_only = event.GetId() == XRCID("ID_ADDTOQUEUE");

	long item = -1;
	for (;;)
	{
		item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
		if (!item && m_hasParent)
			continue;
		if (item == -1)
			break;

		const CLocalFileData *data = GetData(item);
		if (!data)
			break;

		if (data->flags == fill)
			continue;

		CServerPath path = m_pState->GetRemotePath();
		if (path.IsEmpty())
		{
			wxBell();
			break;
		}

		if (data->dir)
		{
			path.ChangePath(data->name);

			CLocalPath localPath(m_dir);
			localPath.AddSegment(data->name);
			m_pQueue->QueueFolder(event.GetId() == XRCID("ID_ADDTOQUEUE"), false, localPath, path, *pServer);
		}
		else
		{
			m_pQueue->QueueFile(queue_only, false, data->name, wxEmptyString, CLocalPath(m_dir), path, *pServer, data->size);
			added = true;
		}
	}
	if (added)
		m_pQueue->QueueFile_Finish(!queue_only);
}
Пример #7
0
	virtual bool OnDrop(wxCoord x, wxCoord y)
	{
		ClearDropHighlight();

		wxTreeItemId hit = GetHit(wxPoint(x, y));
		if (!hit)
			return false;

		const wxString dir = GetDirFromItem(hit);
		if (dir == _T("") || !CLocalPath(dir).IsWriteable())
			return false;

		return true;
	}
Пример #8
0
CLocalPath CUpdateWizard::GetDownloadDir() const
{
#ifdef __WXMSW__
	// Old Vista has a profile directory for downloaded files,
	// need to get it using SHGetKnownFolderPath which we need to
	// load dynamically to preserve forward compatibility with the
	// upgrade to Windows XP.
	wxDynamicLibrary lib(_T("shell32.dll"));
	if (lib.IsLoaded() && lib.HasSymbol(_T("SHGetKnownFolderPath")))
	{
		tSHGetKnownFolderPath pSHGetKnownFolderPath = (tSHGetKnownFolderPath)lib.GetSymbol(_T("SHGetKnownFolderPath"));

		PWSTR path;
		HRESULT result = pSHGetKnownFolderPath(VISTASHIT_FOLDERID_Downloads, 0, 0, &path);
		if (result == S_OK)
		{
			wxString dir = path;
			CoTaskMemFree(path);
			return CLocalPath(dir);
		}
	}
#endif
	return CLocalPath(wxStandardPaths::Get().GetDocumentsDir());
}
CLocalPath CState::GetSynchronizedDirectory(CServerPath remote_path)
{
	std::list<wxString> segments;
	while (remote_path.HasParent() && remote_path != m_sync_browse.remote_root)
	{
		segments.push_front(remote_path.GetLastSegment());
		remote_path = remote_path.GetParent();
	}
	if (remote_path != m_sync_browse.remote_root)
		return CLocalPath();

	CLocalPath local_path = m_sync_browse.local_root;
	for (std::list<wxString>::const_iterator iter = segments.begin(); iter != segments.end(); ++iter)
		local_path.AddSegment(*iter);

	return local_path;
}
Пример #10
0
void CLocalTreeView::OnMenuMkdir(wxCommandEvent& event)
{
	if (!m_contextMenuItem.IsOk())
		return;

	wxString path = GetDirFromItem(m_contextMenuItem);
	if (path.Last() != wxFileName::GetPathSeparator())
		path += wxFileName::GetPathSeparator();

	if (!CLocalPath(path).IsWriteable())
	{
		wxBell();
		return;
	}

	CInputDialog dlg;
	if (!dlg.Create(this, _("Create directory"), _("Please enter the name of the directory which should be created:")))
		return;

	wxString newName = _("New directory");
	dlg.SetValue(path + newName);
	dlg.SelectText(path.Len(), path.Len() + newName.Len());

	if (dlg.ShowModal() != wxID_OK)
		return;

	wxFileName fn(dlg.GetValue(), _T(""));
	if (!fn.Normalize(wxPATH_NORM_ALL, path))
	{
		wxBell();
		return;
	}

	bool res;
	{
		wxLogNull log;
		res = fn.Mkdir(fn.GetPath(), 0777, wxPATH_MKDIR_FULL);
	}

	if (!res)
		wxBell();

	Refresh();
	m_pState->RefreshLocal();
}
Пример #11
0
	virtual bool OnDrop(wxCoord x, wxCoord y)
	{
		if (!CScrollableDropTarget<wxTreeCtrlEx>::OnDrop(x, y)) {
			return false;
		}

		ClearDropHighlight();

		wxTreeItemId hit = GetHit(wxPoint(x, y));
		if (!hit)
			return false;

		const wxString dir = GetDirFromItem(hit);
		if (dir.empty() || !CLocalPath(dir).IsWriteable())
			return false;

		return true;
	}
Пример #12
0
CLocalPath COptions::GetUnadjustedSettingsDir()
{
	wxFileName fn;
#ifdef __WXMSW__
	wxChar buffer[MAX_PATH * 2 + 1];

	if (SUCCEEDED(SHGetFolderPath(0, CSIDL_APPDATA, 0, SHGFP_TYPE_CURRENT, buffer))) {
		fn = wxFileName(buffer, _T(""));
		fn.AppendDir(_T("FileZilla"));
	}
	else {
		// Fall back to directory where the executable is
		if (GetModuleFileName(0, buffer, MAX_PATH * 2))
			fn = buffer;
	}
#else
	wxString cfg = TryDirectory(GetEnv(_T("XDG_CONFIG_HOME")), _T("filezilla/"), true);
	if( cfg.empty() ) {
		cfg = TryDirectory(wxGetHomeDir(), _T(".config/filezilla/"), true);
	}
	if( cfg.empty() ) {
		cfg = TryDirectory(wxGetHomeDir(), _T(".filezilla/"), true);
	}
	if( cfg.empty() ) {
		cfg = TryDirectory(GetEnv(_T("XDG_CONFIG_HOME")), _T("filezilla/"), false);
	}
	if( cfg.empty() ) {
		cfg = TryDirectory(wxGetHomeDir(), _T(".config/filezilla/"), false);
	}
	if( cfg.empty() ) {
		cfg = TryDirectory(wxGetHomeDir(), _T(".filezilla/"), false);
	}
	fn = wxFileName(cfg, _T(""));
#endif
	return CLocalPath(fn.GetPath());
}
Пример #13
0
bool CLocalListView::DisplayDir(wxString dirname)
{
	CancelLabelEdit();

	wxString focused;
	std::list<wxString> selectedNames;
	bool ensureVisible = false;
	if (m_dir != dirname)
	{
		ResetSearchPrefix();

		if (IsComparing())
			ExitComparisonMode();

		ClearSelection();
		focused = m_pState->GetPreviouslyVisitedLocalSubdir();
		ensureVisible = !focused.IsEmpty();
		if (focused.IsEmpty())
			focused = _T("..");

		if (GetItemCount())
			EnsureVisible(0);
		m_dir = dirname;
	}
	else
	{
		// Remember which items were selected
		selectedNames = RememberSelectedItems(focused);
	}

	if (m_pFilelistStatusBar)
		m_pFilelistStatusBar->UnselectAll();

	const int oldItemCount = m_indexMapping.size();

	m_fileData.clear();
	m_indexMapping.clear();

	m_hasParent = CLocalPath(dirname).HasLogicalParent();

	if (m_hasParent)
	{
		CLocalFileData data;
		data.flags = normal;
		data.dir = true;
		data.icon = -2;
		data.name = _T("..");
#ifdef __WXMSW__
		data.label = _T("..");
#endif
		data.size = -1;
		m_fileData.push_back(data);
		m_indexMapping.push_back(0);
	}

#ifdef __WXMSW__
	if (dirname == _T("\\"))
	{
		DisplayDrives();
	}
	else if (dirname.Left(2) == _T("\\\\"))
	{
		int pos = dirname.Mid(2).Find('\\');
		if (pos != -1 && pos + 3 != (int)dirname.Len())
			goto regular_dir;

		// UNC path without shares
		DisplayShares(dirname);
	}
	else
#endif
	{
#ifdef __WXMSW__
regular_dir:
#endif
		CFilterManager filter;
		CLocalFileSystem local_filesystem;

		if (!local_filesystem.BeginFindFiles(dirname, false))
		{
			SetItemCount(1);
			return false;
		}

		wxLongLong totalSize;
		int unknown_sizes = 0;
		int totalFileCount = 0;
		int totalDirCount = 0;
		int hidden = 0;

		int num = m_fileData.size();
		CLocalFileData data;
		data.flags = normal;
		data.icon = -2;
		bool wasLink;
		while (local_filesystem.GetNextFile(data.name, wasLink, data.dir, &data.size, &data.lastModified, &data.attributes))
		{
			if (data.name.IsEmpty())
			{
				wxGetApp().DisplayEncodingWarning();
				continue;
			}
#ifdef __WXMSW__
			data.label = data.name;
#endif

			m_fileData.push_back(data);
			if (!filter.FilenameFiltered(data.name, dirname, data.dir, data.size, true, data.attributes, data.lastModified))
			{
				if (data.dir)
					totalDirCount++;
				else
				{
					if (data.size != -1)
						totalSize += data.size;
					else
						unknown_sizes++;
					totalFileCount++;
				}
				m_indexMapping.push_back(num);
			}
			else
				hidden++;
			num++;
		}

		if (m_pFilelistStatusBar)
			m_pFilelistStatusBar->SetDirectoryContents(totalFileCount, totalDirCount, totalSize, unknown_sizes, hidden);
	}

	if (m_dropTarget != -1)
	{
		CLocalFileData* data = GetData(m_dropTarget);
		if (!data || !data->dir)
		{
			SetItemState(m_dropTarget, 0, wxLIST_STATE_DROPHILITED);
			m_dropTarget = -1;
		}
	}

	const int count = m_indexMapping.size();
	if (oldItemCount != count)
		SetItemCount(count);

	SortList(-1, -1, false);

	if (IsComparing())
	{
		m_originalIndexMapping.clear();
		RefreshComparison();
	}

	ReselectItems(selectedNames, focused, ensureVisible);

	RefreshListOnly();

	return true;
}
Пример #14
0
CFolderItem::CFolderItem(CServerItem* parent, bool queued, const CServerPath& remotePath, const wxString& remoteFile)
	: CFileItem(parent, queued, false, _T(""), remoteFile, CLocalPath(), remotePath, -1)
{
}
Пример #15
0
void CState::HandleDroppedFiles(const wxFileDataObject* pFileDataObject, const CLocalPath& path, bool copy)
{
	const wxArrayString &files = pFileDataObject->GetFilenames();
	if (!files.Count())
		return;

#ifdef __WXMSW__
	int len = 1;

	for (unsigned int i = 0; i < files.Count(); i++)
		len += files[i].Len() + 1;

	// SHFILEOPSTRUCT's pTo and pFrom accept null-terminated lists
	// of null-terminated filenames.
	wxChar* from = new wxChar[len];
	wxChar* p = from;
	for (unsigned int i = 0; i < files.Count(); i++)
	{
		wxStrcpy(p, files[i]);
		p += files[i].Len() + 1;
	}
	*p = 0; // End of list

	wxChar* to = new wxChar[path.GetPath().Len() + 2];
	wxStrcpy(to, path.GetPath());
	to[path.GetPath().Len() + 1] = 0; // End of list

	SHFILEOPSTRUCT op = {0};
	op.pFrom = from;
	op.pTo = to;
	op.wFunc = copy ? FO_COPY : FO_MOVE;
	op.hwnd = (HWND)m_pMainFrame->GetHandle();
	SHFileOperation(&op);

	delete [] to;
	delete [] from;
#else
	for (unsigned int i = 0; i < files.Count(); i++)
	{
		const wxString& file(files[i]);

		wxLongLong size;
		bool is_link;
		CLocalFileSystem::local_fileType type = CLocalFileSystem::GetFileInfo(file, is_link, &size, 0, 0);
		if (type == CLocalFileSystem::file)
		{
			wxString name;
			CLocalPath sourcePath(file, &name);
			if (name.empty())
				continue;
			if (copy)
				wxCopyFile(file, path.GetPath() + name);
			else
				wxRenameFile(file, path.GetPath() + name);
		}
		else if (type == CLocalFileSystem::dir)
		{
			if (copy)
				RecursiveCopy(CLocalPath(file), path);
			else
			{
				CLocalPath sourcePath(file);
				if (!sourcePath.HasParent())
					continue;
				wxRenameFile(file, path.GetPath() + sourcePath.GetLastSegment());
			}
		}
	}
#endif

	RefreshLocal();
}
Пример #16
0
CFolderItem::CFolderItem(CServerItem* parent, bool queued, CServerPath const& remotePath, std::wstring const& remoteFile)
    : CFileItem(parent, queued, false, std::wstring(), remoteFile, CLocalPath(), remotePath, -1)
{
}
Пример #17
0
void CLocalListView::OnItemActivated(wxListEvent &event)
{
	int count = 0;
	bool back = false;

	int item = -1;
	for (;;)
	{
		item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
		if (item == -1)
			break;

		count++;

		if (!item && m_hasParent)
			back = true;
	}
	if (count > 1)
	{
		if (back)
		{
			wxBell();
			return;
		}

		wxCommandEvent cmdEvent;
		OnMenuUpload(cmdEvent);
		return;
	}

	item = event.GetIndex();

	CLocalFileData *data = GetData(item);
	if (!data)
		return;

	if (data->dir)
	{
		const int action = COptions::Get()->GetOptionVal(OPTION_DOUBLECLICK_ACTION_DIRECTORY);
		if (action == 3)
		{
			// No action
			wxBell();
			return;
		}

		if (!action || data->name == _T(".."))
		{
			// Enter action

			wxString error;
			if (!m_pState->SetLocalDir(data->name, &error))
			{
				if (error != _T(""))
					wxMessageBoxEx(error, _("Failed to change directory"), wxICON_INFORMATION);
				else
					wxBell();
			}
			return;
		}

		wxCommandEvent evt(0, action == 1 ? XRCID("ID_UPLOAD") : XRCID("ID_ADDTOQUEUE"));
		OnMenuUpload(evt);
		return;
	}

	if (data->flags == fill)
	{
		wxBell();
		return;
	}

	const int action = COptions::Get()->GetOptionVal(OPTION_DOUBLECLICK_ACTION_FILE);
	if (action == 3)
	{
		// No action
		wxBell();
		return;
	}

	if (action == 2)
	{
		// View / Edit action
		wxCommandEvent evt;
		OnMenuEdit(evt);
		return;
	}

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

	CServerPath path = m_pState->GetRemotePath();
	if (path.IsEmpty())
	{
		wxBell();
		return;
	}

	const bool queue_only = action == 1;

	m_pQueue->QueueFile(queue_only, false, data->name, wxEmptyString, CLocalPath(m_dir), path, *pServer, data->size);
	m_pQueue->QueueFile_Finish(true);
}
Пример #18
0
void CRemoteTreeView::OnMenuChmod(wxCommandEvent&)
{
	if (!m_pState->IsRemoteIdle())
		return;

	if (!m_contextMenuItem)
		return;

	const CServerPath& path = GetPathFromItem(m_contextMenuItem);
	if (path.empty())
		return;

	const bool hasParent = path.HasParent();

	CChmodDialog* pChmodDlg = new CChmodDialog;

	// Get current permissions of directory
	const wxString& name = GetItemText(m_contextMenuItem);
	char permissions[9] = {0};
	bool cached = false;

	// Obviously item needs to have a parent directory...
	if (hasParent)
	{
		const CServerPath& parentPath = path.GetParent();
		CDirectoryListing listing;

		// ... and it needs to be cached
		cached = m_pState->m_pEngine->CacheLookup(parentPath, listing) == FZ_REPLY_OK;
		if (cached)
		{
			for (unsigned int i = 0; i < listing.GetCount(); i++)
			{
				if (listing[i].name != name)
					continue;

				pChmodDlg->ConvertPermissions(*listing[i].permissions, permissions);
			}
		}
	}

	if (!pChmodDlg->Create(this, 0, 1, name, permissions))
	{
		pChmodDlg->Destroy();
		pChmodDlg = 0;
		return;
	}

	if (pChmodDlg->ShowModal() != wxID_OK)
	{
		pChmodDlg->Destroy();
		pChmodDlg = 0;
		return;
	}

	// State may have changed while chmod dialog was shown
	if (!m_contextMenuItem || !m_pState->IsRemoteConnected() || !m_pState->IsRemoteIdle())
	{
		pChmodDlg->Destroy();
		pChmodDlg = 0;
		return;
	}

	const int applyType = pChmodDlg->GetApplyType();

	CRecursiveOperation* pRecursiveOperation = m_pState->GetRecursiveOperationHandler();

	if (cached) // Implies hasParent
	{
		// Change directory permissions
		if (!applyType || applyType == 2)
		{
			wxString newPerms = pChmodDlg->GetPermissions(permissions, true);

			m_pState->m_pCommandQueue->ProcessCommand(new CChmodCommand(path.GetParent(), name, newPerms));
		}

		if (pChmodDlg->Recursive())
			// Start recursion
			pRecursiveOperation->AddDirectoryToVisit(path, _T(""), CLocalPath());
	}
	else
	{
		if (hasParent)
			pRecursiveOperation->AddDirectoryToVisitRestricted(path.GetParent(), name, pChmodDlg->Recursive());
		else
			pRecursiveOperation->AddDirectoryToVisitRestricted(path, _T(""), pChmodDlg->Recursive());
	}

	if (!cached || pChmodDlg->Recursive())
	{
		pRecursiveOperation->SetChmodDialog(pChmodDlg);

		CServerPath currentPath;
		const wxTreeItemId selected = GetSelection();
		if (selected)
			currentPath = GetPathFromItem(selected);
		CFilterManager filter;
		pRecursiveOperation->StartRecursiveOperation(CRecursiveOperation::recursive_chmod, hasParent ? path.GetParent() : path, filter.GetActiveFilters(false), !cached, currentPath);
	}
	else
	{
		pChmodDlg->Destroy();
		const wxTreeItemId selected = GetSelection();
		if (selected)
		{
			CServerPath currentPath = GetPathFromItem(selected);
			m_pState->ChangeRemoteDir(currentPath);
		}
	}
}