1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
/* -*- 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 <vcl/UserResourceScanner.hxx>
#include <sal/config.h>
#include <sal/log.hxx>
#include <salhelper/linkhelper.hxx>
#include <unotools/pathoptions.hxx>
#include <o3tl/string_view.hxx>
#include <deque>
namespace vcl
{
namespace
{
OUString convertToAbsolutePath(const OUString& path)
{
salhelper::LinkResolver resolver(0);
osl::FileBase::RC rc = resolver.fetchFileStatus(path);
if (rc != osl::FileBase::E_None)
{
SAL_WARN("vcl.app", "Could not resolve path '" << path << "' to search for icon themes.");
if (rc == osl::FileBase::E_MULTIHOP)
{
throw std::runtime_error("Provided a recursive symlink to an icon theme directory that "
"could not be resolved.");
}
}
return resolver.m_aStatus.getFileURL();
}
}
namespace file
{
// read the status of a file. Returns false if the status could not be determined.
bool readFileStatus(osl::FileStatus& status, const OUString& file)
{
osl::DirectoryItem dirItem;
osl::FileBase::RC retvalGet = osl::DirectoryItem::get(file, dirItem);
if (retvalGet != osl::FileBase::E_None)
{
SAL_WARN("vcl.app", "Could not determine status for file '" << file << "'.");
return false;
}
osl::FileBase::RC retvalStatus = dirItem.getFileStatus(status);
if (retvalStatus != osl::FileBase::E_None)
{
SAL_WARN("vcl.app", "Could not determine status for file '" << file << "'.");
return false;
}
return true;
}
void splitPathString(std::u16string_view aPathString, std::deque<OUString>& rPaths)
{
sal_Int32 nIndex = 0;
do
{
rPaths.push_front(OUString(o3tl::getToken(aPathString, 0, ';', nIndex)));
} while (nIndex >= 0);
}
}
UserResourceScanner::UserResourceScanner() = default;
void UserResourceScanner::addPaths(std::u16string_view aPathString)
{
std::deque<OUString> aPaths;
vcl::file::splitPathString(aPathString, aPaths);
for (const auto& path : aPaths)
{
osl::FileStatus aFileStatus(osl_FileStatus_Mask_Type);
if (!vcl::file::readFileStatus(aFileStatus, path))
continue;
if (!aFileStatus.isDirectory())
{
SAL_INFO("vcl.app", "Can not search for resource files in '"
<< path << "'. It is not a directory.");
continue;
}
std::vector<OUString> aResourcePaths = readFilesFromPath(path);
if (aResourcePaths.empty())
{
SAL_WARN("vcl.app",
"Could not find any file in the provided directory ('" << path << "'.");
continue;
}
for (auto const& iconThemePath : aResourcePaths)
addResource(iconThemePath);
}
}
std::vector<OUString> UserResourceScanner::readFilesFromPath(const OUString& dir)
{
std::vector<OUString> found;
SAL_INFO("vcl", "Scanning directory '" << dir << " for potential resource files.");
osl::Directory dirToScan(dir);
osl::FileBase::RC retvalOpen = dirToScan.open();
if (retvalOpen != osl::FileBase::E_None)
return found;
osl::DirectoryItem directoryItem;
while (dirToScan.getNextItem(directoryItem) == osl::FileBase::E_None)
{
osl::FileStatus status(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL
| osl_FileStatus_Mask_FileName);
osl::FileBase::RC retvalStatus = directoryItem.getFileStatus(status);
if (retvalStatus != osl::FileBase::E_None)
continue;
OUString filename = convertToAbsolutePath(status.getFileURL());
if (isValidResource(filename))
found.push_back(filename);
}
return found;
}
} // end namespace vcl
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|