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(); }
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(); }
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()); }
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()); }
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); }
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); }
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; }
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; }
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(); }
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; }
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()); }
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; }
CFolderItem::CFolderItem(CServerItem* parent, bool queued, const CServerPath& remotePath, const wxString& remoteFile) : CFileItem(parent, queued, false, _T(""), remoteFile, CLocalPath(), remotePath, -1) { }
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(); }
CFolderItem::CFolderItem(CServerItem* parent, bool queued, CServerPath const& remotePath, std::wstring const& remoteFile) : CFileItem(parent, queued, false, std::wstring(), remoteFile, CLocalPath(), remotePath, -1) { }
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); }
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); } } }