Line data Source code
1 : // SPDX-FileCopyrightText: 2026 Anne Jan Brouwer
2 : // SPDX-License-Identifier: GPL-3.0-or-later
3 : /**
4 : * @file
5 : * @brief Dialog that imports an ASCII-armored GPG public key from a file or
6 : * the clipboard by running `gpg --import`.
7 : */
8 : #ifndef SRC_IMPORTKEYDIALOG_H_
9 : #define SRC_IMPORTKEYDIALOG_H_
10 :
11 : #include <QDialog>
12 : #include <QScopedPointer>
13 : #include <QString>
14 :
15 : namespace Ui {
16 : class ImportKeyDialog;
17 : }
18 :
19 : /**
20 : * @class ImportKeyDialog
21 : * @ingroup keys
22 : * @brief Dialog for importing GPG keys from file or clipboard.
23 : *
24 : * Allows users to import GPG public keys without leaving QtPass.
25 : * Offers two import paths: from file or from clipboard text.
26 : */
27 : class ImportKeyDialog : public QDialog {
28 26 : Q_OBJECT
29 :
30 : public:
31 : /**
32 : * @brief Construct an ImportKeyDialog.
33 : * @param gpgExe Path to the gpg executable (falls back to "gpg" if empty).
34 : * @param parent Optional parent widget.
35 : */
36 : explicit ImportKeyDialog(const QString &gpgExe, QWidget *parent = nullptr);
37 : /** @brief Destroys the dialog and its generated UI. */
38 : ~ImportKeyDialog() override;
39 :
40 : /**
41 : * @brief Get the imported key id on success.
42 : * @return The imported key id (or fingerprint when GnuPG status output
43 : * provides one), or empty if import failed.
44 : */
45 : auto importedKeyId() const -> QString;
46 :
47 : /**
48 : * @brief Parse GPG import output to extract a key id or fingerprint.
49 : *
50 : * Prefers locale-independent status lines (\c [GNUPG:] IMPORT_OK and
51 : * \c [GNUPG:] IMPORTED) when present, then falls back to the
52 : * human-readable \c "gpg: key ...: imported" line (English locale only).
53 : *
54 : * @param output Combined stdout/stderr from `gpg --import --status-fd 1`.
55 : * @return The imported key id or fingerprint, or empty if not found.
56 : */
57 : static auto parseGpgImportOutput(const QString &output) -> QString;
58 :
59 : private slots:
60 : /**
61 : * @brief "From file" button: picks a file, reads it as a regular file of at
62 : * most 16 MiB, requires the `-----BEGIN PGP` armor header and loads the
63 : * text into the input field. Binary keyrings are refused with a hint to
64 : * `gpg --armor --export` first.
65 : */
66 : void on_fileButton_clicked();
67 :
68 : /**
69 : * @brief "From clipboard" button: replaces the input field with the
70 : * clipboard text, unless the clipboard is empty.
71 : */
72 : void on_pasteButton_clicked();
73 :
74 : /**
75 : * @brief "Import" button: runs importFromString() on the trimmed input and
76 : * closes the dialog with `accept()` on success.
77 : */
78 : void on_importButton_clicked();
79 :
80 : /**
81 : * @brief Enables the Import button only while the input field holds
82 : * non-blank text.
83 : */
84 : void on_inputTextEdit_textChanged();
85 :
86 : private:
87 : /** @brief Generated form (`importkeydialog.ui`); owned. */
88 : QScopedPointer<Ui::ImportKeyDialog> ui;
89 : /** @brief Key id or fingerprint of the last successful import; empty until
90 : * then. Read back through importedKeyId(). */
91 : QString m_importedKeyId;
92 : /** @brief Path of the gpg binary to run; empty means plain `gpg` on PATH. */
93 : QString m_gpgExe;
94 :
95 : /**
96 : * @brief Feeds @p input to `gpg --status-fd 1 --import --batch --yes` via
97 : * Executor::executeBlocking() and records the imported key id.
98 : * @param input Armored key text, trimmed.
99 : * @return true when gpg exited with 0 and a key id could be parsed from its
100 : * output; false after showError() otherwise.
101 : */
102 : auto importFromString(const QString &input) -> bool;
103 : /**
104 : * @brief Shows @p message in a plain-text warning box (gpg's stderr quotes
105 : * user IDs, which must not be read as markup).
106 : * @param message The error text.
107 : */
108 : void showError(const QString &message);
109 : /**
110 : * @brief Shows the "imported, now verify the fingerprint" information box.
111 : * @param keyId The imported key id or fingerprint.
112 : */
113 : void showSuccess(const QString &keyId);
114 : };
115 : #endif // SRC_IMPORTKEYDIALOG_H_
|