/** * This file is part of GpgFrontend. * * GpgFrontend is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Foobar. If not, see . * * The initial version of the source code is inherited from gpg4usb-team. * Their source code version also complies with GNU General Public License. * * The source code version of this software was modified and released * by Saturneric starting on May 12, 2021. * */ #include "ui/KeyMgmt.h" #include #include "gpg/function/GpgKeyGetter.h" #include "gpg/function/GpgKeyImportExportor.h" #include "gpg/function/GpgKeyOpera.h" #include "ui/SignalStation.h" namespace GpgFrontend::UI { KeyMgmt::KeyMgmt(QWidget* parent) : QMainWindow(parent), appPath(qApp->applicationDirPath()), settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", QSettings::IniFormat) { /* the list of Keys available*/ mKeyList = new KeyList(); mKeyList->setColumnWidth(2, 250); mKeyList->setColumnWidth(3, 250); setCentralWidget(mKeyList); mKeyList->setDoubleClickedAction([this](const GpgKey& key, QWidget* parent) { new KeyDetailsDialog(key, parent); }); createActions(); createMenus(); createToolBars(); connect(this, SIGNAL(signalStatusBarChanged(QString)), this->parent(), SLOT(slotSetStatusBarText(QString))); /* Restore the iconstyle */ this->settings.sync(); QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize(); settings.setValue("toolbar/iconsize", iconSize); Qt::ToolButtonStyle buttonStyle = static_cast( settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon) .toUInt()); this->setIconSize(iconSize); this->setToolButtonStyle(buttonStyle); // state sets pos & size of dock-widgets this->restoreState(this->settings.value("keymgmt/windowState").toByteArray()); qDebug() << "windows/windowSave" << this->settings.value("window/windowSave").toBool(); // Restore window size & location if (this->settings.value("keymgmt/setWindowSize").toBool()) { QPoint pos = settings.value("keymgmt/pos", QPoint(100, 100)).toPoint(); QSize size = settings.value("keymgmt/size", QSize(900, 600)).toSize(); qDebug() << "Settings size" << size << "pos" << pos; this->setMinimumSize(size); this->move(pos); } else { qDebug() << "Use default min windows size and pos"; QPoint defaultPoint(100, 100); QSize defaultMinSize(900, 600); this->setMinimumSize(defaultMinSize); this->move(defaultPoint); this->settings.setValue("keymgmt/pos", defaultPoint); this->settings.setValue("keymgmt/size", defaultMinSize); this->settings.setValue("keymgmt/setWindowSize", true); } setWindowTitle(_("Key Pair Management")); mKeyList->addMenuAction(deleteSelectedKeysAct); mKeyList->addMenuAction(showKeyDetailsAct); connect(this, SIGNAL(signalKeyStatusUpdated()), SignalStation::GetInstance(), SIGNAL(KeyDatabaseRefresh())); } void KeyMgmt::createActions() { openKeyFileAct = new QAction(_("Open"), this); openKeyFileAct->setShortcut(QKeySequence(_("Ctrl+O"))); openKeyFileAct->setToolTip(_("Open Key File")); connect(openKeyFileAct, SIGNAL(triggered()), this, SLOT(slotImportKeyFromFile())); closeAct = new QAction(_("Close"), this); closeAct->setShortcut(QKeySequence(_("Ctrl+Q"))); closeAct->setIcon(QIcon(":exit.png")); closeAct->setToolTip(_("Close")); connect(closeAct, SIGNAL(triggered()), this, SLOT(close())); generateKeyPairAct = new QAction(_("New Keypair"), this); generateKeyPairAct->setShortcut(QKeySequence(_("Ctrl+N"))); generateKeyPairAct->setIcon(QIcon(":key_generate.png")); generateKeyPairAct->setToolTip(_("Generate KeyPair")); connect(generateKeyPairAct, SIGNAL(triggered()), this, SLOT(slotGenerateKeyDialog())); generateSubKeyAct = new QAction(_("New Subkey"), this); generateSubKeyAct->setShortcut(QKeySequence(_("Ctrl+Shift+N"))); generateSubKeyAct->setIcon(QIcon(":key_generate.png")); generateSubKeyAct->setToolTip(_("Generate Subkey For Selected KeyPair")); connect(generateSubKeyAct, SIGNAL(triggered()), this, SLOT(slotGenerateSubKey())); importKeyFromFileAct = new QAction(_("File"), this); importKeyFromFileAct->setIcon(QIcon(":import_key_from_file.png")); importKeyFromFileAct->setToolTip(_("Import New Key From File")); connect(importKeyFromFileAct, SIGNAL(triggered()), this, SLOT(slotImportKeyFromFile())); importKeyFromClipboardAct = new QAction(_("Clipboard"), this); importKeyFromClipboardAct->setIcon(QIcon(":import_key_from_clipboard.png")); importKeyFromClipboardAct->setToolTip(_("Import New Key From Clipboard")); connect(importKeyFromClipboardAct, SIGNAL(triggered()), this, SLOT(slotImportKeyFromClipboard())); importKeyFromKeyServerAct = new QAction(_("Keyserver"), this); importKeyFromKeyServerAct->setIcon(QIcon(":import_key_from_server.png")); importKeyFromKeyServerAct->setToolTip(_("Import New Key From Keyserver")); connect(importKeyFromKeyServerAct, SIGNAL(triggered()), this, SLOT(slotImportKeyFromKeyServer())); exportKeyToClipboardAct = new QAction(_("Export To Clipboard"), this); exportKeyToClipboardAct->setIcon(QIcon(":export_key_to_clipboard.png")); exportKeyToClipboardAct->setToolTip(_("Export Selected Key(s) To Clipboard")); connect(exportKeyToClipboardAct, SIGNAL(triggered()), this, SLOT(slotExportKeyToClipboard())); exportKeyToFileAct = new QAction(_("Export To File"), this); exportKeyToFileAct->setIcon(QIcon(":export_key_to_file.png")); exportKeyToFileAct->setToolTip(_("Export Selected Key(s) To File")); connect(exportKeyToFileAct, SIGNAL(triggered()), this, SLOT(slotExportKeyToFile())); deleteSelectedKeysAct = new QAction(_("Delete Selected Key(s)"), this); deleteSelectedKeysAct->setToolTip(_("Delete the Selected keys")); connect(deleteSelectedKeysAct, SIGNAL(triggered()), this, SLOT(slotDeleteSelectedKeys())); deleteCheckedKeysAct = new QAction(_("Delete Checked Key(s)"), this); deleteCheckedKeysAct->setToolTip(_("Delete the Checked keys")); deleteCheckedKeysAct->setIcon(QIcon(":button_delete.png")); connect(deleteCheckedKeysAct, SIGNAL(triggered()), this, SLOT(slotDeleteCheckedKeys())); showKeyDetailsAct = new QAction(_("Show Key Details"), this); showKeyDetailsAct->setToolTip(_("Show Details for this Key")); connect(showKeyDetailsAct, SIGNAL(triggered()), this, SLOT(slotShowKeyDetails())); } void KeyMgmt::createMenus() { fileMenu = menuBar()->addMenu(_("File")); fileMenu->addAction(openKeyFileAct); fileMenu->addAction(closeAct); keyMenu = menuBar()->addMenu(_("Key")); generateKeyMenu = keyMenu->addMenu(_("Generate Key")); generateKeyMenu->addAction(generateKeyPairAct); generateKeyMenu->addAction(generateSubKeyAct); importKeyMenu = keyMenu->addMenu(_("Import Key")); importKeyMenu->addAction(importKeyFromFileAct); importKeyMenu->addAction(importKeyFromClipboardAct); importKeyMenu->addAction(importKeyFromKeyServerAct); keyMenu->addAction(exportKeyToFileAct); keyMenu->addAction(exportKeyToClipboardAct); keyMenu->addSeparator(); keyMenu->addAction(deleteCheckedKeysAct); } void KeyMgmt::createToolBars() { QToolBar* keyToolBar = addToolBar(_("Key")); keyToolBar->setObjectName("keytoolbar"); // add button with popup menu for import auto* generateToolButton = new QToolButton(this); generateToolButton->setMenu(generateKeyMenu); generateToolButton->setPopupMode(QToolButton::InstantPopup); generateToolButton->setIcon(QIcon(":key_generate.png")); generateToolButton->setText(_("Generate")); generateToolButton->setToolTip(_("Generate A New Keypair or Subkey")); generateToolButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); keyToolBar->addWidget(generateToolButton); // add button with popup menu for import auto* toolButton = new QToolButton(this); toolButton->setMenu(importKeyMenu); toolButton->setPopupMode(QToolButton::InstantPopup); toolButton->setIcon(QIcon(":key_import.png")); toolButton->setToolTip(_("Import key")); toolButton->setText(_("Import Key")); toolButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); keyToolBar->addWidget(toolButton); keyToolBar->addSeparator(); keyToolBar->addAction(deleteCheckedKeysAct); keyToolBar->addSeparator(); keyToolBar->addAction(exportKeyToFileAct); keyToolBar->addAction(exportKeyToClipboardAct); } void KeyMgmt::slotImportKeys(const std::string& in_buffer) { GpgImportInformation result = GpgKeyImportExportor::GetInstance().ImportKey( std::make_unique(in_buffer)); emit signalKeyStatusUpdated(); new KeyImportDetailDialog(result, false, this); } void KeyMgmt::slotImportKeyFromFile() { QString file_name = QFileDialog::getOpenFileName( this, _("Open Key"), QString(), QString(_("Key Files")) + " (*.asc *.txt);;" + _("Keyring files") + " (*.gpg);;All Files (*)"); if (!file_name.isNull()) { slotImportKeys(read_all_data_in_file(file_name.toStdString())); } } void KeyMgmt::slotImportKeyFromKeyServer() { importDialog = new KeyServerImportDialog(mKeyList, false, this); importDialog->show(); } void KeyMgmt::slotImportKeyFromClipboard() { QClipboard* cb = QApplication::clipboard(); slotImportKeys(cb->text(QClipboard::Clipboard).toUtf8().toStdString()); } void KeyMgmt::slotDeleteSelectedKeys() { deleteKeysWithWarning(mKeyList->getSelected()); } void KeyMgmt::slotDeleteCheckedKeys() { deleteKeysWithWarning(mKeyList->getChecked()); } void KeyMgmt::deleteKeysWithWarning(KeyIdArgsListPtr key_ids) { /** * TODO: Different Messages for private/public key, check if * more than one selected... compare to seahorse "delete-dialog" */ LOG(INFO) << "KeyMgmt::deleteKeysWithWarning Called"; if (key_ids->empty()) return; QString keynames; for (const auto& key_id : *key_ids) { auto key = GpgKeyGetter::GetInstance().GetKey(key_id); if (!key.good()) continue; keynames.append(QString::fromStdString(key.name())); keynames.append(" <"); keynames.append(QString::fromStdString(key.email())); keynames.append(">
"); } int ret = QMessageBox::warning( this, _("Deleting Keys"), "" + QString( _("Are you sure that you want to delete the following keys?")) + "

