QtPass Developer documentation
QtPass test coverage
Current view: top level - src/keygendialog.h Coverage Total Hit
Test: QtPass Lines: 100.0 % 1 1
Test Date: 2026-11-14 13:19:18 Functions: - 0 0

            Line data    Source code
       1              : // SPDX-FileCopyrightText: 2015 Anne Jan Brouwer
       2              : // SPDX-License-Identifier: GPL-3.0-or-later
       3              : /**
       4              :  * @file
       5              :  * @brief Dialog that collects name, e-mail and passphrase for a new GPG
       6              :  * keypair and drives `gpg --gen-key --batch` through the Pass backend.
       7              :  */
       8              : #ifndef SRC_KEYGENDIALOG_H_
       9              : #define SRC_KEYGENDIALOG_H_
      10              : 
      11              : #include <QDialog>
      12              : #include <QScopedPointer>
      13              : #include <memory>
      14              : 
      15              : #include "qprogressindicator.h"
      16              : 
      17              : namespace Ui {
      18              : class KeygenDialog;
      19              : }
      20              : 
      21              : class Pass;
      22              : 
      23              : /**
      24              :  * @class KeygenDialog
      25              :  * @ingroup keys
      26              :  * @brief Handles GPG keypair generation.
      27              :  *
      28              :  * The form asks for a name, an e-mail address and a passphrase typed twice
      29              :  * (or an explicit "no passphrase"); an Expert checkbox reveals the editable
      30              :  * GPG batch template that the name and e-mail fields are mirrored into. The
      31              :  * passphrase is never written into that template: on OK, done() validates
      32              :  * the fields, splices the passphrase in with applyPassphrase() and hands the
      33              :  * batch to Pass::GenerateGPGKeys(), replacing the form with a progress
      34              :  * indicator. The dialog owns nothing of the backend; it connects to
      35              :  * Pass::finishedGenerateGPGKeys (accept) and Pass::generateGPGKeysFailed
      36              :  * (show the error and give the form back) for the duration of one attempt
      37              :  * only, so an `exec()` caller such as the first-run wizard sees `Accepted`
      38              :  * exactly when a key exists.
      39              :  */
      40              : class KeygenDialog : public QDialog {
      41           10 :   Q_OBJECT
      42              : 
      43              : public:
      44              :   /**
      45              :    * @brief Construct a KeygenDialog.
      46              :    * @param gpgExe Path to the gpg executable (for the default template).
      47              :    * @param pass Backend that runs `gpg --gen-key`; the dialog accepts on its
      48              :    *             finishedGenerateGPGKeys() and shows generateGPGKeysFailed().
      49              :    * @param parent Parent widget, or nullptr.
      50              :    */
      51              :   explicit KeygenDialog(const QString &gpgExe, Pass *pass,
      52              :                         QWidget *parent = nullptr);
      53              :   /** @brief Destroys the dialog and its generated UI. */
      54              :   ~KeygenDialog() override;
      55              : 
      56              :   /**
      57              :    * @brief Splice a passphrase into a GPG batch template.
      58              :    *
      59              :    * Replaces %no-protection (or an existing Passphrase: line) with
      60              :    * "Passphrase: <passphrase>"; an empty passphrase yields %no-protection.
      61              :    * @param batch GPG batch template text.
      62              :    * @param passphrase Key passphrase, empty for an unprotected key.
      63              :    * @return Batch text ready for gpg --gen-key --batch.
      64              :    */
      65              :   static QString applyPassphrase(const QString &batch,
      66              :                                  const QString &passphrase);
      67              : 
      68              :   /**
      69              :    * @brief Whether @p value can go into a GPG batch line as one value.
      70              :    *
      71              :    * The batch is line-oriented, and gpg reads a line as a C string: a line
      72              :    * break or NUL in a name or passphrase would start a directive of its own
      73              :    * (%no-protection, a Passphrase: of the paster's choosing).
      74              :    * @param value A field's text.
      75              :    * @return False when it holds a CR, LF or NUL.
      76              :    */
      77              :   [[nodiscard]] static auto isBatchValue(const QString &value) -> bool;
      78              : 
      79              : protected:
      80              : private slots:
      81              :   /**
      82              :    * @brief First passphrase field edited: re-evaluates whether OK may be
      83              :    * enabled. The text itself stays out of the template box.
      84              :    * @param arg1 The new field text (unused).
      85              :    */
      86              :   void on_passphrase1_textChanged(const QString &arg1);
      87              :   /**
      88              :    * @brief Confirmation field edited: same as on_passphrase1_textChanged().
      89              :    * @param arg1 The new field text (unused).
      90              :    */
      91              :   void on_passphrase2_textChanged(const QString &arg1);
      92              :   /**
      93              :    * @brief Ticking "no passphrase" clears and disables the passphrase
      94              :    * fields and makes OK available; unticking it asks for one again.
      95              :    * @param checked The checkbox state.
      96              :    */
      97              :   void setNoPassphrase(bool checked);
      98              :   /**
      99              :    * @brief Enable or disable expert mode (the editable batch template).
     100              :    *
     101              :    * Connected explicitly to QCheckBox::toggled in the constructor; the box
     102              :    * is two-state, so the deprecated stateChanged(int) is not needed.
     103              :    * @param checked true when the Expert box is checked.
     104              :    */
     105              :   void setExpertMode(bool checked);
     106              :   /**
     107              :    * @brief Mirrors the e-mail field into the template's `Name-Email:` line.
     108              :    * @param arg1 The new field text.
     109              :    */
     110              :   void on_email_textChanged(const QString &arg1);
     111              :   /**
     112              :    * @brief Mirrors the name field into the template's `Name-Real:` line.
     113              :    * @param arg1 The new field text.
     114              :    */
     115              :   void on_name_textChanged(const QString &arg1);
     116              : 
     117              : private:
     118              :   /**
     119              :    * @brief OK is available when a passphrase is typed twice the same, or
     120              :    * when no passphrase was asked for explicitly. Empty fields alone are not
     121              :    * a choice: the key would be stored unprotected without anyone saying so.
     122              :    */
     123              :   void updateOkState();
     124              :   /**
     125              :    * @brief Whether the passphrase question has an answer: typed twice the
     126              :    * same, or waived with the checkbox. Empty fields alone are neither.
     127              :    * @return true when generation may proceed as far as the passphrase goes.
     128              :    */
     129              :   auto passphraseChosen() const -> bool;
     130              :   /** @brief Generated form (`keygendialog.ui`); owned. */
     131              :   QScopedPointer<Ui::KeygenDialog> ui;
     132              :   /**
     133              :    * @brief Rewrites every `<key>: ...` line of the batch template to carry
     134              :    * @p value. Values that fail isBatchValue() are ignored so a pasted line
     135              :    * break can never become a directive of its own.
     136              :    * @param key Batch parameter name, e.g. `Name-Real`.
     137              :    * @param value New value for that parameter.
     138              :    */
     139              :   void replace(const QString &key, const QString &value);
     140              :   /**
     141              :    * @brief On `Accepted`, validates the form (passphrase chosen, no line
     142              :    * breaks, name of 5+ characters, plausible e-mail), swaps the form for the
     143              :    * progress indicator and calls startGeneration(); the dialog only closes
     144              :    * once the backend reports success. Any other result disconnects the
     145              :    * backend signals and closes normally.
     146              :    * @param r The QDialog result code.
     147              :    */
     148              :   void done(int r) override;
     149              :   /**
     150              :    * @brief Connects to the backend's finished/failed signals for this one
     151              :    * attempt and calls Pass::GenerateGPGKeys(). With no backend the attempt
     152              :    * fails at once.
     153              :    * @param batch Complete batch text, passphrase already spliced in.
     154              :    */
     155              :   void startGeneration(const QString &batch);
     156              :   /**
     157              :    * @brief Stops and hides the progress indicator, re-enables the form under
     158              :    * the usual OK rule and shows @p error in the status label, so the user can
     159              :    * correct the input and try again.
     160              :    * @param error Backend error text; HTML-escaped before display.
     161              :    */
     162              :   void generationFailed(const QString &error);
     163              :   /** @brief Backend that runs gpg; not owned, may be nullptr. */
     164              :   Pass *m_pass;
     165              :   /** @brief Connection to Pass::finishedGenerateGPGKeys, live only during an
     166              :    * attempt. */
     167              :   QMetaObject::Connection m_finished;
     168              :   /** @brief Connection to Pass::generateGPGKeysFailed, live only during an
     169              :    * attempt. */
     170              :   QMetaObject::Connection m_failed;
     171              :   /** @brief Spinner shown while gpg works; created lazily on the first
     172              :    * attempt, reused (hidden) across retries. */
     173              :   std::unique_ptr<QProgressIndicator> m_progressIndicator;
     174              : };
     175              : 
     176              : #endif // SRC_KEYGENDIALOG_H_
        

Generated by: LCOV version 2.0-1