Add help text for attribute S/R.
[qpwmc.git] / pwmdFileOptionsWidget.cpp
blob6af9e8a32a876894c93f54867b47ccc5887060b2
1 /*
2 Copyright (C) 2015-2024 Ben Kibbey <bjk@luxsci.net>
4 This file is part of qpwmc.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 USA
21 #include <QMessageBox>
22 #include "pwmdFileOptionsWidget.h"
23 #include "pwmdPasswordDialog.h"
24 #include "cmdIds.h"
26 static int lastCacheTimeout;
28 PwmdFileOptionsWidget::PwmdFileOptionsWidget (QWidget *p) : QFrame (p)
30 ui.setupUi (this);
32 _finishing = false;
33 _opened = false;
34 _decryptKeyFile = QString ();
35 _filename = QString ();
36 _sym = false;
37 _sign = false;
38 connect (ui.pb_changePassphrase, SIGNAL (clicked()), this,
39 SLOT (slotChangePassword ()));
40 connect (ui.pb_clearCache, SIGNAL (clicked ()), this,
41 SLOT (slotClearCacheEntry ()));
42 connect (ui.pb_updateCacheTimeout, SIGNAL (clicked ()), this,
43 SLOT (slotUpdateCacheTimeout ()));
44 ui.pb_updateCacheTimeout->setEnabled (false);
45 connect (ui.sp_cacheTimeout, SIGNAL (valueChanged (int)), this,
46 SLOT (slotCacheTimeoutChanged (int)));
47 connect (ui.ck_notCached, SIGNAL (stateChanged (int)), this,
48 SLOT (slotNotCachedChanged (int)));
49 connect (ui.ck_noTimeout, SIGNAL (stateChanged (int)), this,
50 SLOT (slotNoTimeoutChanged (int)));
53 PwmdFileOptionsWidget::~PwmdFileOptionsWidget ()
57 QString
58 PwmdFileOptionsWidget::decryptKeyFile ()
60 return _decryptKeyFile;
63 /* 'opened' is true when called from PwmdFileOptionsDialog. */
64 void
65 PwmdFileOptionsWidget::setFilename (QString s, bool opened)
67 _filename = s;
68 ui.l_filename->setText (s.isEmpty () ? "-" : _filename);
70 if (!opened)
72 ui.pb_changePassphrase->setText (tr ("&Key file..."));
73 if (s.isEmpty ())
74 return;
77 pwm->command (new PwmdCommandQueueItem (PwmdCmdIdFileGetConfig, "GETCONFIG",
78 Pwmd::inquireCallback,
79 new PwmdInquireData (QString ("%1 cache_timeout").arg (_filename))),
80 true);
82 PwmdInquireData *inq = new PwmdInquireData (_filename);
83 PwmdCommandQueueItem *item = new PwmdCommandQueueItem (PwmdCmdIdFileIsCached,
84 "ISCACHED",
85 Pwmd::inquireCallback, inq);
86 item->addError (GPG_ERR_SOURCE_USER_1, GPG_ERR_ENOENT);
87 pwm->command (item, true);
89 if (opened)
91 _opened = true;
92 connect (ui.ck_lock, SIGNAL (stateChanged (int)), this,
93 SLOT (slotLock (int)));
95 item = new PwmdCommandQueueItem (PwmdCmdIdFileKeyInfo, "KEYINFO",
96 Pwmd::inquireCallback, 0);
97 item->addError (GPG_ERR_SOURCE_USER_1, GPG_ERR_NO_DATA);
98 pwm->command (item, true);
100 pwm->command (new PwmdCommandQueueItem (PwmdCmdIdFileClientInfo,
101 "GETINFO", Pwmd::inquireCallback,
102 new PwmdInquireData ("--verbose CLIENTS")));
104 else
105 pwm->runQueue ();
107 ui.sp_cacheTimeout->setEnabled (pwm->state () == Pwmd::Opened
108 && pwm->filename () == s);
109 ui.ck_noTimeout->setEnabled (ui.sp_cacheTimeout->isEnabled ());
110 ui.ck_notCached->setEnabled (ui.sp_cacheTimeout->isEnabled ());
111 ui.pb_updateCacheTimeout->setEnabled (ui.sp_cacheTimeout->isEnabled ());
114 bool
115 PwmdFileOptionsWidget::lock ()
117 return ui.ck_lock->isChecked ();
120 void
121 PwmdFileOptionsWidget::slotLock (int n)
123 bool b = n == Qt::Checked ? true : false;
124 PwmdInquireData *inq = new PwmdInquireData();
125 inq->setUserBool (b);
126 PwmdCommandQueueItem *cmd = new PwmdCommandQueueItem (PwmdCmdIdFileLock,
127 b ? "LOCK" : "UNLOCK",
128 0, inq);
129 if (!b)
130 cmd->addError (GPG_ERR_SOURCE_USER_1, GPG_ERR_NOT_LOCKED);
132 if (!pwm->command (cmd))
133 delete inq;
136 void
137 PwmdFileOptionsWidget::setHandle (Pwmd *p)
139 pwm = p;
140 connect (pwm, SIGNAL (statusMessage (QString, void *)), this, SLOT (slotStatusMessage (QString, void *)));
141 connect (pwm, SIGNAL (commandResult (PwmdCommandQueueItem *, QString, gpg_error_t, bool)), this, SLOT (slotCommandResult (PwmdCommandQueueItem *, QString, gpg_error_t, bool)));
144 void
145 PwmdFileOptionsWidget::setLocked (bool b)
147 ui.ck_lock->disconnect (this);
148 ui.ck_lock->setChecked (b);
149 connect (ui.ck_lock, SIGNAL (stateChanged (int)), this, SLOT (slotLock (int)));
152 void
153 PwmdFileOptionsWidget::isCachedFinalize (gpg_error_t rc)
155 if (gpg_err_code (rc) == GPG_ERR_ENOENT)
156 ui.pb_changePassphrase->setEnabled (false);
158 ui.l_cached->setText (rc ? tr ("no") : tr ("yes"));
159 ui.pb_clearCache->setEnabled (rc ? false : true);
162 void
163 PwmdFileOptionsWidget::cacheTimeoutFinalize (const QString &result)
165 int n = result.toInt();
167 lastCacheTimeout = n;
168 ui.sp_cacheTimeout->setValue (n);
169 slotCacheTimeoutChanged (n);
172 static void
173 showErrorMsg (gpg_error_t rc, const QString &str)
175 QMessageBox m;
177 m.setText (QApplication::
178 tr ("There was an error while communicating with pwmd."));
179 m.setInformativeText (QString ("ERR %1: %2: %3").arg (rc).arg (gpg_strsource (rc), str));
180 m.setIcon (QMessageBox::Critical);
181 m.exec ();
184 void
185 PwmdFileOptionsWidget::refreshClientInfoFinalize (const QString &line)
187 QStringList list = line.split ("\n");
188 unsigned t = list.count();
190 for (unsigned i = 0; i < t; i++)
192 if (list.at (i).isEmpty())
193 continue;
195 ClientInfo *ci = ClientInfo::parseLine (list.at (i));
196 if (ci->filename () == _filename && ci->self ())
198 ui.ck_lock->disconnect (this);
199 ui.ck_lock->setChecked (ci->locked ());
200 connect (ui.ck_lock, SIGNAL (stateChanged (int)), this, SLOT (slotLock (int)));
201 delete ci;
202 break;
205 delete ci;
209 void
210 PwmdFileOptionsWidget::slotCommandResult (PwmdCommandQueueItem *item,
211 QString result, gpg_error_t rc,
212 bool queued)
214 if ((item->id () >= 0 && item->id () <= PwmdCmdIdClientMax)
215 || item->id () >= PwmdCmdIdFileMax)
217 item->setSeen ();
218 return;
221 switch (item->id ())
223 case PwmdCmdIdInternalConnect:
224 case PwmdCmdIdInternalConnectHost:
225 case PwmdCmdIdInternalOpen:
226 case PwmdCmdIdInternalSave:
227 item->setSeen ();
228 return;
229 case PwmdCmdIdInternalPassword:
230 (void)pwmd_setopt (pwm->handle (), PWMD_OPTION_LOCAL_PINENTRY, 0);
231 (void)pwmd_setopt (pwm->handle (), PWMD_OPTION_OVERRIDE_INQUIRE, 0);
232 break;
233 case PwmdCmdIdFileIsCached:
234 isCachedFinalize (rc);
235 break;
236 case PwmdCmdIdFileGetConfig:
237 cacheTimeoutFinalize (result);
238 break;
239 case PwmdCmdIdFileCacheTimeout:
240 updateCacheTimeoutFinalize (rc);
241 break;
242 case PwmdCmdIdFileClearCache:
243 clearCacheEntryFinalize (rc);
244 break;
245 case PwmdCmdIdFileKeyInfo:
246 keyInfoFinalize (rc, result);
247 break;
248 case PwmdCmdIdFileClientInfo:
249 if (!rc)
250 refreshClientInfoFinalize (result);
251 break;
252 case PwmdCmdIdFileLock:
253 if (rc && gpg_err_code (rc) != GPG_ERR_NOT_LOCKED)
255 ui.ck_lock->disconnect (this);
256 ui.ck_lock->setChecked (!ui.ck_lock->isChecked ());
257 connect (ui.ck_lock, SIGNAL (stateChanged (int)), this, SLOT (slotLock (int)));
260 emit clientLockStateChanged (ui.ck_lock->isChecked ());
261 break;
262 default:
263 break;
266 if (rc && !item->checkError (rc) && !queued)
268 if (item->error () && !item->errorString().isEmpty ())
269 showErrorMsg (item->error (), item->errorString ());
270 else
271 Pwmd::showError (rc, pwm);
274 item->setSeen ();
277 void
278 PwmdFileOptionsWidget::keyInfoFinalize (gpg_error_t rc, const QString &result)
280 _sym = true;
281 _sign = false;
282 QStringList list;
284 if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
285 goto done;
287 list = result.split ("\n");
289 for (int n = 0; n < list.count(); n++)
291 if (list.at(n).at(0) != 'S')
292 _sym = false;
293 else
294 _sign = true;
297 done:
298 ui.pb_changePassphrase->setEnabled (!_sym);
301 void
302 PwmdFileOptionsWidget::slotStatusMessage (QString line, void *data)
304 (void)data;
305 if (line.contains ("CACHE"))
307 PwmdCommandQueueItem *item = new PwmdCommandQueueItem (PwmdCmdIdFileIsCached, QString("ISCACHED %1").arg (pwm->filename()));
308 item->addError (GPG_ERR_SOURCE_USER_1, GPG_ERR_ENOENT);
309 pwm->command (item);
313 void
314 PwmdFileOptionsWidget::clearCacheEntryFinalize (gpg_error_t rc)
316 if (!rc)
317 ui.l_cached->setText (tr ("no"));
318 ui.pb_clearCache->setEnabled (!rc ? false : true);
321 void
322 PwmdFileOptionsWidget::slotClearCacheEntry ()
324 pwm->command (new PwmdCommandQueueItem (PwmdCmdIdFileClearCache, QString ("CLEARCACHE %1").arg (_filename)));
327 void
328 PwmdFileOptionsWidget::updateCacheTimeoutFinalize (gpg_error_t rc)
330 if (!rc)
332 lastCacheTimeout = ui.sp_cacheTimeout->value ();
333 ui.ck_notCached->setChecked (ui.sp_cacheTimeout->value () == 0);
334 ui.ck_noTimeout->setChecked (ui.sp_cacheTimeout->value () == -1);
337 ui.pb_updateCacheTimeout->setEnabled (!!rc);
338 if (_finishing)
339 emit commandsFinished ();
342 void
343 PwmdFileOptionsWidget::slotUpdateCacheTimeout ()
345 pwm->command (new PwmdCommandQueueItem (PwmdCmdIdFileCacheTimeout, QString ("CACHETIMEOUT %1").arg (ui.sp_cacheTimeout->value())));
348 bool
349 PwmdFileOptionsWidget::updateCacheTimeout ()
351 if (ui.pb_updateCacheTimeout->isEnabled ())
353 _finishing = true;
354 slotUpdateCacheTimeout ();
355 return false;
358 return true;
361 void
362 PwmdFileOptionsWidget::slotCacheTimeoutChanged (int n)
364 ui.pb_updateCacheTimeout->setEnabled (lastCacheTimeout != n);
365 ui.ck_noTimeout->setChecked (n == -1);
366 ui.ck_notCached->setChecked (n == 0);
369 void
370 PwmdFileOptionsWidget::slotNotCachedChanged (int n)
372 bool b = n == Qt::Checked ? true : false;
374 ui.ck_noTimeout->setChecked (!b && ui.sp_cacheTimeout->value () == -1);
375 if (b)
376 ui.sp_cacheTimeout->setValue (0);
379 void
380 PwmdFileOptionsWidget::slotNoTimeoutChanged (int n)
382 bool b = n == Qt::Checked ? true : false;
384 ui.ck_notCached->setChecked (!b && ui.sp_cacheTimeout->value () == 0);
385 if (b)
386 ui.sp_cacheTimeout->setValue (-1);
389 /* Also used to select a filename during PwmdOpenDialog. */
390 void
391 PwmdFileOptionsWidget::slotChangePassword ()
393 PwmdPasswordDialog *d = new PwmdPasswordDialog (this);
395 if (!_opened)
396 d->setDecryptKeyFile (_decryptKeyFile);
398 d->setSymmetric (_sym);
399 d->setHasSigners (_sign);
400 d->setNewFile (false);
402 if (d->exec ())
404 gpg_error_t rc;
406 if (d->useKeyFile ())
408 if (!_opened)
410 _decryptKeyFile = d->decryptKeyFile ();
411 delete d;
412 return;
415 PwmdInquireData *inq = new PwmdInquireData;
417 inq->setHandle (pwm->handle());
418 inq->setKeyFile (d->decryptKeyFile ());
420 if (!_sym)
421 inq->setEncryptKeyFile (d->signKeyFile ());
422 else
423 inq->setEncryptKeyFile (d->encryptKeyFile ());
425 inq->setSignKeyFile (d->signKeyFile ());
426 rc = pwmd_setopt (pwm->handle (), PWMD_OPTION_LOCAL_PINENTRY, 1);
427 if (!rc)
428 rc = pwmd_setopt (pwm->handle (), PWMD_OPTION_OVERRIDE_INQUIRE, 1);
430 if (!rc)
431 pwm->passwd (0, Pwmd::inquireCallback, inq);
433 else
435 rc = pwmd_setopt (pwm->handle (), PWMD_OPTION_LOCAL_PINENTRY, 0);
436 if (!rc)
437 rc = pwmd_setopt (pwm->handle (), PWMD_OPTION_OVERRIDE_INQUIRE, 0);
439 if (!rc)
440 pwm->passwd ();
443 if (rc)
444 Pwmd::showError (rc, pwm);
447 delete d;