/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include namespace comphelper { typedef std::shared_ptr FileSharedPtr; std::u16string_view DirectoryHelper::splitAtLastToken(std::u16string_view rSrc, sal_Unicode aToken, OUString& rRight) { const size_t nIndex(rSrc.rfind(aToken)); std::u16string_view aRetval; if (std::u16string_view::npos == nIndex) { aRetval = rSrc; rRight.clear(); } else if (nIndex > 0) { aRetval = rSrc.substr(0, nIndex); if (rSrc.size() > nIndex + 1) { rRight = rSrc.substr(nIndex + 1); } } return aRetval; } bool DirectoryHelper::fileExists(const OUString& rBaseURL) { if (!rBaseURL.isEmpty()) { FileSharedPtr aBaseFile = std::make_shared(rBaseURL); return (osl::File::E_None == aBaseFile->open(osl_File_OpenFlag_Read)); } return false; } bool DirectoryHelper::dirExists(const OUString& rDirURL) { if (!rDirURL.isEmpty()) { osl::Directory aDirectory(rDirURL); return (osl::FileBase::E_None == aDirectory.open()); } return false; } void DirectoryHelper::scanDirsAndFiles(const OUString& rDirURL, std::set& rDirs, std::set>& rFiles) { if (rDirURL.isEmpty()) return; osl::Directory aDirectory(rDirURL); if (osl::FileBase::E_None != aDirectory.open()) return; auto lcl_encodeUriSegment = [](OUString const& rPath) { return rtl::Uri::encode(rPath, rtl_UriCharClassUricNoSlash, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8); }; osl::DirectoryItem aDirectoryItem; while (osl::FileBase::E_None == aDirectory.getNextItem(aDirectoryItem)) { osl::FileStatus aFileStatus(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName); if (osl::FileBase::E_None == aDirectoryItem.getFileStatus(aFileStatus)) { if (aFileStatus.isDirectory()) { const OUString aFileName(aFileStatus.getFileName()); if (!aFileName.isEmpty()) { rDirs.insert(lcl_encodeUriSegment(aFileName)); } } else if (aFileStatus.isRegular()) { OUString aFileName(aFileStatus.getFileName()); OUString aExtension; aFileName = splitAtLastToken(aFileName, '.', aExtension); if (!aFileName.isEmpty()) { rFiles.insert(std::pair(lcl_encodeUriSegment(aFileName), lcl_encodeUriSegment(aExtension))); } } } } } bool DirectoryHelper::deleteDirRecursively(const OUString& rDirURL) { std::set aDirs; std::set> aFiles; bool bError(false); scanDirsAndFiles(rDirURL, aDirs, aFiles); for (const auto& dir : aDirs) { const OUString aNewDirURL(rDirURL + "/" + dir); bError |= deleteDirRecursively(aNewDirURL); } for (const auto& file : aFiles) { OUString aNewFileURL(rDirURL + "/" + file.first); if (!file.second.isEmpty()) { aNewFileURL += "." + file.second; } bError |= (osl::FileBase::E_None != osl::File::remove(aNewFileURL)); } bError |= (osl::FileBase::E_None != osl::Directory::remove(rDirURL)); return bError; } // both exist, move content bool DirectoryHelper::moveDirContent(const OUString& rSourceDirURL, std::u16string_view rTargetDirURL, const std::set& rExcludeList) { std::set aDirs; std::set> aFiles; bool bError(false); scanDirsAndFiles(rSourceDirURL, aDirs, aFiles); for (const auto& dir : aDirs) { const bool bExcluded(!rExcludeList.empty() && rExcludeList.find(dir) != rExcludeList.end()); if (!bExcluded) { const OUString aNewSourceDirURL(rSourceDirURL + "/" + dir); if (dirExists(aNewSourceDirURL)) { const OUString aNewTargetDirURL(OUString::Concat(rTargetDirURL) + "/" + dir); if (dirExists(aNewTargetDirURL)) { deleteDirRecursively(aNewTargetDirURL); } bError |= (osl::FileBase::E_None != osl::File::move(aNewSourceDirURL, aNewTargetDirURL)); } } } for (const auto& file : aFiles) { OUString aSourceFileURL(rSourceDirURL + "/" + file.first); if (!file.second.isEmpty()) { aSourceFileURL += "." + file.second; } if (fileExists(aSourceFileURL)) { OUString aTargetFileURL(OUString::Concat(rTargetDirURL) + "/" + file.first); if (!file.second.isEmpty()) { aTargetFileURL += "." + file.second; } if (fileExists(aTargetFileURL)) { osl::File::remove(aTargetFileURL); } bError |= (osl::FileBase::E_None != osl::File::move(aSourceFileURL, aTargetFileURL)); } } return bError; } }