mirror-chatterino2/src/util/XDGDesktopFile.cpp
Sam Heybey 69c983e0d9
Add support for opening links in incognito mode on Linux & BSD (#4745)
Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
2023-08-06 15:57:01 +02:00

118 lines
3 KiB
C++

#include "util/XDGDesktopFile.hpp"
#include "util/XDGDirectory.hpp"
#include <QDir>
#include <QFile>
#include <functional>
#if defined(Q_OS_UNIX) and !defined(Q_OS_DARWIN)
namespace chatterino {
XDGDesktopFile::XDGDesktopFile(const QString &filename)
{
QFile file(filename);
if (!file.open(QIODevice::ReadOnly))
{
return;
}
this->valid = true;
std::optional<std::reference_wrapper<XDGEntries>> entries;
while (!file.atEnd())
{
auto lineBytes = file.readLine().trimmed();
// Ignore comments & empty lines
if (lineBytes.startsWith('#') || lineBytes.size() == 0)
{
continue;
}
auto line = QString::fromUtf8(lineBytes);
if (line.startsWith('['))
{
// group header
auto end = line.indexOf(']', 1);
if (end == -1 || end == 1)
{
// malformed header - either empty or no closing bracket
continue;
}
auto groupName = line.mid(1, end - 1);
// it is against spec for the group name to already exist, but the
// parsing behavior for that case is not specified. operator[] will
// result in duplicate groups being merged, which makes the most
// sense for a read-only parser
entries = this->groups[groupName];
continue;
}
// group entry
if (!entries.has_value())
{
// no group header yet, entry before a group header is against spec
// and should be ignored
continue;
}
auto delimiter = line.indexOf('=');
if (delimiter == -1)
{
// line is not a group header or a key value pair, ignore it
continue;
}
auto key = QStringView(line).left(delimiter).trimmed().toString();
// QStringView.mid() does not do bounds checking before qt 5.15, so
// we have to do it ourselves
auto valueStart = delimiter + 1;
QString value;
if (valueStart < line.size())
{
value = QStringView(line).mid(valueStart).trimmed().toString();
}
// existing keys are against spec, so we can overwrite them with
// wild abandon
entries->get().emplace(key, value);
}
}
XDGEntries XDGDesktopFile::getEntries(const QString &groupHeader) const
{
auto group = this->groups.find(groupHeader);
if (group != this->groups.end())
{
return group->second;
}
return {};
}
std::optional<XDGDesktopFile> XDGDesktopFile::findDesktopFile(
const QString &desktopFileID)
{
for (const auto &dataDir : getXDGDirectories(XDGDirectoryType::Data))
{
auto fileName =
QDir::cleanPath(dataDir + QDir::separator() + "applications" +
QDir::separator() + desktopFileID);
XDGDesktopFile desktopFile(fileName);
if (desktopFile.isValid())
{
return desktopFile;
}
}
return {};
}
} // namespace chatterino
#endif