2 Copyright (C) 2010-2023 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
21 #include <QApplication>
23 #include <QCommonStyle>
27 #include <QMessageBox>
32 #include "pwmdSaveDialog.h"
33 #include "pwmdSaveWidget.h"
35 #include "pwmdPasswordDialog.h"
36 #include "pwmdKeyGenDialog.h"
38 static bool searching
;
40 PwmdSaveWidget::PwmdSaveWidget (QWidget
*p
) : QFrame (p
)
46 _recipients
= QString ();
47 _signers
= QString ();
49 newSigners
= QString ();
50 newRecipients
= QString ();
51 currentKeyListIndex
= 0;
52 selectSignKeyId
= false;
53 QSettings
cfg ("qpwmc");
55 encryptKeyFile
= QString ();
56 signKeyFile
= QString ();
58 generatedKeyId
= QString ();
60 ui
.keyList
->setParent(this);
61 ui
.recipientList
->setParent(this);
62 ui
.recipientList
->setIsRecipientList();
63 connect (ui
.tb_refreshKeyList
, SIGNAL (clicked()), this, SLOT(slotRefreshKeyList()));
64 ui
.tb_refreshKeyList
->setIcon (QIcon (":icons/matt-icons_view-refresh.svg"));
65 connect (ui
.keyList
, SIGNAL (currentItemChanged (QTreeWidgetItem
*, QTreeWidgetItem
*)), this, SLOT (slotKeyIdChanged (QTreeWidgetItem
*, QTreeWidgetItem
*)));
66 connect (ui
.keyList
, SIGNAL (itemSelectionChanged ()), this, SLOT (slotKeySelectionChanged ()));
67 connect (ui
.recipientList
, SIGNAL (currentItemChanged (QTreeWidgetItem
*, QTreeWidgetItem
*)), this, SLOT (slotKeyIdChanged (QTreeWidgetItem
*, QTreeWidgetItem
*)));
69 list
<< tr("Key ID") << tr("Validity") << tr("Trust") << tr ("Flags")
71 ui
.keyList
->setHeaderLabels(list
);
72 ui
.recipientList
->setHeaderLabels(list
);
73 ui
.keyList
->header()->restoreState(cfg
.value ("keyListHeaderState").toByteArray());
74 ui
.recipientList
->header()->restoreState(cfg
.value ("keyListHeaderState").toByteArray());
76 connect (ui
.keyList
->header(), SIGNAL(sectionResized(int, int, int)), this, SLOT (slotHeaderSectionResized(int, int, int)));
78 connect (ui
.pb_generate
, SIGNAL (clicked ()), this, SLOT (slotGenerate ()));
79 connect (ui
.ck_symmetric
, SIGNAL (stateChanged (int)), this, SLOT (slotSymmetricChanged(int)));
80 connect (ui
.ck_secretOnly
, SIGNAL (stateChanged (int)), this, SLOT (slotSecretOnlyChanged (int)));
81 ui
.tb_addRecipient
->setIcon (QIcon (":icons/matt-icons_list-add.svg"));
82 connect (ui
.tb_addRecipient
, SIGNAL (clicked()), this, SLOT (slotAddRecipients()));
83 ui
.tb_removeRecipient
->setIcon (QIcon (":icons/matt-icons_list-remove.svg"));
84 connect (ui
.tb_removeRecipient
, SIGNAL (clicked()), this, SLOT (slotRemoveRecipients()));
86 QShortcut
*sc
= new QShortcut (QKeySequence ("Ctrl+F"), this);
87 connect (sc
, SIGNAL (activated ()), this, SLOT (slotFindKeyActivated ()));
88 connect (ui
.le_searchKeyList
, SIGNAL (textChanged (const QString
&)), this,
89 SLOT (slotSearchKeyListChanged (const QString
&)));
90 connect (ui
.le_searchKeyList
, SIGNAL (returnPressed()), this,
91 SLOT (slotSearchKeyList()));
92 connect (ui
.tb_searchKeyList
, SIGNAL (clicked()), this,
93 SLOT (slotSearchKeyList()));
95 connect (ui
.tb_learn
, SIGNAL (clicked()), this, SLOT (slotLearn()));
96 ui
.tb_learn
->setIcon (QIcon (":icons/rodentia-icons_emblem-information.svg"));
98 connect (ui
.pb_keyFileOptions
, SIGNAL (clicked()), this, SLOT (slotSelectKeyFile()));
100 connect (ui
.tb_delete
, SIGNAL (clicked ()), SLOT (slotDeleteKey ()));
101 ui
.tb_delete
->setIcon (QIcon (":icons/rodentia-icons_user-trash-full.svg"));
102 ui
.tb_delete
->setEnabled (false);
103 ui
.tb_removeRecipient
->setEnabled (false);
104 ui
.tb_addRecipient
->setEnabled (false);
105 QScroller::grabGesture(ui
.scrollArea
, QScroller::TouchGesture
);
108 PwmdSaveWidget::~PwmdSaveWidget ()
110 QSettings
cfg ("qpwmc");
112 cfg
.setValue ("keyListHeaderState", ui
.keyList
->header()->saveState());
117 PwmdSaveWidget::isSearching ()
119 return ui
.le_searchKeyList
->hasFocus ();
123 PwmdSaveWidget::slotKeySelectionChanged ()
125 QList
<QTreeWidgetItem
*> list
= ui
.keyList
->selectedItems ();
127 ui
.tb_delete
->setEnabled (!(list
.isEmpty () || list
.size () > 1));
131 PwmdSaveWidget::slotStatusMessage (QString line
, void *user
)
134 QStringList l
= QString (line
).split (" ");
136 if (l
.at (0) == "GENKEY" && l
.size () == 3)
138 generatedKeyId
= l
.at(2);
143 PwmdSaveWidget::slotGenerate ()
145 PwmdKeyGenDialog
d (this, pwm
);
150 PwmdSaveWidget::slotLearn ()
152 pwm
->command (new PwmdCommandQueueItem (PwmdCmdIdSaveLearn
, "KEYINFO", nullptr,
153 new PwmdInquireData ("--learn")));
157 PwmdSaveWidget::slotCopyKeyIdToClipboard ()
159 QClipboard
*c
= QApplication::clipboard ();
160 QTreeWidgetItem
*item
= ui
.keyList
->currentItem ();
161 PwmdKeyItemData
*data
= qvariant_cast
<PwmdKeyItemData
* >(item
->data (0, Qt::UserRole
));
163 if (c
->supportsSelection ())
164 c
->setText (data
->subKey()->keyId (), QClipboard::Selection
);
165 c
->setText (data
->subKey()->keyId ());
169 PwmdSaveWidget::slotCopyRecipientKeyIdToClipboard ()
171 QClipboard
*c
= QApplication::clipboard ();
172 QTreeWidgetItem
*item
= ui
.recipientList
->currentItem ();
173 PwmdKeyItemData
*data
= qvariant_cast
<PwmdKeyItemData
* >(item
->data (0, Qt::UserRole
));
175 if (c
->supportsSelection ())
176 c
->setText (data
->subKey()->keyId (), QClipboard::Selection
);
177 c
->setText (data
->subKey()->keyId ());
181 PwmdSaveWidget::slotDeleteKey ()
183 QList
<QTreeWidgetItem
*> list
= ui
.keyList
->selectedItems ();
184 PwmdKeyItemData
*data
= qvariant_cast
<PwmdKeyItemData
* >(list
.at (0)->data (0, Qt::UserRole
));
185 QString key
= QString ("User ID: %1\nFingerprint: %2").arg (data
->key()->userIds ().at(0)->userId(), data
->subKey ()->fingerprint ());
186 int b
= QMessageBox::question (this, tr ("Delete key pair?"),
187 QString (tr ("Do you really want to delete the following public and private keys from the keyring?\n\n%1").arg (key
)),
188 QMessageBox::Yes
| QMessageBox::No
,
191 if (b
!= QMessageBox::Yes
)
194 PwmdCommandQueueItem
*item
= new PwmdCommandQueueItem (PwmdCmdIdSaveDeleteKey
,
195 "DELETEKEY", nullptr,
196 new PwmdInquireData (data
->subKey ()->fingerprint ()));
201 PwmdSaveWidget::slotCommandResult (PwmdCommandQueueItem
*item
,
202 QString result
, gpg_error_t rc
, bool queued
)
204 PwmdInquireData
*inq
= item
->data ();
206 if ((item
->id () >= 0 && item
->id () <= PwmdCmdIdOpenMax
)
207 || item
->id () >= PwmdCmdIdSaveMax
)
215 case PwmdCmdIdInternalConnect
:
216 case PwmdCmdIdInternalOpen
:
217 case PwmdCmdIdInternalPassword
:
220 case PwmdCmdIdInternalSave
:
221 (void)pwmd_setopt (pwm
->handle (), PWMD_OPTION_LOCAL_PINENTRY
, 0);
222 (void)pwmd_setopt (pwm
->handle (), PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
225 case PwmdCmdIdSaveKeyInfo
:
227 updateCurrentKeyInfoFinalize (result
);
229 case PwmdCmdIdInternalGenKey
:
230 (void)pwmd_setopt (pwm
->handle (), PWMD_OPTION_LOCAL_PINENTRY
, 0);
231 (void)pwmd_setopt (pwm
->handle (), PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
233 refreshKeyLists (true);
240 case PwmdCmdIdSaveLearn
:
242 refreshKeyLists (true);
244 case PwmdCmdIdSaveListKeys
:
246 getKeyListFinalize (result
, inq
->userBool());
248 case PwmdCmdIdSaveDeleteKey
:
250 refreshKeyLists (true);
256 if (rc
&& !item
->checkError (rc
) && !queued
)
257 Pwmd::showError (rc
, pwm
);
263 PwmdSaveWidget::slotSelectKeyFile ()
265 PwmdPasswordDialog
*d
= new PwmdPasswordDialog (this);
267 slotConfirmKeySelection ();
268 d
->setSymmetric (ui
.ck_symmetric
->isChecked ());
269 d
->setHasSigners (!newSigners
.isEmpty ());
270 d
->setNewFile (newFile
);
271 d
->setDecryptKeyFile (keyFile
);
272 d
->setEncryptKeyFile (encryptKeyFile
);
273 d
->setSignKeyFile (signKeyFile
);
275 if (d
->exec () && d
->useKeyFile ())
277 keyFile
= d
->decryptKeyFile ();
278 encryptKeyFile
= d
->encryptKeyFile ();
279 signKeyFile
= d
->signKeyFile ();
282 keyFile
= encryptKeyFile
= signKeyFile
= QString ();
288 PwmdSaveWidget::slotSecretOnlyChanged (int s
)
290 updateKeyList (s
== Qt::Checked
);
294 PwmdSaveWidget::resetRecipients ()
296 newRecipients
= QString ();
297 newSigners
= QString ();
298 clearRecipientList ();
302 PwmdSaveWidget::slotResetRecipients ()
304 if (keyList
.count() && (recipients().isEmpty () || signers().isEmpty()))
305 updateCurrentKeyInfo ();
307 setKeyListRecipients ();
311 PwmdSaveWidget::slotSymmetricChanged (int s
)
313 bool b
= s
== Qt::Checked
? true : false;
315 ui
.ck_secretOnly
->setChecked (b
);
316 ui
.ck_secretOnly
->setEnabled (!b
);
317 ui
.pb_keyFileOptions
->setEnabled (ui
.recipientList
->topLevelItemCount () || b
);
318 emit
saveReady (testRecipients ());
322 PwmdSaveWidget::reset ()
327 PwmdSaveWidget::needsRefresh ()
329 return _needsRefresh
;
333 PwmdSaveWidget::setNeedsRefresh (bool b
)
339 PwmdSaveWidget::refreshKeyLists (bool force
)
341 slotResetRecipients ();
343 if (needsRefresh () || force
)
345 _recipients
= QString ();
346 _signers
= QString ();
347 updateCurrentKeyInfo ();
348 getKeyList (QString (), force
, ui
.ck_symmetric
->isChecked ());
353 PwmdSaveWidget::showEvent (QShowEvent
*ev
)
355 if (!ev
->spontaneous())
356 refreshKeyLists (false);
358 QFrame::showEvent (ev
);
362 PwmdSaveWidget::updateCurrentKeyInfoFinalize (const QString
&result
)
364 QStringList list
= result
.split ("\n");
368 for (int n
= 0; n
< list
.count(); n
++)
370 if (list
.at(n
).at(0) == 'S' && !sign
)
381 str
.append (list
.at(n
).mid(1)+",");
383 str
.append (list
.at(n
)+",");
395 setNeedsRefresh (false);
399 PwmdSaveWidget::updateCurrentKeyInfo ()
401 pwm
->command (new PwmdCommandQueueItem (PwmdCmdIdSaveKeyInfo
, "KEYINFO",
402 nullptr, new PwmdInquireData ()));
406 PwmdSaveWidget::slotHeaderSectionResized (int idx
, int old
, int newSize
)
411 QByteArray b
= ui
.keyList
->header()->saveState();
413 ui
.recipientList
->header()->restoreState (b
);
417 PwmdSaveWidget::keyPressEvent (QKeyEvent
*ev
)
419 QFrame::keyPressEvent (ev
);
423 PwmdSaveWidget::setSymmetric ()
425 if (recipients().isEmpty ())
427 ui
.ck_symmetric
->setHidden (!newFile
);
428 ui
.ck_symmetric
->setChecked (!newFile
);
432 ui
.ck_symmetric
->setHidden (!newFile
);
433 ui
.ck_symmetric
->setChecked (false);
438 PwmdSaveWidget::setIsNew (bool b
)
445 PwmdSaveWidget::setHandle (Pwmd
*p
, bool isNewFile
)
448 disconnect (pwm
, SIGNAL (commandResult (PwmdCommandQueueItem
*, QString
, gpg_error_t
, bool)), this, SLOT (slotCommandResult (PwmdCommandQueueItem
*, QString
, gpg_error_t
, bool)));
451 connect (pwm
, SIGNAL (commandResult (PwmdCommandQueueItem
*, QString
, gpg_error_t
, bool)), this, SLOT (slotCommandResult (PwmdCommandQueueItem
*, QString
, gpg_error_t
, bool)));
452 connect (pwm
, SIGNAL (statusMessage (QString
, void *)), this,
453 SLOT (slotStatusMessage (QString
, void *)));
454 setIsNew (isNewFile
);
458 PwmdSaveWidget::saveFinalize ()
461 _signers
= newSigners
;
462 _recipients
= newRecipients
;
463 updateCurrentKeyInfo ();
464 setKeyListRecipients ();
468 PwmdSaveWidget::save (const QString
&args
, bool fromWidget
)
472 PwmdInquireData
*inq
= new PwmdInquireData (pwm
->handle (), pwm
->filename ());
473 QString saveArgs
= args
;
474 bool useKeyFile
= false;
478 pwm
->save (saveArgs
, Pwmd::inquireCallback
, inq
);
482 slotConfirmKeySelection ();
484 if (!keyFile
.isEmpty () || !encryptKeyFile
.isEmpty ()
485 || !signKeyFile
.isEmpty())
488 if (ui
.ck_symmetric
->isChecked () && ui
.ck_symmetric
->isEnabled ())
489 saveArgs
.append (" --symmetric");
491 if (!newRecipients
.isEmpty())
492 saveArgs
.append(QString(" --keyid=%1").arg (newRecipients
));
494 if (!newSigners
.isEmpty())
495 saveArgs
.append(QString(" --sign-keyid=%1").arg (newSigners
));
496 else if (newSigners
.isEmpty() && ui
.ck_symmetric
->isChecked() && !init
)
497 saveArgs
.append(QString(" --sign-keyid="));
503 pwmd_socket_type (pwm
->handle (), &type
);
504 if (type
!= PWMD_SOCKET_LOCAL
|| useKeyFile
)
508 inq
->setKeyFile (keyFile
);
509 inq
->setEncryptKeyFile (encryptKeyFile
);
510 inq
->setSignKeyFile (signKeyFile
);
513 rc
= pwmd_setopt (pwm
->handle (), PWMD_OPTION_LOCAL_PINENTRY
, 1);
515 rc
= pwmd_setopt (pwm
->handle (), PWMD_OPTION_OVERRIDE_INQUIRE
, 1);
524 pwm
->save (saveArgs
, Pwmd::inquireCallback
, inq
);
527 pwm
->save (saveArgs
, Pwmd::inquireCallback
, inq
);
533 keyFlags (PwmdKey
*key
)
537 if (key
->canEncrypt())
543 if (key
->canCertify())
546 if (key
->canAuthenticate())
553 currentKeyListItemIndex (QTreeWidget
*w
, QTreeWidgetItem
*item
)
556 QList
< QTreeWidgetItem
* >list
= w
->findItems ("*", Qt::MatchWildcard
| Qt::MatchRecursive
);
558 for (i
= 0; i
< list
.count(); i
++)
560 if (list
.at(i
) == item
)
568 openpgp_algorithm (PwmdSubKey
*key
)
570 switch (key
->pubkeyAlgo())
589 return QApplication::tr("unknown");
593 PwmdSaveWidget::slotKeyIdChanged (QTreeWidgetItem
* item
,
594 QTreeWidgetItem
* old
)
600 if (old
&& old
->treeWidget () == ui
.keyList
)
601 ui
.tb_addRecipient
->setEnabled (false);
602 else if (old
&& old
->treeWidget () == ui
.recipientList
)
603 ui
.tb_removeRecipient
->setEnabled (false);
607 ui
.pb_keyFileOptions
->setEnabled (ui
.recipientList
->topLevelItemCount ()
608 || ui
.ck_symmetric
->isChecked ());
609 PwmdKeyItemData
*data
= qvariant_cast
<PwmdKeyItemData
* >(item
->data (0, Qt::UserRole
));
610 ui
.l_fingerprint
->setText(data
->subKey()->fingerprint());
611 ui
.l_keygrip
->setText(data
->subKey()->keygrip());
613 QString cn
= data
->subKey()->cardNumber();
614 ui
.l_cardNumber
->setText(cn
.isEmpty () ? "-" : cn
);
616 QDateTime t
= QDateTime::fromSecsSinceEpoch (data
->subKey()->created());
617 ui
.l_created
->setText(t
.toString("MM/dd/yyyy hh:mm:ss"));
619 if (data
->subKey()->expires())
621 t
= QDateTime::fromSecsSinceEpoch (data
->subKey()->expires());
622 ui
.l_expires
->setText(t
.toString("MM/dd/yyyy hh:mm:ss"));
625 ui
.l_expires
->setText("-");
627 if (data
->subKey()->curve().isEmpty ())
628 ui
.l_algorithm
->setText (QString ("%1-%2").arg (openpgp_algorithm(data
->subKey())).arg (data
->subKey()->nBits()));
630 ui
.l_algorithm
->setText (QString ("%1-%2-%3").arg (openpgp_algorithm(data
->subKey())).arg (data
->subKey()->nBits()).arg (data
->subKey()->curve()));
632 if (item
->treeWidget () == ui
.keyList
)
634 if (ui
.ck_symmetric
->isChecked () && !data
->subKey()->canSign ())
635 ui
.tb_addRecipient
->setEnabled (false);
637 ui
.tb_addRecipient
->setEnabled (true);
639 else if (item
->treeWidget () == ui
.recipientList
)
640 ui
.tb_removeRecipient
->setEnabled (true);
642 ui
.keyList
->scrollToItem (item
);
645 currentKeyListIndex
= currentKeyListItemIndex (ui
.keyList
,
646 ui
.keyList
->currentItem ());
650 PwmdSaveWidget::slotConfirmKeySelection ()
652 QList
<QTreeWidgetItem
*> list
;
654 list
= ui
.recipientList
->findItems ("*", Qt::MatchWildcard
);
656 QString signer
, recipient
;
658 for (i
= 0; i
< list
.count(); i
++)
660 QTreeWidgetItem
*item
= list
.at(i
);
661 PwmdKeyItemData
*data
= qvariant_cast
<PwmdKeyItemData
* >(item
->data (0, Qt::UserRole
));
662 PwmdSubKey
*s
= data
->subKey();
665 signer
.append (s
->fingerprint()+",");
668 recipient
.append (s
->keyId()+",");
674 if (recipient
.size())
678 newRecipients
= recipient
;
682 PwmdSaveWidget::slotRefreshKeyList ()
684 ui
.l_created
->setText (tr("-"));
685 ui
.l_expires
->setText (tr("-"));
686 ui
.l_fingerprint
->setText (tr("-"));
687 ui
.l_keygrip
->setText (tr("-"));
688 ui
.l_cardNumber
->setText (tr("-"));
689 getKeyList (QString (), true, selectSignKeyId
);
690 updateCurrentKeyInfo ();
694 PwmdSaveWidget::searchKeyList (const QString
&str
, int &index
, bool next
,
697 QList
< QTreeWidgetItem
* >items
= ui
.keyList
->findItems ("*", Qt::MatchWildcard
| Qt::MatchRecursive
);
699 QTreeWidgetItem
*item
= nullptr;
701 if (index
>= items
.count())
704 x
= index
< 0 ? 0 : index
;
706 for (i
= x
; i
< items
.count(); i
++)
709 if (item
->isHidden())
712 PwmdKeyItemData
*data
= qvariant_cast
<PwmdKeyItemData
* >(item
->data (0, Qt::UserRole
));
715 for (n
= 0; n
< data
->key()->userIds().count(); n
++)
717 if (data
->key()->userIds().at(n
)->userId().contains (str
, Qt::CaseInsensitive
)
718 && ui
.keyList
->indexOfTopLevelItem (item
) != -1)
720 else if (data
->key()->userIds().at(n
)->comment().contains (str
, Qt::CaseInsensitive
)
721 && ui
.keyList
->indexOfTopLevelItem (item
) != -1)
725 if (data
->subKey()->fingerprint().contains (str
, Qt::CaseInsensitive
))
727 if (data
->subKey()->keygrip().contains (str
, Qt::CaseInsensitive
))
729 else if (data
->subKey()->keyId().contains (str
, Qt::CaseInsensitive
))
734 if (i
< items
.count())
736 else if (next
&& !wrapAround
)
739 item
= searchKeyList (str
, x
, next
, true);
745 return i
< items
.count() ? item
: nullptr;
749 PwmdSaveWidget::slotSearchKeyListChanged (const QString
&str
)
751 ui
.tb_searchKeyList
->setEnabled (!str
.isEmpty ());
755 int n
= currentKeyListIndex
;
756 QTreeWidgetItem
*item
= searchKeyList (str
, n
);
760 ui
.keyList
->setCurrentItem (item
);
761 ui
.keyList
->scrollToItem (item
);
765 PwmdSaveWidget::slotFindKeyActivated ()
767 ui
.le_searchKeyList
->setFocus ();
768 if (ui
.le_searchKeyList
->text ().isEmpty ())
771 ui
.le_searchKeyList
->setSelection (0, ui
.le_searchKeyList
->text ().length ());
775 PwmdSaveWidget::slotSearchKeyList ()
777 if (ui
.le_searchKeyList
->text ().isEmpty ())
780 QTreeWidgetItem
*item
= searchKeyList (ui
.le_searchKeyList
->text(),
781 currentKeyListIndex
, true);
785 // Fixes slotKeyIdChanged changing currentKeyListIndex.
787 ui
.keyList
->setCurrentItem (item
);
788 ui
.keyList
->scrollToItem (item
);
793 ownerTrust (PwmdKey
*key
)
795 if (key
->protocol() != 0) // GPGME_PROTOCOL_OPENPGP
798 switch (key
->ownerTrust())
801 return QApplication::tr("Unknown");
803 return QApplication::tr("Undefined");
805 return QApplication::tr("Never");
807 return QApplication::tr("Marginal");
809 return QApplication::tr("Full");
811 return QApplication::tr("Ultimate");
818 validity (PwmdKey
*key
)
820 QString s
= QString ();
822 if (key
->isRevoked())
823 s
= QApplication::tr("Revoked");
824 else if (key
->isExpired())
825 s
= QApplication::tr("Expired");
826 else if (key
->isInvalid())
827 s
= QApplication::tr("Invalid");
828 else if (key
->isDisabled())
829 s
= QApplication::tr("Disabled");
831 s
= QApplication::tr ("Valid");
837 PwmdSaveWidget::createSubKeyItemOnce (QTreeWidgetItem
*item
, QString keyId
,
838 PwmdKey
*key
, QString uids
)
840 item
->setText (0, QString ("0x")+keyId
.right (8));
841 item
->setText (1, validity (key
));
842 item
->setText (2, ownerTrust (key
));
843 item
->setText (3, keyFlags (key
));
844 item
->setText (4, uids
);
848 buildKeyUserIds (PwmdKey
*key
)
853 for (i
= 0; i
< key
->userIds().count(); i
++)
854 uids
+= key
->userIds().at(i
)->userId() + "\n";
861 PwmdSaveWidget::createSubKeyItem (PwmdKey
*key
)
865 QTreeWidgetItem
*parent
= nullptr;
866 PwmdSubKey
*subKey
= key
->subKeys().at(0);
867 QTreeWidgetItem
*item
= new QTreeWidgetItem (parent
);
868 PwmdKeyItemData
*data
= new PwmdKeyItemData (key
, subKey
);
870 uids
= buildKeyUserIds (key
);
871 item
->setTextAlignment (0, Qt::AlignTop
);
872 item
->setTextAlignment (1, Qt::AlignTop
);
873 item
->setTextAlignment (2, Qt::AlignTop
);
874 item
->setTextAlignment (3, Qt::AlignTop
);
875 item
->setTextAlignment (4, Qt::AlignTop
);
876 createSubKeyItemOnce (item
, subKey
->keyId(), key
, uids
);
877 item
->setData (0, Qt::UserRole
, QVariant::fromValue (data
));
878 ui
.keyList
->addTopLevelItem (item
);
881 for (i
= 0; i
< key
->subKeys().count(); i
++)
883 subKey
= key
->subKeys().at(i
);
884 item
= new QTreeWidgetItem (parent
);
885 data
= new PwmdKeyItemData (key
, subKey
);
886 item
->setTextAlignment (0, Qt::AlignTop
);
887 item
->setTextAlignment (1, Qt::AlignTop
);
888 item
->setTextAlignment (2, Qt::AlignTop
);
889 item
->setTextAlignment (3, Qt::AlignTop
);
890 createSubKeyItemOnce (item
, subKey
->keyId(), subKey
);
891 item
->setData (0, Qt::UserRole
, QVariant::fromValue (data
));
896 PwmdSaveWidget::setKeyListRecipients ()
898 clearRecipientList ();
899 doSetKeyListRecipients (recipients());
900 doSetKeyListRecipients (signers());
901 emit
saveReady (testRecipients ());
905 PwmdSaveWidget::doSetKeyListRecipients (QString keys
)
908 QList
<QTreeWidgetItem
*> list
= ui
.keyList
->findItems ("*",
912 r
= keys
.split (",");
913 r
.removeDuplicates();
915 for (i
= 0; i
< r
.count(); i
++)
919 if (r
.at(i
).isEmpty())
922 for (n
= 0; n
< list
.count(); n
++)
924 QTreeWidgetItem
*item
= list
.at(n
);
925 PwmdKeyItemData
*data
= qvariant_cast
<PwmdKeyItemData
* >(item
->data (0, Qt::UserRole
));
926 QString keyId
= data
->subKey()->keyId ();
927 QString fpr
= data
->subKey()->fingerprint ();
930 if (keyId
.right (8).toLower () == r
.at(i
).right (8).toLower ()
931 || fpr
.right (8).toLower () == r
.at(i
).right (8).toLower ())
937 for (c
= 0; c
< item
->childCount(); c
++)
939 QTreeWidgetItem
*child
= item
->child(c
);
941 data
= qvariant_cast
<PwmdKeyItemData
* >(child
->data (0, Qt::UserRole
));
942 keyId
= data
->subKey()->keyId ();
943 fpr
= data
->subKey()->fingerprint ();
945 if (keyId
.right (8).toLower () == r
.at(i
).right (8).toLower ()
946 || fpr
.right (8).toLower () == r
.at(i
).right (8).toLower ())
957 PwmdSaveWidget::updateKeyList (bool secret
)
959 QList
<QTreeWidgetItem
*> list
= ui
.keyList
->findItems ("*",
960 Qt::MatchWildcard
|Qt::MatchRecursive
);
963 selectSignKeyId
= secret
;
965 for (n
= 0; n
< list
.count(); n
++)
967 QTreeWidgetItem
*item
= list
.at(n
);
968 PwmdKeyItemData
*data
= qvariant_cast
<PwmdKeyItemData
* >(item
->data (0, Qt::UserRole
));
969 Qt::ItemFlags flags
= item
->flags();
970 bool hasSecret
= data
->key()->isSecret();
971 bool revoked
= data
->key()->isRevoked() || data
->subKey()->isRevoked();
973 if (!data
->key()->isSecret() && secret
)
974 item
->setHidden (true);
976 item
->setHidden (false);
978 if (data
->key()->canEncrypt() || data
->subKey()->canEncrypt()
979 || ((data
->key()->canSign() || data
->subKey()->canSign()) && hasSecret
))
980 flags
|= Qt::ItemIsSelectable
;
982 flags
&= ~Qt::ItemIsSelectable
;
985 flags
&= ~Qt::ItemIsSelectable
;
987 item
->setFlags (flags
);
990 setKeyListRecipients ();
991 if (ui
.recipientList
->topLevelItemCount ())
993 QTreeWidgetItem
*item
= ui
.recipientList
->topLevelItem (0);
994 PwmdKeyItemData
*data
= qvariant_cast
<PwmdKeyItemData
* >(item
->data (0, Qt::UserRole
));
995 slotJumpToKey (data
->subKey()->fingerprint ());
996 ui
.recipientList
->setCurrentItem (item
);
997 ui
.recipientList
->scrollToItem (item
);
1002 openpgp_unescape (QString str
)
1004 str
.replace (QString("\\x3a"), QString(":"));
1005 str
.replace ("\\x5c", "\\");
1010 PwmdSaveWidget::clearRecipientList ()
1012 ui
.recipientList
->clear ();
1016 PwmdSaveWidget::clearKeyList ()
1018 while (!keyList
.isEmpty ())
1020 PwmdKey
*key
= keyList
.takeFirst ();
1024 foreach (QTreeWidgetItem
*item
,
1025 ui
.keyList
->findItems ("*", Qt::MatchWildcard
| Qt::MatchRecursive
))
1027 PwmdKeyItemData
*data
= qvariant_cast
<PwmdKeyItemData
* >(item
->data (0, Qt::UserRole
));
1028 data
->setKey (nullptr);
1029 data
->setSubKey (nullptr);
1033 ui
.keyList
->clear ();
1034 clearRecipientList ();
1038 PwmdSaveWidget::getKeyListFinalize (const QString
&result
, bool secret
)
1042 QList
<PwmdKey
*> newKeys
;
1044 if (result
.isEmpty())
1047 lines
= result
.split ("\n");
1048 for (l
= 0; l
< lines
.count(); l
++)
1050 PwmdKey
*key
= new PwmdKey();
1051 QStringList fields
= lines
.at(l
).split (":");
1053 QList
<PwmdSubKey
*> subKeys
;
1054 QList
<PwmdUserId
*> userIds
;
1055 unsigned n_subKeys
= 0, s
;
1057 for (f
= i
= 0; i
< 17; i
++, f
++)
1062 b
= fields
.at(f
).toInt() == 0 ? false : true;
1066 case 0: key
->setRevoked(b
); break;
1067 case 1: key
->setExpired(b
); break;
1068 case 2: key
->setDisabled(b
); break;
1069 case 3: key
->setInvalid(b
); break;
1070 case 4: key
->setCanEncrypt(b
); break;
1071 case 5: key
->setCanSign(b
); break;
1072 case 6: key
->setCanCertify(b
); break;
1073 case 7: key
->setSecret(b
); break;
1074 case 8: key
->setCanAuthenticate(b
); break;
1075 case 9: key
->setQualified(b
); break;
1076 case 10: key
->setProtocol(fields
.at(f
).toInt()); break;
1077 case 11: key
->setIssuerSerial(fields
.at(f
)); break;
1078 case 12: key
->setIssuerName(fields
.at(f
)); break;
1079 case 13: key
->setChainId(fields
.at(f
)); break;
1080 case 14: key
->setOwnerTrust(fields
.at(f
).toInt()); break;
1081 case 15: break; // n_userIds = fields.at(f).toUInt(); break;
1082 case 16: n_subKeys
= fields
.at(f
).toUInt(); break;
1086 for (s
= 0; s
< n_subKeys
; s
++)
1088 PwmdSubKey
*subKey
= new PwmdSubKey();
1091 for (i
= 0; i
< 20; i
++, f
++)
1094 b
= fields
.at(f
).toInt() == 0 ? false : true;
1098 case 0: subKey
->setRevoked(b
); break;
1099 case 1: subKey
->setExpired(b
); break;
1100 case 2: subKey
->setDisabled(b
); break;
1101 case 3: subKey
->setInvalid(b
); break;
1102 case 4: subKey
->setCanEncrypt(b
); break;
1103 case 5: subKey
->setCanSign(b
); break;
1104 case 6: subKey
->setCanCertify(b
); break;
1105 case 7: subKey
->setSecret(b
); break;
1106 case 8: subKey
->setCanAuthenticate(b
); break;
1107 case 9: subKey
->setQualified(b
); break;
1108 case 10: subKey
->setCardKey(b
); break;
1109 case 11: subKey
->setPubkeyAlgo(fields
.at(f
).toInt()); break;
1110 case 12: subKey
->setNBits(fields
.at(f
).toUInt()); break;
1111 case 13: subKey
->setKeyId (fields
.at(f
)); break;
1112 case 14: subKey
->setFingerprint (fields
.at(f
)); break;
1113 case 15: subKey
->setKeygrip (fields
.at(f
)); break;
1114 case 16: subKey
->setCreated (fields
.at(f
).toLong()); break;
1115 case 17: subKey
->setExpires (fields
.at(f
).toLong()); break;
1116 case 18: subKey
->setCardNumber (fields
.at(f
).length() > 1
1117 ? fields
.at(f
) : QString ());
1119 case 19: subKey
->setCurve (openpgp_unescape (fields
.at (f
)));
1124 subKeys
.append (subKey
);
1127 // Re-create a line containing the userIds.
1128 for (; f
< fields
.count (); f
++)
1130 PwmdUserId
*userId
= new PwmdUserId();
1132 userId
->setRevoked (fields
.at(f
++).toUInt());
1133 userId
->setInvalid (fields
.at(f
++).toUInt());
1134 userId
->setValidity (fields
.at(f
++).toUInt());
1135 userId
->setUserId (openpgp_unescape (fields
.at(f
++)));
1136 userId
->setName (openpgp_unescape (fields
.at(f
++)));
1137 userId
->setEmail (openpgp_unescape (fields
.at(f
++)));
1138 userId
->setComment (openpgp_unescape (fields
.at(f
)));
1139 userIds
.append(userId
);
1142 key
->setSubkeys (subKeys
);
1143 key
->setUserIds (userIds
);
1144 newKeys
.append (key
);
1150 for (l
= 0; l
< keyList
.count(); l
++)
1151 createSubKeyItem (keyList
.at(l
));
1154 updateKeyList (secret
);
1156 if (!generatedKeyId
.isEmpty ())
1157 slotJumpToKey (generatedKeyId
);
1159 generatedKeyId
= QString ();
1163 PwmdSaveWidget::getKeyList (const QString
&s
, bool force
, bool secret
)
1165 if (keyList
.count() && !force
)
1167 updateKeyList (secret
);
1171 PwmdInquireData
*inq
= new PwmdInquireData (s
);
1172 inq
->setUserBool (secret
);
1173 PwmdCommandQueueItem
*item
= new PwmdCommandQueueItem (PwmdCmdIdSaveListKeys
,
1175 Pwmd::inquireCallback
,
1177 pwm
->command (item
);
1181 PwmdSaveWidget::slotRemoveRecipients ()
1183 QList
<QTreeWidgetItem
*> list
= ui
.recipientList
->selectedItems ();
1185 while (!list
.isEmpty ())
1187 QTreeWidgetItem
*item
= list
.takeFirst ();
1188 int n
= ui
.recipientList
->indexOfTopLevelItem (item
);
1190 ui
.recipientList
->takeTopLevelItem (n
);
1194 ui
.pb_keyFileOptions
->setEnabled (ui
.recipientList
->topLevelItemCount ()
1195 || ui
.ck_symmetric
->isChecked ());
1196 emit
saveReady (testRecipients ());
1200 PwmdSaveWidget::addRecipient (PwmdKeyItemData
*data
)
1202 QTreeWidgetItem
*newItem
= new QTreeWidgetItem ();
1203 PwmdKey
*key
= data
->key ();
1204 PwmdSubKey
*subKey
= data
->subKey ();
1206 newItem
->setTextAlignment (0, Qt::AlignTop
);
1207 newItem
->setTextAlignment (1, Qt::AlignTop
);
1208 newItem
->setTextAlignment (2, Qt::AlignTop
);
1209 newItem
->setTextAlignment (3, Qt::AlignTop
);
1210 newItem
->setTextAlignment (4, Qt::AlignTop
);
1212 if (subKey
->canSign ())
1214 QList
< QTreeWidgetItem
* >list
= ui
.recipientList
->findItems ("*", Qt::MatchWildcard
| Qt::MatchRecursive
);
1215 foreach (QTreeWidgetItem
*item
, list
)
1217 PwmdKeyItemData
*d
= qvariant_cast
<PwmdKeyItemData
* >(item
->data (0, Qt::UserRole
));
1218 if (d
->subKey ()->canSign ())
1220 ui
.recipientList
->takeTopLevelItem (ui
.recipientList
->indexOfTopLevelItem (item
));
1227 createSubKeyItemOnce (newItem
, subKey
->keyId(), subKey
, buildKeyUserIds(key
));
1228 newItem
->setData (0, Qt::UserRole
, QVariant::fromValue (data
));
1229 ui
.recipientList
->addTopLevelItem (newItem
);
1230 ui
.pb_keyFileOptions
->setEnabled (true);
1234 PwmdSaveWidget::slotAddSubKey ()
1236 QList
<QTreeWidgetItem
*> keys
= ui
.keyList
->selectedItems();
1237 QTreeWidgetItem
*item
= keys
.at (0);
1239 PwmdKeyItemData
*data
= qvariant_cast
<PwmdKeyItemData
* >(item
->data (0, Qt::UserRole
));
1240 PwmdKeyGenDialog
d (this, pwm
);
1241 d
.setSubKey (data
->key ());
1246 PwmdSaveWidget::testRecipients ()
1249 bool encrypt
= false;
1251 if (ui
.ck_symmetric
->isChecked ())
1254 QList
< QTreeWidgetItem
* >list
= ui
.recipientList
->findItems ("*", Qt::MatchWildcard
| Qt::MatchRecursive
);
1256 foreach (QTreeWidgetItem
*item
, list
)
1258 PwmdKeyItemData
*data
= qvariant_cast
<PwmdKeyItemData
* >(item
->data (0, Qt::UserRole
));
1259 PwmdSubKey
*s
= data
->subKey();
1264 if (s
->canEncrypt ())
1268 return sign
&& encrypt
? true : false;
1272 PwmdSaveWidget::slotAddRecipients ()
1274 QList
<QTreeWidgetItem
*> list
= ui
.keyList
->selectedItems();
1276 while (!list
.isEmpty ())
1278 QTreeWidgetItem
*item
= list
.takeFirst ();
1279 PwmdKeyItemData
*data
= qvariant_cast
<PwmdKeyItemData
* >(item
->data (0, Qt::UserRole
));
1280 PwmdSubKey
*s
= data
->subKey ();
1282 if (ui
.ck_symmetric
->isChecked () && !s
->canSign ())
1285 addRecipient (data
);
1288 emit
saveReady (testRecipients ());
1292 PwmdSaveWidget::changeKeyListFocus (PwmdKeyTreeWidget
*w
, bool out
)
1295 slotKeyIdChanged (w
->currentItem(), nullptr);
1299 PwmdSaveWidget::recipients ()
1305 PwmdSaveWidget::signers ()
1311 PwmdSaveWidget::slotJumpToKey (const QString
&fpr
)
1317 QList
<QTreeWidgetItem
*> list
= ui
.recipientList
->selectedItems();
1319 if (list
.isEmpty ())
1322 QTreeWidgetItem
*item
= list
.at(0);
1323 PwmdKeyItemData
*data
= qvariant_cast
<PwmdKeyItemData
* >(item
->data (0, Qt::UserRole
));
1324 s
= data
->subKey()->fingerprint ();
1328 QTreeWidgetItem
*match
= searchKeyList (s
, n
);
1331 ui
.keyList
->setCurrentItem (match
);
1332 ui
.keyList
->scrollToItem (match
);