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 
18 namespace comphelper
19 {
20 typedef std::shared_ptr<osl::File> FileSharedPtr;
21 
22 OUString DirectoryHelper::splitAtLastToken(const OUString& rSrc, sal_Unicode aToken,
23  OUString& rRight)
24 {
25  const sal_Int32 nIndex(rSrc.lastIndexOf(aToken));
26  OUString aRetval;
27 
28  if (-1 == nIndex)
29  {
30  aRetval = rSrc;
31  rRight.clear();
32  }
33  else if (nIndex > 0)
34  {
35  aRetval = rSrc.copy(0, nIndex);
36 
37  if (rSrc.getLength() > nIndex + 1)
38  {
39  rRight = rSrc.copy(nIndex + 1);
40  }
41  }
42 
43  return aRetval;
44 }
45 
46 bool 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 
58 bool 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 
70 void 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 
119 bool 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
151 bool 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 }
sal_Int32 nIndex
OUStringBuffer & remove(OUStringBuffer &rIn, sal_Unicode c)
Removes all occurrences of a character from within the source string.
Definition: string.hxx:50
static bool fileExists(const OUString &rBaseURL)
sal_uInt16 sal_Unicode
std::shared_ptr< osl::File > FileSharedPtr
static OUString splitAtLastToken(const OUString &rSrc, sal_Unicode aToken, OUString &rRight)
static bool moveDirContent(const OUString &rSourceDirURL, std::u16string_view rTargetDirURL, const std::set< OUString > &rExcludeList)
static void scanDirsAndFiles(const OUString &rDirURL, std::set< OUString > &rDirs, std::set< std::pair< OUString, OUString >> &rFiles)
static bool deleteDirRecursively(const OUString &rDirURL)
static bool dirExists(const OUString &rDirURL)