void COptions::LoadGlobalDefaultOptions(std::map<std::string, unsigned int> const& nameOptionMap) { CLocalPath const defaultsDir = wxGetApp().GetDefaultsDir(); if (defaultsDir.empty()) { return; } CXmlFile file(defaultsDir.GetPath() + _T("fzdefaults.xml")); if (!file.Load()) { return; } auto element = file.GetElement(); if (!element) { return; } element = element.child("Settings"); if (!element) { return; } for (auto setting = element.child("Setting"); setting; setting = setting.next_sibling("Setting")) { LoadOptionFromElement(setting, nameOptionMap, true); } }
void CRemoteTreeView::OnMenuDownload(wxCommandEvent& event) { CLocalPath localDir = m_pState->GetLocalDir(); if (!localDir.IsWriteable()) { wxBell(); return; } if (!m_pState->IsRemoteIdle()) return; if (!m_contextMenuItem) return; const CServerPath& path = GetPathFromItem(m_contextMenuItem); if (path.empty()) return; const wxString& name = GetItemText(m_contextMenuItem); localDir.AddSegment(CQueueView::ReplaceInvalidCharacters(name)); CRecursiveOperation* pRecursiveOperation = m_pState->GetRecursiveOperationHandler(); pRecursiveOperation->AddDirectoryToVisit(path, _T(""), localDir); CServerPath currentPath; const wxTreeItemId selected = GetSelection(); if (selected) currentPath = GetPathFromItem(selected); const bool addOnly = event.GetId() == XRCID("ID_ADDTOQUEUE"); CFilterManager filter; pRecursiveOperation->StartRecursiveOperation(addOnly ? CRecursiveOperation::recursive_addtoqueue : CRecursiveOperation::recursive_download, path, filter.GetActiveFilters(false), true, currentPath); }
COptions::COptions() { m_theOptions = this; m_pXmlFile = 0; m_pLastServer = 0; SetDefaultValues(); m_save_timer.SetOwner(this); auto const nameOptionMap = GetNameOptionMap(); LoadGlobalDefaultOptions(nameOptionMap); CLocalPath const dir = InitSettingsDir(); CInterProcessMutex mutex(MUTEX_OPTIONS); m_pXmlFile = new CXmlFile(dir.GetPath() + _T("filezilla.xml")); if (!m_pXmlFile->Load()) { wxString msg = m_pXmlFile->GetError() + _T("\n\n") + _("For this session the default settings will be used. Any changes to the settings will not be saved."); wxMessageBoxEx(msg, _("Error loading xml file"), wxICON_ERROR); delete m_pXmlFile; m_pXmlFile = 0; } else CreateSettingsXmlElement(); LoadOptions(nameOptionMap); }
bool CState::RecursiveCopy(CLocalPath source, const CLocalPath& target) { if (source.empty() || target.empty()) return false; if (source == target) return false; if (source.IsParentOf(target)) return false; if (!source.HasParent()) return false; wxString last_segment; if (!source.MakeParent(&last_segment)) return false; std::list<wxString> dirsToVisit; dirsToVisit.push_back(last_segment + CLocalPath::path_separator); // Process any subdirs which still have to be visited while (!dirsToVisit.empty()) { wxString dirname = dirsToVisit.front(); dirsToVisit.pop_front(); wxMkdir(target.GetPath() + dirname); CLocalFileSystem fs; if (!fs.BeginFindFiles(source.GetPath() + dirname, false)) continue; bool is_dir, is_link; wxString file; while (fs.GetNextFile(file, is_link, is_dir, 0, 0, 0)) { if (file.empty()) { wxGetApp().DisplayEncodingWarning(); continue; } if (is_dir) { if (is_link) continue; const wxString subDir = dirname + file + CLocalPath::path_separator; dirsToVisit.push_back(subDir); } else wxCopyFile(source.GetPath() + dirname + file, target.GetPath() + dirname + file); } } return true; }
CServerPath CState::GetSynchronizedDirectory(CLocalPath local_path) { std::list<wxString> segments; while (local_path.HasParent() && local_path != m_sync_browse.local_root) { wxString last; local_path.MakeParent(&last); segments.push_front(last); } if (local_path != m_sync_browse.local_root) return CServerPath(); CServerPath remote_path = m_sync_browse.remote_root; for (std::list<wxString>::const_iterator iter = segments.begin(); iter != segments.end(); ++iter) remote_path.AddSegment(*iter); return remote_path; }
CLocalPath COptions::GetUnadjustedSettingsDir() { CLocalPath ret; #ifdef FZ_WINDOWS wchar_t buffer[MAX_PATH * 2 + 1]; if (SUCCEEDED(SHGetFolderPath(0, CSIDL_APPDATA, 0, SHGFP_TYPE_CURRENT, buffer))) { CLocalPath tmp(buffer); if (!tmp.empty()) { tmp.AddSegment(L"FileZilla"); } ret = tmp; } else { // Fall back to directory where the executable is DWORD c = GetModuleFileName(0, buffer, MAX_PATH * 2); if (c && c < MAX_PATH * 2) { std::wstring tmp; ret.SetPath(buffer, &tmp); } } #else std::wstring 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); } ret.SetPath(cfg); #endif return ret; }
void CState::LocalDirCreated(const CLocalPath& path) { if (!path.IsSubdirOf(m_localDir)) return; wxString next_segment = path.GetPath().Mid(m_localDir.GetPath().Len()); int pos = next_segment.Find(CLocalPath::path_separator); if (pos <= 0) { // Shouldn't ever come true return; } // Current local path is /foo/ // Called with /foo/bar/baz/ // -> Refresh /foo/bar/ next_segment = next_segment.Left(pos); NotifyHandlers(STATECHANGE_LOCAL_REFRESH_FILE, next_segment); }
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(); }
virtual wxDragResult OnDragOver(wxCoord x, wxCoord y, wxDragResult def) { CListCtrlDropTarget::OnDragOver(x, y, def); if (def == wxDragError || def == wxDragNone || def == wxDragCancel) { ClearDropHighlight(); return def; } if (m_pLocalListView->m_fileData.empty()) { ClearDropHighlight(); return wxDragNone; } const wxString& subdir = DoDisplayDropHighlight(wxPoint(x, y)); CLocalPath dir = m_pLocalListView->m_pState->GetLocalDir(); if (subdir == _T("")) { const CDragDropManager* pDragDropManager = CDragDropManager::Get(); if (pDragDropManager && pDragDropManager->localParent == m_pLocalListView->m_dir) return wxDragNone; } else { if (!dir.ChangePath(subdir)) return wxDragNone; } if (!dir.IsWriteable()) return wxDragNone; if (def == wxDragLink) def = wxDragCopy; return def; }
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(); }
void COptions::LoadGlobalDefaultOptions(std::map<std::string, unsigned int> const& nameOptionMap) { CLocalPath const defaultsDir = wxGetApp().GetDefaultsDir(); if (defaultsDir.empty()) return; CXmlFile file(defaultsDir.GetPath() + _T("fzdefaults.xml")); if (!file.Load()) return; TiXmlElement* pElement = file.GetElement(); if (!pElement) return; pElement = pElement->FirstChildElement("Settings"); if (!pElement) return; for (TiXmlElement* pSetting = pElement->FirstChildElement("Setting"); pSetting; pSetting = pSetting->NextSiblingElement("Setting")) { LoadOptionFromElement(pSetting, nameOptionMap, true); } }
void CQueueStorage::Impl::ReadLocalPaths() { if (!selectLocalPathQuery_) return; int res; do { res = sqlite3_step(selectLocalPathQuery_); if (res == SQLITE_ROW) { int64_t id = GetColumnInt64(selectLocalPathQuery_, path_table_column_names::id); wxString localPathRaw = GetColumnText(selectLocalPathQuery_, path_table_column_names::path); CLocalPath localPath; if (id > 0 && !localPathRaw.empty() && localPath.SetPath(localPathRaw)) reverseLocalPaths_[id] = localPath; } } while (res == SQLITE_BUSY || res == SQLITE_ROW); sqlite3_reset(selectLocalPathQuery_); }
int64_t CQueueStorage::Impl::SaveLocalPath(const CLocalPath& path) { std::unordered_map<wxString, int64_t, wxStringHash, fast_equal>::const_iterator it = localPaths_.find(path.GetPath()); if (it != localPaths_.end()) return it->second; Bind(insertLocalPathQuery_, path_table_column_names::path, path.GetPath()); int res; do { res = sqlite3_step(insertLocalPathQuery_); } while (res == SQLITE_BUSY); sqlite3_reset(insertLocalPathQuery_); if (res == SQLITE_DONE) { int64_t id = sqlite3_last_insert_rowid(db_); localPaths_[path.GetPath()] = id; return id; } return -1; }
bool CLocalPath::IsSubdirOf(const CLocalPath &path) const { if (empty() || path.empty()) return false; if (path.m_path->size() > m_path->size()) return false; #ifdef FZ_WINDOWS if (fz::stricmp(*path.m_path, m_path->substr(0, path.m_path->size()))) return false; #else if (*path.m_path != m_path->substr(0, path.m_path->size())) return false; #endif return true; }
bool CLocalPath::IsSubdirOf(const CLocalPath &path) const { if (empty() || path.empty()) return false; if (path.m_path.Len() > m_path.Len()) return false; #ifdef __WXMSW__ if (path.m_path.CmpNoCase(m_path.Left(path.m_path.Len()))) return false; #else if (path.m_path != m_path.Left(path.m_path.Len())) return false; #endif return true; }
bool CLocalPath::IsParentOf(const CLocalPath &path) const { if (empty() || path.empty()) return false; if (path.m_path->Len() < m_path->Len()) return false; #ifdef __WXMSW__ if (m_path->CmpNoCase(path.m_path->Left(m_path->Len()))) return false; #else if (*m_path != path.m_path->Left(m_path->Len())) return false; #endif return true; }
bool CLocalPath::IsParentOf(const CLocalPath &path) const { if (empty() || path.empty()) { return false; } if (path.m_path->size() < m_path->size()) { return false; } #ifdef FZ_WINDOWS if (fz::stricmp(*m_path, path.m_path->substr(0, m_path->size()))) return false; #else if (*m_path != path.m_path->substr(0, m_path->size())) return false; #endif return true; }
CLocalPath COptions::InitSettingsDir() { CLocalPath p; std::wstring dir = GetOption(OPTION_DEFAULT_SETTINGSDIR); if (!dir.empty()) { dir = ExpandPath(dir); p.SetPath(wxGetApp().GetDefaultsDir().GetPath()); p.ChangePath(dir); } else { p = GetUnadjustedSettingsDir(); } if (!p.empty() && !p.Exists()) { wxFileName::Mkdir(p.GetPath(), 0700, wxPATH_MKDIR_FULL); } SetOption(OPTION_DEFAULT_SETTINGSDIR, p.GetPath()); return p; }
CLocalPath COptions::InitSettingsDir() { CLocalPath p; wxString dir(GetOption(OPTION_DEFAULT_SETTINGSDIR)); if (!dir.empty()) { wxStringTokenizer tokenizer(dir, _T("/\\"), wxTOKEN_RET_EMPTY_ALL); dir = _T(""); while (tokenizer.HasMoreTokens()) { wxString token = tokenizer.GetNextToken(); if (!token.empty() && token[0] == '$') { if (token.size() > 1 && token[1] == '$') token = token.Mid(1); else { token = GetEnv(token.Mid(1)); } } dir += token; const wxChar delimiter = tokenizer.GetLastDelimiter(); if (delimiter) dir += delimiter; } p.SetPath(wxGetApp().GetDefaultsDir().GetPath()); p.ChangePath(dir); } else { p = GetUnadjustedSettingsDir(); } if (!p.empty() && !p.Exists()) wxFileName::Mkdir( p.GetPath(), 0700, wxPATH_MKDIR_FULL ); SetOption(OPTION_DEFAULT_SETTINGSDIR, p.GetPath()); return p; }
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(); }
virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def) { if (def == wxDragError || def == wxDragNone || def == wxDragCancel) return def; if (m_pLocalListView->m_fileData.empty()) return wxDragError; if (def != wxDragCopy && def != wxDragMove) return wxDragError; CDragDropManager* pDragDropManager = CDragDropManager::Get(); if (pDragDropManager) pDragDropManager->pDropTarget = m_pLocalListView; wxString subdir; int flags; int hit = m_pLocalListView->HitTest(wxPoint(x, y), flags, 0); if (hit != -1 && (flags & wxLIST_HITTEST_ONITEM)) { const CLocalFileData* const data = m_pLocalListView->GetData(hit); if (data && data->dir) subdir = data->name; } CLocalPath dir = m_pLocalListView->m_pState->GetLocalDir(); if (subdir != _T("")) { if (!dir.ChangePath(subdir)) return wxDragError; } if (!dir.IsWriteable()) return wxDragError; if (!GetData()) return wxDragError; if (m_pDataObject->GetReceivedFormat() == m_pFileDataObject->GetFormat()) m_pLocalListView->m_pState->HandleDroppedFiles(m_pFileDataObject, dir, def == wxDragCopy); else { if (m_pRemoteDataObject->GetProcessId() != (int)wxGetProcessId()) { wxMessageBoxEx(_("Drag&drop between different instances of FileZilla has not been implemented yet.")); return wxDragNone; } if (!m_pLocalListView->m_pState->GetServer() || !m_pRemoteDataObject->GetServer().EqualsNoPass(*m_pLocalListView->m_pState->GetServer())) { wxMessageBoxEx(_("Drag&drop between different servers has not been implemented yet.")); return wxDragNone; } if (!m_pLocalListView->m_pState->DownloadDroppedFiles(m_pRemoteDataObject, dir)) return wxDragNone; } return def; }
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 wxString error; for (unsigned int i = 0; i < files.Count(); i++) { const wxString& file(files[i]); int64_t 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; wxString target = path.GetPath() + name; if (file == target) continue; if (copy) wxCopyFile(file, target); else wxRenameFile(file, target); } else if (type == CLocalFileSystem::dir) { CLocalPath sourcePath(file); if (sourcePath == path || sourcePath.GetParent() == path) continue; if (sourcePath.IsParentOf(path)) { error = _("A directory cannot be dragged into one of its subdirectories."); continue; } if (copy) RecursiveCopy(sourcePath, path); else { if (!sourcePath.HasParent()) continue; wxRenameFile(file, path.GetPath() + sourcePath.GetLastSegment()); } } } if (!error.empty()) wxMessageBoxEx(error, _("Could not complete operation")); #endif RefreshLocal(); }
bool CState::SetLocalDir(CLocalPath const& dir, wxString *error, bool rememberPreviousSubdir) { if (m_sync_browse.is_changing) { wxMessageBoxEx(_T("Cannot change directory, there already is a synchronized browsing operation in progress."), _("Synchronized browsing")); return false; } if (!dir.Exists(error)) return false; if (!m_sync_browse.local_root.empty()) { wxASSERT(m_pServer); if (dir != m_sync_browse.local_root && !dir.IsSubdirOf(m_sync_browse.local_root)) { wxString msg = wxString::Format(_("The local directory '%s' is not below the synchronization root (%s).\nDisable synchronized browsing and continue changing the local directory?"), dir.GetPath(), m_sync_browse.local_root.GetPath()); if (wxMessageBoxEx(msg, _("Synchronized browsing"), wxICON_QUESTION | wxYES_NO) != wxYES) return false; SetSyncBrowse(false); } else if (!IsRemoteIdle()) { wxString msg(_("A remote operation is in progress and synchronized browsing is enabled.\nDisable synchronized browsing and continue changing the local directory?")); if (wxMessageBoxEx(msg, _("Synchronized browsing"), wxICON_QUESTION | wxYES_NO) != wxYES) return false; SetSyncBrowse(false); } else { CServerPath remote_path = GetSynchronizedDirectory(dir); if (remote_path.empty()) { SetSyncBrowse(false); wxString msg = wxString::Format(_("Could not obtain corresponding remote directory for the local directory '%s'.\nSynchronized browsing has been disabled."), dir.GetPath()); wxMessageBoxEx(msg, _("Synchronized browsing")); return false; } m_sync_browse.is_changing = true; m_sync_browse.compare = m_pComparisonManager->IsComparing(); CListCommand *pCommand = new CListCommand(remote_path); m_pCommandQueue->ProcessCommand(pCommand); return true; } } if (dir == m_localDir.GetParent() && rememberPreviousSubdir) { #ifdef __WXMSW__ if (dir.GetPath() == _T("\\")) { m_previouslyVisitedLocalSubdir = m_localDir.GetPath(); m_previouslyVisitedLocalSubdir.RemoveLast(); } else #endif m_previouslyVisitedLocalSubdir = m_localDir.GetLastSegment(); } else m_previouslyVisitedLocalSubdir = _T(""); m_localDir = dir; COptions::Get()->SetOption(OPTION_LASTLOCALDIR, m_localDir.GetPath()); NotifyHandlers(STATECHANGE_LOCAL_DIR); return true; }