1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QSETTINGS_P_H
6#define QSETTINGS_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include "QtCore/qdatetime.h"
20#include "QtCore/qmap.h"
21#include "QtCore/qmutex.h"
22#include "QtCore/qiodevice.h"
23#include "QtCore/qstack.h"
24#include "QtCore/qstringlist.h"
25
26#include <QtCore/qvariant.h>
27#include "qsettings.h"
28
29#ifndef QT_NO_QOBJECT
30#include "private/qobject_p.h"
31#endif
32
33QT_BEGIN_NAMESPACE
34
35#ifndef Q_OS_WIN
36#define QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER
37#endif
38
39// used in testing framework
40#define QSETTINGS_P_H_VERSION 3
41
42#ifdef QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER
43static const Qt::CaseSensitivity IniCaseSensitivity = Qt::CaseSensitive;
44
45class QSettingsKey : public QString
46{
47public:
48 inline QSettingsKey(const QString &key, Qt::CaseSensitivity cs, qsizetype /* position */ = -1)
49 : QString(key) { Q_ASSERT(cs == Qt::CaseSensitive); Q_UNUSED(cs); }
50
51 inline QString originalCaseKey() const { return *this; }
52 inline qsizetype originalKeyPosition() const { return -1; }
53};
54#else
55static const Qt::CaseSensitivity IniCaseSensitivity = Qt::CaseInsensitive;
56
57class QSettingsKey : public QString
58{
59public:
60 inline QSettingsKey(const QString &key, Qt::CaseSensitivity cs, qsizetype position = -1)
61 : QString(key), theOriginalKey(key), theOriginalKeyPosition(position)
62 {
63 if (cs == Qt::CaseInsensitive)
64 QString::operator=(toLower());
65 }
66
67 inline QString originalCaseKey() const { return theOriginalKey; }
68 inline qsizetype originalKeyPosition() const { return theOriginalKeyPosition; }
69
70private:
71 QString theOriginalKey;
72 qsizetype theOriginalKeyPosition;
73};
74#endif
75
76Q_DECLARE_TYPEINFO(QSettingsKey, Q_RELOCATABLE_TYPE);
77
78typedef QMap<QSettingsKey, QByteArray> UnparsedSettingsMap;
79typedef QMap<QSettingsKey, QVariant> ParsedSettingsMap;
80
81class QSettingsGroup
82{
83public:
84 inline QSettingsGroup()
85 : num(-1), maxNum(-1) {}
86 inline QSettingsGroup(const QString &s)
87 : str(s), num(-1), maxNum(-1) {}
88 inline QSettingsGroup(const QString &s, bool guessArraySize)
89 : str(s), num(0), maxNum(guessArraySize ? 0 : -1) {}
90
91 inline QString name() const { return str; }
92 inline QString toString() const;
93 inline bool isArray() const { return num != -1; }
94 inline qsizetype arraySizeGuess() const { return maxNum; }
95 inline void setArrayIndex(qsizetype i)
96 { num = i + 1; if (maxNum != -1 && num > maxNum) maxNum = num; }
97
98 QString str;
99 qsizetype num;
100 qsizetype maxNum;
101};
102Q_DECLARE_TYPEINFO(QSettingsGroup, Q_RELOCATABLE_TYPE);
103
104inline QString QSettingsGroup::toString() const
105{
106 QString result;
107 result = str;
108 if (num > 0) {
109 result += u'/';
110 result += QString::number(num);
111 }
112 return result;
113}
114
115class QConfFile
116{
117public:
118 ~QConfFile();
119
120 ParsedSettingsMap mergedKeyMap() const;
121 bool isWritable() const;
122
123 static QConfFile *fromName(const QString &name, bool _userPerms);
124 Q_AUTOTEST_EXPORT
125 static void clearCache();
126
127 QString name;
128 QDateTime timeStamp;
129 qint64 size;
130 UnparsedSettingsMap unparsedIniSections;
131 ParsedSettingsMap originalKeys;
132 ParsedSettingsMap addedKeys;
133 ParsedSettingsMap removedKeys;
134 QAtomicInt ref;
135 QMutex mutex;
136 bool userPerms;
137
138private:
139#ifdef Q_DISABLE_COPY
140 QConfFile(const QConfFile &);
141 QConfFile &operator=(const QConfFile &);
142#endif
143 QConfFile(const QString &name, bool _userPerms);
144
145 friend class QConfFile_createsItself; // silences compiler warning
146};
147
148class Q_AUTOTEST_EXPORT QSettingsPrivate
149#ifndef QT_NO_QOBJECT
150 : public QObjectPrivate
151#endif
152{
153#ifdef QT_NO_QOBJECT
154 QSettings *q_ptr;
155#endif
156 Q_DECLARE_PUBLIC(QSettings)
157
158public:
159 QSettingsPrivate(QSettings::Format format);
160 QSettingsPrivate(QSettings::Format format, QSettings::Scope scope,
161 const QString &organization, const QString &application);
162 virtual ~QSettingsPrivate();
163
164 virtual void remove(const QString &key) = 0;
165 virtual void set(const QString &key, const QVariant &value) = 0;
166 virtual std::optional<QVariant> get(const QString &key) const = 0;
167
168 enum ChildSpec { AllKeys, ChildKeys, ChildGroups };
169 virtual QStringList children(const QString &prefix, ChildSpec spec) const = 0;
170
171 virtual void clear() = 0;
172 virtual void sync() = 0;
173 virtual void flush() = 0;
174 virtual bool isWritable() const = 0;
175 virtual QString fileName() const = 0;
176
177 QVariant value(QAnyStringView key, const QVariant *defaultValue) const;
178 QString actualKey(QAnyStringView key) const;
179 void beginGroupOrArray(const QSettingsGroup &group);
180 void setStatus(QSettings::Status status) const;
181 void requestUpdate();
182 void update();
183
184 static QString normalizedKey(QAnyStringView key);
185 static QSettingsPrivate *create(QSettings::Format format, QSettings::Scope scope,
186 const QString &organization, const QString &application);
187 static QSettingsPrivate *create(const QString &fileName, QSettings::Format format);
188
189 static void processChild(QStringView key, ChildSpec spec, QStringList &result);
190
191 // Variant streaming functions
192 static QStringList variantListToStringList(const QVariantList &l);
193 static QVariant stringListToVariantList(const QStringList &l);
194
195 // parser functions
196 static QString variantToString(const QVariant &v);
197 static QVariant stringToVariant(const QString &s);
198 static void iniEscapedKey(const QString &key, QByteArray &result);
199 static bool iniUnescapedKey(QByteArrayView key, QString &result);
200 static void iniEscapedString(const QString &str, QByteArray &result);
201 static void iniEscapedStringList(const QStringList &strs, QByteArray &result);
202 static bool iniUnescapedStringList(QByteArrayView str, QString &stringResult,
203 QStringList &stringListResult);
204 static QStringList splitArgs(const QString &s, qsizetype idx);
205
206 QSettings::Format format;
207 QSettings::Scope scope;
208 QString organizationName;
209 QString applicationName;
210
211protected:
212 QStack<QSettingsGroup> groupStack;
213 QString groupPrefix;
214 bool fallbacks;
215 bool pendingChanges;
216 bool atomicSyncOnly = true;
217 mutable QSettings::Status status;
218};
219
220class QConfFileSettingsPrivate : public QSettingsPrivate
221{
222public:
223 QConfFileSettingsPrivate(QSettings::Format format, QSettings::Scope scope,
224 const QString &organization, const QString &application);
225 QConfFileSettingsPrivate(const QString &fileName, QSettings::Format format);
226 ~QConfFileSettingsPrivate();
227
228 void remove(const QString &key) override;
229 void set(const QString &key, const QVariant &value) override;
230 std::optional<QVariant> get(const QString &key) const override;
231
232 QStringList children(const QString &prefix, ChildSpec spec) const override;
233
234 void clear() override;
235 void sync() override;
236 void flush() override;
237 bool isWritable() const override;
238 QString fileName() const override;
239
240 bool readIniFile(QByteArrayView data, UnparsedSettingsMap *unparsedIniSections);
241 static bool readIniSection(const QSettingsKey &section, QByteArrayView data,
242 ParsedSettingsMap *settingsMap);
243 static bool readIniLine(QByteArrayView data, qsizetype &dataPos,
244 qsizetype &lineStart, qsizetype &lineLen,
245 qsizetype &equalsPos);
246
247protected:
248 const QList<QConfFile *> &getConfFiles() const { return confFiles; }
249
250private:
251 void initFormat();
252 virtual void initAccess();
253 void syncConfFile(QConfFile *confFile);
254 bool writeIniFile(QIODevice &device, const ParsedSettingsMap &map);
255#ifdef Q_OS_DARWIN
256 bool readPlistFile(const QByteArray &data, ParsedSettingsMap *map) const;
257 bool writePlistFile(QIODevice &file, const ParsedSettingsMap &map) const;
258#endif
259 void ensureAllSectionsParsed(QConfFile *confFile) const;
260 void ensureSectionParsed(QConfFile *confFile, const QSettingsKey &key) const;
261
262 QList<QConfFile *> confFiles;
263 QSettings::ReadFunc readFunc;
264 QSettings::WriteFunc writeFunc;
265 QString extension;
266 Qt::CaseSensitivity caseSensitivity;
267 qsizetype nextPosition;
268#ifdef Q_OS_WASM
269 friend class QWasmIDBSettingsPrivate;
270#endif
271};
272
273QT_END_NAMESPACE
274
275#endif // QSETTINGS_P_H
276

source code of qtbase/src/corelib/io/qsettings_p.h