/** * 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 "SettingsGeneral.h" #ifdef SERVER_SUPPORT #include "server/ComUtils.h" #endif #ifdef MULTI_LANG_SUPPORT #include "SettingsDialog.h" #endif #include "GlobalSettingStation.h" #include "gpg/function/GpgKeyGetter.h" #include "rapidjson/prettywriter.h" #include "ui/widgets/KeyList.h" namespace GpgFrontend::UI { GeneralTab::GeneralTab(QWidget* parent) : QWidget(parent) { #ifdef SERVER_SUPPORT /***************************************** * GpgFrontend Server *****************************************/ auto* serverBox = new QGroupBox(_("GpgFrontend Server")); auto* serverBoxLayout = new QVBoxLayout(); serverSelectBox = new QComboBox(); serverBoxLayout->addWidget(serverSelectBox); serverBoxLayout->addWidget(new QLabel( _("Server that provides short key and key exchange services"))); serverBox->setLayout(serverBoxLayout); #endif /***************************************** * Save-Checked-Keys-Box *****************************************/ auto* saveCheckedKeysBox = new QGroupBox(_("Save Checked Keys")); auto* saveCheckedKeysBoxLayout = new QHBoxLayout(); saveCheckedKeysCheckBox = new QCheckBox( _("Save checked private keys on exit and restore them on next start."), this); saveCheckedKeysBoxLayout->addWidget(saveCheckedKeysCheckBox); saveCheckedKeysBox->setLayout(saveCheckedKeysBoxLayout); /***************************************** * Key-Impport-Confirmation Box *****************************************/ auto* importConfirmationBox = new QGroupBox(_("Confirm drag'n'drop key import")); auto* importConfirmationBoxLayout = new QHBoxLayout(); importConfirmationCheckBox = new QCheckBox( _("Import files dropped on the Key List without confirmation."), this); importConfirmationBoxLayout->addWidget(importConfirmationCheckBox); importConfirmationBox->setLayout(importConfirmationBoxLayout); #ifdef MULTI_LANG_SUPPORT /***************************************** * Language Select Box *****************************************/ auto* langBox = new QGroupBox(_("Language")); auto* langBoxLayout = new QVBoxLayout(); langSelectBox = new QComboBox; lang = SettingsDialog::listLanguages(); for (const auto& l : lang) { langSelectBox->addItem(l); } langBoxLayout->addWidget(langSelectBox); langBoxLayout->addWidget(new QLabel( "" + QString(_("NOTE")) + _(": ") + "" + _("GpgFrontend will restart automatically if you change the language!"))); langBox->setLayout(langBoxLayout); connect(langSelectBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotLanguageChanged())); #endif #ifdef SERVER_SUPPORT /***************************************** * Own Key Select Box *****************************************/ auto* ownKeyBox = new QGroupBox(_("Own key")); auto* ownKeyBoxLayout = new QVBoxLayout(); auto* ownKeyServiceTokenLayout = new QHBoxLayout(); ownKeySelectBox = new QComboBox; getServiceTokenButton = new QPushButton(_("Get Service Token")); serviceTokenLabel = new QLabel(_("No Service Token Found")); serviceTokenLabel->setAlignment(Qt::AlignCenter); ownKeyBox->setLayout(ownKeyBoxLayout); mKeyList = new KeyList(); // Fill the keyid hashmap keyIds.insert({QString(), ""}); auto private_keys = mKeyList->getAllPrivateKeys(); for (const auto& keyid : *private_keys) { auto key = GpgKeyGetter::GetInstance().GetKey(keyid); if (!key.good()) continue; keyIds.insert({key.id(), key.uids()->front().uid()}); } for (const auto& k : keyIds) { ownKeySelectBox->addItem(QString::fromStdString(k.second)); keyIdsList.push_back(k.first); } connect(ownKeySelectBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotOwnKeyIdChanged())); connect(getServiceTokenButton, SIGNAL(clicked(bool)), this, SLOT(slotGetServiceToken())); ownKeyBoxLayout->addWidget(new QLabel( _("Key pair for synchronization and identity authentication"))); ownKeyBoxLayout->addWidget(ownKeySelectBox); ownKeyBoxLayout->addLayout(ownKeyServiceTokenLayout); ownKeyServiceTokenLayout->addWidget(getServiceTokenButton); ownKeyServiceTokenLayout->addWidget(serviceTokenLabel); ownKeyServiceTokenLayout->stretch(0); #endif /***************************************** * Mainlayout *****************************************/ auto* mainLayout = new QVBoxLayout; #ifdef SERVER_SUPPORT mainLayout->addWidget(serverBox); #endif mainLayout->addWidget(saveCheckedKeysBox); mainLayout->addWidget(importConfirmationBox); #ifdef MULTI_LANG_SUPPORT mainLayout->addWidget(langBox); #endif #ifdef SERVER_SUPPORT mainLayout->addWidget(ownKeyBox); #endif setSettings(); mainLayout->addStretch(1); setLayout(mainLayout); } /********************************** * Read the settings from config * and set the buttons and checkboxes * appropriately **********************************/ void GeneralTab::setSettings() { auto& settings = GlobalSettingStation::GetInstance().GetUISettings(); try { bool save_key_checked = settings.lookup("general.save_key_checked"); if (save_key_checked) saveCheckedKeysCheckBox->setCheckState(Qt::Checked); } catch (...) { LOG(ERROR) << _("Setting Operation Error") << _("save_key_checked"); } #ifdef SERVER_SUPPORT auto serverList = settings.value("general/gpgfrontendServerList").toStringList(); if (serverList.empty()) { serverList.append("service.gpgfrontend.pub"); serverList.append("localhost"); } for (const auto& s : serverList) serverSelectBox->addItem(s); qDebug() << "Current Gpgfrontend Server" << settings.value("general/currentGpgfrontendServer").toString(); serverSelectBox->setCurrentText( settings .value("general/currentGpgfrontendServer", "service.gpgfrontend.pub") .toString()); connect(serverSelectBox, QOverload::of(&QComboBox::currentTextChanged), this, [&](const QString& current) -> void { settings.setValue("general/currentGpgfrontendServer", current); }); #endif #ifdef MULTI_LANG_SUPPORT try { std::string lang_key = settings.lookup("general.lang"); QString lang_value = lang.value(lang_key.c_str()); LOG(INFO) << "lang settings current" << lang_value.toStdString(); if (!lang.empty()) { langSelectBox->setCurrentIndex(langSelectBox->findText(lang_value)); } else { langSelectBox->setCurrentIndex(0); } } catch (...) { LOG(ERROR) << _("Setting Operation Error") << _("lang"); } #endif #ifdef SERVER_SUPPORT auto own_key_id = settings.value("general/ownKeyId").toString().toStdString(); if (own_key_id.empty()) { ownKeySelectBox->setCurrentText(""); } else { const auto uid = keyIds.find(own_key_id)->second; ownKeySelectBox->setCurrentText(QString::fromStdString(uid)); } serviceToken = settings.value("general/serviceToken").toString().toStdString(); if (!serviceToken.empty()) { serviceTokenLabel->setText(QString::fromStdString(serviceToken)); } #endif try { bool confirm_import_keys = settings.lookup("general.confirm_import_keys"); LOG(INFO) << "confirm_import_keys" << confirm_import_keys; if (confirm_import_keys) importConfirmationCheckBox->setCheckState(Qt::Checked); } catch (...) { LOG(ERROR) << _("Setting Operation Error") << _("confirm_import_keys"); } } /*********************************** * get the values of the buttons and * write them to settings-file *************************************/ void GeneralTab::applySettings() { auto& settings = GpgFrontend::UI::GlobalSettingStation::GetInstance().GetUISettings(); if (!settings.exists("general") || settings.lookup("general").getType() != libconfig::Setting::TypeGroup) settings.add("general", libconfig::Setting::TypeGroup); auto& general = settings["general"]; if (!general.exists("save_key_checked")) general.add("save_key_checked", libconfig::Setting::TypeBoolean) = saveCheckedKeysCheckBox->isChecked(); else { general["save_key_checked"] = saveCheckedKeysCheckBox->isChecked(); } #ifdef SERVER_SUPPORT qDebug() << "serverSelectBox currentText" << serverSelectBox->currentText(); settings.setValue("general/currentGpgfrontendServer", serverSelectBox->currentText()); auto* serverList = new QStringList(); for (int i = 0; i < serverSelectBox->count(); i++) serverList->append(serverSelectBox->itemText(i)); settings.setValue("general/gpgfrontendServerList", *serverList); delete serverList; #endif #ifdef MULTI_LANG_SUPPORT if (!general.exists("lang")) general.add("lang", libconfig::Setting::TypeBoolean) = lang.key(langSelectBox->currentText()).toStdString(); else { general["lang"] = lang.key(langSelectBox->currentText()).toStdString(); #endif } #ifdef SERVER_SUPPORT settings.setValue( "general/ownKeyId", QString::fromStdString(keyIdsList[ownKeySelectBox->currentIndex()])); settings.setValue("general/serviceToken", QString::fromStdString(serviceToken)); #endif if (!general.exists("confirm_import_keys")) general.add("confirm_import_keys", libconfig::Setting::TypeBoolean) = importConfirmationCheckBox->isChecked(); else { general["confirm_import_keys"] = importConfirmationCheckBox->isChecked(); } } #ifdef MULTI_LANG_SUPPORT void GeneralTab::slotLanguageChanged() { emit signalRestartNeeded(true); } #endif #ifdef SERVER_SUPPORT void GeneralTab::slotOwnKeyIdChanged() { // Set ownKeyId to currently selected this->serviceTokenLabel->setText(_("No Service Token Found")); serviceToken.clear(); } #endif #ifdef SERVER_SUPPORT void GeneralTab::slotGetServiceToken() { auto utils = new ComUtils(this); QUrl reqUrl(utils->getUrl(ComUtils::GetServiceToken)); QNetworkRequest request(reqUrl); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); const auto keyId = keyIdsList[ownKeySelectBox->currentIndex()]; qDebug() << "KeyId" << keyIdsList[ownKeySelectBox->currentIndex()]; if (keyId.isEmpty()) { QMessageBox::critical( this, _("Invalid Operation"), _("Own Key can not be None while getting service token.")); return; } QStringList selectedKeyIds(keyIdsList[ownKeySelectBox->currentIndex()]); QByteArray keyDataBuf; mCtx->exportKeys(&selectedKeyIds, &keyDataBuf); GpgKey key = mCtx->getKeyRefById(keyId); if (!key.good) { QMessageBox::critical(this, _("Error"), _("Key Not Exists")); return; } qDebug() << "keyDataBuf" << keyDataBuf; /** * { * "publicKey" : ... * "sha": ... * "signedFpr": ... * "version": ... * } */ QCryptographicHash shaGen(QCryptographicHash::Sha256); shaGen.addData(keyDataBuf); auto shaStr = shaGen.result().toHex(); auto signFprStr = ComUtils::getSignStringBase64(mCtx, key.fpr, key); rapidjson::Value pubkey, ver, sha, signFpr; rapidjson::Document doc; doc.SetObject(); pubkey.SetString(keyDataBuf.constData(), keyDataBuf.count()); auto version = qApp->applicationVersion(); ver.SetString(version.toUtf8().constData(), qApp->applicationVersion().count()); sha.SetString(shaStr.constData(), shaStr.count()); signFpr.SetString(signFprStr.constData(), signFprStr.count()); rapidjson::Document::AllocatorType& allocator = doc.GetAllocator(); doc.AddMember("publicKey", pubkey, allocator); doc.AddMember("sha", sha, allocator); doc.AddMember("signedFpr", signFpr, allocator); doc.AddMember("version", ver, allocator); rapidjson::StringBuffer sb; rapidjson::PrettyWriter writer(sb); doc.Accept(writer); QByteArray postData(sb.GetString()); QNetworkReply* reply = utils->getNetworkManager().post(request, postData); // Show Waiting Dailog auto dialog = new WaitingDialog("Getting Token From Server", this); dialog->show(); while (reply->isRunning()) { QApplication::processEvents(); } dialog->close(); if (utils->checkServerReply(reply->readAll().constData())) { /** * { * "serviceToken" : ... * "fpr": ... * } */ if (!utils->checkDataValueStr("serviceToken") || !utils->checkDataValueStr("fpr")) { QMessageBox::critical(this, _("Error"), _("The communication content with the server does " "not meet the requirements")); return; } QString serviceTokenTemp = utils->getDataValueStr("serviceToken"); QString fpr = utils->getDataValueStr("fpr"); auto key = mCtx->getKeyRefByFpr(fpr); if (utils->checkServiceTokenFormat(serviceTokenTemp) && key.good) { serviceToken = serviceTokenTemp; qDebug() << "Get Service Token" << serviceToken; // Auto update settings settings.setValue("general/serviceToken", serviceToken); serviceTokenLabel->setText(serviceToken); QMessageBox::information(this, _("Notice"), _("Succeed in getting service token")); } else { QMessageBox::critical( this, _("Error"), _("There is a problem with the communication with the server")); } } } #endif } // namespace GpgFrontend::UI