LibreOffice Module comphelper (master) 1
DirectoryHelper.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
11
12#include <sal/config.h>
13#include <osl/file.hxx>
14#include <rtl/uri.hxx>
15
16#include <memory>
17
18namespace comphelper
19{
20typedef std::shared_ptr<osl::File> FileSharedPtr;
21
22std::u16string_view DirectoryHelper::splitAtLastToken(std::u16string_view rSrc, sal_Unicode aToken,
23 OUString& rRight)
24{
25 const size_t nIndex(rSrc.rfind(aToken));
26 std::u16string_view aRetval;
27
28 if (std::u16string_view::npos == nIndex)
29 {
30 aRetval = rSrc;
31 rRight.clear();
32 }
33 else if (nIndex > 0)
34 {
35 aRetval = rSrc.substr(0, nIndex);
36
37 if (rSrc.size() > nIndex + 1)
38 {
39 rRight = rSrc.substr(nIndex + 1);
40 }
41 }
42
43 return aRetval;
44}
45
46bool DirectoryHelper::fileExists(const OUString& rBaseURL)
47{
48 if (!rBaseURL.isEmpty())
49 {
50 FileSharedPtr aBaseFile = std::make_shared<osl::File>(rBaseURL);
51
52 return (osl::File::E_None == aBaseFile->open(osl_File_OpenFlag_Read));
53 }
54
55 return false;
56}
57
58bool DirectoryHelper::dirExists(const OUString& rDirURL)
59{
60 if (!rDirURL.isEmpty())
61 {
62 osl::Directory aDirectory(rDirURL);
63
64 return (osl::FileBase::E_None == aDirectory.open());
65 }
66
67 return false;
68}
69
70void DirectoryHelper::scanDirsAndFiles(const OUString& rDirURL, std::set<OUString>& rDirs,
71 std::set<std::pair<OUString, OUString>>& rFiles)
72{
73 if (rDirURL.isEmpty())
74 return;
75
76 osl::Directory aDirectory(rDirURL);
77
78 if (osl::FileBase::E_None != aDirectory.open())
79 return;
80
81 auto lcl_encodeUriSegment = [](OUString const& rPath) {
82 return rtl::Uri::encode(rPath, rtl_UriCharClassUricNoSlash, rtl_UriEncodeIgnoreEscapes,
83 RTL_TEXTENCODING_UTF8);
84 };
85
86 osl::DirectoryItem aDirectoryItem;
87
88 while (osl::FileBase::E_None == aDirectory.getNextItem(aDirectoryItem))
89 {
90 osl::FileStatus aFileStatus(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName);
91
92 if (osl::FileBase::E_None == aDirectoryItem.getFileStatus(aFileStatus))
93 {
94 if (aFileStatus.isDirectory())
95 {
96 const OUString aFileName(aFileStatus.getFileName());
97
98 if (!aFileName.isEmpty())
99 {
100 rDirs.insert(lcl_encodeUriSegment(aFileName));
101 }
102 }
103 else if (aFileStatus.isRegular())
104 {
105 OUString aFileName(aFileStatus.getFileName());
106 OUString aExtension;
107 aFileName = splitAtLastToken(aFileName, '.', aExtension);
108
109 if (!aFileName.isEmpty())
110 {
111 rFiles.insert(std::pair<OUString, OUString>(lcl_encodeUriSegment(aFileName),
112 lcl_encodeUriSegment(aExtension)));
113 }
114 }
115 }
116 }
117}
118
119bool DirectoryHelper::deleteDirRecursively(const OUString& rDirURL)
120{
121 std::set<OUString> aDirs;
122 std::set<std::pair<OUString, OUString>> aFiles;
123 bool bError(false);
124
125 scanDirsAndFiles(rDirURL, aDirs, aFiles);
126
127 for (const auto& dir : aDirs)
128 {
129 const OUString aNewDirURL(rDirURL + "/" + dir);
130
131 bError |= deleteDirRecursively(aNewDirURL);
132 }
133
134 for (const auto& file : aFiles)
135 {
136 OUString aNewFileURL(rDirURL + "/" + file.first);
137
138 if (!file.second.isEmpty())
139 {
140 aNewFileURL += "." + file.second;
141 }
142 bError |= (osl::FileBase::E_None != osl::File::remove(aNewFileURL));
143 }
144
145 bError |= (osl::FileBase::E_None != osl::Directory::remove(rDirURL));
146
147 return bError;
148}
149
150// both exist, move content
151bool DirectoryHelper::moveDirContent(const OUString& rSourceDirURL,
152 std::u16string_view rTargetDirURL,
153 const std::set<OUString>& rExcludeList)
154{
155 std::set<OUString> aDirs;
156 std::set<std::pair<OUString, OUString>> aFiles;
157 bool bError(false);
158
159 scanDirsAndFiles(rSourceDirURL, aDirs, aFiles);
160
161 for (const auto& dir : aDirs)
162 {
163 const bool bExcluded(!rExcludeList.empty() && rExcludeList.find(dir) != rExcludeList.end());
164
165 if (!bExcluded)
166 {
167 const OUString aNewSourceDirURL(rSourceDirURL + "/" + dir);
168
169 if (dirExists(aNewSourceDirURL))
170 {
171 const OUString aNewTargetDirURL(OUString::Concat(rTargetDirURL) + "/" + dir);
172
173 if (dirExists(aNewTargetDirURL))
174 {
175 deleteDirRecursively(aNewTargetDirURL);
176 }
177
178 bError |= (osl::FileBase::E_None
179 != osl::File::move(aNewSourceDirURL, aNewTargetDirURL));
180 }
181 }
182 }
183
184 for (const auto& file : aFiles)
185 {
186 OUString aSourceFileURL(rSourceDirURL + "/" + file.first);
187
188 if (!file.second.isEmpty())
189 {
190 aSourceFileURL += "." + file.second;
191 }
192
193 if (fileExists(aSourceFileURL))
194 {
195 OUString aTargetFileURL(OUString::Concat(rTargetDirURL) + "/" + file.first);
196
197 if (!file.second.isEmpty())
198 {
199 aTargetFileURL += "." + file.second;
200 }
201
202 if (fileExists(aTargetFileURL))
203 {
204 osl::File::remove(aTargetFileURL);
205 }
206
207 bError |= (osl::FileBase::E_None != osl::File::move(aSourceFileURL, aTargetFileURL));
208 }
209 }
210
211 return bError;
212}
213}
static std::u16string_view splitAtLastToken(std::u16string_view rSrc, sal_Unicode aToken, OUString &rRight)
static bool deleteDirRecursively(const OUString &rDirURL)
static bool dirExists(const OUString &rDirURL)
static void scanDirsAndFiles(const OUString &rDirURL, std::set< OUString > &rDirs, std::set< std::pair< OUString, OUString > > &rFiles)
static bool moveDirContent(const OUString &rSourceDirURL, std::u16string_view rTargetDirURL, const std::set< OUString > &rExcludeList)
static bool fileExists(const OUString &rBaseURL)
sal_Int32 nIndex
OUStringBuffer & remove(OUStringBuffer &rIn, sal_Unicode c)
Removes all occurrences of a character from within the source string.
Definition: string.hxx:49
std::shared_ptr< osl::File > FileSharedPtr
sal_uInt16 sal_Unicode