Line data Source code
1 : // SPDX-FileCopyrightText: 2016 Anne Jan Brouwer
2 : // SPDX-License-Identifier: GPL-3.0-or-later
3 : /**
4 : * @file
5 : * @brief Implements SettingsSerializer: one SettingsConstants key per
6 : * AppSettings field, with the defaults applied in load() and the obsolete
7 : * WebDAV keys dropped in save().
8 : */
9 : #include "settingsserializer.h"
10 : #include "settingsconstants.h"
11 :
12 : #include <QDebug>
13 : #include <QSettings>
14 :
15 2590 : auto SettingsSerializer::loadPasswordConfiguration(QSettings &qs)
16 : -> PasswordConfiguration {
17 2590 : PasswordConfiguration config;
18 :
19 2590 : int length = qs.value(SettingsConstants::passwordLength, 16).toInt();
20 2590 : if (length <= 0) {
21 : length = 16;
22 : }
23 2590 : config.length = length;
24 :
25 : // The ini value is untrusted: anything outside the enum would be used as an
26 : // index into PasswordConfiguration::Characters, so clamp it here, once, and
27 : // every consumer sees a valid selection.
28 : const int selected =
29 2590 : qs.value(SettingsConstants::passwordCharsSelection, 0).toInt();
30 2590 : if (selected < 0 || selected >= PasswordConfiguration::CHARSETS_COUNT) {
31 8 : qWarning() << "Ignoring out-of-range passwordCharsSelection" << selected;
32 8 : config.selected = PasswordConfiguration::ALLCHARS;
33 : } else {
34 2582 : config.selected =
35 : static_cast<PasswordConfiguration::CharacterSet>(selected);
36 : }
37 :
38 : config.Characters[PasswordConfiguration::CUSTOM] =
39 5180 : qs.value(SettingsConstants::passwordChars, QString()).toString();
40 :
41 2590 : return config;
42 0 : }
43 :
44 2577 : auto SettingsSerializer::load(QSettings &qs) -> AppSettings {
45 2577 : AppSettings s;
46 :
47 : // Window / session
48 5154 : s.version = qs.value(SettingsConstants::version).toString();
49 5154 : s.geometry = qs.value(SettingsConstants::geometry).toByteArray();
50 5154 : s.savestate = qs.value(SettingsConstants::savestate).toByteArray();
51 5154 : s.activeProfile = qs.value(SettingsConstants::profile).toString();
52 :
53 : // Backend selection / store
54 2577 : s.usePass = qs.value(SettingsConstants::usePass, false).toBool();
55 5154 : s.passStore = qs.value(SettingsConstants::passStore).toString();
56 5154 : s.passSigningKey = qs.value(SettingsConstants::passSigningKey).toString();
57 :
58 : // Executables
59 5154 : s.passExecutable = qs.value(SettingsConstants::passExecutable).toString();
60 5154 : s.gitExecutable = qs.value(SettingsConstants::gitExecutable).toString();
61 5154 : s.gpgExecutable = qs.value(SettingsConstants::gpgExecutable).toString();
62 5154 : s.pwgenExecutable = qs.value(SettingsConstants::pwgenExecutable).toString();
63 : s.qrencodeExecutable =
64 5154 : qs.value(SettingsConstants::qrencodeExecutable).toString();
65 5154 : s.gpgHome = qs.value(SettingsConstants::gpgHome).toString();
66 : s.sshAuthSockOverride =
67 5154 : qs.value(SettingsConstants::sshAuthSockOverride).toString();
68 :
69 : // Clipboard / autoclear
70 2577 : s.clipBoardType = static_cast<Enums::ClipBoardType>(
71 5154 : qs.value(SettingsConstants::clipBoardType,
72 5154 : static_cast<int>(Enums::CLIPBOARD_NEVER))
73 2577 : .toInt());
74 2577 : s.useSelection = qs.value(SettingsConstants::useSelection, false).toBool();
75 2577 : s.useAutoclear = qs.value(SettingsConstants::useAutoclear, false).toBool();
76 2577 : s.restoreClipboard =
77 2577 : qs.value(SettingsConstants::restoreClipboard, true).toBool();
78 2577 : s.autoclearSeconds = qs.value(SettingsConstants::autoclearSeconds, 0).toInt();
79 2577 : s.useAutoclearPanel =
80 2577 : qs.value(SettingsConstants::useAutoclearPanel, false).toBool();
81 2577 : s.autoclearPanelSeconds =
82 2577 : qs.value(SettingsConstants::autoclearPanelSeconds, 0).toInt();
83 :
84 : // Content display
85 2577 : s.hidePassword = qs.value(SettingsConstants::hidePassword, false).toBool();
86 2577 : s.hideSecretFields =
87 2577 : qs.value(SettingsConstants::hideSecretFields, true).toBool();
88 2577 : s.hideAllFields = qs.value(SettingsConstants::hideAllFields, false).toBool();
89 : // Never saved (a new settings file, or one from 1.8): the default set.
90 : // Saved, it is what the user left, an empty list included.
91 2577 : if (qs.contains(SettingsConstants::secretFieldNames)) {
92 2391 : s.secretFieldNames.clear();
93 : for (const QString &name :
94 36570 : qs.value(SettingsConstants::secretFieldNames).toStringList()) {
95 31788 : if (!name.trimmed().isEmpty()) {
96 31787 : s.secretFieldNames << name.trimmed();
97 : }
98 : }
99 : } else {
100 372 : s.secretFieldNames = AppSettings::defaultSecretFieldNames();
101 : }
102 2577 : s.hideContent = qs.value(SettingsConstants::hideContent, false).toBool();
103 2577 : s.useMonospace = qs.value(SettingsConstants::useMonospace, false).toBool();
104 2577 : s.displayAsIs = qs.value(SettingsConstants::displayAsIs, false).toBool();
105 2577 : s.noLineWrapping =
106 2577 : qs.value(SettingsConstants::noLineWrapping, false).toBool();
107 :
108 : // Features
109 : // Default true: AppSettings::addGPGId defaults to true.
110 2577 : s.addGPGId = qs.value(SettingsConstants::addGPGId, true).toBool();
111 2577 : s.useGit = qs.value(SettingsConstants::useGit, false).toBool();
112 2577 : s.useGrepSearch = qs.value(SettingsConstants::useGrepSearch, false).toBool();
113 : // Defaults to true: OTP no longer depends on an external extension, and a
114 : // stored value from an older profile still wins over this default.
115 2577 : s.useOtp = qs.value(SettingsConstants::useOtp, true).toBool();
116 2577 : s.useQrencode = qs.value(SettingsConstants::useQrencode, false).toBool();
117 2577 : s.usePwgen = qs.value(SettingsConstants::usePwgen, false).toBool();
118 2577 : s.autoPull = qs.value(SettingsConstants::autoPull, false).toBool();
119 2577 : s.autoPush = qs.value(SettingsConstants::autoPush, false).toBool();
120 2577 : s.gitUseParentRepository =
121 2577 : qs.value(SettingsConstants::gitUseParentRepository, false).toBool();
122 2577 : s.showProcessOutput =
123 2577 : qs.value(SettingsConstants::showProcessOutput, false).toBool();
124 2577 : s.showMenuBar = qs.value(SettingsConstants::showMenuBar, false).toBool();
125 :
126 : // Templates
127 5154 : s.passTemplate = qs.value(SettingsConstants::passTemplate).toString();
128 2577 : s.useTemplate = qs.value(SettingsConstants::useTemplate, false).toBool();
129 2577 : s.templateAllFields =
130 2577 : qs.value(SettingsConstants::templateAllFields, false).toBool();
131 :
132 : // Password generation
133 2577 : s.passwordConfiguration = loadPasswordConfiguration(qs);
134 2577 : s.avoidCapitals = qs.value(SettingsConstants::avoidCapitals, false).toBool();
135 2577 : s.avoidNumbers = qs.value(SettingsConstants::avoidNumbers, false).toBool();
136 2577 : s.lessRandom = qs.value(SettingsConstants::lessRandom, false).toBool();
137 2577 : s.useSymbols = qs.value(SettingsConstants::useSymbols, false).toBool();
138 :
139 : // System / tray
140 2577 : s.useTrayIcon = qs.value(SettingsConstants::useTrayIcon, false).toBool();
141 2577 : s.hideOnClose = qs.value(SettingsConstants::hideOnClose, false).toBool();
142 2577 : s.startMinimized =
143 2577 : qs.value(SettingsConstants::startMinimized, false).toBool();
144 2577 : s.alwaysOnTop = qs.value(SettingsConstants::alwaysOnTop, false).toBool();
145 :
146 2577 : return s;
147 0 : }
148 :
149 769 : void SettingsSerializer::save(QSettings &qs, const AppSettings &s) {
150 : // Window / session
151 769 : qs.setValue(SettingsConstants::version, s.version);
152 769 : qs.setValue(SettingsConstants::geometry, s.geometry);
153 769 : qs.setValue(SettingsConstants::savestate, s.savestate);
154 769 : qs.setValue(SettingsConstants::profile, s.activeProfile);
155 :
156 : // Backend selection / store
157 769 : qs.setValue(SettingsConstants::usePass, s.usePass);
158 769 : qs.setValue(SettingsConstants::passStore, s.passStore);
159 769 : qs.setValue(SettingsConstants::passSigningKey, s.passSigningKey);
160 :
161 : // Executables
162 769 : qs.setValue(SettingsConstants::passExecutable, s.passExecutable);
163 769 : qs.setValue(SettingsConstants::gitExecutable, s.gitExecutable);
164 769 : qs.setValue(SettingsConstants::gpgExecutable, s.gpgExecutable);
165 769 : qs.setValue(SettingsConstants::pwgenExecutable, s.pwgenExecutable);
166 769 : qs.setValue(SettingsConstants::qrencodeExecutable, s.qrencodeExecutable);
167 769 : qs.setValue(SettingsConstants::gpgHome, s.gpgHome);
168 769 : qs.setValue(SettingsConstants::sshAuthSockOverride, s.sshAuthSockOverride);
169 :
170 : // Clipboard / autoclear
171 769 : qs.setValue(SettingsConstants::clipBoardType,
172 1538 : static_cast<int>(s.clipBoardType));
173 769 : qs.setValue(SettingsConstants::useSelection, s.useSelection);
174 769 : qs.setValue(SettingsConstants::useAutoclear, s.useAutoclear);
175 769 : qs.setValue(SettingsConstants::restoreClipboard, s.restoreClipboard);
176 769 : qs.setValue(SettingsConstants::autoclearSeconds, s.autoclearSeconds);
177 769 : qs.setValue(SettingsConstants::useAutoclearPanel, s.useAutoclearPanel);
178 769 : qs.setValue(SettingsConstants::autoclearPanelSeconds,
179 1538 : s.autoclearPanelSeconds);
180 :
181 : // Content display
182 769 : qs.setValue(SettingsConstants::hidePassword, s.hidePassword);
183 769 : qs.setValue(SettingsConstants::hideSecretFields, s.hideSecretFields);
184 769 : qs.setValue(SettingsConstants::hideAllFields, s.hideAllFields);
185 769 : qs.setValue(SettingsConstants::secretFieldNames, s.secretFieldNames);
186 769 : qs.setValue(SettingsConstants::hideContent, s.hideContent);
187 769 : qs.setValue(SettingsConstants::useMonospace, s.useMonospace);
188 769 : qs.setValue(SettingsConstants::displayAsIs, s.displayAsIs);
189 769 : qs.setValue(SettingsConstants::noLineWrapping, s.noLineWrapping);
190 :
191 : // Features
192 769 : qs.setValue(SettingsConstants::addGPGId, s.addGPGId);
193 769 : qs.setValue(SettingsConstants::useGit, s.useGit);
194 769 : qs.setValue(SettingsConstants::useGrepSearch, s.useGrepSearch);
195 769 : qs.setValue(SettingsConstants::useOtp, s.useOtp);
196 769 : qs.setValue(SettingsConstants::useQrencode, s.useQrencode);
197 769 : qs.setValue(SettingsConstants::usePwgen, s.usePwgen);
198 : // The WebDAV mount was removed in 2.0; drop its keys, including the
199 : // plaintext webDavPassword, from configurations written by older versions.
200 3845 : for (const auto &obsolete :
201 769 : {QStringLiteral("useWebDav"), QStringLiteral("webDavUrl"),
202 7690 : QStringLiteral("webDavUser"), QStringLiteral("webDavPassword")}) {
203 3076 : qs.remove(obsolete);
204 3845 : }
205 769 : qs.setValue(SettingsConstants::autoPull, s.autoPull);
206 769 : qs.setValue(SettingsConstants::autoPush, s.autoPush);
207 769 : qs.setValue(SettingsConstants::gitUseParentRepository,
208 1538 : s.gitUseParentRepository);
209 769 : qs.setValue(SettingsConstants::showProcessOutput, s.showProcessOutput);
210 769 : qs.setValue(SettingsConstants::showMenuBar, s.showMenuBar);
211 :
212 : // Templates
213 769 : qs.setValue(SettingsConstants::passTemplate, s.passTemplate);
214 769 : qs.setValue(SettingsConstants::useTemplate, s.useTemplate);
215 769 : qs.setValue(SettingsConstants::templateAllFields, s.templateAllFields);
216 :
217 : // Password generation
218 769 : qs.setValue(SettingsConstants::passwordLength,
219 1538 : s.passwordConfiguration.length);
220 769 : qs.setValue(SettingsConstants::passwordCharsSelection,
221 1538 : static_cast<int>(s.passwordConfiguration.selected));
222 769 : qs.setValue(
223 : SettingsConstants::passwordChars,
224 1538 : s.passwordConfiguration.Characters[PasswordConfiguration::CUSTOM]);
225 769 : qs.setValue(SettingsConstants::avoidCapitals, s.avoidCapitals);
226 769 : qs.setValue(SettingsConstants::avoidNumbers, s.avoidNumbers);
227 769 : qs.setValue(SettingsConstants::lessRandom, s.lessRandom);
228 769 : qs.setValue(SettingsConstants::useSymbols, s.useSymbols);
229 :
230 : // System / tray
231 769 : qs.setValue(SettingsConstants::useTrayIcon, s.useTrayIcon);
232 769 : qs.setValue(SettingsConstants::hideOnClose, s.hideOnClose);
233 769 : qs.setValue(SettingsConstants::startMinimized, s.startMinimized);
234 769 : qs.setValue(SettingsConstants::alwaysOnTop, s.alwaysOnTop);
235 769 : }
|