" + keynames + +"
" + _("The action can not be undone."), QMessageBox::No | QMessageBox::Yes); if (ret == QMessageBox::Yes) { GpgKeyOpera::GetInstance().DeleteKeys(std::move(key_ids)); emit signalKeyStatusUpdated(); } } void KeyMgmt::slotShowKeyDetails() { auto keys_selected = mKeyList->getSelected(); if (keys_selected->empty()) return; auto key = GpgKeyGetter::GetInstance().GetKey(keys_selected->front()); if (!key.good()) { QMessageBox::critical(nullptr, _("Error"), _("Key Not Found.")); return; } new KeyDetailsDialog(key); } void KeyMgmt::slotExportKeyToFile() { ByteArrayPtr key_export_data = nullptr; auto keys_checked = mKeyList->getChecked(); if (!GpgKeyImportExportor::GetInstance().ExportKeys(keys_checked, key_export_data)) { return; } auto key = GpgKeyGetter::GetInstance().GetKey(mKeyList->getSelected()->front()); if (!key.good()) { QMessageBox::critical(nullptr, _("Error"), _("Key Not Found.")); return; } QString fileString = QString::fromStdString(key.name() + " " + key.email() + "(" + key.id() + ")_pub.asc"); QString file_name = QFileDialog::getSaveFileName( this, _("Export Key To File"), fileString, QString(_("Key Files")) + " (*.asc *.txt);;All Files (*)"); write_buffer_to_file(file_name.toStdString(), *key_export_data); emit signalStatusBarChanged(QString(_("key(s) exported"))); } void KeyMgmt::slotExportKeyToClipboard() { ByteArrayPtr key_export_data = nullptr; auto keys_checked = mKeyList->getChecked(); if (!GpgKeyImportExportor::GetInstance().ExportKeys(keys_checked, key_export_data)) { return; } QApplication::clipboard()->setText(QString::fromStdString(*key_export_data)); } void KeyMgmt::slotGenerateKeyDialog() { auto* keyGenDialog = new KeyGenDialog(this); keyGenDialog->show(); } void KeyMgmt::closeEvent(QCloseEvent* event) { QMainWindow::closeEvent(event); } void KeyMgmt::slotGenerateSubKey() { auto keys_selected = mKeyList->getSelected(); if (keys_selected->empty()) { QMessageBox::information( nullptr, _("Invalid Operation"), _("Please select one KeyPair before doing this operation.")); return; } const auto key = GpgKeyGetter::GetInstance().GetKey(keys_selected->front()); if (!key.good()) { QMessageBox::critical(nullptr, _("Error"), _("Key Not Found.")); return; } if (!key.is_private_key()) { QMessageBox::critical(nullptr, _("Invalid Operation"), _("If a key pair does not have a private key then " "it will not be able to generate sub-keys.")); return; } auto dialog = new SubkeyGenerateDialog(key.id(), this); dialog->show(); } } // namespace GpgFrontend::UI