Coverage Report

Created: 2025-12-31 10:39

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