Skip to content

Commit 5b702ae

Browse files
Vogtinatordavidedmundson
authored andcommitted
Session: Parse .desktop files manually again
Using QSettings::IniFormat doesn't quite work. Implement a custom parser for those files to handle them according to the specification. Fixes #1745
1 parent 22f389b commit 5b702ae

File tree

1 file changed

+51
-1
lines changed

1 file changed

+51
-1
lines changed

src/common/Session.cpp

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,56 @@
3434
const QString s_entryExtention = QStringLiteral(".desktop");
3535

3636
namespace SDDM {
37+
// QSettings::IniFormat can't be used to read .desktop files due to different
38+
// syntax of values (escape sequences, quoting, automatic QStringList detection).
39+
// So implement yet another .desktop file parser.
40+
class DesktopFileFormat {
41+
static bool readFunc(QIODevice &device, QSettings::SettingsMap &map)
42+
{
43+
QString currentSectionName;
44+
while(!device.atEnd())
45+
{
46+
// Iterate each line, remove line terminators
47+
const auto line = device.readLine().replace("\r", "").replace("\n", "");
48+
if(line.isEmpty() || line.startsWith('#'))
49+
continue; // Ignore empty lines and comments
50+
51+
if(line.startsWith('[')) // Section header
52+
{
53+
// Remove [ and ].
54+
currentSectionName = QString::fromUtf8(line.mid(1, line.length() - 2));
55+
}
56+
else if(int equalsPos = line.indexOf('='); equalsPos > 0) // Key=Value
57+
{
58+
const auto key = QString::fromUtf8(line.left(equalsPos));
59+
60+
// Read the value, handle escape sequences
61+
auto valueBytes = line.mid(equalsPos + 1);
62+
valueBytes.replace("\\s", " ").replace("\\n", "\n");
63+
valueBytes.replace("\\t", "\t").replace("\\r", "\r");
64+
valueBytes.replace("\\\\", "\\");
65+
66+
auto value = QString::fromUtf8(valueBytes);
67+
map.insert(currentSectionName + QLatin1Char('/') + key, value);
68+
}
69+
}
70+
71+
return true;
72+
}
73+
public:
74+
// Register the .desktop file format if necessary, return its id.
75+
static QSettings::Format format()
76+
{
77+
static QSettings::Format s_format = QSettings::InvalidFormat;
78+
if (s_format == QSettings::InvalidFormat)
79+
s_format = QSettings::registerFormat(QStringLiteral("desktop"),
80+
DesktopFileFormat::readFunc, nullptr,
81+
Qt::CaseSensitive);
82+
83+
return s_format;
84+
}
85+
};
86+
3787
Session::Session()
3888
: m_valid(false)
3989
, m_type(UnknownSession)
@@ -169,7 +219,7 @@ namespace SDDM {
169219
if (!file.isOpen())
170220
return;
171221

172-
QSettings settings(m_fileName, QSettings::IniFormat);
222+
QSettings settings(m_fileName, DesktopFileFormat::format());
173223
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
174224
settings.setIniCodec("UTF-8");
175225
#endif

0 commit comments

Comments
 (0)