diff --git a/Qt-SESAM/mainwindow.cpp b/Qt-SESAM/mainwindow.cpp index 76a641aa..c41033f9 100644 --- a/Qt-SESAM/mainwindow.cpp +++ b/Qt-SESAM/mainwindow.cpp @@ -59,6 +59,8 @@ #include #include #include +#include +#include #include "global.h" #include "util.h" @@ -323,6 +325,7 @@ MainWindow::MainWindow(bool forceStart, QWidget *parent) QObject::connect(ui->actionAbout, SIGNAL(triggered(bool)), SLOT(about())); QObject::connect(ui->actionAboutQt, SIGNAL(triggered(bool)), SLOT(aboutQt())); QObject::connect(ui->actionOptions, SIGNAL(triggered(bool)), SLOT(showOptionsDialog())); + QObject::connect(ui->actionExportAllLoginDataAsClearText, SIGNAL(triggered(bool)), SLOT(onExportAllLoginDataAsClearText())); QObject::connect(ui->actionExportCurrentSettingsAsQRCode, SIGNAL(triggered(bool)), SLOT(onExportCurrentSettingsAsQRCode())); QObject::connect(ui->actionExportKGK, SIGNAL(triggered(bool)), SLOT(onExportKGK())); QObject::connect(ui->actionImportKGK, SIGNAL(triggered(bool)), SLOT(onImportKGK())); @@ -2392,7 +2395,86 @@ void MainWindow::onEasySelectorValuesChanged(int length, int complexity) } -QImage MainWindow::currentDomainSettings2QRCode(void) +struct LoginToTextConverter +{ + LoginToTextConverter(const SecureByteArray &kgk) + : KGK(kgk) + { /* ... */ } + typedef SecureByteArray result_type; + SecureByteArray KGK; + SecureByteArray operator()(const DomainSettings &ds) + { + SecureString pwd = ds.legacyPassword; + if (pwd.isEmpty()) { + Password gpwd(ds); + gpwd.generate(KGK); + pwd = gpwd(); + } + SecureByteArray data = pwd.isEmpty() + ? SecureByteArray() + : SecureString("%1\t%2\t%3\t%4") + .arg(ds.domainName) + .arg(ds.url) + .arg(ds.userName) + .arg(pwd) + .toUtf8(); + return data; + } +}; + + +void concat(SecureByteArray &all, const SecureByteArray &intermediate) +{ + if (!intermediate.isEmpty()) { + all.append(intermediate).append("\n"); + } +} + + +static const QString LoginDataFileExtension = QObject::tr("Login data file (*.csv)"); + +void MainWindow::onExportAllLoginDataAsClearText(void) +{ + Q_D(MainWindow); + QString filename = + QFileDialog::getSaveFileName(this, + tr("Export all login data as clear text"), + QString(), + LoginDataFileExtension); + if (!filename.isEmpty()) { + QProgressDialog progressDialog(this); + progressDialog.setLabelText(tr("Exporting logins\nin %1 thread%2 ...") + .arg(QThread::idealThreadCount()) + .arg(QThread::idealThreadCount() == 1 ? "" : tr("s"))); + progressDialog.setCancelButtonText(tr("Cancel")); + QFutureWatcher futureWatcher; + QObject::connect(&futureWatcher, SIGNAL(finished()), &progressDialog, SLOT(reset())); + QObject::connect(&progressDialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel())); + QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int, int)), &progressDialog, SLOT(setRange(int, int))); + QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &progressDialog, SLOT(setValue(int))); + QFuture future = QtConcurrent::mappedReduced( + d->domains, + LoginToTextConverter(d->KGK), + concat, + QtConcurrent::OrderedReduce); + futureWatcher.setFuture(future); + progressDialog.show(); + progressDialog.exec(); + futureWatcher.waitForFinished(); + if (!futureWatcher.future().isCanceled()) { + QFile outFile(filename); + bool ok = outFile.open(QIODevice::Truncate | QIODevice::WriteOnly); + if (ok) { + outFile.write("Domain\tURL\tUsername\tPassword\n"); + outFile.write(future.result()); + outFile.close(); + } + } + } +} + + +QImage MainWindow::currentDomainSettings2QRCode(void) const { static const int ModuleSize = 10; static const int Margin = ModuleSize; diff --git a/Qt-SESAM/mainwindow.h b/Qt-SESAM/mainwindow.h index 60b8915a..36c5af12 100644 --- a/Qt-SESAM/mainwindow.h +++ b/Qt-SESAM/mainwindow.h @@ -44,11 +44,13 @@ #include #include #include +#include #include "global.h" #include "domainsettings.h" #include "domainsettingslist.h" #include "pbkdf2.h" +#include "securebytearray.h" namespace Ui { class MainWindow; @@ -101,6 +103,7 @@ private slots: void onDomainTextChanged(const QString &); void onDomainSelected(QString); void onEasySelectorValuesChanged(int, int); + void onExportAllLoginDataAsClearText(void); void onExportCurrentSettingsAsQRCode(void); void onPasswordTemplateChanged(const QString &); void masterPasswordInvalidationTimeMinsChanged(int); @@ -213,7 +216,7 @@ private slots: void cleanupAfterMasterPasswordChanged(void); void prepareExit(void); void removeOutdatedBackupFilesThread(void); - QImage currentDomainSettings2QRCode(void); + QImage currentDomainSettings2QRCode(void) const; }; #endif // __MAINWINDOW_H_ diff --git a/Qt-SESAM/mainwindow.ui b/Qt-SESAM/mainwindow.ui index 8becb789..3dc704d5 100644 --- a/Qt-SESAM/mainwindow.ui +++ b/Qt-SESAM/mainwindow.ui @@ -868,15 +868,28 @@ Expert actions + + + Export + + + + + + + + Import + + + - - - + + @@ -1024,12 +1037,12 @@ - Export KGK ... + KGK ... - Import KGK ... + KGK ... @@ -1053,7 +1066,12 @@ - Export current settings as QR code ... + Current domain settings as QR code ... + + + + + All login data as clear text ... diff --git a/Qt-SESAM/translations/QtSESAM_de.ts b/Qt-SESAM/translations/QtSESAM_de.ts index 47e16686..6975451c 100644 --- a/Qt-SESAM/translations/QtSESAM_de.ts +++ b/Qt-SESAM/translations/QtSESAM_de.ts @@ -219,7 +219,7 @@ auf deinem Computer: %3 Cancel - Abbrechen + Abbrechen SHA512 hash (hex) @@ -726,7 +726,7 @@ auf deinem Computer: %3 Export KGK ... - KGK exportieren ... + KGK exportieren ... Security hint @@ -734,7 +734,7 @@ auf deinem Computer: %3 Import KGK ... - KGK importieren ... + KGK importieren ... Export KGK to ... @@ -1090,7 +1090,7 @@ auf deinem Computer: %3 Export - Exportieren + Exportieren Current settings as QR code ... @@ -1120,7 +1120,33 @@ auf deinem Computer: %3 Export current settings as QR code ... - Aktuelle Domain-Einstellungen als QR-Code exportieren ... + Aktuelle Domain-Einstellungen als QR-Code exportieren ... + + + KGK ... + KGK ... + + + Current domain settings as QR code ... + Aktuelle Domain-Daten als QR-Code ... + + + All login data as clear text ... + All Logins im Klartext ... + + + Export all login data as clear text + All Login-Daten im Klartext exportieren + + + Exporting logins +in %1 thread%2 ... + Exportieren der Logins +in %1 Thread%2 ... + + + s + s @@ -1758,6 +1784,14 @@ auf deinem Computer: %3 QR code file (*.png) QR-Code-Datei (*.png) + + Login data file (*.csv *.sesam) + Login-Daten (*.csv *.sesam) + + + Login data file (*.csv) + + ServerCertificateWidget