inline int CmpTime(const CDirentry &data1, const CDirentry &data2) const { if (!data1.has_date()) { if (data2.has_date()) return -1; else return 0; } else { if (!data2.has_date()) return 1; if (data1.time < data2.time) return -1; else if (data1.time > data2.time) return 1; else return 0; } }
inline int CmpDir(const CDirentry &data1, const CDirentry &data2) const { switch (m_dirSortMode) { default: case dirsort_ontop: if (data1.is_dir()) { if (!data2.is_dir()) return -1; else return 0; } else { if (data2.is_dir()) return 1; else return 0; } case dirsort_onbottom: if (data1.is_dir()) { if (!data2.is_dir()) return 1; else return 0; } else { if (data2.is_dir()) return -1; else return 0; } case dirsort_inline: return 0; } }
int CControlSocket::CheckOverwriteFile() { if (!m_pCurOpData) { LogMessage(__TFILE__, __LINE__, this, MessageType::Debug_Info, _T("Empty m_pCurOpData")); ResetOperation(FZ_REPLY_INTERNALERROR); return FZ_REPLY_ERROR; } CFileTransferOpData *pData = static_cast<CFileTransferOpData *>(m_pCurOpData); if (pData->download) { if (!wxFile::Exists(pData->localFile)) return FZ_REPLY_OK; } CDirentry entry; bool dirDidExist; bool matchedCase; CServerPath remotePath; if (pData->tryAbsolutePath || m_CurrentPath.empty()) remotePath = pData->remotePath; else remotePath = m_CurrentPath; bool found = engine_.GetDirectoryCache().LookupFile(entry, *m_pCurrentServer, remotePath, pData->remoteFile, dirDidExist, matchedCase); // Ignore entries with wrong case if (found && !matchedCase) found = false; if (!pData->download) { if (!found && pData->remoteFileSize < 0 && !pData->fileTime.empty()) return FZ_REPLY_OK; } CFileExistsNotification *pNotification = new CFileExistsNotification; pNotification->download = pData->download; pNotification->localFile = pData->localFile; pNotification->remoteFile = pData->remoteFile; pNotification->remotePath = pData->remotePath; pNotification->localSize = pData->localFileSize; pNotification->remoteSize = pData->remoteFileSize; pNotification->ascii = !pData->transferSettings.binary; if (pData->download && pNotification->localSize >= 0) pNotification->canResume = true; else if (!pData->download && pNotification->remoteSize >= 0) pNotification->canResume = true; else pNotification->canResume = false; pNotification->localTime = fz::local_filesys::get_modification_time(fz::to_native(pData->localFile)); if (pData->fileTime.empty()) pNotification->remoteTime = pData->fileTime; if (found) { if (!pData->fileTime.empty()) { if (entry.has_date()) { pNotification->remoteTime = entry.time; pData->fileTime = entry.time; } } } SendAsyncRequest(pNotification); return FZ_REPLY_WOULDBLOCK; }
bool CControlSocket::SetFileExistsAction(CFileExistsNotification *pFileExistsNotification) { wxASSERT(pFileExistsNotification); if (!m_pCurOpData || m_pCurOpData->opId != Command::transfer) { LogMessage(__TFILE__, __LINE__, this, MessageType::Debug_Info, _T("No or invalid operation in progress, ignoring request reply %f"), pFileExistsNotification->GetRequestID()); return false; } CFileTransferOpData *pData = static_cast<CFileTransferOpData *>(m_pCurOpData); switch (pFileExistsNotification->overwriteAction) { case CFileExistsNotification::overwrite: SendNextCommand(); break; case CFileExistsNotification::overwriteNewer: if (!pFileExistsNotification->localTime.empty() || !pFileExistsNotification->remoteTime.empty()) SendNextCommand(); else if (pFileExistsNotification->download && pFileExistsNotification->localTime.earlier_than(pFileExistsNotification->remoteTime)) SendNextCommand(); else if (!pFileExistsNotification->download && pFileExistsNotification->localTime.later_than(pFileExistsNotification->remoteTime)) SendNextCommand(); else { if (pData->download) { wxString filename = pData->remotePath.FormatFilename(pData->remoteFile); LogMessage(MessageType::Status, _("Skipping download of %s"), filename); } else { LogMessage(MessageType::Status, _("Skipping upload of %s"), pData->localFile); } ResetOperation(FZ_REPLY_OK); } break; case CFileExistsNotification::overwriteSize: /* First compare flags both size known but different, one size known and the other not (obviously they are different). Second compare flags the remaining case in which we need to send command : both size unknown */ if ((pFileExistsNotification->localSize != pFileExistsNotification->remoteSize) || (pFileExistsNotification->localSize < 0)) SendNextCommand(); else { if (pData->download) { wxString filename = pData->remotePath.FormatFilename(pData->remoteFile); LogMessage(MessageType::Status, _("Skipping download of %s"), filename); } else { LogMessage(MessageType::Status, _("Skipping upload of %s"), pData->localFile); } ResetOperation(FZ_REPLY_OK); } break; case CFileExistsNotification::overwriteSizeOrNewer: if (!pFileExistsNotification->localTime.empty() || !pFileExistsNotification->remoteTime.empty()) SendNextCommand(); /* First compare flags both size known but different, one size known and the other not (obviously they are different). Second compare flags the remaining case in which we need to send command : both size unknown */ else if ((pFileExistsNotification->localSize != pFileExistsNotification->remoteSize) || (pFileExistsNotification->localSize < 0)) SendNextCommand(); else if (pFileExistsNotification->download && pFileExistsNotification->localTime.earlier_than(pFileExistsNotification->remoteTime)) SendNextCommand(); else if (!pFileExistsNotification->download && pFileExistsNotification->localTime.later_than(pFileExistsNotification->remoteTime)) SendNextCommand(); else { if (pData->download) { wxString filename = pData->remotePath.FormatFilename(pData->remoteFile); LogMessage(MessageType::Status, _("Skipping download of %s"), filename); } else { LogMessage(MessageType::Status, _("Skipping upload of %s"), pData->localFile); } ResetOperation(FZ_REPLY_OK); } break; case CFileExistsNotification::resume: if (pData->download && pData->localFileSize >= 0) pData->resume = true; else if (!pData->download && pData->remoteFileSize >= 0) pData->resume = true; SendNextCommand(); break; case CFileExistsNotification::rename: if (pData->download) { wxFileName fn = pData->localFile; fn.SetFullName(pFileExistsNotification->newName); pData->localFile = fn.GetFullPath(); int64_t size; bool isLink; if (fz::local_filesys::get_file_info(fz::to_native(pData->localFile), isLink, &size, 0, 0) == fz::local_filesys::file) pData->localFileSize = size; else pData->localFileSize = -1; if (CheckOverwriteFile() == FZ_REPLY_OK) SendNextCommand(); } else { pData->remoteFile = pFileExistsNotification->newName; CDirentry entry; bool dir_did_exist; bool matched_case; if (engine_.GetDirectoryCache().LookupFile(entry, *m_pCurrentServer, pData->tryAbsolutePath ? pData->remotePath : m_CurrentPath, pData->remoteFile, dir_did_exist, matched_case) && matched_case) { pData->remoteFileSize = entry.size; if (entry.has_date()) pData->fileTime = entry.time; if (CheckOverwriteFile() != FZ_REPLY_OK) break; } else { pData->fileTime = fz::datetime(); pData->remoteFileSize = -1; } SendNextCommand(); } break; case CFileExistsNotification::skip: if (pData->download) { wxString filename = pData->remotePath.FormatFilename(pData->remoteFile); LogMessage(MessageType::Status, _("Skipping download of %s"), filename); } else { LogMessage(MessageType::Status, _("Skipping upload of %s"), pData->localFile); } ResetOperation(FZ_REPLY_OK); break; default: LogMessage(__TFILE__, __LINE__, this, MessageType::Debug_Warning, _T("Unknown file exists action: %d"), pFileExistsNotification->overwriteAction); ResetOperation(FZ_REPLY_INTERNALERROR); return false; } return true; }