/**
* 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/SettingsDialog.h"
#include "ui/WaitingDialog.h"
#include "server/ComUtils.h"
#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
GeneralTab::GeneralTab(GpgME::GpgContext *ctx, QWidget *parent)
: QWidget(parent), appPath(qApp->applicationDirPath()),
settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
QSettings::IniFormat) {
mCtx = ctx;
/*****************************************
* GpgFrontend Server
*****************************************/
auto *serverBox = new QGroupBox(tr("GpgFrontend Server"));
auto *serverBoxLayout = new QVBoxLayout();
serverSelectBox = new QComboBox();
serverBoxLayout->addWidget(serverSelectBox);
serverBoxLayout->addWidget(new QLabel(
tr("Server that provides short key and key exchange services")));
connect(serverSelectBox, QOverload::of(&QComboBox::currentTextChanged),
this, [&](const QString ¤t) -> void {
settings.setValue("general/currentGpgfrontendServer", current);
});
serverBox->setLayout(serverBoxLayout);
/*****************************************
* Save-Checked-Keys-Box
*****************************************/
auto *saveCheckedKeysBox = new QGroupBox(tr("Save Checked Keys"));
auto *saveCheckedKeysBoxLayout = new QHBoxLayout();
saveCheckedKeysCheckBox = new QCheckBox(
tr("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(tr("Confirm drag'n'drop key import"));
auto *importConfirmationBoxLayout = new QHBoxLayout();
importConfirmationCheckBox = new QCheckBox(
tr("Import files dropped on the keylist without confirmation."), this);
importConfirmationBoxLayout->addWidget(importConfirmationCheckBox);
importConfirmationBox->setLayout(importConfirmationBoxLayout);
/*****************************************
* Language Select Box
*****************************************/
auto *langBox = new QGroupBox(tr("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(tr("NOTE: GpgFrontend will restart automatically if "
"you change the language!")));
langBox->setLayout(langBoxLayout);
connect(langSelectBox, SIGNAL(currentIndexChanged(int)), this,
SLOT(slotLanguageChanged()));
/*****************************************
* Own Key Select Box
*****************************************/
auto *ownKeyBox = new QGroupBox(tr("Own key"));
auto *ownKeyBoxLayout = new QVBoxLayout();
auto *ownKeyServiceTokenLayout = new QHBoxLayout();
ownKeySelectBox = new QComboBox;
getServiceTokenButton = new QPushButton(tr("Get Service Token"));
serviceTokenLabel = new QLabel(tr("No Service Token Found"));
ownKeyBox->setLayout(ownKeyBoxLayout);
mKeyList = new KeyList(mCtx);
// Fill the keyid hashmap
keyIds.insert("", tr(""));
for (const auto &keyid : *mKeyList->getAllPrivateKeys()) {
auto &key = mCtx->getKeyById(keyid);
keyIds.insert(key.id, key.uids.first().uid);
}
for (const auto &k : keyIds.keys()) {
ownKeySelectBox->addItem(keyIds.find(k).value());
keyIdsList.append(k);
}
connect(ownKeySelectBox, SIGNAL(currentIndexChanged(int)), this,
SLOT(slotOwnKeyIdChanged()));
connect(getServiceTokenButton, SIGNAL(clicked(bool)), this,
SLOT(slotGetServiceToken()));
ownKeyBoxLayout->addWidget(new QLabel(
tr("Key pair for synchronization and identity authentication")));
ownKeyBoxLayout->addWidget(ownKeySelectBox);
ownKeyBoxLayout->addLayout(ownKeyServiceTokenLayout);
ownKeyServiceTokenLayout->addWidget(getServiceTokenButton);
ownKeyServiceTokenLayout->addWidget(serviceTokenLabel);
ownKeyServiceTokenLayout->stretch(0);
/*****************************************
* Mainlayout
*****************************************/
auto *mainLayout = new QVBoxLayout;
mainLayout->addWidget(serverBox);
mainLayout->addWidget(saveCheckedKeysBox);
mainLayout->addWidget(importConfirmationBox);
mainLayout->addWidget(langBox);
mainLayout->addWidget(ownKeyBox);
setSettings();
mainLayout->addStretch(1);
setLayout(mainLayout);
}
/**********************************
* Read the settings from config
* and set the buttons and checkboxes
* appropriately
**********************************/
void GeneralTab::setSettings() {
// Keysaving
if (settings.value("keys/saveKeyChecked").toBool()) {
saveCheckedKeysCheckBox->setCheckState(Qt::Checked);
}
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);
serverSelectBox->setCurrentText(settings.value("general/currentGpgfrontendServer",
"service.gpgfrontend.pub").toString());
// Language setting
QString langKey = settings.value("int/lang").toString();
QString langValue = lang.value(langKey);
if (langKey != "") {
langSelectBox->setCurrentIndex(langSelectBox->findText(langValue));
}
QString own_key_id = settings.value("general/ownKeyId").toString();
qDebug() << "OwnKeyId" << own_key_id;
if (own_key_id.isEmpty()) {
ownKeySelectBox->setCurrentText("");
} else {
const auto text = keyIds.find(own_key_id).value();
qDebug() << "OwnKey" << own_key_id << text;
ownKeySelectBox->setCurrentText(text);
}
serviceToken = settings.value("general/serviceToken").toString();
qDebug() << "Load Service Token" << serviceToken;
if (!serviceToken.isEmpty()) {
serviceTokenLabel->setText(serviceToken);
}
// Get own key information from keydb/gpg.conf (if contained)
if (settings.value("general/confirmImportKeys", Qt::Checked).toBool()) {
importConfirmationCheckBox->setCheckState(Qt::Checked);
}
}
/***********************************
* get the values of the buttons and
* write them to settings-file
*************************************/
void GeneralTab::applySettings() {
settings.setValue("keys/saveKeyChecked",
saveCheckedKeysCheckBox->isChecked());
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;
settings.setValue("int/lang", lang.key(langSelectBox->currentText()));
settings.setValue("general/ownKeyId",
keyIdsList[ownKeySelectBox->currentIndex()]);
settings.setValue("general/serviceToken",
serviceToken);
settings.setValue("general/confirmImportKeys",
importConfirmationCheckBox->isChecked());
}
void GeneralTab::slotLanguageChanged() { emit signalRestartNeeded(true); }
void GeneralTab::slotOwnKeyIdChanged() {
// Set ownKeyId to currently selected
this->serviceTokenLabel->setText(tr("No Service Token Found"));
serviceToken.clear();
}
void GeneralTab::slotGetServiceToken() {
auto utils = new ComUtils(this);
QUrl reqUrl(utils->getUrl(ComUtils::GetServiceToken));
QNetworkRequest request(reqUrl);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
// Building Post Data
QByteArray keyDataBuf;
const auto keyId = keyIdsList[ownKeySelectBox->currentIndex()];
qDebug() << "KeyId" << keyIdsList[ownKeySelectBox->currentIndex()];
if (keyId.isEmpty()) {
QMessageBox::critical(this, tr("Invalid Operation"),
tr("Own Key can not be None while getting service token."));
return;
}
QStringList selectedKeyIds(keyIdsList[ownKeySelectBox->currentIndex()]);
mCtx->exportKeys(&selectedKeyIds, &keyDataBuf);
qDebug() << "keyDataBuf" << keyDataBuf;
rapidjson::Value p, v;
rapidjson::Document doc;
doc.SetObject();
p.SetString(keyDataBuf.constData(), keyDataBuf.count());
auto version = qApp->applicationVersion();
v.SetString(version.toUtf8().constData(), qApp->applicationVersion().count());
doc.AddMember("publicKey", p, doc.GetAllocator());
doc.AddMember("version", v, doc.GetAllocator());
rapidjson::StringBuffer sb;
rapidjson::PrettyWriter writer(sb);
doc.Accept(writer);
QByteArray postData(sb.GetString());
QNetworkReply *reply = manager.post(request, postData);
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->checkDataValue("serviceToken") || !utils->checkDataValue("fpr")) {
QMessageBox::critical(this, tr("Error"), tr("The communication content with the server does not meet the requirements"));
return;
}
QString serviceTokenTemp = utils->getDataValue("serviceToken");
QString fpr = utils->getDataValue("fpr");
auto key = mCtx->getKeyByFpr(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, tr("Notice"),
tr("Succeed in getting service token"));
} else {
QMessageBox::critical(this, tr("Error"), tr("There is a problem with the communication with the server"));
}
}
}